LyoKICogQ29weXJpZ2h0IDIwMDIgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CgojaW5jbHVkZSAid2luYmFzZS5oIgojaW5jbHVkZSAid2ludXNlci5oIgojaW5jbHVkZSAid2lubmxzLmgiCiNpbmNsdWRlICJ3aW5lcnJvci5oIgojaW5jbHVkZSAid2luZG93c3guaCIKI2luY2x1ZGUgIm1tc3lzdGVtLmgiCiNpbmNsdWRlICJ2ZncuaCIKI2luY2x1ZGUgIm1zYWNtLmgiCgojaW5jbHVkZSAiYXZpZmlsZV9wcml2YXRlLmgiCgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKV0lORV9ERUZBVUxUX0RFQlVHX0NIQU5ORUwoYXZpZmlsZSk7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuUXVlcnlJbnRlcmZhY2UoSUFWSVN0cmVhbSppZmFjZSxSRUZJSUQgcmVmaWlkLExQVk9JRCAqb2JqKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIEFDTVN0cmVhbV9mbkFkZFJlZihJQVZJU3RyZWFtKmlmYWNlKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIEFDTVN0cmVhbV9mblJlbGVhc2UoSUFWSVN0cmVhbSogaWZhY2UpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuQ3JlYXRlKElBVklTdHJlYW0qaWZhY2UsTFBBUkFNIGxQYXJhbTEsTFBBUkFNIGxQYXJhbTIpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuSW5mbyhJQVZJU3RyZWFtKmlmYWNlLEFWSVNUUkVBTUlORk9XICpwc2ksTE9ORyBzaXplKTsKc3RhdGljIExPTkcgICAgV0lOQVBJIEFDTVN0cmVhbV9mbkZpbmRTYW1wbGUoSUFWSVN0cmVhbSppZmFjZSxMT05HIHBvcyxMT05HIGZsYWdzKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIEFDTVN0cmVhbV9mblJlYWRGb3JtYXQoSUFWSVN0cmVhbSppZmFjZSxMT05HIHBvcyxMUFZPSUQgZm9ybWF0LExPTkcgKmZvcm1hdHNpemUpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuU2V0Rm9ybWF0KElBVklTdHJlYW0qaWZhY2UsTE9ORyBwb3MsTFBWT0lEIGZvcm1hdCxMT05HIGZvcm1hdHNpemUpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuUmVhZChJQVZJU3RyZWFtKmlmYWNlLExPTkcgc3RhcnQsTE9ORyBzYW1wbGVzLExQVk9JRCBidWZmZXIsTE9ORyBidWZmZXJzaXplLExPTkcgKmJ5dGVzcmVhZCxMT05HICpzYW1wbGVzcmVhZCk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBBQ01TdHJlYW1fZm5Xcml0ZShJQVZJU3RyZWFtKmlmYWNlLExPTkcgc3RhcnQsTE9ORyBzYW1wbGVzLExQVk9JRCBidWZmZXIsTE9ORyBidWZmZXJzaXplLERXT1JEIGZsYWdzLExPTkcgKnNhbXB3cml0dGVuLExPTkcgKmJ5dGVzd3JpdHRlbik7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBBQ01TdHJlYW1fZm5EZWxldGUoSUFWSVN0cmVhbSppZmFjZSxMT05HIHN0YXJ0LExPTkcgc2FtcGxlcyk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBBQ01TdHJlYW1fZm5SZWFkRGF0YShJQVZJU3RyZWFtKmlmYWNlLERXT1JEIGZjYyxMUFZPSUQgbHAsTE9ORyAqbHByZWFkKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIEFDTVN0cmVhbV9mbldyaXRlRGF0YShJQVZJU3RyZWFtKmlmYWNlLERXT1JEIGZjYyxMUFZPSUQgbHAsTE9ORyBzaXplKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIEFDTVN0cmVhbV9mblNldEluZm8oSUFWSVN0cmVhbSppZmFjZSxBVklTVFJFQU1JTkZPVyppbmZvLExPTkcgaW5mb2xlbik7CgpzdHJ1Y3QgSUNPTV9WVEFCTEUoSUFWSVN0cmVhbSkgaWFjbXN0ID0gewogIElDT01fTVNWVEFCTEVfQ09NUEFUX0R1bW15UlRUSVZBTFVFCiAgQUNNU3RyZWFtX2ZuUXVlcnlJbnRlcmZhY2UsCiAgQUNNU3RyZWFtX2ZuQWRkUmVmLAogIEFDTVN0cmVhbV9mblJlbGVhc2UsCiAgQUNNU3RyZWFtX2ZuQ3JlYXRlLAogIEFDTVN0cmVhbV9mbkluZm8sCiAgQUNNU3RyZWFtX2ZuRmluZFNhbXBsZSwKICBBQ01TdHJlYW1fZm5SZWFkRm9ybWF0LAogIEFDTVN0cmVhbV9mblNldEZvcm1hdCwKICBBQ01TdHJlYW1fZm5SZWFkLAogIEFDTVN0cmVhbV9mbldyaXRlLAogIEFDTVN0cmVhbV9mbkRlbGV0ZSwKICBBQ01TdHJlYW1fZm5SZWFkRGF0YSwKICBBQ01TdHJlYW1fZm5Xcml0ZURhdGEsCiAgQUNNU3RyZWFtX2ZuU2V0SW5mbwp9OwoKdHlwZWRlZiBzdHJ1Y3QgX0lBVklTdHJlYW1JbXBsIHsKICAvKiBJVW5rbm93biBzdHVmZiAqLwogIElDT01fVkZJRUxEKElBVklTdHJlYW0pOwogIERXT1JECQkgIHJlZjsKCiAgLyogSUFWSVN0cmVhbSBzdHVmZiAqLwogIFBBVklTVFJFQU0gICAgICBwU3RyZWFtOwogIEFWSVNUUkVBTUlORk9XICBzSW5mbzsKCiAgSEFDTVNUUkVBTSAgICAgIGhhczsKCiAgTFBXQVZFRk9STUFURVggIGxwSW5Gb3JtYXQ7CiAgTE9ORyAgICAgICAgICAgIGNiSW5Gb3JtYXQ7CgogIExQV0FWRUZPUk1BVEVYICBscE91dEZvcm1hdDsKICBMT05HICAgICAgICAgICAgY2JPdXRGb3JtYXQ7CgogIEFDTVNUUkVBTUhFQURFUiBhY21TdHJlYW1IZHI7Cn0gSUFWSVN0cmVhbUltcGw7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgojZGVmaW5lIENPTlZFUlRfU1RSRUFNX3RvX1RISVMoYSkgeyBcCiAgICAgICAgICAgYWNtU3RyZWFtU2l6ZShUaGlzLT5oYXMsKGEpKlRoaXMtPmxwSW5Gb3JtYXQtPm5CbG9ja0FsaWduLFwKICAgICAgICAgICAgICAgICAgICAgICAgICYoYSksIEFDTV9TVFJFQU1TSVpFRl9TT1VSQ0UpOyBcCiAgICAgICAgICAgKGEpIC89IFRoaXMtPmxwT3V0Rm9ybWF0LT5uQmxvY2tBbGlnbjsgfQojZGVmaW5lIENPTlZFUlRfVEhJU190b19TVFJFQU0oYSkgeyBcCiAgICAgICAgICAgYWNtU3RyZWFtU2l6ZShUaGlzLT5oYXMsKGEpKlRoaXMtPmxwT3V0Rm9ybWF0LT5uQmxvY2tBbGlnbixcCiAgICAgICAgICAgICAgICAgICAgICAgICAmKGEpLCBBQ01fU1RSRUFNU0laRUZfREVTVElOQVRJT04pOyBcCiAgICAgICAgICAgKGEpIC89IFRoaXMtPmxwSW5Gb3JtYXQtPm5CbG9ja0FsaWduOyB9CgpzdGF0aWMgSFJFU1VMVCBBVklGSUxFX09wZW5Db21wcmVzc29yKElBVklTdHJlYW1JbXBsICpUaGlzKTsKCkhSRVNVTFQgQVZJRklMRV9DcmVhdGVBQ01TdHJlYW0oUkVGSUlEIHJpaWQsIExQVk9JRCAqcHB2KQp7CiAgSUFWSVN0cmVhbUltcGwgKnBzdHJlYW07CiAgSFJFU1VMVCAgICAgICAgIGhyOwoKICBhc3NlcnQocmlpZCAhPSBOVUxMICYmIHBwdiAhPSBOVUxMKTsKCiAgKnBwdiA9IE5VTEw7CgogIHBzdHJlYW0gPSAoSUFWSVN0cmVhbUltcGwqKUxvY2FsQWxsb2MoTFBUUiwgc2l6ZW9mKElBVklTdHJlYW1JbXBsKSk7CiAgaWYgKHBzdHJlYW0gPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwoKICBJQ09NX1ZUQkwocHN0cmVhbSkgID0gJmlhY21zdDsKCiAgaHIgPSBJVW5rbm93bl9RdWVyeUludGVyZmFjZSgoSVVua25vd24qKXBzdHJlYW0sIHJpaWQsIHBwdik7CiAgaWYgKEZBSUxFRChocikpCiAgICBMb2NhbEZyZWUoKEhMT0NBTClwc3RyZWFtKTsKCiAgcmV0dXJuIGhyOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuUXVlcnlJbnRlcmZhY2UoSUFWSVN0cmVhbSAqaWZhY2UsCgkJCQkJCSAgUkVGSUlEIHJlZmlpZCwgTFBWT0lEICpvYmopCnsKICBJQ09NX1RISVMoSUFWSVN0cmVhbUltcGwsaWZhY2UpOwoKICBUUkFDRSgiKCVwLCVzLCVwKVxuIiwgaWZhY2UsIGRlYnVnc3RyX2d1aWQocmVmaWlkKSwgb2JqKTsKCiAgaWYgKElzRXF1YWxHVUlEKCZJSURfSVVua25vd24sIHJlZmlpZCkgfHwKICAgICAgSXNFcXVhbEdVSUQoJklJRF9JQVZJU3RyZWFtLCByZWZpaWQpKSB7CiAgICAqb2JqID0gVGhpczsKICAgIElBVklTdHJlYW1fQWRkUmVmKGlmYWNlKTsKCiAgICByZXR1cm4gU19PSzsKICB9CgogIHJldHVybiBPTEVfRV9FTlVNX05PTU9SRTsKfQoKc3RhdGljIFVMT05HIFdJTkFQSSBBQ01TdHJlYW1fZm5BZGRSZWYoSUFWSVN0cmVhbSAqaWZhY2UpCnsKICBJQ09NX1RISVMoSUFWSVN0cmVhbUltcGwsaWZhY2UpOwoKICBUUkFDRSgiKCVwKSAtPiAlbGRcbiIsIGlmYWNlLCBUaGlzLT5yZWYgKyAxKTsKCiAgLyogYWxzbyBhZGQgcmVmZXJlbmNlIHRvIHRoZSBuZXN0ZWQgc3RyZWFtICovCiAgaWYgKFRoaXMtPnBTdHJlYW0gIT0gTlVMTCkKICAgIElBVklTdHJlYW1fQWRkUmVmKFRoaXMtPnBTdHJlYW0pOwoKICByZXR1cm4gKysoVGhpcy0+cmVmKTsKfQoKc3RhdGljIFVMT05HIFdJTkFQSSBBQ01TdHJlYW1fZm5SZWxlYXNlKElBVklTdHJlYW0qIGlmYWNlKQp7CiAgSUNPTV9USElTKElBVklTdHJlYW1JbXBsLGlmYWNlKTsKCiAgVFJBQ0UoIiglcCkgLT4gJWxkXG4iLCBpZmFjZSwgVGhpcy0+cmVmIC0gMSk7CgogIGlmIChUaGlzLT5yZWYgPT0gMCkgewogICAgLyogZGVzdHJ1Y3QgKi8KICAgIGlmIChUaGlzLT5oYXMgIT0gTlVMTCkgewogICAgICBpZiAoVGhpcy0+YWNtU3RyZWFtSGRyLmZkd1N0YXR1cyAmIEFDTVNUUkVBTUhFQURFUl9TVEFUVVNGX1BSRVBBUkVEKQoJYWNtU3RyZWFtVW5wcmVwYXJlSGVhZGVyKFRoaXMtPmhhcywgJlRoaXMtPmFjbVN0cmVhbUhkciwgMCk7CiAgICAgIGFjbVN0cmVhbUNsb3NlKFRoaXMtPmhhcywgMCk7CiAgICAgIFRoaXMtPmhhcyA9IE5VTEw7CiAgICB9CiAgICBpZiAoVGhpcy0+YWNtU3RyZWFtSGRyLnBiU3JjICE9IE5VTEwpIHsKICAgICAgR2xvYmFsRnJlZVB0cihUaGlzLT5hY21TdHJlYW1IZHIucGJTcmMpOwogICAgICBUaGlzLT5hY21TdHJlYW1IZHIucGJTcmMgPSBOVUxMOwogICAgfQogICAgaWYgKFRoaXMtPmFjbVN0cmVhbUhkci5wYkRzdCAhPSBOVUxMKSB7CiAgICAgIEdsb2JhbEZyZWVQdHIoVGhpcy0+YWNtU3RyZWFtSGRyLnBiRHN0KTsKICAgICAgVGhpcy0+YWNtU3RyZWFtSGRyLnBiRHN0ID0gTlVMTDsKICAgIH0KICAgIGlmIChUaGlzLT5scEluRm9ybWF0ICE9IE5VTEwpIHsKICAgICAgR2xvYmFsRnJlZVB0cihUaGlzLT5scEluRm9ybWF0KTsKICAgICAgVGhpcy0+bHBJbkZvcm1hdCA9IE5VTEw7CiAgICAgIFRoaXMtPmNiSW5Gb3JtYXQgPSAwOwogICAgfQogICAgaWYgKFRoaXMtPmxwT3V0Rm9ybWF0ICE9IE5VTEwpIHsKICAgICAgR2xvYmFsRnJlZVB0cihUaGlzLT5scE91dEZvcm1hdCk7CiAgICAgIFRoaXMtPmxwT3V0Rm9ybWF0ID0gTlVMTDsKICAgICAgVGhpcy0+Y2JPdXRGb3JtYXQgPSAwOwogICAgfQogICAgaWYgKFRoaXMtPnBTdHJlYW0gIT0gTlVMTCkgewogICAgICBJQVZJU3RyZWFtX1JlbGVhc2UoVGhpcy0+cFN0cmVhbSk7CiAgICAgIFRoaXMtPnBTdHJlYW0gPSBOVUxMOwogICAgfQogICAgTG9jYWxGcmVlKChITE9DQUwpVGhpcyk7CgogICAgcmV0dXJuIDA7CiAgfQoKICAvKiBhbHNvIHJlbGVhc2UgcmVmZXJlbmNlIHRvIHRoZSBuZXN0ZWQgc3RyZWFtICovCiAgaWYgKFRoaXMtPnBTdHJlYW0gIT0gTlVMTCkKICAgIElBVklTdHJlYW1fUmVsZWFzZShUaGlzLT5wU3RyZWFtKTsKCiAgcmV0dXJuIC0tVGhpcy0+cmVmOwp9CgovKiBsUGFyYW0xOiBQQVZJU1RSRUFNCiAqIGxQYXJhbTI6IExQQVZJQ09NUFJFU1NPUFRJT05TIC0tIGV2ZW4gaWYgZG9jJ3Mgc2F5IExQV0FWRUZPUk1BVAogKi8Kc3RhdGljIEhSRVNVTFQgV0lOQVBJIEFDTVN0cmVhbV9mbkNyZWF0ZShJQVZJU3RyZWFtICppZmFjZSwgTFBBUkFNIGxQYXJhbTEsCgkJCQkJICBMUEFSQU0gbFBhcmFtMikKewogIElDT01fVEhJUyhJQVZJU3RyZWFtSW1wbCxpZmFjZSk7CgogIFRSQUNFKCIoJXAsMHglMDhsWCwweCUwOGxYKVxuIiwgaWZhY2UsIGxQYXJhbTEsIGxQYXJhbTIpOwoKICAvKiBjaGVjayBmb3Igc3dhcHBlZCBwYXJhbWV0ZXJzICovCiAgaWYgKChMUFZPSUQpbFBhcmFtMSAhPSBOVUxMICYmCiAgICAgICgoTFBBVklDT01QUkVTU09QVElPTlMpbFBhcmFtMSktPmZjY1R5cGUgPT0gc3RyZWFtdHlwZUFVRElPKSB7CiAgICByZWdpc3RlciBMUEFSQU0gdG1wID0gbFBhcmFtMTsKCiAgICBsUGFyYW0xID0gbFBhcmFtMjsKICAgIGxQYXJhbTIgPSB0bXA7CiAgfQoKICBpZiAoKExQVk9JRClsUGFyYW0xID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX0JBRFBBUkFNOwoKICBJQVZJU3RyZWFtX0luZm8oKFBBVklTVFJFQU0pbFBhcmFtMSwgJlRoaXMtPnNJbmZvLCBzaXplb2YoVGhpcy0+c0luZm8pKTsKICBpZiAoVGhpcy0+c0luZm8uZmNjVHlwZSAhPSBzdHJlYW10eXBlQVVESU8pCiAgICByZXR1cm4gQVZJRVJSX0VSUk9SOyAvKiBlcnJvciBpbiByZWdpc3RyeSBvciBBVklNYWtlQ29tcHJlc3NlZFN0cmVhbSAqLwoKICBUaGlzLT5zSW5mby5mY2NIYW5kbGVyID0gMDsgLyogYmUgcGFyYW5vaWQgKi8KCiAgLyogRklYTUU6IGNoZWNrIEFDTSB2ZXJzaW9uPyBXaGljaCB2ZXJzaW9uIGRvZXMgd2UgbmVlZD8gKi8KCiAgaWYgKChMUFZPSUQpbFBhcmFtMiAhPSBOVUxMKSB7CiAgICAvKiBXZSBvbmx5IG5lZWQgdGhlIGZvcm1hdCBmcm9tIHRoZSBjb21wcmVzcy1vcHRpb25zICovCiAgICBpZiAoKChMUEFWSUNPTVBSRVNTT1BUSU9OUylsUGFyYW0yKS0+ZmNjVHlwZSA9PSBzdHJlYW10eXBlQVVESU8pCiAgICAgIGxQYXJhbTIgPSAoTFBBUkFNKSgoTFBBVklDT01QUkVTU09QVElPTlMpbFBhcmFtMiktPmxwRm9ybWF0OwoKICAgIGlmICgoKExQV0FWRUZPUk1BVEVYKWxQYXJhbTIpLT53Rm9ybWF0VGFnICE9IFdBVkVfRk9STUFUX1BDTSkKICAgICAgVGhpcy0+Y2JPdXRGb3JtYXQgPSBzaXplb2YoV0FWRUZPUk1BVEVYKSArICgoTFBXQVZFRk9STUFURVgpbFBhcmFtMiktPmNiU2l6ZTsKICAgIGVsc2UKICAgICAgVGhpcy0+Y2JPdXRGb3JtYXQgPSBzaXplb2YoUENNV0FWRUZPUk1BVCk7CgogICAgVGhpcy0+bHBPdXRGb3JtYXQgPSAoTFBXQVZFRk9STUFURVgpR2xvYmFsQWxsb2NQdHIoR0hORCwgVGhpcy0+Y2JPdXRGb3JtYXQpOwogICAgaWYgKFRoaXMtPmxwT3V0Rm9ybWF0ID09IE5VTEwpCiAgICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwoKICAgIG1lbWNweShUaGlzLT5scE91dEZvcm1hdCwgKExQVk9JRClsUGFyYW0yLCBUaGlzLT5jYk91dEZvcm1hdCk7CiAgfSBlbHNlIHsKICAgIFRoaXMtPmxwT3V0Rm9ybWF0ID0gTlVMTDsKICAgIFRoaXMtPmNiT3V0Rm9ybWF0ID0gMDsKICB9CgogIFRoaXMtPnBTdHJlYW0gPSAoUEFWSVNUUkVBTSlsUGFyYW0xOwogIElBVklTdHJlYW1fQWRkUmVmKFRoaXMtPnBTdHJlYW0pOwoKICByZXR1cm4gQVZJRVJSX09LOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuSW5mbyhJQVZJU3RyZWFtICppZmFjZSxMUEFWSVNUUkVBTUlORk9XIHBzaSwKCQkJCQlMT05HIHNpemUpCnsKICBJQ09NX1RISVMoSUFWSVN0cmVhbUltcGwsaWZhY2UpOwoKICBUUkFDRSgiKCVwLCVwLCVsZClcbiIsIGlmYWNlLCBwc2ksIHNpemUpOwoKICBpZiAocHNpID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX0JBRFBBUkFNOwogIGlmIChzaXplIDwgMCkKICAgIHJldHVybiBBVklFUlJfQkFEU0laRTsKCiAgLyogTmVlZCBjb2RlYyB0byBjb3JyZWN0IHNvbWUgdmFsdWVzIGluIHN0cnVjdHVyZSAqLwogIGlmIChUaGlzLT5oYXMgPT0gTlVMTCkgewogICAgSFJFU1VMVCBociA9IEFWSUZJTEVfT3BlbkNvbXByZXNzb3IoVGhpcyk7CgogICAgaWYgKEZBSUxFRChocikpCiAgICAgIHJldHVybiBocjsKICB9CgogIG1lbWNweShwc2ksICZUaGlzLT5zSW5mbywgbWluKHNpemUsIHNpemVvZihUaGlzLT5zSW5mbykpKTsKCiAgaWYgKHNpemUgPCBzaXplb2YoVGhpcy0+c0luZm8pKQogICAgcmV0dXJuIEFWSUVSUl9CVUZGRVJUT09TTUFMTDsKICByZXR1cm4gQVZJRVJSX09LOwp9CgpzdGF0aWMgTE9ORyBXSU5BUEkgQUNNU3RyZWFtX2ZuRmluZFNhbXBsZShJQVZJU3RyZWFtICppZmFjZSwgTE9ORyBwb3MsCgkJCQkJICAgTE9ORyBmbGFncykKewogIElDT01fVEhJUyhJQVZJU3RyZWFtSW1wbCxpZmFjZSk7CgogIFRSQUNFKCIoJXAsJWxkLDB4JTA4bFgpXG4iLGlmYWNlLHBvcyxmbGFncyk7CgogIGlmIChmbGFncyAmIEZJTkRfRlJPTV9TVEFSVCkgewogICAgcG9zID0gVGhpcy0+c0luZm8uZHdTdGFydDsKICAgIGZsYWdzICY9IH4oRklORF9GUk9NX1NUQVJUfEZJTkRfUFJFVik7CiAgICBmbGFncyB8PSBGSU5EX05FWFQ7CiAgfQoKICAvKiBjb252ZXJ0IHBvcyBmcm9tIG91ciAnc3BhY2UnIHRvIFRoaXMtPnBTdHJlYW0ncyBvbmUgKi8KICBDT05WRVJUX1RISVNfdG9fU1RSRUFNKHBvcyk7CgogIC8qIGFzayBzdHJlYW0gKi8KICBwb3MgPSBJQVZJU3RyZWFtX0ZpbmRTYW1wbGUoVGhpcy0+cFN0cmVhbSwgcG9zLCBmbGFncyk7CgogIGlmIChwb3MgIT0gLTEpIHsKICAgIC8qIGNvbnZlcnQgcG9zIGJhY2sgdG8gb3VyICdzcGFjZScgaWYgaXQncyBubyBzaXplIG9yIHBoeXNpY2FsIHBvcyAqLwogICAgaWYgKChmbGFncyAmIEZJTkRfUkVUKSA9PSAwKQogICAgICBDT05WRVJUX1NUUkVBTV90b19USElTKHBvcyk7CiAgfQoKICByZXR1cm4gcG9zOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuUmVhZEZvcm1hdChJQVZJU3RyZWFtICppZmFjZSwgTE9ORyBwb3MsCgkJCQkJICAgICAgTFBWT0lEIGZvcm1hdCwgTE9ORyAqZm9ybWF0c2l6ZSkKewogIElDT01fVEhJUyhJQVZJU3RyZWFtSW1wbCxpZmFjZSk7CgogIFRSQUNFKCIoJXAsJWxkLCVwLCVwKVxuIiwgaWZhY2UsIHBvcywgZm9ybWF0LCBmb3JtYXRzaXplKTsKCiAgaWYgKGZvcm1hdHNpemUgPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfQkFEUEFSQU07CgogIGlmIChUaGlzLT5oYXMgPT0gTlVMTCkgewogICAgSFJFU1VMVCBociA9IEFWSUZJTEVfT3BlbkNvbXByZXNzb3IoVGhpcyk7CgogICAgaWYgKEZBSUxFRChocikpCiAgICAgIHJldHVybiBocjsKICB9CgogIC8qIG9ubHkgaW50ZXJlc3RlZCBpbiBuZWVkZWQgYnVmZmVyc2l6ZT8gKi8KICBpZiAoZm9ybWF0ID09IE5VTEwgfHwgKmZvcm1hdHNpemUgPD0gMCkgewogICAgKmZvcm1hdHNpemUgPSBUaGlzLT5jYk91dEZvcm1hdDsKCiAgICByZXR1cm4gQVZJRVJSX09LOwogIH0KCiAgLyogY29weSBpbml0aWFsIGZvcm1hdCAob25seSBhcyBtdWNoIGFzIHdpbGwgZml0KSAqLwogIG1lbWNweShmb3JtYXQsIFRoaXMtPmxwT3V0Rm9ybWF0LCBtaW4oKmZvcm1hdHNpemUsIFRoaXMtPmNiT3V0Rm9ybWF0KSk7CiAgaWYgKCpmb3JtYXRzaXplIDwgVGhpcy0+Y2JPdXRGb3JtYXQpIHsKICAgICpmb3JtYXRzaXplID0gVGhpcy0+Y2JPdXRGb3JtYXQ7CiAgICByZXR1cm4gQVZJRVJSX0JVRkZFUlRPT1NNQUxMOwogIH0KCiAgKmZvcm1hdHNpemUgPSBUaGlzLT5jYk91dEZvcm1hdDsKICByZXR1cm4gQVZJRVJSX09LOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuU2V0Rm9ybWF0KElBVklTdHJlYW0gKmlmYWNlLCBMT05HIHBvcywKCQkJCQkgICAgIExQVk9JRCBmb3JtYXQsIExPTkcgZm9ybWF0c2l6ZSkKewogIElDT01fVEhJUyhJQVZJU3RyZWFtSW1wbCxpZmFjZSk7CgogIEhSRVNVTFQgaHI7CgogIFRSQUNFKCIoJXAsJWxkLCVwLCVsZClcbiIsIGlmYWNlLCBwb3MsIGZvcm1hdCwgZm9ybWF0c2l6ZSk7CgogIC8qIGNoZWNrIHBhcmFtZXRlcnMgKi8KICBpZiAoZm9ybWF0ID09IE5VTEwgfHwgZm9ybWF0c2l6ZSA8PSAwKQogICAgcmV0dXJuIEFWSUVSUl9CQURQQVJBTTsKCiAgLyogSW5wdXQgZm9ybWF0IGFscmVhZHkga25vd24/CiAgICogQ2hhbmdpbmcgaXMgdW5zdXBwb3J0ZWQsIGJ1dCBiZSBxdWlldCBpZiBpdCdzIHRoZSBzYW1lICovCiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQgIT0gTlVMTCkgewogICAgaWYgKFRoaXMtPmNiSW5Gb3JtYXQgIT0gZm9ybWF0c2l6ZSB8fAoJbWVtY21wKGZvcm1hdCwgVGhpcy0+bHBJbkZvcm1hdCwgZm9ybWF0c2l6ZSkgIT0gMCkKICAgICAgcmV0dXJuIEFWSUVSUl9VTlNVUFBPUlRFRDsKCiAgICByZXR1cm4gQVZJRVJSX09LOwogIH0KCiAgLyogRG9lcyB0aGUgbmVzdGVkIHN0cmVhbSBzdXBwb3J0IHdyaXRpbmc/ICovCiAgaWYgKChUaGlzLT5zSW5mby5kd0NhcHMgJiBBVklGSUxFQ0FQU19DQU5XUklURSkgPT0gMCkKICAgIHJldHVybiBBVklFUlJfUkVBRE9OTFk7CgogIFRoaXMtPmxwSW5Gb3JtYXQgPSAoTFBXQVZFRk9STUFURVgpR2xvYmFsQWxsb2NQdHIoR01FTV9NT1ZFQUJMRSwgZm9ybWF0c2l6ZSk7CiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQgPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwogIFRoaXMtPmNiSW5Gb3JtYXQgPSBmb3JtYXRzaXplOwogIG1lbWNweShUaGlzLT5scEluRm9ybWF0LCBmb3JtYXQsIGZvcm1hdHNpemUpOwoKICAvKiBpbml0aWFsaXplIGZvcm1hdHMgYW5kIGdldCBjb21wcmVzc29yICovCiAgaHIgPSBBVklGSUxFX09wZW5Db21wcmVzc29yKFRoaXMpOwogIGlmIChGQUlMRUQoaHIpKQogICAgcmV0dXJuIGhyOwoKICBDT05WRVJUX1RISVNfdG9fU1RSRUFNKHBvcyk7CgogIC8qIHRlbGwgdGhlIG5lc3RlZCBzdHJlYW0gdGhlIG5ldyBmb3JtYXQgKi8KICByZXR1cm4gSUFWSVN0cmVhbV9TZXRGb3JtYXQoVGhpcy0+cFN0cmVhbSwgcG9zLCBUaGlzLT5scE91dEZvcm1hdCwKCQkJICAgICAgVGhpcy0+Y2JPdXRGb3JtYXQpOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuUmVhZChJQVZJU3RyZWFtICppZmFjZSwgTE9ORyBzdGFydCwKCQkJCQlMT05HIHNhbXBsZXMsIExQVk9JRCBidWZmZXIsCgkJCQkJTE9ORyBidWZmZXJzaXplLCBMUExPTkcgYnl0ZXNyZWFkLAoJCQkJCUxQTE9ORyBzYW1wbGVzcmVhZCkKewogIElDT01fVEhJUyhJQVZJU3RyZWFtSW1wbCxpZmFjZSk7CgogIEhSRVNVTFQgaHI7CiAgTE9ORyAgICBzaXplOwoKICBUUkFDRSgiKCVwLCVsZCwlbGQsJXAsJWxkLCVwLCVwKVxuIiwgaWZhY2UsIHN0YXJ0LCBzYW1wbGVzLCBidWZmZXIsCiAJYnVmZmVyc2l6ZSwgYnl0ZXNyZWFkLCBzYW1wbGVzcmVhZCk7CgogIC8qIGNsZWFyIHJldHVybiBwYXJhbWV0ZXJzIGlmIGdpdmVuICovCiAgaWYgKGJ5dGVzcmVhZCAhPSBOVUxMKQogICAgKmJ5dGVzcmVhZCA9IDA7CiAgaWYgKHNhbXBsZXNyZWFkICE9IE5VTEwpCiAgICAqc2FtcGxlc3JlYWQgPSAwOwoKICAvKiBEbyB3ZSBoYXZlIG91ciBjb21wcmVzc29yPyAqLwogIGlmIChUaGlzLT5oYXMgPT0gTlVMTCkgewogICAgaHIgPSBBVklGSUxFX09wZW5Db21wcmVzc29yKFRoaXMpOwoKICAgIGlmIChGQUlMRUQoaHIpKQogICAgICByZXR1cm4gaHI7CiAgfQoKICAvKiBvbmx5IG5lZWQgdG8gcGFzcyB0aHJvdWdoPyAqLwogIGlmIChUaGlzLT5jYkluRm9ybWF0ID09IFRoaXMtPmNiT3V0Rm9ybWF0ICYmCiAgICAgIG1lbWNtcChUaGlzLT5scEluRm9ybWF0LCBUaGlzLT5scE91dEZvcm1hdCwgVGhpcy0+Y2JJbkZvcm1hdCkgPT0gMCkgewogICAgcmV0dXJuIElBVklTdHJlYW1fUmVhZChUaGlzLT5wU3RyZWFtLCBzdGFydCwgc2FtcGxlcywgYnVmZmVyLCBidWZmZXJzaXplLAoJCQkgICBieXRlc3JlYWQsIHNhbXBsZXNyZWFkKTsKICB9CgogIC8qIHJlYWQgYXMgbXVjaCBhcyBmaXQ/ICovCiAgaWYgKHNhbXBsZXMgPT0gLTEpCiAgICBzYW1wbGVzID0gYnVmZmVyc2l6ZSAvIFRoaXMtPmxwT3V0Rm9ybWF0LT5uQmxvY2tBbGlnbjsKICAvKiBsaW1pdCB0byBidWZmZXJzaXplICovCiAgaWYgKHNhbXBsZXMgKiBUaGlzLT5scE91dEZvcm1hdC0+bkJsb2NrQWxpZ24gPiBidWZmZXJzaXplKQogICAgc2FtcGxlcyA9IGJ1ZmZlcnNpemUgLyBUaGlzLT5scE91dEZvcm1hdC0+bkJsb2NrQWxpZ247CgogIC8qIG9ubHkgcmV0dXJuIG5lZWRlZCBzaXplPyAqLwogIGlmIChidWZmZXIgPT0gTlVMTCB8fCBidWZmZXJzaXplIDw9IDAgfHwgc2FtcGxlcyA9PSAwKSB7CiAgICBpZiAoYnl0ZXNyZWFkID09IE5VTEwgJiYgc2FtcGxlc3JlYWQgPT0gTlVMTCkKICAgICAgcmV0dXJuIEFWSUVSUl9CQURQQVJBTTsKCiAgICBpZiAoYnl0ZXNyZWFkICE9IE5VTEwpCiAgICAgICpieXRlc3JlYWQgPSBzYW1wbGVzICogVGhpcy0+bHBPdXRGb3JtYXQtPm5CbG9ja0FsaWduOwogICAgaWYgKHNhbXBsZXNyZWFkICE9IE5VTEwpCiAgICAgICpzYW1wbGVzcmVhZCA9IHNhbXBsZXM7CgogICAgcmV0dXJuIEFWSUVSUl9PSzsKICB9CgogIC8qIG1hcCBvdXIgcG9zaXRpb25zIHRvIHBTdHJlYW0gcG9zaXRpb25zICovCiAgQ09OVkVSVF9USElTX3RvX1NUUkVBTShzdGFydCk7CgogIC8qIG91ciBuZWVkZWQgaW50ZXJuYWwgYnVmZmVyc2l6ZSAqLwogIHNpemUgPSBzYW1wbGVzICogVGhpcy0+bHBJbkZvcm1hdC0+bkJsb2NrQWxpZ247CgogIC8qIE5lZWQgdG8gZnJlZSBkZXN0aW5hdGlvbiBidWZmZXIgdXNlZCBmb3Igd3JpdGluZz8gKi8KICBpZiAoVGhpcy0+YWNtU3RyZWFtSGRyLnBiRHN0ICE9IE5VTEwpIHsKICAgIEdsb2JhbEZyZWVQdHIoVGhpcy0+YWNtU3RyZWFtSGRyLnBiRHN0KTsKICAgIFRoaXMtPmFjbVN0cmVhbUhkci5wYkRzdCAgICAgPSBOVUxMOwogICAgVGhpcy0+YWNtU3RyZWFtSGRyLmR3RHN0VXNlciA9IDA7CiAgfQoKICAvKiBuZWVkIGJpZ2dlciBzb3VyY2UgYnVmZmVyPyAqLwogIGlmIChUaGlzLT5hY21TdHJlYW1IZHIucGJTcmMgPT0gTlVMTCB8fAogICAgICBUaGlzLT5hY21TdHJlYW1IZHIuZHdTcmNVc2VyIDwgc2l6ZSkgewogICAgVGhpcy0+YWNtU3RyZWFtSGRyLnBiU3JjID0gR2xvYmFsUmVBbGxvY1B0cihUaGlzLT5hY21TdHJlYW1IZHIucGJTcmMsCgkJCQkJCXNpemUsIEdNRU1fTU9WRUFCTEUpOwogICAgaWYgKFRoaXMtPmFjbVN0cmVhbUhkci5wYlNyYyA9PSBOVUxMKQogICAgICByZXR1cm4gQVZJRVJSX01FTU9SWTsKICAgIFRoaXMtPmFjbVN0cmVhbUhkci5kd1NyY1VzZXIgPSBzaXplOwogIH0KCiAgVGhpcy0+YWNtU3RyZWFtSGRyLmNiU3RydWN0ID0gc2l6ZW9mKFRoaXMtPmFjbVN0cmVhbUhkcik7CiAgVGhpcy0+YWNtU3RyZWFtSGRyLmNiU3JjTGVuZ3RoVXNlZCA9IDA7CiAgVGhpcy0+YWNtU3RyZWFtSGRyLmNiRHN0TGVuZ3RoVXNlZCA9IDA7CiAgVGhpcy0+YWNtU3RyZWFtSGRyLmNiU3JjTGVuZ3RoICAgICA9IHNpemU7CgogIC8qIHJlYWQgc291cmNlIGRhdGEgKi8KICBociA9IElBVklTdHJlYW1fUmVhZChUaGlzLT5wU3RyZWFtLCBzdGFydCwgLTEsIFRoaXMtPmFjbVN0cmVhbUhkci5wYlNyYywKCQkgICAgICAgVGhpcy0+YWNtU3RyZWFtSGRyLmNiU3JjTGVuZ3RoLAoJCSAgICAgICAmVGhpcy0+YWNtU3RyZWFtSGRyLmNiU3JjTGVuZ3RoLCBOVUxMKTsKICBpZiAoRkFJTEVEKGhyKSB8fCBUaGlzLT5hY21TdHJlYW1IZHIuY2JTcmNMZW5ndGggPT0gMCkKICAgIHJldHVybiBocjsKCiAgLyogbmVlZCB0byBwcmVwYXJlIHN0cmVhbT8gKi8KICBUaGlzLT5hY21TdHJlYW1IZHIucGJEc3QgICAgICAgPSBidWZmZXI7CiAgVGhpcy0+YWNtU3RyZWFtSGRyLmNiRHN0TGVuZ3RoID0gYnVmZmVyc2l6ZTsKICBpZiAoKFRoaXMtPmFjbVN0cmVhbUhkci5mZHdTdGF0dXMgJiBBQ01TVFJFQU1IRUFERVJfU1RBVFVTRl9QUkVQQVJFRCkgPT0gMCkgewogICAgaWYgKGFjbVN0cmVhbVByZXBhcmVIZWFkZXIoVGhpcy0+aGFzLCAmVGhpcy0+YWNtU3RyZWFtSGRyLCAwKSAhPSBTX09LKSB7CiAgICAgIFRoaXMtPmFjbVN0cmVhbUhkci5wYkRzdCAgICAgICA9IE5VTEw7CiAgICAgIFRoaXMtPmFjbVN0cmVhbUhkci5jYkRzdExlbmd0aCA9IDA7CiAgICAgIHJldHVybiBBVklFUlJfQ09NUFJFU1NPUjsKICAgIH0KICB9CgogIC8qIG5vdyBkbyB0aGUgY29udmVyc2lvbiAqLwogIC8qIEZJWE1FOiB1c2UgQUNNX0NPTlZFUlRGXyogZmxhZ3MgKi8KICBpZiAoYWNtU3RyZWFtQ29udmVydChUaGlzLT5oYXMsICZUaGlzLT5hY21TdHJlYW1IZHIsIDApICE9IFNfT0spCiAgICBociA9IEFWSUVSUl9DT01QUkVTU09SOwoKICBUaGlzLT5hY21TdHJlYW1IZHIucGJEc3QgICAgICAgPSBOVUxMOwogIFRoaXMtPmFjbVN0cmVhbUhkci5jYkRzdExlbmd0aCA9IDA7CgogIC8qIGZpbGwgb3V0IHJldHVybiBwYXJhbWV0ZXJzIGlmIGdpdmVuICovCiAgaWYgKGJ5dGVzcmVhZCAhPSBOVUxMKQogICAgKmJ5dGVzcmVhZCA9IFRoaXMtPmFjbVN0cmVhbUhkci5jYkRzdExlbmd0aFVzZWQ7CiAgaWYgKHNhbXBsZXNyZWFkICE9IE5VTEwpCiAgICAqc2FtcGxlc3JlYWQgPQogICAgICBUaGlzLT5hY21TdHJlYW1IZHIuY2JEc3RMZW5ndGhVc2VkIC8gVGhpcy0+bHBPdXRGb3JtYXQtPm5CbG9ja0FsaWduOwoKICByZXR1cm4gaHI7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBBQ01TdHJlYW1fZm5Xcml0ZShJQVZJU3RyZWFtICppZmFjZSwgTE9ORyBzdGFydCwKCQkJCQkgTE9ORyBzYW1wbGVzLCBMUFZPSUQgYnVmZmVyLAoJCQkJCSBMT05HIGJ1ZmZlcnNpemUsIERXT1JEIGZsYWdzLAoJCQkJCSBMUExPTkcgc2FtcHdyaXR0ZW4sCgkJCQkJIExQTE9ORyBieXRlc3dyaXR0ZW4pCnsKICBJQ09NX1RISVMoSUFWSVN0cmVhbUltcGwsaWZhY2UpOwoKICBIUkVTVUxUIGhyOwogIExPTkcgICAgc2l6ZTsKCiAgVFJBQ0UoIiglcCwlbGQsJWxkLCVwLCVsZCwweCUwOGxYLCVwLCVwKVxuIiwgaWZhY2UsIHN0YXJ0LCBzYW1wbGVzLAoJYnVmZmVyLCBidWZmZXJzaXplLCBmbGFncywgc2FtcHdyaXR0ZW4sIGJ5dGVzd3JpdHRlbik7CgogIC8qIGNsZWFyIHJldHVybiBwYXJhbWV0ZXJzIGlmIGdpdmVuICovCiAgaWYgKHNhbXB3cml0dGVuICE9IE5VTEwpCiAgICAqc2FtcHdyaXR0ZW4gPSAwOwogIGlmIChieXRlc3dyaXR0ZW4gIT0gTlVMTCkKICAgICpieXRlc3dyaXR0ZW4gPSAwOwoKICAvKiBjaGVjayBwYXJhbWV0ZXJzICovCiAgaWYgKGJ1ZmZlciA9PSBOVUxMICYmIChidWZmZXJzaXplID4gMCB8fCBzYW1wbGVzID4gMCkpCiAgICByZXR1cm4gQVZJRVJSX0JBRFBBUkFNOwoKICAvKiBIYXZlIHdlIHdyaXRlIGNhcGFiaWxpdHk/ICovCiAgaWYgKChUaGlzLT5zSW5mby5kd0NhcHMgJiBBVklGSUxFQ0FQU19DQU5XUklURSkgPT0gMCkKICAgIHJldHVybiBBVklFUlJfUkVBRE9OTFk7CgogIC8qIGFsc28gbmVlZCBhIGNvbXByZXNzb3IgKi8KICBpZiAoVGhpcy0+aGFzID09IE5VTEwpCiAgICByZXR1cm4gQVZJRVJSX05PQ09NUFJFU1NPUjsKCiAgLyogbWFwIG91ciBzaXplcyB0byBwU3RyZWFtIHNpemVzICovCiAgc2l6ZSA9IGJ1ZmZlcnNpemU7CiAgQ09OVkVSVF9USElTX3RvX1NUUkVBTShzaXplKTsKICBDT05WRVJUX1RISVNfdG9fU1RSRUFNKHN0YXJ0KTsKCiAgLyogbm8gYnl0ZXMgdG8gd3JpdGU/IC0tIHNob3J0IGNpcmN1aXQgKi8KICBpZiAoc2l6ZSA9PSAwKSB7CiAgICByZXR1cm4gSUFWSVN0cmVhbV9Xcml0ZShUaGlzLT5wU3RyZWFtLCAtMSwgc2FtcGxlcywgYnVmZmVyLCBzaXplLAoJCQkgICAgZmxhZ3MsIHNhbXB3cml0dGVuLCBieXRlc3dyaXR0ZW4pOwogIH0KCiAgLyogTmVlZCB0byBmcmVlIHNvdXJjZSBidWZmZXIgdXNlZCBmb3IgcmVhZGluZz8gKi8KICBpZiAoVGhpcy0+YWNtU3RyZWFtSGRyLnBiU3JjICE9IE5VTEwpIHsKICAgIEdsb2JhbEZyZWVQdHIoVGhpcy0+YWNtU3RyZWFtSGRyLnBiU3JjKTsKICAgIFRoaXMtPmFjbVN0cmVhbUhkci5wYlNyYyAgICAgPSBOVUxMOwogICAgVGhpcy0+YWNtU3RyZWFtSGRyLmR3U3JjVXNlciA9IDA7CiAgfQoKICAvKiBOZWVkIGJpZ2dlciBkZXN0aW5hdGlvbiBidWZmZXI/ICovCiAgaWYgKFRoaXMtPmFjbVN0cmVhbUhkci5wYkRzdCA9PSBOVUxMIHx8CiAgICAgIFRoaXMtPmFjbVN0cmVhbUhkci5kd0RzdFVzZXIgPCBzaXplKSB7CiAgICBUaGlzLT5hY21TdHJlYW1IZHIucGJEc3QgPSBHbG9iYWxSZUFsbG9jUHRyKFRoaXMtPmFjbVN0cmVhbUhkci5wYkRzdCwKCQkJCQkJc2l6ZSwgR01FTV9NT1ZFQUJMRSk7CiAgICBpZiAoVGhpcy0+YWNtU3RyZWFtSGRyLnBiRHN0ID09IE5VTEwpCiAgICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwogICAgVGhpcy0+YWNtU3RyZWFtSGRyLmR3RHN0VXNlciA9IHNpemU7CiAgfQogIFRoaXMtPmFjbVN0cmVhbUhkci5jYlN0cnVjdCAgICAgICAgPSBzaXplb2YoVGhpcy0+YWNtU3RyZWFtSGRyKTsKICBUaGlzLT5hY21TdHJlYW1IZHIuY2JTcmNMZW5ndGhVc2VkID0gMDsKICBUaGlzLT5hY21TdHJlYW1IZHIuY2JEc3RMZW5ndGhVc2VkID0gMDsKICBUaGlzLT5hY21TdHJlYW1IZHIuY2JEc3RMZW5ndGggICAgID0gVGhpcy0+YWNtU3RyZWFtSGRyLmR3RHN0VXNlcjsKCiAgLyogbmVlZCB0byBwcmVwYXJlIHN0cmVhbT8gKi8KICBUaGlzLT5hY21TdHJlYW1IZHIucGJTcmMgICAgICAgPSBidWZmZXI7CiAgVGhpcy0+YWNtU3RyZWFtSGRyLmNiU3JjTGVuZ3RoID0gYnVmZmVyc2l6ZTsKICBpZiAoKFRoaXMtPmFjbVN0cmVhbUhkci5mZHdTdGF0dXMgJiBBQ01TVFJFQU1IRUFERVJfU1RBVFVTRl9QUkVQQVJFRCkgPT0gMCkgewogICAgaWYgKGFjbVN0cmVhbVByZXBhcmVIZWFkZXIoVGhpcy0+aGFzLCAmVGhpcy0+YWNtU3RyZWFtSGRyLCAwKSAhPSBTX09LKSB7CiAgICAgIFRoaXMtPmFjbVN0cmVhbUhkci5wYlNyYyAgICAgICA9IE5VTEw7CiAgICAgIFRoaXMtPmFjbVN0cmVhbUhkci5jYlNyY0xlbmd0aCA9IDA7CiAgICAgIHJldHVybiBBVklFUlJfQ09NUFJFU1NPUjsKICAgIH0KICB9CgogIC8qIG5vdyBkbyB0aGUgY29udmVyc2lvbiAqLwogIC8qIEZJWE1FOiB1c2UgQUNNX0NPTlZFUlRGXyogZmxhZ3MgKi8KICBpZiAoYWNtU3RyZWFtQ29udmVydChUaGlzLT5oYXMsICZUaGlzLT5hY21TdHJlYW1IZHIsIDApICE9IFNfT0spCiAgICBociA9IEFWSUVSUl9DT01QUkVTU09SOwogIGVsc2UKICAgIGhyID0gQVZJRVJSX09LOwoKICBUaGlzLT5hY21TdHJlYW1IZHIucGJTcmMgICAgICAgPSBOVUxMOwogIFRoaXMtPmFjbVN0cmVhbUhkci5jYlNyY0xlbmd0aCA9IDA7CgogIGlmIChGQUlMRUQoaHIpKQogICAgcmV0dXJuIGhyOwoKICByZXR1cm4gSUFWSVN0cmVhbV9Xcml0ZShUaGlzLT5wU3RyZWFtLC0xLFRoaXMtPmFjbVN0cmVhbUhkci5jYkRzdExlbmd0aFVzZWQgLwoJCQkgIFRoaXMtPmxwT3V0Rm9ybWF0LT5uQmxvY2tBbGlnbixUaGlzLT5hY21TdHJlYW1IZHIucGJEc3QsCgkJCSAgVGhpcy0+YWNtU3RyZWFtSGRyLmNiRHN0TGVuZ3RoVXNlZCxmbGFncyxzYW1wd3JpdHRlbiwKCQkJICBieXRlc3dyaXR0ZW4pOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuRGVsZXRlKElBVklTdHJlYW0gKmlmYWNlLCBMT05HIHN0YXJ0LAoJCQkJCSAgTE9ORyBzYW1wbGVzKQp7CiAgSUNPTV9USElTKElBVklTdHJlYW1JbXBsLGlmYWNlKTsKCiAgVFJBQ0UoIiglcCwlbGQsJWxkKVxuIiwgaWZhY2UsIHN0YXJ0LCBzYW1wbGVzKTsKCiAgLyogY2hlY2sgcGFyYW1ldGVycyAqLwogIGlmIChzdGFydCA8IDAgfHwgc2FtcGxlcyA8IDApCiAgICByZXR1cm4gQVZJRVJSX0JBRFBBUkFNOwoKICAvKiBEZWxldGUgYmVmb3JlIHN0YXJ0IG9mIHN0cmVhbT8gKi8KICBpZiAoc3RhcnQgKyBzYW1wbGVzIDwgVGhpcy0+c0luZm8uZHdTdGFydCkKICAgIHJldHVybiBBVklFUlJfT0s7CgogIC8qIERlbGV0ZSBhZnRlciBlbmQgb2Ygc3RyZWFtPyAqLwogIGlmIChzdGFydCA+IFRoaXMtPnNJbmZvLmR3TGVuZ3RoKQogICAgcmV0dXJuIEFWSUVSUl9PSzsKCiAgLyogRm9yIHRoZSByZXN0IHdlIG5lZWQgd3JpdGUgY2FwYWJpbGl0eSAqLwogIGlmICgoVGhpcy0+c0luZm8uZHdDYXBzICYgQVZJRklMRUNBUFNfQ0FOV1JJVEUpID09IDApCiAgICByZXR1cm4gQVZJRVJSX1JFQURPTkxZOwoKICAvKiBBIGNvbXByZXNzb3IgaXMgYWxzbyBuZWNjZXNzYXJ5ICovCiAgaWYgKFRoaXMtPmhhcyA9PSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9OT0NPTVBSRVNTT1I7CgogIC8qIG1hcCBvdXIgcG9zaXRpb25zIHRvIHBTdHJlYW0gcG9zaXRpb25zICovCiAgQ09OVkVSVF9USElTX3RvX1NUUkVBTShzdGFydCk7CiAgQ09OVkVSVF9USElTX3RvX1NUUkVBTShzYW1wbGVzKTsKCiAgcmV0dXJuIElBVklTdHJlYW1fRGVsZXRlKFRoaXMtPnBTdHJlYW0sIHN0YXJ0LCBzYW1wbGVzKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIEFDTVN0cmVhbV9mblJlYWREYXRhKElBVklTdHJlYW0gKmlmYWNlLCBEV09SRCBmY2MsCgkJCQkJICAgIExQVk9JRCBscCwgTFBMT05HIGxwcmVhZCkKewogIElDT01fVEhJUyhJQVZJU3RyZWFtSW1wbCxpZmFjZSk7CgogIFRSQUNFKCIoJXAsMHglMDhsWCwlcCwlcClcbiIsIGlmYWNlLCBmY2MsIGxwLCBscHJlYWQpOwoKICBhc3NlcnQoVGhpcy0+cFN0cmVhbSAhPSBOVUxMKTsKCiAgcmV0dXJuIElBVklTdHJlYW1fUmVhZERhdGEoVGhpcy0+cFN0cmVhbSwgZmNjLCBscCwgbHByZWFkKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIEFDTVN0cmVhbV9mbldyaXRlRGF0YShJQVZJU3RyZWFtICppZmFjZSwgRFdPUkQgZmNjLAoJCQkJCSAgICAgTFBWT0lEIGxwLCBMT05HIHNpemUpCnsKICBJQ09NX1RISVMoSUFWSVN0cmVhbUltcGwsaWZhY2UpOwoKICBUUkFDRSgiKCVwLDB4JTA4bHgsJXAsJWxkKVxuIiwgaWZhY2UsIGZjYywgbHAsIHNpemUpOwoKICBhc3NlcnQoVGhpcy0+cFN0cmVhbSAhPSBOVUxMKTsKCiAgcmV0dXJuIElBVklTdHJlYW1fV3JpdGVEYXRhKFRoaXMtPnBTdHJlYW0sIGZjYywgbHAsIHNpemUpOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQUNNU3RyZWFtX2ZuU2V0SW5mbyhJQVZJU3RyZWFtICppZmFjZSwKCQkJCQkgICBMUEFWSVNUUkVBTUlORk9XIGluZm8sIExPTkcgaW5mb2xlbikKewogIEZJWE1FKCIoJXAsJXAsJWxkKTogc3R1YlxuIiwgaWZhY2UsIGluZm8sIGluZm9sZW4pOwoKICByZXR1cm4gRV9GQUlMOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpzdGF0aWMgSFJFU1VMVCBBVklGSUxFX09wZW5Db21wcmVzc29yKElBVklTdHJlYW1JbXBsICpUaGlzKQp7CiAgSFJFU1VMVCBocjsKCiAgLyogcHJlLWNvbmRpdGlvbnMgKi8KICBhc3NlcnQoVGhpcyAhPSBOVUxMKTsKICBhc3NlcnQoVGhpcy0+cFN0cmVhbSAhPSBOVUxMKTsKCiAgaWYgKFRoaXMtPmhhcyAhPSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9PSzsKCiAgaWYgKFRoaXMtPmxwSW5Gb3JtYXQgPT0gTlVMTCkgewogICAgLyogZGVjb2RlIG9yIGVuY29kZSB0aGUgZGF0YSBmcm9tIHBTdHJlYW0gKi8KICAgIGhyID0gQVZJU3RyZWFtRm9ybWF0U2l6ZShUaGlzLT5wU3RyZWFtLCBUaGlzLT5zSW5mby5kd1N0YXJ0LCAmVGhpcy0+Y2JJbkZvcm1hdCk7CiAgICBpZiAoRkFJTEVEKGhyKSkKICAgICAgcmV0dXJuIGhyOwogICAgVGhpcy0+bHBJbkZvcm1hdCA9IChMUFdBVkVGT1JNQVRFWClHbG9iYWxBbGxvY1B0cihHTUVNX01PVkVBQkxFLCBUaGlzLT5jYkluRm9ybWF0KTsKICAgIGlmIChUaGlzLT5scEluRm9ybWF0ID09IE5VTEwpCiAgICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwoKICAgIGhyID0gSUFWSVN0cmVhbV9SZWFkRm9ybWF0KFRoaXMtPnBTdHJlYW0sIFRoaXMtPnNJbmZvLmR3U3RhcnQsCgkJCSAgICAgICBUaGlzLT5scEluRm9ybWF0LCAmVGhpcy0+Y2JJbkZvcm1hdCk7CiAgICBpZiAoRkFJTEVEKGhyKSkKICAgICAgcmV0dXJuIGhyOwoKICAgIGlmIChUaGlzLT5scE91dEZvcm1hdCA9PSBOVUxMKSB7CiAgICAgIC8qIHdlIG11c3QgZGVjb2RlIHRvIGRlZmF1bHQgZm9ybWF0ICovCiAgICAgIFRoaXMtPmNiT3V0Rm9ybWF0ID0gc2l6ZW9mKFBDTVdBVkVGT1JNQVQpOwogICAgICBUaGlzLT5scE91dEZvcm1hdCA9IChMUFdBVkVGT1JNQVRFWClHbG9iYWxBbGxvY1B0cihHSE5ELCBUaGlzLT5jYk91dEZvcm1hdCk7CiAgICAgIGlmIChUaGlzLT5scE91dEZvcm1hdCA9PSBOVUxMKQoJcmV0dXJuIEFWSUVSUl9NRU1PUlk7CgogICAgICBUaGlzLT5scE91dEZvcm1hdC0+d0Zvcm1hdFRhZyA9IFdBVkVfRk9STUFUX1BDTTsKICAgICAgaWYgKGFjbUZvcm1hdFN1Z2dlc3QoTlVMTCwgVGhpcy0+bHBJbkZvcm1hdCwgVGhpcy0+bHBPdXRGb3JtYXQsCgkJCSAgIFRoaXMtPmNiT3V0Rm9ybWF0LCBBQ01fRk9STUFUU1VHR0VTVEZfV0ZPUk1BVFRBRykgIT0gU19PSykKCXJldHVybiBBVklFUlJfTk9DT01QUkVTU09SOwogICAgfQogIH0gZWxzZSBpZiAoVGhpcy0+bHBPdXRGb3JtYXQgPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfRVJST1I7IC8qIFRvIHdoYXQgc2hvdWxkIEkgZW5jb2RlPyAqLwoKICBpZiAoYWNtU3RyZWFtT3BlbigmVGhpcy0+aGFzLCBOVUxMLCBUaGlzLT5scEluRm9ybWF0LCBUaGlzLT5scE91dEZvcm1hdCwKCQkgICAgTlVMTCwgMCwgMCwgQUNNX1NUUkVBTU9QRU5GX05PTlJFQUxUSU1FKSAhPSBTX09LKQogICAgcmV0dXJuIEFWSUVSUl9OT0NPTVBSRVNTT1I7CgogIC8qIHVwZGF0ZSBBVklTVFJFQU1JTkZPIHN0cnVjdHVyZSAqLwogIFRoaXMtPnNJbmZvLmR3U2FtcGxlU2l6ZSA9IFRoaXMtPmxwT3V0Rm9ybWF0LT5uQmxvY2tBbGlnbjsKICBUaGlzLT5zSW5mby5kd1NjYWxlICAgICAgPSBUaGlzLT5scE91dEZvcm1hdC0+bkJsb2NrQWxpZ247CiAgVGhpcy0+c0luZm8uZHdSYXRlICAgICAgID0gVGhpcy0+bHBPdXRGb3JtYXQtPm5BdmdCeXRlc1BlclNlYzsKICBUaGlzLT5zSW5mby5kd1F1YWxpdHkgICAgPSBJQ1FVQUxJVFlfREVGQVVMVDsKICBTZXRSZWN0RW1wdHkoJlRoaXMtPnNJbmZvLnJjRnJhbWUpOwoKICAvKiBjb252ZXJ0IHBvc2l0aW9ucyBhbnNkIHNpemVzIHRvIG91dHB1dCBmb3JtYXQgKi8KICBDT05WRVJUX1NUUkVBTV90b19USElTKFRoaXMtPnNJbmZvLmR3U3RhcnQpOwogIENPTlZFUlRfU1RSRUFNX3RvX1RISVMoVGhpcy0+c0luZm8uZHdMZW5ndGgpOwogIENPTlZFUlRfU1RSRUFNX3RvX1RISVMoVGhpcy0+c0luZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplKTsKCiAgcmV0dXJuIEFWSUVSUl9PSzsKfQo=