LyoKICogQ29weXJpZ2h0IDIwMDIgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojZGVmaW5lIENPTV9OT19XSU5ET1dTX0gKI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8c3RkYXJnLmg+CgojaW5jbHVkZSAid2luZGVmLmgiCiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5nZGkuaCIKI2luY2x1ZGUgIndpbnVzZXIuaCIKI2luY2x1ZGUgIndpbm5scy5oIgojaW5jbHVkZSAid2luZXJyb3IuaCIKI2luY2x1ZGUgIndpbmRvd3N4LmgiCiNpbmNsdWRlICJtbXN5c3RlbS5oIgojaW5jbHVkZSAidmZ3LmgiCiNpbmNsdWRlICJtc2FjbS5oIgoKI2luY2x1ZGUgImF2aWZpbGVfcHJpdmF0ZS5oIgoKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKGF2aWZpbGUpOwoKI2RlZmluZSBNQVhfRlJBTUVTSVpFICAgICAgICgxNiAqIDEwMjQgKiAxMDI0KQojZGVmaW5lIE1BWF9GUkFNRVNJWkVfRElGRiAgNTEyCgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNNU3RyZWFtX2ZuUXVlcnlJbnRlcmZhY2UoSUFWSVN0cmVhbSppZmFjZSxSRUZJSUQgcmVmaWlkLExQVk9JRCAqb2JqKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIElDTVN0cmVhbV9mbkFkZFJlZihJQVZJU3RyZWFtKmlmYWNlKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIElDTVN0cmVhbV9mblJlbGVhc2UoSUFWSVN0cmVhbSogaWZhY2UpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNNU3RyZWFtX2ZuQ3JlYXRlKElBVklTdHJlYW0qaWZhY2UsTFBBUkFNIGxQYXJhbTEsTFBBUkFNIGxQYXJhbTIpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNNU3RyZWFtX2ZuSW5mbyhJQVZJU3RyZWFtKmlmYWNlLEFWSVNUUkVBTUlORk9XICpwc2ksTE9ORyBzaXplKTsKc3RhdGljIExPTkcgICAgV0lOQVBJIElDTVN0cmVhbV9mbkZpbmRTYW1wbGUoSUFWSVN0cmVhbSppZmFjZSxMT05HIHBvcyxMT05HIGZsYWdzKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDTVN0cmVhbV9mblJlYWRGb3JtYXQoSUFWSVN0cmVhbSppZmFjZSxMT05HIHBvcyxMUFZPSUQgZm9ybWF0LExPTkcgKmZvcm1hdHNpemUpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNNU3RyZWFtX2ZuU2V0Rm9ybWF0KElBVklTdHJlYW0qaWZhY2UsTE9ORyBwb3MsTFBWT0lEIGZvcm1hdCxMT05HIGZvcm1hdHNpemUpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNNU3RyZWFtX2ZuUmVhZChJQVZJU3RyZWFtKmlmYWNlLExPTkcgc3RhcnQsTE9ORyBzYW1wbGVzLExQVk9JRCBidWZmZXIsTE9ORyBidWZmZXJzaXplLExPTkcgKmJ5dGVzcmVhZCxMT05HICpzYW1wbGVzcmVhZCk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ01TdHJlYW1fZm5Xcml0ZShJQVZJU3RyZWFtKmlmYWNlLExPTkcgc3RhcnQsTE9ORyBzYW1wbGVzLExQVk9JRCBidWZmZXIsTE9ORyBidWZmZXJzaXplLERXT1JEIGZsYWdzLExPTkcgKnNhbXB3cml0dGVuLExPTkcgKmJ5dGVzd3JpdHRlbik7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ01TdHJlYW1fZm5EZWxldGUoSUFWSVN0cmVhbSppZmFjZSxMT05HIHN0YXJ0LExPTkcgc2FtcGxlcyk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ01TdHJlYW1fZm5SZWFkRGF0YShJQVZJU3RyZWFtKmlmYWNlLERXT1JEIGZjYyxMUFZPSUQgbHAsTE9ORyAqbHByZWFkKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDTVN0cmVhbV9mbldyaXRlRGF0YShJQVZJU3RyZWFtKmlmYWNlLERXT1JEIGZjYyxMUFZPSUQgbHAsTE9ORyBzaXplKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDTVN0cmVhbV9mblNldEluZm8oSUFWSVN0cmVhbSppZmFjZSxBVklTVFJFQU1JTkZPVyppbmZvLExPTkcgaW5mb2xlbik7CgpzdGF0aWMgY29uc3Qgc3RydWN0IElBVklTdHJlYW1WdGJsIGlpY21zdCA9IHsKICBJQ01TdHJlYW1fZm5RdWVyeUludGVyZmFjZSwKICBJQ01TdHJlYW1fZm5BZGRSZWYsCiAgSUNNU3RyZWFtX2ZuUmVsZWFzZSwKICBJQ01TdHJlYW1fZm5DcmVhdGUsCiAgSUNNU3RyZWFtX2ZuSW5mbywKICBJQ01TdHJlYW1fZm5GaW5kU2FtcGxlLAogIElDTVN0cmVhbV9mblJlYWRGb3JtYXQsCiAgSUNNU3RyZWFtX2ZuU2V0Rm9ybWF0LAogIElDTVN0cmVhbV9mblJlYWQsCiAgSUNNU3RyZWFtX2ZuV3JpdGUsCiAgSUNNU3RyZWFtX2ZuRGVsZXRlLAogIElDTVN0cmVhbV9mblJlYWREYXRhLAogIElDTVN0cmVhbV9mbldyaXRlRGF0YSwKICBJQ01TdHJlYW1fZm5TZXRJbmZvCn07Cgp0eXBlZGVmIHN0cnVjdCBfSUFWSVN0cmVhbUltcGwgewogIC8qIElVbmtub3duIHN0dWZmICovCiAgY29uc3QgSUFWSVN0cmVhbVZ0YmwgKmxwVnRibDsKICBMT05HCQkgICAgIHJlZjsKCiAgLyogSUFWSVN0cmVhbSBzdHVmZiAqLwogIFBBVklTVFJFQU0gICAgICAgICBwU3RyZWFtOwogIEFWSVNUUkVBTUlORk9XICAgICBzSW5mbzsKCiAgUEdFVEZSQU1FICAgICAgICAgIHBnOwogIEhJQyAgICAgICAgICAgICAgICBoaWM7CiAgRFdPUkQgICAgICAgICAgICAgIGR3SUNNRmxhZ3M7CgogIExPTkcgICAgICAgICAgICAgICBsQ3VycmVudDsKICBMT05HICAgICAgICAgICAgICAgbExhc3RLZXk7CiAgTE9ORyAgICAgICAgICAgICAgIGxLZXlGcmFtZUV2ZXJ5OwogIERXT1JEICAgICAgICAgICAgICBkd0xhc3RRdWFsaXR5OwogIERXT1JEICAgICAgICAgICAgICBkd0J5dGVzUGVyRnJhbWU7CiAgRFdPUkQgICAgICAgICAgICAgIGR3VW51c2VkQnl0ZXM7CgogIExQQklUTUFQSU5GT0hFQURFUiBscGJpQ3VyOyAgLyogY3VycmVudCBmcmFtZSAqLwogIExQVk9JRCAgICAgICAgICAgICBscEN1cjsKICBMUEJJVE1BUElORk9IRUFERVIgbHBiaVByZXY7IC8qIHByZXZpb3VzIGZyYW1lICovCiAgTFBWT0lEICAgICAgICAgICAgIGxwUHJldjsKCiAgTFBCSVRNQVBJTkZPSEVBREVSIGxwYmlPdXRwdXQ7IC8qIG91dHB1dCBmb3JtYXQgb2YgY29kZWMgKi8KICBMT05HICAgICAgICAgICAgICAgY2JPdXRwdXQ7CiAgTFBCSVRNQVBJTkZPSEVBREVSIGxwYmlJbnB1dDsgIC8qIGlucHV0IGZvcm1hdCBmb3IgY29kZWMgKi8KICBMT05HICAgICAgICAgICAgICAgY2JJbnB1dDsKfSBJQVZJU3RyZWFtSW1wbDsKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCnN0YXRpYyBIUkVTVUxUIEFWSUZJTEVfRW5jb2RlRnJhbWUoSUFWSVN0cmVhbUltcGwgKlRoaXMsCgkJCQkgICBMUEJJVE1BUElORk9IRUFERVIgbHBiaSwgTFBWT0lEIGxwQml0cyk7CnN0YXRpYyBIUkVTVUxUIEFWSUZJTEVfT3BlbkdldEZyYW1lKElBVklTdHJlYW1JbXBsICpUaGlzKTsKCnN0YXRpYyBpbmxpbmUgdm9pZCBBVklGSUxFX1Jlc2V0KElBVklTdHJlYW1JbXBsICpUaGlzKQp7CiAgVGhpcy0+bEN1cnJlbnQgICAgICA9IC0xOwogIFRoaXMtPmxMYXN0S2V5ICAgICAgPSAwOwogIFRoaXMtPmR3TGFzdFF1YWxpdHkgPSBJQ1FVQUxJVFlfSElHSDsKICBUaGlzLT5kd1VudXNlZEJ5dGVzID0gMDsKfQoKSFJFU1VMVCBBVklGSUxFX0NyZWF0ZUlDTVN0cmVhbShSRUZJSUQgcmlpZCwgTFBWT0lEICpwcHYpCnsKICBJQVZJU3RyZWFtSW1wbCAqcHN0cmVhbTsKICBIUkVTVUxUICAgICAgICAgaHI7CgogIGFzc2VydChyaWlkICE9IE5VTEwgJiYgcHB2ICE9IE5VTEwpOwoKICAqcHB2ID0gTlVMTDsKCiAgcHN0cmVhbSA9IChJQVZJU3RyZWFtSW1wbCopTG9jYWxBbGxvYyhMUFRSLCBzaXplb2YoSUFWSVN0cmVhbUltcGwpKTsKICBpZiAocHN0cmVhbSA9PSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9NRU1PUlk7CgogIHBzdHJlYW0tPmxwVnRibCAgPSAmaWljbXN0OwogIEFWSUZJTEVfUmVzZXQocHN0cmVhbSk7CgogIGhyID0gSUFWSVN0cmVhbV9RdWVyeUludGVyZmFjZSgoSUFWSVN0cmVhbSopcHN0cmVhbSwgcmlpZCwgcHB2KTsKICBpZiAoRkFJTEVEKGhyKSkKICAgIExvY2FsRnJlZSgoSExPQ0FMKXBzdHJlYW0pOwoKICByZXR1cm4gaHI7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ01TdHJlYW1fZm5RdWVyeUludGVyZmFjZShJQVZJU3RyZWFtICppZmFjZSwKCQkJCQkJICBSRUZJSUQgcmVmaWlkLCBMUFZPSUQgKm9iaikKewogIElBVklTdHJlYW1JbXBsICpUaGlzID0gKElBVklTdHJlYW1JbXBsICopaWZhY2U7CgogIFRSQUNFKCIoJXAsJXMsJXApXG4iLCBpZmFjZSwgZGVidWdzdHJfZ3VpZChyZWZpaWQpLCBvYmopOwoKICBpZiAoSXNFcXVhbEdVSUQoJklJRF9JVW5rbm93biwgcmVmaWlkKSB8fAogICAgICBJc0VxdWFsR1VJRCgmSUlEX0lBVklTdHJlYW0sIHJlZmlpZCkpIHsKICAgICpvYmogPSBUaGlzOwogICAgSUFWSVN0cmVhbV9BZGRSZWYoaWZhY2UpOwoKICAgIHJldHVybiBTX09LOwogIH0KCiAgcmV0dXJuIE9MRV9FX0VOVU1fTk9NT1JFOwp9CgpzdGF0aWMgVUxPTkcgV0lOQVBJIElDTVN0cmVhbV9mbkFkZFJlZihJQVZJU3RyZWFtICppZmFjZSkKewogIElBVklTdHJlYW1JbXBsICpUaGlzID0gKElBVklTdHJlYW1JbXBsICopaWZhY2U7CiAgVUxPTkcgcmVmID0gSW50ZXJsb2NrZWRJbmNyZW1lbnQoJlRoaXMtPnJlZik7CgogIFRSQUNFKCIoJXApIC0+ICVsZFxuIiwgaWZhY2UsIHJlZik7CgogIC8qIGFsc28gYWRkIHJlZmVyZW5jZSB0byB0aGUgbmVzdGVkIHN0cmVhbSAqLwogIGlmIChUaGlzLT5wU3RyZWFtICE9IE5VTEwpCiAgICBJQVZJU3RyZWFtX0FkZFJlZihUaGlzLT5wU3RyZWFtKTsKCiAgcmV0dXJuIHJlZjsKfQoKc3RhdGljIFVMT05HIFdJTkFQSSBJQ01TdHJlYW1fZm5SZWxlYXNlKElBVklTdHJlYW0qIGlmYWNlKQp7CiAgSUFWSVN0cmVhbUltcGwgKlRoaXMgPSAoSUFWSVN0cmVhbUltcGwgKilpZmFjZTsKICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZERlY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgVFJBQ0UoIiglcCkgLT4gJWxkXG4iLCBpZmFjZSwgcmVmKTsKCiAgaWYgKHJlZiA9PSAwKSB7CiAgICAvKiBkZXN0cnVjdCAqLwogICAgaWYgKFRoaXMtPnBnICE9IE5VTEwpIHsKICAgICAgQVZJU3RyZWFtR2V0RnJhbWVDbG9zZShUaGlzLT5wZyk7CiAgICAgIFRoaXMtPnBnID0gTlVMTDsKICAgIH0KICAgIGlmIChUaGlzLT5wU3RyZWFtICE9IE5VTEwpIHsKICAgICAgSUFWSVN0cmVhbV9SZWxlYXNlKFRoaXMtPnBTdHJlYW0pOwogICAgICBUaGlzLT5wU3RyZWFtID0gTlVMTDsKICAgIH0KICAgIGlmIChUaGlzLT5oaWMgIT0gTlVMTCkgewogICAgICBpZiAoVGhpcy0+bHBiaVByZXYgIT0gTlVMTCkgewoJSUNEZWNvbXByZXNzRW5kKFRoaXMtPmhpYyk7CglHbG9iYWxGcmVlUHRyKFRoaXMtPmxwYmlQcmV2KTsKCVRoaXMtPmxwYmlQcmV2ID0gTlVMTDsKCVRoaXMtPmxwUHJldiAgID0gTlVMTDsKICAgICAgfQogICAgICBJQ0NvbXByZXNzRW5kKFRoaXMtPmhpYyk7CiAgICAgIFRoaXMtPmhpYyA9IE5VTEw7CiAgICB9CiAgICBpZiAoVGhpcy0+bHBiaUN1ciAhPSBOVUxMKSB7CiAgICAgIEdsb2JhbEZyZWVQdHIoVGhpcy0+bHBiaUN1cik7CiAgICAgIFRoaXMtPmxwYmlDdXIgPSBOVUxMOwogICAgICBUaGlzLT5scEN1ciAgID0gTlVMTDsKICAgIH0KICAgIGlmIChUaGlzLT5scGJpT3V0cHV0ICE9IE5VTEwpIHsKICAgICAgR2xvYmFsRnJlZVB0cihUaGlzLT5scGJpT3V0cHV0KTsKICAgICAgVGhpcy0+bHBiaU91dHB1dCA9IE5VTEw7CiAgICAgIFRoaXMtPmNiT3V0cHV0ICAgPSAwOwogICAgfQogICAgaWYgKFRoaXMtPmxwYmlJbnB1dCAhPSBOVUxMKSB7CiAgICAgIEdsb2JhbEZyZWVQdHIoVGhpcy0+bHBiaUlucHV0KTsKICAgICAgVGhpcy0+bHBiaUlucHV0ID0gTlVMTDsKICAgICAgVGhpcy0+Y2JJbnB1dCAgID0gMDsKICAgIH0KCiAgICBMb2NhbEZyZWUoKEhMT0NBTClUaGlzKTsKCiAgICByZXR1cm4gMDsKICB9CgogIC8qIGFsc28gcmVsZWFzZSByZWZlcmVuY2UgdG8gdGhlIG5lc3RlZCBzdHJlYW0gKi8KICBpZiAoVGhpcy0+cFN0cmVhbSAhPSBOVUxMKQogICAgSUFWSVN0cmVhbV9SZWxlYXNlKFRoaXMtPnBTdHJlYW0pOwoKICByZXR1cm4gcmVmOwp9CgovKiBsUGFyYW0xOiBQQVZJU1RSRUFNCiAqIGxQYXJhbTI6IExQQVZJQ09NUFJFU1NPUFRJT05TCiAqLwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNNU3RyZWFtX2ZuQ3JlYXRlKElBVklTdHJlYW0gKmlmYWNlLCBMUEFSQU0gbFBhcmFtMSwKCQkJCQkgIExQQVJBTSBsUGFyYW0yKQp7CiAgSUFWSVN0cmVhbUltcGwgKlRoaXMgPSAoSUFWSVN0cmVhbUltcGwgKilpZmFjZTsKCiAgSUNJTkZPICAgICAgICAgICAgICAgaWNpbmZvOwogIElDQ09NUFJFU1NGUkFNRVMgICAgIGljRnJhbWVzOwogIExQQVZJQ09NUFJFU1NPUFRJT05TIHBjbyA9IChMUEFWSUNPTVBSRVNTT1BUSU9OUylsUGFyYW0yOwoKICBUUkFDRSgiKCVwLDB4JTA4bFgsMHglMDhsWClcbiIsIGlmYWNlLCBsUGFyYW0xLCBsUGFyYW0yKTsKCiAgLyogY2hlY2sgcGFyYW1ldGVyICovCiAgaWYgKChMUFZPSUQpbFBhcmFtMSA9PSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9CQURQQVJBTTsKCiAgLyogZ2V0IGluZm9zIGZyb20gc3RyZWFtICovCiAgSUFWSVN0cmVhbV9JbmZvKChQQVZJU1RSRUFNKWxQYXJhbTEsICZUaGlzLT5zSW5mbywgc2l6ZW9mKFRoaXMtPnNJbmZvKSk7CiAgaWYgKFRoaXMtPnNJbmZvLmZjY1R5cGUgIT0gc3RyZWFtdHlwZVZJREVPKQogICAgcmV0dXJuIEFWSUVSUl9FUlJPUjsgLyogZXJyb3IgaW4gcmVnaXN0cnkgb3IgQVZJTWFrZUNvbXByZXNzZWRTdHJlYW0gKi8KCiAgLyogYWRkIHJlZmVyZW5jZSB0byB0aGUgc3RyZWFtICovCiAgVGhpcy0+cFN0cmVhbSA9IChQQVZJU1RSRUFNKWxQYXJhbTE7CiAgSUFWSVN0cmVhbV9BZGRSZWYoVGhpcy0+cFN0cmVhbSk7CgogIEFWSUZJTEVfUmVzZXQoVGhpcyk7CgogIGlmIChwY28gIT0gTlVMTCAmJiBwY28tPmZjY0hhbmRsZXIgIT0gY29tcHR5cGVESUIpIHsKICAgIC8qIHdlIHNob3VsZCBjb21wcmVzcyAqLwogICAgVGhpcy0+c0luZm8uZmNjSGFuZGxlciA9IHBjby0+ZmNjSGFuZGxlcjsKCiAgICBUaGlzLT5oaWMgPSBJQ09wZW4oSUNUWVBFX1ZJREVPLCBwY28tPmZjY0hhbmRsZXIsIElDTU9ERV9DT01QUkVTUyk7CiAgICBpZiAoVGhpcy0+aGljID09IE5VTEwpCiAgICAgIHJldHVybiBBVklFUlJfTk9DT01QUkVTU09SOwoKICAgIC8qIHJlc3RvcmUgc2F2ZWQgc3RhdGUgb2YgY29kZWMgKi8KICAgIGlmIChwY28tPmNiUGFybXMgPiAwICYmIHBjby0+bHBQYXJtcyAhPSBOVUxMKSB7CiAgICAgIElDU2V0U3RhdGUoVGhpcy0+aGljLCBwY28tPmxwUGFybXMsIHBjby0+Y2JQYXJtcyk7CiAgICB9CgogICAgLyogc2V0IHF1YWxpdHkgLS0gcmVzb2x2ZSBkZWZhdWx0IHF1YWxpdHkgKi8KICAgIFRoaXMtPnNJbmZvLmR3UXVhbGl0eSA9IHBjby0+ZHdRdWFsaXR5OwogICAgaWYgKHBjby0+ZHdRdWFsaXR5ID09IElDUVVBTElUWV9ERUZBVUxUKQogICAgICBUaGlzLT5zSW5mby5kd1F1YWxpdHkgPSBJQ0dldERlZmF1bHRRdWFsaXR5KFRoaXMtPmhpYyk7CgogICAgLyogZ2V0IGNhcGFiaWxpdGllcyBvZiBjb2RlYyAqLwogICAgSUNHZXRJbmZvKFRoaXMtPmhpYywgJmljaW5mbywgc2l6ZW9mKGljaW5mbykpOwogICAgVGhpcy0+ZHdJQ01GbGFncyA9IGljaW5mby5kd0ZsYWdzOwoKICAgIC8qIHVzZSBrZXlmcmFtZXM/ICovCiAgICBpZiAoKHBjby0+ZHdGbGFncyAmIEFWSUNPTVBSRVNTRl9LRVlGUkFNRVMpICYmCgkoaWNpbmZvLmR3RmxhZ3MgJiAoVklEQ0ZfVEVNUE9SQUx8VklEQ0ZfRkFTVFRFTVBPUkFMQykpKSB7CiAgICAgIFRoaXMtPmxLZXlGcmFtZUV2ZXJ5ID0gcGNvLT5kd0tleUZyYW1lRXZlcnk7CiAgICB9IGVsc2UKICAgICAgVGhpcy0+bEtleUZyYW1lRXZlcnkgPSAxOwoKICAgIC8qIHVzZSBkYXRhcmF0ZT8gKi8KICAgIGlmICgocGNvLT5kd0ZsYWdzICYgQVZJQ09NUFJFU1NGX0RBVEFSQVRFKSkgewogICAgICAvKiBEbyB3ZSBoYXZlIGEgY2hhbmNlIHRvIHJlZHVjZSBzaXplIHRvIGRlc2lyZWQgb25lPyAqLwogICAgICBpZiAoKGljaW5mby5kd0ZsYWdzICYgKFZJRENGX0NSVU5DSHxWSURDRl9RVUFMSVRZKSkgPT0gMCkKCXJldHVybiBBVklFUlJfTk9DT01QUkVTU09SOwoKICAgICAgYXNzZXJ0KFRoaXMtPnNJbmZvLmR3UmF0ZSAhPSAwKTsKCiAgICAgIFRoaXMtPmR3Qnl0ZXNQZXJGcmFtZSA9IE11bERpdihwY28tPmR3Qnl0ZXNQZXJTZWNvbmQsCgkJCQkgICAgIFRoaXMtPnNJbmZvLmR3U2NhbGUsIFRoaXMtPnNJbmZvLmR3UmF0ZSk7CiAgICB9IGVsc2UgewogICAgICBwY28tPmR3Qnl0ZXNQZXJTZWNvbmQgPSAwOwogICAgICBUaGlzLT5kd0J5dGVzUGVyRnJhbWUgPSAwOwogICAgfQoKICAgIGlmIChpY2luZm8uZHdGbGFncyAmIFZJRENGX0NPTVBSRVNTRlJBTUVTKSB7CiAgICAgIG1lbXNldCgmaWNGcmFtZXMsIDAsIHNpemVvZihpY0ZyYW1lcykpOwogICAgICBpY0ZyYW1lcy5scGJpT3V0cHV0ICA9IFRoaXMtPmxwYmlPdXRwdXQ7CiAgICAgIGljRnJhbWVzLmxwYmlJbnB1dCAgID0gVGhpcy0+bHBiaUlucHV0OwogICAgICBpY0ZyYW1lcy5sRnJhbWVDb3VudCA9IFRoaXMtPnNJbmZvLmR3TGVuZ3RoOwogICAgICBpY0ZyYW1lcy5sUXVhbGl0eSAgICA9IFRoaXMtPnNJbmZvLmR3UXVhbGl0eTsKICAgICAgaWNGcmFtZXMubERhdGFSYXRlICAgPSBwY28tPmR3Qnl0ZXNQZXJTZWNvbmQ7CiAgICAgIGljRnJhbWVzLmxLZXlSYXRlICAgID0gVGhpcy0+bEtleUZyYW1lRXZlcnk7CiAgICAgIGljRnJhbWVzLmR3UmF0ZSAgICAgID0gVGhpcy0+c0luZm8uZHdSYXRlOwogICAgICBpY0ZyYW1lcy5kd1NjYWxlICAgICA9IFRoaXMtPnNJbmZvLmR3U2NhbGU7CiAgICAgIElDU2VuZE1lc3NhZ2UoVGhpcy0+aGljLCBJQ01fQ09NUFJFU1NfRlJBTUVTX0lORk8sCgkJICAgIChMUEFSQU0pJmljRnJhbWVzLCAoTFBBUkFNKXNpemVvZihpY0ZyYW1lcykpOwogICAgfQogIH0gZWxzZQogICAgVGhpcy0+c0luZm8uZmNjSGFuZGxlciA9IGNvbXB0eXBlRElCOwoKICByZXR1cm4gQVZJRVJSX09LOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNNU3RyZWFtX2ZuSW5mbyhJQVZJU3RyZWFtICppZmFjZSxMUEFWSVNUUkVBTUlORk9XIHBzaSwKCQkJCQlMT05HIHNpemUpCnsKICBJQVZJU3RyZWFtSW1wbCAqVGhpcyA9IChJQVZJU3RyZWFtSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVwLCVsZClcbiIsIGlmYWNlLCBwc2ksIHNpemUpOwoKICBpZiAocHNpID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX0JBRFBBUkFNOwogIGlmIChzaXplIDwgMCkKICAgIHJldHVybiBBVklFUlJfQkFEU0laRTsKCiAgbWVtY3B5KHBzaSwgJlRoaXMtPnNJbmZvLCBtaW4oKERXT1JEKXNpemUsIHNpemVvZihUaGlzLT5zSW5mbykpKTsKCiAgaWYgKChEV09SRClzaXplIDwgc2l6ZW9mKFRoaXMtPnNJbmZvKSkKICAgIHJldHVybiBBVklFUlJfQlVGRkVSVE9PU01BTEw7CiAgcmV0dXJuIEFWSUVSUl9PSzsKfQoKc3RhdGljIExPTkcgV0lOQVBJIElDTVN0cmVhbV9mbkZpbmRTYW1wbGUoSUFWSVN0cmVhbSAqaWZhY2UsIExPTkcgcG9zLAoJCQkJCSAgIExPTkcgZmxhZ3MpCnsKICBJQVZJU3RyZWFtSW1wbCAqVGhpcyA9IChJQVZJU3RyZWFtSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVsZCwweCUwOGxYKVxuIixpZmFjZSxwb3MsZmxhZ3MpOwoKICBpZiAoZmxhZ3MgJiBGSU5EX0ZST01fU1RBUlQpIHsKICAgIHBvcyA9IFRoaXMtPnNJbmZvLmR3U3RhcnQ7CiAgICBmbGFncyAmPSB+KEZJTkRfRlJPTV9TVEFSVHxGSU5EX1BSRVYpOwogICAgZmxhZ3MgfD0gRklORF9ORVhUOwogIH0KCiAgaWYgKGZsYWdzICYgRklORF9SRVQpCiAgICBXQVJOKCI6IEZJTkRfUkVUIGZsYWdzIHdpbGwgYmUgaWdub3JlZCFcbiIpOwoKICBpZiAoZmxhZ3MgJiBGSU5EX0tFWSkgewogICAgaWYgKFRoaXMtPmhpYyA9PSBOVUxMKQogICAgICByZXR1cm4gcG9zOyAvKiB3ZSBkZWNvbXByZXNzIHNvIGV2ZXJ5IGZyYW1lIGlzIGEga2V5ZnJhbWUgKi8KCiAgICBpZiAoZmxhZ3MgJiBGSU5EX1BSRVYpIHsKICAgICAgLyogbmVlZCB0byByZWFkIG9sZCBvciBuZXcgZnJhbWVzPyAqLwogICAgICBpZiAoVGhpcy0+bExhc3RLZXkgPD0gcG9zIHx8IHBvcyA8IFRoaXMtPmxDdXJyZW50KQoJSUFWSVN0cmVhbV9SZWFkKGlmYWNlLCBwb3MsIDEsIE5VTEwsIDAsIE5VTEwsIE5VTEwpOwoKICAgICAgcmV0dXJuIFRoaXMtPmxMYXN0S2V5OwogICAgfQogIH0gZWxzZSBpZiAoZmxhZ3MgJiBGSU5EX0FOWSkgewogICAgcmV0dXJuIHBvczsgLyogV2UgcmVhbGx5IGRvbid0IGtub3csIHJlcmVhZCBpcyB0byBleHBlbnNpdmUsIHNvIGd1ZXNzLiAqLwogIH0gZWxzZSBpZiAoZmxhZ3MgJiBGSU5EX0ZPUk1BVCkgewogICAgaWYgKGZsYWdzICYgRklORF9QUkVWKQogICAgICByZXR1cm4gMDsKICB9CgogIHJldHVybiAtMTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDTVN0cmVhbV9mblJlYWRGb3JtYXQoSUFWSVN0cmVhbSAqaWZhY2UsIExPTkcgcG9zLAoJCQkJCSAgICAgIExQVk9JRCBmb3JtYXQsIExPTkcgKmZvcm1hdHNpemUpCnsKICBJQVZJU3RyZWFtSW1wbCAqVGhpcyA9IChJQVZJU3RyZWFtSW1wbCAqKWlmYWNlOwoKICBMUEJJVE1BUElORk9IRUFERVIgbHBiaTsKICBIUkVTVUxUICAgICAgICAgICAgaHI7CgogIFRSQUNFKCIoJXAsJWxkLCVwLCVwKVxuIiwgaWZhY2UsIHBvcywgZm9ybWF0LCBmb3JtYXRzaXplKTsKCiAgaWYgKGZvcm1hdHNpemUgPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfQkFEUEFSQU07CgogIGlmIChUaGlzLT5wZyA9PSBOVUxMKSB7CiAgICBociA9IEFWSUZJTEVfT3BlbkdldEZyYW1lKFRoaXMpOwoKICAgIGlmIChGQUlMRUQoaHIpKQogICAgICByZXR1cm4gaHI7CiAgfQoKICBscGJpID0gKExQQklUTUFQSU5GT0hFQURFUilBVklTdHJlYW1HZXRGcmFtZShUaGlzLT5wZywgcG9zKTsKICBpZiAobHBiaSA9PSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9NRU1PUlk7CgogIGlmIChUaGlzLT5oaWMgPT0gTlVMTCkgewogICAgTE9ORyBzaXplID0gbHBiaS0+YmlTaXplICsgbHBiaS0+YmlDbHJVc2VkICogc2l6ZW9mKFJHQlFVQUQpOwoKICAgIGlmIChzaXplID4gMCkgewogICAgICBpZiAoVGhpcy0+c0luZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplIDwgbHBiaS0+YmlTaXplSW1hZ2UpCglUaGlzLT5zSW5mby5kd1N1Z2dlc3RlZEJ1ZmZlclNpemUgPSBscGJpLT5iaVNpemVJbWFnZTsKCiAgICAgIFRoaXMtPmNiT3V0cHV0ID0gc2l6ZTsKICAgICAgaWYgKGZvcm1hdCAhPSBOVUxMKSB7CglpZiAoVGhpcy0+bHBiaU91dHB1dCAhPSBOVUxMKQoJICBtZW1jcHkoZm9ybWF0LCBUaGlzLT5scGJpT3V0cHV0LCBtaW4oKmZvcm1hdHNpemUsIFRoaXMtPmNiT3V0cHV0KSk7CgllbHNlCgkgIG1lbWNweShmb3JtYXQsIGxwYmksIG1pbigqZm9ybWF0c2l6ZSwgc2l6ZSkpOwogICAgICB9CiAgICB9CiAgfSBlbHNlIGlmIChmb3JtYXQgIT0gTlVMTCkKICAgIG1lbWNweShmb3JtYXQsIFRoaXMtPmxwYmlPdXRwdXQsIG1pbigqZm9ybWF0c2l6ZSwgVGhpcy0+Y2JPdXRwdXQpKTsKCiAgaWYgKCpmb3JtYXRzaXplIDwgVGhpcy0+Y2JPdXRwdXQpCiAgICBociA9IEFWSUVSUl9CVUZGRVJUT09TTUFMTDsKICBlbHNlCiAgICBociA9IEFWSUVSUl9PSzsKCiAgKmZvcm1hdHNpemUgPSBUaGlzLT5jYk91dHB1dDsKICByZXR1cm4gaHI7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ01TdHJlYW1fZm5TZXRGb3JtYXQoSUFWSVN0cmVhbSAqaWZhY2UsIExPTkcgcG9zLAoJCQkJCSAgICAgTFBWT0lEIGZvcm1hdCwgTE9ORyBmb3JtYXRzaXplKQp7CiAgSUFWSVN0cmVhbUltcGwgKlRoaXMgPSAoSUFWSVN0cmVhbUltcGwgKilpZmFjZTsKCiAgVFJBQ0UoIiglcCwlbGQsJXAsJWxkKVxuIiwgaWZhY2UsIHBvcywgZm9ybWF0LCBmb3JtYXRzaXplKTsKCiAgLyogY2hlY2sgcGFyYW1ldGVycyAqLwogIGlmIChmb3JtYXQgPT0gTlVMTCB8fCBmb3JtYXRzaXplIDw9IDApCiAgICByZXR1cm4gQVZJRVJSX0JBRFBBUkFNOwoKICAvKiBXZSBjYW4gb25seSBhY2NlcHQgUkdCIGRhdGEgZm9yIHdyaXRpbmcgKi8KICBpZiAoKChMUEJJVE1BUElORk9IRUFERVIpZm9ybWF0KS0+YmlDb21wcmVzc2lvbiAhPSBCSV9SR0IpIHsKICAgIFdBUk4oIjogbmVlZCBSR0IgZGF0YSBhcyBpbnB1dFxuIik7CiAgICByZXR1cm4gQVZJRVJSX1VOU1VQUE9SVEVEOwogIH0KCiAgLyogSW5wdXQgZm9ybWF0IGFscmVhZHkga25vd24/CiAgICogQ2hhbmdpbmcgb2YgcGFsZXR0ZSBpcyBzdXBwb3J0ZWQsIGJ1dCBiZSBxdWlldCBpZiBpdCdzIHRoZSBzYW1lICovCiAgaWYgKFRoaXMtPmxwYmlJbnB1dCAhPSBOVUxMKSB7CiAgICBpZiAoVGhpcy0+Y2JJbnB1dCAhPSBmb3JtYXRzaXplKQogICAgICByZXR1cm4gQVZJRVJSX1VOU1VQUE9SVEVEOwoKICAgIGlmIChtZW1jbXAoZm9ybWF0LCBUaGlzLT5scGJpSW5wdXQsIGZvcm1hdHNpemUpID09IDApCiAgICAgIHJldHVybiBBVklFUlJfT0s7CiAgfQoKICAvKiBEb2VzIHRoZSBuZXN0ZWQgc3RyZWFtIHN1cHBvcnQgd3JpdGluZz8gKi8KICBpZiAoKFRoaXMtPnNJbmZvLmR3Q2FwcyAmIEFWSUZJTEVDQVBTX0NBTldSSVRFKSA9PSAwKQogICAgcmV0dXJuIEFWSUVSUl9SRUFET05MWTsKCiAgLyogY2hlY2sgaWYgZnJhbWUgaXMgYWxyZWFkeSB3cml0dGVuICovCiAgaWYgKFRoaXMtPnNJbmZvLmR3TGVuZ3RoICsgVGhpcy0+c0luZm8uZHdTdGFydCA+IHBvcykKICAgIHJldHVybiBBVklFUlJfVU5TVVBQT1JURUQ7CgogIC8qIGNoZWNrIGlmIHdlIHNob3VsZCBjb21wcmVzcyAqLwogIGlmIChUaGlzLT5zSW5mby5mY2NIYW5kbGVyID09IDAgfHwKICAgICAgVGhpcy0+c0luZm8uZmNjSGFuZGxlciA9PSBtbWlvRk9VUkNDKCdOJywnTycsJ04nLCdFJykpCiAgICBUaGlzLT5zSW5mby5mY2NIYW5kbGVyID0gY29tcHR5cGVESUI7CgogIC8qIG9ubHkgcGFzcyB0aHJvdWdoPyAqLwogIGlmIChUaGlzLT5zSW5mby5mY2NIYW5kbGVyID09IGNvbXB0eXBlRElCKQogICAgcmV0dXJuIElBVklTdHJlYW1fU2V0Rm9ybWF0KFRoaXMtPnBTdHJlYW0sIHBvcywgZm9ybWF0LCBmb3JtYXRzaXplKTsKCiAgLyogaW5pdGlhbCBmb3JtYXQgc2V0dGluZz8gKi8KICBpZiAoVGhpcy0+bHBiaUlucHV0ID09IE5VTEwpIHsKICAgIFVMT05HIHNpemU7CgogICAgYXNzZXJ0KFRoaXMtPmhpYyAhPSBOVUxMKTsKCiAgICAvKiBnZXQgbWVtb3J5IGZvciBpbnB1dCBmb3JtYXQgKi8KICAgIFRoaXMtPmxwYmlJbnB1dCA9IChMUEJJVE1BUElORk9IRUFERVIpR2xvYmFsQWxsb2NQdHIoR0hORCwgZm9ybWF0c2l6ZSk7CiAgICBpZiAoVGhpcy0+bHBiaUlucHV0ID09IE5VTEwpCiAgICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwogICAgVGhpcy0+Y2JJbnB1dCA9IGZvcm1hdHNpemU7CiAgICBtZW1jcHkoVGhpcy0+bHBiaUlucHV0LCBmb3JtYXQsIGZvcm1hdHNpemUpOwoKICAgIC8qIGdldCBvdXRwdXQgZm9ybWF0ICovCiAgICBzaXplID0gSUNDb21wcmVzc0dldEZvcm1hdFNpemUoVGhpcy0+aGljLCBUaGlzLT5scGJpSW5wdXQpOwogICAgaWYgKHNpemUgPCBzaXplb2YoQklUTUFQSU5GT0hFQURFUikpCiAgICAgIHJldHVybiBBVklFUlJfQ09NUFJFU1NPUjsKICAgIFRoaXMtPmxwYmlPdXRwdXQgPSAoTFBCSVRNQVBJTkZPSEVBREVSKUdsb2JhbEFsbG9jUHRyKEdITkQsIHNpemUpOwogICAgaWYgKFRoaXMtPmxwYmlPdXRwdXQgPT0gTlVMTCkKICAgICAgcmV0dXJuIEFWSUVSUl9NRU1PUlk7CiAgICBUaGlzLT5jYk91dHB1dCA9IHNpemU7CiAgICBpZiAoSUNDb21wcmVzc0dldEZvcm1hdChUaGlzLT5oaWMsVGhpcy0+bHBiaUlucHV0LFRoaXMtPmxwYmlPdXRwdXQpIDwgU19PSykKICAgICAgcmV0dXJuIEFWSUVSUl9DT01QUkVTU09SOwoKICAgIC8qIHVwZGF0ZSBBVklTVFJFQU1JTkZPIHN0cnVjdHVyZSAqLwogICAgVGhpcy0+c0luZm8ucmNGcmFtZS5yaWdodCAgPQogICAgICBUaGlzLT5zSW5mby5yY0ZyYW1lLmxlZnQgKyBUaGlzLT5scGJpT3V0cHV0LT5iaVdpZHRoOwogICAgVGhpcy0+c0luZm8ucmNGcmFtZS5ib3R0b20gPQogICAgICBUaGlzLT5zSW5mby5yY0ZyYW1lLnRvcCAgKyBUaGlzLT5scGJpT3V0cHV0LT5iaUhlaWdodDsKCiAgICAvKiBwcmVwYXJlIGNvZGVjIGZvciBjb21wcmVzc2lvbiAqLwogICAgaWYgKElDQ29tcHJlc3NCZWdpbihUaGlzLT5oaWMsIFRoaXMtPmxwYmlJbnB1dCwgVGhpcy0+bHBiaU91dHB1dCkgIT0gU19PSykKICAgICAgcmV0dXJuIEFWSUVSUl9DT01QUkVTU09SOwoKICAgIC8qIGFsbG9jYXRlIG1lbW9yeSBmb3IgY29tcHJlc3NlZCBmcmFtZSAqLwogICAgc2l6ZSA9IElDQ29tcHJlc3NHZXRTaXplKFRoaXMtPmhpYywgVGhpcy0+bHBiaUlucHV0LCBUaGlzLT5scGJpT3V0cHV0KTsKICAgIFRoaXMtPmxwYmlDdXIgPQogICAgICAoTFBCSVRNQVBJTkZPSEVBREVSKUdsb2JhbEFsbG9jUHRyKEdNRU1fTU9WRUFCTEUsIFRoaXMtPmNiT3V0cHV0ICsgc2l6ZSk7CiAgICBpZiAoVGhpcy0+bHBiaUN1ciA9PSBOVUxMKQogICAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgIG1lbWNweShUaGlzLT5scGJpQ3VyLCBUaGlzLT5scGJpT3V0cHV0LCBUaGlzLT5jYk91dHB1dCk7CiAgICBUaGlzLT5scEN1ciA9IERJQlBUUihUaGlzLT5scGJpQ3VyKTsKCiAgICAvKiBhbGxvY2F0ZSBtZW1vcnkgZm9yIGxhc3QgZnJhbWUgaWYgbmVlZGVkICovCiAgICBpZiAoVGhpcy0+bEtleUZyYW1lRXZlcnkgIT0gMSAmJgoJKFRoaXMtPmR3SUNNRmxhZ3MgJiBWSURDRl9GQVNUVEVNUE9SQUxDKSA9PSAwKSB7CiAgICAgIHNpemUgPSBJQ0RlY29tcHJlc3NHZXRGb3JtYXRTaXplKFRoaXMtPmhpYywgVGhpcy0+bHBiaU91dHB1dCk7CiAgICAgIFRoaXMtPmxwYmlQcmV2ID0gKExQQklUTUFQSU5GT0hFQURFUilHbG9iYWxBbGxvY1B0cihHSE5ELCBzaXplKTsKICAgICAgaWYgKFRoaXMtPmxwYmlQcmV2ID09IE5VTEwpCglyZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgICAgaWYgKElDRGVjb21wcmVzc0dldEZvcm1hdChUaGlzLT5oaWMsIFRoaXMtPmxwYmlPdXRwdXQsIFRoaXMtPmxwYmlQcmV2KSA8IFNfT0spCglyZXR1cm4gQVZJRVJSX0NPTVBSRVNTT1I7CgogICAgICBpZiAoVGhpcy0+bHBiaVByZXYtPmJpU2l6ZUltYWdlID09IDApIHsKCVRoaXMtPmxwYmlQcmV2LT5iaVNpemVJbWFnZSA9CgkgIERJQldJRFRIQllURVMoKlRoaXMtPmxwYmlQcmV2KSAqIFRoaXMtPmxwYmlQcmV2LT5iaUhlaWdodDsKICAgICAgfQoKICAgICAgLyogZ2V0IG1lbW9yeSBmb3IgZm9ybWF0IGFuZCBwaWN0dXJlICovCiAgICAgIHNpemUgKz0gVGhpcy0+bHBiaVByZXYtPmJpU2l6ZUltYWdlOwogICAgICBUaGlzLT5scGJpUHJldiA9CiAgICAgICAoTFBCSVRNQVBJTkZPSEVBREVSKUdsb2JhbFJlQWxsb2NQdHIoVGhpcy0+bHBiaVByZXYsc2l6ZSxHTUVNX01PVkVBQkxFKTsKICAgICAgaWYgKFRoaXMtPmxwYmlQcmV2ID09IE5VTEwpCglyZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgICAgVGhpcy0+bHBQcmV2ID0gRElCUFRSKFRoaXMtPmxwYmlQcmV2KTsKCiAgICAgIC8qIHByZXBhcmUgY29kZWMgYWxzbyBmb3IgZGVjb21wcmVzc2lvbiAqLwogICAgICBpZiAoSUNEZWNvbXByZXNzQmVnaW4oVGhpcy0+aGljLFRoaXMtPmxwYmlPdXRwdXQsVGhpcy0+bHBiaVByZXYpICE9IFNfT0spCglyZXR1cm4gQVZJRVJSX0NPTVBSRVNTT1I7CiAgICB9CiAgfSBlbHNlIHsKICAgIC8qIGZvcm1hdCBjaGFuZ2UgLS0gY2hlY2sgdGhhdCdzIG9ubHkgdGhlIHBhbGV0dGUgKi8KICAgIExQQklUTUFQSU5GT0hFQURFUiBscGJpID0gKExQQklUTUFQSU5GT0hFQURFUilmb3JtYXQ7CgogICAgaWYgKGxwYmktPmJpU2l6ZSAhPSBUaGlzLT5scGJpSW5wdXQtPmJpU2l6ZSB8fAoJbHBiaS0+YmlXaWR0aCAhPSBUaGlzLT5scGJpSW5wdXQtPmJpV2lkdGggfHwKCWxwYmktPmJpSGVpZ2h0ICE9IFRoaXMtPmxwYmlJbnB1dC0+YmlIZWlnaHQgfHwKCWxwYmktPmJpQml0Q291bnQgIT0gVGhpcy0+bHBiaUlucHV0LT5iaUJpdENvdW50IHx8CglscGJpLT5iaVBsYW5lcyAhPSBUaGlzLT5scGJpSW5wdXQtPmJpUGxhbmVzIHx8CglscGJpLT5iaUNvbXByZXNzaW9uICE9IFRoaXMtPmxwYmlJbnB1dC0+YmlDb21wcmVzc2lvbiB8fAoJbHBiaS0+YmlDbHJVc2VkICE9IFRoaXMtPmxwYmlJbnB1dC0+YmlDbHJVc2VkKQogICAgICByZXR1cm4gQVZJRVJSX1VOU1VQUE9SVEVEOwoKICAgIC8qIGdldCBuZXcgb3V0cHV0IGZvcm1hdCAqLwogICAgaWYgKElDQ29tcHJlc3NHZXRGb3JtYXQoVGhpcy0+aGljLCBscGJpLCBUaGlzLT5scGJpT3V0cHV0KSA8IFNfT0spCiAgICAgIHJldHVybiBBVklFUlJfQkFERk9STUFUOwoKICAgIC8qIHJlc3RhcnQgY29tcHJlc3Npb24gKi8KICAgIElDQ29tcHJlc3NFbmQoVGhpcy0+aGljKTsKICAgIGlmIChJQ0NvbXByZXNzQmVnaW4oVGhpcy0+aGljLCBscGJpLCBUaGlzLT5scGJpT3V0cHV0KSAhPSBTX09LKQogICAgICByZXR1cm4gQVZJRVJSX0NPTVBSRVNTT1I7CgogICAgLyogY2hlY2sgaWYgd2UgbmVlZCB0byByZXN0YXJ0IGRlY29tcHJlc2lvbiBhbHNvICovCiAgICBpZiAoVGhpcy0+bEtleUZyYW1lRXZlcnkgIT0gMSAmJgoJKFRoaXMtPmR3SUNNRmxhZ3MgJiBWSURDRl9GQVNUVEVNUE9SQUxDKSA9PSAwKSB7CiAgICAgIElDRGVjb21wcmVzc0VuZChUaGlzLT5oaWMpOwogICAgICBpZiAoSUNEZWNvbXByZXNzR2V0Rm9ybWF0KFRoaXMtPmhpYyxUaGlzLT5scGJpT3V0cHV0LFRoaXMtPmxwYmlQcmV2KSA8IFNfT0spCglyZXR1cm4gQVZJRVJSX0NPTVBSRVNTT1I7CiAgICAgIGlmIChJQ0RlY29tcHJlc3NCZWdpbihUaGlzLT5oaWMsVGhpcy0+bHBiaU91dHB1dCxUaGlzLT5scGJpUHJldikgIT0gU19PSykKCXJldHVybiBBVklFUlJfQ09NUFJFU1NPUjsKICAgIH0KICB9CgogIC8qIHRlbGwgbmVzdGVkIHN0cmVhbSB0aGUgbmV3IGZvcm1hdCAqLwogIHJldHVybiBJQVZJU3RyZWFtX1NldEZvcm1hdChUaGlzLT5wU3RyZWFtLCBwb3MsCgkJCSAgICAgIFRoaXMtPmxwYmlPdXRwdXQsIFRoaXMtPmNiT3V0cHV0KTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDTVN0cmVhbV9mblJlYWQoSUFWSVN0cmVhbSAqaWZhY2UsIExPTkcgc3RhcnQsCgkJCQkJTE9ORyBzYW1wbGVzLCBMUFZPSUQgYnVmZmVyLAoJCQkJCUxPTkcgYnVmZmVyc2l6ZSwgTFBMT05HIGJ5dGVzcmVhZCwKCQkJCQlMUExPTkcgc2FtcGxlc3JlYWQpCnsKICBJQVZJU3RyZWFtSW1wbCAqVGhpcyA9IChJQVZJU3RyZWFtSW1wbCAqKWlmYWNlOwoKICBMUEJJVE1BUElORk9IRUFERVIgbHBiaTsKCiAgVFJBQ0UoIiglcCwlbGQsJWxkLCVwLCVsZCwlcCwlcClcbiIsIGlmYWNlLCBzdGFydCwgc2FtcGxlcywgYnVmZmVyLAogCWJ1ZmZlcnNpemUsIGJ5dGVzcmVhZCwgc2FtcGxlc3JlYWQpOwoKICAvKiBjbGVhciByZXR1cm4gcGFyYW1ldGVycyBpZiBnaXZlbiAqLwogIGlmIChieXRlc3JlYWQgIT0gTlVMTCkKICAgICpieXRlc3JlYWQgPSAwOwogIGlmIChzYW1wbGVzcmVhZCAhPSBOVUxMKQogICAgKnNhbXBsZXNyZWFkID0gMDsKCiAgaWYgKHNhbXBsZXMgPT0gMCkKICAgIHJldHVybiBBVklFUlJfT0s7CgogIC8qIGNoZWNrIHBhcmFtZXRlcnMgKi8KICBpZiAoc2FtcGxlcyAhPSAxICYmIChieXRlc3JlYWQgPT0gTlVMTCAmJiBzYW1wbGVzcmVhZCA9PSBOVUxMKSkKICAgIHJldHVybiBBVklFUlJfQkFEUEFSQU07CiAgaWYgKHNhbXBsZXMgPT0gLTEpIC8qIHJlYWQgYXMgbXVjaCBhcyB3ZSBjb3VsZCAqLwogICAgc2FtcGxlcyA9IDE7CgogIGlmIChUaGlzLT5wZyA9PSBOVUxMKSB7CiAgICBIUkVTVUxUIGhyID0gQVZJRklMRV9PcGVuR2V0RnJhbWUoVGhpcyk7CgogICAgaWYgKEZBSUxFRChocikpCiAgICAgIHJldHVybiBocjsKICB9CgogIC8qIGNvbXByZXNzIG9yIGRlY29tcHJlc3M/ICovCiAgaWYgKFRoaXMtPmhpYyA9PSBOVUxMKSB7CiAgICAvKiBkZWNvbXByZXNzICovCiAgICBscGJpID0gKExQQklUTUFQSU5GT0hFQURFUilBVklTdHJlYW1HZXRGcmFtZShUaGlzLT5wZywgc3RhcnQpOwogICAgaWYgKGxwYmkgPT0gTlVMTCkKICAgICAgcmV0dXJuIEFWSUVSUl9NRU1PUlk7CgogICAgaWYgKGJ1ZmZlciAhPSBOVUxMICYmIGJ1ZmZlcnNpemUgPiAwKSB7CiAgICAgIC8qIGNoZWNrIGJ1ZmZlcnNpemUgKi8KICAgICAgaWYgKGJ1ZmZlcnNpemUgPCBscGJpLT5iaVNpemVJbWFnZSkKCXJldHVybiBBVklFUlJfQlVGRkVSVE9PU01BTEw7CgogICAgICBtZW1jcHkoYnVmZmVyLCBESUJQVFIobHBiaSksIGxwYmktPmJpU2l6ZUltYWdlKTsKICAgIH0KCiAgICAvKiBmaWxsIG91dCByZXR1cm4gcGFyYW1ldGVycyBpZiBnaXZlbiAqLwogICAgaWYgKGJ5dGVzcmVhZCAhPSBOVUxMKQogICAgICAqYnl0ZXNyZWFkID0gbHBiaS0+YmlTaXplSW1hZ2U7CiAgfSBlbHNlIHsKICAgIC8qIGNvbXByZXNzICovCiAgICBpZiAoVGhpcy0+bEN1cnJlbnQgPiBzdGFydCkKICAgICAgQVZJRklMRV9SZXNldChUaGlzKTsKCiAgICB3aGlsZSAoc3RhcnQgPiBUaGlzLT5sQ3VycmVudCkgewogICAgICBIUkVTVUxUIGhyOwoKICAgICAgbHBiaSA9IChMUEJJVE1BUElORk9IRUFERVIpQVZJU3RyZWFtR2V0RnJhbWUoVGhpcy0+cGcsICsrVGhpcy0+bEN1cnJlbnQpOwogICAgICBpZiAobHBiaSA9PSBOVUxMKSB7CglBVklGSUxFX1Jlc2V0KFRoaXMpOwoJcmV0dXJuIEFWSUVSUl9NRU1PUlk7CiAgICAgIH0KCiAgICAgIGhyID0gQVZJRklMRV9FbmNvZGVGcmFtZShUaGlzLCBscGJpLCBESUJQVFIobHBiaSkpOwogICAgICBpZiAoRkFJTEVEKGhyKSkgewoJQVZJRklMRV9SZXNldChUaGlzKTsKCXJldHVybiBocjsKICAgICAgfQogICAgfQoKICAgIGlmIChidWZmZXIgIT0gTlVMTCAmJiBidWZmZXJzaXplID4gMCkgewogICAgICAvKiBjaGVjayBidWZmZXJzaXplICovCiAgICAgIGlmIChUaGlzLT5scGJpQ3VyLT5iaVNpemVJbWFnZSA+IGJ1ZmZlcnNpemUpCglyZXR1cm4gQVZJRVJSX0JVRkZFUlRPT1NNQUxMOwoKICAgICAgbWVtY3B5KGJ1ZmZlciwgVGhpcy0+bHBDdXIsIFRoaXMtPmxwYmlDdXItPmJpU2l6ZUltYWdlKTsKICAgIH0KCiAgICAvKiBmaWxsIG91dCByZXR1cm4gcGFyYW1ldGVycyBpZiBnaXZlbiAqLwogICAgaWYgKGJ5dGVzcmVhZCAhPSBOVUxMKQogICAgICAqYnl0ZXNyZWFkID0gVGhpcy0+bHBiaUN1ci0+YmlTaXplSW1hZ2U7CiAgfQoKICAvKiBmaWxsIG91dCByZXR1cm4gcGFyYW1ldGVycyBpZiBnaXZlbiAqLwogIGlmIChzYW1wbGVzcmVhZCAhPSBOVUxMKQogICAgKnNhbXBsZXNyZWFkID0gMTsKCiAgcmV0dXJuIEFWSUVSUl9PSzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDTVN0cmVhbV9mbldyaXRlKElBVklTdHJlYW0gKmlmYWNlLCBMT05HIHN0YXJ0LAoJCQkJCSBMT05HIHNhbXBsZXMsIExQVk9JRCBidWZmZXIsCgkJCQkJIExPTkcgYnVmZmVyc2l6ZSwgRFdPUkQgZmxhZ3MsCgkJCQkJIExQTE9ORyBzYW1wd3JpdHRlbiwKCQkJCQkgTFBMT05HIGJ5dGVzd3JpdHRlbikKewogIElBVklTdHJlYW1JbXBsICpUaGlzID0gKElBVklTdHJlYW1JbXBsICopaWZhY2U7CgogIEhSRVNVTFQgaHI7CgogIFRSQUNFKCIoJXAsJWxkLCVsZCwlcCwlbGQsMHglMDhsWCwlcCwlcClcbiIsIGlmYWNlLCBzdGFydCwgc2FtcGxlcywKCWJ1ZmZlciwgYnVmZmVyc2l6ZSwgZmxhZ3MsIHNhbXB3cml0dGVuLCBieXRlc3dyaXR0ZW4pOwoKICAvKiBjbGVhciByZXR1cm4gcGFyYW1ldGVycyBpZiBnaXZlbiAqLwogIGlmIChzYW1wd3JpdHRlbiAhPSBOVUxMKQogICAgKnNhbXB3cml0dGVuID0gMDsKICBpZiAoYnl0ZXN3cml0dGVuICE9IE5VTEwpCiAgICAqYnl0ZXN3cml0dGVuID0gMDsKCiAgLyogY2hlY2sgcGFyYW1ldGVycyAqLwogIGlmIChidWZmZXIgPT0gTlVMTCAmJiAoYnVmZmVyc2l6ZSA+IDAgfHwgc2FtcGxlcyA+IDApKQogICAgcmV0dXJuIEFWSUVSUl9CQURQQVJBTTsKCiAgaWYgKFRoaXMtPnNJbmZvLmZjY0hhbmRsZXIgPT0gY29tcHR5cGVESUIpIHsKICAgIC8qIG9ubHkgcGFzcyB0aHJvdWdoICovCiAgICBmbGFncyB8PSBBVklJRl9LRVlGUkFNRTsKCiAgICByZXR1cm4gSUFWSVN0cmVhbV9Xcml0ZShUaGlzLT5wU3RyZWFtLCBzdGFydCwgc2FtcGxlcywgYnVmZmVyLCBidWZmZXJzaXplLAoJCQkgICAgZmxhZ3MsIHNhbXB3cml0dGVuLCBieXRlc3dyaXR0ZW4pOwogIH0gZWxzZSB7CiAgICAvKiBjb21wcmVzcyBkYXRhIGJlZm9yZSB3cml0aW5nIHRvIHBTdHJlYW0gKi8KICAgIGlmIChzYW1wbGVzICE9IDEgJiYgKHNhbXB3cml0dGVuID09IE5VTEwgJiYgYnl0ZXN3cml0dGVuID09IE5VTEwpKQogICAgICByZXR1cm4gQVZJRVJSX1VOU1VQUE9SVEVEOwoKICAgIFRoaXMtPmxDdXJyZW50ID0gc3RhcnQ7CiAgICBociA9IEFWSUZJTEVfRW5jb2RlRnJhbWUoVGhpcywgVGhpcy0+bHBiaUlucHV0LCBidWZmZXIpOwogICAgaWYgKEZBSUxFRChocikpCiAgICAgIHJldHVybiBocjsKCiAgICBpZiAoVGhpcy0+bExhc3RLZXkgPT0gc3RhcnQpCiAgICAgIGZsYWdzIHw9IEFWSUlGX0tFWUZSQU1FOwoKICAgIHJldHVybiBJQVZJU3RyZWFtX1dyaXRlKFRoaXMtPnBTdHJlYW0sIHN0YXJ0LCBzYW1wbGVzLCBUaGlzLT5scEN1ciwKCQkJICAgIFRoaXMtPmxwYmlDdXItPmJpU2l6ZUltYWdlLCBmbGFncywgYnl0ZXN3cml0dGVuLAoJCQkgICAgc2FtcHdyaXR0ZW4pOwogIH0KfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDTVN0cmVhbV9mbkRlbGV0ZShJQVZJU3RyZWFtICppZmFjZSwgTE9ORyBzdGFydCwKCQkJCQkgIExPTkcgc2FtcGxlcykKewogIElBVklTdHJlYW1JbXBsICpUaGlzID0gKElBVklTdHJlYW1JbXBsICopaWZhY2U7CgogIFRSQUNFKCIoJXAsJWxkLCVsZClcbiIsIGlmYWNlLCBzdGFydCwgc2FtcGxlcyk7CgogIHJldHVybiBJQVZJU3RyZWFtX0RlbGV0ZShUaGlzLT5wU3RyZWFtLCBzdGFydCwgc2FtcGxlcyk7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ01TdHJlYW1fZm5SZWFkRGF0YShJQVZJU3RyZWFtICppZmFjZSwgRFdPUkQgZmNjLAoJCQkJCSAgICBMUFZPSUQgbHAsIExQTE9ORyBscHJlYWQpCnsKICBJQVZJU3RyZWFtSW1wbCAqVGhpcyA9IChJQVZJU3RyZWFtSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLDB4JTA4bFgsJXAsJXApXG4iLCBpZmFjZSwgZmNjLCBscCwgbHByZWFkKTsKCiAgYXNzZXJ0KFRoaXMtPnBTdHJlYW0gIT0gTlVMTCk7CgogIHJldHVybiBJQVZJU3RyZWFtX1JlYWREYXRhKFRoaXMtPnBTdHJlYW0sIGZjYywgbHAsIGxwcmVhZCk7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ01TdHJlYW1fZm5Xcml0ZURhdGEoSUFWSVN0cmVhbSAqaWZhY2UsIERXT1JEIGZjYywKCQkJCQkgICAgIExQVk9JRCBscCwgTE9ORyBzaXplKQp7CiAgSUFWSVN0cmVhbUltcGwgKlRoaXMgPSAoSUFWSVN0cmVhbUltcGwgKilpZmFjZTsKCiAgVFJBQ0UoIiglcCwweCUwOGx4LCVwLCVsZClcbiIsIGlmYWNlLCBmY2MsIGxwLCBzaXplKTsKCiAgYXNzZXJ0KFRoaXMtPnBTdHJlYW0gIT0gTlVMTCk7CgogIHJldHVybiBJQVZJU3RyZWFtX1dyaXRlRGF0YShUaGlzLT5wU3RyZWFtLCBmY2MsIGxwLCBzaXplKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDTVN0cmVhbV9mblNldEluZm8oSUFWSVN0cmVhbSAqaWZhY2UsCgkJCQkJICAgTFBBVklTVFJFQU1JTkZPVyBpbmZvLCBMT05HIGluZm9sZW4pCnsKICBGSVhNRSgiKCVwLCVwLCVsZCk6IHN0dWJcbiIsIGlmYWNlLCBpbmZvLCBpbmZvbGVuKTsKCiAgcmV0dXJuIEVfRkFJTDsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwoKc3RhdGljIEhSRVNVTFQgQVZJRklMRV9FbmNvZGVGcmFtZShJQVZJU3RyZWFtSW1wbCAqVGhpcywKCQkJCSAgIExQQklUTUFQSU5GT0hFQURFUiBscGJpLCBMUFZPSUQgbHBCaXRzKQp7CiAgRFdPUkQgZHdNaW5RdWFsLCBkd01heFF1YWwsIGR3Q3VyUXVhbDsKICBEV09SRCBkd1JlcXVlc3Q7CiAgRFdPUkQgaWNtRmxhZ3MgPSAwOwogIERXT1JEIGlkeEZsYWdzID0gMDsKICBCT09MICBiRGVjcmVhc2VkUXVhbCA9IEZBTFNFOwogIEJPT0wgIGRvU2l6ZUNoZWNrOwogIEJPT0wgIG5vUHJldjsKCiAgLyogbWFrZSBsS2V5RnJhbWVFdmVyeSBhbmQgYXQgc3RhcnQgYSBrZXlmcmFtZSAqLwogIGlmICgoVGhpcy0+bEtleUZyYW1lRXZlcnkgIT0gMCAmJgogICAgICAgKFRoaXMtPmxDdXJyZW50IC0gVGhpcy0+bExhc3RLZXkpID49IFRoaXMtPmxLZXlGcmFtZUV2ZXJ5KSB8fAogICAgICBUaGlzLT5sQ3VycmVudCA9PSBUaGlzLT5zSW5mby5kd1N0YXJ0KSB7CiAgICBpZHhGbGFncyA9IEFWSUlGX0tFWUZSQU1FOwogICAgaWNtRmxhZ3MgPSBJQ0NPTVBSRVNTX0tFWUZSQU1FOwogIH0KCiAgaWYgKFRoaXMtPmxLZXlGcmFtZUV2ZXJ5ICE9IDApIHsKICAgIGlmIChUaGlzLT5sQ3VycmVudCA9PSBUaGlzLT5zSW5mby5kd1N0YXJ0KSB7CiAgICAgIGlmIChpZHhGbGFncyAmIEFWSUlGX0tFWUZSQU1FKSB7CgkvKiBmb3Iga2V5ZnJhbWVzIGFsbG93IHRvIGNvbnN1bWUgYWxsIHVudXNlZCBieXRlcyAqLwoJZHdSZXF1ZXN0ID0gVGhpcy0+ZHdCeXRlc1BlckZyYW1lICsgVGhpcy0+ZHdVbnVzZWRCeXRlczsKCVRoaXMtPmR3VW51c2VkQnl0ZXMgPSAwOwogICAgICB9IGVsc2UgewoJLyogZm9yIG5vbi1rZXlmcmFtZXMgb25seSBhbGxvdyBzb21ldGhpbmcgb2YgdGhlIHVudXNlZCBieXRlcyB0byBiZSBjb25zdW1lZCAqLwoJRFdPUkQgdG1wMSA9IDA7CglEV09SRCB0bXAyOwoKCWlmIChUaGlzLT5kd0J5dGVzUGVyRnJhbWUgPj0gVGhpcy0+ZHdVbnVzZWRCeXRlcykKCSAgdG1wMSA9IFRoaXMtPmR3Qnl0ZXNQZXJGcmFtZSAvIFRoaXMtPmxLZXlGcmFtZUV2ZXJ5OwoJdG1wMiA9IChUaGlzLT5kd1VudXNlZEJ5dGVzICsgdG1wMSkgLyBUaGlzLT5sS2V5RnJhbWVFdmVyeTsKCglkd1JlcXVlc3QgPSBUaGlzLT5kd0J5dGVzUGVyRnJhbWUgLSB0bXAxICsgdG1wMjsKCVRoaXMtPmR3VW51c2VkQnl0ZXMgLT0gdG1wMjsKICAgICAgfQogICAgfSBlbHNlCiAgICAgIGR3UmVxdWVzdCA9IE1BWF9GUkFNRVNJWkU7CiAgfSBlbHNlIHsKICAgIC8qIG9ubHkgb25lIGtleWZyYW1lIGF0IHN0YXJ0IGRlc2lyZWQgKi8KICAgIGlmIChUaGlzLT5sQ3VycmVudCA9PSBUaGlzLT5zSW5mby5kd1N0YXJ0KSB7CiAgICAgIGR3UmVxdWVzdCA9IFRoaXMtPmR3Qnl0ZXNQZXJGcmFtZSArIFRoaXMtPmR3VW51c2VkQnl0ZXM7CiAgICAgIFRoaXMtPmR3VW51c2VkQnl0ZXMgPSAwOwogICAgfSBlbHNlCiAgICAgIGR3UmVxdWVzdCA9IE1BWF9GUkFNRVNJWkU7CiAgfQoKICAvKiBtdXN0IHdlIGNoZWNrIGZvciBmcmFtZXNpemUgdG8gZ2FpbiByZXF1ZXN0ZWQKICAgKiBkYXRhcmF0ZSBvciBjb3VsZCB3ZSB0cnVzdCBjb2RlYz8gKi8KICBkb1NpemVDaGVjayA9IChkd1JlcXVlc3QgIT0gMCAmJiAoKFRoaXMtPmR3SUNNRmxhZ3MgJiAoVklEQ0ZfQ1JVTkNIfFZJRENGX1FVQUxJVFkpKSA9PSAwKSk7CgogIGR3TWF4UXVhbCA9IGR3Q3VyUXVhbCA9IFRoaXMtPnNJbmZvLmR3UXVhbGl0eTsKICBkd01pblF1YWwgPSBJQ1FVQUxJVFlfTE9XOwoKICBub1ByZXYgPSBUUlVFOwogIGlmICgoaWNtRmxhZ3MgJiBJQ0NPTVBSRVNTX0tFWUZSQU1FKSA9PSAwICYmIAogICAgICAoVGhpcy0+ZHdJQ01GbGFncyAmIFZJRENGX0ZBU1RURU1QT1JBTEMpID09IDApCiAgICBub1ByZXYgPSBGQUxTRTsKCiAgZG8gewogICAgRFdPUkQgICBpZHhDa2lkID0gMDsKICAgIEhSRVNVTFQgaHI7CgogICAgaHIgPSBJQ0NvbXByZXNzKFRoaXMtPmhpYyxpY21GbGFncyxUaGlzLT5scGJpQ3VyLFRoaXMtPmxwQ3VyLGxwYmksbHBCaXRzLAoJCSAgICAmaWR4Q2tpZCwgJmlkeEZsYWdzLCBUaGlzLT5sQ3VycmVudCwgZHdSZXF1ZXN0LCBkd0N1clF1YWwsCgkJICAgIG5vUHJldiA/IE5VTEw6VGhpcy0+bHBiaVByZXYsIG5vUHJldiA/IE5VTEw6VGhpcy0+bHBQcmV2KTsKICAgIGlmIChociA9PSBJQ0VSUl9ORVdQQUxFVFRFKSB7CiAgICAgIEZJWE1FKCI6IGNvZGVjIGhhcyBjaGFuZ2VkIHBhbGV0dGUgLS0gdW5oYW5kbGVkIVxuIik7CiAgICB9IGVsc2UgaWYgKGhyICE9IElDRVJSX09LKQogICAgICByZXR1cm4gQVZJRVJSX0NPTVBSRVNTT1I7CgogICAgLyogbmVlZCB0byBjaGVjayBmb3IgZnJhbWVzaXplICovCiAgICBpZiAoISBkb1NpemVDaGVjaykKICAgICAgYnJlYWs7CgogICAgaWYgKGR3UmVxdWVzdCA+PSBUaGlzLT5scGJpQ3VyLT5iaVNpemVJbWFnZSkgewogICAgICAvKiBmcmFtZSBpcyBzbWFsbGVyIC0tIHRyeSB0byBtYXhpbWl6ZSBxdWFsaXR5ICovCiAgICAgIGlmIChkd01heFF1YWwgLSBkd0N1clF1YWwgPiAxMCkgewoJRFdPUkQgdG1wID0gZHdSZXF1ZXN0IC8gODsKCglpZiAodG1wIDwgTUFYX0ZSQU1FU0laRV9ESUZGKQoJICB0bXAgPSBNQVhfRlJBTUVTSVpFX0RJRkY7CgoJaWYgKHRtcCA8IGR3UmVxdWVzdCAtIFRoaXMtPmxwYmlDdXItPmJpU2l6ZUltYWdlICYmIGJEZWNyZWFzZWRRdWFsKSB7CgkgIHRtcCA9IGR3Q3VyUXVhbDsKCSAgZHdDdXJRdWFsID0gKGR3TWluUXVhbCArIGR3TWF4UXVhbCkgLyAyOwoJICBkd01pblF1YWwgPSB0bXA7CgkgIGNvbnRpbnVlOwoJfQogICAgICB9IGVsc2UKCWJyZWFrOwogICAgfSBlbHNlIGlmIChkd01heFF1YWwgLSBkd01pblF1YWwgPD0gMSkgewogICAgICBicmVhazsKICAgIH0gZWxzZSB7CiAgICAgIGR3TWF4UXVhbCA9IGR3Q3VyUXVhbDsKCiAgICAgIGlmIChiRGVjcmVhc2VkUXVhbCB8fCBkd0N1clF1YWwgPT0gVGhpcy0+ZHdMYXN0UXVhbGl0eSkKCWR3Q3VyUXVhbCA9IChkd01pblF1YWwgKyBkd01heFF1YWwpIC8gMjsKICAgICAgZWxzZQoJRklYTUUoIjogbm8gbmV3IHF1YWxpdHkgY29tcHV0ZWQgbWluPSVsdSBjdXI9JWx1IG1heD0lbHUgbGFzdD0lbHVcbiIsCgkgICAgICBkd01pblF1YWwsIGR3Q3VyUXVhbCwgZHdNYXhRdWFsLCBUaGlzLT5kd0xhc3RRdWFsaXR5KTsKCiAgICAgIGJEZWNyZWFzZWRRdWFsID0gVFJVRTsKICAgIH0KICB9IHdoaWxlIChUUlVFKTsKCiAgLyogcmVtZW1iZXIgc29tZSB2YWx1ZXMgKi8KICBUaGlzLT5kd0xhc3RRdWFsaXR5ID0gZHdDdXJRdWFsOwogIFRoaXMtPmR3VW51c2VkQnl0ZXMgPSBkd1JlcXVlc3QgLSBUaGlzLT5scGJpQ3VyLT5iaVNpemVJbWFnZTsKICBpZiAoaWNtRmxhZ3MgJiBJQ0NPTVBSRVNTX0tFWUZSQU1FKQogICAgVGhpcy0+bExhc3RLZXkgPSBUaGlzLT5sQ3VycmVudDsKCiAgLyogRG9lcyB3ZSBtYW5hZ2UgcHJldmlvdXMgZnJhbWU/ICovCiAgaWYgKFRoaXMtPmxwUHJldiAhPSBOVUxMICYmIFRoaXMtPmxLZXlGcmFtZUV2ZXJ5ICE9IDEpCiAgICBJQ0RlY29tcHJlc3MoVGhpcy0+aGljLCAwLCBUaGlzLT5scGJpQ3VyLCBUaGlzLT5scEN1ciwKCQkgVGhpcy0+bHBiaVByZXYsIFRoaXMtPmxwUHJldik7CgogIHJldHVybiBBVklFUlJfT0s7Cn0KCnN0YXRpYyBIUkVTVUxUIEFWSUZJTEVfT3BlbkdldEZyYW1lKElBVklTdHJlYW1JbXBsICpUaGlzKQp7CiAgTFBCSVRNQVBJTkZPSEVBREVSIGxwYmk7CiAgRFdPUkQgICAgICAgICAgICAgIHNpemU7CgogIC8qIHByZS1jb25kaXRpb25zICovCiAgYXNzZXJ0KFRoaXMgIT0gTlVMTCk7CiAgYXNzZXJ0KFRoaXMtPnBTdHJlYW0gIT0gTlVMTCk7CiAgYXNzZXJ0KFRoaXMtPnBnID09IE5VTEwpOwoKICBUaGlzLT5wZyA9IEFWSVN0cmVhbUdldEZyYW1lT3BlbihUaGlzLT5wU3RyZWFtLCBOVUxMKTsKICBpZiAoVGhpcy0+cGcgPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfRVJST1I7CgogIC8qIFdoZW4gd2Ugb25seSBkZWNvbXByZXNzIHRoaXMgaXMgZW5vdWdoICovCiAgaWYgKFRoaXMtPnNJbmZvLmZjY0hhbmRsZXIgPT0gY29tcHR5cGVESUIpCiAgICByZXR1cm4gQVZJRVJSX09LOwoKICBhc3NlcnQoVGhpcy0+aGljICE9IE5VTEwpOwogIGFzc2VydChUaGlzLT5scGJpT3V0cHV0ID09IE5VTEwpOwoKICAvKiBnZXQgaW5wdXQgZm9ybWF0ICovCiAgbHBiaSA9IChMUEJJVE1BUElORk9IRUFERVIpQVZJU3RyZWFtR2V0RnJhbWUoVGhpcy0+cGcsIFRoaXMtPnNJbmZvLmR3U3RhcnQpOwogIGlmIChscGJpID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKCiAgLyogZ2V0IG1lbW9yeSBmb3Igb3V0cHV0IGZvcm1hdCAqLwogIHNpemUgPSBJQ0NvbXByZXNzR2V0Rm9ybWF0U2l6ZShUaGlzLT5oaWMsIGxwYmkpOwogIGlmICgoTE9ORylzaXplIDwgKExPTkcpc2l6ZW9mKEJJVE1BUElORk9IRUFERVIpKQogICAgcmV0dXJuIEFWSUVSUl9DT01QUkVTU09SOwogIFRoaXMtPmxwYmlPdXRwdXQgPSAoTFBCSVRNQVBJTkZPSEVBREVSKUdsb2JhbEFsbG9jUHRyKEdITkQsIHNpemUpOwogIGlmIChUaGlzLT5scGJpT3V0cHV0ID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKICBUaGlzLT5jYk91dHB1dCA9IHNpemU7CgogIGlmIChJQ0NvbXByZXNzR2V0Rm9ybWF0KFRoaXMtPmhpYywgbHBiaSwgVGhpcy0+bHBiaU91dHB1dCkgPCBTX09LKQogICAgcmV0dXJuIEFWSUVSUl9CQURGT1JNQVQ7CgogIC8qIHVwZGF0ZSBBVklTVFJFQU1JTkZPIHN0cnVjdHVyZSAqLwogIFRoaXMtPnNJbmZvLnJjRnJhbWUucmlnaHQgID0KICAgIFRoaXMtPnNJbmZvLnJjRnJhbWUubGVmdCArIFRoaXMtPmxwYmlPdXRwdXQtPmJpV2lkdGg7CiAgVGhpcy0+c0luZm8ucmNGcmFtZS5ib3R0b20gPQogICAgVGhpcy0+c0luZm8ucmNGcmFtZS50b3AgICsgVGhpcy0+bHBiaU91dHB1dC0+YmlIZWlnaHQ7CiAgVGhpcy0+c0luZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplID0KICAgIElDQ29tcHJlc3NHZXRTaXplKFRoaXMtPmhpYywgbHBiaSwgVGhpcy0+bHBiaU91dHB1dCk7CgogIC8qIHByZXBhcmUgY29kZWMgZm9yIGNvbXByZXNzaW9uICovCiAgaWYgKElDQ29tcHJlc3NCZWdpbihUaGlzLT5oaWMsIGxwYmksIFRoaXMtPmxwYmlPdXRwdXQpICE9IFNfT0spCiAgICByZXR1cm4gQVZJRVJSX0NPTVBSRVNTT1I7CgogIC8qIGFsbG9jYXRlIG1lbW9yeSBmb3IgY3VycmVudCBmcmFtZSAqLwogIHNpemUgKz0gVGhpcy0+c0luZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplOwogIFRoaXMtPmxwYmlDdXIgPSAoTFBCSVRNQVBJTkZPSEVBREVSKUdsb2JhbEFsbG9jUHRyKEdNRU1fTU9WRUFCTEUsIHNpemUpOwogIGlmIChUaGlzLT5scGJpQ3VyID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKICBtZW1jcHkoVGhpcy0+bHBiaUN1ciwgVGhpcy0+bHBiaU91dHB1dCwgVGhpcy0+Y2JPdXRwdXQpOwogIFRoaXMtPmxwQ3VyID0gRElCUFRSKFRoaXMtPmxwYmlDdXIpOwoKICAvKiBhbGxvY2F0ZSBtZW1vcnkgZm9yIGxhc3QgZnJhbWUgaWYgbmVlZGVkICovCiAgaWYgKFRoaXMtPmxLZXlGcmFtZUV2ZXJ5ICE9IDEgJiYKICAgICAgKFRoaXMtPmR3SUNNRmxhZ3MgJiBWSURDRl9GQVNUVEVNUE9SQUxDKSA9PSAwKSB7CiAgICBzaXplID0gSUNEZWNvbXByZXNzR2V0Rm9ybWF0U2l6ZShUaGlzLT5oaWMsIFRoaXMtPmxwYmlPdXRwdXQpOwogICAgVGhpcy0+bHBiaVByZXYgPSAoTFBCSVRNQVBJTkZPSEVBREVSKUdsb2JhbEFsbG9jUHRyKEdITkQsIHNpemUpOwogICAgaWYgKFRoaXMtPmxwYmlQcmV2ID09IE5VTEwpCiAgICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwogICAgaWYgKElDRGVjb21wcmVzc0dldEZvcm1hdChUaGlzLT5oaWMsIFRoaXMtPmxwYmlPdXRwdXQsIFRoaXMtPmxwYmlQcmV2KSA8IFNfT0spCiAgICAgIHJldHVybiBBVklFUlJfQ09NUFJFU1NPUjsKCiAgICBpZiAoVGhpcy0+bHBiaVByZXYtPmJpU2l6ZUltYWdlID09IDApIHsKICAgICAgVGhpcy0+bHBiaVByZXYtPmJpU2l6ZUltYWdlID0KCURJQldJRFRIQllURVMoKlRoaXMtPmxwYmlQcmV2KSAqIFRoaXMtPmxwYmlQcmV2LT5iaUhlaWdodDsKICAgIH0KCiAgICAvKiBnZXQgbWVtb3J5IGZvciBmb3JtYXQgYW5kIHBpY3R1cmUgKi8KICAgIHNpemUgKz0gVGhpcy0+bHBiaVByZXYtPmJpU2l6ZUltYWdlOwogICAgVGhpcy0+bHBiaVByZXYgPQogICAgICAoTFBCSVRNQVBJTkZPSEVBREVSKUdsb2JhbFJlQWxsb2NQdHIoVGhpcy0+bHBiaVByZXYsc2l6ZSxHTUVNX01PVkVBQkxFKTsKICAgIGlmIChUaGlzLT5scGJpUHJldiA9PSBOVUxMKQogICAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgIFRoaXMtPmxwUHJldiA9IERJQlBUUihUaGlzLT5scGJpUHJldik7CgogICAgLyogcHJlcGFyZSBjb2RlYyBhbHNvIGZvciBkZWNvbXByZXNzaW9uICovCiAgICBpZiAoSUNEZWNvbXByZXNzQmVnaW4oVGhpcy0+aGljLFRoaXMtPmxwYmlPdXRwdXQsVGhpcy0+bHBiaVByZXYpICE9IFNfT0spCiAgICAgIHJldHVybiBBVklFUlJfQ09NUFJFU1NPUjsKICB9CgogIHJldHVybiBBVklFUlJfT0s7Cn0K