LyoKICogQ29weXJpZ2h0IDIwMDItMjAwMyBNaWNoYWVsIEf8bm5ld2lnCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIKICogdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVQogKiBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3QsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEsIFVTQQogKi8KCiNpbmNsdWRlIDxhc3NlcnQuaD4KI2luY2x1ZGUgPHN0ZGFyZy5oPgoKI2luY2x1ZGUgIndpbmRlZi5oIgojaW5jbHVkZSAid2luYmFzZS5oIgojaW5jbHVkZSAid2lubmxzLmgiCiNpbmNsdWRlICJ3aW5nZGkuaCIKI2luY2x1ZGUgIndpbnVzZXIuaCIKI2luY2x1ZGUgInZmdy5oIgoKI2luY2x1ZGUgImF2aWZpbGVfcHJpdmF0ZS5oIgoKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKGF2aWZpbGUpOwoKI2lmbmRlZiBESUJQVFIKI2RlZmluZSBESUJQVFIobHApICAgICAgKChMUEJZVEUpKGxwKSArIChscCktPmJpU2l6ZSArIFwKICAgICAgICAgICAgICAgICAgICAgICAgIChscCktPmJpQ2xyVXNlZCAqIHNpemVvZihSR0JRVUFEKSkKI2VuZGlmCgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUdldEZyYW1lX2ZuUXVlcnlJbnRlcmZhY2UoSUdldEZyYW1lICppZmFjZSwKCQkJCQkJIFJFRklJRCByZWZpaWQsIExQVk9JRCAqb2JqKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIElHZXRGcmFtZV9mbkFkZFJlZihJR2V0RnJhbWUgKmlmYWNlKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIElHZXRGcmFtZV9mblJlbGVhc2UoSUdldEZyYW1lICppZmFjZSk7CnN0YXRpYyBMUFZPSUQgIFdJTkFQSSBJR2V0RnJhbWVfZm5HZXRGcmFtZShJR2V0RnJhbWUgKmlmYWNlLCBMT05HIGxQb3MpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUdldEZyYW1lX2ZuQmVnaW4oSUdldEZyYW1lICppZmFjZSwgTE9ORyBsU3RhcnQsCgkJCQkJTE9ORyBsRW5kLCBMT05HIGxSYXRlKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mbkVuZChJR2V0RnJhbWUgKmlmYWNlKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mblNldEZvcm1hdChJR2V0RnJhbWUgKmlmYWNlLAoJCQkJCSAgICBMUEJJVE1BUElORk9IRUFERVIgbHBiaSwKCQkJCQkgICAgTFBWT0lEIGxwQml0cywgSU5UIHgsIElOVCB5LAoJCQkJCSAgICBJTlQgZHgsIElOVCBkeSk7CgpzdGF0aWMgY29uc3Qgc3RydWN0IElHZXRGcmFtZVZ0YmwgaWdldGZyYW1lVnRibCA9IHsKICBJR2V0RnJhbWVfZm5RdWVyeUludGVyZmFjZSwKICBJR2V0RnJhbWVfZm5BZGRSZWYsCiAgSUdldEZyYW1lX2ZuUmVsZWFzZSwKICBJR2V0RnJhbWVfZm5HZXRGcmFtZSwKICBJR2V0RnJhbWVfZm5CZWdpbiwKICBJR2V0RnJhbWVfZm5FbmQsCiAgSUdldEZyYW1lX2ZuU2V0Rm9ybWF0Cn07Cgp0eXBlZGVmIHN0cnVjdCBfSUdldEZyYW1lSW1wbCB7CiAgLyogSVVua25vd24gc3R1ZmYgKi8KICBjb25zdCBJR2V0RnJhbWVWdGJsICpscFZ0Ymw7CiAgTE9ORyAgICAgICAgICAgICAgIHJlZjsKCiAgLyogSUdldEZyYW1lIHN0dWZmICovCiAgQk9PTCAgICAgICAgICAgICAgIGJGaXhlZFN0cmVhbTsKICBQQVZJU1RSRUFNICAgICAgICAgcFN0cmVhbTsKCiAgTFBWT0lEICAgICAgICAgICAgIGxwSW5CdWZmZXI7CiAgTE9ORyAgICAgICAgICAgICAgIGNiSW5CdWZmZXI7CiAgTFBCSVRNQVBJTkZPSEVBREVSIGxwSW5Gb3JtYXQ7CiAgTE9ORyAgICAgICAgICAgICAgIGNiSW5Gb3JtYXQ7CgogIExPTkcgICAgICAgICAgICAgICBsQ3VycmVudEZyYW1lOwogIExQQklUTUFQSU5GT0hFQURFUiBscE91dEZvcm1hdDsKICBMUFZPSUQgICAgICAgICAgICAgbHBPdXRCdWZmZXI7CgogIEhJQyAgICAgICAgICAgICAgICBoaWM7CiAgQk9PTCAgICAgICAgICAgICAgIGJSZXNpemU7CiAgRFdPUkQgICAgICAgICAgICAgIHg7CiAgRFdPUkQgICAgICAgICAgICAgIHk7CiAgRFdPUkQgICAgICAgICAgICAgIGR4OwogIERXT1JEICAgICAgICAgICAgICBkeTsKCiAgQk9PTCAgICAgICAgICAgICAgIGJGb3JtYXRDaGFuZ2VzOwogIERXT1JEICAgICAgICAgICAgICBkd0Zvcm1hdENoYW5nZUNvdW50OwogIERXT1JEICAgICAgICAgICAgICBkd0VkaXRDb3VudDsKfSBJR2V0RnJhbWVJbXBsOwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwoKc3RhdGljIHZvaWQgQVZJRklMRV9DbG9zZUNvbXByZXNzb3IoSUdldEZyYW1lSW1wbCAqVGhpcykKewogIGlmIChUaGlzLT5scEluRm9ybWF0ICE9IFRoaXMtPmxwT3V0Rm9ybWF0KSB7CiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzLT5scE91dEZvcm1hdCk7CiAgICBUaGlzLT5scE91dEZvcm1hdCA9IE5VTEw7CiAgfQogIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIFRoaXMtPmxwSW5Gb3JtYXQpOwogIFRoaXMtPmxwSW5Gb3JtYXQgPSBOVUxMOwogIGlmIChUaGlzLT5oaWMgIT0gTlVMTCkgewogICAgaWYgKFRoaXMtPmJSZXNpemUpCiAgICAgIElDRGVjb21wcmVzc0V4RW5kKFRoaXMtPmhpYyk7CiAgICBlbHNlCiAgICAgIElDRGVjb21wcmVzc0VuZChUaGlzLT5oaWMpOwogICAgSUNDbG9zZShUaGlzLT5oaWMpOwogICAgVGhpcy0+aGljID0gTlVMTDsKICB9Cn0KClBHRVRGUkFNRSBBVklGSUxFX0NyZWF0ZUdldEZyYW1lKFBBVklTVFJFQU0gcFN0cmVhbSkKewogIElHZXRGcmFtZUltcGwgKnBnOwoKICAvKiBjaGVjayBwYXJhbWV0ZXIgKi8KICBpZiAocFN0cmVhbSA9PSBOVUxMKQogICAgcmV0dXJuIE5VTEw7CgogIHBnID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIEhFQVBfWkVST19NRU1PUlksIHNpemVvZihJR2V0RnJhbWVJbXBsKSk7CiAgaWYgKHBnICE9IE5VTEwpIHsKICAgIHBnLT5scFZ0YmwgICAgICAgID0gJmlnZXRmcmFtZVZ0Ymw7CiAgICBwZy0+cmVmICAgICAgICAgICA9IDE7CiAgICBwZy0+bEN1cnJlbnRGcmFtZSA9IC0xOwogICAgcGctPnBTdHJlYW0gICAgICAgPSBwU3RyZWFtOwogICAgSUFWSVN0cmVhbV9BZGRSZWYocFN0cmVhbSk7CiAgfQoKICByZXR1cm4gKFBHRVRGUkFNRSlwZzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mblF1ZXJ5SW50ZXJmYWNlKElHZXRGcmFtZSAqaWZhY2UsCgkJCQkJCSBSRUZJSUQgcmVmaWlkLCBMUFZPSUQgKm9iaikKewogIElHZXRGcmFtZUltcGwgKlRoaXMgPSAoSUdldEZyYW1lSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVzLCVwKVxuIiwgVGhpcywgZGVidWdzdHJfZ3VpZChyZWZpaWQpLCBvYmopOwoKICBpZiAoSXNFcXVhbEdVSUQoJklJRF9JVW5rbm93biwgcmVmaWlkKSB8fAogICAgICBJc0VxdWFsR1VJRCgmSUlEX0lHZXRGcmFtZSwgcmVmaWlkKSkgewogICAgKm9iaiA9IGlmYWNlOwogICAgcmV0dXJuIFNfT0s7CiAgfQoKICByZXR1cm4gT0xFX0VfRU5VTV9OT01PUkU7Cn0KCnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJR2V0RnJhbWVfZm5BZGRSZWYoSUdldEZyYW1lICppZmFjZSkKewogIElHZXRGcmFtZUltcGwgKlRoaXMgPSAoSUdldEZyYW1lSW1wbCAqKWlmYWNlOwogIFVMT05HIHJlZiA9IEludGVybG9ja2VkSW5jcmVtZW50KCZUaGlzLT5yZWYpOwoKICBUUkFDRSgiKCVwKVxuIiwgaWZhY2UpOwoKICByZXR1cm4gcmVmOwp9CgpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSUdldEZyYW1lX2ZuUmVsZWFzZShJR2V0RnJhbWUgKmlmYWNlKQp7CiAgSUdldEZyYW1lSW1wbCAqVGhpcyA9IChJR2V0RnJhbWVJbXBsICopaWZhY2U7CiAgVUxPTkcgcmVmID0gSW50ZXJsb2NrZWREZWNyZW1lbnQoJlRoaXMtPnJlZik7CgogIFRSQUNFKCIoJXApXG4iLCBpZmFjZSk7CgogIGlmICghcmVmKSB7CiAgICBBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKICAgIGlmIChUaGlzLT5wU3RyZWFtICE9IE5VTEwpIHsKICAgICAgSUFWSVN0cmVhbV9SZWxlYXNlKFRoaXMtPnBTdHJlYW0pOwogICAgICBUaGlzLT5wU3RyZWFtID0gTlVMTDsKICAgIH0KCiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBpZmFjZSk7CiAgICByZXR1cm4gMDsKICB9CgogIHJldHVybiByZWY7Cn0KCnN0YXRpYyBMUFZPSUQgIFdJTkFQSSBJR2V0RnJhbWVfZm5HZXRGcmFtZShJR2V0RnJhbWUgKmlmYWNlLCBMT05HIGxQb3MpCnsKICBJR2V0RnJhbWVJbXBsICpUaGlzID0gKElHZXRGcmFtZUltcGwgKilpZmFjZTsKCiAgTE9ORyByZWFkQnl0ZXM7CiAgTE9ORyByZWFkU2FtcGxlczsKCiAgVFJBQ0UoIiglcCwlZClcbiIsIGlmYWNlLCBsUG9zKTsKCiAgLyogV2UgZG9uJ3Qgd2FudCBuZWdhdGl2ZSBzdGFydCB2YWx1ZXMhIC0tIG1hcmtzIGludmFsaWQgYnVmZmVyIGNvbnRlbnQgKi8KICBpZiAobFBvcyA8IDApCiAgICByZXR1cm4gTlVMTDsKCiAgLyogY2hlY2sgc3RhdGUgKi8KICBpZiAoVGhpcy0+cFN0cmVhbSA9PSBOVUxMKQogICAgcmV0dXJuIE5VTEw7CiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQgPT0gTlVMTCkKICAgIHJldHVybiBOVUxMOwoKICAvKiBDb3VsZCBzdHJlYW0gaGF2ZSBjaGFuZ2VkPyAqLwogIGlmICghIFRoaXMtPmJGaXhlZFN0cmVhbSkgewogICAgQVZJU1RSRUFNSU5GT1cgc0luZm87CgogICAgSUFWSVN0cmVhbV9JbmZvKFRoaXMtPnBTdHJlYW0sICZzSW5mbywgc2l6ZW9mKHNJbmZvKSk7CgogICAgaWYgKHNJbmZvLmR3RWRpdENvdW50ICE9IFRoaXMtPmR3RWRpdENvdW50KSB7CiAgICAgIFRoaXMtPmR3RWRpdENvdW50ICAgPSBzSW5mby5kd0VkaXRDb3VudDsKICAgICAgVGhpcy0+bEN1cnJlbnRGcmFtZSA9IC0xOwogICAgfQoKICAgIGlmIChzSW5mby5kd0Zvcm1hdENoYW5nZUNvdW50ICE9IFRoaXMtPmR3Rm9ybWF0Q2hhbmdlQ291bnQpIHsKICAgICAgLyogc3RyZWFtIGhhcyBjaGFuZ2VkICovCiAgICAgIGlmIChUaGlzLT5scE91dEZvcm1hdCAhPSBOVUxMKSB7CglCSVRNQVBJTkZPSEVBREVSIGJpOwoKCW1lbWNweSgmYmksIFRoaXMtPmxwT3V0Rm9ybWF0LCBzaXplb2YoYmkpKTsKCUFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwoKCWlmIChGQUlMRUQoSUdldEZyYW1lX1NldEZvcm1hdChpZmFjZSwgJmJpLCBOVUxMLCAwLCAwLCAtMSwgLTEpKSkgewoJICBpZiAoRkFJTEVEKElHZXRGcmFtZV9TZXRGb3JtYXQoaWZhY2UsIE5VTEwsIE5VTEwsIDAsIDAsIC0xLCAtMSkpKQoJICAgIHJldHVybiBOVUxMOwoJfQogICAgICB9IGVsc2UgaWYgKEZBSUxFRChJR2V0RnJhbWVfU2V0Rm9ybWF0KGlmYWNlLCBOVUxMLCBOVUxMLCAwLCAwLCAtMSwgLTEpKSkKCXJldHVybiBOVUxMOwogICAgfQogIH0KCiAgaWYgKGxQb3MgIT0gVGhpcy0+bEN1cnJlbnRGcmFtZSkgewogICAgTE9ORyBsTmV4dCA9IElBVklTdHJlYW1fRmluZFNhbXBsZShUaGlzLT5wU3RyZWFtLGxQb3MsRklORF9LRVl8RklORF9QUkVWKTsKCiAgICBpZiAobE5leHQgPT0gLTEpCiAgICAgIHJldHVybiBOVUxMOyAvKiBmcmFtZSBkb2Vzbid0IGV4aXN0ICovCiAgICBpZiAobE5leHQgPD0gVGhpcy0+bEN1cnJlbnRGcmFtZSAmJiBUaGlzLT5sQ3VycmVudEZyYW1lIDwgbFBvcykKICAgICAgbE5leHQgPSBUaGlzLT5sQ3VycmVudEZyYW1lICsgMTsKCiAgICBmb3IgKDsgbE5leHQgPD0gbFBvczsgbE5leHQrKykgewogICAgICAvKiBuZXcgZm9ybWF0IGZvciB0aGlzIGZyYW1lPyAqLwogICAgICBpZiAoVGhpcy0+YkZvcm1hdENoYW5nZXMpIHsKCUlBVklTdHJlYW1fUmVhZEZvcm1hdChUaGlzLT5wU3RyZWFtLCBsTmV4dCwKCQkJICAgICAgVGhpcy0+bHBJbkZvcm1hdCwgJlRoaXMtPmNiSW5Gb3JtYXQpOwoJaWYgKFRoaXMtPmxwT3V0Rm9ybWF0ICE9IE5VTEwpIHsKCSAgaWYgKFRoaXMtPmxwT3V0Rm9ybWF0LT5iaUJpdENvdW50IDw9IDgpCgkgICAgSUNEZWNvbXByZXNzR2V0UGFsZXR0ZShUaGlzLT5oaWMsIFRoaXMtPmxwSW5Gb3JtYXQsCgkJCQkgICBUaGlzLT5scE91dEZvcm1hdCk7Cgl9CiAgICAgIH0KCiAgICAgIC8qIHJlYWQgaW5wdXQgZnJhbWUgKi8KICAgICAgd2hpbGUgKEZBSUxFRChBVklTdHJlYW1SZWFkKFRoaXMtPnBTdHJlYW0sIGxOZXh0LCAxLCBUaGlzLT5scEluQnVmZmVyLAoJCQkJICBUaGlzLT5jYkluQnVmZmVyLCAmcmVhZEJ5dGVzLCAmcmVhZFNhbXBsZXMpKSkgewoJLyogbm90IGVub3VnaCBtZW1vcnkgZm9yIGlucHV0IGJ1ZmZlcj8gKi8KCXJlYWRCeXRlcyA9IDA7CglpZiAoRkFJTEVEKEFWSVN0cmVhbVNhbXBsZVNpemUoVGhpcy0+cFN0cmVhbSwgbE5leHQsICZyZWFkQnl0ZXMpKSkKCSAgcmV0dXJuIE5VTEw7IC8qIGJhZCB0aGluZywgYnV0IGJhZCB0aGluZ3Mgd2lsbCBoYXBwZW4gKi8KCWlmIChyZWFkQnl0ZXMgPD0gMCkgewoJICBFUlIoIjogSUFWSVN0cmVhbTo6UkVhZCBkb2Vzbid0IHJldHVybiBuZWVkZWQgYnl0ZXMhXG4iKTsKCSAgcmV0dXJuIE5VTEw7Cgl9CgoJLyogSUFWSVN0cmVhbTo6UmVhZCBmYWlsZWQgYmVjYXVzZSBvZiBvdGhlciByZWFzb25zIG5vdCBidWZmZXJzaXplPyAqLwoJaWYgKFRoaXMtPmNiSW5CdWZmZXIgPj0gcmVhZEJ5dGVzKQoJICBicmVhazsKCVRoaXMtPmNiSW5CdWZmZXIgPSBUaGlzLT5jYkluRm9ybWF0ICsgcmVhZEJ5dGVzOwoJVGhpcy0+bHBJbkZvcm1hdCA9IEhlYXBSZUFsbG9jKEdldFByb2Nlc3NIZWFwKCksIDAsIFRoaXMtPmxwSW5Gb3JtYXQsIFRoaXMtPmNiSW5CdWZmZXIpOwoJaWYgKFRoaXMtPmxwSW5Gb3JtYXQgPT0gTlVMTCkKCSAgcmV0dXJuIE5VTEw7IC8qIG91dCBvZiBtZW1vcnkgKi8KCVRoaXMtPmxwSW5CdWZmZXIgPSAoQllURSopVGhpcy0+bHBJbkZvcm1hdCArIFRoaXMtPmNiSW5Gb3JtYXQ7CiAgICAgIH0KCiAgICAgIGlmIChyZWFkU2FtcGxlcyAhPSAxKSB7CglFUlIoIjogbm8gZnJhbWVzIHJlYWRcbiIpOwoJcmV0dXJuIE5VTEw7CiAgICAgIH0KICAgICAgaWYgKHJlYWRCeXRlcyAhPSAwKSB7CglUaGlzLT5scEluRm9ybWF0LT5iaVNpemVJbWFnZSA9IHJlYWRCeXRlczsKCgkvKiBub3RoaW5nIHRvIGRlY29tcHJlc3M/ICovCglpZiAoVGhpcy0+aGljID09IE5VTEwpIHsKCSAgVGhpcy0+bEN1cnJlbnRGcmFtZSA9IGxQb3M7CgkgIHJldHVybiBUaGlzLT5scEluRm9ybWF0OwoJfQoKCWlmIChUaGlzLT5iUmVzaXplKSB7CgkgIElDRGVjb21wcmVzc0V4KFRoaXMtPmhpYywwLFRoaXMtPmxwSW5Gb3JtYXQsVGhpcy0+bHBJbkJ1ZmZlciwwLDAsCgkJCSBUaGlzLT5scEluRm9ybWF0LT5iaVdpZHRoLFRoaXMtPmxwSW5Gb3JtYXQtPmJpSGVpZ2h0LAoJCQkgVGhpcy0+bHBPdXRGb3JtYXQsVGhpcy0+bHBPdXRCdWZmZXIsVGhpcy0+eCxUaGlzLT55LAoJCQkgVGhpcy0+ZHgsVGhpcy0+ZHkpOwoJfSBlbHNlIHsKCSAgSUNEZWNvbXByZXNzKFRoaXMtPmhpYywgMCwgVGhpcy0+bHBJbkZvcm1hdCwgVGhpcy0+bHBJbkJ1ZmZlciwKCQkgICAgICAgVGhpcy0+bHBPdXRGb3JtYXQsIFRoaXMtPmxwT3V0QnVmZmVyKTsKCX0KICAgICAgfQogICAgfSAvKiBmb3IgKGxOZXh0IDwgbFBvcykgKi8KICB9IC8qIGlmIChUaGlzLT5sQ3VycmVudEZyYW1lICE9IGxQb3MpICovCgogIHJldHVybiAoVGhpcy0+aGljID09IE5VTEwgPyBUaGlzLT5scEluRm9ybWF0IDogVGhpcy0+bHBPdXRGb3JtYXQpOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUdldEZyYW1lX2ZuQmVnaW4oSUdldEZyYW1lICppZmFjZSwgTE9ORyBsU3RhcnQsCgkJCQkJTE9ORyBsRW5kLCBMT05HIGxSYXRlKQp7CiAgSUdldEZyYW1lSW1wbCAqVGhpcyA9IChJR2V0RnJhbWVJbXBsICopaWZhY2U7CgogIFRSQUNFKCIoJXAsJWQsJWQsJWQpXG4iLCBpZmFjZSwgbFN0YXJ0LCBsRW5kLCBsUmF0ZSk7CgogIFRoaXMtPmJGaXhlZFN0cmVhbSA9IFRSVUU7CgogIHJldHVybiAoSUdldEZyYW1lX0dldEZyYW1lKGlmYWNlLCBsU3RhcnQpID8gQVZJRVJSX09LIDogQVZJRVJSX0VSUk9SKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mbkVuZChJR2V0RnJhbWUgKmlmYWNlKQp7CiAgSUdldEZyYW1lSW1wbCAqVGhpcyA9IChJR2V0RnJhbWVJbXBsICopaWZhY2U7CgogIFRSQUNFKCIoJXApXG4iLCBpZmFjZSk7CgogIFRoaXMtPmJGaXhlZFN0cmVhbSA9IEZBTFNFOwoKICByZXR1cm4gQVZJRVJSX09LOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUdldEZyYW1lX2ZuU2V0Rm9ybWF0KElHZXRGcmFtZSAqaWZhY2UsCgkJCQkJICAgIExQQklUTUFQSU5GT0hFQURFUiBscGJpV2FudGVkLAoJCQkJCSAgICBMUFZPSUQgbHBCaXRzLCBJTlQgeCwgSU5UIHksCgkJCQkJICAgIElOVCBkeCwgSU5UIGR5KQp7CiAgSUdldEZyYW1lSW1wbCAqVGhpcyA9IChJR2V0RnJhbWVJbXBsICopaWZhY2U7CgogIEFWSVNUUkVBTUlORk9XICAgICBzSW5mbzsKICBMUEJJVE1BUElORk9IRUFERVIgbHBiaSAgICAgICAgID0gbHBiaVdhbnRlZDsKICBCT09MICAgICAgICAgICAgICAgYkJlc3REaXNwbGF5ID0gRkFMU0U7CgogIFRSQUNFKCIoJXAsJXAsJXAsJWQsJWQsJWQsJWQpXG4iLCBpZmFjZSwgbHBiaVdhbnRlZCwgbHBCaXRzLAoJeCwgeSwgZHgsIGR5KTsKCiAgaWYgKFRoaXMtPnBTdHJlYW0gPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfRVJST1I7CgogIGlmIChscGJpV2FudGVkID09IChMUEJJVE1BUElORk9IRUFERVIpQVZJR0VURlJBTUVGX0JFU1RESVNQTEFZRk1UKSB7CiAgICBscGJpID0gTlVMTDsKICAgIGJCZXN0RGlzcGxheSA9IFRSVUU7CiAgfQoKICBJQVZJU3RyZWFtX0luZm8oVGhpcy0+cFN0cmVhbSwgJnNJbmZvLCBzaXplb2Yoc0luZm8pKTsKICBpZiAoc0luZm8uZmNjVHlwZSAhPSBzdHJlYW10eXBlVklERU8pCiAgICByZXR1cm4gQVZJRVJSX1VOU1VQUE9SVEVEOwoKICBUaGlzLT5iRm9ybWF0Q2hhbmdlcyA9CiAgICAoc0luZm8uZHdGbGFncyAmIEFWSVNUUkVBTUlORk9fRk9STUFUQ0hBTkdFUyA/IFRSVUUgOiBGQUxTRSApOwogIFRoaXMtPmR3Rm9ybWF0Q2hhbmdlQ291bnQgPSBzSW5mby5kd0Zvcm1hdENoYW5nZUNvdW50OwogIFRoaXMtPmR3RWRpdENvdW50ICAgICAgICAgPSBzSW5mby5kd0VkaXRDb3VudDsKICBUaGlzLT5sQ3VycmVudEZyYW1lICAgICAgID0gLTE7CgogIC8qIGdldCBpbnB1dCBmb3JtYXQgZnJvbSBzdHJlYW0gKi8KICBpZiAoVGhpcy0+bHBJbkZvcm1hdCA9PSBOVUxMKSB7CiAgICBIUkVTVUxUIGhyOwoKICAgIFRoaXMtPmNiSW5CdWZmZXIgPSAoTE9ORylzSW5mby5kd1N1Z2dlc3RlZEJ1ZmZlclNpemU7CiAgICBpZiAoVGhpcy0+Y2JJbkJ1ZmZlciA9PSAwKQogICAgICBUaGlzLT5jYkluQnVmZmVyID0gMTAyNDsKCiAgICBJQVZJU3RyZWFtX1JlYWRGb3JtYXQoVGhpcy0+cFN0cmVhbSwgc0luZm8uZHdTdGFydCwKCQkJICBOVUxMLCAmVGhpcy0+Y2JJbkZvcm1hdCk7CgogICAgVGhpcy0+bHBJbkZvcm1hdCA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzLT5jYkluRm9ybWF0ICsgVGhpcy0+Y2JJbkJ1ZmZlcik7CiAgICBpZiAoVGhpcy0+bHBJbkZvcm1hdCA9PSBOVUxMKSB7CiAgICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgIH0KCiAgICBociA9IElBVklTdHJlYW1fUmVhZEZvcm1hdChUaGlzLT5wU3RyZWFtLCBzSW5mby5kd1N0YXJ0LCBUaGlzLT5scEluRm9ybWF0LCAmVGhpcy0+Y2JJbkZvcm1hdCk7CiAgICBpZiAoRkFJTEVEKGhyKSkgewogICAgICBBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKICAgICAgcmV0dXJuIGhyOwogICAgfQoKICAgIFRoaXMtPmxwSW5CdWZmZXIgPSAoKExQQllURSlUaGlzLT5scEluRm9ybWF0KSArIFRoaXMtPmNiSW5Gb3JtYXQ7CiAgfQoKICAvKiBjaGVjayBpbnB1dCBmb3JtYXQgKi8KICBpZiAoVGhpcy0+bHBJbkZvcm1hdC0+YmlDbHJVc2VkID09IDAgJiYgVGhpcy0+bHBJbkZvcm1hdC0+YmlCaXRDb3VudCA8PSA4KQogICAgVGhpcy0+bHBJbkZvcm1hdC0+YmlDbHJVc2VkID0gMXUgPDwgVGhpcy0+bHBJbkZvcm1hdC0+YmlCaXRDb3VudDsKICBpZiAoVGhpcy0+bHBJbkZvcm1hdC0+YmlTaXplSW1hZ2UgPT0gMCAmJgogICAgICBUaGlzLT5scEluRm9ybWF0LT5iaUNvbXByZXNzaW9uID09IEJJX1JHQikgewogICAgVGhpcy0+bHBJbkZvcm1hdC0+YmlTaXplSW1hZ2UgPQogICAgICBESUJXSURUSEJZVEVTKCpUaGlzLT5scEluRm9ybWF0KSAqIFRoaXMtPmxwSW5Gb3JtYXQtPmJpSGVpZ2h0OwogIH0KCiAgLyogb25seSB0byBwYXNzIHRocm91Z2g/ICovCiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQtPmJpQ29tcHJlc3Npb24gPT0gQklfUkdCICYmIGxwQml0cyA9PSBOVUxMKSB7CiAgICBpZiAobHBiaSA9PSBOVUxMIHx8IAoJKGxwYmktPmJpQ29tcHJlc3Npb24gPT0gQklfUkdCICYmCgkgbHBiaS0+YmlXaWR0aCA9PSBUaGlzLT5scEluRm9ybWF0LT5iaVdpZHRoICYmCgkgbHBiaS0+YmlIZWlnaHQgPT0gVGhpcy0+bHBJbkZvcm1hdC0+YmlIZWlnaHQgJiYKCSBscGJpLT5iaUJpdENvdW50ID09IFRoaXMtPmxwSW5Gb3JtYXQtPmJpQml0Q291bnQpKSB7CiAgICAgIFRoaXMtPmxwT3V0Rm9ybWF0ID0gVGhpcy0+bHBJbkZvcm1hdDsKICAgICAgVGhpcy0+bHBPdXRCdWZmZXIgPSBESUJQVFIoVGhpcy0+bHBJbkZvcm1hdCk7CiAgICAgIHJldHVybiBBVklFUlJfT0s7CiAgICB9CiAgfQoKICAvKiBuZWVkIG1lbW9yeSBmb3Igb3V0cHV0IGZvcm1hdD8gKi8KICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQgPT0gTlVMTCkgewogICAgVGhpcy0+bHBPdXRGb3JtYXQgPQogICAgICBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgc2l6ZW9mKEJJVE1BUElORk9IRUFERVIpICsgMjU2ICogc2l6ZW9mKFJHQlFVQUQpKTsKICAgIGlmIChUaGlzLT5scE91dEZvcm1hdCA9PSBOVUxMKSB7CiAgICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgIH0KICB9CgogIC8qIG5lZWQgaGFuZGxlIHRvIHZpZGVvIGNvbXByZXNzb3IgKi8KICBpZiAoVGhpcy0+aGljID09IE5VTEwpIHsKICAgIEZPVVJDQyBmY2NIYW5kbGVyOwoKICAgIGlmIChUaGlzLT5scEluRm9ybWF0LT5iaUNvbXByZXNzaW9uID09IEJJX1JHQikKICAgICAgZmNjSGFuZGxlciA9IGNvbXB0eXBlRElCOwogICAgZWxzZSBpZiAoVGhpcy0+bHBJbkZvcm1hdC0+YmlDb21wcmVzc2lvbiA9PSBCSV9STEU4KQogICAgICBmY2NIYW5kbGVyID0gbW1pb0ZPVVJDQygnUicsJ0wnLCdFJywnICcpOwogICAgZWxzZQogICAgICBmY2NIYW5kbGVyID0gc0luZm8uZmNjSGFuZGxlcjsKCiAgICBpZiAobHBiaSAhPSBOVUxMKSB7CiAgICAgIGlmIChscGJpLT5iaVdpZHRoID09IDApCglscGJpLT5iaVdpZHRoID0gVGhpcy0+bHBJbkZvcm1hdC0+YmlXaWR0aDsKICAgICAgaWYgKGxwYmktPmJpSGVpZ2h0ID09IDApCglscGJpLT5iaUhlaWdodCA9IFRoaXMtPmxwSW5Gb3JtYXQtPmJpSGVpZ2h0OwogICAgfQoKICAgIFRoaXMtPmhpYyA9IElDTG9jYXRlKElDVFlQRV9WSURFTywgZmNjSGFuZGxlciwgVGhpcy0+bHBJbkZvcm1hdCwgbHBiaSwgSUNNT0RFX0RFQ09NUFJFU1MpOwogICAgaWYgKFRoaXMtPmhpYyA9PSBOVUxMKSB7CiAgICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgICByZXR1cm4gQVZJRVJSX05PQ09NUFJFU1NPUjsKICAgIH0KICB9CgogIC8qIG91dHB1dCBmb3JtYXQgZ2l2ZW4/ICovCiAgaWYgKGxwYmkgIT0gTlVMTCkgewogICAgLyogY2hlY2sgdGhlIGdpdmVuIG91dHB1dCBmb3JtYXQgLi4uICovCiAgICBpZiAobHBiaS0+YmlDbHJVc2VkID09IDAgJiYgbHBiaS0+YmlCaXRDb3VudCA8PSA4KQogICAgICBscGJpLT5iaUNsclVzZWQgPSAxdSA8PCBscGJpLT5iaUJpdENvdW50OwoKICAgIC8qIC4uLiBhbmQgcmVtZW1iZXIgaXQgKi8KICAgIG1lbWNweShUaGlzLT5scE91dEZvcm1hdCwgbHBiaSwKCSAgIGxwYmktPmJpU2l6ZSArIGxwYmktPmJpQ2xyVXNlZCAqIHNpemVvZihSR0JRVUFEKSk7CiAgICBpZiAobHBiaS0+YmlCaXRDb3VudCA8PSA4KQogICAgICBJQ0RlY29tcHJlc3NHZXRQYWxldHRlKFRoaXMtPmhpYywgVGhpcy0+bHBJbkZvcm1hdCwgVGhpcy0+bHBPdXRGb3JtYXQpOwoKICAgIHJldHVybiBBVklFUlJfT0s7CiAgfSBlbHNlIHsKICAgIGlmIChiQmVzdERpc3BsYXkpIHsKICAgICAgSUNHZXREaXNwbGF5Rm9ybWF0KFRoaXMtPmhpYywgVGhpcy0+bHBJbkZvcm1hdCwKCQkJIFRoaXMtPmxwT3V0Rm9ybWF0LCAwLCBkeCwgZHkpOwogICAgfSBlbHNlIGlmIChJQ0RlY29tcHJlc3NHZXRGb3JtYXQoVGhpcy0+aGljLCBUaGlzLT5scEluRm9ybWF0LAoJCQkJICAgICBUaGlzLT5scE91dEZvcm1hdCkgPCAwKSB7CiAgICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgICByZXR1cm4gQVZJRVJSX05PQ09NUFJFU1NPUjsKICAgIH0KCiAgICAvKiBjaGVjayBvdXRwdXQgZm9ybWF0ICovCiAgICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQtPmJpQ2xyVXNlZCA9PSAwICYmCglUaGlzLT5scE91dEZvcm1hdC0+YmlCaXRDb3VudCA8PSA4KQogICAgICBUaGlzLT5scE91dEZvcm1hdC0+YmlDbHJVc2VkID0gMXUgPDwgVGhpcy0+bHBPdXRGb3JtYXQtPmJpQml0Q291bnQ7CiAgICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQtPmJpU2l6ZUltYWdlID09IDAgJiYKCVRoaXMtPmxwT3V0Rm9ybWF0LT5iaUNvbXByZXNzaW9uID09IEJJX1JHQikgewogICAgICBUaGlzLT5scE91dEZvcm1hdC0+YmlTaXplSW1hZ2UgPQoJRElCV0lEVEhCWVRFUygqVGhpcy0+bHBPdXRGb3JtYXQpICogVGhpcy0+bHBPdXRGb3JtYXQtPmJpSGVpZ2h0OwogICAgfQoKICAgIGlmIChscEJpdHMgPT0gTlVMTCkgewogICAgICByZWdpc3RlciBEV09SRCBzaXplID0gVGhpcy0+bHBPdXRGb3JtYXQtPmJpQ2xyVXNlZCAqIHNpemVvZihSR0JRVUFEKTsKCiAgICAgIHNpemUgKz0gVGhpcy0+bHBPdXRGb3JtYXQtPmJpU2l6ZSArIFRoaXMtPmxwT3V0Rm9ybWF0LT5iaVNpemVJbWFnZTsKICAgICAgVGhpcy0+bHBPdXRGb3JtYXQgPSBIZWFwUmVBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzLT5scE91dEZvcm1hdCwgc2l6ZSk7CiAgICAgIGlmIChUaGlzLT5scE91dEZvcm1hdCA9PSBOVUxMKSB7CglBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKCXJldHVybiBBVklFUlJfTUVNT1JZOwogICAgICB9CiAgICAgIFRoaXMtPmxwT3V0QnVmZmVyID0gRElCUFRSKFRoaXMtPmxwT3V0Rm9ybWF0KTsKICAgIH0gZWxzZQogICAgICBUaGlzLT5scE91dEJ1ZmZlciA9IGxwQml0czsKCiAgICAvKiBmb3IgdXNlciBzaXplIHdhcyBpcnJlbGV2YW50ICovCiAgICBpZiAoZHggPT0gLTEpCiAgICAgIGR4ID0gVGhpcy0+bHBPdXRGb3JtYXQtPmJpV2lkdGg7CiAgICBpZiAoZHkgPT0gLTEpCiAgICAgIGR5ID0gVGhpcy0+bHBPdXRGb3JtYXQtPmJpSGVpZ2h0OwoKICAgIC8qIG5lZWQgdG8gcmVzaXplPyAqLwogICAgaWYgKHggIT0gMCB8fCB5ICE9IDApIHsKICAgICAgaWYgKGR5ID09IFRoaXMtPmxwT3V0Rm9ybWF0LT5iaUhlaWdodCAmJgoJICBkeCA9PSBUaGlzLT5scE91dEZvcm1hdC0+YmlXaWR0aCkKCVRoaXMtPmJSZXNpemUgPSBGQUxTRTsKICAgICAgZWxzZQoJVGhpcy0+YlJlc2l6ZSA9IFRSVUU7CiAgICB9CgogICAgaWYgKFRoaXMtPmJSZXNpemUpIHsKICAgICAgVGhpcy0+eCAgPSB4OwogICAgICBUaGlzLT55ICA9IHk7CiAgICAgIFRoaXMtPmR4ID0gZHg7CiAgICAgIFRoaXMtPmR5ID0gZHk7CgogICAgICBpZiAoSUNEZWNvbXByZXNzRXhCZWdpbihUaGlzLT5oaWMsMCxUaGlzLT5scEluRm9ybWF0LFRoaXMtPmxwSW5CdWZmZXIsMCwKCQkJICAgICAgMCxUaGlzLT5scEluRm9ybWF0LT5iaVdpZHRoLAoJCQkgICAgICBUaGlzLT5scEluRm9ybWF0LT5iaUhlaWdodCxUaGlzLT5scE91dEZvcm1hdCwKCQkJICAgICAgVGhpcy0+bHBPdXRCdWZmZXIsIHgsIHksIGR4LCBkeSkgPT0gSUNFUlJfT0spCglyZXR1cm4gQVZJRVJSX09LOwogICAgfSBlbHNlIGlmIChJQ0RlY29tcHJlc3NCZWdpbihUaGlzLT5oaWMsIFRoaXMtPmxwSW5Gb3JtYXQsCgkJCQkgVGhpcy0+bHBPdXRGb3JtYXQpID09IElDRVJSX09LKQogICAgICByZXR1cm4gQVZJRVJSX09LOwoKICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwoKICAgIHJldHVybiBBVklFUlJfQ09NUFJFU1NPUjsKICB9Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8K