LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqIAogKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lCiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZQogKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvbgogKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlCiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUKICogIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZQogKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqIAogKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKiAKICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLAogKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbgogKiAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkKICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlCiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnMKICogdW5kZXIgdGhlIExpY2Vuc2UuCiAqIAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCgoKLy8gTUFSS0VSKHVwZGF0ZV9wcmVjb21wLnB5KTogYXV0b2dlbiBpbmNsdWRlIHN0YXRlbWVudCwgZG8gbm90IHJlbW92ZQojaW5jbHVkZSAicHJlY29tcGlsZWRfYmFzaWMuaHh4IgoKI2luY2x1ZGUgInJ1bnRpbWUuaHh4IgojaWZuZGVmIEdDQwojZW5kaWYKI2luY2x1ZGUgImlvc3lzLmh4eCIKI2luY2x1ZGUgImltYWdlLmh4eCIKI2luY2x1ZGUgInNiaW50ZXJuLmh4eCIKI2luY2x1ZGUgInNidW5vb2JqLmh4eCIKI2luY2x1ZGUgIm9wY29kZXMuaHh4IgoKI2luY2x1ZGUgPGNvbS9zdW4vc3Rhci9jb250YWluZXIvWEluZGV4QWNjZXNzLmhwcD4KI2luY2x1ZGUgPGNvbS9zdW4vc3Rhci9zY3JpcHQvWERlZmF1bHRNZXRob2QuaHBwPgojaW5jbHVkZSA8Y29tL3N1bi9zdGFyL2JlYW5zL1hQcm9wZXJ0eVNldC5ocHA+CiNpbmNsdWRlIDxjb20vc3VuL3N0YXIvdW5vL0FueS5oeHg+CiNpbmNsdWRlIDxjb21waGVscGVyL3Byb2Nlc3NmYWN0b3J5Lmh4eD4KCnVzaW5nIG5hbWVzcGFjZSBjb206OnN1bjo6c3Rhcjo6dW5vOwp1c2luZyBuYW1lc3BhY2UgY29tOjpzdW46OnN0YXI6OmNvbnRhaW5lcjsKdXNpbmcgbmFtZXNwYWNlIGNvbTo6c3VuOjpzdGFyOjpsYW5nOwp1c2luZyBuYW1lc3BhY2UgY29tOjpzdW46OnN0YXI6OmJlYW5zOwp1c2luZyBuYW1lc3BhY2UgY29tOjpzdW46OnN0YXI6OnNjcmlwdDsKCnVzaW5nIGNvbTo6c3VuOjpzdGFyOjp1bm86OlJlZmVyZW5jZTsKClNieFZhcmlhYmxlKiBnZXRWQkFDb25zdGFudCggY29uc3QgU3RyaW5nJiByTmFtZSApOwoKLy8gU3VjaGVuIGVpbmVzIEVsZW1lbnRzCi8vIERpZSBCaXRzIGltIFN0cmluZy1JRDoKLy8gMHg4MDAwIC0gQXJndiBpc3QgYmVsZWd0CgpTYnhWYXJpYWJsZSogU2JpUnVudGltZTo6RmluZEVsZW1lbnQKCSggU2J4T2JqZWN0KiBwT2JqLCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiwgU2JFcnJvciBuTm90Rm91bmQsIHNhbF9Cb29sIGJMb2NhbCwgc2FsX0Jvb2wgYlN0YXRpYyApCnsKCWJvb2wgYklzVkJBSW50ZXJPcCA9IFNiaVJ1bnRpbWU6OmlzVkJBRW5hYmxlZCgpOwoJaWYoIGJJc1ZCQUludGVyT3AgKQoJewoJCVN0YXJCQVNJQyogcE1TT01hY3JvUnVudGltZUxpYiA9IEdldFNiRGF0YSgpLT5wTVNPTWFjcm9SdW50aW1MaWI7CgkJaWYoIHBNU09NYWNyb1J1bnRpbWVMaWIgIT0gTlVMTCApCgkJCXBNU09NYWNyb1J1bnRpbWVMaWItPlJlc2V0RmxhZyggU0JYX0VYVFNFQVJDSCApOwoJfQoKCVNieFZhcmlhYmxlKiBwRWxlbSA9IE5VTEw7CglpZiggIXBPYmogKQoJewoJCUVycm9yKCBTYkVSUl9OT19PQkpFQ1QgKTsKCQlwRWxlbSA9IG5ldyBTYnhWYXJpYWJsZTsKCX0KCWVsc2UKCXsKCQlzYWxfQm9vbCBiRmF0YWxFcnJvciA9IHNhbF9GYWxzZTsKCQlTYnhEYXRhVHlwZSB0ID0gKFNieERhdGFUeXBlKSBuT3AyOwoJCVN0cmluZyBhTmFtZSggcEltZy0+R2V0U3RyaW5nKCBzdGF0aWNfY2FzdDxzaG9ydD4oIG5PcDEgJiAweDdGRkYgKSApICk7CgkJLy8gSGFja3kgY2FwdHVyZSBvZiBFdmFsdWF0ZSBbXSBzeW50YXgKCQkvLyB0aGlzIHNob3VsZCBiZSB0YWNrbGVkIEkgZmVlbCBhdCB0aGUgcGNvZGUgbGV2ZWwKCQlpZiAoIGJJc1ZCQUludGVyT3AgJiYgYU5hbWUuU2VhcmNoKCdbJykgPT0gMCApCgkJewoJCQkvLyBlbXVsYXRlIHBjb2RlIGhlcmUKCQkJU3RlcEFSR0MoKTsKCQkJLy8gcHN1ZWRvIFN0ZXBMT0FEU0MKCQkJU3RyaW5nIHNBcmcgPSBhTmFtZS5Db3B5KCAxLCBhTmFtZS5MZW4oKSAtIDIgKTsKCQkJU2J4VmFyaWFibGUqIHAgPSBuZXcgU2J4VmFyaWFibGU7CgkJCXAtPlB1dFN0cmluZyggc0FyZyApOwoJCQlQdXNoVmFyKCBwICk7CgkJCS8vCgkJCVN0ZXBBUkdWKCk7CgkJCW5PcDEgPSBuT3AxIHwgMHg4MDAwOyAvLyBpbmRpY2F0ZSBwYXJhbXMgYXJlIHByZXNlbnQKCQkJYU5hbWUgPSBTdHJpbmc6OkNyZWF0ZUZyb21Bc2NpaSgiRXZhbHVhdGUiKTsKCQl9CgkJaWYoIGJMb2NhbCApCgkJewoJCQlpZiAoIGJTdGF0aWMgKQoJCQl7CQoJCQkJaWYgKCBwTWV0aCApCgkJCQkJcEVsZW0gPSBwTWV0aC0+R2V0U3RhdGljcygpLT5GaW5kKCBhTmFtZSwgU2J4Q0xBU1NfRE9OVENBUkUgKTsKCQkJfQoKCQkJaWYgKCAhcEVsZW0gKQoJCQkJcEVsZW0gPSByZWZMb2NhbHMtPkZpbmQoIGFOYW1lLCBTYnhDTEFTU19ET05UQ0FSRSApOwoJCX0KCQlpZiggIXBFbGVtICkKCQl7CgkJCS8vIERpZSBSVEwgYnJhdWNoZW4gd2lyIG5pY2h0IG1laHIgenUgZHVyY2hzdWNoZW4hCgkJCXNhbF9Cb29sIGJTYXZlID0gckJhc2ljLmJOb1J0bDsKCQkJckJhc2ljLmJOb1J0bCA9IHNhbF9UcnVlOwoJCQlwRWxlbSA9IHBPYmotPkZpbmQoIGFOYW1lLCBTYnhDTEFTU19ET05UQ0FSRSApOwoKCQkJLy8gIzExMDAwNCwgIzExMjAxNTogTWFrZSBwcml2YXRlIHJlYWxseSBwcml2YXRlCgkJCWlmKCBiTG9jYWwgJiYgcEVsZW0gKQkvLyBMb2NhbCBhcyBmbGFnIGZvciBnbG9iYWwgc2VhcmNoCgkJCXsKCQkJCWlmKCBwRWxlbS0+SXNTZXQoIFNCWF9QUklWQVRFICkgKQoJCQkJewoJCQkJCVNiaUluc3RhbmNlKiBwSW5zdF8gPSBwSU5TVDsKCQkJCQlpZiggcEluc3RfICYmIHBJbnN0Xy0+SXNDb21wYXRpYmlsaXR5KCkgJiYgcE9iaiAhPSBwRWxlbS0+R2V0UGFyZW50KCkgKQoJCQkJCQlwRWxlbSA9IE5VTEw7CS8vIEZvdW5kIGJ1dCBpbiB3cm9uZyBtb2R1bGUhCgoJCQkJCS8vIEludGVyZmFjZXM6IFVzZSBTQlhfRVhURk9VTkQKCQkJCX0KCQkJfQoJCQlyQmFzaWMuYk5vUnRsID0gYlNhdmU7CgoJCQkvLyBJc3QgZXMgZWluIGdsb2JhbGVyIFVuby1CZXplaWNobmVyPwoJCQlpZiggYkxvY2FsICYmICFwRWxlbSApCgkJCXsKCQkJCWJvb2wgYlNldE5hbWUgPSB0cnVlOyAvLyBwcmVzZXJ2ZSBub3JtYWwgYmVoYXZpb3VyCgoJCQkJLy8gaSNpNjg4OTQjIGlmIFZCQUludGVyT3AgZmF2b3VyIHNlYXJjaGluZyB2YmEgZ2xvYmFscwoJCQkJLy8gb3ZlciBzZWFyY2hpbmcgZm9yIHVubyBjbGFzc2VzcwoJCQkJaWYgKCBiVkJBRW5hYmxlZCApCgkJCQl7CgkJCQkJLy8gVHJ5IEZpbmQgaW4gVkJBIHN5bWJvbHMgc3BhY2UKCQkJCQlwRWxlbSA9IHJCYXNpYy5WQkFGaW5kKCBhTmFtZSwgU2J4Q0xBU1NfRE9OVENBUkUgKTsKCQkJCQlpZiAoIHBFbGVtICkKCQkJCQkJYlNldE5hbWUgPSBmYWxzZTsgLy8gZG9uJ3Qgb3ZlcndyaXRlIHVubyBuYW1lCgkJCQkJZWxzZQoJCQkJCQlwRWxlbSA9IGdldFZCQUNvbnN0YW50KCBhTmFtZSApOwoJCQkJfQoKCQkJCWlmKCAhcEVsZW0gKQoJCQkJewoJCQkJCS8vICM3MjM4MiBWT1JTSUNIVCEgTGllZmVydCBqZXR6dCB3ZWdlbiB1bmJla2FubnRlbgoJCQkJCS8vIE1vZHVsZW4gSU1NRVIgZWluIEVyZ2VibmlzIQoJCQkJCVNiVW5vQ2xhc3MqIHBVbm9DbGFzcyA9IGZpbmRVbm9DbGFzcyggYU5hbWUgKTsKCQkJCQlpZiggcFVub0NsYXNzICkKCQkJCQl7CgkJCQkJCXBFbGVtID0gbmV3IFNieFZhcmlhYmxlKCB0ICk7CgkJCQkJCVNieFZhbHVlcyBhUmVzKCBTYnhPQkpFQ1QgKTsKCQkJCQkJYVJlcy5wT2JqID0gcFVub0NsYXNzOwoJCQkJCQlwRWxlbS0+U2J4VmFyaWFibGU6OlB1dCggYVJlcyApOwoJCQkJCX0KCQkJCX0KCgkJCQkvLyAjNjI5MzkgV2VubiBlaW5lIFVuby1LbGFzc2UgZ2VmdW5kZW4gd3VyZGUsIG11c3MKCQkJCS8vIGRhcyBXcmFwcGVyLU9iamVrdCBnZWhhbHRlbiB3ZXJkZW4sIGRhIHNvbnN0IGF1Y2gKCQkJCS8vIGRpZSBVbm8tS2xhc3NlLCB6LkIuICJzdGFyZGl2IiBpbW1lciB3aWVkZXIgbmV1CgkJCQkvLyBhdXMgZGVyIFJlZ2lzdHJ5IGdlbGVzZW4gd2VyZGVuIG11c3MKCQkJCWlmKCBwRWxlbSApCgkJCQl7CgkJCQkJLy8gIzYzNzc0IERhcmYgbmljaHQgbWl0IGdlc3BlaWNoZXJ0IHdlcmRlbiEhIQoJCQkJCXBFbGVtLT5TZXRGbGFnKCBTQlhfRE9OVFNUT1JFICk7CgkJCQkJcEVsZW0tPlNldEZsYWcoIFNCWF9OT19NT0RJRlkpOwoKCQkJCQkvLyAjNzIzODIgTG9rYWwgc3BlaWNoZXJuLCBzb25zdCB3ZXJkZW4gYWxsZSBpbXBsaXppdAoJCQkJCS8vIGRla2xhcmllcnRlbiBWYXJzIGF1dG9tYXRpc2NoIGdsb2JhbCAhCgkJCQkJaWYgKCBiU2V0TmFtZSApCgkJCQkJCXBFbGVtLT5TZXROYW1lKCBhTmFtZSApOwoJCQkJCXJlZkxvY2Fscy0+UHV0KCBwRWxlbSwgcmVmTG9jYWxzLT5Db3VudCgpICk7CgkJCQl9CgkJCX0KCgkJCWlmKCAhcEVsZW0gKQoJCQl7CgkJCQkvLyBOaWNodCBkYSB1bmQgbmljaHQgaW0gT2JqZWt0PwoJCQkJLy8gSGF0IGRhcyBEaW5nIFBhcmFtZXRlciwgbmljaHQgZWlucmljaHRlbiEKCQkJCWlmKCBuT3AxICYgMHg4MDAwICkKCQkJCQliRmF0YWxFcnJvciA9IHNhbF9UcnVlOwoJCQkJCS8vIEFMVDogU3RhckJBU0lDOjpGYXRhbEVycm9yKCBuTm90Rm91bmQgKTsKCgkJCQkvLyBTb25zdCwgZmFsbHMga2VpbmUgUGFyYW1ldGVyIHNpbmQsIGFuZGVyZW4gRXJyb3IgQ29kZSB2ZXJ3ZW5kZW4KCQkJCWlmKCAhYkxvY2FsIHx8IHBJbWctPkdldEZsYWcoIFNCSU1HX0VYUExJQ0lUICkgKQoJCQkJewoJCQkJCS8vICMzOTEwOCBCZWkgZXhwbGl6aXQgdW5kIGFscyBFTEVNIGltbWVyIGVpbiBGYXRhbCBFcnJvcgoJCQkJCWJGYXRhbEVycm9yID0gc2FsX1RydWU7CgoJCQkJCS8vIEZhbGxzIGtlaW5lIFBhcmFtZXRlciBzaW5kLCBhbmRlcmVuIEVycm9yIENvZGUgdmVyd2VuZGVuCgkJCQkJaWYoICEoIG5PcDEgJiAweDgwMDAgKSAmJiBuTm90Rm91bmQgPT0gU2JFUlJfUFJPQ19VTkRFRklORUQgKQoJCQkJCQluTm90Rm91bmQgPSBTYkVSUl9WQVJfVU5ERUZJTkVEOwoJCQkJfQoJCQkJaWYoIGJGYXRhbEVycm9yICkKCQkJCXsKCQkJCQkvLyAjMzkxMDggU3RhdHQgRmF0YWxFcnJvciB6dSBzZXR6ZW4sIER1bW15LVZhcmlhYmxlIGxpZWZlcm4KCQkJCQlpZiggIXhEdW1teVZhci5JcygpICkKCQkJCQkJeER1bW15VmFyID0gbmV3IFNieFZhcmlhYmxlKCBTYnhWQVJJQU5UICk7CgkJCQkJcEVsZW0gPSB4RHVtbXlWYXI7CgoJCQkJCS8vIFBhcmFtZXRlciB2b24gSGFuZCBsb2VzY2hlbgoJCQkJCUNsZWFyQXJndlN0YWNrKCk7CgoJCQkJCS8vIE5vcm1hbGVuIEVycm9yIHNldHplbgoJCQkJCUVycm9yKCBuTm90Rm91bmQsIGFOYW1lICk7CgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJaWYgKCBiU3RhdGljICkKCQkJCQkJcEVsZW0gPSBTdGVwU1RBVElDX0ltcGwoIGFOYW1lLCB0ICk7CgkJCQkJaWYgKCAhcEVsZW0gKQoJCQkJCXsKCQkJCQkJLy8gU29uc3QgVmFyaWFibGUgbmV1IGFubGVnZW4KCQkJCQkJcEVsZW0gPSBuZXcgU2J4VmFyaWFibGUoIHQgKTsKCQkJCQkJaWYoIHQgIT0gU2J4VkFSSUFOVCApCgkJCQkJCQlwRWxlbS0+U2V0RmxhZyggU0JYX0ZJWEVEICk7CgkJCQkJCXBFbGVtLT5TZXROYW1lKCBhTmFtZSApOwoJCQkJCQlyZWZMb2NhbHMtPlB1dCggcEVsZW0sIHJlZkxvY2Fscy0+Q291bnQoKSApOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQkvLyAjMzkxMDggQXJncyBrb2VubmVuIHNjaG9uIGdlbG9lc2NodCBzZWluIQoJCWlmKCAhYkZhdGFsRXJyb3IgKQoJCQlTZXR1cEFyZ3MoIHBFbGVtLCBuT3AxICk7CgkJLy8gRWluIGJlc3RpbW10ZXIgQ2FsbC1UeXBlIHd1cmRlIGdld3VlbnNjaHQsIGRhaGVyIG11ZXNzZW4KCQkvLyB3aXIgaGllciBkZW4gVHlwIHNldHplbiB1bmQgZGFzIERpbmcgYW5mYXNzZW4sIHVtIGRlbgoJCS8vIGtvcnJla3RlbiBSZXR1cm53ZXJ0IHp1IGVyaGFsdGVuIQoJCWlmKCBwRWxlbS0+SXNBKCBUWVBFKFNieE1ldGhvZCkgKSApCgkJewoJCQkvLyBTb2xsIGRlciBUeXAga29udmVydGllcnQgd2VyZGVuPwoJCQlTYnhEYXRhVHlwZSB0MiA9IHBFbGVtLT5HZXRUeXBlKCk7CgkJCXNhbF9Cb29sIGJTZXQgPSBzYWxfRmFsc2U7CgkJCWlmKCAhKCBwRWxlbS0+R2V0RmxhZ3MoKSAmIFNCWF9GSVhFRCApICkKCQkJewoJCQkJaWYoIHQgIT0gU2J4VkFSSUFOVCAmJiB0ICE9IHQyICYmCgkJCQkJdCA+PSBTYnhJTlRFR0VSICYmIHQgPD0gU2J4U1RSSU5HICkKCQkJCQlwRWxlbS0+U2V0VHlwZSggdCApLCBiU2V0ID0gc2FsX1RydWU7CgkJCX0KCQkJLy8gcEVsZW0gYXVmIGVpbmUgUmVmIHp1d2Vpc2VuLCB1bSBnZ2YuIGVpbmUgVGVtcC1WYXIgenUgbG9lc2NoZW4KCQkJU2J4VmFyaWFibGVSZWYgcmVmVGVtcCA9IHBFbGVtOwoKCQkJLy8gTW9lZ2xpY2hlIFJlc3RlIHZvbSBsZXR6dGVuIEF1ZnJ1ZiBkZXIgU2J4TWV0aG9kIGJlc2VpdGlnZW4KCQkJLy8gVm9yaGVyIFNjaHJlaWJlbiBmcmVpZ2ViZW4sIGRhbWl0IGtlaW4gRXJyb3IgZ2VzZXR6dCB3aXJkLgoJCQlzYWxfdUludDE2IG5TYXZGbGFncyA9IHBFbGVtLT5HZXRGbGFncygpOwoJCQlwRWxlbS0+U2V0RmxhZyggU0JYX1JFQURXUklURSB8IFNCWF9OT19CUk9BRENBU1QgKTsKCQkJcEVsZW0tPlNieFZhbHVlOjpDbGVhcigpOwoJCQlwRWxlbS0+U2V0RmxhZ3MoIG5TYXZGbGFncyApOwoKCQkJLy8gRXJzdCBuYWNoIGRlbSBTZXR6ZW4gYW5mYXNzZW4sIGRhIHouQi4gTEVGVCgpCgkJCS8vIGRlbiBVbnRlcnNjaGllZCB6d2lzY2hlbiBMZWZ0JCgpIHVuZCBMZWZ0KCkga2VubmVuIG11c3MKCgkJCS8vIEFCIDEyLjguOTY6IERhIGluIFBvcFZhcigpIGRpZSBQYXJhbWV0ZXIgdm9uIE1ldGhvZGVuIHdlZ2dlaGF1ZW4KCQkJLy8gd2VyZGVuLCBtdWVzc2VuIHdpciBoaWVyIGV4cGxpeml0IGVpbmUgbmV1ZSBTYnhNZXRob2QgYW5sZWdlbgoJCQlTYnhWYXJpYWJsZSogcE5ldyA9IG5ldyBTYnhNZXRob2QoICooKFNieE1ldGhvZCopcEVsZW0pICk7IC8vIGRhcyBpc3QgZGVyIENhbGwhCgkJCS8vQUxUOiBTYnhWYXJpYWJsZSogcE5ldyA9IG5ldyBTYnhWYXJpYWJsZSggKnBFbGVtICk7IC8vIGRhcyBpc3QgZGVyIENhbGwhCgoJCQlwRWxlbS0+U2V0UGFyYW1ldGVycygwKTsgLy8gc29uc3QgYmxlaWJ0IFJlZiBhdWYgc2ljaCBzZWxic3QKCQkJcE5ldy0+U2V0RmxhZyggU0JYX1JFQURXUklURSApOwoKCQkJLy8gZGVuIERhdGVudHlwZW4genVydWVja3NldHplbj8KCQkJaWYoIGJTZXQgKQoJCQkJcEVsZW0tPlNldFR5cGUoIHQyICk7CgkJCXBFbGVtID0gcE5ldzsKCQl9IAoJCS8vIEluZGV4LUFjY2VzcyBiZWkgVW5vT2JqZWt0ZW4gYmVydWVja3NpY2h0aWdlbgoJCS8vIGRlZmluaXRlbHkgd2Ugd2FudCB0aGlzIGZvciBWQkEgd2hlcmUgcHJvcGVydGllcyBhcmUgb2Z0ZW4gCgkJLy8gY29sbGVjdGlvbnMgKCB3aGljaCBuZWVkIGluZGV4IGFjY2VzcyApLCBidXQgbGV0cyBvbmx5IGRvIAoJCS8vIHRoaXMgaWYgd2UgYWN0dWFsbHkgaGF2ZSBwYXJhbXMgZm9sbG93aW5nCgkJZWxzZSBpZiggYlZCQUVuYWJsZWQgJiYgcEVsZW0tPklTQShTYlVub1Byb3BlcnR5KSAmJiBwRWxlbS0+R2V0UGFyYW1ldGVycygpICkKCQl7CgkJCS8vIHBFbGVtIGF1ZiBlaW5lIFJlZiB6dXdlaXNlbiwgdW0gZ2dmLiBlaW5lIFRlbXAtVmFyIHp1IGxvZXNjaGVuCgkJCVNieFZhcmlhYmxlUmVmIHJlZlRlbXAgPSBwRWxlbTsKCgkJCS8vIFZhcmlhYmxlIGtvcGllcmVuIHVuZCBkYWJlaSBkZW4gTm90aWZ5IGF1ZmxvZXNlbgoJCQlTYnhWYXJpYWJsZSogcE5ldyA9IG5ldyBTYnhWYXJpYWJsZSggKigoU2J4VmFyaWFibGUqKXBFbGVtKSApOyAvLyBkYXMgaXN0IGRlciBDYWxsIQoJCQlwRWxlbS0+U2V0UGFyYW1ldGVycyggTlVMTCApOyAvLyBzb25zdCBibGVpYnQgUmVmIGF1ZiBzaWNoIHNlbGJzdAoJCQlwRWxlbSA9IHBOZXc7CgkJfQoJfQoJcmV0dXJuIENoZWNrQXJyYXkoIHBFbGVtICk7Cn0KCi8vIEZpbmQtRnVua3Rpb24gdWViZXIgTmFtZSBmdWVyIGFrdHVlbGxlbiBTY29wZSAoei5CLiBBYmZyYWdlIGF1cyBCQVNJQy1JREUpClNieEJhc2UqIFNiaVJ1bnRpbWU6OkZpbmRFbGVtZW50RXh0ZXJuKCBjb25zdCBTdHJpbmcmIHJOYW1lICkKewoJLy8gSGlud2VpcyB6dSAjMzUyODEjOiBFcyBkYXJmIG5pY2h0IGRhdm9uIGF1c2dlZ2FuZ2VuIHdlcmRlbiwgZGFzcwoJLy8gcE1ldGggIT0gbnVsbCwgZGEgaW0gUnVuSW5pdCBub2NoIGtlaW5lIGdlc2V0enQgaXN0LgoKCVNieFZhcmlhYmxlKiBwRWxlbSA9IE5VTEw7CglpZiggIXBNb2QgfHwgIXJOYW1lLkxlbigpICkKCQlyZXR1cm4gTlVMTDsKCgkvLyBMb2thbCBzdWNoZW4KCWlmKCByZWZMb2NhbHMgKQoJCXBFbGVtID0gcmVmTG9jYWxzLT5GaW5kKCByTmFtZSwgU2J4Q0xBU1NfRE9OVENBUkUgKTsKCgkvLyBJbiBTdGF0aWNzIHN1Y2hlbgoJaWYgKCAhcEVsZW0gJiYgcE1ldGggKQoJewoJCS8vIEJlaSBTdGF0aWNzLCBOYW1lIGRlciBNZXRob2RlIGRhdm9yIHNldHplbgoJCVN0cmluZyBhTWV0aE5hbWUgPSBwTWV0aC0+R2V0TmFtZSgpOwoJCWFNZXRoTmFtZSArPSAnOic7CgkJYU1ldGhOYW1lICs9IHJOYW1lOwoJCXBFbGVtID0gcE1vZC0+RmluZChhTWV0aE5hbWUsIFNieENMQVNTX0RPTlRDQVJFKTsKCX0KCgkvLyBJbiBQYXJhbWV0ZXItTGlzdGUgc3VjaGVuCglpZiggIXBFbGVtICYmIHBNZXRoICkKCXsKCQlTYnhJbmZvKiBwSW5mbyA9IHBNZXRoLT5HZXRJbmZvKCk7CgkJaWYoIHBJbmZvICYmIHJlZlBhcmFtcyApCgkJewogICAgICAgIAlzYWxfdUludDE2IG5QYXJhbUNvdW50ID0gcmVmUGFyYW1zLT5Db3VudCgpOwoJCQlzYWxfdUludDE2IGogPSAxOwoJCQljb25zdCBTYnhQYXJhbUluZm8qIHBQYXJhbSA9IHBJbmZvLT5HZXRQYXJhbSggaiApOwoJCQl3aGlsZSggcFBhcmFtICkKCQkJewoJCQkJaWYoIHBQYXJhbS0+YU5hbWUuRXF1YWxzSWdub3JlQ2FzZUFzY2lpKCByTmFtZSApICkKCQkJCXsKCSAgICAgICAgICAgICAgICBpZiggaiA+PSBuUGFyYW1Db3VudCApCgkgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBQYXJhbWV0ZXIgaXMgbWlzc2luZwogICAgCQkJCQlwRWxlbSA9IG5ldyBTYnhWYXJpYWJsZSggU2J4U1RSSU5HICk7CiAgICAgICAgICAgICAgICAgICAgICAgIHBFbGVtLT5QdXRTdHJpbmcoIFN0cmluZyggUlRMX0NPTlNUQVNDSUlfVVNUUklOR1BBUkFNKCI8bWlzc2luZyBwYXJhbWV0ZXI+IiApICkgKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIHsKICAgIAkJCQkJcEVsZW0gPSByZWZQYXJhbXMtPkdldCggaiApOwogICAgICAgICAgICAgICAgICAgIH0KCQkJCQlicmVhazsKCQkJCX0KCQkJCXBQYXJhbSA9IHBJbmZvLT5HZXRQYXJhbSggKytqICk7CgkJCX0KCQl9Cgl9CgoJLy8gSW0gTW9kdWwgc3VjaGVuCglpZiggIXBFbGVtICkKCXsKCQkvLyBSVEwgbmljaHQgZHVyY2hzdWNoZW4hCgkJc2FsX0Jvb2wgYlNhdmUgPSByQmFzaWMuYk5vUnRsOwoJCXJCYXNpYy5iTm9SdGwgPSBzYWxfVHJ1ZTsKCQlwRWxlbSA9IHBNb2QtPkZpbmQoIHJOYW1lLCBTYnhDTEFTU19ET05UQ0FSRSApOwoJCXJCYXNpYy5iTm9SdGwgPSBiU2F2ZTsKCX0KCXJldHVybiBwRWxlbTsKfQoKCi8vIEFyZ3VtZW50ZSBlaW5lcyBFbGVtZW50cyBzZXR6ZW4KLy8gRGFiZWkgYXVjaCBkaWUgQXJndW1lbnRlIHVtc2V0emVuLCBmYWxscyBiZW5hbm50ZSBQYXJhbWV0ZXIKLy8gdmVyd2VuZGV0IHd1cmRlbgoKdm9pZCBTYmlSdW50aW1lOjpTZXR1cEFyZ3MoIFNieFZhcmlhYmxlKiBwLCBzYWxfdUludDMyIG5PcDEgKQp7CglpZiggbk9wMSAmIDB4ODAwMCApCgl7CgkJaWYoICFyZWZBcmd2ICkKCQkJU3RhckJBU0lDOjpGYXRhbEVycm9yKCBTYkVSUl9JTlRFUk5BTF9FUlJPUiApOwoJCXNhbF9Cb29sIGJIYXNOYW1lZCA9IHNhbF9GYWxzZTsKCQlzYWxfdUludDE2IGk7CgkJc2FsX3VJbnQxNiBuQXJnQ291bnQgPSByZWZBcmd2LT5Db3VudCgpOwoJCWZvciggaSA9IDEgOyBpIDwgbkFyZ0NvdW50IDsgaSsrICkKCQl7CgkJCWlmKCByZWZBcmd2LT5HZXRBbGlhcyggaSApLkxlbigpICkKCQkJewoJCQkJYkhhc05hbWVkID0gc2FsX1RydWU7IGJyZWFrOwoJCQl9CgkJfQoJCWlmKCBiSGFzTmFtZWQgKQoJCXsKCQkJLy8gV2lyIGhhYmVuIG1pbmRlc3RlbnMgZWluZW4gYmVuYW5udGVuIFBhcmFtZXRlciEKCQkJLy8gV2lyIG11ZXNzZW4gYWxzbyB1bXNvcnRpZXJlbgoJCQkvLyBHaWJ0IGVzIFBhcmFtZXRlci1JbmZvcz8KCQkJU2J4SW5mbyogcEluZm8gPSBwLT5HZXRJbmZvKCk7CgkJCWlmKCAhcEluZm8gKQoJCQl7CgkJCQlib29sIGJFcnJvcl8gPSB0cnVlOwoKCQkJCVNiVW5vTWV0aG9kKiBwVW5vTWV0aG9kID0gUFRSX0NBU1QoU2JVbm9NZXRob2QscCk7CgkJCQlTYlVub1Byb3BlcnR5KiBwVW5vUHJvcGVydHkgPSBQVFJfQ0FTVChTYlVub1Byb3BlcnR5LHApOwoJCQkJaWYoIHBVbm9NZXRob2QgfHwgcFVub1Byb3BlcnR5ICkKCQkJCXsKCQkJCQlTYlVub09iamVjdCogcFBhcmVudFVub09iaiA9IFBUUl9DQVNUKCBTYlVub09iamVjdCxwLT5HZXRQYXJlbnQoKSApOwoJCQkJCWlmKCBwUGFyZW50VW5vT2JqICkKCQkJCQl7CgkJCQkJCUFueSBhVW5vQW55ID0gcFBhcmVudFVub09iai0+Z2V0VW5vQW55KCk7CgkJCQkJCVJlZmVyZW5jZTwgWEludm9jYXRpb24gPiB4SW52b2NhdGlvbjsKCQkJCQkJYVVub0FueSA+Pj0geEludm9jYXRpb247CgkJCQkJCWlmKCB4SW52b2NhdGlvbi5pcygpICkJLy8gVE9ETzogaWYoIHhPTEVBdXRvbWF0aW9uLmlzKCkgKQoJCQkJCQl7CgkJCQkJCQliRXJyb3JfID0gZmFsc2U7CgoJCQkJCQkJc2FsX3VJbnQxNiBuQ3VyUGFyID0gMTsKCQkJCQkJCUF1dG9tYXRpb25OYW1lZEFyZ3NTYnhBcnJheSogcEFyZyA9CgkJCQkJCQkJbmV3IEF1dG9tYXRpb25OYW1lZEFyZ3NTYnhBcnJheSggbkFyZ0NvdW50ICk7CgkJCQkJCQk6OnJ0bDo6T1VTdHJpbmcqIHBOYW1lcyA9IHBBcmctPmdldE5hbWVzKCkuZ2V0QXJyYXkoKTsKCQkJCQkJCWZvciggaSA9IDEgOyBpIDwgbkFyZ0NvdW50IDsgaSsrICkKCQkJCQkJCXsKCQkJCQkJCQlTYnhWYXJpYWJsZSogcFZhciA9IHJlZkFyZ3YtPkdldCggaSApOwoJCQkJCQkJCWNvbnN0IFN0cmluZyYgck5hbWUgPSByZWZBcmd2LT5HZXRBbGlhcyggaSApOwoJCQkJCQkJCWlmKCByTmFtZS5MZW4oKSApCgkJCQkJCQkJCXBOYW1lc1tpXSA9IHJOYW1lOwoJCQkJCQkJCXBBcmctPlB1dCggcFZhciwgbkN1clBhcisrICk7CgkJCQkJCQl9CgkJCQkJCQlyZWZBcmd2ID0gcEFyZzsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJCWVsc2UgaWYoIGJWQkFFbmFibGVkICYmIHAtPkdldFR5cGUoKSA9PSBTYnhPQkpFQ1QgJiYgKCFwLT5JU0EoU2J4TWV0aG9kKSB8fCAhcC0+SXNCcm9hZGNhc3RlcigpKSApCgkJCQl7CgkJCQkJLy8gQ2hlY2sgZm9yIGRlZmF1bHQgbWV0aG9kIHdpdGggbmFtZWQgcGFyYW1ldGVycwoJCQkJCVNieEJhc2VSZWYgcE9iaiA9IChTYnhCYXNlKilwLT5HZXRPYmplY3QoKTsKCQkJCQlpZiggcE9iaiAmJiBwT2JqLT5JU0EoU2JVbm9PYmplY3QpICkKCQkJCQl7CgkJCQkJCVNiVW5vT2JqZWN0KiBwVW5vT2JqID0gKFNiVW5vT2JqZWN0KikoU2J4QmFzZSopcE9iajsKCQkJCQkJQW55IGFBbnkgPSBwVW5vT2JqLT5nZXRVbm9BbnkoKTsKCgkJCQkJCWlmKCBhQW55LmdldFZhbHVlVHlwZSgpLmdldFR5cGVDbGFzcygpID09IFR5cGVDbGFzc19JTlRFUkZBQ0UgKQoJCQkJCQl7CgkJCQkJCQlSZWZlcmVuY2U8IFhJbnRlcmZhY2UgPiB4ID0gKihSZWZlcmVuY2U8IFhJbnRlcmZhY2UgPiopYUFueS5nZXRWYWx1ZSgpOwoJCQkJCQkJUmVmZXJlbmNlPCBYRGVmYXVsdE1ldGhvZCA+IHhEZmx0TWV0aG9kKCB4LCBVTk9fUVVFUlkgKTsKCgkJCQkJCQlydGw6Ok9VU3RyaW5nIHNEZWZhdWx0TWV0aG9kOwoJCQkJCQkJaWYgKCB4RGZsdE1ldGhvZC5pcygpICkKCQkJCQkJCQlzRGVmYXVsdE1ldGhvZCA9IHhEZmx0TWV0aG9kLT5nZXREZWZhdWx0TWV0aG9kTmFtZSgpOwoJCQkJCQkJaWYgKCBzRGVmYXVsdE1ldGhvZC5nZXRMZW5ndGgoKSApCgkJCQkJCQl7CgkJCQkJCQkJU2J4VmFyaWFibGUqIG1ldGggPSBwVW5vT2JqLT5GaW5kKCBzRGVmYXVsdE1ldGhvZCwgU2J4Q0xBU1NfTUVUSE9EICk7CgkJCQkJCQkJaWYoIG1ldGggIT0gTlVMTCApCgkJCQkJCQkJCXBJbmZvID0gbWV0aC0+R2V0SW5mbygpOwoJCQkJCQkJCWlmKCBwSW5mbyApCgkJCQkJCQkJCWJFcnJvcl8gPSBmYWxzZTsKCQkJCQkJCX0KCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJCWlmKCBiRXJyb3JfICkKCQkJCQlFcnJvciggU2JFUlJfTk9fTkFNRURfQVJHUyApOwoJCQl9CgkJCWVsc2UKCQkJewoJCQkJc2FsX3VJbnQxNiBuQ3VyUGFyID0gMTsKCQkJCVNieEFycmF5KiBwQXJnID0gbmV3IFNieEFycmF5OwoJCQkJZm9yKCBpID0gMSA7IGkgPCBuQXJnQ291bnQgOyBpKysgKQoJCQkJewoJCQkJCVNieFZhcmlhYmxlKiBwVmFyID0gcmVmQXJndi0+R2V0KCBpICk7CgkJCQkJY29uc3QgU3RyaW5nJiByTmFtZSA9IHJlZkFyZ3YtPkdldEFsaWFzKCBpICk7CgkJCQkJaWYoIHJOYW1lLkxlbigpICkKCQkJCQl7CgkJCQkJCS8vIG5DdXJQYXIgd2lyZCBhdWYgZGVuIGdlZnVuZGVuZW4gUGFyYW1ldGVyIGdlc2V0enQKCQkJCQkJc2FsX3VJbnQxNiBqID0gMTsKCQkJCQkJY29uc3QgU2J4UGFyYW1JbmZvKiBwUGFyYW0gPSBwSW5mby0+R2V0UGFyYW0oIGogKTsKCQkJCQkJd2hpbGUoIHBQYXJhbSApCgkJCQkJCXsKCQkJCQkJCWlmKCBwUGFyYW0tPmFOYW1lLkVxdWFsc0lnbm9yZUNhc2VBc2NpaSggck5hbWUgKSApCgkJCQkJCQl7CgkJCQkJCQkJbkN1clBhciA9IGo7CgkJCQkJCQkJYnJlYWs7CgkJCQkJCQl9CgkJCQkJCQlwUGFyYW0gPSBwSW5mby0+R2V0UGFyYW0oICsraiApOwoJCQkJCQl9CgkJCQkJCWlmKCAhcFBhcmFtICkKCQkJCQkJewoJCQkJCQkJRXJyb3IoIFNiRVJSX05BTUVEX05PVF9GT1VORCApOyBicmVhazsKCQkJCQkJfQoJCQkJCX0KCQkJCQlwQXJnLT5QdXQoIHBWYXIsIG5DdXJQYXIrKyApOwoJCQkJfQoJCQkJcmVmQXJndiA9IHBBcmc7CgkJCX0KCQl9CgkJLy8gRWlnZW5lIFZhciBhbHMgUGFyYW1ldGVyIDAKCQlyZWZBcmd2LT5QdXQoIHAsIDAgKTsKCQlwLT5TZXRQYXJhbWV0ZXJzKCByZWZBcmd2ICk7CgkJUG9wQXJndigpOwoJfQoJZWxzZQoJCXAtPlNldFBhcmFtZXRlcnMoIE5VTEwgKTsKfQoKLy8gSG9sZW4gZWluZXMgQXJyYXktRWxlbWVudHMKClNieFZhcmlhYmxlKiBTYmlSdW50aW1lOjpDaGVja0FycmF5KCBTYnhWYXJpYWJsZSogcEVsZW0gKQp7CgkvLyBGYWxscyB3aXIgZWluIEFycmF5IGhhYmVuLCB3b2xsZW4gd2lyIGJpdHRlIGRhcyBBcnJheS1FbGVtZW50IQoJU2J4QXJyYXkqIHBQYXI7CglpZiggcEVsZW0tPkdldFR5cGUoKSAmIFNieEFSUkFZICkKCXsKCQlTYnhCYXNlKiBwRWxlbU9iaiA9IHBFbGVtLT5HZXRPYmplY3QoKTsKCQlTYnhEaW1BcnJheSogcERpbUFycmF5ID0gUFRSX0NBU1QoU2J4RGltQXJyYXkscEVsZW1PYmopOwoJCXBQYXIgPSBwRWxlbS0+R2V0UGFyYW1ldGVycygpOwoJCWlmKCBwRGltQXJyYXkgKQoJCXsKCQkJLy8gRGllIFBhcmFtZXRlciBrb2VubmVuIGZlaGxlbiwgd2VubiBlaW4gQXJyYXkgYWxzCgkJCS8vIEFyZ3VtZW50IHVlYmVyZ2ViZW4gd2lyZC4KCQkJaWYoIHBQYXIgKQoJCQkJcEVsZW0gPSBwRGltQXJyYXktPkdldCggcFBhciApOwoJCX0KCQllbHNlCgkJewoJCQlTYnhBcnJheSogcEFycmF5ID0gUFRSX0NBU1QoU2J4QXJyYXkscEVsZW1PYmopOwoJCQlpZiggcEFycmF5ICkKCQkJewoJCQkJaWYoICFwUGFyICkKCQkJCXsKCQkJCQlFcnJvciggU2JFUlJfT1VUX09GX1JBTkdFICk7CgkJCQkJcEVsZW0gPSBuZXcgU2J4VmFyaWFibGU7CgkJCQl9CgkJCQllbHNlCgkJCQkJcEVsZW0gPSBwQXJyYXktPkdldCggcFBhci0+R2V0KCAxICktPkdldEludGVnZXIoKSApOwoJCQl9CgkJfQoKCQkvLyAjNDI5NDAsIDAuUGFyYW1ldGVyIHp1IE5VTEwgc2V0emVuLCBkYW1pdCBzaWNoIFZhciBuaWNodCBzZWxic3QgaGFlbHQKCQlpZiggcFBhciApCgkJCXBQYXItPlB1dCggTlVMTCwgMCApOwoJfQoJLy8gSW5kZXgtQWNjZXNzIGJlaSBVbm9PYmpla3RlbiBiZXJ1ZWNrc2ljaHRpZ2VuCgllbHNlIGlmKCBwRWxlbS0+R2V0VHlwZSgpID09IFNieE9CSkVDVCAmJiAoIXBFbGVtLT5JU0EoU2J4TWV0aG9kKSB8fCAoYlZCQUVuYWJsZWQgJiYgIXBFbGVtLT5Jc0Jyb2FkY2FzdGVyKCkpICkgKQogICAgewogICAgICAgIHBQYXIgPSBwRWxlbS0+R2V0UGFyYW1ldGVycygpOwogICAgICAgIGlmICggcFBhciApCiAgICAgICAgewogICAgICAgICAgICAvLyBJc3QgZXMgZWluIFVuby1PYmpla3Q/CiAgICAgICAgICAgIFNieEJhc2VSZWYgcE9iaiA9IChTYnhCYXNlKilwRWxlbS0+R2V0T2JqZWN0KCk7CiAgICAgICAgICAgIGlmKCBwT2JqICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYoIHBPYmotPklTQShTYlVub09iamVjdCkgKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIFNiVW5vT2JqZWN0KiBwVW5vT2JqID0gKFNiVW5vT2JqZWN0KikoU2J4QmFzZSopcE9iajsKICAgICAgICAgICAgICAgICAgICBBbnkgYUFueSA9IHBVbm9PYmotPmdldFVub0FueSgpOwoKICAgICAgICAgICAgICAgICAgICBpZiggYUFueS5nZXRWYWx1ZVR5cGUoKS5nZXRUeXBlQ2xhc3MoKSA9PSBUeXBlQ2xhc3NfSU5URVJGQUNFICkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIFJlZmVyZW5jZTwgWEludGVyZmFjZSA+IHggPSAqKFJlZmVyZW5jZTwgWEludGVyZmFjZSA+KilhQW55LmdldFZhbHVlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIFJlZmVyZW5jZTwgWEluZGV4QWNjZXNzID4geEluZGV4QWNjZXNzKCB4LCBVTk9fUVVFUlkgKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCAhYlZCQUVuYWJsZWQgKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIYWJlbiB3aXIgSW5kZXgtQWNjZXNzPwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoIHhJbmRleEFjY2Vzcy5pcygpICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYWxfdUludDMyIG5QYXJhbUNvdW50ID0gKHNhbF91SW50MzIpcFBhci0+Q291bnQoKSAtIDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoIG5QYXJhbUNvdW50ICE9IDEgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RhckJBU0lDOjpFcnJvciggU2JFUlJfQkFEX0FSR1VNRU5UICk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwRWxlbTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluZGV4IGhvbGVuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FsX0ludDMyIG5JbmRleCA9IHBQYXItPkdldCggMSApLT5HZXRMb25nKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmVmZXJlbmNlPCBYSW50ZXJmYWNlID4geFJldDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFueSBhQW55MiA9IHhJbmRleEFjY2Vzcy0+Z2V0QnlJbmRleCggbkluZGV4ICk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFR5cGVDbGFzcyBlVHlwZSA9IGFBbnkyLmdldFZhbHVlVHlwZSgpLmdldFR5cGVDbGFzcygpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiggZVR5cGUgPT0gVHlwZUNsYXNzX0lOVEVSRkFDRSApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4UmV0ID0gKihSZWZlcmVuY2U8IFhJbnRlcmZhY2UgPiopYUFueTIuZ2V0VmFsdWUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24mKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmVpIEV4Y2VwdGlvbiBlcnN0bWFsIGltbWVyIHZvbiBLb252ZXJ0aWVydW5ncy1Qcm9ibGVtIGF1c2dlaGVuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJCQVNJQzo6RXJyb3IoIFNiRVJSX09VVF9PRl9SQU5HRSApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gIzU3ODQ3IEltbWVyIG5ldWUgVmFyaWFibGUgYW5sZWdlbiwgc29uc3QgRmVobGVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZHVyY2ggUHV0T2JqZWN0KE5VTEwpIGJlaSBSZWFkT25seS1Qcm9wZXJ0aWVzLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBFbGVtID0gbmV3IFNieFZhcmlhYmxlKCBTYnhWQVJJQU5UICk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoIHhSZXQuaXMoKSApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhQW55IDw8PSB4UmV0OwoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gIzY3MTczIEtlaW4gTmFtZW4gYW5nZWJlbiwgZGFtaXQgZWNodGVyIEtsYXNzZW4tTmFtZW4gZWludHJhZ2VuIHdpcmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RyaW5nIGFOYW1lOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTYnhPYmplY3RSZWYgeFdyYXBwZXIgPSAoU2J4T2JqZWN0KiluZXcgU2JVbm9PYmplY3QoIGFOYW1lLCBhQW55ICk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBFbGVtLT5QdXRPYmplY3QoIHhXcmFwcGVyICk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBFbGVtLT5QdXRPYmplY3QoIE5VTEwgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydGw6Ok9VU3RyaW5nIHNEZWZhdWx0TWV0aG9kOwoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlZmVyZW5jZTwgWERlZmF1bHRNZXRob2QgPiB4RGZsdE1ldGhvZCggeCwgVU5PX1FVRVJZICk7CgogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCB4RGZsdE1ldGhvZC5pcygpICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzRGVmYXVsdE1ldGhvZCA9IHhEZmx0TWV0aG9kLT5nZXREZWZhdWx0TWV0aG9kTmFtZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiggeEluZGV4QWNjZXNzLmlzKCkgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNEZWZhdWx0TWV0aG9kID0gcnRsOjpPVVN0cmluZyggUlRMX0NPTlNUQVNDSUlfVVNUUklOR1BBUkFNKCAiZ2V0QnlJbmRleCIgKSApOwoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICggc0RlZmF1bHRNZXRob2QuZ2V0TGVuZ3RoKCkgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNieFZhcmlhYmxlKiBtZXRoID0gcFVub09iai0+RmluZCggc0RlZmF1bHRNZXRob2QsIFNieENMQVNTX01FVEhPRCApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNieFZhcmlhYmxlUmVmIHJlZlRlbXAgPSBtZXRoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICggcmVmVGVtcCApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRoLT5TZXRQYXJhbWV0ZXJzKCBwUGFyICk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNieFZhcmlhYmxlKiBwTmV3ID0gbmV3IFNieE1ldGhvZCggKihTYnhNZXRob2QqKW1ldGggKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcEVsZW0gPSBwTmV3OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgLy8gIzQyOTQwLCAwLlBhcmFtZXRlciB6dSBOVUxMIHNldHplbiwgZGFtaXQgc2ljaCBWYXIgbmljaHQgc2VsYnN0IGhhZWx0CiAgICAgICAgICAgICAgICAgICAgcFBhci0+UHV0KCBOVUxMLCAwICk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIGlmKCBwT2JqLT5JU0EoQmFzaWNDb2xsZWN0aW9uKSApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgQmFzaWNDb2xsZWN0aW9uKiBwQ29sID0gKEJhc2ljQ29sbGVjdGlvbiopKFNieEJhc2UqKXBPYmo7CiAgICAgICAgICAgICAgICAgICAgcEVsZW0gPSBuZXcgU2J4VmFyaWFibGUoIFNieFZBUklBTlQgKTsKICAgICAgICAgICAgICAgICAgICBwUGFyLT5QdXQoIHBFbGVtLCAwICk7CiAgICAgICAgICAgICAgICAgICAgcENvbC0+Q29sbEl0ZW0oIHBQYXIgKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoJCQllbHNlIGlmKCBiVkJBRW5hYmxlZCApCS8vICFwT2JqCiAgICAgICAgICAgIHsKCQkJCVNieEFycmF5KiBwUGFyYW0gPSBwRWxlbS0+R2V0UGFyYW1ldGVycygpOwoJCQkJaWYoIHBQYXJhbSAhPSBOVUxMICYmICFwRWxlbS0+SXNTZXQoIFNCWF9WQVJfVE9fRElNICkgKQoJCQkJCUVycm9yKCBTYkVSUl9OT19PQkpFQ1QgKTsKCQkJfQogICAgICAgIH0KICAgIH0KCglyZXR1cm4gcEVsZW07Cn0KCi8vIExhZGVuIGVpbmVzIEVsZW1lbnRzIGF1cyBkZXIgUnVudGltZS1MaWJyYXJ5ICgrU3RyaW5nSUQrVHlwKQoKdm9pZCBTYmlSdW50aW1lOjpTdGVwUlRMKCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiApCnsKCVB1c2hWYXIoIEZpbmRFbGVtZW50KCByQmFzaWMucFJ0bCwgbk9wMSwgbk9wMiwgU2JFUlJfUFJPQ19VTkRFRklORUQsIHNhbF9GYWxzZSApICk7Cn0KCnZvaWQKU2JpUnVudGltZTo6U3RlcEZJTkRfSW1wbCggU2J4T2JqZWN0KiBwT2JqLCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiwgU2JFcnJvciBuTm90Rm91bmQsIHNhbF9Cb29sIGJMb2NhbCwgc2FsX0Jvb2wgYlN0YXRpYyApCnsKCWlmKCAhcmVmTG9jYWxzICkKCQlyZWZMb2NhbHMgPSBuZXcgU2J4QXJyYXk7CglQdXNoVmFyKCBGaW5kRWxlbWVudCggcE9iaiwgbk9wMSwgbk9wMiwgbk5vdEZvdW5kLCBiTG9jYWwsIGJTdGF0aWMgKSApOwp9Ci8vIExhZGVuIGVpbmVyIGxva2FsZW4vZ2xvYmFsZW4gVmFyaWFibGVuICgrU3RyaW5nSUQrVHlwKQoKdm9pZCBTYmlSdW50aW1lOjpTdGVwRklORCggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CglTdGVwRklORF9JbXBsKCBwTW9kLCBuT3AxLCBuT3AyLCBTYkVSUl9QUk9DX1VOREVGSU5FRCwgc2FsX1RydWUgKTsKfQoKLy8gU2VhcmNoIGluc2lkZSBhIGNsYXNzIG1vZHVsZSAoQ00pIHRvIGVuYWJsZSBnbG9iYWwgc2VhcmNoIGluIHRpbWUKdm9pZCBTYmlSdW50aW1lOjpTdGVwRklORF9DTSggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CgoJU2JDbGFzc01vZHVsZU9iamVjdCogcENsYXNzTW9kdWxlT2JqZWN0ID0gUFRSX0NBU1QoU2JDbGFzc01vZHVsZU9iamVjdCxwTW9kKTsKCWlmKCBwQ2xhc3NNb2R1bGVPYmplY3QgKQoJCXBNb2QtPlNldEZsYWcoIFNCWF9HQkxTRUFSQ0ggKTsKCglTdGVwRklORF9JbXBsKCBwTW9kLCBuT3AxLCBuT3AyLCBTYkVSUl9QUk9DX1VOREVGSU5FRCwgc2FsX1RydWUgKTsKCglpZiggcENsYXNzTW9kdWxlT2JqZWN0ICkKCQlwTW9kLT5SZXNldEZsYWcoIFNCWF9HQkxTRUFSQ0ggKTsKfQoKdm9pZCBTYmlSdW50aW1lOjpTdGVwRklORF9TVEFUSUMoIHNhbF91SW50MzIgbk9wMSwgc2FsX3VJbnQzMiBuT3AyICkKewoJU3RlcEZJTkRfSW1wbCggcE1vZCwgbk9wMSwgbk9wMiwgU2JFUlJfUFJPQ19VTkRFRklORUQsIHNhbF9UcnVlLCBzYWxfVHJ1ZSApOwp9CgovLyBMYWRlbiBlaW5lcyBPYmpla3QtRWxlbWVudHMgKCtTdHJpbmdJRCtUeXApCi8vIERhcyBPYmpla3QgbGllZ3QgYXVmIFRPUwoKdm9pZCBTYmlSdW50aW1lOjpTdGVwRUxFTSggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CgkvLyBMaWVndCBhdWYgZGVtIFRPUyBlaW4gT2JqZWt0PwoJU2J4VmFyaWFibGVSZWYgcE9ialZhciA9IFBvcFZhcigpOwoKCVNieE9iamVjdCogcE9iaiA9IFBUUl9DQVNUKFNieE9iamVjdCwoU2J4VmFyaWFibGUqKSBwT2JqVmFyKTsKCWlmKCAhcE9iaiApCgl7CgkJU2J4QmFzZSogcE9ialZhck9iaiA9IHBPYmpWYXItPkdldE9iamVjdCgpOwoJCXBPYmogPSBQVFJfQ0FTVChTYnhPYmplY3QscE9ialZhck9iaik7Cgl9CgoJLy8gIzU2MzY4IEJlaSBTdGVwRWxlbSBSZWZlcmVueiBzaWNoZXJuLCBzb25zdCBrb2VubmVuIE9iamVrdGUKCS8vIGluIFF1YWxpZml6aWVydW5nc2tldHRlbiB3aWUgQWN0aXZlQ29tcG9uZW50LlNlbGVjdGlvbigwKS5UZXh0CgkvLyB6dSBmdWVoIGRpZSBSZWZlcmVueiB2ZXJsaWVyZW4KCS8vICM3NDI1NCBKZXR6dCBwZXIgTGlzdGUKCWlmKCBwT2JqICkKCQlTYXZlUmVmKCAoU2J4VmFyaWFibGUqKXBPYmogKTsKCglQdXNoVmFyKCBGaW5kRWxlbWVudCggcE9iaiwgbk9wMSwgbk9wMiwgU2JFUlJfTk9fTUVUSE9ELCBzYWxfRmFsc2UgKSApOwp9CgovLyBMYWRlbiBlaW5lcyBQYXJhbWV0ZXJzICgrT2Zmc2V0K1R5cCkKLy8gV2VubiBkZXIgRGF0ZW50eXAgbmljaHQgc3RpbW1lbiBzb2xsdGUsIGVpbmUgS29waWUgYW5sZWdlbgovLyBEZXIgRGF0ZW50eXAgU2J4RU1QVFkgemVpZ3QgYW4sIGRhYSBrZWluIFBhcmFtZXRlciBhbmdlZ2ViZW4gaXN0LgovLyBHZXQoIDAgKSBkYXJmIEVNUFRZIHNlaW4KCnZvaWQgU2JpUnVudGltZTo6U3RlcFBBUkFNKCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiApCnsKCXNhbF91SW50MTYgaSA9IHN0YXRpY19jYXN0PHNhbF91SW50MTY+KCBuT3AxICYgMHg3RkZGICk7CglTYnhEYXRhVHlwZSB0ID0gKFNieERhdGFUeXBlKSBuT3AyOwoJU2J4VmFyaWFibGUqIHA7CgoJLy8gIzU3OTE1IE1pc3Npbmcgc2F1YmVyZXIgbG9lc2VuCglzYWxfdUludDE2IG5QYXJhbUNvdW50ID0gcmVmUGFyYW1zLT5Db3VudCgpOwoJaWYoIGkgPj0gblBhcmFtQ291bnQgKQoJewoJCXNhbF9JbnQxNiBpTG9vcCA9IGk7CgkJd2hpbGUoIGlMb29wID49IG5QYXJhbUNvdW50ICkKCQl7CgkJCXAgPSBuZXcgU2J4VmFyaWFibGUoKTsKCgkJCWlmKCBTYmlSdW50aW1lOjppc1ZCQUVuYWJsZWQoKSAmJgoJCQkJKHQgPT0gU2J4T0JKRUNUIHx8IHQgPT0gU2J4U1RSSU5HKSApIAoJCQl7CgkJCQlpZiggdCA9PSBTYnhPQkpFQ1QgKQoJCQkJCXAtPlB1dE9iamVjdCggTlVMTCApOwoJCQkJZWxzZQoJCQkJCXAtPlB1dFN0cmluZyggU3RyaW5nKCkgKTsKCQkJfQoJCQllbHNlCgkJCQlwLT5QdXRFcnIoIDQ0OCApOwkJLy8gV2llIGluIFZCOiBFcnJvci1Db2RlIDQ0OCAoU2JFUlJfTkFNRURfTk9UX0ZPVU5EKQoKCQkJcmVmUGFyYW1zLT5QdXQoIHAsIGlMb29wICk7CgkJCWlMb29wLS07CgkJfQoJfQoJcCA9IHJlZlBhcmFtcy0+R2V0KCBpICk7CgoJaWYoIHAtPkdldFR5cGUoKSA9PSBTYnhFUlJPUiAmJiAoIGkgKSApCgkvL2lmKCBwLT5HZXRUeXBlKCkgPT0gU2J4RU1QVFkgJiYgKCBpICkgKQoJewoJCS8vIFdlbm4gZWluIFBhcmFtZXRlciBmZWhsdCwga2FubiBlciBPUFRJT05BTCBzZWluCgkJc2FsX0Jvb2wgYk9wdCA9IHNhbF9GYWxzZTsKCQlpZiggcE1ldGggKQoJCXsKICAgICAgICAgICAgU2J4SW5mbyogcEluZm8gPSBwTWV0aC0+R2V0SW5mbygpOwogICAgICAgICAgICBpZiAoIHBJbmZvICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY29uc3QgU2J4UGFyYW1JbmZvKiBwUGFyYW0gPSBwSW5mby0+R2V0UGFyYW0oIGkgKTsKICAgICAgICAgICAgICAgIGlmKCBwUGFyYW0gJiYgKCAocFBhcmFtLT5uRmxhZ3MgJiBTQlhfT1BUSU9OQUwpICE9IDAgKSApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gRGVmYXVsdCB2YWx1ZT8KICAgICAgICAgICAgICAgICAgICBzYWxfdUludDE2IG5EZWZhdWx0SWQgPSBzYWw6OnN0YXRpY19pbnRfY2FzdDwgc2FsX3VJbnQxNiA+KAogICAgICAgICAgICAgICAgICAgICAgICBwUGFyYW0tPm5Vc2VyRGF0YSAmIDB4ZmZmZiApOwogICAgICAgICAgICAgICAgICAgIGlmKCBuRGVmYXVsdElkID4gMCApCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBTdHJpbmcgYURlZmF1bHRTdHIgPSBwSW1nLT5HZXRTdHJpbmcoIG5EZWZhdWx0SWQgKTsKICAgICAgICAgICAgICAgICAgICAgICAgcCA9IG5ldyBTYnhWYXJpYWJsZSgpOwogICAgICAgICAgICAgICAgICAgICAgICBwLT5QdXRTdHJpbmcoIGFEZWZhdWx0U3RyICk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlZlBhcmFtcy0+UHV0KCBwLCBpICk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJPcHQgPSBzYWxfVHJ1ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoJCX0KCQlpZiggYk9wdCA9PSBzYWxfRmFsc2UgKQoJCQlFcnJvciggU2JFUlJfTk9UX09QVElPTkFMICk7Cgl9CgllbHNlIGlmKCB0ICE9IFNieFZBUklBTlQgJiYgKFNieERhdGFUeXBlKShwLT5HZXRUeXBlKCkgJiAweDBGRkYgKSAhPSB0ICkKCXsKCQlTYnhWYXJpYWJsZSogcSA9IG5ldyBTYnhWYXJpYWJsZSggdCApOwoJCVNhdmVSZWYoIHEgKTsKCQkqcSA9ICpwOwoJCXAgPSBxOwoJfQoJU2V0dXBBcmdzKCBwLCBuT3AxICk7CglQdXNoVmFyKCBDaGVja0FycmF5KCBwICkgKTsKfQoKLy8gQ2FzZS1UZXN0ICgrVHJ1ZS1UYXJnZXQrVGVzdC1PcGNvZGUpCgp2b2lkIFNiaVJ1bnRpbWU6OlN0ZXBDQVNFSVMoIHNhbF91SW50MzIgbk9wMSwgc2FsX3VJbnQzMiBuT3AyICkKewoJaWYoICFyZWZDYXNlU3RrIHx8ICFyZWZDYXNlU3RrLT5Db3VudCgpICkKCQlTdGFyQkFTSUM6OkZhdGFsRXJyb3IoIFNiRVJSX0lOVEVSTkFMX0VSUk9SICk7CgllbHNlCgl7CgkJU2J4VmFyaWFibGVSZWYgeENvbXAgPSBQb3BWYXIoKTsKCQlTYnhWYXJpYWJsZVJlZiB4Q2FzZSA9IHJlZkNhc2VTdGstPkdldCggcmVmQ2FzZVN0ay0+Q291bnQoKSAtIDEgKTsKCQlpZiggeENhc2UtPkNvbXBhcmUoIChTYnhPcGVyYXRvcikgbk9wMiwgKnhDb21wICkgKQoJCQlTdGVwSlVNUCggbk9wMSApOwoJfQp9CgovLyBBdWZydWYgZWluZXIgRExMLVByb3plZHVyICgrU3RyaW5nSUQrVHlwKQovLyBBdWNoIGhpZXIgemVpZ3QgZGFzIE1TQiBkZXMgU3RyaW5nSURzIGFuLCBkYXNzIEFyZ3YgYmVsZWd0IGlzdAoKdm9pZCBTYmlSdW50aW1lOjpTdGVwQ0FMTCggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CglTdHJpbmcgYU5hbWUgPSBwSW1nLT5HZXRTdHJpbmcoIHN0YXRpY19jYXN0PHNob3J0Piggbk9wMSAmIDB4N0ZGRiApICk7CglTYnhBcnJheSogcEFyZ3MgPSBOVUxMOwoJaWYoIG5PcDEgJiAweDgwMDAgKQoJCXBBcmdzID0gcmVmQXJndjsKCURsbENhbGwoIGFOYW1lLCBhTGliTmFtZSwgcEFyZ3MsIChTYnhEYXRhVHlwZSkgbk9wMiwgc2FsX0ZhbHNlICk7CglhTGliTmFtZSA9IFN0cmluZygpOwoJaWYoIG5PcDEgJiAweDgwMDAgKQoJCVBvcEFyZ3YoKTsKfQoKLy8gQXVmcnVmIGVpbmVyIERMTC1Qcm96ZWR1ciBuYWNoIENEZWNsICgrU3RyaW5nSUQrVHlwKQovLyBBdWNoIGhpZXIgemVpZ3QgZGFzIE1TQiBkZXMgU3RyaW5nSURzIGFuLCBkYXNzIEFyZ3YgYmVsZWd0IGlzdAoKdm9pZCBTYmlSdW50aW1lOjpTdGVwQ0FMTEMoIHNhbF91SW50MzIgbk9wMSwgc2FsX3VJbnQzMiBuT3AyICkKewoJU3RyaW5nIGFOYW1lID0gcEltZy0+R2V0U3RyaW5nKCBzdGF0aWNfY2FzdDxzaG9ydD4oIG5PcDEgJiAweDdGRkYgKSApOwoJU2J4QXJyYXkqIHBBcmdzID0gTlVMTDsKCWlmKCBuT3AxICYgMHg4MDAwICkKCQlwQXJncyA9IHJlZkFyZ3Y7CglEbGxDYWxsKCBhTmFtZSwgYUxpYk5hbWUsIHBBcmdzLCAoU2J4RGF0YVR5cGUpIG5PcDIsIHNhbF9UcnVlICk7CglhTGliTmFtZSA9IFN0cmluZygpOwoJaWYoIG5PcDEgJiAweDgwMDAgKQoJCVBvcEFyZ3YoKTsKfQoKCi8vIEJlZ2lubiBlaW5lcyBTdGF0ZW1lbnRzICgrTGluZStDb2wpCgp2b2lkIFNiaVJ1bnRpbWU6OlN0ZXBTVE1OVCggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CgkvLyBXZW5uIGRlciBFeHByLVN0YWNrIGFtIEFuZmFuZyBlaW5lbiBTdGF0ZW1lbnRzIGVpbmUgVmFyaWFibGUgZW50aGFlbHQsCgkvLyBoYXQgZWluIFRyb3R0ZWwgWCBhbHMgRnVua3Rpb24gYXVmZ2VydWZlbiwgb2J3b2hsIGVzIGVpbmUgVmFyaWFibGUgaXN0IQoJc2FsX0Jvb2wgYkZhdGFsRXhwciA9IHNhbF9GYWxzZTsKICAgIFN0cmluZyBzVW5rbm93bk1ldGhvZE5hbWU7CglpZiggbkV4cHJMdmwgPiAxICkKCQliRmF0YWxFeHByID0gc2FsX1RydWU7CgllbHNlIGlmKCBuRXhwckx2bCApCgl7CgkJU2J4VmFyaWFibGUqIHAgPSByZWZFeHByU3RrLT5HZXQoIDAgKTsKCQlpZiggcC0+R2V0UmVmQ291bnQoKSA+IDEKCQkgJiYgcmVmTG9jYWxzLklzKCkgJiYgcmVmTG9jYWxzLT5GaW5kKCBwLT5HZXROYW1lKCksIHAtPkdldENsYXNzKCkgKSApCiAgICAgICAgewogICAgICAgICAgICBzVW5rbm93bk1ldGhvZE5hbWUgPSBwLT5HZXROYW1lKCk7CgkJCWJGYXRhbEV4cHIgPSBzYWxfVHJ1ZTsKICAgICAgICB9Cgl9CgkvLyBEZXIgRXhwci1TdGFjayBpc3QgbnVuIG5pY2h0IG1laHIgbm90d2VuZGlnCglDbGVhckV4cHJTdGFjaygpOwoKCS8vICM1NjM2OCBLdWVuc3RsaWNoZSBSZWZlcmVueiBmdWVyIFN0ZXBFbGVtIHdpZWRlciBmcmVpZ2ViZW4sCgkvLyBkYW1pdCBzaWUgbmljaHQgdWViZXIgZWluIFN0YXRlbWVudCBoaW5hdXMgZXJoYWx0ZW4gYmxlaWJ0CgkvL3JlZlNhdmVPYmogPSBOVUxMOwoJLy8gIzc0MjU0IEpldHp0IHBlciBMaXN0ZQoJQ2xlYXJSZWZzKCk7CgoJLy8gV2lyIG11ZXNzZW4gaGllciBoYXJ0IGFiYnJlY2hlbiwgZGEgc29uc3QgWmVpbGUgdW5kIFNwYWx0ZSBuaWNodCBtZWhyCgkvLyBzdGltbWVuIQoJaWYoIGJGYXRhbEV4cHIpCgl7CgkJU3RhckJBU0lDOjpGYXRhbEVycm9yKCBTYkVSUl9OT19NRVRIT0QsIHNVbmtub3duTWV0aG9kTmFtZSApOwoJCXJldHVybjsKCX0KCXBTdG1udCA9IHBDb2RlIC0gOTsKCXNhbF91SW50MTYgbk9sZCA9IG5MaW5lOwoJbkxpbmUgPSBzdGF0aWNfY2FzdDxzaG9ydD4oIG5PcDEgKTsKCgkvLyAjMjk5NTUgJiAweEZGLCB1bSBmb3ItU2NobGVpZmVuLUViZW5lIHdlZ3p1ZmlsdGVybgoJbkNvbDEgPSBzdGF0aWNfY2FzdDxzaG9ydD4oIG5PcDIgJiAweEZGICk7CgoJLy8gU3VjaGVuIGRlcyBuYWVjaHN0ZW4gU1RNTlQtQmVmZWhscywKCS8vIHVtIGRpZSBFbmQtU3BhbHRlIGRpZXNlcyBTdGF0ZW1lbnRzIHp1IHNldHplbgoJLy8gU2VhcmNoZXMgb2YgdGhlIG5leHQgU1RNTlQgaW5zdHJ1Y3Rpb24sCgkvLyBhcm91bmQgdGhlIGZpbmFsIGNvbHVtbiBvZiB0aGlzIHN0YXRlbWVudCB0byBzZXQKCgluQ29sMiA9IDB4ZmZmZjsKCXNhbF91SW50MTYgbjEsIG4yOwoJY29uc3Qgc2FsX3VJbnQ4KiBwID0gcE1vZC0+RmluZE5leHRTdG1udCggcENvZGUsIG4xLCBuMiApOwoJaWYoIHAgKQoJewoJCWlmKCBuMSA9PSBuT3AxICkKCQl7CgkJCS8vICMyOTk1NSAmIDB4RkYsIHVtIGZvci1TY2hsZWlmZW4tRWJlbmUgd2VnenVmaWx0ZXJuCgkJCW5Db2wyID0gKG4yICYgMHhGRikgLSAxOwoJCX0KCX0KCgkvLyAjMjk5NTUgZm9yLVNjaGxlaWZlbi1FYmVuZSBrb3JyaWdpZXJlbiwgIzY3NDUyIE5JQ0hUIGltIEVycm9yLUhhbmRsZXIgc29uc3QgQ2hhb3MKCWlmKCAhYkluRXJyb3IgKQoJewoJCS8vIChCZWkgU3By/G5nZW4gYXVzIFNjaGxlaWZlbiB0cml0dCBoaWVyIGVpbmUgRGlmZmVyZW56IGF1ZikKCQlzYWxfdUludDE2IG5FeHNwZWN0ZWRGb3JMZXZlbCA9IHN0YXRpY19jYXN0PHNhbF91SW50MTY+KCBuT3AyIC8gMHgxMDAgKTsKCQlpZiggcEdvc3ViU3RrICkKCQkJbkV4c3BlY3RlZEZvckxldmVsID0gbkV4c3BlY3RlZEZvckxldmVsICsgcEdvc3ViU3RrLT5uU3RhcnRGb3JMdmw7CgoJCS8vIFdlbm4gZGVyIHRhdHNhZWNobGljaGUgRm9yLUxldmVsIHp1IGtsZWluIGlzdCwgd3VyZGUgYXVzCgkJLy8gZWluZXIgU2NobGVpZmUgaGVyYXVzIGdlc3BydW5nZW4gLT4ga29ycmlnaWVyZW4KCQl3aGlsZSggbkZvckx2bCA+IG5FeHNwZWN0ZWRGb3JMZXZlbCApCgkJCVBvcEZvcigpOwoJfQoKCS8vIDE2LjEwLjk2OiAjMzE0NjAgTmV1ZXMgS29uemVwdCBmdWVyIFN0ZXBJbnRvL092ZXIvT3V0CgkvLyBFcmts5HJ1bmcgc2llaGUgYmVpIF9JbXBsR2V0QnJlYWtDYWxsTGV2ZWwuCglpZiggcEluc3QtPm5DYWxsTHZsIDw9IHBJbnN0LT5uQnJlYWtDYWxsTHZsICkKCS8vaWYoIG5GbGFncyAmIFNiREVCVUdfU1RFUElOVE8gKQoJewoJCVN0YXJCQVNJQyogcFN0ZXBCYXNpYyA9IEdldEN1cnJlbnRCYXNpYyggJnJCYXNpYyApOwoJCXNhbF91SW50MTYgbk5ld0ZsYWdzID0gcFN0ZXBCYXNpYy0+U3RlcFBvaW50KCBuTGluZSwgbkNvbDEsIG5Db2wyICk7CgoJCS8vIE5ldWVuIEJyZWFrQ2FsbExldmVsIGVybWl0dGVsbgoJCXBJbnN0LT5DYWxjQnJlYWtDYWxsTGV2ZWwoIG5OZXdGbGFncyApOwoJfQoKCS8vIEJyZWFrcG9pbnRzIG51ciBiZWkgU1RNTlQtQmVmZWhsZW4gaW4gbmV1ZXIgWmVpbGUhCgllbHNlIGlmKCAoIG5PcDEgIT0gbk9sZCApCgkJJiYgKCBuRmxhZ3MgJiBTYkRFQlVHX0JSRUFLICkKCQkmJiBwTW9kLT5Jc0JQKCBzdGF0aWNfY2FzdDxzYWxfdUludDE2Piggbk9wMSApICkgKQoJewoJCVN0YXJCQVNJQyogcEJyZWFrQmFzaWMgPSBHZXRDdXJyZW50QmFzaWMoICZyQmFzaWMgKTsKCQlzYWxfdUludDE2IG5OZXdGbGFncyA9IHBCcmVha0Jhc2ljLT5CcmVha1BvaW50KCBuTGluZSwgbkNvbDEsIG5Db2wyICk7CgoJCS8vIE5ldWVuIEJyZWFrQ2FsbExldmVsIGVybWl0dGVsbgoJCXBJbnN0LT5DYWxjQnJlYWtDYWxsTGV2ZWwoIG5OZXdGbGFncyApOwoJCS8vMTYuMTAuOTYsIEFMVDoKCQkvL2lmKCBuTmV3RmxhZ3MgIT0gU2JERUJVR19DT05USU5VRSApCgkJLy8JbkZsYWdzID0gbk5ld0ZsYWdzOwoJfQp9CgovLyAoK1N2U3RyZWFtRmxhZ3MrRmxhZ3MpCi8vIFN0YWNrOiBCbG9ja2xhZW5nZQovLyAgICAgICAgS2FuYWxudW1tZXIKLy8gICAgICAgIERhdGVpbmFtZQoKdm9pZCBTYmlSdW50aW1lOjpTdGVwT1BFTiggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CglTYnhWYXJpYWJsZVJlZiBwTmFtZSA9IFBvcFZhcigpOwoJU2J4VmFyaWFibGVSZWYgcENoYW4gPSBQb3BWYXIoKTsKCVNieFZhcmlhYmxlUmVmIHBMZW4gID0gUG9wVmFyKCk7CglzaG9ydCBuQmxrTGVuID0gcExlbi0+R2V0SW50ZWdlcigpOwoJc2hvcnQgbkNoYW4gICA9IHBDaGFuLT5HZXRJbnRlZ2VyKCk7CglCeXRlU3RyaW5nIGFOYW1lKCBwTmFtZS0+R2V0U3RyaW5nKCksIGdzbF9nZXRTeXN0ZW1UZXh0RW5jb2RpbmcoKSApOwoJcElvc3lzLT5PcGVuKCBuQ2hhbiwgYU5hbWUsIHN0YXRpY19jYXN0PHNob3J0Piggbk9wMSApLAoJCXN0YXRpY19jYXN0PHNob3J0Piggbk9wMiApLCBuQmxrTGVuICk7CglFcnJvciggcElvc3lzLT5HZXRFcnJvcigpICk7Cn0KCi8vIE9iamVrdCBrcmVpZXJlbiAoK1N0cmluZ0lEK1N0cmluZ0lEKQoKdm9pZCBTYmlSdW50aW1lOjpTdGVwQ1JFQVRFKCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiApCnsKCVN0cmluZyBhQ2xhc3MoIHBJbWctPkdldFN0cmluZyggc3RhdGljX2Nhc3Q8c2hvcnQ+KCBuT3AyICkgKSApOwoJU2J4T2JqZWN0ICpwT2JqID0gU2J4QmFzZTo6Q3JlYXRlT2JqZWN0KCBhQ2xhc3MgKTsKCWlmKCAhcE9iaiApCgkJRXJyb3IoIFNiRVJSX0lOVkFMSURfT0JKRUNUICk7CgllbHNlCgl7CgkJU3RyaW5nIGFOYW1lKCBwSW1nLT5HZXRTdHJpbmcoIHN0YXRpY19jYXN0PHNob3J0Piggbk9wMSApICkgKTsKCQlwT2JqLT5TZXROYW1lKCBhTmFtZSApOwoJLy8gRGFzIE9iamVrdCBtdXNzIEJBU0lDIHJ1ZmVuIGtvZW5uZW4KCQlwT2JqLT5TZXRQYXJlbnQoICZyQmFzaWMgKTsKCQlTYnhWYXJpYWJsZSogcE5ldyA9IG5ldyBTYnhWYXJpYWJsZTsKCQlwTmV3LT5QdXRPYmplY3QoIHBPYmogKTsKCQlQdXNoVmFyKCBwTmV3ICk7Cgl9Cn0KCnZvaWQgU2JpUnVudGltZTo6U3RlcERDUkVBVEUoIHNhbF91SW50MzIgbk9wMSwgc2FsX3VJbnQzMiBuT3AyICkKewogICAgU3RlcERDUkVBVEVfSU1QTCggbk9wMSwgbk9wMiApOwp9Cgp2b2lkIFNiaVJ1bnRpbWU6OlN0ZXBEQ1JFQVRFX1JFRElNUCggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CiAgICBTdGVwRENSRUFURV9JTVBMKCBuT3AxLCBuT3AyICk7Cn0KCgovLyBIZWxwZXIgZnVuY3Rpb24gZm9yIFN0ZXBEQ1JFQVRFX0lNUEwgLyBiUmVkaW1wID0gdHJ1ZQp2b2lkIGltcGxDb3B5RGltQXJyYXlfRENSRUFURSggU2J4RGltQXJyYXkqIHBOZXdBcnJheSwgU2J4RGltQXJyYXkqIHBPbGRBcnJheSwgc2hvcnQgbk1heERpbUluZGV4LAoJc2hvcnQgbkFjdHVhbERpbSwgc2FsX0ludDMyKiBwQWN0dWFsSW5kaWNlcywgc2FsX0ludDMyKiBwTG93ZXJCb3VuZHMsIHNhbF9JbnQzMiogcFVwcGVyQm91bmRzICkKewoJc2FsX0ludDMyJiByaSA9IHBBY3R1YWxJbmRpY2VzW25BY3R1YWxEaW1dOwoJZm9yKCByaSA9IHBMb3dlckJvdW5kc1tuQWN0dWFsRGltXSA7IHJpIDw9IHBVcHBlckJvdW5kc1tuQWN0dWFsRGltXSA7IHJpKysgKQoJewoJCWlmKCBuQWN0dWFsRGltIDwgbk1heERpbUluZGV4ICkKCQl7CgkJCWltcGxDb3B5RGltQXJyYXlfRENSRUFURSggcE5ld0FycmF5LCBwT2xkQXJyYXksIG5NYXhEaW1JbmRleCwgbkFjdHVhbERpbSArIDEsCgkJCQlwQWN0dWFsSW5kaWNlcywgcExvd2VyQm91bmRzLCBwVXBwZXJCb3VuZHMgKTsKCQl9CgkJZWxzZQoJCXsKCQkJU2J4VmFyaWFibGUqIHBTb3VyY2UgPSBwT2xkQXJyYXktPkdldDMyKCBwQWN0dWFsSW5kaWNlcyApOwogICAgICAgICAgICBwTmV3QXJyYXktPlB1dDMyKCBwU291cmNlLCBwQWN0dWFsSW5kaWNlcyApOwoJCX0KCX0KfQoKLy8gIzU2MjA0IE9iamVrdC1BcnJheSBrcmVpZXJlbiAoK1N0cmluZ0lEK1N0cmluZ0lEKSwgRENSRUFURSA9PSBEaW0tQ3JlYXRlCnZvaWQgU2JpUnVudGltZTo6U3RlcERDUkVBVEVfSU1QTCggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CglTYnhWYXJpYWJsZVJlZiByZWZWYXIgPSBQb3BWYXIoKTsKCglEaW1JbXBsKCByZWZWYXIgKTsKCgkvLyBEYXMgQXJyYXkgbWl0IEluc3RhbnplbiBkZXIgZ2Vmb3JkZXJ0ZW4gS2xhc3NlIGZ1ZWxsZW4KCVNieEJhc2VSZWYgeE9iaiA9IChTYnhCYXNlKilyZWZWYXItPkdldE9iamVjdCgpOwoJaWYoICF4T2JqICkKCXsKCQlTdGFyQkFTSUM6OkVycm9yKCBTYkVSUl9JTlZBTElEX09CSkVDVCApOwoJCXJldHVybjsKCX0KCiAgICBTYnhEaW1BcnJheSogcEFycmF5ID0gMDsKCWlmKCB4T2JqLT5JU0EoU2J4RGltQXJyYXkpICkKCXsKCQlTYnhCYXNlKiBwT2JqID0gKFNieEJhc2UqKXhPYmo7CgkJcEFycmF5ID0gKFNieERpbUFycmF5KilwT2JqOwoKCQkvLyBEaW1lbnNpb25lbiBhdXN3ZXJ0ZW4KCQlzaG9ydCBuRGltcyA9IHBBcnJheS0+R2V0RGltcygpOwoJCXNhbF9JbnQzMiBuVG90YWxTaXplID0gMDsKCgkJLy8gZXMgbXVzcyBlaW4gZWluZGltZW5zaW9uYWxlcyBBcnJheSBzZWluCgkJc2FsX0ludDMyIG5Mb3dlciwgblVwcGVyLCBuU2l6ZTsKCQlzYWxfSW50MzIgaTsKCQlmb3IoIGkgPSAwIDsgaSA8IG5EaW1zIDsgaSsrICkKCQl7CgkJCXBBcnJheS0+R2V0RGltMzIoIGkrMSwgbkxvd2VyLCBuVXBwZXIgKTsKCQkJblNpemUgPSBuVXBwZXIgLSBuTG93ZXIgKyAxOwoJCQlpZiggaSA9PSAwICkKCQkJCW5Ub3RhbFNpemUgPSBuU2l6ZTsKCQkJZWxzZQoJCQkJblRvdGFsU2l6ZSAqPSBuU2l6ZTsKCQl9CgoJCS8vIE9iamVrdGUgYW5sZWdlbiB1bmQgaW5zIEFycmF5IGVpbnRyYWdlbgoJCVN0cmluZyBhQ2xhc3MoIHBJbWctPkdldFN0cmluZyggc3RhdGljX2Nhc3Q8c2hvcnQ+KCBuT3AyICkgKSApOwoJCWZvciggaSA9IDAgOyBpIDwgblRvdGFsU2l6ZSA7IGkrKyApCgkJewoJCQlTYnhPYmplY3QgKnBDbGFzc09iaiA9IFNieEJhc2U6OkNyZWF0ZU9iamVjdCggYUNsYXNzICk7CgkJCWlmKCAhcENsYXNzT2JqICkKCQkJewoJCQkJRXJyb3IoIFNiRVJSX0lOVkFMSURfT0JKRUNUICk7CgkJCQlicmVhazsKCQkJfQoJCQllbHNlCgkJCXsKCQkJCVN0cmluZyBhTmFtZSggcEltZy0+R2V0U3RyaW5nKCBzdGF0aWNfY2FzdDxzaG9ydD4oIG5PcDEgKSApICk7CgkJCQlwQ2xhc3NPYmotPlNldE5hbWUoIGFOYW1lICk7CgkJCQkvLyBEYXMgT2JqZWt0IG11c3MgQkFTSUMgcnVmZW4ga29lbm5lbgoJCQkJcENsYXNzT2JqLT5TZXRQYXJlbnQoICZyQmFzaWMgKTsKCQkJCXBBcnJheS0+U2J4QXJyYXk6OlB1dDMyKCBwQ2xhc3NPYmosIGkgKTsKCQkJfQoJCX0KCX0KCglTYnhEaW1BcnJheSogcE9sZEFycmF5ID0gKFNieERpbUFycmF5KikoU2J4QXJyYXkqKXJlZlJlZGltcEFycmF5OwoJaWYoIHBBcnJheSAmJiBwT2xkQXJyYXkgKQoJewoJCXNob3J0IG5EaW1zTmV3ID0gcEFycmF5LT5HZXREaW1zKCk7CgkJc2hvcnQgbkRpbXNPbGQgPSBwT2xkQXJyYXktPkdldERpbXMoKTsKCQlzaG9ydCBuRGltcyA9IG5EaW1zTmV3OwoJCXNhbF9Cb29sIGJSYW5nZUVycm9yID0gc2FsX0ZhbHNlOwoKCQkvLyBTdG9yZSBkaW1zIHRvIHVzZSB0aGVtIGZvciBjb3B5aW5nIGxhdGVyCgkJc2FsX0ludDMyKiBwTG93ZXJCb3VuZHMgPSBuZXcgc2FsX0ludDMyW25EaW1zXTsKCQlzYWxfSW50MzIqIHBVcHBlckJvdW5kcyA9IG5ldyBzYWxfSW50MzJbbkRpbXNdOwoJCXNhbF9JbnQzMiogcEFjdHVhbEluZGljZXMgPSBuZXcgc2FsX0ludDMyW25EaW1zXTsKCQlpZiggbkRpbXNPbGQgIT0gbkRpbXNOZXcgKQoJCXsKCQkJYlJhbmdlRXJyb3IgPSBzYWxfVHJ1ZTsKCQl9CgkJZWxzZQoJCXsKCQkJLy8gQ29tcGFyZSBib3VuZHMKCQkJZm9yKCBzaG9ydCBpID0gMSA7IGkgPD0gbkRpbXMgOyBpKysgKQoJCQl7CgkJCQlzYWxfSW50MzIgbEJvdW5kTmV3LCB1Qm91bmROZXc7CgkJCQlzYWxfSW50MzIgbEJvdW5kT2xkLCB1Qm91bmRPbGQ7CgkJCQlwQXJyYXktPkdldERpbTMyKCBpLCBsQm91bmROZXcsIHVCb3VuZE5ldyApOwoJCQkJcE9sZEFycmF5LT5HZXREaW0zMiggaSwgbEJvdW5kT2xkLCB1Qm91bmRPbGQgKTsKCgkJCQlsQm91bmROZXcgPSBzdGQ6Om1heCggbEJvdW5kTmV3LCBsQm91bmRPbGQgKTsKCQkJCXVCb3VuZE5ldyA9IHN0ZDo6bWluKCB1Qm91bmROZXcsIHVCb3VuZE9sZCApOwoJCQkJc2hvcnQgaiA9IGkgLSAxOwoJCQkJcEFjdHVhbEluZGljZXNbal0gPSBwTG93ZXJCb3VuZHNbal0gPSBsQm91bmROZXc7CgkJCQlwVXBwZXJCb3VuZHNbal0gPSB1Qm91bmROZXc7CgkJCX0KCQl9CgoJCWlmKCBiUmFuZ2VFcnJvciApCgkJewoJCQlTdGFyQkFTSUM6OkVycm9yKCBTYkVSUl9PVVRfT0ZfUkFOR0UgKTsKCQl9CgkJZWxzZQoJCXsKCQkJLy8gQ29weSBkYXRhIGZyb20gb2xkIGFycmF5IGJ5IGdvaW5nIHJlY3Vyc2l2ZWx5IHRocm91Z2ggYWxsIGRpbWVuc2lvbnMKCQkJLy8gKEl0IHdvdWxkIGJlIGZhc3RlciB0byB3b3JrIG9uIHRoZSBmbGF0IGludGVybmFsIGRhdGEgYXJyYXkgb2YgYW4KCQkJLy8gU2J5QXJyYXkgYnV0IHRoaXMgc29sdXRpb24gaXMgY2xlYXJlciBhbmQgZWFzaWVyKQoJCQlpbXBsQ29weURpbUFycmF5X0RDUkVBVEUoIHBBcnJheSwgcE9sZEFycmF5LCBuRGltcyAtIDEsCgkJCQkwLCBwQWN0dWFsSW5kaWNlcywgcExvd2VyQm91bmRzLCBwVXBwZXJCb3VuZHMgKTsKCQl9CgkJZGVsZXRlIFtdIHBVcHBlckJvdW5kczsKCQlkZWxldGUgW10gcExvd2VyQm91bmRzOwoJCWRlbGV0ZSBbXSBwQWN0dWFsSW5kaWNlczsKCQlyZWZSZWRpbXBBcnJheSA9IE5VTEw7CiAgICB9Cn0KCi8vIE9iamVrdCBhdXMgVXNlci1UeXBlIGtyZWllcmVuICAoK1N0cmluZ0lEK1N0cmluZ0lEKQoKU2J4T2JqZWN0KiBjcmVhdGVVc2VyVHlwZUltcGwoIGNvbnN0IFN0cmluZyYgckNsYXNzTmFtZSApOwkvLyBzYi5jeHgKCnZvaWQgU2JpUnVudGltZTo6U3RlcFRDUkVBVEUoIHNhbF91SW50MzIgbk9wMSwgc2FsX3VJbnQzMiBuT3AyICkKewoJU3RyaW5nIGFOYW1lKCBwSW1nLT5HZXRTdHJpbmcoIHN0YXRpY19jYXN0PHNob3J0Piggbk9wMSApICkgKTsKCVN0cmluZyBhQ2xhc3MoIHBJbWctPkdldFN0cmluZyggc3RhdGljX2Nhc3Q8c2hvcnQ+KCBuT3AyICkgKSApOwoKCVNieE9iamVjdCogcENvcHlPYmogPSBjcmVhdGVVc2VyVHlwZUltcGwoIGFDbGFzcyApOwoJaWYoIHBDb3B5T2JqICkKCQlwQ29weU9iai0+U2V0TmFtZSggYU5hbWUgKTsKCVNieFZhcmlhYmxlKiBwTmV3ID0gbmV3IFNieFZhcmlhYmxlOwoJcE5ldy0+UHV0T2JqZWN0KCBwQ29weU9iaiApOwoJcE5ldy0+U2V0RGVjbGFyZUNsYXNzTmFtZSggYUNsYXNzICk7CglQdXNoVmFyKCBwTmV3ICk7Cn0KCnZvaWQgU2JpUnVudGltZTo6aW1wbEhhbmRsZVNieEZsYWdzKCBTYnhWYXJpYWJsZSogcFZhciwgU2J4RGF0YVR5cGUgdCwgc2FsX3VJbnQzMiBuT3AyICkKewoJYm9vbCBiV2l0aEV2ZW50cyA9ICgodCAmIDB4ZmYpID09IFNieE9CSkVDVCAmJiAobk9wMiAmIFNCWF9UWVBFX1dJVEhfRVZFTlRTX0ZMQUcpICE9IDApOwoJaWYoIGJXaXRoRXZlbnRzICkKCQlwVmFyLT5TZXRGbGFnKCBTQlhfV0lUSF9FVkVOVFMgKTsKCglib29sIGJEaW1Bc05ldyA9ICgobk9wMiAmIFNCWF9UWVBFX0RJTV9BU19ORVdfRkxBRykgIT0gMCk7CglpZiggYkRpbUFzTmV3ICkKCQlwVmFyLT5TZXRGbGFnKCBTQlhfRElNX0FTX05FVyApOwoKCWJvb2wgYkZpeGVkU3RyaW5nID0gKCh0ICYgMHhmZikgPT0gU2J4U1RSSU5HICYmIChuT3AyICYgU0JYX0ZJWEVEX0xFTl9TVFJJTkdfRkxBRykgIT0gMCk7CglpZiggYkZpeGVkU3RyaW5nICkKCXsKCQlzYWxfdUludDE2IG5Db3VudCA9IHN0YXRpY19jYXN0PHNhbF91SW50MTY+KCBuT3AyID4+IDE3ICk7CQkvLyBsZW4gPSBhbGwgYml0cyBhYm92ZSAweDEwMDAwCgkJU3RyaW5nIGFTdHI7CgkJYVN0ci5GaWxsKCBuQ291bnQsIDAgKTsKCQlwVmFyLT5QdXRTdHJpbmcoIGFTdHIgKTsKCX0KCglib29sIGJWYXJUb0RpbSA9ICgobk9wMiAmIFNCWF9UWVBFX1ZBUl9UT19ESU1fRkxBRykgIT0gMCk7CglpZiggYlZhclRvRGltICkKCQlwVmFyLT5TZXRGbGFnKCBTQlhfVkFSX1RPX0RJTSApOwp9CgovLyBFaW5yaWNodGVuIGVpbmVyIGxva2FsZW4gVmFyaWFibGVuICgrU3RyaW5nSUQrVHlwKQoKdm9pZCBTYmlSdW50aW1lOjpTdGVwTE9DQUwoIHNhbF91SW50MzIgbk9wMSwgc2FsX3VJbnQzMiBuT3AyICkKewoJaWYoICFyZWZMb2NhbHMuSXMoKSApCgkJcmVmTG9jYWxzID0gbmV3IFNieEFycmF5OwoJU3RyaW5nIGFOYW1lKCBwSW1nLT5HZXRTdHJpbmcoIHN0YXRpY19jYXN0PHNob3J0Piggbk9wMSApICkgKTsKCWlmKCByZWZMb2NhbHMtPkZpbmQoIGFOYW1lLCBTYnhDTEFTU19ET05UQ0FSRSApID09IE5VTEwgKQoJewoJCVNieERhdGFUeXBlIHQgPSAoU2J4RGF0YVR5cGUpKG5PcDIgJiAweGZmZmYpOwoJCVNieFZhcmlhYmxlKiBwID0gbmV3IFNieFZhcmlhYmxlKCB0ICk7CgkJcC0+U2V0TmFtZSggYU5hbWUgKTsKCQlpbXBsSGFuZGxlU2J4RmxhZ3MoIHAsIHQsIG5PcDIgKTsKCQlyZWZMb2NhbHMtPlB1dCggcCwgcmVmTG9jYWxzLT5Db3VudCgpICk7Cgl9Cn0KCi8vIEVpbnJpY2h0ZW4gZWluZXIgbW9kdWxnbG9iYWxlbiBWYXJpYWJsZW4gKCtTdHJpbmdJRCtUeXApCgp2b2lkIFNiaVJ1bnRpbWU6OlN0ZXBQVUJMSUNfSW1wbCggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIsIGJvb2wgYlVzZWRGb3JDbGFzc01vZHVsZSApCnsKCVN0cmluZyBhTmFtZSggcEltZy0+R2V0U3RyaW5nKCBzdGF0aWNfY2FzdDxzaG9ydD4oIG5PcDEgKSApICk7CglTYnhEYXRhVHlwZSB0ID0gKFNieERhdGFUeXBlKShTYnhEYXRhVHlwZSkobk9wMiAmIDB4ZmZmZik7OwoJc2FsX0Jvb2wgYkZsYWcgPSBwTW9kLT5Jc1NldCggU0JYX05PX01PRElGWSApOwoJcE1vZC0+U2V0RmxhZyggU0JYX05PX01PRElGWSApOwoJU2J4VmFyaWFibGVSZWYgcCA9IHBNb2QtPkZpbmQoIGFOYW1lLCBTYnhDTEFTU19QUk9QRVJUWSApOwoJaWYoIHAuSXMoKSApCgkJcE1vZC0+UmVtb3ZlIChwKTsKCVNiUHJvcGVydHkqIHBQcm9wID0gcE1vZC0+R2V0UHJvcGVydHkoIGFOYW1lLCB0ICk7CglpZiggIWJVc2VkRm9yQ2xhc3NNb2R1bGUgKQoJCXBQcm9wLT5TZXRGbGFnKCBTQlhfUFJJVkFURSApOwoJaWYoICFiRmxhZyApCgkJcE1vZC0+UmVzZXRGbGFnKCBTQlhfTk9fTU9ESUZZICk7CglpZiggcFByb3AgKQoJewoJCXBQcm9wLT5TZXRGbGFnKCBTQlhfRE9OVFNUT1JFICk7CgkJLy8gQUI6IDIuNy4xOTk2OiBIQUNLIHdlZ2VuICdSZWZlcmVueiBrYW5uIG5pY2h0IGdlc2ljaGVydCB3ZXJkZW4nCgkJcFByb3AtPlNldEZsYWcoIFNCWF9OT19NT0RJRlkpOwoKCQlpbXBsSGFuZGxlU2J4RmxhZ3MoIHBQcm9wLCB0LCBuT3AyICk7Cgl9Cn0KCnZvaWQgU2JpUnVudGltZTo6U3RlcFBVQkxJQyggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CglTdGVwUFVCTElDX0ltcGwoIG5PcDEsIG5PcDIsIGZhbHNlICk7Cn0KCnZvaWQgU2JpUnVudGltZTo6U3RlcFBVQkxJQ19QKCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiApCnsKICAgIC8vIENyZWF0ZXMgbW9kdWxlIHZhcmlhYmxlIHRoYXQgaXNuJ3QgcmVpbml0aWFsaXNlZCB3aGVuCiAgICAvLyBiZXR3ZWVuIGludm9jYXRpb25zICggZm9yIFZCQVN1cHBvcnQgJiBkb2N1bWVudCBiYXNpYyBvbmx5ICkKICAgIGlmKCBwTW9kLT5wSW1hZ2UtPmJGaXJzdEluaXQgKQoJewoJCWJvb2wgYlVzZWRGb3JDbGFzc01vZHVsZSA9IHBJbWctPkdldEZsYWcoIFNCSU1HX0NMQVNTTU9EVUxFICk7CgkJU3RlcFBVQkxJQ19JbXBsKCBuT3AxLCBuT3AyLCBiVXNlZEZvckNsYXNzTW9kdWxlICk7Cgl9Cn0KCi8vIEVpbnJpY2h0ZW4gZWluZXIgZ2xvYmFsZW4gVmFyaWFibGVuICgrU3RyaW5nSUQrVHlwKQoKdm9pZCBTYmlSdW50aW1lOjpTdGVwR0xPQkFMKCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiApCnsKCWlmKCBwSW1nLT5HZXRGbGFnKCBTQklNR19DTEFTU01PRFVMRSApICkKCQlTdGVwUFVCTElDX0ltcGwoIG5PcDEsIG5PcDIsIHRydWUgKTsKCglTdHJpbmcgYU5hbWUoIHBJbWctPkdldFN0cmluZyggc3RhdGljX2Nhc3Q8c2hvcnQ+KCBuT3AxICkgKSApOwoJU2J4RGF0YVR5cGUgdCA9IChTYnhEYXRhVHlwZSkobk9wMiAmIDB4ZmZmZik7CgoJLy8gU3RvcmUgbW9kdWxlIHNjb3BlIHZhcmlhYmxlcyBhdCBtb2R1bGUgc2NvcGUgCgkvLyBpbiBub24gdmJhIG1vZGUgdGhlc2UgYXJlIHN0b3JlZCBhdCB0aGUgbGlicmFyeSBsZXZlbCA6LwoJLy8gbm90IHN1cmUgaWYgdGhpcyByZWFsbHkgc2hvdWxkIG5vdCBiZSBlbmFibGVkIGZvciBBTEwgYmFzaWMKCVNieE9iamVjdCogcFN0b3JhZ2UgPSAmckJhc2ljOwoJaWYgKCBTYmlSdW50aW1lOjppc1ZCQUVuYWJsZWQoKSApIAoJewoJCXBTdG9yYWdlID0gcE1vZDsKCQlwTW9kLT5BZGRWYXJOYW1lKCBhTmFtZSApOwoJfQoKCXNhbF9Cb29sIGJGbGFnID0gcFN0b3JhZ2UtPklzU2V0KCBTQlhfTk9fTU9ESUZZICk7CglyQmFzaWMuU2V0RmxhZyggU0JYX05PX01PRElGWSApOwoJU2J4VmFyaWFibGVSZWYgcCA9IHBTdG9yYWdlLT5GaW5kKCBhTmFtZSwgU2J4Q0xBU1NfUFJPUEVSVFkgKTsKCWlmKCBwLklzKCkgKQoJCXBTdG9yYWdlLT5SZW1vdmUgKHApOwoJcCA9IHBTdG9yYWdlLT5NYWtlKCBhTmFtZSwgU2J4Q0xBU1NfUFJPUEVSVFksIHQgKTsKCWlmKCAhYkZsYWcgKQoJCXBTdG9yYWdlLT5SZXNldEZsYWcoIFNCWF9OT19NT0RJRlkgKTsKCWlmKCBwICkKCXsKCQlwLT5TZXRGbGFnKCBTQlhfRE9OVFNUT1JFICk7CgkJLy8gQUI6IDIuNy4xOTk2OiBIQUNLIHdlZ2VuICdSZWZlcmVueiBrYW5uIG5pY2h0IGdlc2ljaGVydCB3ZXJkZW4nCgkJcC0+U2V0RmxhZyggU0JYX05PX01PRElGWSk7Cgl9Cn0KCgovLyBDcmVhdGVzIGdsb2JhbCB2YXJpYWJsZSB0aGF0IGlzbid0IHJlaW5pdGlhbGlzZWQgd2hlbgovLyBiYXNpYyBpcyByZXN0YXJ0ZWQsIFA9UEVSU0lTVCAoK1N0cmluZ0lEK1R5cCkKCnZvaWQgU2JpUnVudGltZTo6U3RlcEdMT0JBTF9QKCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiApCnsKICAgIGlmKCBwTW9kLT5wSW1hZ2UtPmJGaXJzdEluaXQgKQogICAgewogICAgICAgIFN0ZXBHTE9CQUwoIG5PcDEsIG5PcDIgKTsKICAgIH0KfQoKCi8vIFNlYXJjaGVzIGZvciBnbG9iYWwgdmFyaWFibGUsIGJlaGF2aW9yIGRlcGVuZHMgb24gdGhlIGZhY3QKLy8gaWYgdGhlIHZhcmlhYmxlIGlzIGluaXRpYWxpc2VkIGZvciB0aGUgZmlyc3QgdGltZQoKdm9pZCBTYmlSdW50aW1lOjpTdGVwRklORF9HKCBzYWxfdUludDMyIG5PcDEsIHNhbF91SW50MzIgbk9wMiApCnsKICAgIGlmKCBwTW9kLT5wSW1hZ2UtPmJGaXJzdEluaXQgKQogICAgewogICAgICAgIC8vIEJlaGF2ZSBsaWtlIGFsd2F5cyBkdXJpbmcgZmlyc3QgaW5pdAogICAgICAgIFN0ZXBGSU5EKCBuT3AxLCBuT3AyICk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgLy8gUmV0dXJuIGR1bW15IHZhcmlhYmxlCgkJU2J4RGF0YVR5cGUgdCA9IChTYnhEYXRhVHlwZSkgbk9wMjsKCQlTdHJpbmcgYU5hbWUoIHBJbWctPkdldFN0cmluZyggc3RhdGljX2Nhc3Q8c2hvcnQ+KCBuT3AxICYgMHg3RkZGICkgKSApOwoKICAgICAgICBTYnhWYXJpYWJsZSogcER1bW15VmFyID0gbmV3IFNieFZhcmlhYmxlKCB0ICk7CgkJcER1bW15VmFyLT5TZXROYW1lKCBhTmFtZSApOwogICAgCVB1c2hWYXIoIHBEdW1teVZhciApOwogICAgfQp9CgoKU2J4VmFyaWFibGUqIFNiaVJ1bnRpbWU6OlN0ZXBTVEFUSUNfSW1wbCggU3RyaW5nJiBhTmFtZSwgU2J4RGF0YVR5cGUmIHQgKQp7CiAgICBTYnhWYXJpYWJsZSogcCA9IE5VTEw7CiAgICBpZiAoIHBNZXRoICkKICAgIHsKICAgICAgICBTYnhBcnJheSogcFN0YXRpY3MgPSBwTWV0aC0+R2V0U3RhdGljcygpOwogICAgICAgIGlmKCBwU3RhdGljcyAmJiAoIHBTdGF0aWNzLT5GaW5kKCBhTmFtZSwgU2J4Q0xBU1NfRE9OVENBUkUgKSA9PSBOVUxMICkgKQogICAgICAgIHsKICAgICAgICAgICAgcCA9IG5ldyBTYnhWYXJpYWJsZSggdCApOwogICAgICAgICAgICBpZiggdCAhPSBTYnhWQVJJQU5UICkKICAgICAgICAgICAgICAgIHAtPlNldEZsYWcoIFNCWF9GSVhFRCApOwogICAgICAgICAgICBwLT5TZXROYW1lKCBhTmFtZSApOwogICAgICAgICAgICBwU3RhdGljcy0+UHV0KCBwLCBwU3RhdGljcy0+Q291bnQoKSApOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBwOwp9Ci8vIEVpbnJpY2h0ZW4gZWluZXIgc3RhdGlzY2hlbiBWYXJpYWJsZW4gKCtTdHJpbmdJRCtUeXApCnZvaWQgU2JpUnVudGltZTo6U3RlcFNUQVRJQyggc2FsX3VJbnQzMiBuT3AxLCBzYWxfdUludDMyIG5PcDIgKQp7CiAgICBTdHJpbmcgYU5hbWUoIHBJbWctPkdldFN0cmluZyggc3RhdGljX2Nhc3Q8c2hvcnQ+KCBuT3AxICkgKSApOwogICAgU2J4RGF0YVR5cGUgdCA9IChTYnhEYXRhVHlwZSkgbk9wMjsKICAgIFN0ZXBTVEFUSUNfSW1wbCggYU5hbWUsIHQgKTsKfQoK