LyoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqIENvcHlyaWdodCAoQykgMTk5Ni0xOTk5LCBJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uIGFuZCAgICAqCiogb3RoZXJzLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqCiogRmlsZSB0Ymxjb2xsLmNwcAoqCiogQ3JlYXRlZCBieTogSGVsZW5hIFNoaWgKKgoqIE1vZGlmaWNhdGlvbiBIaXN0b3J5OgoqCiogIERhdGUgICAgICAgIE5hbWUgICAgICAgIERlc2NyaXB0aW9uCiogIDIvNS85NyAgICAgIGFsaXUgICAgICAgIEFkZGVkIHN0cmVhbUluIGFuZCBzdHJlYW1PdXQgbWV0aG9kcy4gIEFkZGVkCiogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yIHdoaWNoIHJlYWRzIFJ1bGVCYXNlZENvbGxhdG9yIG9iamVjdCBmcm9tCiogICAgICAgICAgICAgICAgICAgICAgICAgIGEgYmluYXJ5IGZpbGUuICBBZGRlZCB3cml0ZVRvRmlsZSBtZXRob2Qgd2hpY2ggc3RyZWFtcwoqICAgICAgICAgICAgICAgICAgICAgICAgICBSdWxlQmFzZWRDb2xsYXRvciBvdXQgdG8gYSBiaW5hcnkgZmlsZS4gIFRoZSBzdHJlYW1JbgoqICAgICAgICAgICAgICAgICAgICAgICAgICBhbmQgc3RyZWFtT3V0IG1ldGhvZHMgdXNlIGlzdHJlYW0gYW5kIG9zdHJlYW0gb2JqZWN0cwoqICAgICAgICAgICAgICAgICAgICAgICAgICBpbiBiaW5hcnkgbW9kZS4KKiAgMi8xMS85NyAgICAgYWxpdSAgICAgICAgTW92ZWQgZGVjbGFyYXRpb25zIG91dCBvZiBmb3IgbG9vcCBpbml0aWFsaXplci4KKiAgICAgICAgICAgICAgICAgICAgICAgICAgQWRkZWQgTWFjIGNvbXBhdGliaWxpdHkgI2lmZGVmIGZvciBpb3M6Om5vY3JlYXRlLgoqICAyLzEyLzk3ICAgICBhbGl1ICAgICAgICBNb2RpZmllZCB0byB1c2UgVGFibGVDb2xsYXRpb25EYXRhIHN1Yi1vYmplY3QgdG8KKiAgICAgICAgICAgICAgICAgICAgICAgICAgaG9sZCBpbnZhcmlhbnQgZGF0YS4KKiAgMi8xMy85NyAgICAgYWxpdSAgICAgICAgTW92ZWQgc2V2ZXJhbCBtZXRob2RzIGludG8gdGhpcyBjbGFzcyBmcm9tIENvbGxhdGlvbi4KKiAgICAgICAgICAgICAgICAgICAgICAgICAgQWRkZWQgYSBwcml2YXRlIFJ1bGVCYXNlZENvbGxhdG9yKExvY2FsZSYpIGNvbnN0cnVjdG9yLAoqICAgICAgICAgICAgICAgICAgICAgICAgICB0byBiZSB1c2VkIGJ5IENvbGxhdG9yOjpnZXRJbnN0YW5jZSgpLiAgR2VuZXJhbAoqICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhbiB1cC4gIE1hZGUgdXNlIG9mIFVFcnJvckNvZGUgdmFyaWFibGVzIGNvbnNpc3RlbnQuCiogIDIvMjAvOTcgICAgIGhlbGVuYSAgICAgIEFkZGVkIGNsb25lLCBvcGVyYXRvcj09LCBvcGVyYXRvciE9LCBvcGVyYXRvcj0sIGFuZCBjb3B5CiogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yIGFuZCBnZXREeW5hbWljQ2xhc3NJRC4KKiAgMy81Lzk3ICAgICAgYWxpdSAgICAgICAgQ2hhbmdlZCBjb21wYWN0aW9uIGN5Y2xlIHRvIGltcHJvdmUgcGVyZm9ybWFuY2UuICBXZQoqICAgICAgICAgICAgICAgICAgICAgICAgICB1c2UgdGhlIG1heGltdW0gYWxsb3dhYmxlIHZhbHVlIHdoaWNoIGlzIGtCbG9ja0NvdW50LgoqICAgICAgICAgICAgICAgICAgICAgICAgICBNb2RpZmllZCBnZXRSdWxlcygpIHRvIGxvYWQgcnVsZXMgZHluYW1pY2FsbHkuICBDaGFuZ2VkCiogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdEZyb21GaWxlKCkgY2FsbCB0byBhY2NvbW9kYXRlIHRoaXMgKGFkZGVkCiogICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlciB0byBzcGVjaWZ5IHdoZXRoZXIgYmluYXJ5IGxvYWRpbmcgaXMgdG8KKiAgICAgICAgICAgICAgICAgICAgICAgICAgdGFrZSBwbGFjZSkuCiogMDUvMDYvOTcgICAgIGhlbGVuYSAgICAgIEFkZGVkIG1lbW9yeSBhbGxvY2F0aW9uIGVycm9yIGNoZWNrLgoqICA2LzIwLzk3ICAgICBoZWxlbmEgICAgICBKYXZhIGNsYXNzIG5hbWUgY2hhbmdlLgoqICA2LzIzLzk3ICAgICBoZWxlbmEgICAgICBBZGRpbmcgY29tbWVudHMgdG8gbWFrZSBjb2RlIG1vcmUgcmVhZGFibGUuCiogMDkvMDMvOTcgICAgIGhlbGVuYSAgICAgIEFkZGVkIGNyZWF0ZUNvbGxhdGlvbktleVZhbHVlcygpLgoqIDA2LzI2Lzk4ICAgICBlcm0gICAgICAgICBDaGFuZ2VzIGZvciBDb2xsYXRpb25LZXlzIHVzaW5nIGJ5dGUgYXJyYXlzLgoqIDA4LzEwLzk4ICAgICBlcm0gICAgICAgICBTeW5jaGVkIHdpdGggMS4yIHZlcnNpb24gb2YgUnVsZUJhc2VkQ29sbGF0b3IuamF2YQoqIDA0LzIzLzk5ICAgICBzdGVwaGVuICAgICBSZW1vdmVkIEVEZWNvbXBvc2l0aW9uTW9kZSwgbWVyZ2VkIHdpdGgKKiAgICAgICAgICAgICAgICAgICAgICAgICAgTm9ybWFsaXplcjo6RU1vZGUKKiAwNi8xNC85OSAgICAgc3RlcGhlbiAgICAgUmVtb3ZlZCBrUmVzb3VyY2VCdW5kbGVTdWZmaXgKKiAwNi8yMi85OSAgICAgc3RlcGhlbiAgICAgRml4ZWQgbG9naWMgaW4gY29uc3RydWN0RnJvbUZpbGUoKSBzaW5jZSAuY3R4CiogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVzIGFyZSBubyBsb25nZXIgdXNlZC4KKiAxMS8wMi85OSAgICAgaGVsZW5hICAgICAgQ29sbGF0b3IgcGVyZm9ybWFuY2UgZW5oYW5jZW1lbnRzLiAgU3BlY2lhbCBjYXNlCiogICAgICAgICAgICAgICAgICAgICAgICAgIGZvciBOT19PUCBzaXR1YXRpb25zLiAKKiAxMS8xNy85OSAgICAgc3JsICAgICAgICAgTW9yZSBwZXJmb3JtYW5jZSBlbmhhbmNlbWVudHMuIElubGluZWQgc29tZSBpbnRlcm5hbCBmdW5jdGlvbnMuCiogMTIvMTUvOTkgICAgIGFsaXUgICAgICAgIFVwZGF0ZSB0byBzdXBwb3J0IFRoYWkgY29sbGF0aW9uLiAgTW92ZSBOb3JtYWxpemVySXRlcmF0b3IKKiAgICAgICAgICAgICAgICAgICAgICAgICAgdG8gaW1wbGVtZW50YXRpb24gZmlsZS4KKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqLwoKI2luY2x1ZGUgInVjbXAzMi5oIgojaW5jbHVkZSAidGNvbGRhdGEuaCIKCiNpbmNsdWRlICJ1bmljb2RlL3RibGNvbGwuaCIKCiNpbmNsdWRlICJ1bmljb2RlL2NvbGVpdHIuaCIKI2luY2x1ZGUgInVuaWNvZGUvbG9jaWQuaCIKI2luY2x1ZGUgInVuaWNvZGUvdW5pY29kZS5oIgojaW5jbHVkZSAidGFibGVzLmgiCiNpbmNsdWRlICJ1bmljb2RlL25vcm1senIuaCIKI2luY2x1ZGUgIm1lcmdlY29sLmgiCiNpbmNsdWRlICJ1bmljb2RlL3Jlc2J1bmQuaCIKI2luY2x1ZGUgImZpbGVzdHJtLmgiCiNpbmNsdWRlICJ1bWVtc3RybS5oIgoKI2lmZGVmIF9ERUJVRwojaW5jbHVkZSAidW5pc3RybS5oIgojZW5kaWYKCiNpbmNsdWRlICJjb21waXRyLmgiCgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSAidW5pY29kZS91c3RyaW5nLmgiCgojaW5jbHVkZSAiY21lbW9yeS5oIgoKCmNsYXNzIFJ1bGVCYXNlZENvbGxhdG9yU3RyZWFtZXIKewpwdWJsaWM6CiAgIHN0YXRpYyB2b2lkIHN0cmVhbUluKFJ1bGVCYXNlZENvbGxhdG9yKiBjb2xsYXRvciwgRmlsZVN0cmVhbSogaXMpOwogICBzdGF0aWMgdm9pZCBzdHJlYW1PdXQoY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIGNvbGxhdG9yLCBGaWxlU3RyZWFtKiBvcyk7CiAgIHN0YXRpYyB2b2lkIHN0cmVhbUluKFJ1bGVCYXNlZENvbGxhdG9yKiBjb2xsYXRvciwgVU1lbW9yeVN0cmVhbSogaXMpOwogICBzdGF0aWMgdm9pZCBzdHJlYW1PdXQoY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIGNvbGxhdG9yLCBVTWVtb3J5U3RyZWFtKiBvcyk7Cn07CgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gIFRoZSBmb2xsb3dpbmcgZGlhZ3JhbSBzaG93cyB0aGUgZGF0YSBzdHJ1Y3R1cmUgb2YgdGhlIFJ1bGVCYXNlZENvbGxhdG9yIG9iamVjdC4KLy8gIFN1cHBvc2Ugd2UgaGF2ZSB0aGUgcnVsZSwgd2hlcmUgJ28tdW1sYXV0JyBpcyB0aGUgdW5pY29kZSBjaGFyIDB4MDBGNi4KLy8gICJhLCBBIDwgYiwgQiA8IGMsIEMsIGNoLCBjSCwgQ2gsIENIIDwgZCwgRCAuLi4gPCBvLCBPOyAnby11bWxhdXQnL0UsICdPLXVtbGF1dCcvRSAuLi4iLgovLyAgV2hhdCB0aGUgcnVsZSBzYXlzIGlzLCBzb3J0cyAnY2gnbGlnYXR1cmVzIGFuZCAnYycgb25seSB3aXRoIHRlcnRpYXJ5IGRpZmZlcmVuY2UgYW5kCi8vICBzb3J0cyAnby11bWxhdXQnIGFzIGlmIGl0J3MgYWx3YXlzIGV4cGFuZGVkIHdpdGggJ2UnLgovLwovLyBtYXBwaW5nIHRhYmxlICAgICAgICAgICAgICAgICAgICAgICBjb250cmFjdGluZyBsaXN0ICAgICAgICAgICAgICAgICAgZXhwYW5kaW5nIGxpc3QKLy8gKGNvbnRhaW5zIGFsbCB1bmljb2RlIGNoYXIKLy8gIGVudHJpZXMpICAgICAgICAgICAgICAgICAgICAgICAgIF9fXyAgICAgX19fX19fX19fX19fXyAgICAgICAgIF9fX19fX19fX19fX19fX19fX19fX19fX18KLy8gICBfX19fX19fXyAgICAgICAgICAgICAgICAgICB8PT0+fF8qX3wtLT58J2MnICB8dignYycpIHwgICB8PT0+fHYoJ28nKXx2KCd1bWxhdXQnKXx2KCdlJyl8Ci8vICB8X1x1MDAwMV98LS0+IHYoJ1x1MDAwMScpICAgfCAgIHxfOl98ICAgfC0tLS0tLS0tLS0tLS18ICAgfCAgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAovLyAgfF9cdTAwMDJffC0tPiB2KCdcdTAwMDInKSAgIHwgICB8XzpffCAgIHwnY2gnIHx2KCdjaCcpfCAgIHwgICB8ICAgICAgICAgICAgIDogICAgICAgICAgIHwKLy8gIHxfX19fOl9fX3wgICAgICAgICAgICAgICAgICB8ICAgfF86X3wgICB8LS0tLS0tLS0tLS0tLXwgICB8ICAgfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Ci8vICB8X19fXzpfX198ICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgfCdjSCcgfHYoJ2NIJyl8ICAgfCAgIHwgICAgICAgICAgICAgOiAgICAgICAgICAgfAovLyAgfF9fJ2EnX19ffC0tPiB2KCdhJykgICAgICAgIHwgICAgICAgICAgIHwtLS0tLS0tLS0tLS0tfCAgIHwgICB8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKLy8gIHxfXydiJ19fX3wtLT4gdignYicpICAgICAgICB8ICAgICAgICAgICB8J0NoJyB8dignQ2gnKXwgICB8ICAgfCAgICAgICAgICAgICA6ICAgICAgICAgICB8Ci8vICB8X19fXzpfX198ICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgfC0tLS0tLS0tLS0tLS18ICAgfCAgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAovLyAgfF9fX186X19ffCAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgIHwnQ0gnIHx2KCdDSCcpfCAgIHwgICB8ICAgICAgICAgICAgIDogICAgICAgICAgIHwKLy8gIHxfX18nYydfX3wtLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgICAgICAgLS0tLS0tLS0tLS0tLSAgICB8ICAgfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Ci8vICB8X19fXzpfX198ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIHwgICAgICAgICAgICAgOiAgICAgICAgICAgfAovLyAgfG8tdW1sYXV0fC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgICB8X19fX19fX19fX19fX19fX19fX19fX19fX3wKLy8gIHxfX19fOl9fX3wKLy8KLy8KLy8gTm90ZWQgYnkgSGVsZW5hIFNoaWggb24gNi8yMy85NyB3aXRoIHBlbmRpbmcgZGVzaWduIGNoYW5nZXMgKHNsaW1taW5nIGNvbGxhdGlvbikuCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OkNIQVJJTkRFWCA9IDB4NzAwMDAwMDA7ICAgICAgICAgICAgIC8vIG5lZWQgbG9vayB1cCBpbiAuY29tbWl0KCkKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6RVhQQU5EQ0hBUklOREVYID0gMHg3RTAwMDAwMDsgICAgICAgLy8gRXhwYW5kIGluZGV4IGZvbGxvd3MKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6Q09OVFJBQ1RDSEFSSU5ERVggPSAweDdGMDAwMDAwOyAgICAgLy8gY29udHJhY3QgaW5kZXhlcyBmb2xsb3dzCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlVOTUFQUEVEID0gMHhGRkZGRkZGRjsgICAgICAgICAgICAgIC8vIHVubWFwcGVkIGNoYXJhY3RlciB2YWx1ZXMKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6UFJJTUFSWU9SREVSSU5DUkVNRU5UID0gMHgwMDAxMDAwMDsgLy8gcHJpbWFyeSBzdHJlbmd0aCBpbmNyZW1lbnQKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6U0VDT05EQVJZT1JERVJJTkNSRU1FTlQgPSAweDAwMDAwMTAwOyAvLyBzZWNvbmRhcnkgc3RyZW5ndGggaW5jcmVtZW50CmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlRFUlRJQVJZT1JERVJJTkNSRU1FTlQgPSAweDAwMDAwMDAxOyAvLyB0ZXJ0aWFyeSBzdHJlbmd0aCBpbmNyZW1lbnQKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6TUFYSUdOT1JBQkxFID0gMHgwMDAxMDAwMDsgICAgICAgICAgLy8gbWF4aW11bSBpZ25vcmFibGUgY2hhciBvcmRlciB2YWx1ZQpjb25zdCBpbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjpQUklNQVJZT1JERVJNQVNLID0gMHhmZmZmMDAwMDsgICAgICAvLyBtYXNrIG9mZiBhbnl0aGluZyBidXQgcHJpbWFyeSBvcmRlcgpjb25zdCBpbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjpTRUNPTkRBUllPUkRFUk1BU0sgPSAweDAwMDBmZjAwOyAgICAvLyBtYXNrIG9mZiBhbnl0aGluZyBidXQgc2Vjb25kYXJ5IG9yZGVyCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlRFUlRJQVJZT1JERVJNQVNLID0gMHgwMDAwMDBmZjsgICAgIC8vIG1hc2sgb2ZmIGFueXRoaW5nIGJ1dCB0ZXJ0aWFyeSBvcmRlcgpjb25zdCBpbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjpTRUNPTkRBUllSRVNFVE1BU0sgPSAweDAwMDBmZmZmOyAgICAvLyBtYXNrIG9mZiBzZWNvbmRhcnkgYW5kIHRlcnRpYXJ5IG9yZGVyCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OklHTk9SQUJMRU1BU0sgPSAweDAwMDBmZmZmOyAgICAgICAgIC8vIG1hc2sgb2ZmIGlnbm9yYWJsZSBjaGFyIG9yZGVyCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlBSSU1BUllESUZGRVJFTkNFT05MWSA9IDB4ZmZmZjAwMDA7IC8vIHVzZSBvbmx5IHRoZSBwcmltYXJ5IGRpZmZlcmVuY2UKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6U0VDT05EQVJZRElGRkVSRU5DRU9OTFkgPSAweGZmZmZmZjAwOyAgLy8gdXNlIG9ubHkgdGhlIHByaW1hcnkgYW5kIHNlY29uZGFyeSBkaWZmZXJlbmNlCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlBSSU1BUllPUkRFUlNISUZUID0gMTY7ICAgICAgICAgICAgIC8vIHByaW1hcnkgb3JkZXIgc2hpZnQKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6U0VDT05EQVJZT1JERVJTSElGVCA9IDg7ICAgICAgICAgICAgLy8gc2Vjb25kYXJ5IG9yZGVyIHNoaWZ0CmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlNPUlRLRVlPRkZTRVQgPSAxOyAgICAgICAgICAgICAgICAgIC8vIG1pbmltdW0gc29ydCBrZXkgb2Zmc2V0CmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OkNPTlRSQUNUQ0hBUk9WRVJGTE9XID0gMHg3RkZGRkZGRjsgIC8vIEluZGljYXRlcyB0aGUgY2hhciBpcyBhIGNvbnRyYWN0IGNoYXIKCmNvbnN0IGludDE2X3QgUnVsZUJhc2VkQ29sbGF0b3I6OkZJTEVJRCA9IDB4NTQ0MzsgICAgICAgICAgICAgICAgICAgIC8vIHVuaXF1ZSBmaWxlIGlkIGZvciBwYXJpdHkgY2hlY2sKY29uc3QgY2hhciogUnVsZUJhc2VkQ29sbGF0b3I6OmtGaWxlbmFtZVN1ZmZpeCA9ICIuY29sIjsgICAgICAgICAgICAgLy8gYmluYXJ5IGNvbGxhdGlvbiBmaWxlIGV4dGVuc2lvbgpjaGFyICBSdWxlQmFzZWRDb2xsYXRvcjo6ZmdDbGFzc0lEID0gMDsgLy8gVmFsdWUgaXMgaXJyZWxldmFudCAgICAgICAvLyBjbGFzcyBpZAoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vIE5vcm1hbGl6ZXJJdGVyYXRvcgovLwovLyBUaGlzIGNsYXNzIGlzIGVzc2VudGlhbGx5IGEgZHVwbGljYXRlIG9mIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciwKLy8gc3RyaXBwZWQgZG93biBmb3Igc3BlZWQuICBJdCBpcyBkZWNsYXJlZCBoZXJlIHNvIHdlIGNhbiBpbmNvcnBvcmF0ZQovLyBpbnRlcm5hbCBjbGFzc2VzIGFzIHN1Ym9iamVjdHMsIGFzIHdlbGwgYXMganVzdCB0byBoaWRlIGl0IGZyb20gdGhlCi8vIHB1YmxpYyBpbnRlcmZhY2UuCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKLyogSW50ZXJuYWwgY2xhc3MgZm9yIHF1aWNrIGl0ZXJhdGlvbiBvdmVyIHRoZSB0ZXh0LgogICAxMDAlIHB1cmUgaW5saW5lIGNvZGUKKi8KY2xhc3MgTm9ybWFsaXplckl0ZXJhdG9yIHsgCnB1YmxpYzoKICAgIE5vcm1hbGl6ZXIgKmN1cnNvcjsKICAgIFZlY3Rvck9mSW50ICpidWZmZXJBbGlhczsKICAgIFZlY3Rvck9mSW50ICpyZW9yZGVyQnVmZmVyOwogICAgVmVjdG9yT2ZJbnQgb3duQnVmZmVyOwogICAgVUNoYXIqICAgICAgdGV4dDsKICAgIGludDMyX3QgICAgIGV4cEluZGV4OwogICAgaW50MzJfdCAgICAgdGV4dExlbjsKICAgIFVUZXh0T2Zmc2V0ICBjdXJyZW50T2Zmc2V0OwogICAgCiAgICBOb3JtYWxpemVySXRlcmF0b3Iodm9pZCk7CiAgICBOb3JtYWxpemVySXRlcmF0b3IoY29uc3QgVUNoYXIqIHNvdXJjZSwgaW50MzJfdCBsZW5ndGgsIE5vcm1hbGl6ZXI6OkVNb2RlIG1vZGUpOwogICAgfk5vcm1hbGl6ZXJJdGVyYXRvcih2b2lkKTsKICAgIHZvaWQgc2V0VGV4dChjb25zdCBVQ2hhciogc291cmNlLCBpbnQzMl90IGxlbmd0aCwgVUVycm9yQ29kZSYgc3RhdHVzKTsKICAgIHZvaWQgc2V0TW9kZUFuZFRleHQoTm9ybWFsaXplcjo6RU1vZGUgbW9kZSwgY29uc3QgVUNoYXIqIHNvdXJjZSwgaW50MzJfdCBsZW5ndGgsIFVFcnJvckNvZGUmIHN0YXR1cyk7CiAgICAKICAgIFVDaGFyIGN1cnJlbnQodm9pZCkgY29uc3Q7CiAgICBVQ2hhciBuZXh0KHZvaWQpOwogICAgdm9pZCByZXNldCh2b2lkKTsKfTsKCmlubGluZQpOb3JtYWxpemVySXRlcmF0b3I6Ok5vcm1hbGl6ZXJJdGVyYXRvcigpIDoKICAgIGN1cnNvcigwKSwKICAgIGJ1ZmZlckFsaWFzKDApLAogICAgcmVvcmRlckJ1ZmZlcigwKSwKICAgIG93bkJ1ZmZlcigyKSwKICAgIHRleHQoMCksCiAgICBleHBJbmRleCgwKSwKICAgIHRleHRMZW4oMCksCiAgICBjdXJyZW50T2Zmc2V0KDApCnsKfQoKaW5saW5lCk5vcm1hbGl6ZXJJdGVyYXRvcjo6Tm9ybWFsaXplckl0ZXJhdG9yKGNvbnN0IFVDaGFyKiBzb3VyY2UsIGludDMyX3QgbGVuZ3RoLCBOb3JtYWxpemVyOjpFTW9kZSBtb2RlKSA6CiAgICBjdXJzb3IoMCksCiAgICBidWZmZXJBbGlhcygwKSwKICAgIHJlb3JkZXJCdWZmZXIoMCksCiAgICBvd25CdWZmZXIoMiksCiAgICB0ZXh0KDApLAogICAgZXhwSW5kZXgoMCksCiAgICB0ZXh0TGVuKDApLAogICAgY3VycmVudE9mZnNldCgwKQp7CiAgICBpZiAobW9kZSA9PSBOb3JtYWxpemVyOjpOT19PUCkgewogICAgICAgIHRleHQgPSAoVUNoYXIqKXNvdXJjZTsKICAgICAgICB0ZXh0TGVuID0gbGVuZ3RoOwogICAgICAgIGN1cnJlbnRPZmZzZXQgPSAwOwogICAgfSBlbHNlIHsKICAgICAgICBjdXJzb3IgPSBuZXcgTm9ybWFsaXplcihzb3VyY2UsIGxlbmd0aCwgbW9kZSk7CgogICAgfQp9CgppbmxpbmUKTm9ybWFsaXplckl0ZXJhdG9yOjp+Tm9ybWFsaXplckl0ZXJhdG9yKCkgCnsKICAgIGlmIChjdXJzb3IgIT0gMCkgewogICAgICAgIGRlbGV0ZSBjdXJzb3I7CiAgICAgICAgY3Vyc29yID0gMDsKICAgIH0KICAgIGlmIChyZW9yZGVyQnVmZmVyICE9IDApIHsKICAgICAgICBkZWxldGUgcmVvcmRlckJ1ZmZlcjsKICAgIH0KfQoKaW5saW5lCnZvaWQKTm9ybWFsaXplckl0ZXJhdG9yOjpzZXRUZXh0KGNvbnN0IFVDaGFyKiBzb3VyY2UsIGludDMyX3QgbGVuZ3RoLCBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmIChjdXJzb3IgPT0gMCkgewogICAgICAgIHRleHQgPSAoVUNoYXIqKXNvdXJjZTsKICAgICAgICB0ZXh0TGVuID0gbGVuZ3RoOwogICAgICAgIGN1cnJlbnRPZmZzZXQgPSAwOwoKICAgIH0gZWxzZSB7CiAgICAgICAgdGV4dCA9IDA7CiAgICAgICAgY3Vyc29yLT5zZXRUZXh0KHNvdXJjZSwgbGVuZ3RoLCBzdGF0dXMpOwogICAgfQogICAgYnVmZmVyQWxpYXMgPSAwOwogICAgY3VycmVudE9mZnNldCA9IDA7Cn0KCi8qIFlvdSBjYW4gb25seSBzZXQgbW9kZSBhZnRlciB0aGUgY29tcGFyaXNpb24gb2YgdHdvIHN0cmluZ3MgaXMgY29tcGxldGVkLgogICBTZXR0aW5nIHRoZSBtb2RlIGluIHRoZSBtaWRkbGUgb2YgYSBjb21wYXJpc29uIGlzIG5vdCBhbGxvd2VkLgogICAqLwppbmxpbmUKdm9pZAoKTm9ybWFsaXplckl0ZXJhdG9yOjpzZXRNb2RlQW5kVGV4dChOb3JtYWxpemVyOjpFTW9kZSBtb2RlLCBjb25zdCBVQ2hhciogc291cmNlLCBpbnQzMl90IGxlbmd0aCwgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICBpZihtb2RlICE9IE5vcm1hbGl6ZXI6Ok5PX09QKQogICAgewogICAgICAgIC8qIERPIGhhdmUgYSBtb2RlIC0gIHdpbGwgbmVlZCBhIG5vcm1hbGl6ZXIgb2JqZWN0ICovCiAgICAgICAgaWYoY3Vyc29yICE9IE5VTEwpCiAgICAgICAgewogICAgICAgICAgICAvKiBKdXN0IG1vZGlmeSB0aGUgZXhpc3RpbmcgY3Vyc29yICovCiAgICAgICAgICAgIGN1cnNvci0+c2V0TW9kZShtb2RlKTsKICAgICAgICAgICAgY3Vyc29yLT5zZXRUZXh0KHNvdXJjZSwgbGVuZ3RoLCBzdGF0dXMpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBjdXJzb3IgPSBuZXcgTm9ybWFsaXplcihzb3VyY2UsIGxlbmd0aCwgbW9kZSk7CiAgICAgICAgfQoKICAgICAgICAvKiBSRVNFVCB0aGUgb2xkIGRhdGEgKi8KICAgICAgICB0ZXh0ID0gMDsKICAgICAgICB0ZXh0TGVuID0gMDsKICAgIH0KICAgIGVsc2UgCiAgICB7CiAgICAgICAgLyogTk9fT1AgbW9kZS4uICovCiAgICAgICAgaWYoY3Vyc29yICE9IE5VTEwpCiAgICAgICAgeyAvKiBnZXQgcmlkIG9mIHRoZSBvbGQgY3Vyc29yICovCiAgICAgICAgICAgIGRlbGV0ZSBjdXJzb3I7IAogICAgICAgICAgICBjdXJzb3IgPSAwOwogICAgICAgIH0KCiAgICAgICAgdGV4dCA9IChVQ2hhciopc291cmNlOwogICAgICAgIHRleHRMZW4gPSBsZW5ndGg7CiAgICB9CiAgICBjdXJyZW50T2Zmc2V0ID0gMDsgLyogYWx3YXlzICovCiAgIAogICAgYnVmZmVyQWxpYXMgPSAwOwp9CgppbmxpbmUKVUNoYXIKTm9ybWFsaXplckl0ZXJhdG9yOjpjdXJyZW50KHZvaWQpIGNvbnN0CnsKICAgIGlmICh0ZXh0ICE9IDApIHsKICAgICAgICBpZihjdXJyZW50T2Zmc2V0ID49IHRleHRMZW4pCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gTm9ybWFsaXplcjo6RE9ORTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIHRleHRbY3VycmVudE9mZnNldF07CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiAoVUNoYXIpY3Vyc29yLT5jdXJyZW50KCk7Cn0KCgppbmxpbmUKVUNoYXIKTm9ybWFsaXplckl0ZXJhdG9yOjpuZXh0KHZvaWQpCnsKICAgIGlmICh0ZXh0ICE9IDApIHsKICAgICAgICByZXR1cm4gKFVDaGFyKSgoY3VycmVudE9mZnNldCA8IHRleHRMZW4pID8gdGV4dFsrK2N1cnJlbnRPZmZzZXRdIDogTm9ybWFsaXplcjo6RE9ORSk7CiAgICB9CiAgICByZXR1cm4gKFVDaGFyKWN1cnNvci0+bmV4dCgpOwp9CgppbmxpbmUKdm9pZApOb3JtYWxpemVySXRlcmF0b3I6OnJlc2V0KHZvaWQpCnsKICAgIGN1cnJlbnRPZmZzZXQgPSAwOwogICAgaWYoY3Vyc29yKQogICAgewogICAgICAgIGN1cnNvci0+cmVzZXQoKTsKICAgIH0KfQoKLy89PT09PT09PT09PT09PT09IFNvbWUgaW5saW5lIGRlZmluaXRpb25zIG9mIGltcGxlbWVudGF0aW9uIGZ1bmN0aW9ucy4uLi4uLi4uID09PT09PT09Ci8qKgogKiBBIGNsb25lIG9mIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6bWFrZVJlb3JkZXJlZEJ1ZmZlciwgdHJpbW1lZCBkb3duCiAqIHRvIG9ubHkgaGFuZGxlIGZvcndhcmQuCiAqLwppbmxpbmUgVmVjdG9yT2ZJbnQqClJ1bGVCYXNlZENvbGxhdG9yOjptYWtlUmVvcmRlcmVkQnVmZmVyKE5vcm1hbGl6ZXJJdGVyYXRvciogY3Vyc29yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVQ2hhciBjb2xGaXJzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50MzJfdCBsYXN0VmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZlY3Rvck9mSW50KiBsYXN0RXhwYW5zaW9uKSBjb25zdCB7CiAgICBWZWN0b3JPZkludCogcmVzdWx0OwoKICAgIGludDMyX3QgZmlyc3RWYWx1ZSA9IHVjbXAzMl9nZXQoZGF0YS0+bWFwcGluZywgY29sRmlyc3QpOwogICAgaWYgKGZpcnN0VmFsdWUgPj0gQ09OVFJBQ1RDSEFSSU5ERVgpIHsKICAgICAgICBVRXJyb3JDb2RlIHN0YXR1cyA9IFVfWkVST19FUlJPUjsKICAgICAgICBmaXJzdFZhbHVlID0gbmV4dENvbnRyYWN0Q2hhcihjdXJzb3IsIGNvbEZpcnN0LCBzdGF0dXMpOwogICAgfQoKICAgIFZlY3Rvck9mSW50KiBmaXJzdEV4cGFuc2lvbiA9IE5VTEw7CiAgICBpZiAoZmlyc3RWYWx1ZSA+PSBFWFBBTkRDSEFSSU5ERVgpIHsKICAgICAgICBmaXJzdEV4cGFuc2lvbiA9IGdldEV4cGFuZFZhbHVlTGlzdChmaXJzdFZhbHVlKTsKICAgIH0KCiAgICBpZiAoZmlyc3RFeHBhbnNpb24gPT0gTlVMTCAmJiBsYXN0RXhwYW5zaW9uID09IE5VTEwpIHsKICAgICAgICBjdXJzb3ItPm93bkJ1ZmZlci5hdCgwKSA9IGZpcnN0VmFsdWU7CiAgICAgICAgY3Vyc29yLT5vd25CdWZmZXIuYXQoMSkgPSBsYXN0VmFsdWU7CiAgICAgICAgcmVzdWx0ID0gJmN1cnNvci0+b3duQnVmZmVyOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgaW50MzJfdCBmaXJzdExlbmd0aCA9IGZpcnN0RXhwYW5zaW9uPT1OVUxMPyAxIDogZmlyc3RFeHBhbnNpb24tPnNpemUoKTsKICAgICAgICBpbnQzMl90IGxhc3RMZW5ndGggPSBsYXN0RXhwYW5zaW9uPT1OVUxMPyAxIDogbGFzdEV4cGFuc2lvbi0+c2l6ZSgpOwogICAgICAgIGlmIChjdXJzb3ItPnJlb3JkZXJCdWZmZXIgPT0gTlVMTCkgewogICAgICAgICAgICBjdXJzb3ItPnJlb3JkZXJCdWZmZXIgPSBuZXcgVmVjdG9yT2ZJbnQoZmlyc3RMZW5ndGgrbGFzdExlbmd0aCk7CiAgICAgICAgfQogICAgICAgIC8vIHJlb3JkZXJkQnVmZmVyIGdldHMgcmV1c2VkIGZvciB0aGUgbGlmZSBvZiB0aGlzIG9iamVjdC4KICAgICAgICAvLyBTaW5jZSBpdHMgaW50ZXJuYWwgYnVmZmVyIG9ubHkgZ3Jvd3MsIHRoZXJlIGlzIGEgZGFuZ2VyCiAgICAgICAgLy8gdGhhdCBpdCB3aWxsIGdldCByZWFsbHksIHJlYWxseSBiaWcsIGFuZCBuZXZlciBzaHJpbmsuICBJZgogICAgICAgIC8vIHRoaXMgaXMgYWN0dWFsbHkgaGFwcGVuaW5nLCBpbnNlcnQgY29kZSBoZXJlIHRvIGNoZWNrIGZvcgogICAgICAgIC8vIHRoZSBjb25kaXRpb24uICBTb21ldGhpbmcgYWxvbmcgdGhlIGxpbmVzIG9mOgogICAgICAgIC8vISBlbHNlIGlmIChyZW9yZGVyQnVmZmVyLT5zaXplKCkgPj0gMjU2ICYmCiAgICAgICAgLy8hICAgICAgICAgIChmaXJzdExlbmd0aCtsYXN0TGVuZ3RoKSA8IDE2KSB7CiAgICAgICAgLy8hICAgICBkZWxldGUgcmVvcmRlckJ1ZmZlcjsKICAgICAgICAvLyEgICAgIHJlb3JkZXJCdWZmZXIgPSBuZXcgVmVjdG9yT2ZJbnQoZmlyc3RMZW5ndGgrbGFzdExlbmd0aCk7CiAgICAgICAgLy8hIH0KICAgICAgICAvLyBUaGUgc3BlY2lmaWMgbnVtZXJpYyB2YWx1ZXMgbmVlZCB0byBiZSBkZXRlcm1pbmVkCiAgICAgICAgLy8gZW1waXJpY2FsbHkuIFthbGl1XQogICAgICAgIHJlc3VsdCA9IGN1cnNvci0+cmVvcmRlckJ1ZmZlcjsKCiAgICAgICAgaWYgKGZpcnN0RXhwYW5zaW9uID09IE5VTEwpIHsKICAgICAgICAgICAgcmVzdWx0LT5hdFB1dCgwLCBmaXJzdFZhbHVlKTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIC8vIFN5c3RlbS5hcnJheWNvcHkoZmlyc3RFeHBhbnNpb24sIDAsIHJlc3VsdCwgMCwgZmlyc3RMZW5ndGgpOwogICAgICAgICAgICAqcmVzdWx0ID0gKmZpcnN0RXhwYW5zaW9uOwogICAgICAgIH0KCiAgICAgICAgaWYgKGxhc3RFeHBhbnNpb24gPT0gTlVMTCkgewogICAgICAgICAgICByZXN1bHQtPmF0UHV0KGZpcnN0TGVuZ3RoLCBsYXN0VmFsdWUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgLy8gU3lzdGVtLmFycmF5Y29weShsYXN0RXhwYW5zaW9uLCAwLCByZXN1bHQsIGZpcnN0TGVuZ3RoLCBsYXN0TGVuZ3RoKTsKICAgICAgICAgICAgZm9yIChpbnQzMl90IGk9MDsgaTxsYXN0TGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgIHJlc3VsdC0+YXRQdXQoZmlyc3RMZW5ndGggKyBpLCBsYXN0RXhwYW5zaW9uLT5hdChpKSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmVzdWx0LT5zZXRTaXplKGZpcnN0TGVuZ3RoK2xhc3RMZW5ndGgpOwogICAgfQoKICAgIHJldHVybiByZXN1bHQ7Cn0KCgoKCgppbmxpbmUgaW50MzJfdApSdWxlQmFzZWRDb2xsYXRvcjo6c3RyZW5ndGhPcmRlcihpbnQzMl90IHZhbHVlKSBjb25zdAp7CiAgICBpZiAoZ2V0U3RyZW5ndGgoKSA9PSBQUklNQVJZKQogICAgewogICAgICAgIHJldHVybiAodmFsdWUgJiBQUklNQVJZRElGRkVSRU5DRU9OTFkpOwogICAgfSBlbHNlIGlmIChnZXRTdHJlbmd0aCgpID09IFNFQ09OREFSWSkKICAgIHsKICAgICAgICByZXR1cm4gKHZhbHVlICYgU0VDT05EQVJZRElGRkVSRU5DRU9OTFkpOwogICAgfQogICAgcmV0dXJuIHZhbHVlOwp9CgoKaW5saW5lIGludDMyX3QKUnVsZUJhc2VkQ29sbGF0b3I6OmdldFN0cmVuZ3RoT3JkZXIoTm9ybWFsaXplckl0ZXJhdG9yKiBjdXJzb3IsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlIHN0YXR1cykgY29uc3QKewogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUjsKICAgIH0KCiAgICBpZiAoY3Vyc29yLT5idWZmZXJBbGlhcyAhPSBOVUxMKQogICAgewogICAgICAgIC8vIGJ1ZmZlckFsaWFzIG5lZWRzIGEgYml0IG9mIGFuIGV4cGxhbmF0aW9uLgogICAgICAgIC8vIFdoZW4gd2UgaGl0IGFuIGV4cGFuZGluZyBjaGFyYWN0ZXIgaW4gdGhlIHRleHQsIHdlIGNhbGwgdGhlIG9yZGVyJ3MKICAgICAgICAvLyBnZXRFeHBhbmRWYWx1ZXMgbWV0aG9kIHRvIHJldHJpZXZlIGFuIGFycmF5IG9mIHRoZSBvcmRlcmluZ3MgZm9yIGFsbAogICAgICAgIC8vIG9mIHRoZSBjaGFyYWN0ZXJzIGluIHRoZSBleHBhbnNpb24gKHNlZSB0aGUgZW5kIG9mIHRoaXMgbWV0aG9kKS4KICAgICAgICAvLyBUaGUgZmlyc3Qgb3JkZXJpbmcgaXMgcmV0dXJuZWQsIGFuZCBhbiBhbGlhcyB0byB0aGUgb3JkZXJpbmdzIGFycmF5CiAgICAgICAgLy8gaXMgc2F2ZWQgc28gdGhhdCB0aGUgcmVtYWluaW5nIG9yZGVyaW5ncyBjYW4gYmUgcmV0dXJuZWQgb24gc3Vic2VxdWVudAogICAgICAgIC8vIGNhbGxzIHRvIG5leHQuICBTbywgaWYgdGhlIGV4cGFuZGluZyBidWZmZXIgaXMgbm90IGV4aGF1c3RlZCwgCiAgICAgICAgLy8gYWxsIHdlIGhhdmUgdG8gZG8gaGVyZSBpcyByZXR1cm4gdGhlIG5leHQgb3JkZXJpbmcgaW4gdGhlIGJ1ZmZlci4gIAogICAgICAgIGlmIChjdXJzb3ItPmV4cEluZGV4IDwgY3Vyc29yLT5idWZmZXJBbGlhcy0+c2l6ZSgpKQogICAgICAgIHsKICAgICAgICAgICAgLy9fTCgoc3RkZXJyLCAibmV4dCBmcm9tIFslMDhYXSBmcm9tIGJ1ZmZlckFsaWFzXG4iLCB0aGlzKSk7CiAgICAgICAgICAgIHJldHVybiBzdHJlbmd0aE9yZGVyKGN1cnNvci0+YnVmZmVyQWxpYXMtPmF0KGN1cnNvci0+ZXhwSW5kZXgrKykpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBjdXJzb3ItPmJ1ZmZlckFsaWFzID0gTlVMTDsKICAgICAgICB9CiAgICB9CgogICAgVUNoYXIgY2ggPSBjdXJzb3ItPmN1cnJlbnQoKTsKICAgIGN1cnNvci0+bmV4dCgpOwoKICAgIC8vX0woKHN0ZGVyciwgIk5leHQgZnJvbSBbJTA4WF0gPSBbJTA0WF0sIFslY11cbiIsIGN1cnNvciwgKGludCljaCAmIDB4RkZGRiwgKGNoYXIpKGNoICYgMHhGRikpKTsKICAgIAogICAgaWYgKGNoID09IE5vcm1hbGl6ZXI6OkRPTkUpIHsKICAgICAgICByZXR1cm4gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpOVUxMT1JERVI7CiAgICB9CiAgICAvLyBBc2sgdGhlIGNvbGxhdG9yIGZvciB0aGlzIGNoYXJhY3RlcidzIG9yZGVyaW5nLgogICAgaW50MzJfdCB2YWx1ZSA9IHVjbXAzMl9nZXQoZGF0YS0+bWFwcGluZywgY2gpOwoKICAgIGlmICh2YWx1ZSA9PSBVTk1BUFBFRCkKICAgIHsKICAgICAgICAvLyBSZXR1cm5lZCBhbiAidW5tYXBwZWQiIGZsYWcgYW5kIHNhdmUgdGhlIGNoYXJhY3RlciBzbyBpdCBjYW4gYmUgCiAgICAgICAgLy8gcmV0dXJuZWQgbmV4dCB0aW1lIHRoaXMgbWV0aG9kIGlzIGNhbGxlZC4KICAgICAgICBpZiAoY2ggPT0gMHgwMDAwKSByZXR1cm4gY2g7IC8vIFx1MDAwMCBpcyBub3QgdmFsaWQgaW4gQysrJ3MgVW5pY29kZVN0cmluZwogICAgICAgIGN1cnNvci0+b3duQnVmZmVyLmF0KDApID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpVTk1BUFBFRENIQVJWQUxVRTsKICAgICAgICBjdXJzb3ItPm93bkJ1ZmZlci5hdCgxKSA9IGNoIDw8IDE2OwogICAgICAgIGN1cnNvci0+YnVmZmVyQWxpYXMgPSAmY3Vyc29yLT5vd25CdWZmZXI7CgogICAgfSBlbHNlIHsKICAgICAgICAKICAgICAgICBpZiAodmFsdWUgPj0gQ09OVFJBQ1RDSEFSSU5ERVgpCiAgICAgICAgewogICAgICAgICAgICB2YWx1ZSA9IG5leHRDb250cmFjdENoYXIoY3Vyc29yLCBjaCwgc3RhdHVzKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgaWYgKHZhbHVlID49IEVYUEFORENIQVJJTkRFWCkgewogICAgICAgICAgICBjdXJzb3ItPmJ1ZmZlckFsaWFzID0gZ2V0RXhwYW5kVmFsdWVMaXN0KHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgaWYgKENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6aXNUaGFpUHJlVm93ZWwoY2gpKSB7CiAgICAgICAgICAgIFVDaGFyIGNvbnNvbmFudCA9IGN1cnNvci0+Y3VycmVudCgpOwogICAgICAgICAgICBpZiAoQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjppc1RoYWlCYXNlQ29uc29uYW50KGNvbnNvbmFudCkpIHsKICAgICAgICAgICAgICAgIGN1cnNvci0+bmV4dCgpOwogICAgICAgICAgICAgICAgY3Vyc29yLT5idWZmZXJBbGlhcyA9IG1ha2VSZW9yZGVyZWRCdWZmZXIoY3Vyc29yLCBjb25zb25hbnQsIHZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3Vyc29yLT5idWZmZXJBbGlhcyk7ICAgICAgICAgICAgICAgIAogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGlmIChjdXJzb3ItPmJ1ZmZlckFsaWFzICE9IE5VTEwpIHsKICAgICAgICBjdXJzb3ItPmV4cEluZGV4ID0gMTsKICAgICAgICB2YWx1ZSA9IGN1cnNvci0+YnVmZmVyQWxpYXMtPmF0KDApOwogICAgfQoKICAgIHJldHVybiBzdHJlbmd0aE9yZGVyKHZhbHVlKTsKfQoKLy8gPT09PT09PT09PT09PT09PT09PT0gRW5kIGlubGluZXMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KClJ1bGVCYXNlZENvbGxhdG9yOjpSdWxlQmFzZWRDb2xsYXRvcigpCiAgICA6IENvbGxhdG9yKCksCiAgICAgIGlzT3Zlcklnbm9yZShGQUxTRSksCiAgICAgIG1QYXR0ZXJuKDApLAogICAgICAvLyAgICAgIHNvdXJjZUN1cnNvcigwKSwKICAgICAgLy90YXJnZXRDdXJzb3IoMCksCiAgICAgIGN1cnNvcjEoMCksCiAgICAgIGN1cnNvcjIoMCksCiAgICAgIGRhdGFJc093bmVkKEZBTFNFKSwKICAgICAgZGF0YSgwKQp7Cn0KClJ1bGVCYXNlZENvbGxhdG9yOjpSdWxlQmFzZWRDb2xsYXRvcihjb25zdCAgUnVsZUJhc2VkQ29sbGF0b3ImICB0aGF0KQogICAgOiBDb2xsYXRvcih0aGF0KSwKICAgICAgaXNPdmVySWdub3JlKHRoYXQuaXNPdmVySWdub3JlKSwKICAgICAgbVBhdHRlcm4oMCksCiAgICAgIC8vICAgICAgc291cmNlQ3Vyc29yKDApLAogICAgICAvL3RhcmdldEN1cnNvcigwKSwKICAgICAgY3Vyc29yMSgwKSwKICAgICAgY3Vyc29yMigwKSwKICAgICAgZGF0YUlzT3duZWQoRkFMU0UpLAogICAgICBkYXRhKHRoYXQuZGF0YSkgLy8gQWxpYXMgdGhlIGRhdGEgcG9pbnRlcgp7Cn0KClVCb29sClJ1bGVCYXNlZENvbGxhdG9yOjpvcGVyYXRvcj09KGNvbnN0IENvbGxhdG9yJiB0aGF0KSBjb25zdAp7CiAgICBpZiAodGhpcyA9PSAmdGhhdCkKICAgIHsKICAgICAgICByZXR1cm4gVFJVRTsKICAgIH0KCiAgICBpZiAodGhpcy0+Z2V0RHluYW1pY0NsYXNzSUQoKSAhPSB0aGF0LmdldER5bmFtaWNDbGFzc0lEKCkpCiAgICB7CiAgICAgICAgcmV0dXJuIEZBTFNFOyAgLy8gbm90IHRoZSBzYW1lIGNsYXNzCiAgICB9CgogICAgaWYgKCFDb2xsYXRvcjo6b3BlcmF0b3I9PSh0aGF0KSkKICAgIHsKICAgICAgICByZXR1cm4gRkFMU0U7CiAgICB9CgogICAgUnVsZUJhc2VkQ29sbGF0b3ImIHRoYXRBbGlhcyA9IChSdWxlQmFzZWRDb2xsYXRvciYpdGhhdDsKCiAgICBpZiAoaXNPdmVySWdub3JlICE9IHRoYXRBbGlhcy5pc092ZXJJZ25vcmUpCiAgICB7CiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQoKICAgIGlmIChkYXRhICE9IHRoYXRBbGlhcy5kYXRhKQogICAgewogICAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KCiAgICByZXR1cm4gVFJVRTsKfQoKUnVsZUJhc2VkQ29sbGF0b3ImClJ1bGVCYXNlZENvbGxhdG9yOjpvcGVyYXRvcj0oY29uc3QgIFJ1bGVCYXNlZENvbGxhdG9yJiB0aGF0KQp7CiAgICBpZiAodGhpcyAhPSAmdGhhdCkKICAgIHsKICAgICAgICBDb2xsYXRvcjo6b3BlcmF0b3I9KHRoYXQpOwogICAgICAgIGlzT3Zlcklnbm9yZSA9IHRoYXQuaXNPdmVySWdub3JlOwoKICAgICAgICBpZiAoZGF0YUlzT3duZWQpCiAgICAgICAgewogICAgICAgICAgICBkZWxldGUgZGF0YTsKICAgICAgICB9CgogICAgICAgIGRhdGEgPSAwOwogICAgICAgIGRlbGV0ZSBtUGF0dGVybjsKICAgICAgICBtUGF0dGVybiA9IDA7CiAgICAgICAgZGF0YUlzT3duZWQgPSBGQUxTRTsKICAgICAgICBkYXRhID0gdGhhdC5kYXRhOwogICAgfQoKICAgIHJldHVybiAqdGhpczsKfQoKUnVsZUJhc2VkQ29sbGF0b3I6OlJ1bGVCYXNlZENvbGxhdG9yKGNvbnN0ICBVbmljb2RlU3RyaW5nJiAgcnVsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiAgICAgIHN0YXR1cykKICAgIDogQ29sbGF0b3IoKSwKICAgICAgaXNPdmVySWdub3JlKEZBTFNFKSwKICAgICAgbVBhdHRlcm4oMCksCiAgICAgIC8vICAgICAgc291cmNlQ3Vyc29yKDApLAogICAgICAvLy8gICAgICB0YXJnZXRDdXJzb3IoMCksCiAgICAgIGN1cnNvcjEoMCksCiAgICAgIGN1cnNvcjIoMCksCiAgICAgIGRhdGFJc093bmVkKEZBTFNFKSwKICAgICAgZGF0YSgwKQp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGNvbnN0cnVjdEZyb21SdWxlcyhydWxlcywgc3RhdHVzKTsKfQoKUnVsZUJhc2VkQ29sbGF0b3I6OlJ1bGVCYXNlZENvbGxhdG9yKGNvbnN0ICBVbmljb2RlU3RyaW5nJiAgcnVsZXMsCiAgICAgICAgICAgICAgICAgICAgIEVDb2xsYXRpb25TdHJlbmd0aCBjb2xsYXRpb25TdHJlbmd0aCwKICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpCiAgOiBDb2xsYXRvcihjb2xsYXRpb25TdHJlbmd0aCwgTm9ybWFsaXplcjo6Tk9fT1ApLAogICAgaXNPdmVySWdub3JlKEZBTFNFKSwKICAgIG1QYXR0ZXJuKDApLAogICAgLy8gICAgc291cmNlQ3Vyc29yKDApLAogICAgLy8gICAgdGFyZ2V0Q3Vyc29yKDApLAogICAgY3Vyc29yMSgwKSwKICAgIGN1cnNvcjIoMCksCiAgICBkYXRhSXNPd25lZChGQUxTRSksCiAgICBkYXRhKDApCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdHJ1Y3RGcm9tUnVsZXMocnVsZXMsIHN0YXR1cyk7Cn0KClJ1bGVCYXNlZENvbGxhdG9yOjpSdWxlQmFzZWRDb2xsYXRvcihjb25zdCAgVW5pY29kZVN0cmluZyYgIHJ1bGVzLAogICAgICAgICAgICAgICAgICAgICBOb3JtYWxpemVyOjpFTW9kZSBkZWNvbXBvc2l0aW9uTW9kZSwKICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpCiAgOiBDb2xsYXRvcihURVJUSUFSWSwgZGVjb21wb3NpdGlvbk1vZGUpLAogICAgaXNPdmVySWdub3JlKEZBTFNFKSwKICAgIG1QYXR0ZXJuKDApLAogICAgLy8gICAgc291cmNlQ3Vyc29yKDApLAogICAgLy8gICAgdGFyZ2V0Q3Vyc29yKDApLAogICAgY3Vyc29yMSgwKSwKICAgIGN1cnNvcjIoMCksCiAgICBkYXRhSXNPd25lZChGQUxTRSksCiAgICBkYXRhKDApCnsKICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgIHJldHVybjsKICAgIH0KICAKICBjb25zdHJ1Y3RGcm9tUnVsZXMocnVsZXMsIHN0YXR1cyk7Cn0KClJ1bGVCYXNlZENvbGxhdG9yOjpSdWxlQmFzZWRDb2xsYXRvcihjb25zdCAgVW5pY29kZVN0cmluZyYgIHJ1bGVzLAogICAgICAgICAgICAgICAgICAgICBFQ29sbGF0aW9uU3RyZW5ndGggY29sbGF0aW9uU3RyZW5ndGgsCiAgICAgICAgICAgICAgICAgICAgIE5vcm1hbGl6ZXI6OkVNb2RlIGRlY29tcG9zaXRpb25Nb2RlLAogICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiAgICAgIHN0YXR1cykKICA6IENvbGxhdG9yKGNvbGxhdGlvblN0cmVuZ3RoLCBkZWNvbXBvc2l0aW9uTW9kZSksCiAgICAgIGlzT3Zlcklnbm9yZShGQUxTRSksCiAgICAgIG1QYXR0ZXJuKDApLAogICAgLy8gICAgICBzb3VyY2VDdXJzb3IoMCksCiAgICAvL3RhcmdldEN1cnNvcigwKSwKICAgICAgY3Vyc29yMSgwKSwKICAgICAgY3Vyc29yMigwKSwKICAgICAgZGF0YUlzT3duZWQoRkFMU0UpLAogICAgICBkYXRhKDApCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgY29uc3RydWN0RnJvbVJ1bGVzKHJ1bGVzLCBzdGF0dXMpOwp9Cgp2b2lkIFJ1bGVCYXNlZENvbGxhdG9yOjpjb25zdHJ1Y3RGcm9tUnVsZXMoY29uc3QgVW5pY29kZVN0cmluZyYgcnVsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIC8vIENvbnN0cnVjdCB0aGlzIGNvbGxhdG9yJ3MgcnVsZXNldCBmcm9tIGl0cyBzdHJpbmcgcmVwcmVzZW50YXRpb24KICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHJ1bGVzLmlzQm9ndXMoKSkKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoZGF0YUlzT3duZWQpCiAgICB7CiAgICAgICAgZGVsZXRlIGRhdGE7CiAgICAgICAgZGF0YSA9IDA7CiAgICB9CgogICAgaXNPdmVySWdub3JlID0gRkFMU0U7CiAgICBzZXRTdHJlbmd0aChDb2xsYXRvcjo6VEVSVElBUlkpOwoKICAgIGRhdGEgPSBuZXcgVGFibGVDb2xsYXRpb25EYXRhOwogICAgaWYgKGRhdGEtPmlzQm9ndXMoKSkKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgIGRlbGV0ZSBkYXRhOwogICAgICAgIGRhdGEgPSAwOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBXZSBjb25zdHJ1Y3RlZCB0aGUgZGF0YSB1c2luZyB0aGUgYnVpbGQgbWV0aG9kLCBzbyB3ZSBvd24gaXQuCiAgICBkYXRhSXNPd25lZCA9IFRSVUU7CgogICAgLy8gTm93IHRoYXQgd2UndmUgZ290IGFsbCB0aGUgYnVmZmVycyBhbGxvY2F0ZWQsIGRvIHRoZSBhY3R1YWwgd29yawogICAgbVBhdHRlcm4gPSAwOwogICAgYnVpbGQocnVsZXMsIHN0YXR1cyk7Cn0KCnZvaWQKUnVsZUJhc2VkQ29sbGF0b3I6OmNvbnN0cnVjdEZyb21GaWxlKGNvbnN0IGNoYXIqIGZpbGVOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICAvLyBUaGlzIG1ldGhvZCB0cmllcyB0byByZWFkIGluIGEgZmxhdHRlbmVkIFJ1bGVCYXNlZENvbGxhdG9yIHRoYXQKICAgIC8vIGhhcyBiZWVuIHByZXZpb3VzbHkgc3RyZWFtZWQgb3V0IHVzaW5nIHRoZSBzdHJlYW1PdXQoKSBtZXRob2QuCiAgICAvLyBUaGUgJ2ZpbGVOYW1lJyBwYXJhbWV0ZXIgc2hvdWxkIGNvbnRhaW4gYSBmdWxsIHBhdGhuYW1lIHZhbGlkIG9uCiAgICAvLyB0aGUgbG9jYWwgZW52aXJvbm1lbnQuCgogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoZGF0YUlzT3duZWQpCiAgICB7CiAgICAgICAgZGVsZXRlIGRhdGE7CiAgICAgICAgZGF0YSA9IDA7CiAgICB9CgogICAgbVBhdHRlcm4gPSAwOwogICAgaXNPdmVySWdub3JlID0gRkFMU0U7CiAgICBzZXRTdHJlbmd0aChDb2xsYXRvcjo6VEVSVElBUlkpOyAvLyBUaGlzIGlzIHRoZSBkZWZhdWx0IHN0cmVuZ3RoCgogICAgRmlsZVN0cmVhbSogaWZzID0gVF9GaWxlU3RyZWFtX29wZW4oZmlsZU5hbWUsICJyYiIpOwogICAgaWYgKGlmcyA9PSAwKSB7CiAgICAgICAgc3RhdHVzID0gVV9GSUxFX0FDQ0VTU19FUlJPUjsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgLy8gVGhlIHN0cmVhbUluIGZ1bmN0aW9uIGRvZXMgdGhlIGFjdHVhbCB3b3JrIGhlcmUuLi4KICAgIFJ1bGVCYXNlZENvbGxhdG9yU3RyZWFtZXI6OnN0cmVhbUluKHRoaXMsIGlmcyk7CgogICAgaWYgKCFUX0ZpbGVTdHJlYW1fZXJyb3IoaWZzKSkKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX1pFUk9fRVJST1I7CiAgICB9CiAgICBlbHNlIGlmIChkYXRhICYmIGRhdGEtPmlzQm9ndXMoKSkKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgIGRlbGV0ZSBkYXRhOwogICAgICAgIGRhdGEgPSAwOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIHN0YXR1cyA9IFVfTUlTU0lOR19SRVNPVVJDRV9FUlJPUjsKICAgICAgICBkZWxldGUgZGF0YTsKICAgICAgICBkYXRhID0gMDsKICAgIH0KCiNpZmRlZiBDT0xMREVCVUcKICAgIGZwcmludGYoc3RkZXJyLCAiYmluYXJ5IHJlYWQgJXMgc2l6ZSAlZCwgJXNcbiIsIGZpbGVOYW1lLCBUX0ZpbGVTdHJlYW1fc2l6ZShpZnMpLCB1X2Vycm9yTmFtZShzdGF0dXMpKTsKI2VuZGlmCgogICAgLy8gV2UgY29uc3RydWN0ZWQgdGhlIGRhdGEgd2hlbiBzdHJlYW1pbmcgaXQgaW4sIHNvIHdlIG93biBpdAogICAgZGF0YUlzT3duZWQgPSBUUlVFOwoKICAgIFRfRmlsZVN0cmVhbV9jbG9zZShpZnMpOwp9Cgpjb25zdCBjaGFyICoKUnVsZUJhc2VkQ29sbGF0b3I6OmNvbnN0cnVjdEZyb21CdW5kbGUoY29uc3QgTG9jYWxlICYgbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKewogIC8vIFRoaXMgbWV0aG9kIHRyaWVzIHRvIGxvY2F0ZSBiaW5hcnkgY29sbGF0aW9uIGRhdGEgd2hpY2ggaGFzIGJlZW4gCiAgLy8gcHJldmlvdXNseSBzdHJlYW1lZCB0byBhIGJpbmFyeSBvYmplY3QgIiUlQ29sbGF0aW9uIiBpbiBhIAogIC8vIHJlc291cmNlIGJ1bmRsZS4gSWYgdGhlIGRhdGEgaXMgZm91bmQsIGl0IGlzIGNhY2hlZC4KICAvLyBjYWNoZSBpcyBjaGVja2VkIGJlZm9yZSBhY3R1YWxseSBzdHJlYW1pbmcgaW4gZGF0YQogIC8vIHJlc291cmNlIGJ1bmRsZSBmYWxsYmFjayBtZWNoYW5pc20gaXMgdXNlZC4KCiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgaWYgKGRhdGFJc093bmVkKQogICAgewogICAgICAgIGRlbGV0ZSBkYXRhOwogICAgICAgIGRhdGEgPSAwOwogICAgfQogICAgY29uc3QgY2hhciogcmVhbE5hbWUgPSAwOwoKICAgIG1QYXR0ZXJuID0gMDsKICAgIGlzT3Zlcklnbm9yZSA9IEZBTFNFOwogICAgc2V0U3RyZW5ndGgoQ29sbGF0b3I6OlRFUlRJQVJZKTsgLy8gVGhpcyBpcyB0aGUgZGVmYXVsdCBzdHJlbmd0aAoKICAgIFJlc291cmNlQnVuZGxlIHJiKChjaGFyICopMCwgbmFtZSwgc3RhdHVzKTsKICAgIGlmKFVfU1VDQ0VTUyhzdGF0dXMpKSB7CiAgICAgIFJlc291cmNlQnVuZGxlIGJpbmFyeSA9IHJiLmdldCgiJSVDb2xsYXRpb24iLCBzdGF0dXMpOyAvL1RoaXMgaXMgdGhlIGJ1bmRsZSB0aGF0IGFjdHVhbGx5IGNvbnRhaW5zIHRoZSBjb2xsYXRpb24gZGF0YQogICAgICByZWFsTmFtZSA9IGJpbmFyeS5nZXROYW1lKCk7CiAgICAgIGlmKFVfU1VDQ0VTUyhzdGF0dXMpKSB7CiAgICAgICAgVUVycm9yQ29kZSBpbnRTdGF0dXMgPSBVX1pFUk9fRVJST1I7CiAgICAgICAgY29uc3RydWN0RnJvbUNhY2hlKHJlYWxOYW1lLCBpbnRTdGF0dXMpOyAvLyBjaGVjayB3aGV0aGVyIHdlIGFscmVhZHkgaGF2ZSB0aGlzIGRhdGEgaW4gY2FjaGUKICAgICAgICBpZihVX1NVQ0NFU1MoaW50U3RhdHVzKSkgewogICAgICAgICAgcmV0dXJuIHJlYWxOYW1lOwogICAgICAgIH0KICAgICAgICBpbnQzMl90IGluRGF0YUxlbiA9IDA7CiAgICAgICAgY29uc3QgdWludDhfdCAqaW5EYXRhID0gYmluYXJ5LmdldEJpbmFyeShpbkRhdGFMZW4sIHN0YXR1cyk7IC8vVGhpcyBnb3QgdXMgdGhlIHJlYWwgYmluYXJ5IGRhdGEKCiAgICAgICAgVU1lbW9yeVN0cmVhbSAqaWZzID0gdXBydl9tc3RybV9vcGVuQnVmZmVyKGluRGF0YSwgaW5EYXRhTGVuKTsKCiAgICAgICAgaWYgKGlmcyA9PSAwKSB7CiAgICAgICAgICBzdGF0dXMgPSBVX0ZJTEVfQUNDRVNTX0VSUk9SOwogICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQoKICAgICAgICAvLyBUaGUgc3RyZWFtSW4gZnVuY3Rpb24gZG9lcyB0aGUgYWN0dWFsIHdvcmsgaGVyZS4uLgogICAgICAgIFJ1bGVCYXNlZENvbGxhdG9yU3RyZWFtZXI6OnN0cmVhbUluKHRoaXMsIGlmcyk7CgogICAgICAgIGlmICghdXBydl9tc3RybV9lcnJvcihpZnMpKSB7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKGRhdGEgJiYgZGF0YS0+aXNCb2d1cygpKSB7CiAgICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgICAgZGVsZXRlIGRhdGE7CiAgICAgICAgICBkYXRhID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3RhdHVzID0gVV9NSVNTSU5HX1JFU09VUkNFX0VSUk9SOwogICAgICAgICAgZGVsZXRlIGRhdGE7CiAgICAgICAgICBkYXRhID0gMDsKICAgICAgICB9CgogICAgICAgIC8vIFdlIGNvbnN0cnVjdGVkIHRoZSBkYXRhIHdoZW4gc3RyZWFtaW5nIGl0IGluLCBzbyB3ZSBvd24gaXQKICAgICAgICBkYXRhSXNPd25lZCA9IFRSVUU7CgogICAgICAgIHVwcnZfbXN0cm1fY2xvc2UoaWZzKTsKICAgICAgICBhZGRUb0NhY2hlKHJlYWxOYW1lKTsgLy8gYWRkIHRoZSBuZXdseSBjb25zdHJ1Y3RlZCBkYXRhIHRvIGNhY2hlCiAgICAgICAgcmV0dXJuIHJlYWxOYW1lOwogICAgICB9IGVsc2UgewogICAgICAgIHN0YXR1cyA9IFVfTUlTU0lOR19SRVNPVVJDRV9FUlJPUjsKICAgICAgICByZXR1cm4gMDsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gMDsKICAgIH0KfQoKUnVsZUJhc2VkQ29sbGF0b3I6OlJ1bGVCYXNlZENvbGxhdG9yKCAgIGNvbnN0IExvY2FsZSYgZGVzaXJlZExvY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCiAgICA6IENvbGxhdG9yKCksCiAgICAgIGlzT3Zlcklnbm9yZShGQUxTRSksCiAgICAgIC8vICAgICAgc291cmNlQ3Vyc29yKDApLAogICAgICAvL3RhcmdldEN1cnNvcigwKSwKICAgICAgY3Vyc29yMSgwKSwKICAgICAgY3Vyc29yMigwKSwKICAgICAgbVBhdHRlcm4oMCksCiAgICAgIGRhdGFJc093bmVkKEZBTFNFKSwKICAgICAgZGF0YSgwKQp7CgoKICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpIHsKICAgIHJldHVybjsKICB9CiAgCiAgLy8gVHJ5IHRvIGxvYWQsIGluIG9yZGVyOgogIC8vIDEuIFRoZSBkZXNpcmVkIGxvY2FsZSdzIGNvbGxhdGlvbi4KICAvLyAyLiBBIGZhbGxiYWNrIG9mIHRoZSBkZXNpcmVkIGxvY2FsZS4KICAvLyAzLiBUaGUgZGVmYXVsdCBsb2NhbGUncyBjb2xsYXRpb24uCiAgLy8gNC4gQSBmYWxsYmFjayBvZiB0aGUgZGVmYXVsdCBsb2NhbGUuCiAgLy8gNS4gVGhlIGRlZmF1bHQgY29sbGF0aW9uIHJ1bGVzLCB3aGljaCBjb250YWlucyBlbl9VUyBjb2xsYXRpb24gcnVsZXMuCgogIC8vIFRvIHJlaXRlcmF0ZSwgd2UgdHJ5OgogIC8vIFNwZWNpZmljOgogIC8vICBsYW5ndWFnZStjb3VudHJ5K3ZhcmlhbnQKICAvLyAgbGFuZ3VhZ2UrY291bnRyeQogIC8vICBsYW5ndWFnZQogIC8vIERlZmF1bHQ6CiAgLy8gIGxhbmd1YWdlK2NvdW50cnkrdmFyaWFudAogIC8vICBsYW5ndWFnZStjb3VudHJ5CiAgLy8gIGxhbmd1YWdlCiAgLy8gUm9vdDogKGFrYSBERUZBVUxUUlVMRVMpCiAgLy8gc3RlcHMgMS01IGFyZSBoYW5kbGVkIGJ5IHJlc291cmNlIGJ1bmRsZSBmYWxsYmFjayBtZWNoYW5pc20uIAogIC8vIGhvd2V2ZXIsIGluIGEgdmVyeSB1bnByb2JhYmxlIHNpdHVhdGlvbiB0aGF0IG5vIHJlc291cmNlIGJ1bmRsZQogIC8vIGRhdGEgZXhpc3RzLCBzdGVwIDUgaXMgcmVwZWF0ZWQgd2l0aCBoYXJkY29kZWQgZGVmYXVsdCBydWxlcy4KCiAgY29uc3QgY2hhciAqbG9jTmFtZSA9IGNvbnN0cnVjdEZyb21CdW5kbGUoZGVzaXJlZExvY2FsZSwgc3RhdHVzKTsgIC8qISovCiAgZGF0YS0+ZGVzaXJlZExvY2FsZSA9IGRlc2lyZWRMb2NhbGU7CiAgCiAgaWYgKFVfU1VDQ0VTUyhzdGF0dXMpKSB7CiAgICBkYXRhLT5yZWFsTG9jYWxlTmFtZSA9IGxvY05hbWU7CiAgICBpZihzdGF0dXMgIT0gVV9VU0lOR19ERUZBVUxUX0VSUk9SKSB7CiAgICAgIHNldERlY29tcG9zaXRpb24oTm9ybWFsaXplcjo6Tk9fT1ApOwogICAgfQogIH0gZWxzZSB7CiAgICBVRXJyb3JDb2RlIGludFN0YXR1cyA9IFVfWkVST19FUlJPUjsKICAgIGNvbnN0cnVjdEZyb21DYWNoZShSZXNvdXJjZUJ1bmRsZTo6a0RlZmF1bHRGaWxlbmFtZSwgaW50U3RhdHVzKTsKICAgIGlmKFVfRkFJTFVSRShpbnRTdGF0dXMpKSB7CiAgICAgIGludFN0YXR1cyA9IFVfWkVST19FUlJPUjsKICAgICAgY29uc3RydWN0RnJvbVJ1bGVzKFJ1bGVCYXNlZENvbGxhdG9yOjpERUZBVUxUUlVMRVMsIGludFN0YXR1cyk7CiAgICAgIGlmIChpbnRTdGF0dXMgPT0gVV9aRVJPX0VSUk9SKSB7CiAgICAgICAgc3RhdHVzID0gVV9VU0lOR19ERUZBVUxUX0VSUk9SOwogICAgICB9IGVsc2UgewogICAgICAgIHN0YXR1cyA9IGludFN0YXR1czsgICAgIC8vIGJ1YmJsZSBiYWNrCiAgICAgIH0KCiAgICAgIGlmIChzdGF0dXMgPT0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUikgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQogICAgZGF0YS0+cmVhbExvY2FsZU5hbWUgPSBSZXNvdXJjZUJ1bmRsZTo6a0RlZmF1bHRGaWxlbmFtZTsKICAgIHNldERlY29tcG9zaXRpb24oTm9ybWFsaXplcjo6Tk9fT1ApOwogICAgYWRkVG9DYWNoZShSZXNvdXJjZUJ1bmRsZTo6a0RlZmF1bHRGaWxlbmFtZSk7CiAgfQogIHJldHVybjsKfQoKdm9pZApSdWxlQmFzZWRDb2xsYXRvcjo6Y29uc3RydWN0RnJvbUZpbGUoICAgY29uc3QgTG9jYWxlJiAgICAgICAgICAgbG9jYWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBVbmljb2RlU3RyaW5nJiAgICBsb2NhbGVGaWxlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUJvb2wgICAgICAgICAgICAgICAgICB0cnlCaW5hcnlGaWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiAgICAgICAgICAgICAgc3RhdHVzKQp7CiAgLy8gY29uc3RydWN0RnJvbUZpbGUgY3JlYXRlcyBhIGNvbGxhdGlvbiBvYmplY3QgYnkgcmVhZGluZyBmcm9tIGEKICAvLyBmaWxlLiAgSXQgZG9lcyBub3QgZW1wbG95IHRoZSB1c3VhbCBGSUxFIHNlYXJjaCBtZWNoYW5pc20gd2l0aAogIC8vIGxvY2FsZXMsIGRlZmF1bHQgbG9jYWxlcywgYW5kIGJhc2UgbG9jYWxlcy4gIEluc3RlYWQsIGl0IHRyaWVzIHRvCiAgLy8gbG9vayBvbmx5IGluIGZpbGVzIHdpdGggdGhlIGdpdmVuIGxvY2FsRmlsZU5hbWUuICBJdCBkb2VzLAogIC8vIGhvd2V2ZXIsIGVtcGxveSB0aGUgTE9DQUxFIHNlYXJjaCBtZWNoYW5pc20uCiAgCiAgLy8gVGhpcyBtZXRob2QgbWFpbnRhaW5zIHRoZSBiaW5hcnkgY29sbGF0aW9uIGZpbGVzLiAgSWYgYSBjb2xsYXRpb24KICAvLyBpcyBub3QgcHJlc2VudCBpbiBiaW5hcnkgZm9ybSwgYnV0IGlzIHByZXNlbnQgaW4gdGV4dCBmb3JtIChpbiBhCiAgLy8gcmVzb3VyY2UgYnVuZGxlIGZpbGUpLCBpdCB3aWxsIGJlIGxvYWRlZCBpbiB0ZXh0IGZvcm0sIGFuZCB0aGVuCiAgLy8gd3JpdHRlbiB0byBkaXNrLgogIAogIC8vIElmIHRyeUJpbmFyeUZpbGUgaXMgdHJ1ZSwgdGhlbiB0cnkgdG8gbG9hZCBmcm9tIHRoZSBiaW5hcnkgZmlsZSBmaXJzdC4KCiAgaWYoVV9GQUlMVVJFKHN0YXR1cykpIHsKICAgIHJldHVybjsKICB9CiAgCiAgaWYoZGF0YUlzT3duZWQpIHsKICAgIGRlbGV0ZSBkYXRhOwogICAgZGF0YSA9IDA7CiAgfQoKICAgIGlmKHRyeUJpbmFyeUZpbGUpIHsKICAgICAgY2hhciAqYmluYXJ5RmlsZVBhdGggPSBjcmVhdGVQYXRoTmFtZShVbmljb2RlU3RyaW5nKHVfZ2V0RGF0YURpcmVjdG9yeSgpLCIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGVGaWxlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVbmljb2RlU3RyaW5nKGtGaWxlbmFtZVN1ZmZpeCwiIikpOwoKICAgICAgICAvLyBUcnkgdG8gbG9hZCB1cCB0aGUgY29sbGF0aW9uIGZyb20gYSBiaW5hcnkgZmlsZSBmaXJzdAogICAgICAgIGNvbnN0cnVjdEZyb21GaWxlKGJpbmFyeUZpbGVQYXRoLCBzdGF0dXMpOwogICAgICAgICNpZmRlZiBDT0xMREVCVUcKICAgICAgICAgICAgY2VyciA8PCBsb2NhbGVGaWxlTmFtZSAgPDwga0ZpbGVuYW1lU3VmZml4IDw8ICIgYmluYXJ5IGxvYWQgIiA8PCB1X2Vycm9yTmFtZShzdGF0dXMpIDw8IGVuZGw7CiAgICAgICAgI2VuZGlmCiAgICAgICAgaWYoVV9TVUNDRVNTKHN0YXR1cykgfHwgc3RhdHVzID09IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1IpIHsKICAgICAgICAgICAgZGVsZXRlIFtdIGJpbmFyeUZpbGVQYXRoOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGlmKHN0YXR1cyA9PSBVX0ZJTEVfQUNDRVNTX0VSUk9SKSB7CiAgICAgICAgICAgIHN0YXR1cyA9IFVfWkVST19FUlJPUjsKICAgICAgICB9CiAgICAgICAgZGVsZXRlIFtdIGJpbmFyeUZpbGVQYXRoOwogICAgfQoKICAvLyBOb3cgdHJ5IHRvIGxvYWQgaXQgdXAgZnJvbSBhIHJlc291cmNlIGJ1bmRsZSB0ZXh0IHNvdXJjZSBmaWxlCiAgVW5pY29kZVN0cmluZyBkYXRhRGlyID0gVW5pY29kZVN0cmluZyh1X2dldERhdGFEaXJlY3RvcnkoKSwiIik7CgogICAgY2hhciAqY2g7CiAgICBjaCA9IG5ldyBjaGFyW2xvY2FsZUZpbGVOYW1lLnNpemUoKSArIDFdOwogICAgY2hbbG9jYWxlRmlsZU5hbWUuZXh0cmFjdCgwLCAweDdmZmZmZmZmLCBjaCwgIiIpXSA9IDA7CiAgICBSZXNvdXJjZUJ1bmRsZSBidW5kbGUoZGF0YURpciwgY2gsIHN0YXR1cyk7CiAgCiAgICBkZWxldGUgW10gY2g7CiAgCiAgLy8gaWYgdGhlcmUgaXMgbm8gcmVzb3VyY2UgYnVuZGxlIGZpbGUgZm9yIHRoZSBnaXZlIGxvY2FsZSwgYnJlYWsgb3V0CiAgaWYoVV9GQUlMVVJFKHN0YXR1cykpCiAgewogICAgICByZXR1cm47CiAgfQoKICAgICNpZmRlZiBDT0xMREVCVUcKICAgICAgICBjZXJyIDw8IGxvY2FsZUZpbGVOYW1lIDw8ICIgYXNjaWkgbG9hZCAiIDw8IHVfZXJyb3JOYW1lKHN0YXR1cykgPDwgZW5kbDsKICAgICNlbmRpZgoKICAgIC8vIGNoZWNrIGFuZCBzZWUgaWYgdGhpcyByZXNvdXJjZSBidW5kbGUgY29udGFpbnMgY29sbGF0aW9uIGRhdGEKICAKICAgIFVuaWNvZGVTdHJpbmcgY29sU3RyaW5nOwogICAgVUVycm9yQ29kZSBpbnRTdGF0dXMgPSBVX1pFUk9fRVJST1I7CgogICAgUmVzb3VyY2VCdW5kbGUgY29sRWxlbXMgPSBidW5kbGUuZ2V0KCJDb2xsYXRpb25FbGVtZW50cyIsIGludFN0YXR1cyk7CiAgICBpZiAoVV9GQUlMVVJFKGludFN0YXR1cykpCiAgICB7CiAgICAgICAgc3RhdHVzID0gVV9NSVNTSU5HX1JFU09VUkNFX0VSUk9SOwogICAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbFN0cmluZyA9IGNvbEVsZW1zLmdldFN0cmluZ0V4KCJTZXF1ZW5jZSIsIGludFN0YXR1cyk7CgogICAgaWYoVV9GQUlMVVJFKGludFN0YXR1cykpIHsKICAgICAgICBzdGF0dXMgPSBVX01JU1NJTkdfUkVTT1VSQ0VfRVJST1I7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmKGNvbFN0cmluZy5pc0JvZ3VzKCkpIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgLy8gSGF2aW5nIGxvYWRlZCB0aGUgY29sbGF0aW9uIGZyb20gdGhlIHJlc291cmNlIGJ1bmRsZSB0ZXh0IGZpbGUsCiAgLy8gbm93IHJldHJpZXZlIHRoZSBDb2xsYXRpb25FbGVtZW50cyB0YWdnZWQgZGF0YSwgbWVyZ2VkIHdpdGggdGhlCiAgLy8gZGVmYXVsdCBydWxlcy4gIElmIHRoYXQgZmFpbHMsIHVzZSB0aGUgZGVmYXVsdCBydWxlcyBhbG9uZS4KCiAgY29sU3RyaW5nLmluc2VydCgwLCBERUZBVUxUUlVMRVMpOwogIGlmKGNvbFN0cmluZy5pc0JvZ3VzKCkpIHsKICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICByZXR1cm47CiAgfQogICAgCiAgY29uc3RydWN0RnJvbVJ1bGVzKGNvbFN0cmluZywgaW50U3RhdHVzKTsKICBpZihpbnRTdGF0dXMgPT0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUikgewogICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgIHJldHVybjsKICB9CiAgCiAgaWYoaW50U3RhdHVzICE9IFVfWkVST19FUlJPUikgIHsKICAgIHN0YXR1cyA9IFVfVVNJTkdfREVGQVVMVF9FUlJPUjsKICAgICAgCiAgICAvLyBwcmVkZWZpbmVkIHRhYmxlcyBzaG91bGQgY29udGFpbiBjb3JyZWN0IGdyYW1tYXIKICAgIGludFN0YXR1cyA9IFVfWkVST19FUlJPUjsKICAgIGNvbnN0cnVjdEZyb21SdWxlcyhERUZBVUxUUlVMRVMsIGludFN0YXR1cyk7CiAgICBpZihpbnRTdGF0dXMgIT0gVV9aRVJPX0VSUk9SKSB7CiAgICAgIHN0YXR1cyA9IGludFN0YXR1czsKICAgIH0KICB9IAogIAojaWZkZWYgQ09MTERFQlVHCiAgY2VyciA8PCBsb2NhbGVGaWxlTmFtZSA8PCAiIGFzY2lpIGxvYWQgIiA8PCAoVV9TVUNDRVNTKHN0YXR1cykgPyAiT0siIDogIkZhaWxlZCIpIDw8ICIgLSB0cnk9ICIgPDwgKHRyeUJpbmFyeUZpbGU/InRydWUiOiJmYWxzZSIpIDw8IGVuZGw7CiNlbmRpZgoKfQoKUnVsZUJhc2VkQ29sbGF0b3I6On5SdWxlQmFzZWRDb2xsYXRvcigpCnsKICAgIGlmIChkYXRhSXNPd25lZCkKICAgIHsKICAgICAgICBkZWxldGUgZGF0YTsKICAgIH0KCiAgICBkYXRhID0gMDsKCiAgICAvLyAgICBkZWxldGUgc291cmNlQ3Vyc29yOwogICAgLy8gICAgc291cmNlQ3Vyc29yID0gMDsKCiAgICAvLyAgICBkZWxldGUgdGFyZ2V0Q3Vyc29yOwogICAgLy8gICAgdGFyZ2V0Q3Vyc29yID0gMDsKCiAgICBpZiAoY3Vyc29yMSAhPSBOVUxMKSB7CiAgICAgICAgZGVsZXRlIGN1cnNvcjE7CiAgICAgICAgY3Vyc29yMSA9IDA7CiAgICB9CiAgICBpZiAoY3Vyc29yMiAhPSBOVUxMKSB7CiAgICAgICAgZGVsZXRlIGN1cnNvcjI7CiAgICAgICAgY3Vyc29yMiA9IDA7CiAgICB9CgogICAgZGVsZXRlIG1QYXR0ZXJuOwogICAgbVBhdHRlcm4gPSAwOwp9CgpDb2xsYXRvcioKUnVsZUJhc2VkQ29sbGF0b3I6OmNsb25lKCkgY29uc3QKewogICAgcmV0dXJuIG5ldyBSdWxlQmFzZWRDb2xsYXRvcigqdGhpcyk7Cn0KCi8vIENyZWF0ZSBhIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBvYmplY3QgdGhhdCB3aWxsIGl0ZXJhdG9yIG92ZXIgdGhlIGVsZW1lbnRzCi8vIGluIGEgc3RyaW5nLCB1c2luZyB0aGUgY29sbGF0aW9uIHJ1bGVzIGRlZmluZWQgaW4gdGhpcyBSdWxlQmFzZWRDb2xsYXRvcgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IqClJ1bGVCYXNlZENvbGxhdG9yOjpjcmVhdGVDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IoY29uc3QgVW5pY29kZVN0cmluZyYgc291cmNlKSBjb25zdAp7CiAgICBVRXJyb3JDb2RlIHN0YXR1cyA9IFVfWkVST19FUlJPUjsKICAgIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciAqbmV3Q3Vyc29yID0gMDsKCiAgICBuZXdDdXJzb3IgPSBuZXcgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKHNvdXJjZSwgdGhpcywgc3RhdHVzKTsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm4gTlVMTDsKICAgIH0KCiAgICByZXR1cm4gbmV3Q3Vyc29yOwp9CgovLyBDcmVhdGUgYSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3Igb2JqZWN0IHRoYXQgd2lsbCBpdGVyYXRvciBvdmVyIHRoZSBlbGVtZW50cwovLyBpbiBhIHN0cmluZywgdXNpbmcgdGhlIGNvbGxhdGlvbiBydWxlcyBkZWZpbmVkIGluIHRoaXMgUnVsZUJhc2VkQ29sbGF0b3IKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKgpSdWxlQmFzZWRDb2xsYXRvcjo6Y3JlYXRlQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKGNvbnN0IENoYXJhY3Rlckl0ZXJhdG9yJiBzb3VyY2UpIGNvbnN0CnsKICAgIFVFcnJvckNvZGUgc3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yICpuZXdDdXJzb3IgPSAwOwoKICAgIG5ld0N1cnNvciA9IG5ldyBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3Ioc291cmNlLCB0aGlzLCBzdGF0dXMpOwogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybiBOVUxMOwogICAgfQoKICAgIHJldHVybiBuZXdDdXJzb3I7Cn0KCi8vIFJldHVybiBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIGNvbGxhdG9yJ3MgcnVsZXMuCi8vIFRoZSBzdHJpbmcgY2FuIGxhdGVyIGJlIHBhc3NlZCB0byB0aGUgY29uc3RydWN0b3IgdGhhdCB0YWtlcyBhCi8vIFVuaWNvZGVTdHJpbmcgYXJndW1lbnQsIHdoaWNoIHdpbGwgY29uc3RydWN0IGEgY29sbGF0b3IgdGhhdCdzCi8vIGZ1bmN0aW9uYWxseSBpZGVudGljYWwgdG8gdGhpcyBvbmUuCi8vIFlvdSBjYW4gYWxzbyBhbGxvdyB1c2VycyB0byBlZGl0IHRoZSBzdHJpbmcgaW4gb3JkZXIgdG8gY2hhbmdlCi8vIHRoZSBjb2xsYXRpb24gZGF0YSwgb3IgeW91IGNhbiBwcmludCBpdCBvdXQgZm9yIGluc3BlY3Rpb24sIG9yIHdoYXRldmVyLgoKY29uc3QgVW5pY29kZVN0cmluZyYKUnVsZUJhc2VkQ29sbGF0b3I6OmdldFJ1bGVzKCkgY29uc3QKewogICAgaWYgKG1QYXR0ZXJuICE9IDApCiAgICB7CiAgICAgICAgTWVyZ2VDb2xsYXRpb24qJiBub25Db25zdE1QYXR0ZXJuID0gKihNZXJnZUNvbGxhdGlvbioqKSZtUGF0dGVybjsKICAgICAgICBtUGF0dGVybi0+ZW1pdFBhdHRlcm4oZGF0YS0+cnVsZVRhYmxlKTsKICAgICAgICBkYXRhLT5pc1J1bGVUYWJsZUxvYWRlZCA9IFRSVUU7CiAgICAgICAgZGVsZXRlIG5vbkNvbnN0TVBhdHRlcm47CiAgICAgICAgbm9uQ29uc3RNUGF0dGVybiA9IDA7CiAgICB9CiAgICBlbHNlIGlmICghZGF0YS0+aXNSdWxlVGFibGVMb2FkZWQpCiAgICB7CiAgICAgICAgLy8gQXQgdGhpcyBwb2ludCB0aGUgY2FsbGVyIHdhbnRzIHRoZSBydWxlcywgYnV0IHRoZSBydWxlIHRhYmxlIGRhdGEKICAgICAgICAvLyBpcyBub3QgbG9hZGVkLiAgRnVydGhlcm1vcmUsIHRoZXJlIGlzIG5vIG1QYXR0ZXJuIG9iamVjdCB0byBsb2FkCiAgICAgICAgLy8gdGhlIHJ1bGVzIGZyb20uICBUaGVyZWZvcmUsIHdlIGZldGNoIHRoZSBydWxlcyBvZmYgdGhlIGRpc2suCiAgICAgICAgLy8gTm90aWNlIHRoYXQgd2UgcGFzcyBpbiBhIHRyeUJpbmFyeUZpbGUgdmFsdWUgb2YgRkFMU0UsIHNpbmNlCiAgICAgICAgLy8gYnkgZGVzaWduIHRoZSBiaW5hcnkgZmlsZSBoYXMgTk8gcnVsZXMgaW4gaXQhCiAgICAgICAgLy9VRXJyb3JDb2RlIHN0YXR1cyA9IFVfWkVST19FUlJPUjsKICAgICAgICAvL1J1bGVCYXNlZENvbGxhdG9yIHRlbXAoZGF0YS0+cmVhbExvY2FsZU5hbWUsIHN0YXR1cyk7CiAgICAgICAgUnVsZUJhc2VkQ29sbGF0b3IgdGVtcDsKICAgICAgICBVRXJyb3JDb2RlIHN0YXR1cyA9IFVfWkVST19FUlJPUjsKICAgICAgICB0ZW1wLmNvbnN0cnVjdEZyb21GaWxlKGRhdGEtPmRlc2lyZWRMb2NhbGUsIGRhdGEtPnJlYWxMb2NhbGVOYW1lLCBGQUxTRSwgc3RhdHVzKTsKCiAgICAgICAgLy8gV2UgbXVzdCBjaGVjayB0aGF0IG1QYXR0ZXJuIGlzIG5vbnplcm8gaGVyZSwgb3Igd2UgcnVuIHRoZSByaXNrCiAgICAgICAgLy8gb2YgYW4gaW5maW5pdGUgbG9vcC4KICAgICAgICBpZiAoVV9TVUNDRVNTKHN0YXR1cykgJiYgdGVtcC5tUGF0dGVybiAhPSAwKQogICAgICAgIHsKICAgICAgICAgICAgZGF0YS0+cnVsZVRhYmxlID0gdGVtcC5nZXRSdWxlcygpOwogICAgICAgICAgICBkYXRhLT5pc1J1bGVUYWJsZUxvYWRlZCA9IFRSVUU7CiNpZmRlZiBfREVCVUcKLy8gICAgICAgICAgICAgIC8vIHRoZSBmb2xsb3dpbmcgaXMgdXNlZnVsIGZvciBzcGVjaWZpYyBkZWJ1Z2dpbmcgcHVycG9zZXMKLy8gICAgICAgICAgICAgICBVbmljb2RlU3RyaW5nIG5hbWU7Ci8vICAgICAgICAgICAgICAgY2VyciA8PCAiVGFibGUgY29sbGF0aW9uIHJ1bGVzIGxvYWRlZCBkeW5hbWljYWxseSBmb3IgIgovLyAgICAgICAgICAgICAgICAgICA8PCBkYXRhLT5kZXNpcmVkTG9jYWxlLmdldE5hbWUobmFtZSkKLy8gICAgICAgICAgICAgICAgICAgPDwgIiBhdCAiCi8vICAgICAgICAgICAgICAgICAgIDw8IGRhdGEtPnJlYWxMb2NhbGVOYW1lCi8vICAgICAgICAgICAgICAgICAgIDw8ICIsICIgPDwgZGVjIDw8IGRhdGEtPnJ1bGVUYWJsZS5zaXplKCkgPDwgIiBjaGFyYWN0ZXJzIgovLyAgICAgICAgICAgICAgICAgICA8PCBlbmRsOwojZW5kaWYKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKI2lmZGVmIF9ERUJVRwovLyAgICAgICAgICAgICAgVW5pY29kZVN0cmluZyBuYW1lOwovLyAgICAgICAgICAgICAgY2VyciA8PCAiVW5hYmxlIHRvIGxvYWQgdGFibGUgY29sbGF0aW9uIHJ1bGVzIGR5bmFtaWNhbGx5IGZvciAiCi8vICAgICAgICAgICAgICAgICAgPDwgZGF0YS0+ZGVzaXJlZExvY2FsZS5nZXROYW1lKG5hbWUpCi8vICAgICAgICAgICAgICAgICAgPDwgIiBhdCAiCi8vICAgICAgICAgICAgICAgICAgPDwgZGF0YS0+cmVhbExvY2FsZU5hbWUKLy8gICAgICAgICAgICAgICAgICA8PCBlbmRsOwovLyAgICAgICAgICAgICAgY2VyciA8PCAiU3RhdHVzICIgPDwgdV9lcnJvck5hbWUoc3RhdHVzKSA8PCAiLCBtUGF0dGVybiAiIDw8IHRlbXAubVBhdHRlcm4gPDwgZW5kbDsKI2VuZGlmCiAgICAgICAgICAgIC8qIFNSTCBoYXZlIHRvIGFkZCB0aGlzIGJlY2F1c2Ugd2Ugbm93IGhhdmUgdGhlIHNpdHVhdGlvbiB3aGVyZQogICAgICAgICAgICAgICBERUZBVUxUIGlzIGxvYWRlZCBmcm9tIGEgYmluYXJ5IGZpbGUgdy8gbm8gcnVsZXMuICovCiAgICAgICAgICAgIFVFcnJvckNvZGUgaW50U3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgICAgICAgICB0ZW1wLmNvbnN0cnVjdEZyb21SdWxlcyhSdWxlQmFzZWRDb2xsYXRvcjo6REVGQVVMVFJVTEVTLCBpbnRTdGF0dXMpOwoKICAgICAgICAgICAgaWYoVV9TVUNDRVNTKGludFN0YXR1cykgJiYgKHRlbXAubVBhdHRlcm4gIT0gMCkpCiAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZGF0YS0+cnVsZVRhYmxlID0gdGVtcC5nZXRSdWxlcygpOwogICAgICAgICAgICAgICAgZGF0YS0+aXNSdWxlVGFibGVMb2FkZWQgPSBUUlVFOwogICAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIGRhdGEtPnJ1bGVUYWJsZTsKfQoKCkNvbGxhdG9yOjpFQ29tcGFyaXNvblJlc3VsdApSdWxlQmFzZWRDb2xsYXRvcjo6Y29tcGFyZSggY29uc3QgVW5pY29kZVN0cmluZyYgc291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgVW5pY29kZVN0cmluZyYgdGFyZ2V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50MzJfdCBsZW5ndGgpIGNvbnN0CnsKICAgIFVuaWNvZGVTdHJpbmcgc291cmNlX3RvZ287CiAgICBVbmljb2RlU3RyaW5nIHRhcmdldF90b2dvOwogICAgVVRleHRPZmZzZXQgYmVnaW49MDsKCiAgICBzb3VyY2UuZXh0cmFjdChiZWdpbiwgdXBydl9taW4obGVuZ3RoLHNvdXJjZS5sZW5ndGgoKSksIHNvdXJjZV90b2dvKTsKICAgIHRhcmdldC5leHRyYWN0KGJlZ2luLCB1cHJ2X21pbihsZW5ndGgsdGFyZ2V0Lmxlbmd0aCgpKSwgdGFyZ2V0X3RvZ28pOwogICAgcmV0dXJuIChSdWxlQmFzZWRDb2xsYXRvcjo6Y29tcGFyZShzb3VyY2VfdG9nbywgdGFyZ2V0X3RvZ28pKTsKfQoKQ29sbGF0b3I6OkVDb21wYXJpc29uUmVzdWx0ICAgClJ1bGVCYXNlZENvbGxhdG9yOjpjb21wYXJlKGNvbnN0ICAgVUNoYXIqIHNvdXJjZSwgCiAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90IHNvdXJjZUxlbmd0aCwKICAgICAgICAgICAgICAgICAgICAgIGNvbnN0ICAgVUNoYXIqICB0YXJnZXQsCiAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90IHRhcmdldExlbmd0aCkgY29uc3QKewogICAgLy8gY2hlY2sgaWYgc291cmNlIGFuZCB0YXJnZXQgYXJlIHZhbGlkIHN0cmluZ3MKICAgIGlmICgoKHNvdXJjZSA9PSAwKSAmJiAodGFyZ2V0ID09IDApKSB8fAogICAgICAgICgoc291cmNlTGVuZ3RoID09IDApICYmICh0YXJnZXRMZW5ndGggPT0gMCkpKQogICAgewogICAgICAgIHJldHVybiBDb2xsYXRvcjo6RVFVQUw7CiAgICB9CgogICAgQ29sbGF0b3I6OkVDb21wYXJpc29uUmVzdWx0IHJlc3VsdCA9IENvbGxhdG9yOjpFUVVBTDsKICAgIFVFcnJvckNvZGUgc3RhdHVzID0gVV9aRVJPX0VSUk9SOwoKICAgIGlmIChjdXJzb3IxID09IE5VTEwpCiAgICB7CiAgICAgICAgKChSdWxlQmFzZWRDb2xsYXRvciAqKXRoaXMpLT5jdXJzb3IxID0gbmV3IE5vcm1hbGl6ZXJJdGVyYXRvcihzb3VyY2UsIHNvdXJjZUxlbmd0aCwgZ2V0RGVjb21wb3NpdGlvbigpKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBjdXJzb3IxLT5zZXRNb2RlQW5kVGV4dChnZXREZWNvbXBvc2l0aW9uKCksIHNvdXJjZSwgc291cmNlTGVuZ3RoLCBzdGF0dXMpOwogICAgfQoKICAgIGlmICggLypjdXJzb3IxLT5jdXJzb3IgPT0gTlVMTCB8fCovIFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybiBDb2xsYXRvcjo6RVFVQUw7CiAgICB9CgogICAgaWYgKGN1cnNvcjIgPT0gTlVMTCkKICAgIHsKICAgICAgICAoKFJ1bGVCYXNlZENvbGxhdG9yICopdGhpcyktPmN1cnNvcjIgPSBuZXcgTm9ybWFsaXplckl0ZXJhdG9yKHRhcmdldCwgdGFyZ2V0TGVuZ3RoLCBnZXREZWNvbXBvc2l0aW9uKCkpOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIGN1cnNvcjItPnNldE1vZGVBbmRUZXh0KGdldERlY29tcG9zaXRpb24oKSwgdGFyZ2V0LCB0YXJnZXRMZW5ndGgsIHN0YXR1cyk7CiAgICB9CgogICAgaWYgKC8qY3Vyc29yMiA9PSBOVUxMIHx8Ki8gVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIENvbGxhdG9yOjpFUVVBTDsKICAgIH0KCiAgICBpbnQzMl90IHNPcmRlciwgdE9yZGVyOwogICAgLy8gICAgaW50MzJfdCBzT3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUiwgdE9yZGVyID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpOVUxMT1JERVI7CiAgICBVQm9vbCBnZXRzID0gVFJVRSwgZ2V0dCA9IFRSVUU7CiAgICBVQm9vbCBpbml0aWFsQ2hlY2tTZWNUZXIgPSBnZXRTdHJlbmd0aCgpID49IENvbGxhdG9yOjpTRUNPTkRBUlk7CiAgICBVQm9vbCBjaGVja1NlY1RlciA9IGluaXRpYWxDaGVja1NlY1RlcjsKICAgIFVCb29sIGNoZWNrVGVydGlhcnkgPSBnZXRTdHJlbmd0aCgpID49IENvbGxhdG9yOjpURVJUSUFSWTsKICAgIFVCb29sIGlzRnJlbmNoU2VjID0gZGF0YS0+aXNGcmVuY2hTZWM7CiAgICB1aW50MzJfdCBwU09yZGVyLCBwVE9yZGVyOwoKICAgIGZvcig7OykKICAgIHsKICAgICAgICAvLyBHZXQgdGhlIG5leHQgY29sbGF0aW9uIGVsZW1lbnQgaW4gZWFjaCBvZiB0aGUgc3RyaW5ncywgdW5sZXNzCiAgICAgICAgLy8gd2UndmUgYmVlbiByZXF1ZXN0ZWQgdG8gc2tpcCBpdC4KICAgICAgICBpZiAoZ2V0cykKICAgICAgICB7CiAgICAgICAgICAgIHNPcmRlciA9IGdldFN0cmVuZ3RoT3JkZXIoKE5vcm1hbGl6ZXJJdGVyYXRvciopY3Vyc29yMSwgc3RhdHVzKTsKCiAgICAgICAgICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0dXJuIENvbGxhdG9yOjpFUVVBTDsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZ2V0cyA9IFRSVUU7CgogICAgICAgIGlmIChnZXR0KQogICAgICAgIHsKICAgICAgICAgICAgdE9yZGVyID0gZ2V0U3RyZW5ndGhPcmRlcigoTm9ybWFsaXplckl0ZXJhdG9yKiljdXJzb3IyLCBzdGF0dXMpOwoKICAgICAgICAgICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkVRVUFMOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGdldHQgPSBUUlVFOwoKICAgICAgICAvLyBJZiB3ZSd2ZSBoaXQgdGhlIGVuZCBvZiBvbmUgb2YgdGhlIHN0cmluZ3MsIGp1bXAgb3V0IG9mIHRoZSBsb29wCiAgICAgICAgaWYgKChzT3JkZXIgPT0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpOVUxMT1JERVIpfHwKICAgICAgICAgICAgKHRPcmRlciA9PSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUikpCiAgICAgICAgewogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIC8vIElmIHRoZXJlJ3Mgbm8gZGlmZmVyZW5jZSBhdCB0aGlzIHBvc2l0aW9uLCB3ZSBjYW4gc2tpcCB0byB0aGUKICAgICAgICAvLyBuZXh0IG9uZS4KICAgICAgICBwU09yZGVyID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmltYXJ5T3JkZXIoc09yZGVyKTsKICAgICAgICBwVE9yZGVyID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmltYXJ5T3JkZXIodE9yZGVyKTsKICAgICAgICBpZiAoc09yZGVyID09IHRPcmRlcikKICAgICAgICB7CiAgICAgICAgICAgIGlmIChpc0ZyZW5jaFNlYyAmJiBwU09yZGVyICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGlmICghY2hlY2tTZWNUZXIpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gaW4gZnJlbmNoLCBhIHNlY29uZGFyeSBkaWZmZXJlbmNlIG1vcmUgdG8gdGhlIHJpZ2h0IGlzIHN0cm9uZ2VyLAogICAgICAgICAgICAgICAgICAgIC8vIHNvIGFjY2VudHMgaGF2ZSB0byBiZSBjaGVja2VkIHdpdGggZWFjaCBiYXNlIGVsZW1lbnQKICAgICAgICAgICAgICAgICAgICBjaGVja1NlY1RlciA9IGluaXRpYWxDaGVja1NlY1RlcjsKCiAgICAgICAgICAgICAgICAgICAgLy8gYnV0IHRlcnRpYXJ5IGRpZmZlcmVuY2VzIGFyZSBsZXNzIGltcG9ydGFudCB0aGFuIHRoZSBmaXJzdCAKICAgICAgICAgICAgICAgICAgICAvLyBzZWNvbmRhcnkgZGlmZmVyZW5jZSwgc28gY2hlY2tpbmcgdGVydGlhcnkgcmVtYWlucyBkaXNhYmxlZAogICAgICAgICAgICAgICAgICAgIGNoZWNrVGVydGlhcnkgPSBGQUxTRTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICAvLyBDb21wYXJlIHByaW1hcnkgZGlmZmVyZW5jZXMgZmlyc3QuCiAgICAgICAgaWYgKHBTT3JkZXIgIT0gcFRPcmRlcikKICAgICAgICB7CiAgICAgICAgICAgIGlmIChzT3JkZXIgPT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gVGhlIGVudGlyZSBzb3VyY2UgZWxlbWVudCBpcyBpZ25vcmFibGUuCiAgICAgICAgICAgICAgICAvLyBTa2lwIHRvIHRoZSBuZXh0IHNvdXJjZSBlbGVtZW50LCBidXQgZG9uJ3QgZmV0Y2ggYW5vdGhlciB0YXJnZXQgZWxlbWVudC4KICAgICAgICAgICAgICAgIGdldHQgPSBGQUxTRTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAodE9yZGVyID09IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGdldHMgPSBGQUxTRTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBUaGUgc291cmNlIGFuZCB0YXJnZXQgZWxlbWVudHMgYXJlbid0IGlnbm9yYWJsZSwgYnV0IGl0J3Mgc3RpbGwgcG9zc2libGUKICAgICAgICAgICAgLy8gZm9yIHRoZSBwcmltYXJ5IGNvbXBvbmVudCBvZiBvbmUgb2YgdGhlIGVsZW1lbnRzIHRvIGJlIGlnbm9yYWJsZS4uLi4KICAgICAgICAgICAgaWYgKHBTT3JkZXIgPT0gMCkgIC8vIHByaW1hcnkgb3JkZXIgaW4gc291cmNlIGlzIGlnbm9yYWJsZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBUaGUgc291cmNlJ3MgcHJpbWFyeSBpcyBpZ25vcmFibGUsIGJ1dCB0aGUgdGFyZ2V0J3MgaXNuJ3QuICBXZSB0cmVhdCBpZ25vcmFibGVzCiAgICAgICAgICAgICAgICAvLyBhcyBhIHNlY29uZGFyeSBkaWZmZXJlbmNlLCBzbyByZW1lbWJlciB0aGF0IHdlIGZvdW5kIG9uZS4KICAgICAgICAgICAgICAgIGlmIChjaGVja1NlY1RlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6R1JFQVRFUjsgIC8vIChzdHJlbmd0aCBpcyBTRUNPTkRBUlkpCiAgICAgICAgICAgICAgICAgICAgY2hlY2tTZWNUZXIgPSBGQUxTRTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyBTa2lwIHRvIHRoZSBuZXh0IHNvdXJjZSBlbGVtZW50LCBidXQgZG9uJ3QgZmV0Y2ggYW5vdGhlciB0YXJnZXQgZWxlbWVudC4KICAgICAgICAgICAgICAgIGdldHQgPSBGQUxTRTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmIChwVE9yZGVyID09IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIHJlY29yZCBkaWZmZXJlbmNlcyAtIHNlZSB0aGUgY29tbWVudCBhYm92ZS4KICAgICAgICAgICAgICAgIGlmIChjaGVja1NlY1RlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6TEVTUzsgIC8vIChzdHJlbmd0aCBpcyBTRUNPTkRBUlkpCiAgICAgICAgICAgICAgICAgICAgY2hlY2tTZWNUZXIgPSBGQUxTRTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyBTa2lwIHRvIHRoZSBuZXh0IHRhcmdldCBlbGVtZW50LCBidXQgZG9uJ3QgZmV0Y2ggYW5vdGhlciBzb3VyY2UgZWxlbWVudC4KICAgICAgICAgICAgICAgIGdldHMgPSBGQUxTRTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIE5laXRoZXIgb2YgdGhlIG9yZGVycyBpcyBpZ25vcmFibGUsIGFuZCB3ZSBhbHJlYWR5IGtub3cgdGhhdCB0aGUgcHJpbWFyeQogICAgICAgICAgICAgICAgLy8gb3JkZXJzIGFyZSBkaWZmZXJlbnQgYmVjYXVzZSBvZiB0aGUgKHBTT3JkZXIgIT0gcFRPcmRlcikgdGVzdCBhYm92ZS4KICAgICAgICAgICAgICAgIC8vIFJlY29yZCB0aGUgZGlmZmVyZW5jZSBhbmQgc3RvcCB0aGUgY29tcGFyaXNvbi4KICAgICAgICAgICAgICAgIGlmIChwU09yZGVyIDwgcFRPcmRlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkxFU1M7ICAvLyAoc3RyZW5ndGggaXMgUFJJTUFSWSkKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkdSRUFURVI7ICAvLyAoc3RyZW5ndGggaXMgUFJJTUFSWSkKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgeyAvLyBlbHNlIG9mIGlmICggcFNPcmRlciAhPSBwVE9yZGVyICkKICAgICAgICAgICAgLy8gcHJpbWFyeSBvcmRlciBpcyB0aGUgc2FtZSwgYnV0IGNvbXBsZXRlIG9yZGVyIGlzIGRpZmZlcmVudC4gU28gdGhlcmUKICAgICAgICAgICAgLy8gYXJlIG5vIGJhc2UgZWxlbWVudHMgYXQgdGhpcyBwb2ludCwgb25seSBpZ25vcmFibGVzIChTaW5jZSB0aGUgc3RyaW5ncyBhcmUKICAgICAgICAgICAgLy8gbm9ybWFsaXplZCkKCiAgICAgICAgICAgIGlmIChjaGVja1NlY1RlcikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gYSBzZWNvbmRhcnkgb3IgdGVydGlhcnkgZGlmZmVyZW5jZSBtYXkgc3RpbGwgbWF0dGVyCiAgICAgICAgICAgICAgICB1aW50MzJfdCBzZWNTT3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNlY29uZGFyeU9yZGVyKHNPcmRlcik7CiAgICAgICAgICAgICAgICB1aW50MzJfdCBzZWNUT3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNlY29uZGFyeU9yZGVyKHRPcmRlcik7CgogICAgICAgICAgICAgICAgaWYgKHNlY1NPcmRlciAhPSBzZWNUT3JkZXIpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gdGhlcmUgaXMgYSBzZWNvbmRhcnkgZGlmZmVyZW5jZQogICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IChzZWNTT3JkZXIgPCBzZWNUT3JkZXIpID8gQ29sbGF0b3I6OkxFU1MgOiBDb2xsYXRvcjo6R1JFQVRFUjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoc3RyZW5ndGggaXMgU0VDT05EQVJZKQogICAgICAgICAgICAgICAgICAgIGNoZWNrU2VjVGVyID0gRkFMU0U7IAogICAgICAgICAgICAgICAgICAgIC8vIChldmVuIGluIGZyZW5jaCwgb25seSB0aGUgZmlyc3Qgc2Vjb25kYXJ5IGRpZmZlcmVuY2Ugd2l0aGluCiAgICAgICAgICAgICAgICAgICAgLy8gIGEgYmFzZSBjaGFyYWN0ZXIgbWF0dGVycykKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoY2hlY2tUZXJ0aWFyeSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEgdGVydGlhcnkgZGlmZmVyZW5jZSBtYXkgc3RpbGwgbWF0dGVyCiAgICAgICAgICAgICAgICAgICAgICAgIHVpbnQzMl90IHRlclNPcmRlciA9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6dGVydGlhcnlPcmRlcihzT3JkZXIpOwogICAgICAgICAgICAgICAgICAgICAgICB1aW50MzJfdCB0ZXJUT3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnRlcnRpYXJ5T3JkZXIodE9yZGVyKTsKCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXJTT3JkZXIgIT0gdGVyVE9yZGVyKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGVyZSBpcyBhIHRlcnRpYXJ5IGRpZmZlcmVuY2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9ICh0ZXJTT3JkZXIgPCB0ZXJUT3JkZXIpID8gQ29sbGF0b3I6OkxFU1MgOiBDb2xsYXRvcjo6R1JFQVRFUjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoc3RyZW5ndGggaXMgVEVSVElBUlkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja1RlcnRpYXJ5ID0gRkFMU0U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gLy8gaWYgKGNoZWNrU2VjVGVyKQoKICAgICAgICB9ICAvLyBpZiAoIHBTT3JkZXIgIT0gcFRPcmRlciApCiAgICB9IC8vIHdoaWxlKCkKCiAgICBpZiAoc09yZGVyICE9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6TlVMTE9SREVSKQogICAgewogICAgICAgIC8vICh0T3JkZXIgbXVzdCBiZSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUiwKICAgICAgICAvLyAgc2luY2UgdGhpcyBwb2ludCBpcyBvbmx5IHJlYWNoZWQgd2hlbiBzT3JkZXIgb3IgdE9yZGVyIGlzIE5VTExPUkRFUi4pCiAgICAgICAgLy8gVGhlIHNvdXJjZSBzdHJpbmcgaGFzIG1vcmUgZWxlbWVudHMsIGJ1dCB0aGUgdGFyZ2V0IHN0cmluZyBoYXNuJ3QuCiAgICAgICAgZG8KICAgICAgICB7CiAgICAgICAgICAgIGlmIChDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnByaW1hcnlPcmRlcihzT3JkZXIpICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIFdlIGZvdW5kIGFuIGFkZGl0aW9uYWwgbm9uLWlnbm9yYWJsZSBiYXNlIGNoYXJhY3RlciBpbiB0aGUgc291cmNlIHN0cmluZy4KICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBwcmltYXJ5IGRpZmZlcmVuY2UsIHNvIHRoZSBzb3VyY2UgaXMgZ3JlYXRlcgogICAgICAgICAgICAgICAgcmV0dXJuIENvbGxhdG9yOjpHUkVBVEVSOyAvLyAoc3RyZW5ndGggaXMgUFJJTUFSWSkKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6c2Vjb25kYXJ5T3JkZXIoc09yZGVyKSAhPSAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBBZGRpdGlvbmFsIHNlY29uZGFyeSBlbGVtZW50cyBtZWFuIHRoZSBzb3VyY2Ugc3RyaW5nIGlzIGdyZWF0ZXIKICAgICAgICAgICAgICAgIGlmIChjaGVja1NlY1RlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6R1JFQVRFUjsgIC8vIChzdHJlbmd0aCBpcyBTRUNPTkRBUlkpCiAgICAgICAgICAgICAgICAgICAgY2hlY2tTZWNUZXIgPSBGQUxTRTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSAKICAgICAgICB9CiAgICAgICAgd2hpbGUgKChzT3JkZXIgPSBnZXRTdHJlbmd0aE9yZGVyKGN1cnNvcjEsIHN0YXR1cykpICE9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6TlVMTE9SREVSKTsKICAgIH0KICAgIGVsc2UgaWYgKHRPcmRlciAhPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUikKICAgIHsKICAgICAgICAvLyBUaGUgdGFyZ2V0IHN0cmluZyBoYXMgbW9yZSBlbGVtZW50cywgYnV0IHRoZSBzb3VyY2Ugc3RyaW5nIGhhc24ndC4KICAgICAgICBkbwogICAgICAgIHsKICAgICAgICAgICAgaWYgKENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6cHJpbWFyeU9yZGVyKHRPcmRlcikgIT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gV2UgZm91bmQgYW4gYWRkaXRpb25hbCBub24taWdub3JhYmxlIGJhc2UgY2hhcmFjdGVyIGluIHRoZSB0YXJnZXQgc3RyaW5nLgogICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIHByaW1hcnkgZGlmZmVyZW5jZSwgc28gdGhlIHNvdXJjZSBpcyBsZXNzCiAgICAgICAgICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkxFU1M7IC8vIChzdHJlbmd0aCBpcyBQUklNQVJZKQogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzZWNvbmRhcnlPcmRlcih0T3JkZXIpICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIEFkZGl0aW9uYWwgc2Vjb25kYXJ5IGVsZW1lbnRzIGluIHRoZSB0YXJnZXQgbWVhbiB0aGUgc291cmNlIHN0cmluZyBpcyBsZXNzCiAgICAgICAgICAgICAgICBpZiAoY2hlY2tTZWNUZXIpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQ29sbGF0b3I6OkxFU1M7ICAvLyAoc3RyZW5ndGggaXMgU0VDT05EQVJZKQogICAgICAgICAgICAgICAgICAgIGNoZWNrU2VjVGVyID0gRkFMU0U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gCiAgICAgICAgfQogICAgICAgIHdoaWxlICgodE9yZGVyID0gZ2V0U3RyZW5ndGhPcmRlcihjdXJzb3IyLCBzdGF0dXMpKSAhPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUik7CiAgICB9CgoKICAgIC8vIEZvciBJREVOVElDQUwgY29tcGFyaXNvbnMsIHdlIHVzZSBhIGJpdHdpc2UgY2hhcmFjdGVyIGNvbXBhcmlzb24KICAgIC8vIGFzIGEgdGllYnJlYWtlciBpZiBhbGwgZWxzZSBpcyBlcXVhbAogICAgLy8gTk9URTogVGhlIGphdmEgY29kZSBjb21wYXJlcyByZXN1bHQgd2l0aCAwLCBhbmQgCiAgICAvLyBwdXRzIHRoZSByZXN1bHQgb2YgdGhlIHN0cmluZyBjb21wYXJpc29uIGRpcmVjdGx5IGludG8gcmVzdWx0CiAgICBpZiAocmVzdWx0ID09IENvbGxhdG9yOjpFUVVBTCAmJiBnZXRTdHJlbmd0aCgpID09IElERU5USUNBTCkKICAgIHsKI2lmIDAKICAgICAgLy8gKioqKioqKiogZm9yIHRoZSAgVUNoYXIgbm9ybWFsaXphdGlvbiBpbnRlcmZhY2UuCiAgICAgIC8vIEl0IGRvZXNuJ3Qgd29yayBtdWNoIGZhc3RlciwgYW5kIHRoZSBjb2RlIHdhcyBicm9rZW4KICAgICAgLy8gc28gaXQncyBjb21tZW50ZWQgb3V0LiAtLXNybAovLyAgICAgICAgICBVQ2hhciBzb3VyY2VEZWNvbXBbMTAyNF0sIHRhcmdldERlY29tcFsxMDI0XTsKLy8gICAgICAgICAgaW50MzJfdCBzb3VyY2VEZWNvbXBMZW5ndGggPSAxMDI0OwovLyAgICAgICAgICBpbnQzMl90IHRhcmdldERlY29tcExlbmd0aCA9IDEwMjQ7CgovLyAgICAgICAgICBpbnQ4X3QgY29tcGFyaXNvbjsKLy8gICAgICAgICAgTm9ybWFsaXplcjo6RU1vZGUgZGVjb21wTW9kZSA9IGdldERlY29tcG9zaXRpb24oKTsKCi8vICAgICAgICAgIGlmIChkZWNvbXBNb2RlICE9IE5vcm1hbGl6ZXI6Ok5PX09QKQovLyAgICAgICAgICAgIHsKLy8gICAgICAgICAgICAgIE5vcm1hbGl6ZXI6Om5vcm1hbGl6ZShzb3VyY2UsIHNvdXJjZUxlbmd0aCwgZGVjb21wTW9kZSwKLy8gICAgICAgICAgICAgICAgICAgICAgICAwLCBzb3VyY2VEZWNvbXAsIHNvdXJjZURlY29tcExlbmd0aCwgc3RhdHVzKTsKCi8vICAgICAgICAgICAgICBOb3JtYWxpemVyOjpub3JtYWxpemUodGFyZ2V0LCB0YXJnZXRMZW5ndGgsIGRlY29tcE1vZGUsCi8vICAgICAgICAgICAgICAgICAgICAgICAgMCwgdGFyZ2V0RGVjb21wLCB0YXJnZXREZWNvbXBMZW5ndGgsIHN0YXR1cyk7CgovLyAgICAgICAgICAgICAgY29tcGFyaXNvbiA9IHVfc3RyY21wKHNvdXJjZURlY29tcCx0YXJnZXREZWNvbXApOwovLyAgICAgICAgICAgIH0KLy8gICAgICAgICAgZWxzZQovLyAgICAgICAgICAgIHsKLy8gICAgICAgICAgICAgIGNvbXBhcmlzb24gPSB1X3N0cmNtcChzb3VyY2UsIHRhcmdldCk7IC8qICEgKi8KLy8gICAgICAgICAgICB9CgojZWxzZQoKICAgICAgICBVbmljb2RlU3RyaW5nIHNvdXJjZURlY29tcCwgdGFyZ2V0RGVjb21wOwoKICAgICAgICBpbnQ4X3QgY29tcGFyaXNvbjsKICAgICAgICAKICAgICAgICBOb3JtYWxpemVyOjpub3JtYWxpemUoc291cmNlLCBnZXREZWNvbXBvc2l0aW9uKCksIAogICAgICAgICAgICAgICAgICAgICAgMCwgc291cmNlRGVjb21wLCAgc3RhdHVzKTsKCiAgICAgICAgTm9ybWFsaXplcjo6bm9ybWFsaXplKHRhcmdldCwgZ2V0RGVjb21wb3NpdGlvbigpLCAKICAgICAgICAgICAgICAgICAgICAgIDAsIHRhcmdldERlY29tcCwgIHN0YXR1cyk7CiAgICAgICAgCiAgICAgICAgY29tcGFyaXNvbiA9IHNvdXJjZURlY29tcC5jb21wYXJlKHRhcmdldERlY29tcCk7CiNlbmRpZgoKICAgICAgICBpZiAoY29tcGFyaXNvbiA8IDApCiAgICAgICAgewogICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6TEVTUzsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoY29tcGFyaXNvbiA9PSAwKQogICAgICAgIHsKICAgICAgICAgICAgcmVzdWx0ID0gQ29sbGF0b3I6OkVRVUFMOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6R1JFQVRFUjsKICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKfQoKCmludDMyX3QKUnVsZUJhc2VkQ29sbGF0b3I6Om5leHRDb250cmFjdENoYXIoTm9ybWFsaXplckl0ZXJhdG9yICpjdXJzb3IsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVQ2hhciBjaCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKSBjb25zdAp7CiAgICAvLyBGaXJzdCBnZXQgdGhlIG9yZGVyaW5nIG9mIHRoaXMgc2luZ2xlIGNoYXJhY3RlcgogICAgVmVjdG9yT2ZQVG9Db250cmFjdEVsZW1lbnQgKmxpc3QgPSBnZXRDb250cmFjdFZhbHVlcyhjaCk7CiAgICBFbnRyeVBhaXIgKnBhaXIgPSAoRW50cnlQYWlyICopbGlzdC0+YXQoMCk7CiAgICBpbnQzMl90IG9yZGVyID0gcGFpci0+dmFsdWU7CgogICAgLy8gTm93IGl0ZXJhdGUgdGhyb3VnaCB0aGUgY2hhcnMgZm9sbG93aW5nIGl0IGFuZAogICAgLy8gbG9vayBmb3IgdGhlIGxvbmdlc3QgbWF0Y2gKICAgICgoVW5pY29kZVN0cmluZyYpa2V5KS5yZW1vdmUoKTsKICAgICgoVW5pY29kZVN0cmluZyYpa2V5KSArPSBjaDsKCiAgICB3aGlsZSAoKGNoID0gY3Vyc29yLT5jdXJyZW50KCkpICE9IE5vcm1hbGl6ZXI6OkRPTkUpCiAgICB7CiAgICAgICAgKChVbmljb2RlU3RyaW5nJilrZXkpICs9IGNoOwoKICAgICAgICBpbnQzMl90IG4gPSBnZXRFbnRyeShsaXN0LCBrZXksIFRSVUUpOwoKICAgICAgICBpZiAobiA9PSBVTk1BUFBFRCkKICAgICAgICB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjdXJzb3ItPm5leHQoKTsKCiAgICAgICAgcGFpciA9IChFbnRyeVBhaXIgKilsaXN0LT5hdChuKTsKICAgICAgICBvcmRlciA9IHBhaXItPnZhbHVlOwogICAgfQoKICAgIHJldHVybiBvcmRlcjsKfQoKLy8gQ29tcGFyZSB0d28gc3RyaW5ncyB1c2luZyB0aGlzIGNvbGxhdG9yCkNvbGxhdG9yOjpFQ29tcGFyaXNvblJlc3VsdApSdWxlQmFzZWRDb2xsYXRvcjo6Y29tcGFyZShjb25zdCBVbmljb2RlU3RyaW5nJiBzb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFVuaWNvZGVTdHJpbmcmIHRhcmdldCkgY29uc3QKewogICAgcmV0dXJuIGNvbXBhcmUoc291cmNlLmdldFVDaGFycygpLCBzb3VyY2UubGVuZ3RoKCksIHRhcmdldC5nZXRVQ2hhcnMoKSwgdGFyZ2V0Lmxlbmd0aCgpKTsKfQoKLy8gUmV0cmlldmUgYSBjb2xsYXRpb24ga2V5IGZvciB0aGUgc3BlY2lmaWVkIHN0cmluZwovLyBUaGUga2V5IGNhbiBiZSBjb21wYXJlZCB3aXRoIG90aGVyIGNvbGxhdGlvbiBrZXlzIHVzaW5nIGEgYml0d2lzZSBjb21wYXJpc29uCi8vIChlLmcuIG1lbWNtcCkgdG8gZmluZCB0aGUgb3JkZXJpbmcgb2YgdGhlaXIgcmVzcGVjdGl2ZSBzb3VyY2Ugc3RyaW5ncy4KLy8gVGhpcyBpcyBoYW5keSB3aGVuIGRvaW5nIGEgc29ydCwgd2hlcmUgZWFjaCBzb3J0IGtleSBtdXN0IGJlIGNvbXBhcmVkCi8vIG1hbnkgdGltZXMuCi8vCi8vIFRoZSBiYXNpYyBhbGdvcml0aG0gaGVyZSBpcyB0byBmaW5kIGFsbCBvZiB0aGUgY29sbGF0aW9uIGVsZW1lbnRzIGZvciBlYWNoCi8vIGNoYXJhY3RlciBpbiB0aGUgc291cmNlIHN0cmluZywgY29udmVydCB0aGVtIHRvIGFuIEFTQ0lJIHJlcHJlc2VudGF0aW9uLAovLyBhbmQgcHV0IHRoZW0gaW50byB0aGUgY29sbGF0aW9uIGtleS4gIEJ1dCBpdCdzIHRyaWNraWVyIHRoYW4gdGhhdC4KLy8gRWFjaCBjb2xsYXRpb24gZWxlbWVudCBpbiBhIHN0cmluZyBoYXMgdGhyZWUgY29tcG9uZW50czogcHJpbWFyeSAoJ0EnIHZzICdCJyksCi8vIHNlY29uZGFyeSAoJ3UnIHZzICf8JyksIGFuZCB0ZXJ0aWFyeSAoJ0EnIHZzICdhJyksIGFuZCBhIHByaW1hcnkgZGlmZmVyZW5jZQovLyBhdCB0aGUgZW5kIG9mIGEgc3RyaW5nIHRha2VzIHByZWNlZGVuY2Ugb3ZlciBhIHNlY29uZGFyeSBvciB0ZXJ0aWFyeQovLyBkaWZmZXJlbmNlIGVhcmxpZXIgaW4gdGhlIHN0cmluZy4KLy8KLy8gVG8gYWNjb3VudCBmb3IgdGhpcywgd2UgcHV0IGFsbCBvZiB0aGUgcHJpbWFyeSBvcmRlcnMgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUKLy8gc3RyaW5nLCBmb2xsb3dlZCBieSB0aGUgc2Vjb25kYXJ5IGFuZCB0ZXJ0aWFyeSBvcmRlcnMuIEVhY2ggc2V0IG9mIG9yZGVycyBpcwovLyB0ZXJtaW5hdGVkIGJ5IG51bGxzIHNvIHRoYXQgYSBrZXkgZm9yIGEgc3RyaW5nIHdoaWNoIGlzIGEgaW5pdGlhbCBzdWJzdHJpbmcgb2YKLy8gYW5vdGhlciBrZXkgd2lsbCBjb21wYXJlIGxlc3Mgd2l0aG91dCBhbnkgc3BlY2lhbCBjYXNlLgovLwovLyBIZXJlJ3MgYSBoeXBvdGhldGljYWwgZXhhbXBsZSwgd2l0aCB0aGUgY29sbGF0aW9uIGVsZW1lbnQgcmVwcmVzZW50ZWQgYXMKLy8gYSB0aHJlZS1kaWdpdCBudW1iZXIsIG9uZSBkaWdpdCBmb3IgcHJpbWFyeSwgb25lIGZvciBzZWNvbmRhcnksIGV0Yy4KLy8KLy8gU3RyaW5nOiAgICAgICAgICAgICAgQSAgICAgYSAgICAgQiAgICDJCi8vIENvbGxhdGlvbiBFbGVtZW50czogMTAxICAgMTAwICAgMjAxICA1MTEKLy8gQ29sbGF0aW9uIEtleTogICAgICAxMTI1PG51bGw+MDAwMTxudWxsPjEwMTE8bnVsbD4KLy8KLy8gVG8gbWFrZSB0aGluZ3MgZXZlbiB0cmlja2llciwgc2Vjb25kYXJ5IGRpZmZlcmVuY2VzIChhY2NlbnQgbWFya3MpIGFyZSBjb21wYXJlZAovLyBzdGFydGluZyBhdCB0aGUgKmVuZCogb2YgdGhlIHN0cmluZyBpbiBsYW5ndWFnZXMgd2l0aCBGcmVuY2ggc2Vjb25kYXJ5IG9yZGVyaW5nLgovLyBCdXQgd2hlbiBjb21wYXJpbmcgdGhlIGFjY2VudCBtYXJrcyBvbiBhIHNpbmdsZSBiYXNlIGNoYXJhY3RlciwgdGhleSBhcmUgY29tcGFyZWQKLy8gZnJvbSB0aGUgYmVnaW5uaW5nLiAgVG8gaGFuZGxlIHRoaXMsIHdlIHJldmVyc2UgYWxsIG9mIHRoZSBhY2NlbnRzIHRoYXQgYmVsb25nCi8vIHRvIGVhY2ggYmFzZSBjaGFyYWN0ZXIsIHRoZW4gd2UgcmV2ZXJzZSB0aGUgZW50aXJlIHN0cmluZyBvZiBzZWNvbmRhcnkgb3JkZXJpbmdzCi8vIGF0IHRoZSBlbmQuCi8vCkNvbGxhdGlvbktleSYKUnVsZUJhc2VkQ29sbGF0b3I6OmdldENvbGxhdGlvbktleSggY29uc3QgICBVbmljb2RlU3RyaW5nJiAgc291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb2xsYXRpb25LZXkmICAgc29ydGtleSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpIGNvbnN0CnsKICAgIHJldHVybiBSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0Q29sbGF0aW9uS2V5KHNvdXJjZS5nZXRVQ2hhcnMoKSwgc291cmNlLmxlbmd0aCgpLCBzb3J0a2V5LCBzdGF0dXMpOwp9CgpDb2xsYXRpb25LZXkmClJ1bGVCYXNlZENvbGxhdG9yOjpnZXRDb2xsYXRpb25LZXkoIGNvbnN0ICAgVUNoYXIqICBzb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludDMyX3Qgc291cmNlTGVuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb2xsYXRpb25LZXkmICAgc29ydGtleSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpIGNvbnN0CnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX0lMTEVHQUxfQVJHVU1FTlRfRVJST1I7CiAgICAgICAgcmV0dXJuIHNvcnRrZXkuc2V0VG9Cb2d1cygpOwogICAgfQogICAgCiAgICBpZiAoKCFzb3VyY2UpIHx8IChzb3VyY2VMZW4gPT0gMCkpCiAgICB7CiAgICAgICAgcmV0dXJuIHNvcnRrZXkucmVzZXQoKTsKICAgIH0KCiAgICBpZiAoY3Vyc29yMSA9PSBOVUxMKQogICAgewogICAgICAoKFJ1bGVCYXNlZENvbGxhdG9yICopdGhpcyktPmN1cnNvcjEgPSBuZXcgTm9ybWFsaXplckl0ZXJhdG9yKHNvdXJjZSwgc291cmNlTGVuLCBnZXREZWNvbXBvc2l0aW9uKCkpOwogICAgfQogICAgZWxzZQogICAgewogICAgICBjdXJzb3IxLT5zZXRNb2RlQW5kVGV4dChnZXREZWNvbXBvc2l0aW9uKCksIHNvdXJjZSxzb3VyY2VMZW4sIHN0YXR1cyk7CiAgICB9CgogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybiBzb3J0a2V5LnNldFRvQm9ndXMoKTsKICAgIH0KCiAgICBVQm9vbCAgY29tcGFyZVNlYyAgID0gKGdldFN0cmVuZ3RoKCkgPj0gQ29sbGF0b3I6OlNFQ09OREFSWSk7CiAgICBVQm9vbCAgY29tcGFyZVRlciAgID0gKGdldFN0cmVuZ3RoKCkgPj0gQ29sbGF0b3I6OlRFUlRJQVJZKTsKICAgIFVCb29sICBjb21wYXJlSWRlbnQgPSAoZ2V0U3RyZW5ndGgoKSA9PSBDb2xsYXRvcjo6SURFTlRJQ0FMKTsKICAgIGludDMyX3Qgb3JkZXIgICAgICAgID0gMDsKICAgIGludDMyX3QgdG90YWxQcmltYXJ5ID0gMDsKICAgIGludDMyX3QgdG90YWxTZWMgICAgID0gMDsKICAgIGludDMyX3QgdG90YWxUZXIgICAgID0gMDsKICAgIGludDMyX3QgdG90YWxJZGVudCAgICAgPSAwOwogICAgVW5pY29kZVN0cmluZyBkZWNvbXA7CgogICAgLy8gaXRlcmF0ZSBvdmVyIHRoZSBzb3VyY2UsIGNvdW50aW5nIHByaW1hcnksIHNlY29uZGFyeSwgYW5kIHRlcnRpYXJ5IGVudHJpZXMKICAgIHdoaWxlKChvcmRlciA9IGdldFN0cmVuZ3RoT3JkZXIoKE5vcm1hbGl6ZXJJdGVyYXRvciopY3Vyc29yMSwgc3RhdHVzKSkgIT0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUikKICAgIHsKICAgICAgICBpbnQzMl90IHNlY09yZGVyID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzZWNvbmRhcnlPcmRlcihvcmRlcik7CiAgICAgICAgaW50MzJfdCB0ZXJPcmRlciA9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6dGVydGlhcnlPcmRlcihvcmRlcik7CgogICAgICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBzb3J0a2V5LnNldFRvQm9ndXMoKTsKICAgICAgICB9CgogICAgICAgIGlmICghIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6aXNJZ25vcmFibGUob3JkZXIpKQogICAgICAgIHsKICAgICAgICAgICAgdG90YWxQcmltYXJ5ICs9IDE7CgogICAgICAgICAgICBpZiAoY29tcGFyZVNlYykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdG90YWxTZWMgKz0gMTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKGNvbXBhcmVUZXIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRvdGFsVGVyICs9IDE7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGNvbXBhcmVTZWMgJiYgc2VjT3JkZXIgIT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdG90YWxTZWMgKz0gMTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKGNvbXBhcmVUZXIgJiYgdGVyT3JkZXIgIT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdG90YWxUZXIgKz0gMTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAvLyBjb3VudCB0aGUgbnVsbCBieXRlcyBhZnRlciB0aGUgZW50aXJlcwogICAgdG90YWxQcmltYXJ5ICs9IDE7CgogICAgaWYgKGNvbXBhcmVTZWMpCiAgICB7CiAgICAgICAgdG90YWxTZWMgKz0gMTsKICAgIH0KCiAgICBpZiAoY29tcGFyZVRlcikKICAgIHsKICAgICAgICB0b3RhbFRlciArPSAxOwogICAgfQoKICAgIGlmIChjb21wYXJlSWRlbnQpCiAgICB7CiAgICAgIE5vcm1hbGl6ZXI6Om5vcm1hbGl6ZShzb3VyY2UsIGdldERlY29tcG9zaXRpb24oKSwgLy8gU1JMOiA/PwogICAgICAgICAgICAgICAgMCwgZGVjb21wLCBzdGF0dXMpOwoKICAgICAgICBpZiAoVV9TVUNDRVNTKHN0YXR1cykpCiAgICAgICAgewogICAgICAgICAgICB0b3RhbElkZW50ID0gZGVjb21wLmxlbmd0aCgpICsgMTsKICAgICAgICB9CiAgICB9CgogICAgLy8gQ29tcHV0ZSB0b3RhbCBudW1iZXIgb2YgYnl0ZXMgdG8gaG9sZCB0aGUgZW50cmllcwogICAgLy8gYW5kIG1ha2Ugc3VyZSB0aGUga2V5IGNhbiBob2xkIHRoZW0KICAgIHVpbnQzMl90IHNpemUgICA9IDIgKiAodG90YWxQcmltYXJ5ICsgdG90YWxTZWMgKyB0b3RhbFRlciArIHRvdGFsSWRlbnQpOwoKICAgIHNvcnRrZXkuZW5zdXJlQ2FwYWNpdHkoc2l6ZSk7CgogICAgaWYgKHNvcnRrZXkuaXNCb2d1cygpKQogICAgewogICAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgICAgcmV0dXJuIHNvcnRrZXk7CiAgICB9CgogICAgaW50MzJfdCBwcmltYXJ5Q3Vyc29yID0gMDsKICAgIGludDMyX3Qgc2VjQ3Vyc29yICAgICA9IDIgKiB0b3RhbFByaW1hcnk7CiAgICBpbnQzMl90IHNlY0Jhc2UgICAgICAgPSBzZWNDdXJzb3I7CiAgICBpbnQzMl90IHByZVNlY0lnbm9yZSAgPSBzZWNCYXNlOwogICAgaW50MzJfdCB0ZXJDdXJzb3IgICAgID0gc2VjQ3Vyc29yICsgKDIgKiB0b3RhbFNlYyk7CiAgICBpbnQzMl90IGlkZW50Q3Vyc29yICAgICAgPSB0ZXJDdXJzb3IgKyAoMiAqIHRvdGFsVGVyKTsKCiAgICAvLyByZXNldCBzb3VyY2UgdG8gdGhlIGJlZ2lubmluZwogICAgY3Vyc29yMS0+cmVzZXQoKTsKCiAgICAvLyBub3cgaXRlcmF0ZSBvdmVyIHRoZSBzb3VyY2UgY29tcHV0aW5nIHRoZSBhY3R1YWwgZW50cmllcwogICAgd2hpbGUoKG9yZGVyID0gZ2V0U3RyZW5ndGhPcmRlcigoTm9ybWFsaXplckl0ZXJhdG9yKiljdXJzb3IxLCBzdGF0dXMpKSAhPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUikKICAgIHsKICAgICAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gc29ydGtleS5yZXNldCgpOwogICAgICAgIH0KCiAgICAgICAgaW50MzJfdCBwcmltYXJ5T3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnByaW1hcnlPcmRlcihvcmRlcik7CiAgICAgICAgaW50MzJfdCBzZWNPcmRlciAgICAgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNlY29uZGFyeU9yZGVyKG9yZGVyKTsKICAgICAgICBpbnQzMl90IHRlck9yZGVyICAgICA9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6dGVydGlhcnlPcmRlcihvcmRlcik7CgogICAgICAgIGlmICghIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6aXNJZ25vcmFibGUob3JkZXIpKQogICAgICAgIHsKICAgICAgICAgICAgcHJpbWFyeUN1cnNvciA9IHNvcnRrZXkuc3RvcmVCeXRlcyhwcmltYXJ5Q3Vyc29yLCBwcmltYXJ5T3JkZXIgKyBTT1JUS0VZT0ZGU0VUKTsKCiAgICAgICAgICAgIGlmIChjb21wYXJlU2VjKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoZGF0YS0+aXNGcmVuY2hTZWMgJiYgKHByZVNlY0lnbm9yZSA8IHNlY0N1cnNvcikpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgc29ydGtleS5yZXZlcnNlQnl0ZXMocHJlU2VjSWdub3JlLCBzZWNDdXJzb3IpOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIHNlY0N1cnNvciA9IHNvcnRrZXkuc3RvcmVCeXRlcyhzZWNDdXJzb3IsIHNlY09yZGVyICsgU09SVEtFWU9GRlNFVCk7CgogICAgICAgICAgICAgICAgcHJlU2VjSWdub3JlID0gc2VjQ3Vyc29yOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoY29tcGFyZVRlcikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdGVyQ3Vyc29yID0gc29ydGtleS5zdG9yZUJ5dGVzKHRlckN1cnNvciwgdGVyT3JkZXIgKyBTT1JUS0VZT0ZGU0VUKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpZiAoY29tcGFyZVNlYyAmJiBzZWNPcmRlciAhPSAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzZWNDdXJzb3IgPSBzb3J0a2V5LnN0b3JlQnl0ZXMoc2VjQ3Vyc29yLCBzZWNPcmRlciArIGRhdGEtPm1heFNlY09yZGVyICsgU09SVEtFWU9GRlNFVCk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChjb21wYXJlVGVyICYmIHRlck9yZGVyICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRlckN1cnNvciA9IHNvcnRrZXkuc3RvcmVCeXRlcyh0ZXJDdXJzb3IsIHRlck9yZGVyICsgZGF0YS0+bWF4VGVyT3JkZXIgKyBTT1JUS0VZT0ZGU0VUKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAvLyBhcHBlbmQgMCBhdCB0aGUgZW5kIG9mIGVhY2ggcG9ydGlvbi4KICAgIHNvcnRrZXkuc3RvcmVCeXRlcyhwcmltYXJ5Q3Vyc29yLCAwKTsKCiAgICBpZiAoY29tcGFyZVNlYykKICAgIHsKICAgICAgICBpZiAoZGF0YS0+aXNGcmVuY2hTZWMpCiAgICAgICAgewogICAgICAgICAgICBpZiAocHJlU2VjSWdub3JlIDwgc2VjQ3Vyc29yKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzb3J0a2V5LnJldmVyc2VCeXRlcyhwcmVTZWNJZ25vcmUsIHNlY0N1cnNvcik7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHNvcnRrZXkucmV2ZXJzZUJ5dGVzKHNlY0Jhc2UsIHNlY0N1cnNvcik7CiAgICAgICAgfQoKICAgICAgICBzb3J0a2V5LnN0b3JlQnl0ZXMoc2VjQ3Vyc29yLCAwKTsKICAgIH0KCiAgICBpZiAoY29tcGFyZVRlcikKICAgIHsKICAgICAgICBzb3J0a2V5LnN0b3JlQnl0ZXModGVyQ3Vyc29yLCAwKTsKICAgIH0KCiAgICBpZiAoY29tcGFyZUlkZW50KQogICAgewogICAgICAgIHNvcnRrZXkuc3RvcmVVbmljb2RlU3RyaW5nKGlkZW50Q3Vyc29yLCBkZWNvbXApOwogICAgfQoKICAgIC8vICAgIERlYnVnZ2luZyAtIHByaW50IG91dCB0aGUgc29ydGtleSBbLS1zcmxdCi8vICAgICAgewovLyAgICAgICAgY29uc3QgdWludDhfdCAqYnl0ZXM7Ci8vICAgICAgICBpbnQzMl90IHhjb3VudDsKLy8gICAgICAgIGJ5dGVzID0gc29ydGtleS5nZXRCeXRlQXJyYXkoeGNvdW50KTsKLy8gICAgICAgIC8vICAgICAgZnByaW50ZihzdGRlcnIsICJcblxuLSAgWyUwMlhdIFslMDJYXVxuXG4iLCAoaW50KShieXRlc1swXSYweEZGKSwgKGludCkoYnl0ZXNbMV0mMHhGRikgKTsKLy8gICAgICB9CgogICAgcmV0dXJuIHNvcnRrZXk7Cn0KCgovLyBCdWlsZCB0aGlzIGNvbGxhdG9yJ3MgcnVsZSB0YWJsZXMgYmFzZWQgb24gYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHJ1bGVzCi8vIFNlZSB0aGUgYmlnIGRpYWdyYW0gYXQgdGhlIHRvcCBvZiB0aGlzIGZpbGUgZm9yIGFuIG92ZXJ2aWV3IG9mIGhvdyB0aGUgdGFibGVzCi8vIGFyZSBvcmdhbml6ZWQuCnZvaWQKUnVsZUJhc2VkQ29sbGF0b3I6OmJ1aWxkKGNvbnN0IFVuaWNvZGVTdHJpbmcmICAgcGF0dGVybiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmICAgICAgc3RhdHVzKQp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vIFRoaXMgYXJyYXkgbWFwcyBVbmljb2RlIGNoYXJhY3RlcnMgdG8gdGhlaXIgY29sbGF0aW9uIG9yZGVyaW5nCiAgICBkYXRhLT5tYXBwaW5nID0gdWNtcDMyX29wZW4oVU5NQVBQRUQpOwoKICAgIGlmIChkYXRhLT5tYXBwaW5nLT5mQm9ndXMpCiAgICB7CiAgICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaW50MzJfdCBpID0gMDsKICAgIFVuaWNvZGVTdHJpbmcgbGFzdEdyb3VwQ2hhcnM7CiAgICBVbmljb2RlU3RyaW5nIGV4cENoYXJzOwogICAgVW5pY29kZVN0cmluZyBncm91cENoYXJzOwoKICAgIGlmIChwYXR0ZXJuLmxlbmd0aCgpID09IDApCiAgICB7CiAgICAgICAgc3RhdHVzID0gVV9JTlZBTElEX0ZPUk1BVF9FUlJPUjsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgLy8gQnVpbGQgdGhlIG1lcmdlZCBjb2xsYXRpb24gZW50cmllcwogICAgLy8gU2luY2UgcnVsZXMgY2FuIGJlIHNwZWNpZmllZCBpbiBhbnkgb3JkZXIgaW4gdGhlIHN0cmluZwogICAgLy8gKGUuZy4gImMgLCBDIDwgZCAsIEQgPCBlICwgRSAuLi4uIEMgPCBDSCIpCiAgICAvLyB0aGlzIHNwbGl0cyBhbGwgb2YgdGhlIHJ1bGVzIGluIHRoZSBzdHJpbmcgb3V0IGludG8gc2VwYXJhdGUKICAgIC8vIG9iamVjdHMgYW5kIHRoZW4gc29ydHMgdGhlbS4gIEluIHRoZSBhYm92ZSBleGFtcGxlLCBpdCBtZXJnZXMgdGhlCiAgICAvLyAiQyA8IENIIiBydWxlIGluIGp1c3QgYmVmb3JlIHRoZSAiQyA8IEQiIHJ1bGUuCgogICAgbVBhdHRlcm4gPSBuZXcgTWVyZ2VDb2xsYXRpb24ocGF0dGVybiwgZ2V0RGVjb21wb3NpdGlvbigpLCBzdGF0dXMpOwogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHVjbXAzMl9jbG9zZShkYXRhLT5tYXBwaW5nKTsKICAgICAgICBkYXRhLT5tYXBwaW5nID0gMDsKICAgICAgICBkZWxldGUgbVBhdHRlcm47CiAgICAgICAgbVBhdHRlcm4gPSAwOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBpbnQzMl90IG9yZGVyID0gMDsKCiAgICAvLyBXYWxrIHRocm91Z2ggZWFjaCBlbnRyeQogICAgZm9yIChpID0gMDsgaSA8IG1QYXR0ZXJuLT5nZXRDb3VudCgpOyArK2kpCiAgICB7CiAgICAgICAgY29uc3QgUGF0dGVybkVudHJ5KiBlbnRyeSA9IG1QYXR0ZXJuLT5nZXRJdGVtQXQoaSk7CiAgICAgICAgZ3JvdXBDaGFycy5yZW1vdmUoKTsKICAgICAgICBleHBDaGFycy5yZW1vdmUoKTsKCiAgICAgICAgLy8gaWYgZW50cnkgaXMgdmFsaWQKICAgICAgICBpZiAoZW50cnkgIT0gTlVMTCkKICAgICAgICB7CiAgICAgICAgICAgIGVudHJ5LT5nZXRDaGFycyhncm91cENoYXJzKTsKCiAgICAgICAgICAgIC8vIGNoZWNrIGlmIGZyZW5jaCBzZWNvbmRhcnkgbmVlZHMgdG8gYmUgdHVybmVkIG9uCiAgICAgICAgICAgIGlmICgoZ3JvdXBDaGFycy5sZW5ndGgoKSA+IDEpICYmCiAgICAgICAgICAgICAgICAoZ3JvdXBDaGFyc1tncm91cENoYXJzLmxlbmd0aCgpLTFdID09IDB4MDA0MCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGRhdGEtPmlzRnJlbmNoU2VjID0gVFJVRTsKICAgICAgICAgICAgICAgIGdyb3VwQ2hhcnMucmVtb3ZlKGdyb3VwQ2hhcnMubGVuZ3RoKCktMSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIG9yZGVyID0gaW5jcmVtZW50KChDb2xsYXRvcjo6RUNvbGxhdGlvblN0cmVuZ3RoKWVudHJ5LT5nZXRTdHJlbmd0aCgpLCBvcmRlcik7CgogICAgICAgICAgICBpZiAoZW50cnktPmdldEV4dGVuc2lvbihleHBDaGFycykubGVuZ3RoKCkgIT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gZW5jb3VudGVyZWQgYW4gZXhwYW5kaW5nIGNoYXJhY3Rlciwgd2hlcmUgb25lIGNoYXJhY3RlciBvbiBpbnB1dAogICAgICAgICAgICAgICAgLy8gZXhwYW5kcyB0byBzZXZlcmFsIHNvcnQgZWxlbWVudHMgKGUuZy4gJ/YnIC0tPiAnbycgJ2UnKQogICAgICAgICAgICAgICAgYWRkRXhwYW5kT3JkZXIoZ3JvdXBDaGFycywgZXhwQ2hhcnMsIG9yZGVyLCBzdGF0dXMpOwogICAgICAgICAgICAgICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmIChncm91cENoYXJzLmxlbmd0aCgpID4gMSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gZW5jb3VudGVyZWQgYSBjb250cmFjdGluZyBjaGFyYWN0ZXIsIHdoZXJlIHNldmVyYWwgY2hhcmFjdGVycyBvbiBpbnB1dAogICAgICAgICAgICAgICAgLy8gY29udHJhY3QgaW50byBvbmUgc29ydCBvcmRlci4gIEZvciBleGFtcGxlLCAiY2giIGlzIHRyZWF0ZWQgYXMgYSBzaW5nbGUKICAgICAgICAgICAgICAgIC8vIGNoYXJhY3RlciBpbiB0cmFkaXRpb25hbCBTcGFuaXNoIHNvcnRpbmcuCiAgICAgICAgICAgICAgICBhZGRDb250cmFjdE9yZGVyKGdyb3VwQ2hhcnMsIG9yZGVyLCBzdGF0dXMpOwogICAgICAgICAgICAgICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIE5vdGhpbmcgb3V0IG9mIHRoZSBvcmRpbmFyeSAtLSBvbmUgY2hhcmFjdGVyIG1hcHMgdG8gb25lIHNvcnQgb3JkZXIKICAgICAgICAgICAgICAgIGFkZE9yZGVyKGdyb3VwQ2hhcnNbMF0sIG9yZGVyLCBzdGF0dXMpOwogICAgICAgICAgICAgICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAvLyBhZGQgZXhwYW5kaW5nIGVudHJpZXMgZm9yIHByZS1jb21wb3NlZCBjaGFyYWN0ZXJzCiAgICBhZGRDb21wb3NlZENoYXJzKCk7CgogICAgLy8gRmlsbCBpbiBhbGwgdGhlIGV4cGFuZGluZyBjaGFycyB2YWx1ZXMKICAgIGNvbW1pdCgpOwoKICAgIC8vIENvbXBhY3QgdGhlIGRhdGEgbWFwcGluZyB0YWJsZQogICAgdWNtcDMyX2NvbXBhY3QoZGF0YS0+bWFwcGluZywgMSk7Cn0KCi8qKgogKiBBZGQgZXhwYW5kaW5nIGVudHJpZXMgZm9yIHByZS1jb21wb3NlZCB1bmljb2RlIGNoYXJhY3RlcnMgc28gdGhhdCB0aGlzCiAqIGNvbGxhdG9yIGNhbiBiZSB1c2VkIHJlYXNvbmFibHkgd2VsbCB3aXRoIGRlY29tcG9zaXRpb24gdHVybmVkIG9mZi4KICovCiB2b2lkIFJ1bGVCYXNlZENvbGxhdG9yOjphZGRDb21wb3NlZENoYXJzKCkKIHsKICAgIFVuaWNvZGVTdHJpbmcgYnVmOwogICAgVUVycm9yQ29kZSBzdGF0dXMgPSBVX1pFUk9fRVJST1I7CgogICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGFsbCBvZiB0aGUgcHJlLWNvbXBvc2VkIGNoYXJhY3RlcnMgaW4gVW5pY29kZQogICAgQ29tcG9zZWRDaGFySXRlciBpdGVyOwogICAgVW5pY29kZVN0cmluZyBkZWNvbXA7CgogICAgd2hpbGUgKGl0ZXIuaGFzTmV4dCgpKQogICAgewogICAgICAgIFVDaGFyIGMgPSBpdGVyLm5leHQoKTsKICAgICAgICAKICAgICAgICBpZiAoZ2V0Q2hhck9yZGVyKGMpID09IFVOTUFQUEVEKQogICAgICAgIHsKICAgICAgICAgICAgLy8gCiAgICAgICAgICAgIC8vIFdlIGRvbid0IGFscmVhZHkgaGF2ZSBhbiBvcmRlcmluZyBmb3IgdGhpcyBwcmUtY29tcG9zZWQgY2hhcmFjdGVyLgogICAgICAgICAgICAvLwogICAgICAgICAgICAvLyBGaXJzdCwgc2VlIGlmIHRoZSBkZWNvbXBvc2VkIHN0cmluZyBpcyBhbHJlYWR5IGluIG91cgogICAgICAgICAgICAvLyB0YWJsZXMgYXMgYSBzaW5nbGUgY29udHJhY3Rpbmctc3RyaW5nIG9yZGVyaW5nLgogICAgICAgICAgICAvLyBJZiBzbywganVzdCBtYXAgdGhlIHByZWNvbXBvc2VkIGNoYXJhY3RlciB0byB0aGF0IG9yZGVyLgogICAgICAgICAgICAvLwogICAgICAgICAgICAvLyBUT0RPOiBXaGF0IHdlIHNob3VsZCByZWFsbHkgYmUgZG9pbmcgaGVyZSBpcyB0cnlpbmcgdG8gZmluZCB0aGUKICAgICAgICAgICAgLy8gbG9uZ2VzdCBpbml0aWFsIHN1YnN0cmluZyBvZiB0aGUgZGVjb21wb3NpdGlvbiB0aGF0IGlzIHByZXNlbnQKICAgICAgICAgICAgLy8gaW4gdGhlIHRhYmxlcyBhcyBhIGNvbnRyYWN0aW5nIGNoYXJhY3RlciBzZXF1ZW5jZSwgYW5kIGZpbmQgaXRzCiAgICAgICAgICAgIC8vIG9yZGVyaW5nLiAgVGhlbiBkbyB0aGlzIHJlY3Vyc2l2ZWx5IHdpdGggdGhlIHJlbWFpbmluZyBjaGFycwogICAgICAgICAgICAvLyBzbyB0aGF0IHdlIGJ1aWxkIGEgbGlzdCBvZiBvcmRlcmluZ3MsIGFuZCBhZGQgdGhhdCBsaXN0IHRvCiAgICAgICAgICAgIC8vIHRoZSBleHBhbnNpb24gdGFibGUuIAogICAgICAgICAgICAvLyBUaGF0IHdvdWxkIGJlIG1vcmUgY29ycmVjdCBidXQgYWxzbyBzaWduaWZpY2FudGx5IHNsb3dlciwgc28KICAgICAgICAgICAgLy8gSSdtIG5vdCB0b3RhbGx5IHN1cmUgaXQncyB3b3J0aCBkb2luZy4KICAgICAgICAgICAgLy8KICAgICAgICAgICAgaXRlci5nZXREZWNvbXBvc2l0aW9uKGRlY29tcCk7CiAgICAgICAgICAgIGludCBjb250cmFjdE9yZGVyID0gZ2V0Q29udHJhY3RPcmRlcihkZWNvbXApOwoKICAgICAgICAgICAgaWYgKGNvbnRyYWN0T3JkZXIgIT0gVU5NQVBQRUQpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGFkZE9yZGVyKGMsIGNvbnRyYWN0T3JkZXIsIHN0YXR1cyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLwogICAgICAgICAgICAgICAgLy8gV2UgZG9uJ3QgaGF2ZSBhIGNvbnRyYWN0aW5nIG9yZGVyaW5nIGZvciB0aGUgZW50aXJlIHN0cmluZwogICAgICAgICAgICAgICAgLy8gdGhhdCByZXN1bHRzIGZyb20gdGhlIGRlY29tcG9zaXRpb24sIGJ1dCBpZiB3ZSBoYXZlIG9yZGVycwogICAgICAgICAgICAgICAgLy8gZm9yIGVhY2ggaW5kaXZpZHVhbCBjaGFyYWN0ZXIsIHdlIGNhbiBhZGQgYW4gZXhwYW5kaW5nCiAgICAgICAgICAgICAgICAvLyB0YWJsZSBlbnRyeSBmb3IgdGhlIHByZS1jb21wb3NlZCBjaGFyYWN0ZXIgCiAgICAgICAgICAgICAgICAvLwogICAgICAgICAgICAgICAgVUJvb2wgYWxsVGhlcmUgPSBUUlVFOwogICAgICAgICAgICAgICAgaW50MzJfdCBpOwoKICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBkZWNvbXAubGVuZ3RoKCk7IGkgKz0gMSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0Q2hhck9yZGVyKGRlY29tcFtpXSkgPT0gVU5NQVBQRUQpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBhbGxUaGVyZSA9IEZBTFNFOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgaWYgKGFsbFRoZXJlKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGJ1Zi5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICBidWYgKz0gYzsKICAgICAgICAgICAgICAgICAgICBhZGRFeHBhbmRPcmRlcihidWYsIGRlY29tcCwgVU5NQVBQRUQsIHN0YXR1cyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9Cn0KICAgIAovLyBXaGVuIHRoZSBleHBhbmRpbmcgY2hhcmFjdGVyIHRhYmxlcyBhcmUgYnVpbHQgYnkgYWRkRXhwYW5kT3JkZXIsCi8vIGl0IGRvZXNuJ3Qga25vdyB3aGF0IHRoZSBmaW5hbCBvcmRlcmluZyBvZiBlYWNoIGNoYXJhY3RlcgovLyBpbiB0aGUgZXhwYW5zaW9uIHdpbGwgYmUuICBJbnN0ZWFkLCBpdCBqdXN0IHB1dHMgdGhlIHJhdyBjaGFyYWN0ZXIKLy8gY29kZSBpbnRvIHRoZSB0YWJsZSwgYWRkaW5nIENIQVJJTkRFWCBhcyBhIGZsYWcuICBOb3cgdGhhdCB3ZSd2ZQovLyBmaW5pc2hlZCBidWlsZGluZyB0aGUgbWFwcGluZyB0YWJsZSwgd2UgY2FuIGdvIGJhY2sgYW5kIGxvb2sgdXAKLy8gdGhhdCBjaGFyYWN0ZXIgdG8gc2VlIHdoYXQgaXRzIHJlYWwgY29sbGF0aW9uIG9yZGVyIGlzIGFuZAovLyBzdGljayB0aGF0IGludG8gdGhlIGV4cGFuc2lvbiB0YWJsZS4gIFRoYXQgbGV0cyB1cyBhdm9pZCBkb2luZwovLyBhIHR3by1zdGFnZSBsb29rdXAgbGF0ZXIuCgp2b2lkClJ1bGVCYXNlZENvbGxhdG9yOjpjb21taXQoKQp7CiAgICAvLyBpZiB0aGVyZSBhcmUgYW55IGV4cGFuZGluZyBjaGFyYWN0ZXJzCiAgICBpZiAoZGF0YS0+ZXhwYW5kVGFibGUgIT0gTlVMTCkKICAgIHsKICAgICAgICBpbnQzMl90IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGRhdGEtPmV4cGFuZFRhYmxlLT5zaXplKCk7IGkgKz0gMSkKICAgICAgICB7CiAgICAgICAgICAgIFZlY3Rvck9mSW50KiB2YWx1ZUxpc3QgPSBkYXRhLT5leHBhbmRUYWJsZS0+YXQoaSk7CiAgICAgICAgICAgIGludDMyX3QgajsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHZhbHVlTGlzdC0+c2l6ZSgpOyBqKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIGZvdW5kIGEgZXhwYW5kaW5nIGNoYXJhY3RlcgogICAgICAgICAgICAgICAgLy8gdGhlIGV4cGFuZGluZyBjaGFyIHZhbHVlIGlzIG5vdCBmaWxsZWQgaW4geWV0CiAgICAgICAgICAgICAgICBpZiAoKHZhbHVlTGlzdC0+YXQoaikgPCBFWFBBTkRDSEFSSU5ERVgpICYmCiAgICAgICAgICAgICAgICAgICAgKHZhbHVlTGlzdC0+YXQoaikgPiBDSEFSSU5ERVgpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIC8vIEdldCB0aGUgcmVhbCB2YWx1ZXMgZm9yIHRoZSBub24tZmlsbGVkIGVudHJ5CiAgICAgICAgICAgICAgICAgICAgVUNoYXIgY2ggPSAoVUNoYXIpKHZhbHVlTGlzdC0+YXQoaikgLSBDSEFSSU5ERVgpOwogICAgICAgICAgICAgICAgICAgIGludDMyX3QgcmVhbFZhbHVlID0gdWNtcDMyX2dldChkYXRhLT5tYXBwaW5nLCBjaCk7CgogICAgICAgICAgICAgICAgICAgIGlmIChyZWFsVmFsdWUgPT0gVU5NQVBQRUQpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgcmVhbCB2YWx1ZSBpcyBzdGlsbCB1bm1hcHBlZCwgbWF5YmUgaXQnc2lnbm9yYWJsZQogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUxpc3QtPmF0UHV0KGosIElHTk9SQUJMRU1BU0sgJiBjaCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIC8vIGZpbGwgaW4gdGhlIHZhbHVlCiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVMaXN0LT5hdFB1dChqLCByZWFsVmFsdWUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KIH0KCi8qKgogKiAgSW5jcmVtZW50IG9mIHRoZSBsYXN0IG9yZGVyIGJhc2VkIG9uIHRoZSBjb21wYXJpc29uIGxldmVsLgogKi8KaW50MzJfdApSdWxlQmFzZWRDb2xsYXRvcjo6aW5jcmVtZW50KENvbGxhdG9yOjpFQ29sbGF0aW9uU3RyZW5ndGggYVN0cmVuZ3RoLCBpbnQzMl90IGxhc3RWYWx1ZSkKewogICAgc3dpdGNoKGFTdHJlbmd0aCkKICAgIHsKICAgIGNhc2UgQ29sbGF0b3I6OlBSSU1BUlk6CiAgICAgICAgLy8gaW5jcmVtZW50IHByaWFtcnkgb3JkZXIgIGFuZCBtYXNrIG9mZiBzZWNvbmRhcnkgYW5kIHRlcnRpYXJ5IGRpZmZlcmVuY2UKICAgICAgICBsYXN0VmFsdWUgKz0gUFJJTUFSWU9SREVSSU5DUkVNRU5UOwogICAgICAgIGxhc3RWYWx1ZSAmPSBQUklNQVJZT1JERVJNQVNLOwogICAgICAgIGlzT3Zlcklnbm9yZSA9IFRSVUU7CiAgICAgICAgYnJlYWs7CgogICAgY2FzZSBDb2xsYXRvcjo6U0VDT05EQVJZOgogICAgICAgIC8vIGluY3JlbWVudCBzZWNvbmRhcnkgb3JkZXIgYW5kIG1hc2sgb2ZmIHRlcnRpYXJ5IGRpZmZlcmVuY2UKICAgICAgICBsYXN0VmFsdWUgKz0gU0VDT05EQVJZT1JERVJJTkNSRU1FTlQ7CiAgICAgICAgbGFzdFZhbHVlICY9IFNFQ09OREFSWURJRkZFUkVOQ0VPTkxZOwoKICAgICAgICAvLyByZWNvcmQgbWF4ICMgb2YgaWdub3JhYmxlIGNoYXJzIHdpdGggc2Vjb25kYXJ5IGRpZmZlcmVuY2UKICAgICAgICBpZiAoaXNPdmVySWdub3JlID09IEZBTFNFKQogICAgICAgIHsKICAgICAgICAgICAgZGF0YS0+bWF4U2VjT3JkZXIgKz0gMTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CgogICAgY2FzZSBDb2xsYXRvcjo6VEVSVElBUlk6CiAgICAgICAgLy8gaW5jcmVtZW50IHRlcnRpYXJ5IG9yZGVyCiAgICAgICAgbGFzdFZhbHVlICs9IFRFUlRJQVJZT1JERVJJTkNSRU1FTlQ7CgogICAgICAgIC8vIHJlY29yZCBtYXggIyBvZiBpZ25vcmFibGUgY2hhcnMgd2l0aCB0ZXJ0aWFyeSBkaWZmZXJlbmNlCiAgICAgICAgaWYgKGlzT3Zlcklnbm9yZSA9PSBGQUxTRSkKICAgICAgICB7CiAgICAgICAgICAgIGRhdGEtPm1heFRlck9yZGVyICs9IDE7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwoKICAvLyBjYXNlIElERU5USUNBTD8gIAogICAgfQoKICAgIHJldHVybiBsYXN0VmFsdWU7Cn0KCi8vIEFkZHMgYSBjaGFyYWN0ZXIgYW5kIGl0cyBkZXNpZ25hdGVkIG9yZGVyIGludG8gdGhlIGNvbGxhdGlvbiB0YWJsZS4KLy8gVGhpcyBpcyB0aGUgc2ltcGxlIGNhc2UsIHdpdGggbm8gZXhwYW5zaW9uIG9yIGNvbnRyYWN0aW9uCnZvaWQKUnVsZUJhc2VkQ29sbGF0b3I6OmFkZE9yZGVyKFVDaGFyIGNoLAogICAgICAgICAgICAgICAgICAgICAgICAgaW50MzJfdCBhbk9yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vIHRyeSB0byBmaW5kIHRoZSBvcmRlciBvZiB0aGUgY2hhciBpbiB0aGUgbWFwcGluZyB0YWJsZQogICAgaW50MzJfdCBvcmRlciA9IHVjbXAzMl9nZXQoZGF0YS0+bWFwcGluZywgY2gpOwoKICAgIGlmIChvcmRlciA+PSBDT05UUkFDVENIQVJJTkRFWCkKICAgIHsKICAgICAgICAvLyBUaGVyZSdzIGFscmVhZHkgYW4gZW50cnkgZm9yIHRoaXMgY2hhcmFjdGVyIHRoYXQgcG9pbnRzIHRvIGEgY29udHJhY3RpbmcKICAgICAgICAvLyBjaGFyYWN0ZXIgdGFibGUuICBJbnN0ZWFkIG9mIGFkZGluZyB0aGUgY2hhcmFjdGVyIGRpcmVjdGx5IHRvIHRoZSBtYXBwaW5nCiAgICAgICAgLy8gdGFibGUsIHdlIG11c3QgYWRkIGl0IHRvIHRoZSBjb250cmFjdCB0YWJsZSBpbnN0ZWFkLgogICAgICAgIGtleS5yZW1vdmUoKTsKICAgICAgICBrZXkgKz0gY2g7CiAgICAgICAgaWYgKGtleS5pc0JvZ3VzKCkpCiAgICAgICAgewogICAgICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBhZGRDb250cmFjdE9yZGVyKGtleSwgYW5PcmRlciwgc3RhdHVzKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICAvLyBhZGQgdGhlIGVudHJ5IHRvIHRoZSBtYXBwaW5nIHRhYmxlLCB0aGUgc2FtZSBsYXRlciBlbnRyeSByZXBsYWNlcyB0aGUgcHJldmlvdXMgb25lCiAgICAgICAgdWNtcDMyX3NldChkYXRhLT5tYXBwaW5nLCBjaCwgYW5PcmRlcik7CiAgICB9Cn0KCi8vIEFkZCBhbiBleHBhbmRpbmctY2hhcmFjdGVyIGVudHJ5IHRvIHRoZSB0YWJsZS4Kdm9pZApSdWxlQmFzZWRDb2xsYXRvcjo6YWRkRXhwYW5kT3JkZXIoICBjb25zdCAgIFVuaWNvZGVTdHJpbmcmIGNvbnRyYWN0Q2hhcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgICBVbmljb2RlU3RyaW5nJiBleHBhbmRDaGFycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90IGFuT3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vIENyZWF0ZSBhbiBleHBhbnNpb24gdGFibGUgZW50cnkKICAgIGludDMyX3QgdGFibGVJbmRleCA9IGFkZEV4cGFuc2lvbihhbk9yZGVyLCBleHBhbmRDaGFycyk7CiAgICAKICAgIC8vIEFuZCBhZGQgaXRzIGluZGV4IGludG8gdGhlIG1haW4gbWFwcGluZyB0YWJsZQogICAgaWYgKGNvbnRyYWN0Q2hhcnMubGVuZ3RoKCkgPiAxKQogICAgewogICAgICAgIGFkZENvbnRyYWN0T3JkZXIoY29udHJhY3RDaGFycywgdGFibGVJbmRleCwgc3RhdHVzKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBhZGRPcmRlcihjb250cmFjdENoYXJzWzBdLCB0YWJsZUluZGV4LCBzdGF0dXMpOwogICAgfQp9CgppbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjphZGRFeHBhbnNpb24oaW50MzJfdCBhbk9yZGVyLCBjb25zdCBVbmljb2RlU3RyaW5nICZleHBhbmRDaGFycykKewogICAgaWYgKGRhdGEtPmV4cGFuZFRhYmxlID09IE5VTEwpCiAgICB7CiAgICAgICAgZGF0YS0+ZXhwYW5kVGFibGUgPSBuZXcgVmVjdG9yT2ZQVG9FeHBhbmRUYWJsZSgpOwoKICAgICAgICBpZiAoZGF0YS0+ZXhwYW5kVGFibGUgPT0gTlVMTCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAwOwogICAgICAgIH0KICAgIH0KICAgIAogICAgLy8gSWYgYW5PcmRlciBpcyB2YWxpZCwgd2Ugd2FudCB0byBhZGQgaXQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgbGlzdAogICAgaW50MzJfdCBvZmZzZXQgPSAoYW5PcmRlciA9PSBVTk1BUFBFRCkgPyAwIDogMTsKICAgIAogICAgVmVjdG9yT2ZJbnQgKnZhbHVlTGlzdCA9IG5ldyBWZWN0b3JPZkludChleHBhbmRDaGFycy5sZW5ndGgoKSArIG9mZnNldCk7CgogICAgaWYgKG9mZnNldCA9PSAxKQogICAgewogICAgICAgIHZhbHVlTGlzdC0+YXRQdXQoMCwgYW5PcmRlcik7CiAgICB9CgogICAgaW50MzJfdCBpOwogICAgZm9yIChpID0gMDsgaSA8IGV4cGFuZENoYXJzLmxlbmd0aCgpOyBpICs9IDEpCiAgICB7CiAgICAgICAgVUNoYXIgY2ggPSBleHBhbmRDaGFyc1tpXTsKICAgICAgICBpbnQzMl90IG1hcFZhbHVlID0gZ2V0Q2hhck9yZGVyKGNoKTsKICAgICAgICAKICAgICAgICBpZiAobWFwVmFsdWUgIT0gVU5NQVBQRUQpCiAgICAgICAgewogICAgICAgICAgICB2YWx1ZUxpc3QtPmF0UHV0KGkgKyBvZmZzZXQsIG1hcFZhbHVlKTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgLy8gY2FuJ3QgZmluZCBpdCBpbiB0aGUgdGFibGUsIHdpbGwgYmUgZmlsbGVkIGluIGJ5IGNvbW1pdCgpLgogICAgICAgICAgICB2YWx1ZUxpc3QtPmF0UHV0KGkgKyBvZmZzZXQsIENIQVJJTkRFWCArIChpbnQzMl90KWNoKTsKICAgICAgICB9CiAgICB9CgogICAgLy8gQWRkIHRoZSBleHBhbmRpbmcgY2hhciBsaXN0IGludG8gdGhlIGV4cGFuc2lvbiB0YWJsZS4KICAgIGludDMyX3QgdGFibGVJbmRleCA9IEVYUEFORENIQVJJTkRFWCArIGRhdGEtPmV4cGFuZFRhYmxlLT5zaXplKCk7CiAgICBkYXRhLT5leHBhbmRUYWJsZS0+YXRQdXQoZGF0YS0+ZXhwYW5kVGFibGUtPnNpemUoKSwgdmFsdWVMaXN0KTsKICAgIAogICAgcmV0dXJuIHRhYmxlSW5kZXg7Cn0KCi8vIEFkZCBhIHN0cmluZyBvZiBjaGFyYWN0ZXJzIHRoYXQgY29udHJhY3RzIGludG8gYSBzaW5nbGUgb3JkZXJpbmcuCnZvaWQKUnVsZUJhc2VkQ29sbGF0b3I6OmFkZENvbnRyYWN0T3JkZXIoY29uc3QgICBVbmljb2RlU3RyaW5nJiBncm91cENoYXJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90IGFuT3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVCb29sIGZ3ZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChkYXRhLT5jb250cmFjdFRhYmxlID09IE5VTEwpCiAgICB7CiAgICAgICAgZGF0YS0+Y29udHJhY3RUYWJsZSA9IG5ldyBWZWN0b3JPZlBUb0NvbnRyYWN0VGFibGUoKTsKICAgICAgICBpZiAoZGF0YS0+Y29udHJhY3RUYWJsZS0+aXNCb2d1cygpKQogICAgICAgIHsKICAgICAgICAgICAgZGVsZXRlIGRhdGEtPmNvbnRyYWN0VGFibGU7CiAgICAgICAgICAgIGRhdGEtPmNvbnRyYWN0VGFibGUgPSBOVUxMOwogICAgICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgfQoKICAgIC8vIFNlZSBpZiB0aGUgaW5pdGlhbCBjaGFyYWN0ZXIgb2YgdGhlIHN0cmluZyBhbHJlYWR5IGhhcyBhIGNvbnRyYWN0IHRhYmxlLgogICAgLy8gZS5nLiBmb3IgImNoIiwgbG9vayBmb3IgJ2MnLgogICAgaW50MzJfdCBlbnRyeSA9IHVjbXAzMl9nZXQoZGF0YS0+bWFwcGluZywgZ3JvdXBDaGFyc1swXSk7CiAgICBWZWN0b3JPZlBUb0NvbnRyYWN0RWxlbWVudCAqZW50cnlUYWJsZSA9IGdldENvbnRyYWN0VmFsdWVzKGVudHJ5IC0gQ09OVFJBQ1RDSEFSSU5ERVgpOwoKICAgIGlmIChlbnRyeVRhYmxlID09IE5VTEwpCiAgICB7CiAgICAgICAgLy8gV2UgbmVlZCB0byBjcmVhdGUgYSBuZXcgdGFibGUgb2YgY29udHJhY3QgZW50cmllcyBmb3IgdGhpcyBiYXNlIGNoYXIKICAgICAgICBpbnQzMl90IHRhYmxlSW5kZXggPSBDT05UUkFDVENIQVJJTkRFWCArIGRhdGEtPmNvbnRyYWN0VGFibGUtPnNpemUoKTsKICAgICAgICBFbnRyeVBhaXIgKnBhaXIgPSBOVUxMOwogICAgICAgIFVuaWNvZGVTdHJpbmcgc3Vic3RyaW5nOwoKICAgICAgICBlbnRyeVRhYmxlID0gbmV3IFZlY3Rvck9mUFRvQ29udHJhY3RFbGVtZW50KCk7CiAgICAgICAgaWYgKGVudHJ5VGFibGUtPmlzQm9ndXMoKSkKICAgICAgICB7CiAgICAgICAgICAgIGRlbGV0ZSBlbnRyeVRhYmxlOwogICAgICAgICAgICBkZWxldGUgZGF0YS0+Y29udHJhY3RUYWJsZTsKICAgICAgICAgICAgZGF0YS0+Y29udHJhY3RUYWJsZSA9IE5VTEw7CiAgICAgICAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIGRhdGEtPmNvbnRyYWN0VGFibGUtPmF0UHV0KGRhdGEtPmNvbnRyYWN0VGFibGUtPnNpemUoKSwgZW50cnlUYWJsZSk7CiAgICAgICAgaWYgKGRhdGEtPmNvbnRyYWN0VGFibGUtPmlzQm9ndXMoKSkKICAgICAgICB7CiAgICAgICAgICAgIGRlbGV0ZSBlbnRyeVRhYmxlOwogICAgICAgICAgICBkZWxldGUgZGF0YS0+Y29udHJhY3RUYWJsZTsKICAgICAgICAgICAgZGF0YS0+Y29udHJhY3RUYWJsZSA9IE5VTEw7CiAgICAgICAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgICAgIAoKICAgICAgICAvLyBBZGQgdGhlIGluaXRpYWwgY2hhcmFjdGVyJ3MgY3VycmVudCBvcmRlcmluZyBmaXJzdC4gdGhlbgogICAgICAgIC8vIHVwZGF0ZSBpdHMgbWFwcGluZyB0byBwb2ludCB0byB0aGlzIGNvbnRyYWN0IHRhYmxlCiAgICAgICAgZ3JvdXBDaGFycy5leHRyYWN0KDAsIDEsIHN1YnN0cmluZyk7CiAgICAgICAgaWYgKHN1YnN0cmluZy5pc0JvZ3VzKCkpCiAgICAgICAgewogICAgICAgICAgICBkZWxldGUgZW50cnlUYWJsZTsKICAgICAgICAgICAgZGVsZXRlIGRhdGEtPmNvbnRyYWN0VGFibGU7CiAgICAgICAgICAgIGRhdGEtPmNvbnRyYWN0VGFibGUgPSBOVUxMOwogICAgICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBwYWlyID0gbmV3IEVudHJ5UGFpcihzdWJzdHJpbmcsIGVudHJ5KTsKCiAgICAgICAgZW50cnlUYWJsZS0+YXRQdXQoMCwgcGFpcik7CiAgICAgICAgaWYgKGVudHJ5VGFibGUtPmlzQm9ndXMoKSkKICAgICAgICB7CiAgICAgICAgICAgIGRlbGV0ZSBlbnRyeVRhYmxlOwogICAgICAgICAgICBkZWxldGUgZGF0YS0+Y29udHJhY3RUYWJsZTsKICAgICAgICAgICAgZGF0YS0+Y29udHJhY3RUYWJsZSA9IE5VTEw7CiAgICAgICAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHVjbXAzMl9zZXQoZGF0YS0+bWFwcGluZywgZ3JvdXBDaGFyc1swXSwgdGFibGVJbmRleCk7CiAgICB9CgogICAgLy8gTm93IGFkZCAob3IgcmVwbGFjZSkgdGhpcyBzdHJpbmcgaW4gdGhlIHRhYmxlCiAgICBpbnQzMl90IGluZGV4ID0gZ2V0RW50cnkoZW50cnlUYWJsZSwgZ3JvdXBDaGFycywgZndkKTsKCiAgICBpZiAoaW5kZXggIT0gVU5NQVBQRUQpCiAgICB7CiAgICAgICAgRW50cnlQYWlyICpwYWlyID0gKEVudHJ5UGFpciAqKSBlbnRyeVRhYmxlLT5hdChpbmRleCk7CiAgICAgICAgcGFpci0+dmFsdWUgPSBhbk9yZGVyOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIEVudHJ5UGFpciAqcGFpciA9IG5ldyBFbnRyeVBhaXIoZ3JvdXBDaGFycywgYW5PcmRlciwgZndkKTsKCiAgICAgICAgZW50cnlUYWJsZS0+YXRQdXQoZW50cnlUYWJsZS0+c2l6ZSgpLCBwYWlyKTsKICAgIH0KICAgIAogICAgLy8gSWYgdGhpcyB3YXMgYSBmb3J3YXJkIG1hcHBpbmcgZm9yIGEgY29udHJhY3Rpbmcgc3RyaW5nLCBhbHNvIGFkZCBhCiAgICAvLyByZXZlcnNlIG1hcHBpbmcgZm9yIGl0LCBzbyB0aGF0IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6cHJldmlvdXMKICAgIC8vIGNhbiB3b3JrIHJpZ2h0CiAgICBpZiAoZndkKQogICAgewogICAgICAgIFVuaWNvZGVTdHJpbmcgcmV2ZXJzZShncm91cENoYXJzKTsKCiAgICAgICAgaWYgKHJldmVyc2UuaXNCb2d1cygpKQogICAgICAgIHsKICAgICAgICAgICAgZGVsZXRlIGVudHJ5VGFibGU7CiAgICAgICAgICAgIGRlbGV0ZSBkYXRhLT5jb250cmFjdFRhYmxlOwogICAgICAgICAgICBkYXRhLT5jb250cmFjdFRhYmxlID0gTlVMTDsKICAgICAgICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgYWRkQ29udHJhY3RPcmRlcihyZXZlcnNlLnJldmVyc2UoKSwgYW5PcmRlciwgRkFMU0UsIHN0YXR1cyk7CiAgICB9Cn0KCi8qKgogKiBJZiB0aGUgZ2l2ZW4gc3RyaW5nIGhhcyBiZWVuIHNwZWNpZmllZCBhcyBhIGNvbnRyYWN0aW5nIHN0cmluZwogKiBpbiB0aGlzIGNvbGxhdGlvbiB0YWJsZSwgcmV0dXJuIGl0cyBvcmRlcmluZy4KICogT3RoZXJ3aXNlIHJldHVybiBVTk1BUFBFRC4KICovCiBpbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjpnZXRDb250cmFjdE9yZGVyKGNvbnN0IFVuaWNvZGVTdHJpbmcgJmdyb3VwQ2hhcnMpIGNvbnN0CnsKICAgIGludDMyX3QgcmVzdWx0ID0gVU5NQVBQRUQ7CgogICAgaWYgKGRhdGEtPmNvbnRyYWN0VGFibGUgIT0gTlVMTCkKICAgIHsKICAgICAgICBWZWN0b3JPZlBUb0NvbnRyYWN0RWxlbWVudCAqZW50cnlUYWJsZSA9IGdldENvbnRyYWN0VmFsdWVzKGdyb3VwQ2hhcnNbMF0pOwoKICAgICAgICBpZiAoZW50cnlUYWJsZSAhPSBOVUxMKQogICAgICAgIHsKICAgICAgICAgICAgaW50MzJfdCBpbmRleCA9IGdldEVudHJ5KGVudHJ5VGFibGUsIGdyb3VwQ2hhcnMsIFRSVUUpOwoKICAgICAgICAgICAgaWYgKGluZGV4ICE9IFVOTUFQUEVEKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBFbnRyeVBhaXIgKnBhaXIgPSBlbnRyeVRhYmxlLT5hdChpbmRleCk7CgogICAgICAgICAgICAgICAgcmVzdWx0ID0gcGFpci0+dmFsdWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKfQoKaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0Q2hhck9yZGVyKFVDaGFyIGNoKSBjb25zdAp7CiAgICBpbnQzMl90IG9yZGVyID0gdWNtcDMyX2dldChkYXRhLT5tYXBwaW5nLCBjaCk7CiAgICAKICAgIGlmIChvcmRlciA+PSBDT05UUkFDVENIQVJJTkRFWCkKICAgIHsKICAgICAgICBWZWN0b3JPZlBUb0NvbnRyYWN0RWxlbWVudCAqZ3JvdXBMaXN0ID0gZ2V0Q29udHJhY3RWYWx1ZXMob3JkZXIgLSBDT05UUkFDVENIQVJJTkRFWCk7CiAgICAgICAgRW50cnlQYWlyICpwYWlyID0gZ3JvdXBMaXN0LT5hdCgwKTsKCiAgICAgICAgb3JkZXIgPSBwYWlyLT52YWx1ZTsKICAgIH0KCiAgICByZXR1cm4gb3JkZXI7Cn0KICAgIAovLyBDcmVhdGUgYSBoYXNoIGNvZGUgZm9yIHRoaXMgY29sbGF0aW9uLiAgSnVzdCBoYXNoIHRoZSBtYWluIHJ1bGUgdGFibGUgLS0KLy8gdGhhdCBzaG91bGQgYmUgZ29vZCBlbm91Z2ggZm9yIGFsbW9zdCBhbnkgdXNlLgppbnQzMl90ClJ1bGVCYXNlZENvbGxhdG9yOjpoYXNoQ29kZSgpIGNvbnN0CnsKICAgIGludDMyX3QgICAgICAgICB2YWx1ZSA9IDA7CiAgICBpbnQzMl90ICAgICAgICAgYzsKICAgIGludDMyX3QgICAgICAgICBjb3VudCA9IGdldFJ1bGVzKCkubGVuZ3RoKCk7CiAgICBVVGV4dE9mZnNldCAgICAgIHBvcyA9IGNvdW50IC0gMTsKCiAgICBpZiAoY291bnQgPiA2NCkKICAgIHsKICAgICAgICBjb3VudCA9IDY0OyAvLyBvbmx5IGhhc2ggdXB0byBsaW1pdAogICAgfQoKICAgIGludDE2X3QgaSA9IDA7CgogICAgd2hpbGUgKGkgPCBjb3VudCkKICAgIHsKICAgICAgICBjID0gZGF0YS0+cnVsZVRhYmxlW3Bvc107CiAgICAgICAgdmFsdWUgPSAoKHZhbHVlIDw8IChjICYgMHgwZikpIF4gKGMgPDwgOCkpICsgKGMgXiB2YWx1ZSk7CiAgICAgICAgaSArPSAxOwogICAgICAgIHBvcyAtPSAxOwogICAgfQoKICAgIGlmICh2YWx1ZSA9PSAwKQogICAgewogICAgICAgIHZhbHVlID0gMTsKICAgIH0KCiAgICByZXR1cm4gdmFsdWU7Cn0KCi8vIGZpbmQgdGhlIGNvbnRyYWN0aW5nIGNoYXIgZW50cnkgaW4gdGhlIGxpc3QKaW50MzJfdApSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0RW50cnkoVmVjdG9yT2ZQVG9Db250cmFjdEVsZW1lbnQqIGxpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBVbmljb2RlU3RyaW5nJiBuYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgVUJvb2wgZndkKQp7CiAgICBpbnQzMl90IGk7CgogICAgaWYgKGxpc3QgIT0gTlVMTCkKICAgIHsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC0+c2l6ZSgpOyBpICs9IDEpCiAgICAgICAgewogICAgICAgICAgICBFbnRyeVBhaXIgKnBhaXIgPSBsaXN0LT5hdChpKTsKCiAgICAgICAgICAgIGlmICgocGFpciAhPSBOVUxMKSAmJiAocGFpci0+ZndkID09IGZ3ZCkgJiYgKHBhaXItPmVudHJ5TmFtZSA9PSBuYW1lKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0dXJuIGk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIFJ1bGVCYXNlZENvbGxhdG9yOjpVTk1BUFBFRDsKfQoKLy8gbG9vayBmb3IgdGhlIGNvbnRyYWN0aW5nIGxpc3QgZW50cnkgd2l0aCB0aGUgYmVnaW5uaW5nIGNoYXIKVmVjdG9yT2ZQVG9Db250cmFjdEVsZW1lbnQqClJ1bGVCYXNlZENvbGxhdG9yOjpnZXRDb250cmFjdFZhbHVlcyhVQ2hhciBjaCkgY29uc3QKewogICAgaW50MzJfdCBpbmRleCA9IHVjbXAzMl9nZXQoZGF0YS0+bWFwcGluZywgY2gpOwogICAgcmV0dXJuIGdldENvbnRyYWN0VmFsdWVzKGluZGV4IC0gQ09OVFJBQ1RDSEFSSU5ERVgpOwp9CgovLyBsb29rIGZvciB0aGUgY29udHJhY3RpbmcgbGlzdCBlbnRyeSB3aXRoIHRoZSBpbmRleApWZWN0b3JPZlBUb0NvbnRyYWN0RWxlbWVudCoKUnVsZUJhc2VkQ29sbGF0b3I6OmdldENvbnRyYWN0VmFsdWVzKGludDMyX3QgICAgaW5kZXgpIGNvbnN0CnsKICAgIGlmIChkYXRhLT5jb250cmFjdFRhYmxlICE9IE5VTEwpCiAgICB7CiAgICAgICAgaWYgKGluZGV4ID49IDApCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gZGF0YS0+Y29udHJhY3RUYWJsZS0+YXQoaW5kZXgpOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBOVUxMOwp9CgovKioKICAqIFJldHVybiB0aGUgbWF4aW11bSBsZW5ndGggb2YgYW55IGV4cGFuc2lvbiBzZXF1ZW5jZXMgdGhhdCBlbmQKICAqIHdpdGggdGhlIHNwZWNpZmllZCBjb21wYXJpc29uIG9yZGVyLgogICoKICAqIEBwYXJhbSBvcmRlciBhIGNvbGxhdGlvbiBvcmRlciByZXR1cm5lZCBieSBwcmV2aW91cyBvciBuZXh0LgogICogQHJldHVybiB0aGUgbWF4aW11bSBsZW5ndGggb2YgYW55IGV4cGFuc2lvbiBzZXVlbmNlcyBlbmRpbmcKICAqICAgICAgICAgd2l0aCB0aGUgc3BlY2lmaWVkIG9yZGVyLgogICoKICAqIEBzZWUgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yI2dldE1heEV4cGFuc2lvbgogICovCmludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OmdldE1heEV4cGFuc2lvbihpbnQzMl90IG9yZGVyKSBjb25zdAp7CiAgICBpbnQzMl90IHJlc3VsdCA9IDE7CiAgICAKICAgIGlmIChkYXRhLT5leHBhbmRUYWJsZSAhPSBOVUxMKQogICAgewogICAgICAgIC8vIFJpZ2h0IG5vdyB0aGlzIGRvZXMgYSBsaW5lYXIgc2VhcmNoIHRocm91Z2ggdGhlIGVudGlyZQogICAgICAgIC8vIGV4cGFuZHNpb24gdGFibGUuICBJZiBhIGNvbGxhdG9yIGhhZCBhIGxhcmdlIG51bWJlciBvZiBleHBhbnNpb25zLAogICAgICAgIC8vIHRoaXMgY291bGQgY2F1c2UgYSBwZXJmb3JtYW5jZSBwcm9ibGVtLCBidXQgaW4gcHJhY3RpY2UgdGhhdAogICAgICAgIC8vIHJhcmVseSBoYXBwZW5zCiAgICAgICAgaW50MzJfdCBpOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBkYXRhLT5leHBhbmRUYWJsZS0+c2l6ZSgpOyBpICs9IDEpCiAgICAgICAgewogICAgICAgICAgICBWZWN0b3JPZkludCAqdmFsdWVMaXN0ID0gZGF0YS0+ZXhwYW5kVGFibGUtPmF0KGkpOwogICAgICAgICAgICBpbnQzMl90IGxlbmd0aCA9IHZhbHVlTGlzdC0+c2l6ZSgpOwogICAgICAgICAgICAKICAgICAgICAgICAgaWYgKGxlbmd0aCA+IHJlc3VsdCAmJiB2YWx1ZUxpc3QtPmF0KGxlbmd0aC0xKSA9PSBvcmRlcikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmVzdWx0ID0gbGVuZ3RoOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiByZXN1bHQ7Cn0KICAgIAovKioKICogIEdldCB0aGUgZW50cnkgb2YgaGFzaCB0YWJsZSBvZiB0aGUgZXhwYW5kaW5nIHN0cmluZyBpbiB0aGUgY29sbGF0aW9uCiAqICB0YWJsZS4KICogIEBwYXJhbSBvZmZzZXQgdGhlIGluZGV4IG9mIHRoZSBleHBhbmRpbmcgc3RyaW5nIHZhbHVlIGxpc3QKICovClZlY3Rvck9mSW50ICpSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0RXhwYW5kVmFsdWVMaXN0KGludDMyX3Qgb3JkZXIpIGNvbnN0CnsKICAgIHJldHVybiBkYXRhLT5leHBhbmRUYWJsZS0+YXQob3JkZXIgLSBFWFBBTkRDSEFSSU5ERVgpOwp9CgoKCnZvaWQgUnVsZUJhc2VkQ29sbGF0b3JTdHJlYW1lcjo6c3RyZWFtSW4oUnVsZUJhc2VkQ29sbGF0b3IqIGNvbGxhdG9yLCBVTWVtb3J5U3RyZWFtKiBpcykKewogICAgaWYgKCF1cHJ2X21zdHJtX2Vycm9yKGlzKSkKICAgIHsKICAgICAgICAvLyBDaGVjayB0aGF0IHRoaXMgaXMgdGhlIGNvcnJlY3QgZmlsZSB0eXBlCiAgICAgICAgaW50MTZfdCBpZDsKCiAgICAgICAgdXBydl9tc3RybV9yZWFkKGlzLCAmaWQsIHNpemVvZihpZCkpOwogICAgICAgIGlmIChpZCAhPSBjb2xsYXRvci0+RklMRUlEKQogICAgICAgIHsKICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0aGUgcmlnaHQgdHlwZSBvZiBmaWxlLiAgTWFyayB0aGUgaW9zCiAgICAgICAgICAgIC8vIGFzIGZhaWxpbmcgYW5kIHJldHVybi4KICAgICAgICAgICAgdXBydl9tc3RybV9zZXRFcnJvcihpcyk7IC8vIGZvcmNlIHRoZSBzdHJlYW0gdG8gc2V0IGl0cyBlcnJvciBmbGFnCiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIC8vIFN0cmVhbSBpbiBsYXJnZSBvYmplY3RzCiAgICAgICAgY2hhciBpc051bGw7CgogICAgICAgIHVwcnZfbXN0cm1fcmVhZChpcywgJmlzTnVsbCwgc2l6ZW9mKGlzTnVsbCkpOwogICAgICAgIGlmIChpc051bGwpCiAgICAgICAgewogICAgICAgICAgICBkZWxldGUgY29sbGF0b3ItPmRhdGE7CiAgICAgICAgICAgIGNvbGxhdG9yLT5kYXRhID0gTlVMTDsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGNvbGxhdG9yLT5kYXRhID09IE5VTEwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGNvbGxhdG9yLT5kYXRhID0gbmV3IFRhYmxlQ29sbGF0aW9uRGF0YTsKICAgICAgICAgICAgfQogICAgICAgICAgICAKICAgICAgICAgICAgY29sbGF0b3ItPmRhdGEtPnN0cmVhbUluKGlzKTsKICAgICAgICAgICAgaWYgKGNvbGxhdG9yLT5kYXRhLT5pc0JvZ3VzKCkpIHsKICAgICAgICAgICAgICAgIHVwcnZfbXN0cm1fc2V0RXJyb3IoaXMpOyAvLyBmb3JjZSB0aGUgc3RyZWFtIHRvIHNldCBpdHMgZXJyb3IgZmxhZwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBWZXJpZnkgdGhhdCB0aGUgZW5kIG1hcmtlciBpcyBwcmVzZW50CiAgICAgICAgdXBydl9tc3RybV9yZWFkKGlzLCAmaWQsIHNpemVvZihpZCkpOwogICAgICAgIGlmIChpZCAhPSBjb2xsYXRvci0+RklMRUlEKQogICAgICAgIHsKICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0aGUgcmlnaHQgdHlwZSBvZiBmaWxlLiAgTWFyayB0aGUgaW9zCiAgICAgICAgICAgIC8vIGFzIGZhaWxpbmcgYW5kIHJldHVybi4KICAgICAgICAgICAgdXBydl9tc3RybV9zZXRFcnJvcihpcyk7IC8vIGZvcmNlIHRoZSBzdHJlYW0gdG8gc2V0IGl0cyBlcnJvciBmbGFnCiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIC8vIFJlc2V0IG90aGVyIGRhdGEgbWVtYmVycwogICAgICAgIGNvbGxhdG9yLT5pc092ZXJJZ25vcmUgPSBGQUxTRTsKICAgICAgICBjb2xsYXRvci0+bGFzdENoYXIgPSAwOwogICAgICAgIGRlbGV0ZSBjb2xsYXRvci0+bVBhdHRlcm47CiAgICAgICAgY29sbGF0b3ItPm1QYXR0ZXJuID0gMDsKICAgICAgICBjb2xsYXRvci0+a2V5LnJlbW92ZSgpOwogICAgICAgIGNvbGxhdG9yLT5kYXRhSXNPd25lZCA9IFRSVUU7CiAgICB9Cn0KCnZvaWQgUnVsZUJhc2VkQ29sbGF0b3JTdHJlYW1lcjo6c3RyZWFtT3V0KGNvbnN0IFJ1bGVCYXNlZENvbGxhdG9yKiBjb2xsYXRvciwgVU1lbW9yeVN0cmVhbSogb3MpCnsKICAgIGlmICghdXBydl9tc3RybV9lcnJvcihvcykpCiAgICB7CiAgICAgICAgLy8gV2UgdXNlIGEgMTYtYml0IElEIGNvZGUgdG8gaWRlbnRpZnkgdGhpcyBmaWxlLgogICAgICAgIGludDE2X3QgaWQgPSBjb2xsYXRvci0+RklMRUlEOwogICAgICAgIHVwcnZfbXN0cm1fd3JpdGUob3MsICh1aW50OF90ICopJmlkLCBzaXplb2YoaWQpKTsKCiAgICAgICAgLy8gU3RyZWFtIG91dCB0aGUgZGF0YQogICAgICAgIGNoYXIgaXNOdWxsOwogICAgICAgIGlzTnVsbCA9IChjb2xsYXRvci0+ZGF0YSA9PSAwKTsKICAgICAgICB1cHJ2X21zdHJtX3dyaXRlKG9zLCAodWludDhfdCopJmlzTnVsbCwgc2l6ZW9mKGlzTnVsbCkpOwoKICAgICAgICBpZiAoIWlzTnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGNvbGxhdG9yLT5kYXRhLT5zdHJlYW1PdXQob3MpOwogICAgICAgIH0KCiAgICAgICAgLy8gV3JpdGUgb3V0IHRoZSBJRCB0byBpbmRpY2F0ZSB0aGUgZW5kCiAgICAgICAgdXBydl9tc3RybV93cml0ZShvcywgKHVpbnQ4X3QgKikmaWQsIHNpemVvZihpZCkpOwogICAgfQp9Cgp2b2lkIFJ1bGVCYXNlZENvbGxhdG9yU3RyZWFtZXI6OnN0cmVhbUluKFJ1bGVCYXNlZENvbGxhdG9yKiBjb2xsYXRvciwgRmlsZVN0cmVhbSogaXMpCnsKICAgIGlmICghVF9GaWxlU3RyZWFtX2Vycm9yKGlzKSkKICAgIHsKICAgICAgICAvLyBDaGVjayB0aGF0IHRoaXMgaXMgdGhlIGNvcnJlY3QgZmlsZSB0eXBlCiAgICAgICAgaW50MTZfdCBpZDsKCiAgICAgICAgVF9GaWxlU3RyZWFtX3JlYWQoaXMsICZpZCwgc2l6ZW9mKGlkKSk7CiAgICAgICAgaWYgKGlkICE9IGNvbGxhdG9yLT5GSUxFSUQpCiAgICAgICAgewogICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRoZSByaWdodCB0eXBlIG9mIGZpbGUuICBNYXJrIHRoZSBpb3MKICAgICAgICAgICAgLy8gYXMgZmFpbGluZyBhbmQgcmV0dXJuLgogICAgICAgICAgICBUX0ZpbGVTdHJlYW1fc2V0RXJyb3IoaXMpOyAvLyBmb3JjZSB0aGUgc3RyZWFtIHRvIHNldCBpdHMgZXJyb3IgZmxhZwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICAvLyBTdHJlYW0gaW4gbGFyZ2Ugb2JqZWN0cwogICAgICAgIGNoYXIgaXNOdWxsOwoKICAgICAgICBUX0ZpbGVTdHJlYW1fcmVhZChpcywgJmlzTnVsbCwgc2l6ZW9mKGlzTnVsbCkpOwogICAgICAgIGlmIChpc051bGwpCiAgICAgICAgewogICAgICAgICAgICBkZWxldGUgY29sbGF0b3ItPmRhdGE7CiAgICAgICAgICAgIGNvbGxhdG9yLT5kYXRhID0gTlVMTDsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGNvbGxhdG9yLT5kYXRhID09IE5VTEwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGNvbGxhdG9yLT5kYXRhID0gbmV3IFRhYmxlQ29sbGF0aW9uRGF0YTsKICAgICAgICAgICAgfQogICAgICAgICAgICAKICAgICAgICAgICAgY29sbGF0b3ItPmRhdGEtPnN0cmVhbUluKGlzKTsKICAgICAgICAgICAgaWYgKGNvbGxhdG9yLT5kYXRhLT5pc0JvZ3VzKCkpIHsKICAgICAgICAgICAgICAgIFRfRmlsZVN0cmVhbV9zZXRFcnJvcihpcyk7IC8vIGZvcmNlIHRoZSBzdHJlYW0gdG8gc2V0IGl0cyBlcnJvciBmbGFnCiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIFZlcmlmeSB0aGF0IHRoZSBlbmQgbWFya2VyIGlzIHByZXNlbnQKICAgICAgICBUX0ZpbGVTdHJlYW1fcmVhZChpcywgJmlkLCBzaXplb2YoaWQpKTsKICAgICAgICBpZiAoaWQgIT0gY29sbGF0b3ItPkZJTEVJRCkKICAgICAgICB7CiAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGhlIHJpZ2h0IHR5cGUgb2YgZmlsZS4gIE1hcmsgdGhlIGlvcwogICAgICAgICAgICAvLyBhcyBmYWlsaW5nIGFuZCByZXR1cm4uCiAgICAgICAgICAgIFRfRmlsZVN0cmVhbV9zZXRFcnJvcihpcyk7IC8vIGZvcmNlIHRoZSBzdHJlYW0gdG8gc2V0IGl0cyBlcnJvciBmbGFnCiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIC8vIFJlc2V0IG90aGVyIGRhdGEgbWVtYmVycwogICAgICAgIGNvbGxhdG9yLT5pc092ZXJJZ25vcmUgPSBGQUxTRTsKICAgICAgICBjb2xsYXRvci0+bGFzdENoYXIgPSAwOwogICAgICAgIGRlbGV0ZSBjb2xsYXRvci0+bVBhdHRlcm47CiAgICAgICAgY29sbGF0b3ItPm1QYXR0ZXJuID0gMDsKICAgICAgICBjb2xsYXRvci0+a2V5LnJlbW92ZSgpOwogICAgICAgIGNvbGxhdG9yLT5kYXRhSXNPd25lZCA9IFRSVUU7CiAgICB9Cn0KCnZvaWQgUnVsZUJhc2VkQ29sbGF0b3JTdHJlYW1lcjo6c3RyZWFtT3V0KGNvbnN0IFJ1bGVCYXNlZENvbGxhdG9yKiBjb2xsYXRvciwgRmlsZVN0cmVhbSogb3MpCnsKICAgIGlmICghVF9GaWxlU3RyZWFtX2Vycm9yKG9zKSkKICAgIHsKICAgICAgICAvLyBXZSB1c2UgYSAxNi1iaXQgSUQgY29kZSB0byBpZGVudGlmeSB0aGlzIGZpbGUuCiAgICAgICAgaW50MTZfdCBpZCA9IGNvbGxhdG9yLT5GSUxFSUQ7CiAgICAgICAgVF9GaWxlU3RyZWFtX3dyaXRlKG9zLCAmaWQsIHNpemVvZihpZCkpOwoKICAgICAgICAvLyBTdHJlYW0gb3V0IHRoZSBkYXRhCiAgICAgICAgY2hhciBpc051bGw7CiAgICAgICAgaXNOdWxsID0gKGNvbGxhdG9yLT5kYXRhID09IDApOwogICAgICAgIFRfRmlsZVN0cmVhbV93cml0ZShvcywgJmlzTnVsbCwgc2l6ZW9mKGlzTnVsbCkpOwoKICAgICAgICBpZiAoIWlzTnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGNvbGxhdG9yLT5kYXRhLT5zdHJlYW1PdXQob3MpOwogICAgICAgIH0KCiAgICAgICAgLy8gV3JpdGUgb3V0IHRoZSBJRCB0byBpbmRpY2F0ZSB0aGUgZW5kCiAgICAgICAgVF9GaWxlU3RyZWFtX3dyaXRlKG9zLCAmaWQsIHNpemVvZihpZCkpOwogICAgfQp9CgpVQm9vbCBSdWxlQmFzZWRDb2xsYXRvcjo6d3JpdGVUb0ZpbGUoY29uc3QgY2hhciogZmlsZU5hbWUpIGNvbnN0CnsKICAgIEZpbGVTdHJlYW0qIG9mcyA9IFRfRmlsZVN0cmVhbV9vcGVuKGZpbGVOYW1lLCAid2IiKTsKICAgIGlmIChvZnMgIT0gMCkKICAgIHsKICAgICAgICBSdWxlQmFzZWRDb2xsYXRvclN0cmVhbWVyOjpzdHJlYW1PdXQodGhpcywgb2ZzKTsKICAgIH0KCiNpZmRlZiBDT0xMREVCVUcKICAgIGZwcmludGYoc3RkZXJyLCAiYmluYXJ5IHdyaXRlICVzIHNpemUgJWQgJXNcbiIsIGZpbGVOYW1lLCBUX0ZpbGVTdHJlYW1fc2l6ZShvZnMpLAogICAgICAgICghVF9GaWxlU3RyZWFtX2Vycm9yKG9mcykgPyAiLCBPSyIgOiAiLCBGQUlMIikpOwojZW5kaWYKCiAgICBVQm9vbCBlcnIgPSBUX0ZpbGVTdHJlYW1fZXJyb3Iob2ZzKSA9PSAwOwoKICAgIFRfRmlsZVN0cmVhbV9jbG9zZShvZnMpOwogICAgcmV0dXJuIGVycjsKfQovKgpVQm9vbCBSdWxlQmFzZWRDb2xsYXRvcjo6cHJlcGFyZUZvckJ1bmRsZSgpIGNvbnN0CnsKICAgIFVNZW1vcnlTdHJlYW0qIG9mcyA9IHVwcnZfbXN0cm1fb3Blbk5ldygwKTsKICAgIGlmIChvZnMgIT0gMCkKICAgIHsKICAgICAgICBSdWxlQmFzZWRDb2xsYXRvclN0cmVhbWVyOjpzdHJlYW1PdXQodGhpcywgb2ZzKTsKICAgIH0KCiNpZmRlZiBDT0xMREVCVUcKICAgIGZwcmludGYoc3RkZXJyLCAiYmluYXJ5IHdyaXRlICVzIHNpemUgJWQgJXNcbiIsIGZpbGVOYW1lLCBUX0ZpbGVTdHJlYW1fc2l6ZShvZnMpLAogICAgICAgICghVF9GaWxlU3RyZWFtX2Vycm9yKG9mcykgPyAiLCBPSyIgOiAiLCBGQUlMIikpOwojZW5kaWYKCiAgICBVQm9vbCBlcnIgPSB1cHJ2X21zdHJtX2Vycm9yKG9mcykgPT0gMDsKCiAgICB1cHJ2X21zdHJtX2Nsb3NlKG9mcyk7CgogICAgcmV0dXJuIGVycjsKfQoqLwoKdm9pZCBSdWxlQmFzZWRDb2xsYXRvcjo6YWRkVG9DYWNoZShjb25zdCBVbmljb2RlU3RyaW5nJiBrZXkpCnsKICAgIC8vIFRoaXMgbWV0aG9kIGRvZXNuJ3QgYWRkIHRoZSBSdWxlQmFzZWRDb2xsYXRvciBpdHNlbGYgdG8gdGhlIGNhY2hlLiAgSW5zdGVhZCwKICAgIC8vIGl0IGFkZHMgdGhlIGdpdmVuIFJ1bGVCYXNlZENvbGxhdG9yJ3MgZGF0YSBvYmplY3QgdG8gdGhlIFRhYmxlQ29sbGF0aW9uRGF0YQogICAgLy8gY2FjaGUsIGFuZCBtYXJrcyBpdCBhcyBub24tb3duZWQgaW4gdGhlIGdpdmVuIFJ1bGVCYXNlZENvbGxhdG9yIG9iamVjdC4KICAgIFRhYmxlQ29sbGF0aW9uRGF0YTo6YWRkVG9DYWNoZShrZXksIGRhdGEpOwogICAgZGF0YUlzT3duZWQgPSBGQUxTRTsKfQoKdm9pZApSdWxlQmFzZWRDb2xsYXRvcjo6Y29uc3RydWN0RnJvbUNhY2hlKGNvbnN0IFVuaWNvZGVTdHJpbmcmIGtleSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIC8vIEF0dGVtcHQgdG8gY29uc3RydWN0IHRoaXMgUnVsZUJhc2VkQ29sbGF0b3Igb2JqZWN0IGZyb20gY2FjaGVkIFRhYmxlQ29sbGF0aW9uRGF0YS4KICAgIC8vIElmIG5vIHN1Y2ggZGF0YSBpcyBpbiB0aGUgY2FjaGUsIHJldHVybiBmYWxzZS4KICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkgcmV0dXJuOwogICAgaWYgKGRhdGFJc093bmVkKQogICAgewogICAgICAgIGRlbGV0ZSBkYXRhOwogICAgICAgIGRhdGEgPSBOVUxMOwogICAgfQoKICAgIGlzT3Zlcklnbm9yZSA9IEZBTFNFOwogICAgbGFzdENoYXIgPSAwOwogICAgbVBhdHRlcm4gPSAwOwogICAgc2V0U3RyZW5ndGgoQ29sbGF0b3I6OlRFUlRJQVJZKTsKCiAgICBkYXRhSXNPd25lZCA9IEZBTFNFOwogICAgZGF0YSA9IFRhYmxlQ29sbGF0aW9uRGF0YTo6ZmluZEluQ2FjaGUoa2V5KTsKICAgIGlmIChkYXRhID09IE5VTEwpCiAgICB7CiAgICAgICAgc3RhdHVzID0gVV9NSVNTSU5HX1JFU09VUkNFX0VSUk9SOwogICAgfQp9CgpjaGFyKgpSdWxlQmFzZWRDb2xsYXRvcjo6Y3JlYXRlUGF0aE5hbWUoICBjb25zdCBVbmljb2RlU3RyaW5nJiAgICBwcmVmaXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgVW5pY29kZVN0cmluZyYgICAgbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBVbmljb2RlU3RyaW5nJiAgICBzdWZmaXgpCnsKICAgIC8vIENvbmNhdGVuYXRlIHRocmVlIGVsZW1lbnRzIHRvIGZvcm0gYSBmaWxlIG5hbWUsIGFuZCByZXR1cm4gaXQuCgogICAgVW5pY29kZVN0cmluZyAgIHdvcmtpbmdOYW1lKHByZWZpeCk7CiAgICBpbnQzMl90ICAgICAgICAgc2l6ZTsKICAgIGNoYXIqICAgICAgICAgICByZXR1cm5WYWw7CgogICAgd29ya2luZ05hbWUgKz0gbmFtZTsKICAgIHdvcmtpbmdOYW1lICs9IHN1ZmZpeDsKCiAgICBzaXplID0gd29ya2luZ05hbWUubGVuZ3RoKCk7CiAgICByZXR1cm5WYWwgPSBuZXcgY2hhcltzaXplICsgMV07CiAgICB3b3JraW5nTmFtZS5leHRyYWN0KDAsIHNpemUsIHJldHVyblZhbCwgIiIpOwogICAgcmV0dXJuVmFsW3NpemVdID0gMDsKCiAgICByZXR1cm4gcmV0dXJuVmFsOwp9Cgp2b2lkClJ1bGVCYXNlZENvbGxhdG9yOjpjaG9wTG9jYWxlKFVuaWNvZGVTdHJpbmcmIGxvY2FsZU5hbWUpCnsKICAgIC8vIGNob3BMb2NhbGUgcmVtb3ZlcyB0aGUgZmluYWwgZWxlbWVudCBmcm9tIGEgbG9jYWxlIHN0cmluZy4KICAgIC8vIEZvciBpbnN0YW5jZSwgImRlX0NIIiBiZWNvbWVzICJkZSIsIGFuZCAiZGUiIGJlY29tZXMgIiIuCiAgICAvLyAiIiByZW1haW5zICIiLgoKICAgIGludDMyX3QgICAgIHNpemUgPSBsb2NhbGVOYW1lLmxlbmd0aCgpOwogICAgaW50MzJfdCAgICAgaTsKCiAgICBmb3IgKGkgPSBzaXplIC0gMTsgaSA+IDA7IGktLSkKICAgIHsKICAgICAgICBpZiAobG9jYWxlTmFtZVtpXSA9PSAweDAwNUYpCiAgICAgICAgewogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CgogICAgaWYgKGkgPCAwKQogICAgewogICAgICAgaSA9IDA7CiAgICB9CgogICAgbG9jYWxlTmFtZS5yZW1vdmUoaSwgc2l6ZSAtIGkpOwp9CgoKdWludDhfdCAqClJ1bGVCYXNlZENvbGxhdG9yOjpjbG9uZVJ1bGVEYXRhKGludDMyX3QgJmxlbmd0aCwgVUVycm9yQ29kZSAmc3RhdHVzKQp7CiAgICBVTWVtb3J5U3RyZWFtICptZW1kYXRhID0gMDsKICAgIHVpbnQ4X3QgKmRhdGEgPSAwOwoKICAgIGlmKFVfRkFJTFVSRShzdGF0dXMpKSB7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CgogICAgbWVtZGF0YSA9IHVwcnZfbXN0cm1fb3Blbk5ldygwKTsKCiAgICBpZiAobWVtZGF0YSAhPSAwKSB7CiAgICAgICAgUnVsZUJhc2VkQ29sbGF0b3JTdHJlYW1lcjo6c3RyZWFtT3V0KHRoaXMsIG1lbWRhdGEpOwogICAgfQoKICAgIFVCb29sIGVyciA9IHVwcnZfbXN0cm1fZXJyb3IobWVtZGF0YSkgPT0gMDsKCgogICAgZGF0YSA9ICh1aW50OF90ICopdXBydl9tYWxsb2MobWVtZGF0YS0+ZlBvcyk7CiAgICBpZihkYXRhID09IDApIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgIHVwcnZfbXN0cm1fY2xvc2UobWVtZGF0YSk7CiAgICAgICAgbGVuZ3RoID0gMDsKICAgICAgICByZXR1cm4gMDsKICAgIH0gZWxzZSB7CiAgICAgICAgdXBydl9tZW1jcHkoZGF0YSwgbWVtZGF0YS0+ZlN0YXJ0LCBtZW1kYXRhLT5mUG9zKTsKICAgICAgICBsZW5ndGggPSBtZW1kYXRhLT5mUG9zOwogICAgICAgIHVwcnZfbXN0cm1fY2xvc2UobWVtZGF0YSk7CiAgICAgICAgcmV0dXJuIGRhdGE7CiAgICB9Cn0KCgovL2VvZgo=