LyoKICogQ29weXJpZ2h0IDIwMDItMjAwMyBNaWNoYWVsIEf8bm5ld2lnCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIKICogdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVQogKiBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQogKi8KCiNkZWZpbmUgQ09NX05PX1dJTkRPV1NfSAojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRhcmcuaD4KCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbm5scy5oIgojaW5jbHVkZSAid2luZG93c3guaCIKI2luY2x1ZGUgIndpbmdkaS5oIgojaW5jbHVkZSAid2ludXNlci5oIgojaW5jbHVkZSAidmZ3LmgiCgojaW5jbHVkZSAiYXZpZmlsZV9wcml2YXRlLmgiCgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKV0lORV9ERUZBVUxUX0RFQlVHX0NIQU5ORUwoYXZpZmlsZSk7CgojaWZuZGVmIERJQlBUUgojZGVmaW5lIERJQlBUUihscCkgICAgICAoKExQQllURSkobHApICsgKGxwKS0+YmlTaXplICsgXAogICAgICAgICAgICAgICAgICAgICAgICAgKGxwKS0+YmlDbHJVc2VkICogc2l6ZW9mKFJHQlFVQUQpKQojZW5kaWYKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJR2V0RnJhbWVfZm5RdWVyeUludGVyZmFjZShJR2V0RnJhbWUgKmlmYWNlLAoJCQkJCQkgUkVGSUlEIHJlZmlpZCwgTFBWT0lEICpvYmopOwpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSUdldEZyYW1lX2ZuQWRkUmVmKElHZXRGcmFtZSAqaWZhY2UpOwpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSUdldEZyYW1lX2ZuUmVsZWFzZShJR2V0RnJhbWUgKmlmYWNlKTsKc3RhdGljIExQVk9JRCAgV0lOQVBJIElHZXRGcmFtZV9mbkdldEZyYW1lKElHZXRGcmFtZSAqaWZhY2UsIExPTkcgbFBvcyk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJR2V0RnJhbWVfZm5CZWdpbihJR2V0RnJhbWUgKmlmYWNlLCBMT05HIGxTdGFydCwKCQkJCQlMT05HIGxFbmQsIExPTkcgbFJhdGUpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUdldEZyYW1lX2ZuRW5kKElHZXRGcmFtZSAqaWZhY2UpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUdldEZyYW1lX2ZuU2V0Rm9ybWF0KElHZXRGcmFtZSAqaWZhY2UsCgkJCQkJICAgIExQQklUTUFQSU5GT0hFQURFUiBscGJpLAoJCQkJCSAgICBMUFZPSUQgbHBCaXRzLCBJTlQgeCwgSU5UIHksCgkJCQkJICAgIElOVCBkeCwgSU5UIGR5KTsKCnN0cnVjdCBJQ09NX1ZUQUJMRShJR2V0RnJhbWUpIGlnZXRmcmFtZVZ0YmwgPSB7CiAgSUNPTV9NU1ZUQUJMRV9DT01QQVRfRHVtbXlSVFRJVkFMVUUKICBJR2V0RnJhbWVfZm5RdWVyeUludGVyZmFjZSwKICBJR2V0RnJhbWVfZm5BZGRSZWYsCiAgSUdldEZyYW1lX2ZuUmVsZWFzZSwKICBJR2V0RnJhbWVfZm5HZXRGcmFtZSwKICBJR2V0RnJhbWVfZm5CZWdpbiwKICBJR2V0RnJhbWVfZm5FbmQsCiAgSUdldEZyYW1lX2ZuU2V0Rm9ybWF0Cn07Cgp0eXBlZGVmIHN0cnVjdCBfSUdldEZyYW1lSW1wbCB7CiAgLyogSVVua25vd24gc3R1ZmYgKi8KICBJQ09NX1ZGSUVMRChJR2V0RnJhbWUpOwogIERXT1JEICAgICAgICAgICAgICByZWY7CgogIC8qIElHZXRGcmFtZSBzdHVmZiAqLwogIEJPT0wgICAgICAgICAgICAgICBiRml4ZWRTdHJlYW07CiAgUEFWSVNUUkVBTSAgICAgICAgIHBTdHJlYW07CgogIExQVk9JRCAgICAgICAgICAgICBscEluQnVmZmVyOwogIExPTkcgICAgICAgICAgICAgICBjYkluQnVmZmVyOwogIExQQklUTUFQSU5GT0hFQURFUiBscEluRm9ybWF0OwogIExPTkcgICAgICAgICAgICAgICBjYkluRm9ybWF0OwoKICBMT05HICAgICAgICAgICAgICAgbEN1cnJlbnRGcmFtZTsKICBMUEJJVE1BUElORk9IRUFERVIgbHBPdXRGb3JtYXQ7CiAgTFBWT0lEICAgICAgICAgICAgIGxwT3V0QnVmZmVyOwoKICBISUMgICAgICAgICAgICAgICAgaGljOwogIEJPT0wgICAgICAgICAgICAgICBiUmVzaXplOwogIERXT1JEICAgICAgICAgICAgICB4OwogIERXT1JEICAgICAgICAgICAgICB5OwogIERXT1JEICAgICAgICAgICAgICBkeDsKICBEV09SRCAgICAgICAgICAgICAgZHk7CgogIEJPT0wgICAgICAgICAgICAgICBiRm9ybWF0Q2hhbmdlczsKICBEV09SRCAgICAgICAgICAgICAgZHdGb3JtYXRDaGFuZ2VDb3VudDsKICBEV09SRCAgICAgICAgICAgICAgZHdFZGl0Q291bnQ7Cn0gSUdldEZyYW1lSW1wbDsKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCnN0YXRpYyB2b2lkIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKElHZXRGcmFtZUltcGwgKlRoaXMpCnsKICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQgIT0gTlVMTCAmJiBUaGlzLT5scEluRm9ybWF0ICE9IFRoaXMtPmxwT3V0Rm9ybWF0KSB7CiAgICBHbG9iYWxGcmVlUHRyKFRoaXMtPmxwT3V0Rm9ybWF0KTsKICAgIFRoaXMtPmxwT3V0Rm9ybWF0ID0gTlVMTDsKICB9CiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQgIT0gTlVMTCkgewogICAgR2xvYmFsRnJlZVB0cihUaGlzLT5scEluRm9ybWF0KTsKICAgIFRoaXMtPmxwSW5Gb3JtYXQgPSBOVUxMOwogIH0KICBpZiAoVGhpcy0+aGljICE9IE5VTEwpIHsKICAgIGlmIChUaGlzLT5iUmVzaXplKQogICAgICBJQ0RlY29tcHJlc3NFeEVuZChUaGlzLT5oaWMpOwogICAgZWxzZQogICAgICBJQ0RlY29tcHJlc3NFbmQoVGhpcy0+aGljKTsKICAgIElDQ2xvc2UoVGhpcy0+aGljKTsKICAgIFRoaXMtPmhpYyA9IE5VTEw7CiAgfQp9CgpQR0VURlJBTUUgQVZJRklMRV9DcmVhdGVHZXRGcmFtZShQQVZJU1RSRUFNIHBTdHJlYW0pCnsKICBJR2V0RnJhbWVJbXBsICpwZzsKCiAgLyogY2hlY2sgcGFyYW1ldGVyICovCiAgaWYgKHBTdHJlYW0gPT0gTlVMTCkKICAgIHJldHVybiBOVUxMOwoKICBwZyA9IChJR2V0RnJhbWVJbXBsKilMb2NhbEFsbG9jKExQVFIsIHNpemVvZihJR2V0RnJhbWVJbXBsKSk7CiAgaWYgKHBnICE9IE5VTEwpIHsKICAgIHBnLT5scFZ0YmwgICAgICAgID0gJmlnZXRmcmFtZVZ0Ymw7CiAgICBwZy0+cmVmICAgICAgICAgICA9IDE7CiAgICBwZy0+bEN1cnJlbnRGcmFtZSA9IC0xOwogICAgcGctPnBTdHJlYW0gICAgICAgPSBwU3RyZWFtOwogICAgSUFWSVN0cmVhbV9BZGRSZWYocFN0cmVhbSk7CiAgfQoKICByZXR1cm4gKFBHRVRGUkFNRSlwZzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElHZXRGcmFtZV9mblF1ZXJ5SW50ZXJmYWNlKElHZXRGcmFtZSAqaWZhY2UsCgkJCQkJCSBSRUZJSUQgcmVmaWlkLCBMUFZPSUQgKm9iaikKewogIElDT01fVEhJUyhJR2V0RnJhbWVJbXBsLGlmYWNlKTsKCiAgVFJBQ0UoIiglcCwlcywlcClcbiIsIFRoaXMsIGRlYnVnc3RyX2d1aWQocmVmaWlkKSwgb2JqKTsKCiAgaWYgKElzRXF1YWxHVUlEKCZJSURfSVVua25vd24sIHJlZmlpZCkgfHwKICAgICAgSXNFcXVhbEdVSUQoJklJRF9JR2V0RnJhbWUsIHJlZmlpZCkpIHsKICAgICpvYmogPSBpZmFjZTsKICAgIHJldHVybiBTX09LOwogIH0KCiAgcmV0dXJuIE9MRV9FX0VOVU1fTk9NT1JFOwp9CgpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSUdldEZyYW1lX2ZuQWRkUmVmKElHZXRGcmFtZSAqaWZhY2UpCnsKICBJQ09NX1RISVMoSUdldEZyYW1lSW1wbCxpZmFjZSk7CgogIFRSQUNFKCIoJXApXG4iLCBpZmFjZSk7CgogIHJldHVybiArKyhUaGlzLT5yZWYpOwp9CgpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSUdldEZyYW1lX2ZuUmVsZWFzZShJR2V0RnJhbWUgKmlmYWNlKQp7CiAgSUNPTV9USElTKElHZXRGcmFtZUltcGwsaWZhY2UpOwoKICBUUkFDRSgiKCVwKVxuIiwgaWZhY2UpOwoKICBpZiAoIS0tKFRoaXMtPnJlZikpIHsKICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgaWYgKFRoaXMtPnBTdHJlYW0gIT0gTlVMTCkgewogICAgICBJQVZJU3RyZWFtX1JlbGVhc2UoVGhpcy0+cFN0cmVhbSk7CiAgICAgIFRoaXMtPnBTdHJlYW0gPSBOVUxMOwogICAgfQoKICAgIExvY2FsRnJlZSgoSExPQ0FMKWlmYWNlKTsKICAgIHJldHVybiAwOwogIH0KCiAgcmV0dXJuIFRoaXMtPnJlZjsKfQoKc3RhdGljIExQVk9JRCAgV0lOQVBJIElHZXRGcmFtZV9mbkdldEZyYW1lKElHZXRGcmFtZSAqaWZhY2UsIExPTkcgbFBvcykKewogIElDT01fVEhJUyhJR2V0RnJhbWVJbXBsLGlmYWNlKTsKCiAgTE9ORyByZWFkQnl0ZXM7CiAgTE9ORyByZWFkU2FtcGxlczsKCiAgVFJBQ0UoIiglcCwlbGQpXG4iLCBpZmFjZSwgbFBvcyk7CgogIC8qIFdlIGRvbid0IHdhbnQgbmVnYXRpdmUgc3RhcnQgdmFsdWVzISAtLSBtYXJrcyBpbnZhbGlkIGJ1ZmZlciBjb250ZW50ICovCiAgaWYgKGxQb3MgPCAwKQogICAgcmV0dXJuIE5VTEw7CgogIC8qIGNoZWNrIHN0YXRlICovCiAgaWYgKFRoaXMtPnBTdHJlYW0gPT0gTlVMTCkKICAgIHJldHVybiBOVUxMOwogIGlmIChUaGlzLT5scEluRm9ybWF0ID09IE5VTEwpCiAgICByZXR1cm4gTlVMTDsKCiAgLyogQ291bGQgc3RyZWFtIGhhdmUgY2hhbmdlZD8gKi8KICBpZiAoISBUaGlzLT5iRml4ZWRTdHJlYW0pIHsKICAgIEFWSVNUUkVBTUlORk9XIHNJbmZvOwoKICAgIElBVklTdHJlYW1fSW5mbyhUaGlzLT5wU3RyZWFtLCAmc0luZm8sIHNpemVvZihzSW5mbykpOwoKICAgIGlmIChzSW5mby5kd0VkaXRDb3VudCAhPSBUaGlzLT5kd0VkaXRDb3VudCkgewogICAgICBUaGlzLT5kd0VkaXRDb3VudCAgID0gc0luZm8uZHdFZGl0Q291bnQ7CiAgICAgIFRoaXMtPmxDdXJyZW50RnJhbWUgPSAtMTsKICAgIH0KCiAgICBpZiAoc0luZm8uZHdGb3JtYXRDaGFuZ2VDb3VudCAhPSBUaGlzLT5kd0Zvcm1hdENoYW5nZUNvdW50KSB7CiAgICAgIC8qIHN0cmVhbSBoYXMgY2hhbmdlZCAqLwogICAgICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQgIT0gTlVMTCkgewoJQklUTUFQSU5GT0hFQURFUiBiaTsKCgltZW1jcHkoJmJpLCBUaGlzLT5scE91dEZvcm1hdCwgc2l6ZW9mKGJpKSk7CglBVklGSUxFX0Nsb3NlQ29tcHJlc3NvcihUaGlzKTsKCglpZiAoRkFJTEVEKElHZXRGcmFtZV9TZXRGb3JtYXQoaWZhY2UsICZiaSwgTlVMTCwgMCwgMCwgLTEsIC0xKSkpIHsKCSAgaWYgKEZBSUxFRChJR2V0RnJhbWVfU2V0Rm9ybWF0KGlmYWNlLCBOVUxMLCBOVUxMLCAwLCAwLCAtMSwgLTEpKSkKCSAgICByZXR1cm4gTlVMTDsKCX0KICAgICAgfSBlbHNlIGlmIChGQUlMRUQoSUdldEZyYW1lX1NldEZvcm1hdChpZmFjZSwgTlVMTCwgTlVMTCwgMCwgMCwgLTEsIC0xKSkpCglyZXR1cm4gTlVMTDsKICAgIH0KICB9CgogIGlmIChsUG9zICE9IFRoaXMtPmxDdXJyZW50RnJhbWUpIHsKICAgIExPTkcgbE5leHQgPSBJQVZJU3RyZWFtX0ZpbmRTYW1wbGUoVGhpcy0+cFN0cmVhbSxsUG9zLEZJTkRfS0VZfEZJTkRfUFJFVik7CgogICAgaWYgKGxOZXh0ID09IC0xKQogICAgICByZXR1cm4gTlVMTDsgLyogZnJhbWUgZG9lc24ndCBleGlzdCAqLwogICAgaWYgKGxOZXh0IDw9IFRoaXMtPmxDdXJyZW50RnJhbWUgJiYgVGhpcy0+bEN1cnJlbnRGcmFtZSA8IGxQb3MpCiAgICAgIGxOZXh0ID0gVGhpcy0+bEN1cnJlbnRGcmFtZSArIDE7CgogICAgZm9yICg7IGxOZXh0IDw9IGxQb3M7IGxOZXh0KyspIHsKICAgICAgLyogbmV3IGZvcm1hdCBmb3IgdGhpcyBmcmFtZT8gKi8KICAgICAgaWYgKFRoaXMtPmJGb3JtYXRDaGFuZ2VzKSB7CglJQVZJU3RyZWFtX1JlYWRGb3JtYXQoVGhpcy0+cFN0cmVhbSwgbE5leHQsCgkJCSAgICAgIFRoaXMtPmxwSW5Gb3JtYXQsICZUaGlzLT5jYkluRm9ybWF0KTsKCWlmIChUaGlzLT5scE91dEZvcm1hdCAhPSBOVUxMKSB7CgkgIGlmIChUaGlzLT5scE91dEZvcm1hdC0+YmlCaXRDb3VudCA8PSA4KQoJICAgIElDRGVjb21wcmVzc0dldFBhbGV0dGUoVGhpcy0+aGljLCBUaGlzLT5scEluRm9ybWF0LAoJCQkJICAgVGhpcy0+bHBPdXRGb3JtYXQpOwoJfQogICAgICB9CgogICAgICAvKiByZWFkIGlucHV0IGZyYW1lICovCiAgICAgIHdoaWxlIChGQUlMRUQoQVZJU3RyZWFtUmVhZChUaGlzLT5wU3RyZWFtLCBsTmV4dCwgMSwgVGhpcy0+bHBJbkJ1ZmZlciwKCQkJCSAgVGhpcy0+Y2JJbkJ1ZmZlciwgJnJlYWRCeXRlcywgJnJlYWRTYW1wbGVzKSkpIHsKCS8qIG5vdCBlbm91Z2ggbWVtb3J5IGZvciBpbnB1dCBidWZmZXI/ICovCglyZWFkQnl0ZXMgPSAwOwoJaWYgKEZBSUxFRChBVklTdHJlYW1TYW1wbGVTaXplKFRoaXMtPnBTdHJlYW0sIGxOZXh0LCAmcmVhZEJ5dGVzKSkpCgkgIHJldHVybiBOVUxMOyAvKiBiYWQgdGhpbmcsIGJ1dCBiYWQgdGhpbmdzIHdpbGwgaGFwcGVuICovCglpZiAocmVhZEJ5dGVzIDw9IDApIHsKCSAgRVJSKCI6IElBVklTdHJlYW06OlJFYWQgZG9lc24ndCByZXR1cm4gbmVlZGVkIGJ5dGVzIVxuIik7CgkgIHJldHVybiBOVUxMOwoJfQoKCS8qIElBVklTdHJlYW06OlJlYWQgZmFpbGVkIGJlY2F1c2Ugb2Ygb3RoZXIgcmVhc29ucyBub3QgYnVmZmVyc2l6ZT8gKi8KCWlmIChUaGlzLT5jYkluQnVmZmVyID49IHJlYWRCeXRlcykKCSAgYnJlYWs7CglUaGlzLT5jYkluQnVmZmVyID0gVGhpcy0+Y2JJbkZvcm1hdCArIHJlYWRCeXRlczsKCVRoaXMtPmxwSW5Gb3JtYXQgPSBHbG9iYWxSZUFsbG9jUHRyKFRoaXMtPmxwSW5Gb3JtYXQsIFRoaXMtPmNiSW5CdWZmZXIsIDApOwoJaWYgKFRoaXMtPmxwSW5Gb3JtYXQgPT0gTlVMTCkKCSAgcmV0dXJuIE5VTEw7IC8qIG91dCBvZiBtZW1vcnkgKi8KCVRoaXMtPmxwSW5CdWZmZXIgPSAoQllURSopVGhpcy0+bHBJbkZvcm1hdCArIFRoaXMtPmNiSW5Gb3JtYXQ7CiAgICAgIH0KCiAgICAgIGlmIChyZWFkU2FtcGxlcyAhPSAxKSB7CglFUlIoIjogbm8gZnJhbWVzIHJlYWRcbiIpOwoJcmV0dXJuIE5VTEw7CiAgICAgIH0KICAgICAgaWYgKHJlYWRCeXRlcyAhPSAwKSB7CglUaGlzLT5scEluRm9ybWF0LT5iaVNpemVJbWFnZSA9IHJlYWRCeXRlczsKCgkvKiBub3RoaW5nIHRvIGRlY29tcHJlc3M/ICovCglpZiAoVGhpcy0+aGljID09IE5VTEwpIHsKCSAgVGhpcy0+bEN1cnJlbnRGcmFtZSA9IGxQb3M7CgkgIHJldHVybiBUaGlzLT5scEluRm9ybWF0OwoJfQoKCWlmIChUaGlzLT5iUmVzaXplKSB7CgkgIElDRGVjb21wcmVzc0V4KFRoaXMtPmhpYywwLFRoaXMtPmxwSW5Gb3JtYXQsVGhpcy0+bHBJbkJ1ZmZlciwwLDAsCgkJCSBUaGlzLT5scEluRm9ybWF0LT5iaVdpZHRoLFRoaXMtPmxwSW5Gb3JtYXQtPmJpSGVpZ2h0LAoJCQkgVGhpcy0+bHBPdXRGb3JtYXQsVGhpcy0+bHBPdXRCdWZmZXIsVGhpcy0+eCxUaGlzLT55LAoJCQkgVGhpcy0+ZHgsVGhpcy0+ZHkpOwoJfSBlbHNlIHsKCSAgSUNEZWNvbXByZXNzKFRoaXMtPmhpYywgMCwgVGhpcy0+bHBJbkZvcm1hdCwgVGhpcy0+bHBJbkJ1ZmZlciwKCQkgICAgICAgVGhpcy0+bHBPdXRGb3JtYXQsIFRoaXMtPmxwT3V0QnVmZmVyKTsKCX0KICAgICAgfQogICAgfSAvKiBmb3IgKGxOZXh0IDwgbFBvcykgKi8KICB9IC8qIGlmIChUaGlzLT5sQ3VycmVudEZyYW1lICE9IGxQb3MpICovCgogIHJldHVybiAoVGhpcy0+aGljID09IE5VTEwgPyBUaGlzLT5scEluRm9ybWF0IDogVGhpcy0+bHBPdXRGb3JtYXQpOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUdldEZyYW1lX2ZuQmVnaW4oSUdldEZyYW1lICppZmFjZSwgTE9ORyBsU3RhcnQsCgkJCQkJTE9ORyBsRW5kLCBMT05HIGxSYXRlKQp7CiAgSUNPTV9USElTKElHZXRGcmFtZUltcGwsaWZhY2UpOwoKICBUUkFDRSgiKCVwLCVsZCwlbGQsJWxkKVxuIiwgaWZhY2UsIGxTdGFydCwgbEVuZCwgbFJhdGUpOwoKICBUaGlzLT5iRml4ZWRTdHJlYW0gPSBUUlVFOwoKICByZXR1cm4gKElHZXRGcmFtZV9HZXRGcmFtZShpZmFjZSwgbFN0YXJ0KSA/IEFWSUVSUl9PSyA6IEFWSUVSUl9FUlJPUik7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJR2V0RnJhbWVfZm5FbmQoSUdldEZyYW1lICppZmFjZSkKewogIElDT01fVEhJUyhJR2V0RnJhbWVJbXBsLGlmYWNlKTsKCiAgVFJBQ0UoIiglcClcbiIsIGlmYWNlKTsKCiAgVGhpcy0+YkZpeGVkU3RyZWFtID0gRkFMU0U7CgogIHJldHVybiBBVklFUlJfT0s7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJR2V0RnJhbWVfZm5TZXRGb3JtYXQoSUdldEZyYW1lICppZmFjZSwKCQkJCQkgICAgTFBCSVRNQVBJTkZPSEVBREVSIGxwYmlXYW50ZWQsCgkJCQkJICAgIExQVk9JRCBscEJpdHMsIElOVCB4LCBJTlQgeSwKCQkJCQkgICAgSU5UIGR4LCBJTlQgZHkpCnsKICBJQ09NX1RISVMoSUdldEZyYW1lSW1wbCxpZmFjZSk7CgogIEFWSVNUUkVBTUlORk9XICAgICBzSW5mbzsKICBMUEJJVE1BUElORk9IRUFERVIgbHBiaSAgICAgICAgID0gbHBiaVdhbnRlZDsKICBCT09MICAgICAgICAgICAgICAgYkJlc3REaXNwbGF5ID0gRkFMU0U7CgogIFRSQUNFKCIoJXAsJXAsJXAsJWQsJWQsJWQsJWQpXG4iLCBpZmFjZSwgbHBiaVdhbnRlZCwgbHBCaXRzLAoJeCwgeSwgZHgsIGR5KTsKCiAgaWYgKFRoaXMtPnBTdHJlYW0gPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfRVJST1I7CgogIGlmICgoTE9ORylscGJpV2FudGVkID09IEFWSUdFVEZSQU1FRl9CRVNURElTUExBWUZNVCkgewogICAgbHBiaSA9IE5VTEw7CiAgICBiQmVzdERpc3BsYXkgPSBUUlVFOwogIH0KCiAgSUFWSVN0cmVhbV9JbmZvKFRoaXMtPnBTdHJlYW0sICZzSW5mbywgc2l6ZW9mKHNJbmZvKSk7CiAgaWYgKHNJbmZvLmZjY1R5cGUgIT0gc3RyZWFtdHlwZVZJREVPKQogICAgcmV0dXJuIEFWSUVSUl9VTlNVUFBPUlRFRDsKCiAgVGhpcy0+YkZvcm1hdENoYW5nZXMgPQogICAgKHNJbmZvLmR3RmxhZ3MgJiBBVklTVFJFQU1JTkZPX0ZPUk1BVENIQU5HRVMgPyBUUlVFIDogRkFMU0UgKTsKICBUaGlzLT5kd0Zvcm1hdENoYW5nZUNvdW50ID0gc0luZm8uZHdGb3JtYXRDaGFuZ2VDb3VudDsKICBUaGlzLT5kd0VkaXRDb3VudCAgICAgICAgID0gc0luZm8uZHdFZGl0Q291bnQ7CiAgVGhpcy0+bEN1cnJlbnRGcmFtZSAgICAgICA9IC0xOwoKICAvKiBnZXQgaW5wdXQgZm9ybWF0IGZyb20gc3RyZWFtICovCiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQgPT0gTlVMTCkgewogICAgSFJFU1VMVCBocjsKCiAgICBUaGlzLT5jYkluQnVmZmVyID0gKExPTkcpc0luZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplOwogICAgaWYgKFRoaXMtPmNiSW5CdWZmZXIgPT0gMCkKICAgICAgVGhpcy0+Y2JJbkJ1ZmZlciA9IDEwMjQ7CgogICAgSUFWSVN0cmVhbV9SZWFkRm9ybWF0KFRoaXMtPnBTdHJlYW0sIHNJbmZvLmR3U3RhcnQsCgkJCSAgTlVMTCwgJlRoaXMtPmNiSW5Gb3JtYXQpOwoKICAgIFRoaXMtPmxwSW5Gb3JtYXQgPQogICAgICAoTFBCSVRNQVBJTkZPSEVBREVSKUdsb2JhbEFsbG9jUHRyKEdITkQsIFRoaXMtPmNiSW5Gb3JtYXQgKyBUaGlzLT5jYkluQnVmZmVyKTsKICAgIGlmIChUaGlzLT5scEluRm9ybWF0ID09IE5VTEwpIHsKICAgICAgQVZJRklMRV9DbG9zZUNvbXByZXNzb3IoVGhpcyk7CiAgICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwogICAgfQoKICAgIGhyID0gSUFWSVN0cmVhbV9SZWFkRm9ybWF0KFRoaXMtPnBTdHJlYW0sIHNJbmZvLmR3U3RhcnQsIFRoaXMtPmxwSW5Gb3JtYXQsICZUaGlzLT5jYkluRm9ybWF0KTsKICAgIGlmIChGQUlMRUQoaHIpKSB7CiAgICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgICByZXR1cm4gaHI7CiAgICB9CgogICAgVGhpcy0+bHBJbkJ1ZmZlciA9ICgoTFBCWVRFKVRoaXMtPmxwSW5Gb3JtYXQpICsgVGhpcy0+Y2JJbkZvcm1hdDsKICB9CgogIC8qIGNoZWNrIGlucHV0IGZvcm1hdCAqLwogIGlmIChUaGlzLT5scEluRm9ybWF0LT5iaUNsclVzZWQgPT0gMCAmJiBUaGlzLT5scEluRm9ybWF0LT5iaUJpdENvdW50IDw9IDgpCiAgICBUaGlzLT5scEluRm9ybWF0LT5iaUNsclVzZWQgPSAxdSA8PCBUaGlzLT5scEluRm9ybWF0LT5iaUJpdENvdW50OwogIGlmIChUaGlzLT5scEluRm9ybWF0LT5iaVNpemVJbWFnZSA9PSAwICYmCiAgICAgIFRoaXMtPmxwSW5Gb3JtYXQtPmJpQ29tcHJlc3Npb24gPT0gQklfUkdCKSB7CiAgICBUaGlzLT5scEluRm9ybWF0LT5iaVNpemVJbWFnZSA9CiAgICAgIERJQldJRFRIQllURVMoKlRoaXMtPmxwSW5Gb3JtYXQpICogVGhpcy0+bHBJbkZvcm1hdC0+YmlIZWlnaHQ7CiAgfQoKICAvKiBvbmx5IHRvIHBhc3MgdGhyb3VnaD8gKi8KICBpZiAoVGhpcy0+bHBJbkZvcm1hdC0+YmlDb21wcmVzc2lvbiA9PSBCSV9SR0IgJiYgbHBCaXRzID09IE5VTEwpIHsKICAgIGlmIChscGJpID09IE5VTEwgfHwgCgkobHBiaS0+YmlDb21wcmVzc2lvbiA9PSBCSV9SR0IgJiYKCSBscGJpLT5iaVdpZHRoID09IFRoaXMtPmxwSW5Gb3JtYXQtPmJpV2lkdGggJiYKCSBscGJpLT5iaUhlaWdodCA9PSBUaGlzLT5scEluRm9ybWF0LT5iaUhlaWdodCAmJgoJIGxwYmktPmJpQml0Q291bnQgPT0gVGhpcy0+bHBJbkZvcm1hdC0+YmlCaXRDb3VudCkpIHsKICAgICAgVGhpcy0+bHBPdXRGb3JtYXQgPSBUaGlzLT5scEluRm9ybWF0OwogICAgICBUaGlzLT5scE91dEJ1ZmZlciA9IERJQlBUUihUaGlzLT5scEluRm9ybWF0KTsKICAgICAgcmV0dXJuIEFWSUVSUl9PSzsKICAgIH0KICB9CgogIC8qIG5lZWQgbWVtb3J5IGZvciBvdXRwdXQgZm9ybWF0PyAqLwogIGlmIChUaGlzLT5scE91dEZvcm1hdCA9PSBOVUxMKSB7CiAgICBUaGlzLT5scE91dEZvcm1hdCA9CiAgICAgIChMUEJJVE1BUElORk9IRUFERVIpR2xvYmFsQWxsb2NQdHIoR0hORCwgc2l6ZW9mKEJJVE1BUElORk9IRUFERVIpCgkJCQkJICsgMjU2ICogc2l6ZW9mKFJHQlFVQUQpKTsKICAgIGlmIChUaGlzLT5scE91dEZvcm1hdCA9PSBOVUxMKSB7CiAgICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgIH0KICB9CgogIC8qIG5lZWQgaGFuZGxlIHRvIHZpZGVvIGNvbXByZXNzb3IgKi8KICBpZiAoVGhpcy0+aGljID09IE5VTEwpIHsKICAgIEZPVVJDQyBmY2NIYW5kbGVyOwoKICAgIGlmIChUaGlzLT5scEluRm9ybWF0LT5iaUNvbXByZXNzaW9uID09IEJJX1JHQikKICAgICAgZmNjSGFuZGxlciA9IGNvbXB0eXBlRElCOwogICAgZWxzZSBpZiAoVGhpcy0+bHBJbkZvcm1hdC0+YmlDb21wcmVzc2lvbiA9PSBCSV9STEU4KQogICAgICBmY2NIYW5kbGVyID0gbW1pb0ZPVVJDQygnUicsJ0wnLCdFJywnICcpOwogICAgZWxzZQogICAgICBmY2NIYW5kbGVyID0gc0luZm8uZmNjSGFuZGxlcjsKCiAgICBpZiAobHBiaSAhPSBOVUxMKSB7CiAgICAgIGlmIChscGJpLT5iaVdpZHRoID09IDApCglscGJpLT5iaVdpZHRoID0gVGhpcy0+bHBJbkZvcm1hdC0+YmlXaWR0aDsKICAgICAgaWYgKGxwYmktPmJpSGVpZ2h0ID09IDApCglscGJpLT5iaUhlaWdodCA9IFRoaXMtPmxwSW5Gb3JtYXQtPmJpSGVpZ2h0OwogICAgfQoKICAgIFRoaXMtPmhpYyA9IElDTG9jYXRlKElDVFlQRV9WSURFTywgZmNjSGFuZGxlciwgVGhpcy0+bHBJbkZvcm1hdCwgbHBiaSwgSUNNT0RFX0RFQ09NUFJFU1MpOwogICAgaWYgKFRoaXMtPmhpYyA9PSBOVUxMKSB7CiAgICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgICByZXR1cm4gQVZJRVJSX05PQ09NUFJFU1NPUjsKICAgIH0KICB9CgogIC8qIG91dHB1dCBmb3JtYXQgZ2l2ZW4/ICovCiAgaWYgKGxwYmkgIT0gTlVMTCkgewogICAgLyogY2hlY2sgdGhlIGdpdmVuIG91dHB1dCBmb3JtYXQgLi4uICovCiAgICBpZiAobHBiaS0+YmlDbHJVc2VkID09IDAgJiYgbHBiaS0+YmlCaXRDb3VudCA8PSA4KQogICAgICBscGJpLT5iaUNsclVzZWQgPSAxdSA8PCBscGJpLT5iaUJpdENvdW50OwoKICAgIC8qIC4uLiBhbmQgcmVtZW1iZXIgaXQgKi8KICAgIG1lbWNweShUaGlzLT5scE91dEZvcm1hdCwgbHBiaSwKCSAgIGxwYmktPmJpU2l6ZSArIGxwYmktPmJpQ2xyVXNlZCAqIHNpemVvZihSR0JRVUFEKSk7CiAgICBpZiAobHBiaS0+YmlCaXRDb3VudCA8PSA4KQogICAgICBJQ0RlY29tcHJlc3NHZXRQYWxldHRlKFRoaXMtPmhpYywgVGhpcy0+bHBJbkZvcm1hdCwgVGhpcy0+bHBPdXRGb3JtYXQpOwoKICAgIHJldHVybiBBVklFUlJfT0s7CiAgfSBlbHNlIHsKICAgIGlmIChiQmVzdERpc3BsYXkpIHsKICAgICAgSUNHZXREaXNwbGF5Rm9ybWF0KFRoaXMtPmhpYywgVGhpcy0+bHBJbkZvcm1hdCwKCQkJIFRoaXMtPmxwT3V0Rm9ybWF0LCAwLCBkeCwgZHkpOwogICAgfSBlbHNlIGlmIChJQ0RlY29tcHJlc3NHZXRGb3JtYXQoVGhpcy0+aGljLCBUaGlzLT5scEluRm9ybWF0LAoJCQkJICAgICBUaGlzLT5scE91dEZvcm1hdCkgPCAwKSB7CiAgICAgIEFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwogICAgICByZXR1cm4gQVZJRVJSX05PQ09NUFJFU1NPUjsKICAgIH0KCiAgICAvKiBjaGVjayBvdXRwdXQgZm9ybWF0ICovCiAgICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQtPmJpQ2xyVXNlZCA9PSAwICYmCglUaGlzLT5scE91dEZvcm1hdC0+YmlCaXRDb3VudCA8PSA4KQogICAgICBUaGlzLT5scE91dEZvcm1hdC0+YmlDbHJVc2VkID0gMXUgPDwgVGhpcy0+bHBPdXRGb3JtYXQtPmJpQml0Q291bnQ7CiAgICBpZiAoVGhpcy0+bHBPdXRGb3JtYXQtPmJpU2l6ZUltYWdlID09IDAgJiYKCVRoaXMtPmxwT3V0Rm9ybWF0LT5iaUNvbXByZXNzaW9uID09IEJJX1JHQikgewogICAgICBUaGlzLT5scE91dEZvcm1hdC0+YmlTaXplSW1hZ2UgPQoJRElCV0lEVEhCWVRFUygqVGhpcy0+bHBPdXRGb3JtYXQpICogVGhpcy0+bHBPdXRGb3JtYXQtPmJpSGVpZ2h0OwogICAgfQoKICAgIGlmIChscEJpdHMgPT0gTlVMTCkgewogICAgICByZWdpc3RlciBEV09SRCBzaXplID0gVGhpcy0+bHBPdXRGb3JtYXQtPmJpQ2xyVXNlZCAqIHNpemVvZihSR0JRVUFEKTsKCiAgICAgIHNpemUgKz0gVGhpcy0+bHBPdXRGb3JtYXQtPmJpU2l6ZSArIFRoaXMtPmxwT3V0Rm9ybWF0LT5iaVNpemVJbWFnZTsKICAgICAgVGhpcy0+bHBPdXRGb3JtYXQgPQoJKExQQklUTUFQSU5GT0hFQURFUilHbG9iYWxSZUFsbG9jUHRyKFRoaXMtPmxwT3V0Rm9ybWF0LCBzaXplLCBHTUVNX01PVkVBQkxFKTsKICAgICAgaWYgKFRoaXMtPmxwT3V0Rm9ybWF0ID09IE5VTEwpIHsKCUFWSUZJTEVfQ2xvc2VDb21wcmVzc29yKFRoaXMpOwoJcmV0dXJuIEFWSUVSUl9NRU1PUlk7CiAgICAgIH0KICAgICAgVGhpcy0+bHBPdXRCdWZmZXIgPSBESUJQVFIoVGhpcy0+bHBPdXRGb3JtYXQpOwogICAgfSBlbHNlCiAgICAgIFRoaXMtPmxwT3V0QnVmZmVyID0gbHBCaXRzOwoKICAgIC8qIGZvciB1c2VyIHNpemUgd2FzIGlycmVsZXZhbnQgKi8KICAgIGlmIChkeCA9PSAtMSkKICAgICAgZHggPSBUaGlzLT5scE91dEZvcm1hdC0+YmlXaWR0aDsKICAgIGlmIChkeSA9PSAtMSkKICAgICAgZHkgPSBUaGlzLT5scE91dEZvcm1hdC0+YmlIZWlnaHQ7CgogICAgLyogbmVlZCB0byByZXNpemU/ICovCiAgICBpZiAoeCAhPSAwIHx8IHkgIT0gMCkgewogICAgICBpZiAoZHkgPT0gVGhpcy0+bHBPdXRGb3JtYXQtPmJpSGVpZ2h0ICYmCgkgIGR4ID09IFRoaXMtPmxwT3V0Rm9ybWF0LT5iaVdpZHRoKQoJVGhpcy0+YlJlc2l6ZSA9IEZBTFNFOwogICAgICBlbHNlCglUaGlzLT5iUmVzaXplID0gVFJVRTsKICAgIH0KCiAgICBpZiAoVGhpcy0+YlJlc2l6ZSkgewogICAgICBUaGlzLT54ICA9IHg7CiAgICAgIFRoaXMtPnkgID0geTsKICAgICAgVGhpcy0+ZHggPSBkeDsKICAgICAgVGhpcy0+ZHkgPSBkeTsKCiAgICAgIGlmIChJQ0RlY29tcHJlc3NFeEJlZ2luKFRoaXMtPmhpYywwLFRoaXMtPmxwSW5Gb3JtYXQsVGhpcy0+bHBJbkJ1ZmZlciwwLAoJCQkgICAgICAwLFRoaXMtPmxwSW5Gb3JtYXQtPmJpV2lkdGgsCgkJCSAgICAgIFRoaXMtPmxwSW5Gb3JtYXQtPmJpSGVpZ2h0LFRoaXMtPmxwT3V0Rm9ybWF0LAoJCQkgICAgICBUaGlzLT5scE91dEJ1ZmZlciwgeCwgeSwgZHgsIGR5KSA9PSBJQ0VSUl9PSykKCXJldHVybiBBVklFUlJfT0s7CiAgICB9IGVsc2UgaWYgKElDRGVjb21wcmVzc0JlZ2luKFRoaXMtPmhpYywgVGhpcy0+bHBJbkZvcm1hdCwKCQkJCSBUaGlzLT5scE91dEZvcm1hdCkgPT0gSUNFUlJfT0spCiAgICAgIHJldHVybiBBVklFUlJfT0s7CgogICAgQVZJRklMRV9DbG9zZUNvbXByZXNzb3IoVGhpcyk7CgogICAgcmV0dXJuIEFWSUVSUl9DT01QUkVTU09SOwogIH0KfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwo=