LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqIAogKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lCiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZQogKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvbgogKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlCiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUKICogIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZQogKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqIAogKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKiAKICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLAogKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbgogKiAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkKICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlCiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnMKICogdW5kZXIgdGhlIExpY2Vuc2UuCiAqIAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCgoKLy8gTUFSS0VSKHVwZGF0ZV9wcmVjb21wLnB5KTogYXV0b2dlbiBpbmNsdWRlIHN0YXRlbWVudCwgZG8gbm90IHJlbW92ZQojaW5jbHVkZSAicHJlY29tcGlsZWRfYXV0b21hdGlvbi5oeHgiCgoKI2RlZmluZSBFTkFCTEVfQllURVNUUklOR19TVFJFQU1fT1BFUkFUT1JTCiNpbmNsdWRlIDx0b29scy9zb2xhci5oPgojaW5jbHVkZSA8YXV0b21hdGlvbi9zaW1wbGVjbS5oeHg+CgojaW5jbHVkZSA8YXV0b21hdGlvbi9jb21tZGVmaW5lcy5oeHg+CiNpbmNsdWRlICJwYWNrZXRoYW5kbGVyLmh4eCIKI2luY2x1ZGUgInRjcGlvLmh4eCIKCiNpZiBPU0xfREVCVUdfTEVWRUwgPiAxCiNpbmNsdWRlIDxzdGRpby5oPgp2b2lkIGRlYnVnX3ByaW50ZiggY29uc3QgY2hhciAqY2hhcnMgKQp7CiAgICBzdGF0aWMgc2FsX0Jvb2wgYlByaW50ID0gKGdldGVudigiREVCVUciKSAhPSBOVUxMKTsKICAgIGlmICggYlByaW50ICkKICAgIHsKICAgICAgICBwcmludGYoIGNoYXJzICk7CiAgICAgICAgZmZsdXNoKCBzdGRvdXQgKTsKICAgIH0KfQojZW5kaWYKCkNvbW11bmljYXRpb25MaW5rOjpDb21tdW5pY2F0aW9uTGluayggQ29tbXVuaWNhdGlvbk1hbmFnZXIgKnBNYW4gKQo6IHBNeU1hbmFnZXIocE1hbikKLCBwU2VydmljZURhdGEoTlVMTCkKLCBuU2VydmljZVByb3RvY29sKCAwICkKLCBiSXNJbnNpZGVDYWxsYmFjayggc2FsX0ZhbHNlICkKLCBuVG90YWxCeXRlcyggMCApCiwgbWFBcHBsaWNhdGlvbigiVW5kZWZpbmVkIikKI2lmIE9TTF9ERUJVR19MRVZFTCA+IDEKLCBiRmxhZyggc2FsX0ZhbHNlICkKLCBuU29tZXRoaW5nKCAwICkKI2VuZGlmCnsKfQoKQ29tbXVuaWNhdGlvbkxpbms6On5Db21tdW5pY2F0aW9uTGluaygpCnsKI2lmIE9TTF9ERUJVR19MRVZFTCA+IDEKICAgIGlmICggIWJGbGFnICkgICAgLy8gYkZsYWcgd2lsbCBiZSBzZXQgaWYgZGVsZXRpb24gaXMgZXhwZWN0ZWQgZWxzZSB3ZSBjYW4gc2V0IGEgYnJlYWtwb2ludAogICAgICAgIGJGbGFnID0gc2FsX0ZhbHNlOwojZW5kaWYKCWlmICggcE15TWFuYWdlciApCgkJcE15TWFuYWdlci0+RGVzdHJveWluZ0xpbmsoIHRoaXMgKTsKfQoKdm9pZCBDb21tdW5pY2F0aW9uTGluazo6Q2FsbEluZm9Nc2coIEluZm9TdHJpbmcgYU1zZyApCnsKCWlmICggcE15TWFuYWdlciApCgkJcE15TWFuYWdlci0+SW5mb01zZyggYU1zZyApOwp9OwoKQ01fSW5mb1R5cGUgQ29tbXVuaWNhdGlvbkxpbms6OkdldEluZm9UeXBlKCkKewoJaWYgKCBwTXlNYW5hZ2VyICkKCQlyZXR1cm4gcE15TWFuYWdlci0+R2V0SW5mb1R5cGUoKTsKCWVsc2UKCQlyZXR1cm4gQ01fTk9fVEVYVDsKfQoKSU1QTF9MSU5LKCBDb21tdW5pY2F0aW9uTGluaywgQ29ubmVjdGlvbkNsb3NlZCwgdm9pZCosIEVNUFRZQVJHICkKewoJaWYgKCBwTXlNYW5hZ2VyICkKCQlwTXlNYW5hZ2VyLT5DYWxsQ29ubmVjdGlvbkNsb3NlZCggdGhpcyApOwoJcmV0dXJuIDE7Cn0KCklNUExfTElOSyggQ29tbXVuaWNhdGlvbkxpbmssIERhdGFSZWNlaXZlZCwgdm9pZCosIEVNUFRZQVJHICkKewoJaWYgKCBwTXlNYW5hZ2VyICkKCQlwTXlNYW5hZ2VyLT5DYWxsRGF0YVJlY2VpdmVkKCB0aGlzICk7CglyZXR1cm4gMTsKfQoKc2FsX0Jvb2wgQ29tbXVuaWNhdGlvbkxpbms6OkRvVHJhbnNmZXJEYXRhU3RyZWFtKCBTdlN0cmVhbSAqcERhdGFTdHJlYW0sIENNUHJvdG9jb2wgblByb3RvY29sICkKewoJSU5GT19NU0coIENCeXRlU3RyaW5nKCJTIDoiKS5BcHBlbmQoIEdldENvbW11bmljYXRpb25QYXJ0bmVyKCBDTV9GUUROICkgKSwKCQlDQnl0ZVN0cmluZygiRGF0ZW4gU2VuZGVuOiIpLkFwcGVuZCggR2V0Q29tbXVuaWNhdGlvblBhcnRuZXIoIENNX0ZRRE4gKSApLAoJCUNNX1NFTkQsIHRoaXMgKTsKCXNhbF9Cb29sIGJXYXNFcnJvciA9IHNhbF9GYWxzZTsKCglzYWxfdUludDMyIG5CdWZmZXI7CgluQnVmZmVyID0gcERhdGFTdHJlYW0tPlNlZWtSZWwoMCkgKzE7CgliV2FzRXJyb3IgPSBwUGFja2V0SGFuZGxlci0+VHJhbnNmZXJEYXRhKCAoKFN2TWVtb3J5U3RyZWFtKilwRGF0YVN0cmVhbSktPkdldERhdGEoKSwgbkJ1ZmZlciwgblByb3RvY29sICkgIT0gQ19FUlJPUl9OT05FOwoKCWlmICggYldhc0Vycm9yICkKCXsKCQlJTkZPX01TRyggQ0J5dGVTdHJpbmcoIlNlbmQgRmFpbGVkOiIpLkFwcGVuZCggR2V0Q29tbXVuaWNhdGlvblBhcnRuZXIoIENNX0ZRRE4gKSApLAoJCQlDQnl0ZVN0cmluZyggIlNvY2tldCB3aXJkIHdlZ2VuIEZlaGxlcnMgYmVpbSBTZW5kZW4gZ2VzY2hsb3NzZW46ICIpLkFwcGVuZCggR2V0Q29tbXVuaWNhdGlvblBhcnRuZXIoIENNX0ZRRE4gKSApLAoJCQlDTV9FUlJPUiwgdGhpcyApOwoJCVNodXRkb3duQ29tbXVuaWNhdGlvbigpOwoJfQoJcmV0dXJuICFiV2FzRXJyb3I7Cn0KCnNhbF9Cb29sIENvbW11bmljYXRpb25MaW5rOjpUcmFuc2ZlckRhdGFTdHJlYW0oIFN2U3RyZWFtICpwRGF0YVN0cmVhbSwgQ01Qcm90b2NvbCBuUHJvdG9jb2wgKQp7CglhTGFzdEFjY2VzcyA9IERhdGVUaW1lKCk7CgluVG90YWxCeXRlcyArPSBwRGF0YVN0cmVhbS0+U2VlayggU1RSRUFNX1NFRUtfVE9fRU5EICk7CglyZXR1cm4gRG9UcmFuc2ZlckRhdGFTdHJlYW0oIHBEYXRhU3RyZWFtLCBuUHJvdG9jb2wgKTsKfQoKdm9pZCBDb21tdW5pY2F0aW9uTGluazo6U2V0QXBwbGljYXRpb24oIGNvbnN0IEJ5dGVTdHJpbmcmIGFBcHAgKQp7CgltYUFwcGxpY2F0aW9uID0gYUFwcDsKfQoKClNpbXBsZUNvbW11bmljYXRpb25MaW5rVmlhU29ja2V0OjpTaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldCggQ29tbXVuaWNhdGlvbk1hbmFnZXIgKnBNYW4sIHZvczo6T1N0cmVhbVNvY2tldCAqcFNvY2tldCApCjogQ29tbXVuaWNhdGlvbkxpbmsoIHBNYW4gKQosIGFDb21tdW5pY2F0aW9uUGFydG5lcigpCiwgYU15TmFtZSgpCiwgcFN0cmVhbVNvY2tldCggcFNvY2tldCApCiwgcFJlY2VpdmVTdHJlYW0oIE5VTEwgKQosIGJJc1JlcXVlc3RTaHV0ZG93blBlbmRpbmcoIHNhbF9GYWxzZSApCnsKCXBUQ1BJTyA9IG5ldyBUQ1BJTyggcFN0cmVhbVNvY2tldCApOwoJcFBhY2tldEhhbmRsZXIgPSBuZXcgUGFja2V0SGFuZGxlciggKElUcmFuc21pdGVyKikgcFRDUElPLCBwVENQSU8sIHBNeU1hbmFnZXItPklzTXVsdGlDaGFubmVsKCkgKTsKfQoKU2ltcGxlQ29tbXVuaWNhdGlvbkxpbmtWaWFTb2NrZXQ6On5TaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldCgpCnsKCWRlbGV0ZSBwUGFja2V0SGFuZGxlcjsKICAgIHBQYWNrZXRIYW5kbGVyID0gTlVMTDsKCWRlbGV0ZSBwVENQSU87CiAgICBwVENQSU8gPSBOVUxMOwoJZGVsZXRlIHBTdHJlYW1Tb2NrZXQ7CiAgICBwU3RyZWFtU29ja2V0ID0gTlVMTDsKfQoKdm9pZCBTaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldDo6U2V0U3RyZWFtU29ja2V0KCB2b3M6Ok9TdHJlYW1Tb2NrZXQqIHBTb2NrZXQgKQp7CiAgICBpZiAoIHBUQ1BJTyApCiAgICAgICAgcFRDUElPLT5TZXRTdHJlYW1Tb2NrZXQoIHBTb2NrZXQgKTsKICAgIHBTdHJlYW1Tb2NrZXQgPSBwU29ja2V0Owp9CgpzYWxfQm9vbCBTaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldDo6U3RvcENvbW11bmljYXRpb24oKQp7CglDb21tdW5pY2F0aW9uTGlua1JlZiBySG9sZCh0aGlzKTsJCS8vIGF2b2lkIGRlbGV0aW5nIHRoaXMgbGluayBiZWZvcmUgdGhlIGVuZCBvZiB0aGUgbWV0aG9kCglpZiAoICFJc0NvbW11bmljYXRpb25FcnJvcigpICkJLy8gTWVhbmluZyB0aGF0IHRoZSBDb21tdW5pY2F0aW9uIGlzIHN0aWxsIHJ1bm5pbmcKCXsKI2lmIE9TTF9ERUJVR19MRVZFTCA+IDEKCQlkZWJ1Z19wcmludGYoIlNlbmRpbmcgUkVRVUVTVF9TaHV0ZG93bkxpbmtcbiIpOwojZW5kaWYKCQlTZW5kSGFuZHNoYWtlKCBDSF9SRVFVRVNUX1NodXRkb3duTGluayApOwoJfQoJV2FpdEZvclNodXRkb3duKCk7CglyZXR1cm4gc2FsX1RydWU7Cn0KCnZvaWQgU2ltcGxlQ29tbXVuaWNhdGlvbkxpbmtWaWFTb2NrZXQ6OlNldEZpbmFsUmVjaWV2ZVRpbWVvdXQoKQp7CglpZiAoICFJc0NvbW11bmljYXRpb25FcnJvcigpICkKCXsKICAgICAgICBUaW1lVmFsdWUgYVRpbWUgPSB7MzAsIDB9OyAgIC8vIDMwIHNlY29uZHMKCSAgICBwU3RyZWFtU29ja2V0LT5zZXRSZWN2VGltZW91dCggJmFUaW1lICk7Cgl9Cn0KCnNhbF9Cb29sIFNpbXBsZUNvbW11bmljYXRpb25MaW5rVmlhU29ja2V0OjpJc0NvbW11bmljYXRpb25FcnJvcigpCnsKCXJldHVybiAhcFN0cmVhbVNvY2tldDsKfQoKQnl0ZVN0cmluZyBTaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldDo6R2V0Q29tbXVuaWNhdGlvblBhcnRuZXIoIENNX05hbWVUeXBlIGVUeXBlICkKewoJaWYgKCBwU3RyZWFtU29ja2V0ICkKCXsKCQlzd2l0Y2ggKCBlVHlwZSApCgkJewoJCQljYXNlIENNX0RPVFRFRDoKCQkJCXsKCQkJCQlydGw6Ok9VU3RyaW5nIGFEb3R0ZWQ7CgkJCQkJdm9zOjpPU29ja2V0QWRkciAqcFBlZXJBZHIgPSBuZXcgdm9zOjpPU29ja2V0QWRkcjsKCQkJCQlwU3RyZWFtU29ja2V0LT5nZXRQZWVyQWRkciggKnBQZWVyQWRyICk7CgkJCQkJKCh2b3M6Ok9JbmV0U29ja2V0QWRkciopcFBlZXJBZHIpLT5nZXREb3R0ZWRBZGRyKCBhRG90dGVkICk7CgkJCQkJZGVsZXRlIHBQZWVyQWRyOwoJCQkJCXJldHVybiBCeXRlU3RyaW5nKCBVbmlTdHJpbmcoYURvdHRlZCksIFJUTF9URVhURU5DT0RJTkdfVVRGOCApOwoJCQkJfQoJCQkJLy9icmVhazsKCQkJY2FzZSBDTV9GUUROOgoJCQkJewoJCQkJCWlmICggIWFDb21tdW5pY2F0aW9uUGFydG5lci5MZW4oKSApCgkJCQkJewoJCQkJCQlydGw6Ok9VU3RyaW5nIGFGUUROOwoJCQkJCQlwU3RyZWFtU29ja2V0LT5nZXRQZWVySG9zdCggYUZRRE4gKTsKCQkJCQkJYUNvbW11bmljYXRpb25QYXJ0bmVyID0gQnl0ZVN0cmluZyggVW5pU3RyaW5nKGFGUUROKSwgUlRMX1RFWFRFTkNPRElOR19VVEY4ICk7CgkJCQkJfQoJCQkJCXJldHVybiBhQ29tbXVuaWNhdGlvblBhcnRuZXI7CgkJCQl9CgkJCQkvL2JyZWFrOwoJCX0KCX0KCXJldHVybiBDQnl0ZVN0cmluZyggIlVua25vd24iICk7Cn0KCkJ5dGVTdHJpbmcgU2ltcGxlQ29tbXVuaWNhdGlvbkxpbmtWaWFTb2NrZXQ6OkdldE15TmFtZSggQ01fTmFtZVR5cGUgZVR5cGUgKQp7CglpZiAoIHBTdHJlYW1Tb2NrZXQgKQoJewoJCXN3aXRjaCAoIGVUeXBlICkKCQl7CgkJCWNhc2UgQ01fRE9UVEVEOgoJCQkJewoJCQkJCXJ0bDo6T1VTdHJpbmcgYURvdHRlZDsKCQkJCQl2b3M6Ok9Tb2NrZXRBZGRyICpwUGVlckFkciA9IG5ldyB2b3M6Ok9Tb2NrZXRBZGRyOwoJCQkJCXBTdHJlYW1Tb2NrZXQtPmdldExvY2FsQWRkciggKnBQZWVyQWRyICk7CgkJCQkJKCh2b3M6Ok9JbmV0U29ja2V0QWRkciopcFBlZXJBZHIpLT5nZXREb3R0ZWRBZGRyKCBhRG90dGVkICk7CgkJCQkJZGVsZXRlIHBQZWVyQWRyOwoJCQkJCXJldHVybiBCeXRlU3RyaW5nKCBVbmlTdHJpbmcoYURvdHRlZCksIFJUTF9URVhURU5DT0RJTkdfVVRGOCApOwoJCQkJfQoJCQkJLy9icmVhazsKCQkJY2FzZSBDTV9GUUROOgoJCQkJewoJCQkJCWlmICggIWFNeU5hbWUuTGVuKCkgKQoJCQkJCXsKCQkJCQkJcnRsOjpPVVN0cmluZyBhRlFETjsKCQkJCQkJcFN0cmVhbVNvY2tldC0+Z2V0TG9jYWxIb3N0KCBhRlFETiApOwoJCQkJCQlhTXlOYW1lID0gQnl0ZVN0cmluZyggVW5pU3RyaW5nKGFGUUROKSwgUlRMX1RFWFRFTkNPRElOR19VVEY4ICk7CgkJCQkJfQoJCQkJCXJldHVybiBhTXlOYW1lOwoJCQkJfQoJCQkJLy9icmVhazsKCQl9Cgl9CglyZXR1cm4gQ0J5dGVTdHJpbmcoICJFcnJvciIgKTsKfQoKU3ZTdHJlYW0qIFNpbXBsZUNvbW11bmljYXRpb25MaW5rVmlhU29ja2V0OjpHZXRCZXN0Q29tbXVuaWNhdGlvblN0cmVhbSgpCnsKCVN2U3RyZWFtKiBwU3RyZWFtID0gbmV3IFN2TWVtb3J5U3RyZWFtOwovLwlwU3RyZWFtLT5TZXROdW1iZXJGb3JtYXRJbnQoIE5VTUJFUkZPUk1BVF9JTlRfQklHRU5ESUFOICk7CglyZXR1cm4gcFN0cmVhbTsKfQoKI2RlZmluZSBSRUFEX1NPQ0tFVCggcEJ1ZmZlciwgbkxlbmd0aCApXAoJaWYgKCAhYldhc0Vycm9yIClcCgkJe2JXYXNFcnJvciB8PSBwVENQSU8tPlJlY2VpdmVCeXRlcyggcEJ1ZmZlciwgbkxlbmd0aCApICE9IENfRVJST1JfTk9ORTt9CgojZGVmaW5lIFJFQURfU09DS0VUX0xFTiggcEJ1ZmZlciwgbkxlbmd0aCwgblRvdGFsIClcCglSRUFEX1NPQ0tFVCggcEJ1ZmZlciwgbkxlbmd0aCApO1wKCWlmICggIWJXYXNFcnJvciApXAoJCXtuVG90YWwgKz0gbkxlbmd0aDt9CgpzYWxfQm9vbCBTaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldDo6RG9SZWNlaXZlRGF0YVN0cmVhbSgpCnsKCXNhbF9Cb29sIGJXYXNFcnJvciA9IHNhbF9GYWxzZTsKCXZvaWQqIHBCdWZmZXIgPSBOVUxMOwoJY29tbV9VSU5UMzIgbkxlbjsKCWJXYXNFcnJvciA9IHBQYWNrZXRIYW5kbGVyLT5SZWNlaXZlRGF0YSggcEJ1ZmZlciwgbkxlbiApICE9IENfRVJST1JfTk9ORTsKCWlmICggIWJXYXNFcnJvciApCgl7CgkJcFJlY2VpdmVTdHJlYW0gPSBHZXRCZXN0Q29tbXVuaWNhdGlvblN0cmVhbSgpOwoJCURCR19BU1NFUlQoIHBSZWNlaXZlU3RyZWFtLT5Jc0EoKSA9PSBJRF9NRU1PUllTVFJFQU0sICJDb21tdW5pY2F0aW9uU3RyZWFtIGlzIG5vdCBhbiBTdk1lbW9yeVN0cmVhbS4gQ29tbXVuaWNhdGlvbiBoYXMgdG8gYmUgcmVpbXBsZW1lbnRlZCBoZXJlISIpOwoJCWlmICggcFJlY2VpdmVTdHJlYW0tPklzQSgpID09IElEX01FTU9SWVNUUkVBTSApCgkJCSgoU3ZNZW1vcnlTdHJlYW0qKXBSZWNlaXZlU3RyZWFtKS0+U2V0QnVmZmVyKCBwQnVmZmVyLCBuTGVuLCBzYWxfVHJ1ZSwgbkxlbiApOwoJCURCR19BU1NFUlQoIHBSZWNlaXZlU3RyZWFtLCAiRGF0YXN0cmVhbSBpcyBOVUxMIik7Cgl9CgoJcmV0dXJuICFiV2FzRXJyb3I7Cn0KCnZvaWQgU2ltcGxlQ29tbXVuaWNhdGlvbkxpbmtWaWFTb2NrZXQ6OlNldEFwcGxpY2F0aW9uKCBjb25zdCBCeXRlU3RyaW5nJiBhQXBwICkKewoJQ29tbXVuaWNhdGlvbkxpbms6OlNldEFwcGxpY2F0aW9uKCBhQXBwICk7CglTdlN0cmVhbSogcERhdGEgPSBHZXRCZXN0Q29tbXVuaWNhdGlvblN0cmVhbSgpOwoJKnBEYXRhIDw8IGFBcHA7CglTZW5kSGFuZHNoYWtlKCBDSF9TZXRBcHBsaWNhdGlvbiwgcERhdGEgKTsKCWRlbGV0ZSBwRGF0YTsKfQoKdm9pZCBTaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldDo6U2V0TmV3UGFja2V0QXNDdXJyZW50KCkKewoJcFNlcnZpY2VEYXRhID0gcFJlY2VpdmVTdHJlYW07CgluU2VydmljZVByb3RvY29sID0gcFBhY2tldEhhbmRsZXItPkdldFJlY2VpdmVQcm90b2NvbCgpOwoJblNlcnZpY2VIZWFkZXJUeXBlID0gcFBhY2tldEhhbmRsZXItPkdldFJlY2VpdmVIZWFkZXJUeXBlKCk7Cn0KCnNhbF9Cb29sIFNpbXBsZUNvbW11bmljYXRpb25MaW5rVmlhU29ja2V0OjpTZW5kSGFuZHNoYWtlKCBIYW5kc2hha2VUeXBlIGFIYW5kc2hha2VUeXBlLCBTdlN0cmVhbSogcERhdGEgKQp7CglzYWxfQm9vbCBiV2FzRXJyb3I7CgoJaWYgKCBwRGF0YSApCgl7CgkJc2FsX3VJbnQzMiBuQnVmZmVyOwoJCW5CdWZmZXIgPSBwRGF0YS0+U2VlayggU1RSRUFNX1NFRUtfVE9fRU5EICk7CgkJYldhc0Vycm9yID0gIXBQYWNrZXRIYW5kbGVyLT5TZW5kSGFuZHNoYWtlKCBhSGFuZHNoYWtlVHlwZSwgKChTdk1lbW9yeVN0cmVhbSopcERhdGEpLT5HZXREYXRhKCksIG5CdWZmZXIgKTsKCX0KCWVsc2UKCQliV2FzRXJyb3IgPSAhcFBhY2tldEhhbmRsZXItPlNlbmRIYW5kc2hha2UoIGFIYW5kc2hha2VUeXBlICk7CgoKCWlmICggYldhc0Vycm9yICkKCXsKCQlJTkZPX01TRyggQ0J5dGVTdHJpbmcoIlNlbmQgRmFpbGVkOiIpLkFwcGVuZCggR2V0Q29tbXVuaWNhdGlvblBhcnRuZXIoIENNX0ZRRE4gKSApLAoJCQlDQnl0ZVN0cmluZyggIlNvY2tldCB3aXJkIHdlZ2VuIEZlaGxlcnMgYmVpbSBTZW5kZW4gZ2VzY2hsb3NzZW46ICIpLkFwcGVuZCggR2V0Q29tbXVuaWNhdGlvblBhcnRuZXIoIENNX0ZRRE4gKSApLAoJCQlDTV9FUlJPUiwgdGhpcyApOwoJCVNodXRkb3duQ29tbXVuaWNhdGlvbigpOwoJfQoJZWxzZQoJewkvLyBzZXQgbmV3IHN0YXR1cwoJCXN3aXRjaCAoIGFIYW5kc2hha2VUeXBlICkKCQl7CgkJCWNhc2UgQ0hfUkVRVUVTVF9IYW5kc2hha2VBbGl2ZToKCQkJCWJyZWFrOwoJCQljYXNlIENIX1JFU1BPTlNFX0hhbmRzaGFrZUFsaXZlOgoJCQkJYnJlYWs7CgkJCWNhc2UgQ0hfUkVRVUVTVF9TaHV0ZG93bkxpbms6CgkJCQliSXNSZXF1ZXN0U2h1dGRvd25QZW5kaW5nID0gc2FsX1RydWU7CgkJCQlicmVhazsKCQkJY2FzZSBDSF9TaHV0ZG93bkxpbms6CgkJCQlicmVhazsKCQkJY2FzZSBDSF9TVVBQT1JUX09QVElPTlM6CgkJCQlicmVhazsKCQkJY2FzZSBDSF9TZXRBcHBsaWNhdGlvbjoKCQkJCWJyZWFrOwoJCQlkZWZhdWx0OgoJCQkJREJHX0VSUk9SKCJVbmtub3duIEhhbmRzaGFrZVR5cGUiKTsKCQl9Cgl9CglyZXR1cm4gIWJXYXNFcnJvcjsKfQoKU2ltcGxlQ29tbXVuaWNhdGlvbkxpbmtWaWFTb2NrZXRXaXRoUmVjZWl2ZUNhbGxiYWNrczo6U2ltcGxlQ29tbXVuaWNhdGlvbkxpbmtWaWFTb2NrZXRXaXRoUmVjZWl2ZUNhbGxiYWNrcyggQ29tbXVuaWNhdGlvbk1hbmFnZXIgKnBNYW4sIHZvczo6T1N0cmVhbVNvY2tldCAqcFNvY2tldCApCjogU2ltcGxlQ29tbXVuaWNhdGlvbkxpbmtWaWFTb2NrZXQoIHBNYW4sIHBTb2NrZXQgKQp7Cn0KClNpbXBsZUNvbW11bmljYXRpb25MaW5rVmlhU29ja2V0V2l0aFJlY2VpdmVDYWxsYmFja3M6On5TaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldFdpdGhSZWNlaXZlQ2FsbGJhY2tzKCkKewoJaWYgKCBwTXlNYW5hZ2VyICYmIHBNeU1hbmFnZXItPklzTGlua1ZhbGlkKCB0aGlzICkgJiYgIWJJc1JlcXVlc3RTaHV0ZG93blBlbmRpbmcgKQoJCVN0b3BDb21tdW5pY2F0aW9uKCk7Cn0KCnZvaWQgU2ltcGxlQ29tbXVuaWNhdGlvbkxpbmtWaWFTb2NrZXRXaXRoUmVjZWl2ZUNhbGxiYWNrczo6V2FpdEZvclNodXRkb3duKCkKewoJQ29tbXVuaWNhdGlvbkxpbmtSZWYgckhvbGQodGhpcyk7CQkvLyBhdm9pZCBkZWxldGluZyB0aGlzIGxpbmsgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIG1ldGhvZAoJU2V0RmluYWxSZWNpZXZlVGltZW91dCgpOwogICAgd2hpbGUgKCBwTXlNYW5hZ2VyICYmICFJc0NvbW11bmljYXRpb25FcnJvcigpICkKCQlSZWNlaXZlRGF0YVN0cmVhbSgpOwp9CgpzYWxfQm9vbCBTaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldFdpdGhSZWNlaXZlQ2FsbGJhY2tzOjpSZWNlaXZlRGF0YVN0cmVhbSgpCnsKCWlmICggRG9SZWNlaXZlRGF0YVN0cmVhbSgpICkKCXsKCQlTZXROZXdQYWNrZXRBc0N1cnJlbnQoKTsKCQlTdGFydENhbGxiYWNrKCk7CgkJRGF0YVJlY2VpdmVkKCk7CgkJcmV0dXJuIHNhbF9UcnVlOwoJfQoJZWxzZQoJewoJCVN0YXJ0Q2FsbGJhY2soKTsKCQlTaHV0ZG93bkNvbW11bmljYXRpb24oKTsKCQlyZXR1cm4gc2FsX0ZhbHNlOwoJfQp9CgpzYWxfQm9vbCBTaW1wbGVDb21tdW5pY2F0aW9uTGlua1ZpYVNvY2tldFdpdGhSZWNlaXZlQ2FsbGJhY2tzOjpTaHV0ZG93bkNvbW11bmljYXRpb24oKQp7CiAgICBpZiAoIEdldFN0cmVhbVNvY2tldCgpICkKCQlHZXRTdHJlYW1Tb2NrZXQoKS0+c2h1dGRvd24oKTsKCglpZiAoIEdldFN0cmVhbVNvY2tldCgpICkKCQlHZXRTdHJlYW1Tb2NrZXQoKS0+Y2xvc2UoKTsKCiAgICB2b3M6Ok9TdHJlYW1Tb2NrZXQgKnBUZW1wU29ja2V0ID0gR2V0U3RyZWFtU29ja2V0KCk7CiAgICBTZXRTdHJlYW1Tb2NrZXQoIE5VTEwgKTsKICAgIGRlbGV0ZSBwVGVtcFNvY2tldDsKCglDb25uZWN0aW9uQ2xvc2VkKCk7CgoJcmV0dXJuIHNhbF9UcnVlOwp9CgoKCkNvbW11bmljYXRpb25NYW5hZ2VyOjpDb21tdW5pY2F0aW9uTWFuYWdlciggc2FsX0Jvb2wgYlVzZU11bHRpQ2hhbm5lbCApCjogbkluZm9UeXBlKCBDTV9OT05FICkKLCBiSXNDb21tdW5pY2F0aW9uUnVubmluZyggc2FsX0ZhbHNlICkKLCBtYUFwcGxpY2F0aW9uKCJVbmtub3duIikKLCBiSXNNdWx0aUNoYW5uZWwoIGJVc2VNdWx0aUNoYW5uZWwgKQp7Cn0KCkNvbW11bmljYXRpb25NYW5hZ2VyOjp+Q29tbXVuaWNhdGlvbk1hbmFnZXIoKQp7Cgl4TGFzdE5ld0xpbmsuQ2xlYXIoKTsKfQoKc2FsX0Jvb2wgQ29tbXVuaWNhdGlvbk1hbmFnZXI6OlN0YXJ0Q29tbXVuaWNhdGlvbiggU3RyaW5nIGFBcHAsIFN0cmluZyBhUGFyYW1zICkKewogICAgKHZvaWQpIGFBcHA7IC8qIGF2b2lkIHdhcm5pbmcgYWJvdXQgdW51c2VkIHBhcmFtZXRlciAqLyAKICAgICh2b2lkKSBhUGFyYW1zOyAvKiBhdm9pZCB3YXJuaW5nIGFib3V0IHVudXNlZCBwYXJhbWV0ZXIgKi8gCiAgICByZXR1cm4gc2FsX0ZhbHNlOwp9CgpzYWxfQm9vbCBDb21tdW5pY2F0aW9uTWFuYWdlcjo6U3RhcnRDb21tdW5pY2F0aW9uKCBCeXRlU3RyaW5nIGFIb3N0LCBzYWxfdUxvbmcgblBvcnQgKQp7CiAgICAodm9pZCkgYUhvc3Q7IC8qIGF2b2lkIHdhcm5pbmcgYWJvdXQgdW51c2VkIHBhcmFtZXRlciAqLyAKICAgICh2b2lkKSBuUG9ydDsgLyogYXZvaWQgd2FybmluZyBhYm91dCB1bnVzZWQgcGFyYW1ldGVyICovIAogICAgcmV0dXJuIHNhbF9GYWxzZTsKfQoKQnl0ZVN0cmluZyBDb21tdW5pY2F0aW9uTWFuYWdlcjo6R2V0TXlOYW1lKCBDTV9OYW1lVHlwZSApCnsKCXJ0bDo6T1VTdHJpbmcgYUhvc3RuYW1lOwoJdm9zOjpPU29ja2V0QWRkcjo6Z2V0TG9jYWxIb3N0bmFtZSggYUhvc3RuYW1lICk7CglyZXR1cm4gQnl0ZVN0cmluZyggVW5pU3RyaW5nKGFIb3N0bmFtZSksIFJUTF9URVhURU5DT0RJTkdfVVRGOCApOwp9Cgp2b2lkIENvbW11bmljYXRpb25NYW5hZ2VyOjpDYWxsQ29ubmVjdGlvbk9wZW5lZCggQ29tbXVuaWNhdGlvbkxpbmsqIHBDTCApCnsKCXBDTC0+U3RhcnRDYWxsYmFjaygpOwkJLy8gU29sbHRlIGJlcmVpdHMgdm9yIGRlbSBBdWZydWYgZ2VydWZlbiB3ZXJkZW4KCXBDTC0+YVN0YXJ0ID0gRGF0ZVRpbWUoKTsKCXBDTC0+YUxhc3RBY2Nlc3MgPSBwQ0wtPmFTdGFydDsKCWJJc0NvbW11bmljYXRpb25SdW5uaW5nID0gc2FsX1RydWU7CglwQ0wtPlNldEFwcGxpY2F0aW9uKCBHZXRBcHBsaWNhdGlvbigpICk7CgoJeExhc3ROZXdMaW5rID0gcENMOwoKCUlORk9fTVNHKCBDQnl0ZVN0cmluZygiQys6IikuQXBwZW5kKCBwQ0wtPkdldENvbW11bmljYXRpb25QYXJ0bmVyKCBDTV9GUUROICkgKSwKCQlDQnl0ZVN0cmluZygiVmVyYmluZHVuZyBhdWZnZWJhdXQ6ICIpLkFwcGVuZCggcENMLT5HZXRDb21tdW5pY2F0aW9uUGFydG5lciggQ01fRlFETiApICksCgkJQ01fT1BFTiwgcENMICk7CglDb25uZWN0aW9uT3BlbmVkKCBwQ0wgKTsKCXBDTC0+RmluaXNoQ2FsbGJhY2soKTsKfQoKdm9pZCBDb21tdW5pY2F0aW9uTWFuYWdlcjo6Q2FsbENvbm5lY3Rpb25DbG9zZWQoIENvbW11bmljYXRpb25MaW5rKiBwQ0wgKQp7CglwQ0wtPlN0YXJ0Q2FsbGJhY2soKTsJCS8vIFNvbGx0ZSBiZXJlaXRzIHZvciBkZW0gQXVmcnVmIGdlcnVmZW4gd2VyZGVuCglwQ0wtPmFMYXN0QWNjZXNzID0gRGF0ZVRpbWUoKTsKCglJTkZPX01TRyggQ0J5dGVTdHJpbmcoIkMtOiIpLkFwcGVuZCggcENMLT5HZXRDb21tdW5pY2F0aW9uUGFydG5lciggQ01fRlFETiApICksCgkJQ0J5dGVTdHJpbmcoIlZlcmJpbmR1bmcgYWJnZWJyb2NoZW46ICIpLkFwcGVuZCggcENMLT5HZXRDb21tdW5pY2F0aW9uUGFydG5lciggQ01fRlFETiApICksCgkJQ01fQ0xPU0UsIHBDTCApOwoJQ29ubmVjdGlvbkNsb3NlZCggcENMICk7CgoJaWYgKCB4TGFzdE5ld0xpbmsgPT0gcENMICkKCQl4TGFzdE5ld0xpbmsuQ2xlYXIoKTsKCglwQ0wtPkZpbmlzaENhbGxiYWNrKCk7Ci8vCWRlbGV0ZSBwQ0w7Cn0KCnZvaWQgQ29tbXVuaWNhdGlvbk1hbmFnZXI6OkNhbGxEYXRhUmVjZWl2ZWQoIENvbW11bmljYXRpb25MaW5rKiBwQ0wgKQp7CglwQ0wtPlN0YXJ0Q2FsbGJhY2soKTsJCS8vIFNvbGx0ZSBiZXJlaXRzIHZvciBkZW0gQXVmcnVmIGdlcnVmZW4gd2VyZGVuCglwQ0wtPmFMYXN0QWNjZXNzID0gRGF0ZVRpbWUoKTsKCUNvbW11bmljYXRpb25MaW5rUmVmIHJIb2xkKHBDTCk7CS8vIEjkbHQgZGVuIFplaWdlciBiaXMgenVtIEVuZGUgZGVzIGNhbGxzCgoJLy8gc2hvdWxkIGJlIGltcG9zc2libGUgYnV0IGhhcHBlbnMgZm9yIG15c3RlcmlvdXMgcmVhc29ucwoJaWYgKCAhcENMLT5wU2VydmljZURhdGEgKQoJewoJCURCR19FUlJPUiggIkRhdGFzdHJlYW0gaXMgTlVMTCIgKTsKCQlwQ0wtPkZpbmlzaENhbGxiYWNrKCk7CgkJcmV0dXJuOwoJfQoKCglpZiAoIENIX0hhbmRzaGFrZSA9PSBwQ0wtPm5TZXJ2aWNlSGVhZGVyVHlwZSApCgl7CgkJU3ZTdHJlYW0gKnBEYXRhID0gcENMLT5HZXRTZXJ2aWNlRGF0YSgpOwoJCXNhbF91SW50MTYgblR5cGU7CgkJcERhdGEtPlNldE51bWJlckZvcm1hdEludCggTlVNQkVSRk9STUFUX0lOVF9CSUdFTkRJQU4gKTsJLy8gVW5mb3J0dWxhdGVseSBpdCBpcyB3cml0dGVuIHRoaXMgd2F5IDooKAoJCSpwRGF0YSA+PiBuVHlwZTsKCQlwRGF0YS0+U2V0TnVtYmVyRm9ybWF0SW50KCBOVU1CRVJGT1JNQVRfSU5UX0xJVFRMRUVORElBTiApOwoJCXN3aXRjaCAoIG5UeXBlICkKCQl7CgkJCWNhc2UgQ0hfUkVRVUVTVF9IYW5kc2hha2VBbGl2ZToKCQkJCXsKCQkJCQlwQ0wtPlNlbmRIYW5kc2hha2UoIENIX1JFU1BPTlNFX0hhbmRzaGFrZUFsaXZlICk7CgkJCQl9CgkJCQlicmVhazsKCQkJY2FzZSBDSF9SRVFVRVNUX1NodXRkb3duTGluazoKCQkJCXsKI2lmIE9TTF9ERUJVR19MRVZFTCA+IDEKCQkJCQlkZWJ1Z19wcmludGYoIlNlbmRpbmcgU2h1dGRvd25MaW5rXG4iKTsKI2VuZGlmCgkJCQkJcENMLT5TZW5kSGFuZHNoYWtlKCBDSF9TaHV0ZG93bkxpbmsgKTsKCQkJCX0KCQkJCWJyZWFrOwoJCQljYXNlIENIX1NodXRkb3duTGluazoKCQkJCXsKI2lmIE9TTF9ERUJVR19MRVZFTCA+IDEKCQkJCQlkZWJ1Z19wcmludGYoIkV4ZWN1dGluZyBTaHV0ZG93bkxpbmtcbiIpOwojZW5kaWYKCQkJCQlwQ0wtPlNodXRkb3duQ29tbXVuaWNhdGlvbigpOwoJCQkJfQoJCQkJYnJlYWs7CgkJCWNhc2UgQ0hfU2V0QXBwbGljYXRpb246CgkJCQl7CgkJCQkJQnl0ZVN0cmluZyBhQXBwbGljYXRpb247CgkJCQkJKnBEYXRhID4+IGFBcHBsaWNhdGlvbjsKCQkJCQlwQ0wtPkNvbW11bmljYXRpb25MaW5rOjpTZXRBcHBsaWNhdGlvbiggYUFwcGxpY2F0aW9uICk7CiNpZiBPU0xfREVCVUdfTEVWRUwgPiAxCgkJCQkJZGVidWdfcHJpbnRmKCAiU2V0dGluZyBBcHBsaWNhdGlvbiB0byAiICk7CgkJCQkJZGVidWdfcHJpbnRmKCBhQXBwbGljYXRpb24uR2V0QnVmZmVyKCkgKTsKCQkJCQlkZWJ1Z19wcmludGYoICJcbiIgKTsKI2VuZGlmCgkJCQl9CgkJCQlicmVhazsKCiNpZiBPU0xfREVCVUdfTEVWRUwgPiAxCgkJCWRlZmF1bHQ6CgkJCQl7CgkJCQkJZGVidWdfcHJpbnRmKCJVbmtub3duIEhhbmRzaGFrZSByZWNlaXZlZFxuIik7CgkJCQl9CiNlbmRpZgoJCX0KCQlkZWxldGUgcERhdGE7Cgl9CgllbHNlCgl7CgkJaWYgKCBwQ0wtPnBTZXJ2aWNlRGF0YSApCgkJewoJCQlwQ0wtPm5Ub3RhbEJ5dGVzICs9IHBDTC0+cFNlcnZpY2VEYXRhLT5TZWVrKCBTVFJFQU1fU0VFS19UT19FTkQgKTsKCQkJcENMLT5wU2VydmljZURhdGEtPlNlZWsoIFNUUkVBTV9TRUVLX1RPX0JFR0lOICk7CgkJfQoKCQlJTkZPX01TRyggQ0J5dGVTdHJpbmcoIkQgOiIpLkFwcGVuZCggcENMLT5HZXRDb21tdW5pY2F0aW9uUGFydG5lciggQ01fRlFETiApICksCgkJCUNCeXRlU3RyaW5nKCJEYXRlbiBFbXBmYW5nZW46IikuQXBwZW5kKCBwQ0wtPkdldENvbW11bmljYXRpb25QYXJ0bmVyKCBDTV9GUUROICkgKSwKCQkJQ01fUkVDRUlWRSwgcENMICk7CgkJRGF0YVJlY2VpdmVkKCBwQ0wgKTsKCX0KCWRlbGV0ZSBwQ0wtPkdldFNlcnZpY2VEYXRhKCk7CglwQ0wtPkZpbmlzaENhbGxiYWNrKCk7Cn0KCnZvaWQgQ29tbXVuaWNhdGlvbk1hbmFnZXI6OkNhbGxJbmZvTXNnKCBJbmZvU3RyaW5nIGFNc2cgKQp7CgkvLyBIaWVyIHdpcmQgZXMgd29obCBrZWluIEhvdXNla2VlcGluZyBnZWJlbgoJSW5mb01zZyggYU1zZyApOwp9Cgp2b2lkIENvbW11bmljYXRpb25NYW5hZ2VyOjpTZXRBcHBsaWNhdGlvbiggY29uc3QgQnl0ZVN0cmluZyYgYUFwcCwgc2FsX0Jvb2wgYlJ1bm5pbmdMaW5rcyApCnsKCW1hQXBwbGljYXRpb24gPSBhQXBwOwoJaWYgKCBiUnVubmluZ0xpbmtzICkKCXsKCQlzYWxfdUludDE2IGk7CgkJZm9yICggaSA9IDAgOyBpIDwgR2V0Q29tbXVuaWNhdGlvbkxpbmtDb3VudCgpIDsgaSsrICkKCQkJR2V0Q29tbXVuaWNhdGlvbkxpbmsoIGkgKS0+U2V0QXBwbGljYXRpb24oIGFBcHAgKTsKCX0KfQoKCgpTaW5nbGVDb21tdW5pY2F0aW9uTWFuYWdlcjo6U2luZ2xlQ29tbXVuaWNhdGlvbk1hbmFnZXIoIHNhbF9Cb29sIGJVc2VNdWx0aUNoYW5uZWwgKQo6IENvbW11bmljYXRpb25NYW5hZ2VyKCBiVXNlTXVsdGlDaGFubmVsICkKewoJeEFjdGl2ZUxpbmsgPSBOVUxMOwoJcEluYWN0aXZlTGluayA9IE5VTEw7Cn0KClNpbmdsZUNvbW11bmljYXRpb25NYW5hZ2VyOjp+U2luZ2xlQ29tbXVuaWNhdGlvbk1hbmFnZXIoKQp7CglTdG9wQ29tbXVuaWNhdGlvbigpOwoJaWYgKCBwSW5hY3RpdmVMaW5rICkKCQlwSW5hY3RpdmVMaW5rLT5JbnZhbGlkYXRlTWFuYWdlcigpOwp9CgpzYWxfQm9vbCBTaW5nbGVDb21tdW5pY2F0aW9uTWFuYWdlcjo6U3RvcENvbW11bmljYXRpb24oKQp7CglpZiAoIHhBY3RpdmVMaW5rLklzKCkgKQoJewoJCXNhbF9Cb29sIGJTdWNjZXNzID0geEFjdGl2ZUxpbmstPlN0b3BDb21tdW5pY2F0aW9uKCk7CgkJaWYgKCBwSW5hY3RpdmVMaW5rICkKCQkJcEluYWN0aXZlTGluay0+SW52YWxpZGF0ZU1hbmFnZXIoKTsKCQlwSW5hY3RpdmVMaW5rID0geEFjdGl2ZUxpbms7CgkJeEFjdGl2ZUxpbmsuQ2xlYXIoKTsKCQlyZXR1cm4gYlN1Y2Nlc3M7Cgl9CglyZXR1cm4gc2FsX1RydWU7Cn0KCnNhbF9Cb29sIFNpbmdsZUNvbW11bmljYXRpb25NYW5hZ2VyOjpJc0xpbmtWYWxpZCggQ29tbXVuaWNhdGlvbkxpbmsqIHBDTCApCnsKCXJldHVybiAmeEFjdGl2ZUxpbmsgPT0gcENMOwp9CgpzYWxfdUludDE2IFNpbmdsZUNvbW11bmljYXRpb25NYW5hZ2VyOjpHZXRDb21tdW5pY2F0aW9uTGlua0NvdW50KCkKewoJcmV0dXJuIElzQ29tbXVuaWNhdGlvblJ1bm5pbmcoKT8xOjA7Cn0KCkNvbW11bmljYXRpb25MaW5rUmVmIFNpbmdsZUNvbW11bmljYXRpb25NYW5hZ2VyOjpHZXRDb21tdW5pY2F0aW9uTGluayggc2FsX3VJbnQxNiApCnsKCXJldHVybiB4QWN0aXZlTGluazsKfQoKdm9pZCBTaW5nbGVDb21tdW5pY2F0aW9uTWFuYWdlcjo6Q2FsbENvbm5lY3Rpb25PcGVuZWQoIENvbW11bmljYXRpb25MaW5rKiBwQ0wgKQp7CglEQkdfQVNTRVJUKCAheEFjdGl2ZUxpbmsuSXMoKSwgIkVzIGlzdCBiZXJlaXRzIGVpbiBDb21tdW5pY2F0aW9uTGluayBha3RpdiIpOwoJaWYgKCB4QWN0aXZlTGluay5JcygpICkKCXsKCQlpZiAoIHBJbmFjdGl2ZUxpbmsgKQoJCQlwSW5hY3RpdmVMaW5rLT5JbnZhbGlkYXRlTWFuYWdlcigpOwoJCXBJbmFjdGl2ZUxpbmsgPSB4QWN0aXZlTGluazsKCQl4QWN0aXZlTGluay0+U3RvcENvbW11bmljYXRpb24oKTsJLy8gRGVuIGFsdGVuIExpbmsgYnJ1dGFsIGFid/xyZ2VuCgl9Cgl4QWN0aXZlTGluayA9IHBDTDsKCUNvbW11bmljYXRpb25NYW5hZ2VyOjpDYWxsQ29ubmVjdGlvbk9wZW5lZCggcENMICk7Cn0KCnZvaWQgU2luZ2xlQ29tbXVuaWNhdGlvbk1hbmFnZXI6OkNhbGxDb25uZWN0aW9uQ2xvc2VkKCBDb21tdW5pY2F0aW9uTGluayogcENMICkKewoJQ29tbXVuaWNhdGlvbk1hbmFnZXI6OkNhbGxDb25uZWN0aW9uQ2xvc2VkKCBwQ0wgKTsKCglEQkdfQVNTRVJUKCBwQ0wgPT0geEFjdGl2ZUxpbmssICJTaW5nbGVDb21tdW5pY2F0aW9uTWFuYWdlcjo6Q2FsbENvbm5lY3Rpb25DbG9zZWQgbWl0IGZyZW1kZW0gTGluayIpOwoJaWYgKCBwSW5hY3RpdmVMaW5rICkKCQlwSW5hY3RpdmVMaW5rLT5JbnZhbGlkYXRlTWFuYWdlcigpOwoJcEluYWN0aXZlTGluayA9IHhBY3RpdmVMaW5rOwoJeEFjdGl2ZUxpbmsuQ2xlYXIoKTsKCWJJc0NvbW11bmljYXRpb25SdW5uaW5nID0gc2FsX0ZhbHNlOwp9Cgp2b2lkIFNpbmdsZUNvbW11bmljYXRpb25NYW5hZ2VyOjpEZXN0cm95aW5nTGluayggQ29tbXVuaWNhdGlvbkxpbmsgKnBDTCApCnsKCXBJbmFjdGl2ZUxpbmsgPSBOVUxMOwoJcENMLT5JbnZhbGlkYXRlTWFuYWdlcigpOwp9CgoKU2luZ2xlQ29tbXVuaWNhdGlvbk1hbmFnZXJDbGllbnRWaWFTb2NrZXQ6OlNpbmdsZUNvbW11bmljYXRpb25NYW5hZ2VyQ2xpZW50VmlhU29ja2V0KCBCeXRlU3RyaW5nIGFIb3N0LCBzYWxfdUxvbmcgblBvcnQsIHNhbF9Cb29sIGJVc2VNdWx0aUNoYW5uZWwgKQo6IFNpbmdsZUNvbW11bmljYXRpb25NYW5hZ2VyKCBiVXNlTXVsdGlDaGFubmVsICkKLCBhSG9zdFRvVGFsayggYUhvc3QgKQosIG5Qb3J0VG9UYWxrKCBuUG9ydCApCnsKfQoKClNpbmdsZUNvbW11bmljYXRpb25NYW5hZ2VyQ2xpZW50VmlhU29ja2V0OjpTaW5nbGVDb21tdW5pY2F0aW9uTWFuYWdlckNsaWVudFZpYVNvY2tldCggc2FsX0Jvb2wgYlVzZU11bHRpQ2hhbm5lbCApCjogU2luZ2xlQ29tbXVuaWNhdGlvbk1hbmFnZXIoIGJVc2VNdWx0aUNoYW5uZWwgKQosIGFIb3N0VG9UYWxrKCkKLCBuUG9ydFRvVGFsayggMCApCnsKfQoKCnNhbF9Cb29sIENvbW1vblNvY2tldEZ1bmN0aW9uczo6RG9TdGFydENvbW11bmljYXRpb24oIENvbW11bmljYXRpb25NYW5hZ2VyICpwQ00sIElDb21tdW5pY2F0aW9uTWFuYWdlckNsaWVudCAqcENNQywgQnl0ZVN0cmluZyBhSG9zdCwgc2FsX3VMb25nIG5Qb3J0ICkKewoJdm9zOjpPSW5ldFNvY2tldEFkZHIgQWRkcjsKCXZvczo6T0Nvbm5lY3RvclNvY2tldCAqcENvbm5Tb2NrZXQ7CgoJQWRkci5zZXRBZGRyKCBydGw6Ok9VU3RyaW5nKCBVbmlTdHJpbmcoIGFIb3N0LCBSVExfVEVYVEVOQ09ESU5HX1VURjggKSApICk7CglBZGRyLnNldFBvcnQoIG5Qb3J0ICk7CgoJVGltZVZhbHVlIGFUVjsKCWFUVi5TZWNvbmRzID0gMTA7CQkvLyBXYXJ0ZSAxMCBTZWt1bmRlbgoJYVRWLk5hbm9zZWMgPSAwOwoJZG8KCXsKCQlwQ29ublNvY2tldCA9IG5ldyB2b3M6Ok9Db25uZWN0b3JTb2NrZXQoKTsKCQlwQ29ublNvY2tldC0+c2V0VGNwTm9EZWxheSggMSApOwoJCWlmICggcENvbm5Tb2NrZXQtPmNvbm5lY3QoIEFkZHIsICZhVFYgKSA9PSB2b3M6OklTb2NrZXRUeXBlczo6VFJlc3VsdF9PayApCgkJewoJCQlwQ29ublNvY2tldC0+c2V0VGNwTm9EZWxheSggMSApOwoKCQkJcENNLT5DYWxsQ29ubmVjdGlvbk9wZW5lZCggQ3JlYXRlQ29tbXVuaWNhdGlvbkxpbmsoIHBDTSwgcENvbm5Tb2NrZXQgKSApOwoJCQlyZXR1cm4gc2FsX1RydWU7CgkJfQoJCWVsc2UKCQkJZGVsZXRlIHBDb25uU29ja2V0OwoKCX0gd2hpbGUgKCBwQ01DLT5SZXRyeUNvbm5lY3QoKSApOwoKCXJldHVybiBzYWxfRmFsc2U7Cn0KCg==