LyoKICogQ29weXJpZ2h0IDIwMDItMjAwMyBNaWNoYWVsIEf8bm5ld2lnCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIKICogdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVQogKiBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQogKi8KCiNkZWZpbmUgQ09NX05PX1dJTkRPV1NfSAojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRhcmcuaD4KCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbm5scy5oIgojaW5jbHVkZSAid2luZ2RpLmgiCiNpbmNsdWRlICJ3aW51c2VyLmgiCiNpbmNsdWRlICJ2ZncuaCIKCiNpbmNsdWRlICJhdmlmaWxlX3ByaXZhdGUuaCIKCiNpbmNsdWRlICJ3aW5lL2RlYnVnLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChhdmlmaWxlKTsKCiNpZm5kZWYgRElCUFRSCiNkZWZpbmUgRElCUFRSKGxwKSAgICAgICgoTFBCWVRFKShscCkgKyAobHApLT5iaVNpemUgKyBcCiAgICAgICAgICAgICAgICAgICAgICAgICAobHApLT5iaUNsclVzZWQgKiBzaXplb2YoUkdCUVVBRCkpCiNlbmRpZgoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mblF1ZXJ5SW50ZXJmYWNlKElHZXRGcmFtZSAqaWZhY2UsCgkJCQkJCSBSRUZJSUQgcmVmaWlkLCBMUFZPSUQgKm9iaik7CnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJR2V0RnJhbWVfZm5BZGRSZWYoSUdldEZyYW1lICppZmFjZSk7CnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJR2V0RnJhbWVfZm5SZWxlYXNlKElHZXRGcmFtZSAqaWZhY2UpOwpzdGF0aWMgTFBWT0lEICBXSU5BUEkgSUdldEZyYW1lX2ZuR2V0RnJhbWUoSUdldEZyYW1lICppZmFjZSwgTE9ORyBsUG9zKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mbkJlZ2luKElHZXRGcmFtZSAqaWZhY2UsIExPTkcgbFN0YXJ0LAoJCQkJCUxPTkcgbEVuZCwgTE9ORyBsUmF0ZSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJR2V0RnJhbWVfZm5FbmQoSUdldEZyYW1lICppZmFjZSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJR2V0RnJhbWVfZm5TZXRGb3JtYXQoSUdldEZyYW1lICppZmFjZSwKCQkJCQkgICAgTFBCSVRNQVBJTkZPSEVBREVSIGxwYmksCgkJCQkJICAgIExQVk9JRCBscEJpdHMsIElOVCB4LCBJTlQgeSwKCQkJCQkgICAgSU5UIGR4LCBJTlQgZHkpOwoKc3RhdGljIGNvbnN0IHN0cnVjdCBJR2V0RnJhbWVWdGJsIGlnZXRmcmFtZVZ0YmwgPSB7CiAgSUdldEZyYW1lX2ZuUXVlcnlJbnRlcmZhY2UsCiAgSUdldEZyYW1lX2ZuQWRkUmVmLAogIElHZXRGcmFtZV9mblJlbGVhc2UsCiAgSUdldEZyYW1lX2ZuR2V0RnJhbWUsCiAgSUdldEZyYW1lX2ZuQmVnaW4sCiAgSUdldEZyYW1lX2ZuRW5kLAogIElHZXRGcmFtZV9mblNldEZvcm1hdAp9OwoKdHlwZWRlZiBzdHJ1Y3QgX0lHZXRGcmFtZUltcGwgewogIC8qIElVbmtub3duIHN0dWZmICovCiAgY29uc3QgSUdldEZyYW1lVnRibCAqbHBWdGJsOwogIExPTkcgICAgICAgICAgICAgICByZWY7CgogIC8qIElHZXRGcmFtZSBzdHVmZiAqLwogIEJPT0wgICAgICAgICAgICAgICBiRml4ZWRTdHJlYW07CiAgUEFWSVNUUkVBTSAgICAgICAgIHBTdHJlYW07CgogIExQVk9JRCAgICAgICAgICAgICBscEluQnVmZmVyOwogIExPTkcgICAgICAgICAgICAgICBjYkluQnVmZmVyOwogIExQQklUTUFQSU5GT0hFQURFUiBscEluRm9ybWF0OwogIExPTkcgICAgICAgICAgICAgICBjYkluRm9ybWF0OwoKICBMT05HICAgICAgICAgICAgICAgbEN1cnJlbnRGcmFtZTsKICBMUEJJVE1BUElORk9IRUFERVIgbHBPdXRGb3JtYXQ7CiAgTFBWT0lEICAgICAgICAgICAgIGxwT3V0QnVmZmVyOwoKICBISUMgICAgICAgICAgICAgICAgaGljOwogIEJPT0wgICAgICAgICAgICAgICBiUmVzaXplOwogIERXT1JEICAgICAgICAgICAgICB4OwogIERXT1JEICAgICAgICAgICAgICB5OwogIERXT1JEICAgICAgICAgICAgICBkeDsKICBEV09SRCAgICAgICAgICAgICAgZHk7CgogIEJPT0wgICAgICAgICAgICAgICBiRm9ybWF0Q2hhbmdlczsKICBEV09SRCAgICAgICAgICAgICAgZHdGb3JtYXRDaGFuZ2VDb3VudDsKICBEV09SRCAgICAgICAgICAgICAgZHdFZGl0Q291bnQ7Cn0gSUdldEZyYW1lSW1wbDsKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCnN0YXRpYyB2b2lkIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKElHZXRGcmFtZUltcGwgKlRoaXMpCnsKICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQgIT0gTlVMTCAmJiBUaGlzLT5scEluRm9ybWF0ICE9IFRoaXMtPmxwT3V0Rm9ybWF0KSB7CiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzLT5scE91dEZvcm1hdCk7CiAgICBUaGlzLT5scE91dEZvcm1hdCA9IE5VTEw7CiAgfQogIGlmIChUaGlzLT5scEluRm9ybWF0ICE9IE5VTEwpIHsKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIFRoaXMtPmxwSW5Gb3JtYXQpOwogICAgVGhpcy0+bHBJbkZvcm1hdCA9IE5VTEw7CiAgfQogIGlmIChUaGlzLT5oaWMgIT0gTlVMTCkgewogICAgaWYgKFRoaXMtPmJSZXNpemUpCiAgICAgIElDRGVjb21wcmVzc0V4RW5kKFRoaXMtPmhpYyk7CiAgICBlbHNlCiAgICAgIElDRGVjb21wcmVzc0VuZChUaGlzLT5oaWMpOwogICAgSUNDbG9zZShUaGlzLT5oaWMpOwogICAgVGhpcy0+aGljID0gTlVMTDsKICB9Cn0KClBHRVRGUkFNRSBBVklGSUxFX0NyZWF0ZUdldEZyYW1lKFBBVklTVFJFQU0gcFN0cmVhbSkKewogIElHZXRGcmFtZUltcGwgKnBnOwoKICAvKiBjaGVjayBwYXJhbWV0ZXIgKi8KICBpZiAocFN0cmVhbSA9PSBOVUxMKQogICAgcmV0dXJuIE5VTEw7CgogIHBnID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIEhFQVBfWkVST19NRU1PUlksIHNpemVvZihJR2V0RnJhbWVJbXBsKSk7CiAgaWYgKHBnICE9IE5VTEwpIHsKICAgIHBnLT5scFZ0YmwgICAgICAgID0gJmlnZXRmcmFtZVZ0Ymw7CiAgICBwZy0+cmVmICAgICAgICAgICA9IDE7CiAgICBwZy0+bEN1cnJlbnRGcmFtZSA9IC0xOwogICAgcGctPnBTdHJlYW0gICAgICAgPSBwU3RyZWFtOwogICAgSUFWSVN0cmVhbV9BZGRSZWYocFN0cmVhbSk7CiAgfQoKICByZXR1cm4gKFBHRVRGUkFNRSlwZzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mblF1ZXJ5SW50ZXJmYWNlKElHZXRGcmFtZSAqaWZhY2UsCgkJCQkJCSBSRUZJSUQgcmVmaWlkLCBMUFZPSUQgKm9iaikKewogIElHZXRGcmFtZUltcGwgKlRoaXMgPSAoSUdldEZyYW1lSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVzLCVwKVxuIiwgVGhpcywgZGVidWdzdHJfZ3VpZChyZWZpaWQpLCBvYmopOwoKICBpZiAoSXNFcXVhbEdVSUQoJklJRF9JVW5rbm93biwgcmVmaWlkKSB8fAogICAgICBJc0VxdWFsR1VJRCgmSUlEX0lHZXRGcmFtZSwgcmVmaWlkKSkgewogICAgKm9iaiA9IGlmYWNlOwogICAgcmV0dXJuIFNfT0s7CiAgfQoKICByZXR1cm4gT0xFX0VfRU5VTV9OT01PUkU7Cn0KCnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJR2V0RnJhbWVfZm5BZGRSZWYoSUdldEZyYW1lICppZmFjZSkKewogIElHZXRGcmFtZUltcGwgKlRoaXMgPSAoSUdldEZyYW1lSW1wbCAqKWlmYWNlOwogIFVMT05HIHJlZiA9IEludGVybG9ja2VkSW5jcmVtZW50KCZUaGlzLT5yZWYpOwoKICBUUkFDRSgiKCVwKVxuIiwgaWZhY2UpOwoKICByZXR1cm4gcmVmOwp9CgpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSUdldEZyYW1lX2ZuUmVsZWFzZShJR2V0RnJhbWUgKmlmYWNlKQp7CiAgSUdldEZyYW1lSW1wbCAqVGhpcyA9IChJR2V0RnJhbWVJbXBsICopaWZhY2U7CiAgVUxPTkcgcmVmID0gSW50ZXJsb2NrZWREZWNyZW1lbnQoJlRoaXMtPnJlZik7CgogIFRSQUNFKCIoJXApXG4iLCBpZmFjZSk7CgogIGlmICghcmVmKSB7CiAgICBBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKICAgIGlmIChUaGlzLT5wU3RyZWFtICE9IE5VTEwpIHsKICAgICAgSUFWSVN0cmVhbV9SZWxlYXNlKFRoaXMtPnBTdHJlYW0pOwogICAgICBUaGlzLT5wU3RyZWFtID0gTlVMTDsKICAgIH0KCiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBpZmFjZSk7CiAgICByZXR1cm4gMDsKICB9CgogIHJldHVybiByZWY7Cn0KCnN0YXRpYyBMUFZPSUQgIFdJTkFQSSBJR2V0RnJhbWVfZm5HZXRGcmFtZShJR2V0RnJhbWUgKmlmYWNlLCBMT05HIGxQb3MpCnsKICBJR2V0RnJhbWVJbXBsICpUaGlzID0gKElHZXRGcmFtZUltcGwgKilpZmFjZTsKCiAgTE9ORyByZWFkQnl0ZXM7CiAgTE9ORyByZWFkU2FtcGxlczsKCiAgVFJBQ0UoIiglcCwlbGQpXG4iLCBpZmFjZSwgbFBvcyk7CgogIC8qIFdlIGRvbid0IHdhbnQgbmVnYXRpdmUgc3RhcnQgdmFsdWVzISAtLSBtYXJrcyBpbnZhbGlkIGJ1ZmZlciBjb250ZW50ICovCiAgaWYgKGxQb3MgPCAwKQogICAgcmV0dXJuIE5VTEw7CgogIC8qIGNoZWNrIHN0YXRlICovCiAgaWYgKFRoaXMtPnBTdHJlYW0gPT0gTlVMTCkKICAgIHJldHVybiBOVUxMOwogIGlmIChUaGlzLT5scEluRm9ybWF0ID09IE5VTEwpCiAgICByZXR1cm4gTlVMTDsKCiAgLyogQ291bGQgc3RyZWFtIGhhdmUgY2hhbmdlZD8gKi8KICBpZiAoISBUaGlzLT5iRml4ZWRTdHJlYW0pIHsKICAgIEFWSVNUUkVBTUlORk9XIHNJbmZvOwoKICAgIElBVklTdHJlYW1fSW5mbyhUaGlzLT5wU3RyZWFtLCAmc0luZm8sIHNpemVvZihzSW5mbykpOwoKICAgIGlmIChzSW5mby5kd0VkaXRDb3VudCAhPSBUaGlzLT5kd0VkaXRDb3VudCkgewogICAgICBUaGlzLT5kd0VkaXRDb3VudCAgID0gc0luZm8uZHdFZGl0Q291bnQ7CiAgICAgIFRoaXMtPmxDdXJyZW50RnJhbWUgPSAtMTsKICAgIH0KCiAgICBpZiAoc0luZm8uZHdGb3JtYXRDaGFuZ2VDb3VudCAhPSBUaGlzLT5kd0Zvcm1hdENoYW5nZUNvdW50KSB7CiAgICAgIC8qIHN0cmVhbSBoYXMgY2hhbmdlZCAqLwogICAgICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQgIT0gTlVMTCkgewoJQklUTUFQSU5GT0hFQURFUiBiaTsKCgltZW1jcHkoJmJpLCBUaGlzLT5scE91dEZvcm1hdCwgc2l6ZW9mKGJpKSk7CglBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKCglpZiAoRkFJTEVEKElHZXRGcmFtZV9TZXRGb3JtYXQoaWZhY2UsICZiaSwgTlVMTCwgMCwgMCwgLTEsIC0xKSkpIHsKCSAgaWYgKEZBSUxFRChJR2V0RnJhbWVfU2V0Rm9ybWF0KGlmYWNlLCBOVUxMLCBOVUxMLCAwLCAwLCAtMSwgLTEpKSkKCSAgICByZXR1cm4gTlVMTDsKCX0KICAgICAgfSBlbHNlIGlmIChGQUlMRUQoSUdldEZyYW1lX1NldEZvcm1hdChpZmFjZSwgTlVMTCwgTlVMTCwgMCwgMCwgLTEsIC0xKSkpCglyZXR1cm4gTlVMTDsKICAgIH0KICB9CgogIGlmIChsUG9zICE9IFRoaXMtPmxDdXJyZW50RnJhbWUpIHsKICAgIExPTkcgbE5leHQgPSBJQVZJU3RyZWFtX0ZpbmRTYW1wbGUoVGhpcy0+cFN0cmVhbSxsUG9zLEZJTkRfS0VZfEZJTkRfUFJFVik7CgogICAgaWYgKGxOZXh0ID09IC0xKQogICAgICByZXR1cm4gTlVMTDsgLyogZnJhbWUgZG9lc24ndCBleGlzdCAqLwogICAgaWYgKGxOZXh0IDw9IFRoaXMtPmxDdXJyZW50RnJhbWUgJiYgVGhpcy0+bEN1cnJlbnRGcmFtZSA8IGxQb3MpCiAgICAgIGxOZXh0ID0gVGhpcy0+bEN1cnJlbnRGcmFtZSArIDE7CgogICAgZm9yICg7IGxOZXh0IDw9IGxQb3M7IGxOZXh0KyspIHsKICAgICAgLyogbmV3IGZvcm1hdCBmb3IgdGhpcyBmcmFtZT8gKi8KICAgICAgaWYgKFRoaXMtPmJGb3JtYXRDaGFuZ2VzKSB7CglJQVZJU3RyZWFtX1JlYWRGb3JtYXQoVGhpcy0+cFN0cmVhbSwgbE5leHQsCgkJCSAgICAgIFRoaXMtPmxwSW5Gb3JtYXQsICZUaGlzLT5jYkluRm9ybWF0KTsKCWlmIChUaGlzLT5scE91dEZvcm1hdCAhPSBOVUxMKSB7CgkgIGlmIChUaGlzLT5scE91dEZvcm1hdC0+YmlCaXRDb3VudCA8PSA4KQoJICAgIElDRGVjb21wcmVzc0dldFBhbGV0dGUoVGhpcy0+aGljLCBUaGlzLT5scEluRm9ybWF0LAoJCQkJICAgVGhpcy0+bHBPdXRGb3JtYXQpOwoJfQogICAgICB9CgogICAgICAvKiByZWFkIGlucHV0IGZyYW1lICovCiAgICAgIHdoaWxlIChGQUlMRUQoQVZJU3RyZWFtUmVhZChUaGlzLT5wU3RyZWFtLCBsTmV4dCwgMSwgVGhpcy0+bHBJbkJ1ZmZlciwKCQkJCSAgVGhpcy0+Y2JJbkJ1ZmZlciwgJnJlYWRCeXRlcywgJnJlYWRTYW1wbGVzKSkpIHsKCS8qIG5vdCBlbm91Z2ggbWVtb3J5IGZvciBpbnB1dCBidWZmZXI/ICovCglyZWFkQnl0ZXMgPSAwOwoJaWYgKEZBSUxFRChBVklTdHJlYW1TYW1wbGVTaXplKFRoaXMtPnBTdHJlYW0sIGxOZXh0LCAmcmVhZEJ5dGVzKSkpCgkgIHJldHVybiBOVUxMOyAvKiBiYWQgdGhpbmcsIGJ1dCBiYWQgdGhpbmdzIHdpbGwgaGFwcGVuICovCglpZiAocmVhZEJ5dGVzIDw9IDApIHsKCSAgRVJSKCI6IElBVklTdHJlYW06OlJFYWQgZG9lc24ndCByZXR1cm4gbmVlZGVkIGJ5dGVzIVxuIik7CgkgIHJldHVybiBOVUxMOwoJfQoKCS8qIElBVklTdHJlYW06OlJlYWQgZmFpbGVkIGJlY2F1c2Ugb2Ygb3RoZXIgcmVhc29ucyBub3QgYnVmZmVyc2l6ZT8gKi8KCWlmIChUaGlzLT5jYkluQnVmZmVyID49IHJlYWRCeXRlcykKCSAgYnJlYWs7CglUaGlzLT5jYkluQnVmZmVyID0gVGhpcy0+Y2JJbkZvcm1hdCArIHJlYWRCeXRlczsKCVRoaXMtPmxwSW5Gb3JtYXQgPSBIZWFwUmVBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzLT5scEluRm9ybWF0LCBUaGlzLT5jYkluQnVmZmVyKTsKCWlmIChUaGlzLT5scEluRm9ybWF0ID09IE5VTEwpCgkgIHJldHVybiBOVUxMOyAvKiBvdXQgb2YgbWVtb3J5ICovCglUaGlzLT5scEluQnVmZmVyID0gKEJZVEUqKVRoaXMtPmxwSW5Gb3JtYXQgKyBUaGlzLT5jYkluRm9ybWF0OwogICAgICB9CgogICAgICBpZiAocmVhZFNhbXBsZXMgIT0gMSkgewoJRVJSKCI6IG5vIGZyYW1lcyByZWFkXG4iKTsKCXJldHVybiBOVUxMOwogICAgICB9CiAgICAgIGlmIChyZWFkQnl0ZXMgIT0gMCkgewoJVGhpcy0+bHBJbkZvcm1hdC0+YmlTaXplSW1hZ2UgPSByZWFkQnl0ZXM7CgoJLyogbm90aGluZyB0byBkZWNvbXByZXNzPyAqLwoJaWYgKFRoaXMtPmhpYyA9PSBOVUxMKSB7CgkgIFRoaXMtPmxDdXJyZW50RnJhbWUgPSBsUG9zOwoJICByZXR1cm4gVGhpcy0+bHBJbkZvcm1hdDsKCX0KCglpZiAoVGhpcy0+YlJlc2l6ZSkgewoJICBJQ0RlY29tcHJlc3NFeChUaGlzLT5oaWMsMCxUaGlzLT5scEluRm9ybWF0LFRoaXMtPmxwSW5CdWZmZXIsMCwwLAoJCQkgVGhpcy0+bHBJbkZvcm1hdC0+YmlXaWR0aCxUaGlzLT5scEluRm9ybWF0LT5iaUhlaWdodCwKCQkJIFRoaXMtPmxwT3V0Rm9ybWF0LFRoaXMtPmxwT3V0QnVmZmVyLFRoaXMtPngsVGhpcy0+eSwKCQkJIFRoaXMtPmR4LFRoaXMtPmR5KTsKCX0gZWxzZSB7CgkgIElDRGVjb21wcmVzcyhUaGlzLT5oaWMsIDAsIFRoaXMtPmxwSW5Gb3JtYXQsIFRoaXMtPmxwSW5CdWZmZXIsCgkJICAgICAgIFRoaXMtPmxwT3V0Rm9ybWF0LCBUaGlzLT5scE91dEJ1ZmZlcik7Cgl9CiAgICAgIH0KICAgIH0gLyogZm9yIChsTmV4dCA8IGxQb3MpICovCiAgfSAvKiBpZiAoVGhpcy0+bEN1cnJlbnRGcmFtZSAhPSBsUG9zKSAqLwoKICByZXR1cm4gKFRoaXMtPmhpYyA9PSBOVUxMID8gVGhpcy0+bHBJbkZvcm1hdCA6IFRoaXMtPmxwT3V0Rm9ybWF0KTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mbkJlZ2luKElHZXRGcmFtZSAqaWZhY2UsIExPTkcgbFN0YXJ0LAoJCQkJCUxPTkcgbEVuZCwgTE9ORyBsUmF0ZSkKewogIElHZXRGcmFtZUltcGwgKlRoaXMgPSAoSUdldEZyYW1lSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVsZCwlbGQsJWxkKVxuIiwgaWZhY2UsIGxTdGFydCwgbEVuZCwgbFJhdGUpOwoKICBUaGlzLT5iRml4ZWRTdHJlYW0gPSBUUlVFOwoKICByZXR1cm4gKElHZXRGcmFtZV9HZXRGcmFtZShpZmFjZSwgbFN0YXJ0KSA/IEFWSUVSUl9PSyA6IEFWSUVSUl9FUlJPUik7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJR2V0RnJhbWVfZm5FbmQoSUdldEZyYW1lICppZmFjZSkKewogIElHZXRGcmFtZUltcGwgKlRoaXMgPSAoSUdldEZyYW1lSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwKVxuIiwgaWZhY2UpOwoKICBUaGlzLT5iRml4ZWRTdHJlYW0gPSBGQUxTRTsKCiAgcmV0dXJuIEFWSUVSUl9PSzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mblNldEZvcm1hdChJR2V0RnJhbWUgKmlmYWNlLAoJCQkJCSAgICBMUEJJVE1BUElORk9IRUFERVIgbHBiaVdhbnRlZCwKCQkJCQkgICAgTFBWT0lEIGxwQml0cywgSU5UIHgsIElOVCB5LAoJCQkJCSAgICBJTlQgZHgsIElOVCBkeSkKewogIElHZXRGcmFtZUltcGwgKlRoaXMgPSAoSUdldEZyYW1lSW1wbCAqKWlmYWNlOwoKICBBVklTVFJFQU1JTkZPVyAgICAgc0luZm87CiAgTFBCSVRNQVBJTkZPSEVBREVSIGxwYmkgICAgICAgICA9IGxwYmlXYW50ZWQ7CiAgQk9PTCAgICAgICAgICAgICAgIGJCZXN0RGlzcGxheSA9IEZBTFNFOwoKICBUUkFDRSgiKCVwLCVwLCVwLCVkLCVkLCVkLCVkKVxuIiwgaWZhY2UsIGxwYmlXYW50ZWQsIGxwQml0cywKCXgsIHksIGR4LCBkeSk7CgogIGlmIChUaGlzLT5wU3RyZWFtID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX0VSUk9SOwoKICBpZiAobHBiaVdhbnRlZCA9PSAoTFBCSVRNQVBJTkZPSEVBREVSKUFWSUdFVEZSQU1FRl9CRVNURElTUExBWUZNVCkgewogICAgbHBiaSA9IE5VTEw7CiAgICBiQmVzdERpc3BsYXkgPSBUUlVFOwogIH0KCiAgSUFWSVN0cmVhbV9JbmZvKFRoaXMtPnBTdHJlYW0sICZzSW5mbywgc2l6ZW9mKHNJbmZvKSk7CiAgaWYgKHNJbmZvLmZjY1R5cGUgIT0gc3RyZWFtdHlwZVZJREVPKQogICAgcmV0dXJuIEFWSUVSUl9VTlNVUFBPUlRFRDsKCiAgVGhpcy0+YkZvcm1hdENoYW5nZXMgPQogICAgKHNJbmZvLmR3RmxhZ3MgJiBBVklTVFJFQU1JTkZPX0ZPUk1BVENIQU5HRVMgPyBUUlVFIDogRkFMU0UgKTsKICBUaGlzLT5kd0Zvcm1hdENoYW5nZUNvdW50ID0gc0luZm8uZHdGb3JtYXRDaGFuZ2VDb3VudDsKICBUaGlzLT5kd0VkaXRDb3VudCAgICAgICAgID0gc0luZm8uZHdFZGl0Q291bnQ7CiAgVGhpcy0+bEN1cnJlbnRGcmFtZSAgICAgICA9IC0xOwoKICAvKiBnZXQgaW5wdXQgZm9ybWF0IGZyb20gc3RyZWFtICovCiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQgPT0gTlVMTCkgewogICAgSFJFU1VMVCBocjsKCiAgICBUaGlzLT5jYkluQnVmZmVyID0gKExPTkcpc0luZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplOwogICAgaWYgKFRoaXMtPmNiSW5CdWZmZXIgPT0gMCkKICAgICAgVGhpcy0+Y2JJbkJ1ZmZlciA9IDEwMjQ7CgogICAgSUFWSVN0cmVhbV9SZWFkRm9ybWF0KFRoaXMtPnBTdHJlYW0sIHNJbmZvLmR3U3RhcnQsCgkJCSAgTlVMTCwgJlRoaXMtPmNiSW5Gb3JtYXQpOwoKICAgIFRoaXMtPmxwSW5Gb3JtYXQgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgVGhpcy0+Y2JJbkZvcm1hdCArIFRoaXMtPmNiSW5CdWZmZXIpOwogICAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQgPT0gTlVMTCkgewogICAgICBBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKICAgICAgcmV0dXJuIEFWSUVSUl9NRU1PUlk7CiAgICB9CgogICAgaHIgPSBJQVZJU3RyZWFtX1JlYWRGb3JtYXQoVGhpcy0+cFN0cmVhbSwgc0luZm8uZHdTdGFydCwgVGhpcy0+bHBJbkZvcm1hdCwgJlRoaXMtPmNiSW5Gb3JtYXQpOwogICAgaWYgKEZBSUxFRChocikpIHsKICAgICAgQVZJRklMRV9DbG9zZUNvbXByZXNzb3IoVGhpcyk7CiAgICAgIHJldHVybiBocjsKICAgIH0KCiAgICBUaGlzLT5scEluQnVmZmVyID0gKChMUEJZVEUpVGhpcy0+bHBJbkZvcm1hdCkgKyBUaGlzLT5jYkluRm9ybWF0OwogIH0KCiAgLyogY2hlY2sgaW5wdXQgZm9ybWF0ICovCiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQtPmJpQ2xyVXNlZCA9PSAwICYmIFRoaXMtPmxwSW5Gb3JtYXQtPmJpQml0Q291bnQgPD0gOCkKICAgIFRoaXMtPmxwSW5Gb3JtYXQtPmJpQ2xyVXNlZCA9IDF1IDw8IFRoaXMtPmxwSW5Gb3JtYXQtPmJpQml0Q291bnQ7CiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQtPmJpU2l6ZUltYWdlID09IDAgJiYKICAgICAgVGhpcy0+bHBJbkZvcm1hdC0+YmlDb21wcmVzc2lvbiA9PSBCSV9SR0IpIHsKICAgIFRoaXMtPmxwSW5Gb3JtYXQtPmJpU2l6ZUltYWdlID0KICAgICAgRElCV0lEVEhCWVRFUygqVGhpcy0+bHBJbkZvcm1hdCkgKiBUaGlzLT5scEluRm9ybWF0LT5iaUhlaWdodDsKICB9CgogIC8qIG9ubHkgdG8gcGFzcyB0aHJvdWdoPyAqLwogIGlmIChUaGlzLT5scEluRm9ybWF0LT5iaUNvbXByZXNzaW9uID09IEJJX1JHQiAmJiBscEJpdHMgPT0gTlVMTCkgewogICAgaWYgKGxwYmkgPT0gTlVMTCB8fCAKCShscGJpLT5iaUNvbXByZXNzaW9uID09IEJJX1JHQiAmJgoJIGxwYmktPmJpV2lkdGggPT0gVGhpcy0+bHBJbkZvcm1hdC0+YmlXaWR0aCAmJgoJIGxwYmktPmJpSGVpZ2h0ID09IFRoaXMtPmxwSW5Gb3JtYXQtPmJpSGVpZ2h0ICYmCgkgbHBiaS0+YmlCaXRDb3VudCA9PSBUaGlzLT5scEluRm9ybWF0LT5iaUJpdENvdW50KSkgewogICAgICBUaGlzLT5scE91dEZvcm1hdCA9IFRoaXMtPmxwSW5Gb3JtYXQ7CiAgICAgIFRoaXMtPmxwT3V0QnVmZmVyID0gRElCUFRSKFRoaXMtPmxwSW5Gb3JtYXQpOwogICAgICByZXR1cm4gQVZJRVJSX09LOwogICAgfQogIH0KCiAgLyogbmVlZCBtZW1vcnkgZm9yIG91dHB1dCBmb3JtYXQ/ICovCiAgaWYgKFRoaXMtPmxwT3V0Rm9ybWF0ID09IE5VTEwpIHsKICAgIFRoaXMtPmxwT3V0Rm9ybWF0ID0KICAgICAgSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIDAsIHNpemVvZihCSVRNQVBJTkZPSEVBREVSKSArIDI1NiAqIHNpemVvZihSR0JRVUFEKSk7CiAgICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQgPT0gTlVMTCkgewogICAgICBBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKICAgICAgcmV0dXJuIEFWSUVSUl9NRU1PUlk7CiAgICB9CiAgfQoKICAvKiBuZWVkIGhhbmRsZSB0byB2aWRlbyBjb21wcmVzc29yICovCiAgaWYgKFRoaXMtPmhpYyA9PSBOVUxMKSB7CiAgICBGT1VSQ0MgZmNjSGFuZGxlcjsKCiAgICBpZiAoVGhpcy0+bHBJbkZvcm1hdC0+YmlDb21wcmVzc2lvbiA9PSBCSV9SR0IpCiAgICAgIGZjY0hhbmRsZXIgPSBjb21wdHlwZURJQjsKICAgIGVsc2UgaWYgKFRoaXMtPmxwSW5Gb3JtYXQtPmJpQ29tcHJlc3Npb24gPT0gQklfUkxFOCkKICAgICAgZmNjSGFuZGxlciA9IG1taW9GT1VSQ0MoJ1InLCdMJywnRScsJyAnKTsKICAgIGVsc2UKICAgICAgZmNjSGFuZGxlciA9IHNJbmZvLmZjY0hhbmRsZXI7CgogICAgaWYgKGxwYmkgIT0gTlVMTCkgewogICAgICBpZiAobHBiaS0+YmlXaWR0aCA9PSAwKQoJbHBiaS0+YmlXaWR0aCA9IFRoaXMtPmxwSW5Gb3JtYXQtPmJpV2lkdGg7CiAgICAgIGlmIChscGJpLT5iaUhlaWdodCA9PSAwKQoJbHBiaS0+YmlIZWlnaHQgPSBUaGlzLT5scEluRm9ybWF0LT5iaUhlaWdodDsKICAgIH0KCiAgICBUaGlzLT5oaWMgPSBJQ0xvY2F0ZShJQ1RZUEVfVklERU8sIGZjY0hhbmRsZXIsIFRoaXMtPmxwSW5Gb3JtYXQsIGxwYmksIElDTU9ERV9ERUNPTVBSRVNTKTsKICAgIGlmIChUaGlzLT5oaWMgPT0gTlVMTCkgewogICAgICBBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKICAgICAgcmV0dXJuIEFWSUVSUl9OT0NPTVBSRVNTT1I7CiAgICB9CiAgfQoKICAvKiBvdXRwdXQgZm9ybWF0IGdpdmVuPyAqLwogIGlmIChscGJpICE9IE5VTEwpIHsKICAgIC8qIGNoZWNrIHRoZSBnaXZlbiBvdXRwdXQgZm9ybWF0IC4uLiAqLwogICAgaWYgKGxwYmktPmJpQ2xyVXNlZCA9PSAwICYmIGxwYmktPmJpQml0Q291bnQgPD0gOCkKICAgICAgbHBiaS0+YmlDbHJVc2VkID0gMXUgPDwgbHBiaS0+YmlCaXRDb3VudDsKCiAgICAvKiAuLi4gYW5kIHJlbWVtYmVyIGl0ICovCiAgICBtZW1jcHkoVGhpcy0+bHBPdXRGb3JtYXQsIGxwYmksCgkgICBscGJpLT5iaVNpemUgKyBscGJpLT5iaUNsclVzZWQgKiBzaXplb2YoUkdCUVVBRCkpOwogICAgaWYgKGxwYmktPmJpQml0Q291bnQgPD0gOCkKICAgICAgSUNEZWNvbXByZXNzR2V0UGFsZXR0ZShUaGlzLT5oaWMsIFRoaXMtPmxwSW5Gb3JtYXQsIFRoaXMtPmxwT3V0Rm9ybWF0KTsKCiAgICByZXR1cm4gQVZJRVJSX09LOwogIH0gZWxzZSB7CiAgICBpZiAoYkJlc3REaXNwbGF5KSB7CiAgICAgIElDR2V0RGlzcGxheUZvcm1hdChUaGlzLT5oaWMsIFRoaXMtPmxwSW5Gb3JtYXQsCgkJCSBUaGlzLT5scE91dEZvcm1hdCwgMCwgZHgsIGR5KTsKICAgIH0gZWxzZSBpZiAoSUNEZWNvbXByZXNzR2V0Rm9ybWF0KFRoaXMtPmhpYywgVGhpcy0+bHBJbkZvcm1hdCwKCQkJCSAgICAgVGhpcy0+bHBPdXRGb3JtYXQpIDwgMCkgewogICAgICBBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKICAgICAgcmV0dXJuIEFWSUVSUl9OT0NPTVBSRVNTT1I7CiAgICB9CgogICAgLyogY2hlY2sgb3V0cHV0IGZvcm1hdCAqLwogICAgaWYgKFRoaXMtPmxwT3V0Rm9ybWF0LT5iaUNsclVzZWQgPT0gMCAmJgoJVGhpcy0+bHBPdXRGb3JtYXQtPmJpQml0Q291bnQgPD0gOCkKICAgICAgVGhpcy0+bHBPdXRGb3JtYXQtPmJpQ2xyVXNlZCA9IDF1IDw8IFRoaXMtPmxwT3V0Rm9ybWF0LT5iaUJpdENvdW50OwogICAgaWYgKFRoaXMtPmxwT3V0Rm9ybWF0LT5iaVNpemVJbWFnZSA9PSAwICYmCglUaGlzLT5scE91dEZvcm1hdC0+YmlDb21wcmVzc2lvbiA9PSBCSV9SR0IpIHsKICAgICAgVGhpcy0+bHBPdXRGb3JtYXQtPmJpU2l6ZUltYWdlID0KCURJQldJRFRIQllURVMoKlRoaXMtPmxwT3V0Rm9ybWF0KSAqIFRoaXMtPmxwT3V0Rm9ybWF0LT5iaUhlaWdodDsKICAgIH0KCiAgICBpZiAobHBCaXRzID09IE5VTEwpIHsKICAgICAgcmVnaXN0ZXIgRFdPUkQgc2l6ZSA9IFRoaXMtPmxwT3V0Rm9ybWF0LT5iaUNsclVzZWQgKiBzaXplb2YoUkdCUVVBRCk7CgogICAgICBzaXplICs9IFRoaXMtPmxwT3V0Rm9ybWF0LT5iaVNpemUgKyBUaGlzLT5scE91dEZvcm1hdC0+YmlTaXplSW1hZ2U7CiAgICAgIFRoaXMtPmxwT3V0Rm9ybWF0ID0gSGVhcFJlQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgVGhpcy0+bHBPdXRGb3JtYXQsIHNpemUpOwogICAgICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQgPT0gTlVMTCkgewoJQVZJRklMRV9DbG9zZUNvbXByZXNzb3IoVGhpcyk7CglyZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgICAgfQogICAgICBUaGlzLT5scE91dEJ1ZmZlciA9IERJQlBUUihUaGlzLT5scE91dEZvcm1hdCk7CiAgICB9IGVsc2UKICAgICAgVGhpcy0+bHBPdXRCdWZmZXIgPSBscEJpdHM7CgogICAgLyogZm9yIHVzZXIgc2l6ZSB3YXMgaXJyZWxldmFudCAqLwogICAgaWYgKGR4ID09IC0xKQogICAgICBkeCA9IFRoaXMtPmxwT3V0Rm9ybWF0LT5iaVdpZHRoOwogICAgaWYgKGR5ID09IC0xKQogICAgICBkeSA9IFRoaXMtPmxwT3V0Rm9ybWF0LT5iaUhlaWdodDsKCiAgICAvKiBuZWVkIHRvIHJlc2l6ZT8gKi8KICAgIGlmICh4ICE9IDAgfHwgeSAhPSAwKSB7CiAgICAgIGlmIChkeSA9PSBUaGlzLT5scE91dEZvcm1hdC0+YmlIZWlnaHQgJiYKCSAgZHggPT0gVGhpcy0+bHBPdXRGb3JtYXQtPmJpV2lkdGgpCglUaGlzLT5iUmVzaXplID0gRkFMU0U7CiAgICAgIGVsc2UKCVRoaXMtPmJSZXNpemUgPSBUUlVFOwogICAgfQoKICAgIGlmIChUaGlzLT5iUmVzaXplKSB7CiAgICAgIFRoaXMtPnggID0geDsKICAgICAgVGhpcy0+eSAgPSB5OwogICAgICBUaGlzLT5keCA9IGR4OwogICAgICBUaGlzLT5keSA9IGR5OwoKICAgICAgaWYgKElDRGVjb21wcmVzc0V4QmVnaW4oVGhpcy0+aGljLDAsVGhpcy0+bHBJbkZvcm1hdCxUaGlzLT5scEluQnVmZmVyLDAsCgkJCSAgICAgIDAsVGhpcy0+bHBJbkZvcm1hdC0+YmlXaWR0aCwKCQkJICAgICAgVGhpcy0+bHBJbkZvcm1hdC0+YmlIZWlnaHQsVGhpcy0+bHBPdXRGb3JtYXQsCgkJCSAgICAgIFRoaXMtPmxwT3V0QnVmZmVyLCB4LCB5LCBkeCwgZHkpID09IElDRVJSX09LKQoJcmV0dXJuIEFWSUVSUl9PSzsKICAgIH0gZWxzZSBpZiAoSUNEZWNvbXByZXNzQmVnaW4oVGhpcy0+aGljLCBUaGlzLT5scEluRm9ybWF0LAoJCQkJIFRoaXMtPmxwT3V0Rm9ybWF0KSA9PSBJQ0VSUl9PSykKICAgICAgcmV0dXJuIEFWSUVSUl9PSzsKCiAgICBBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKCiAgICByZXR1cm4gQVZJRVJSX0NPTVBSRVNTT1I7CiAgfQp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCg==