Ly8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBAQEAgU1RBUlQgQ09QWVJJR0hUIEBAQAovLwovLyBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lCi8vIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZQovLyBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvbgovLyByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlCi8vIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUKLy8gIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZQovLyB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0Ci8vCi8vICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCi8vCi8vIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywKLy8gc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4KLy8gIkFTIElTIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZCi8vIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZQovLyBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zCi8vIHVuZGVyIHRoZSBMaWNlbnNlLgovLwovLyBAQEAgRU5EIENPUFlSSUdIVCBAQEAKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8KLy8gRmlsZTogICAgICAgICBNYXRjaE91dHB1dC5jcHAKLy8gRGVzY3JpcHRpb246ICAKLy8gICAgICAgICAgICAgICAKLy8gICAgICAgICAgICAgICAKLy8gICAgICAgICAgICAgICAKLy8KLy8gQ3JlYXRlZDogICAgICAwOC8yOC8wOAovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoKI2luY2x1ZGUgIlFtc01WRGV0YWlscy5oIgojaW5jbHVkZSAiUW1zTVZDYW5kaWRhdGUuaCIKI2luY2x1ZGUgIlFtc01hdGNoVGVzdC5oIgojaW5jbHVkZSAiUmFuZ2UuaCIKCgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyAgQ2xhc3MgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0KLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KClJld3JpdGVJbnN0cnVjdGlvbnNJdGVtOjpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShjb25zdCBRUkVsZW1lbnRQdHIgIHF1ZXJ5RWxlbWVudCwKCQkJCQkJIGNvbnN0IFFSRWxlbWVudFB0ciAgbXZFbGVtZW50LAoJCQkJCQkgUmVzdWx0Q29kZQkgICAgICByZXN1bHRDb2RlLAoJCQkJCQkgUmVzdWx0U3RhdHVzCSAgICAgIHN0YXR1cywKCQkJCQkJIEFERF9NRU1DSEVDS19BUkdTX0RFRihDb2xsSGVhcCogaGVhcCkpCiAgOiBOQUludHJ1c2l2ZVNoYXJlZFB0ck9iamVjdChBRERfTUVNQ0hFQ0tfQVJHU19QQVNTKGhlYXApKQogICAgLHF1ZXJ5RWxlbWVudF8ocXVlcnlFbGVtZW50KQogICAgLG12RWxlbWVudF8obXZFbGVtZW50KQogICAgLHJlc3VsdENvZGVfKHJlc3VsdENvZGUpCiAgICAsc2Vjb25kYXJ5UmVzdWx0Q29kZV8oUkNfSU5WQUxJRF9SRVNVTFQpCiAgICAsc3RhdHVzXyhzdGF0dXMpCiAgICAsc3ViRWxlbWVudHNfKG5ldyAoaGVhcCkgY29tcG9zaXRlTWF0Y2hpbmdSZXN1bHRzKEFERF9NRU1DSEVDS19BUkdTX1BBU1MoaGVhcCkpKQogICAgLGV4dHJhSHViVGFibGVzXyhoZWFwKQogICAgLGJhY2tKb2luVGFibGVzXyhoZWFwKQp7Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKUmV3cml0ZUluc3RydWN0aW9uc0l0ZW06OlJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGNvbnN0IFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtJiBvdGhlciwKCQkJCQkJIEFERF9NRU1DSEVDS19BUkdTX0RFRihDb2xsSGVhcCogaGVhcCkpCiAgOiBOQUludHJ1c2l2ZVNoYXJlZFB0ck9iamVjdChBRERfTUVNQ0hFQ0tfQVJHU19QQVNTKGhlYXApKQogICAgLHF1ZXJ5RWxlbWVudF8ob3RoZXIucXVlcnlFbGVtZW50XykKICAgICxtdkVsZW1lbnRfKG90aGVyLm12RWxlbWVudF8pCiAgICAscmVzdWx0Q29kZV8ob3RoZXIucmVzdWx0Q29kZV8pCiAgICAsc2Vjb25kYXJ5UmVzdWx0Q29kZV8ob3RoZXIuc2Vjb25kYXJ5UmVzdWx0Q29kZV8pCiAgICAsc3RhdHVzXyhvdGhlci5zdGF0dXNfKQogICAgLHN1YkVsZW1lbnRzXyhuZXcgKGhlYXApIGNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0cyhBRERfTUVNQ0hFQ0tfQVJHU19QQVNTKGhlYXApKSkKICAgICxleHRyYUh1YlRhYmxlc18oaGVhcCkKICAgICxiYWNrSm9pblRhYmxlc18oaGVhcCkKewogIGV4dHJhSHViVGFibGVzXy5pbnNlcnQob3RoZXIuZXh0cmFIdWJUYWJsZXNfKTsKICBiYWNrSm9pblRhYmxlc18uaW5zZXJ0KG90aGVyLmJhY2tKb2luVGFibGVzXyk7CiAgYWRkU3ViRWxlbWVudHMob3RoZXIuc3ViRWxlbWVudHNfKTsKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbTo6flJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKCkKewogIGRlbGV0ZVB0cihzdWJFbGVtZW50c18pOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCnZvaWQgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW06OmFkZFN1YkVsZW1lbnQoUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgc3ViRWxlbWVudCkKeyAKICAvLyBDb2xsZWN0IHRoZSBzcGVjaWFsIHRhYmxlcyBhdCB0aGUgdG9wLgogIGV4dHJhSHViVGFibGVzXy5pbnNlcnQoc3ViRWxlbWVudC0+Z2V0RXh0cmFIdWJUYWJsZXMoKSk7CiAgYmFja0pvaW5UYWJsZXNfLmluc2VydChzdWJFbGVtZW50LT5nZXRCYWNrSm9pblRhYmxlcygpKTsKCiAgLy8gQWRkIHRoZSByZXdyaXRlIGluc3RydWN0aW9ucyBpdGVtIHRvIHRoZSBsaXN0LgogIHN1YkVsZW1lbnRzXy0+aW5zZXJ0KHN1YkVsZW1lbnQpOyAKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgp2b2lkIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtOjphZGRTdWJFbGVtZW50cyhjb25zdCBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbUxpc3QmIHN1YkVsZW1lbnRzLCAKCQkJCQkgICAgIE5BQm9vbGVhbiBpc1NwZWNpYWwpCnsgCiAgaWYgKHN1YkVsZW1lbnRzLmVudHJpZXMoKSA9PSAwKQogICAgcmV0dXJuOwoKICBpZiAoaXNTcGVjaWFsKQogIHsKICAgIC8vIFRoZXJlIGFyZSBiYWNram9pbiBvciBleHRyYSBodWIgdGFibGVzIGludm9sdmVkIC0gaW5zZXJ0IG9uZSBieSBvbmUuCiAgICBDb2xsSW5kZXggbWF4RW50cmllcyA9IHN1YkVsZW1lbnRzLmVudHJpZXMoKTsKICAgIGZvciAoQ29sbEluZGV4IGk9MDsgaTxtYXhFbnRyaWVzOyBpKyspCiAgICAgIGFkZFN1YkVsZW1lbnQoc3ViRWxlbWVudHNbaV0pOwogIH0KICBlbHNlCiAgewogICAgLy8gTm8gc3BlY2lhbCB0YWJsZXMgaW52b2x2ZWQgLSBqdXN0IGluc2VydCB0aGUgbGlzdC4KICAgIHN1YkVsZW1lbnRzXy0+aW5zZXJ0KHN1YkVsZW1lbnRzKTsgCiAgfQp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCnZvaWQgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW06OmFkZFN1YkVsZW1lbnRzKGNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0c1B0ciBvdGhlcikKewogIGFkZFN1YkVsZW1lbnRzKG90aGVyLT5wcm92aWRlZElucHV0c18sIEZBTFNFKTsKICBhZGRTdWJFbGVtZW50cyhvdGhlci0+bm90UHJvdmlkZWRJbnB1dHNfLCBGQUxTRSk7CiAgYWRkU3ViRWxlbWVudHMob3RoZXItPm91dHNpZGVJbnB1dHNfLCBGQUxTRSk7CiAgYWRkU3ViRWxlbWVudHMob3RoZXItPmluZGlyZWN0SW5wdXRzXywgRkFMU0UpOwogIGFkZFN1YkVsZW1lbnRzKG90aGVyLT5leHRyYWh1YklucHV0c18sIFRSVUUpOwogIGFkZFN1YkVsZW1lbnRzKG90aGVyLT5iYWNrSm9pbklucHV0c18sIFRSVUUpOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCmNvbnN0IGNoYXIqIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtOjpnZXRSZXN1bHRTdHJpbmcoUmVzdWx0Q29kZSByYykKewogIHN3aXRjaCAocmMpCiAgewogICAgY2FzZSBSQ19PVVRTSURFCSAgICA6IHJldHVybiAiT3V0c2lkZSI7CiAgICBjYXNlIFJDX1BST1ZJREVECSAgICA6IHJldHVybiAiUHJvdmlkZWQiOwogICAgY2FzZSBSQ19OT1RQUk9WSURFRAkgICAgOiByZXR1cm4gIk5vdFByb3ZpZGVkIjsKICAgIGNhc2UgUkNfUkVKRUNUCSAgICA6IHJldHVybiAiUmVqZWN0IjsKICAgIGNhc2UgUkNfQ09OVElOVUUJICAgIDogcmV0dXJuICJDb250aW51ZSI7CiAgICBjYXNlIFJDX0VYVFJBSFVCCSAgICA6IHJldHVybiAiRXh0cmFIdWIiOwogICAgY2FzZSBSQ19CQUNLSk9JTgkgICAgOiByZXR1cm4gIkJhY2tKb2luIjsKICAgIGNhc2UgUkNfSU5ESVJFQ1QJICAgIDogcmV0dXJuICJJbmRpcmVjdCI7CiAgICBjYXNlIFJDX0lOUFVUU19QUk9WSURFRCA6IHJldHVybiAiSW5wdXRzUHJvdmlkZWQiOwogICAgY2FzZSBSQ19FWFBSX1JFV1JJVEUgICAgOiByZXR1cm4gIkV4cHJlc3Npb24gUmV3cml0ZSI7CiAgICBjYXNlIFJDX01BVENIX1JBTkdFICAgICA6IHJldHVybiAiUmFuZ2VTcGVjIGNvbXBhcmlzb24iOwogICAgY2FzZSBSQ19TS0lQX01FICAgICAgICAgOiByZXR1cm4gIlNraXAgbWUiOwogICAgY2FzZSBSQ19ST0xMVVAJICAgIDogcmV0dXJuICJSb2xsdXAiOwogICAgY2FzZSBSQ19ST0xMVVBfRVhQUgkgICAgOiByZXR1cm4gIlJvbGx1cCBleHByZXNzaW9uIjsKICAgIGNhc2UgUkNfQUdHUl9FWFBSICAgICAgIDogcmV0dXJuICJBZ2dyZWdhdGUgZXhwcmVzc2lvbiI7CiAgICBjYXNlIFJDX0lOVkFMSURfUkVTVUxUICA6IHJldHVybiAiSW52YWxpZCByZXN1bHQiOwogICAgZGVmYXVsdAkJICAgIDogcmV0dXJuICJJbnZhbGlkIHJlc3VsdCBjb2RlIjsKICB9Cn0KCmNvbnN0IGNoYXIqIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtOjpnZXRSZXN1bHRTdHJpbmcoKQp7CiAgcmV0dXJuIGdldFJlc3VsdFN0cmluZyhnZXRSZXN1bHRDb2RlKCkpOwp9CgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyAgQ2xhc3MgY29tcG9zaXRlTWF0Y2hpbmdSZXN1bHRzCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCmNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0czo6fmNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0cygpCnsKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8cHJvdmlkZWRJbnB1dHNfLmVudHJpZXMoKTsgaSsrKQogICAgZGVsZXRlUHRyKHByb3ZpZGVkSW5wdXRzX1tpXSk7CiAgcHJvdmlkZWRJbnB1dHNfLmNsZWFyKCk7CgogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxub3RQcm92aWRlZElucHV0c18uZW50cmllcygpOyBpKyspCiAgICBkZWxldGVQdHIobm90UHJvdmlkZWRJbnB1dHNfW2ldKTsKICBub3RQcm92aWRlZElucHV0c18uY2xlYXIoKTsKCiAgZm9yIChDb2xsSW5kZXggaT0wOyBpPG91dHNpZGVJbnB1dHNfLmVudHJpZXMoKTsgaSsrKQogICAgZGVsZXRlUHRyKG91dHNpZGVJbnB1dHNfW2ldKTsKICBvdXRzaWRlSW5wdXRzXy5jbGVhcigpOwoKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8ZXh0cmFodWJJbnB1dHNfLmVudHJpZXMoKTsgaSsrKQogICAgZGVsZXRlUHRyKGV4dHJhaHViSW5wdXRzX1tpXSk7CiAgZXh0cmFodWJJbnB1dHNfLmNsZWFyKCk7CgogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxiYWNrSm9pbklucHV0c18uZW50cmllcygpOyBpKyspCiAgICBkZWxldGVQdHIoYmFja0pvaW5JbnB1dHNfW2ldKTsKICBiYWNrSm9pbklucHV0c18uY2xlYXIoKTsKCiAgZm9yIChDb2xsSW5kZXggaT0wOyBpPGluZGlyZWN0SW5wdXRzXy5lbnRyaWVzKCk7IGkrKykKICAgIGRlbGV0ZVB0cihpbmRpcmVjdElucHV0c19baV0pOwogIGluZGlyZWN0SW5wdXRzXy5jbGVhcigpOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCnZvaWQgY29tcG9zaXRlTWF0Y2hpbmdSZXN1bHRzOjppbnNlcnQoUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgaXRlbSkKewogIHN3aXRjaChpdGVtLT5nZXRSZXN1bHRDb2RlKCkpCiAgewogICAgY2FzZSBSQ19QUk9WSURFRDoKICAgICAgcHJvdmlkZWRJbnB1dHNfLmluc2VydChpdGVtKTsKICAgICAgYnJlYWs7CgogICAgY2FzZSBSQ19OT1RQUk9WSURFRDoKICAgICAgbm90UHJvdmlkZWRJbnB1dHNfLmluc2VydChpdGVtKTsKICAgICAgYnJlYWs7CgogICAgY2FzZSBSQ19PVVRTSURFOgogICAgICBvdXRzaWRlSW5wdXRzXy5pbnNlcnQoaXRlbSk7CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgUkNfRVhUUkFIVUI6CiAgICAgIGV4dHJhaHViSW5wdXRzXy5pbnNlcnQoaXRlbSk7CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgUkNfQkFDS0pPSU46CiAgICAgIGJhY2tKb2luSW5wdXRzXy5pbnNlcnQoaXRlbSk7CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgUkNfSU5ESVJFQ1Q6CiAgICAgIGluZGlyZWN0SW5wdXRzXy5pbnNlcnQoaXRlbSk7CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgUkNfU0tJUF9NRToKICAgICAgYnJlYWs7CgogICAgZGVmYXVsdDoKICAgICAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLCAKICAgICAgICAgICAgICAgICAgICAgICAgRkFMU0UsIFFSTG9naWNFeGNlcHRpb24sIAoJCQkiVW5leHBlY3RlZCByZXR1cm4gY29kZS4iKTsgCiAgfSAvLyBzd2l0Y2gKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgp2b2lkIGNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0czo6aW5zZXJ0KGNvbnN0IFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtTGlzdCYgaXRlbUxpc3QpCnsKICBzd2l0Y2goaXRlbUxpc3RbMF0tPmdldFJlc3VsdENvZGUoKSkKICB7CiAgICBjYXNlIFJDX1BST1ZJREVEOgogICAgICBwcm92aWRlZElucHV0c18uaW5zZXJ0KGl0ZW1MaXN0KTsKICAgICAgYnJlYWs7CgogICAgY2FzZSBSQ19OT1RQUk9WSURFRDoKICAgICAgbm90UHJvdmlkZWRJbnB1dHNfLmluc2VydChpdGVtTGlzdCk7CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgUkNfT1VUU0lERToKICAgICAgb3V0c2lkZUlucHV0c18uaW5zZXJ0KGl0ZW1MaXN0KTsKICAgICAgYnJlYWs7CgogICAgY2FzZSBSQ19FWFRSQUhVQjoKICAgICAgZXh0cmFodWJJbnB1dHNfLmluc2VydChpdGVtTGlzdCk7CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgUkNfQkFDS0pPSU46CiAgICAgIGJhY2tKb2luSW5wdXRzXy5pbnNlcnQoaXRlbUxpc3QpOwogICAgICBicmVhazsKCiAgICBjYXNlIFJDX0lORElSRUNUOgogICAgICBpbmRpcmVjdElucHV0c18uaW5zZXJ0KGl0ZW1MaXN0KTsKICAgICAgYnJlYWs7CgogICAgZGVmYXVsdDoKICAgICAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgICAgICBGQUxTRSwgUVJMb2dpY0V4Y2VwdGlvbiwgCgkJCSJVbmV4cGVjdGVkIHJldHVybiBjb2RlLiIpOyAKICB9IC8vIHN3aXRjaAp9CgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyAgQ2xhc3MgTWF0Y2hUZXN0Ci8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gRGVzdHJ1Y3RvciAtIGRlbGV0ZSB0aGUgcmV3cml0ZSBpbnN0cnVjdGlvblMgTElTVFMuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpNYXRjaFRlc3Q6On5NYXRjaFRlc3QoKQp7CiAgQ29sbEluZGV4IG1heEVudHJpZXMgPSBsaXN0T2ZGaW5hbEluc3RydWN0aW9uc18uZW50cmllcygpOwogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxtYXhFbnRyaWVzOyBpKyspCiAgICBkZWxldGVQdHIobGlzdE9mRmluYWxJbnN0cnVjdGlvbnNfW2ldKTsKICBsaXN0T2ZGaW5hbEluc3RydWN0aW9uc18uY2xlYXIoKTsKCiAgbWF4RW50cmllcyA9IGxpc3RPZlBlbmRpbmdXb3JrXy5lbnRyaWVzKCk7CiAgZm9yIChDb2xsSW5kZXggaj0wOyBqPG1heEVudHJpZXM7IGorKykKICAgIGRlbGV0ZVB0cihsaXN0T2ZQZW5kaW5nV29ya19bal0pOwogIGxpc3RPZlBlbmRpbmdXb3JrXy5jbGVhcigpOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gQWRkIGFuIGl0ZW0gb2YgcmV3cml0ZSBpbnN0cnVjdGlvbnMgdG8gdGhlIGNvbGxlY3Rpb24uCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgp2b2lkIE1hdGNoVGVzdDo6YWRkUmV3cml0ZUluc3RydWN0aW9ucyhSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKSAKewogIFJlc3VsdENvZGUgcmMgPSByZXdyaXRlLT5nZXRSZXN1bHRDb2RlKCk7CiAgaWYgKHJld3JpdGUtPmhhc1NwZWNpYWxTdWJFbGVtZW50KCkpCiAgewogICAgY2FuZGlkYXRlXy0+YWRkRXh0cmFIdWJBbmRCYWNrSm9pblRhYmxlcyhyZXdyaXRlKTsKICB9CgogIGlmIChyZXdyaXRlLT5pc0ZpbmFsKCkpCiAgICBsaXN0T2ZGaW5hbEluc3RydWN0aW9uc18uaW5zZXJ0KHJld3JpdGUpOwogIGVsc2UKICAgIGxpc3RPZlBlbmRpbmdXb3JrXy5pbnNlcnQocmV3cml0ZSk7Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoVGVzdDo6bWF0Y2hQYXNzMigpIAp7CiAgLy8gSXMgdGhlcmUgYW55IHBlbmRpbmcgd29yayBmcm9tIFBhc3MgMT8KICBpZiAoaXNGaW5hbCgpKQogIHsKICAgIC8vIE5vIC0gZ29vZCwgdGhhbiB3ZSBhcmUgZG9uZS4KICAgIHJldHVybiBUUlVFOwogIH0KICBlbHNlCiAgewogICAgLy8gWWVzIC0gdGhlbiBsZXRzIGNoZWNrIHRoZW0gb3V0LgogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1MaXN0JiBwZW5kaW5nTGlzdCA9IGdldExpc3RPZlBlbmRpbmdXb3JrKCk7CiAgICBJbnQzMiBtYXhFbnRyaWVzID0gcGVuZGluZ0xpc3QuZW50cmllcygpOwogICAgZm9yIChJbnQzMiBpPW1heEVudHJpZXMtMTsgaT49MDsgaS0tKQogICAgewogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBwZW5kaW5nID0gcGVuZGluZ0xpc3RbaV07CgogICAgICAvLyBSZW1vdmUgdGhlIGl0ZW0gZnJvbSB0aGUgcGVuZGluZyBsaXN0LgogICAgICAvLyBtYXRjaFBhc3MyT25FbGVtZW50KCkgd2lsbCBhZGQgYW55IG5lZWRlZCBpdGVtcyB0byB0aGUgZmluYWwgbGlzdC4KICAgICAgcGVuZGluZ0xpc3QucmVtb3ZlQXQoaSk7CgogICAgICAvLyBGaXJzdCB2ZXJpZnkgdGhhdCBhbGwgdGhlIGJhY2stam9pbiBhbmQgZXh0cmEtaHViIGNvbHVtbnMgYXJlIEZpbmFsLgogICAgICBpZiAodmVyaWZ5RXh0cmFIdWJBbmRCYWNrSm9pbkNvbHVtbnMocGVuZGluZykgPT0gRkFMU0UpCiAgICAgIHsKCS8vIENhbm5vdCBiZSBwcm92aWRlZCAtIGRpc3F1YWxpZnkgdGhlIE1WLgoJZGVsZXRlUHRyKHBlbmRpbmcpOwoJcmV0dXJuIEZBTFNFOwogICAgICB9CiAgICAgIAogICAgICAvLyBBcmUgdGhlIHJlc3VsdGluZyByZXdyaXRlIGluc3RydWN0aW9ucyBmaW5hbD8KICAgICAgaWYgKHBlbmRpbmctPmlzRmluYWwoKSkKICAgICAgewoJLy8gWWVzIC0gYWRkIHRvIHRoZSBGaW5hbCBsaXN0LgoJYWRkUmV3cml0ZUluc3RydWN0aW9ucyhwZW5kaW5nKTsKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKCS8vIENhbGwgdGhlIHN1Yi1jbGFzcyBzcGVjaWZpYyBtZXRob2QgdG8gaGFuZGxlIHRoZSByZWFsIHdvcmsuCglpZiAobWF0Y2hQYXNzMk9uRWxlbWVudChwZW5kaW5nKSA9PSBGQUxTRSkKCXsKCSAgZGVsZXRlUHRyKHBlbmRpbmcpOwoJICByZXR1cm4gRkFMU0U7Cgl9CiAgICAgIH0KCiAgICAgIC8vZGVsZXRlUHRyKHBlbmRpbmcpOwogICAgfQogIH0KCiAgLy8gQWxsIHRoZSBwZW5kaW5nIHRlc3RzIHBhc3NlZC4KICByZXR1cm4gVFJVRTsKfSAgLy8gTWF0Y2hUZXN0OjptYXRjaFBhc3MyKCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoVGVzdDo6dmVyaWZ5RXh0cmFIdWJBbmRCYWNrSm9pbkNvbHVtbnMoUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcGVuZGluZykKewogIFJlc3VsdENvZGUgcmMgPSBwZW5kaW5nLT5nZXRSZXN1bHRDb2RlKCk7CiAgaWYgKHJjICE9IFJDX0JBQ0tKT0lOICYmCiAgICAgIHJjICE9IFJDX0VYVFJBSFVCICYmCiAgICAgIHBlbmRpbmctPmdldFN1YkVsZW1lbnRzKCktPmJhY2tKb2luSW5wdXRzXy5lbnRyaWVzKCkgPT0gMCAmJgogICAgICBwZW5kaW5nLT5nZXRTdWJFbGVtZW50cygpLT5leHRyYWh1YklucHV0c18uZW50cmllcygpID09IDAgKQogIHsKICAgIC8vIE5vdGhpbmcgdG8gZG8gaGVyZS4KICAgIHJldHVybiBUUlVFOwogIH0KCgogIGlmIChyYyA9PSBSQ19CQUNLSk9JTikKICB7CiAgICAvLyBOb3RoaW5nIG11Y2ggdG8gY2hlY2sgYWJvdXQgQmFjay1Kb2lucy4KICAgIHBlbmRpbmctPnNldFJlc3VsdENvZGUoUkNfTk9UUFJPVklERUQpOwogICAgcGVuZGluZy0+c2V0UmVzdWx0U3RhdHVzKFJTX0ZJTkFMKTsKICB9CiAgaWYgKHJjID09IFJDX0VYVFJBSFVCKQogIHsKICAgIGlmICh2ZXJpZnlFeHRyYUh1YkNvbHVtbihwZW5kaW5nKSA9PSBGQUxTRSkKICAgIHsKICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQogICAgcGVuZGluZy0+c2V0UmVzdWx0Q29kZShSQ19QUk9WSURFRCk7CiAgICBwZW5kaW5nLT5zZXRSZXN1bHRTdGF0dXMoUlNfRklOQUwpOwogIH0KICBlbHNlIGlmIChwZW5kaW5nLT5nZXRBY3R1YWxRdWVyeUVsZW1lbnQoKS0+Z2V0RWxlbWVudFR5cGUoKSA9PSBFVF9FeHByKQogIHsKICAgIC8vIENoZWNrIHRoZSBpbnB1dCBjb2x1bW5zIGZvciBiYWNrIGpvaW5zLgogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1MaXN0JiBiYWNrSm9pbkxpc3QgICAgPSBwZW5kaW5nLT5nZXRTdWJFbGVtZW50cygpLT5iYWNrSm9pbklucHV0c187CiAgICBmb3IgKEludDMyIGk9YmFja0pvaW5MaXN0LmVudHJpZXMoKS0xOyBpPj0wOyBpLS0pCiAgICB7CiAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUgPSBiYWNrSm9pbkxpc3RbaV07CgogICAgICByZXdyaXRlLT5zZXRSZXN1bHRDb2RlKFJDX05PVFBST1ZJREVEKTsKICAgICAgcmV3cml0ZS0+c2V0UmVzdWx0U3RhdHVzKFJTX0ZJTkFMKTsKICAgIH0KCiAgICAvLyBDaGVjayB0aGUgaW5wdXQgY29sdW1ucyBmb3IgZXh0cmEgaHVicy4KICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtTGlzdCYgZXh0cmFIdWJMaXN0ID0gcGVuZGluZy0+Z2V0U3ViRWxlbWVudHMoKS0+ZXh0cmFodWJJbnB1dHNfOwogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1MaXN0JiBwcm92aWRlZExpc3QgPSBwZW5kaW5nLT5nZXRTdWJFbGVtZW50cygpLT5wcm92aWRlZElucHV0c187CiAgICBmb3IgKEludDMyIGo9ZXh0cmFIdWJMaXN0LmVudHJpZXMoKS0xOyBqPj0wOyBqLS0pCiAgICB7CiAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUgPSBleHRyYUh1Ykxpc3Rbal07CiAgICAgIGV4dHJhSHViTGlzdC5yZW1vdmVBdChqKTsKCiAgICAgIGlmICh2ZXJpZnlFeHRyYUh1YkNvbHVtbihyZXdyaXRlKSA9PSBGQUxTRSkKICAgICAgewoJLy8gV2UgaGF2ZSByZW1vdmVkIHJld3JpdGUgZnJvbSBpdHMgbGlzdCwgc28gd2UgbmVlZCB0byBkZWxldGUgaXQgZXhwbGljaXRseS4KCWRlbGV0ZVB0cihyZXdyaXRlKTsKCXJldHVybiBGQUxTRTsKICAgICAgfQogICAgICByZXdyaXRlLT5zZXRSZXN1bHRDb2RlKFJDX1BST1ZJREVEKTsKICAgICAgcmV3cml0ZS0+c2V0UmVzdWx0U3RhdHVzKFJTX0ZJTkFMKTsKCiAgICAgIHByb3ZpZGVkTGlzdC5pbnNlcnQocmV3cml0ZSk7CiAgICB9CgogICAgaWYgKHBlbmRpbmctPmdldFN1YkVsZW1lbnRzKCktPmluZGlyZWN0SW5wdXRzXy5lbnRyaWVzKCkgPT0gMCAmJgogICAgICAgIHBlbmRpbmctPmdldFNlY29uZGFyeVJlc3VsdENvZGUoKSAhPSBSQ19ST0xMVVApCiAgICB7CiAgICAgIC8vIFdlIGhhbmRsZWQgYWxsIHRoZSBlYXN5IGNhc2VzIC0gdGhlIGV4cHJlc3Npb24gaXMgbm93IEZpbmFsLgogICAgICBwZW5kaW5nLT5zZXRSZXN1bHRTdGF0dXMoUlNfRklOQUwpOwogICAgfQogIH0KICBlbHNlIGlmIChwZW5kaW5nLT5nZXRBY3R1YWxRdWVyeUVsZW1lbnQoKS0+Z2V0RWxlbWVudFR5cGUoKSA9PSBFVF9Kb2luUHJlZCkKICB7CiAgICAvLyBDaGVjayB0aGUgaW5wdXQgY29sdW1ucyBmb3IgZXh0cmEtaHVicy4KICAgIGNvbnN0IGNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0c1B0ciBzdWJFbGVtZW50cyA9IHBlbmRpbmctPmdldFN1YkVsZW1lbnRzKCk7CiAgICBOQUJvb2xlYW4gZm91bmRHb29kT25lID0gRkFMU0U7CgogICAgLy8gSWYgd2UgaGF2ZSBhbnkgZXh0cmEtaHViIGNvbHVtbnMsIHVzZSBvaW5lIG9mIHRoZW0uCiAgICBpZiAoc3ViRWxlbWVudHMtPmV4dHJhaHViSW5wdXRzXy5lbnRyaWVzKCkgPiAwKQogICAgewogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbUxpc3QmIGV4dHJhSHViTGlzdCA9IHN1YkVsZW1lbnRzLT5leHRyYWh1YklucHV0c187CgogICAgICBmb3IgKEludDMyIGs9ZXh0cmFIdWJMaXN0LmVudHJpZXMoKS0xOyBrPj0wOyBrLS0pCiAgICAgIHsKICAgICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gZXh0cmFIdWJMaXN0W2tdOwogICAgICAgIGV4dHJhSHViTGlzdC5yZW1vdmVBdChrKTsKCiAgICAgICAgaWYgKGZvdW5kR29vZE9uZSB8fCB2ZXJpZnlFeHRyYUh1YkNvbHVtbihyZXdyaXRlKSA9PSBGQUxTRSkKICAgICAgICB7CgkgIC8vIFdlIGhhdmUgcmVtb3ZlZCByZXdyaXRlIGZyb20gaXRzIGxpc3QsIHNvIHdlIG5lZWQgdG8gZGVsZXRlIGl0IGV4cGxpY2l0bHkuCgkgIGRlbGV0ZVB0cihyZXdyaXRlKTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgIGZvdW5kR29vZE9uZSA9IFRSVUU7CiAgICAgICAgICBwZW5kaW5nLT5zZXRSZXN1bHRDb2RlKFJDX1BST1ZJREVEKTsKICAgICAgICAgIHBlbmRpbmctPnNldFJlc3VsdFN0YXR1cyhSU19GSU5BTCk7CiAgICAgICAgICBwZW5kaW5nLT5zZXRNdkVsZW1lbnQocmV3cml0ZS0+Z2V0TXZFbGVtZW50KCkpOwogICAgICAgIH0KICAgICAgfSAvLyBmb3IgawogICAgfSAvLyBpZiBleHRyYWh1YgoKICAgIC8vIENoZWNrIHRoZSBpbnB1dCBjb2x1bW5zIGZvciBiYWNrIGpvaW5zLgogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1MaXN0JiBiYWNrSm9pbkxpc3QgICAgPSBwZW5kaW5nLT5nZXRTdWJFbGVtZW50cygpLT5iYWNrSm9pbklucHV0c187CiAgICBOQUJvb2xlYW4gaGFzQmFja0pvaW5zID0gYmFja0pvaW5MaXN0LmVudHJpZXMoKSA+IDA7CgogICAgLy8vLyBEZWxldGUgdGhlIHN1Yi1lbGVtZW50cyBpbiB0aGUgYmFjay1qb2luIGxpc3QuCiAgICAvL2ZvciAoaW50IGw9YmFja0pvaW5MaXN0LmVudHJpZXMoKS0xOyBsPj0wOyBsLS0pCiAgICAvL3sKICAgIC8vICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gYmFja0pvaW5MaXN0W2xdOwogICAgLy8gIGJhY2tKb2luTGlzdC5yZW1vdmVBdChsKTsKICAgIC8vICBkZWxldGVQdHIocmV3cml0ZSk7CiAgICAvL30KCiAgICBpZiAoIWZvdW5kR29vZE9uZSkKICAgICAgaWYgKCFoYXNCYWNrSm9pbnMpCiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgICBlbHNlCiAgICAgIHsKICAgICAgICBwZW5kaW5nLT5zZXRSZXN1bHRDb2RlKFJDX05PVFBST1ZJREVEKTsKICAgICAgICBwZW5kaW5nLT5zZXRTZWNvbmRhcnlSZXN1bHRDb2RlKFJDX0JBQ0tKT0lOKTsKICAgICAgICBwZW5kaW5nLT5zZXRSZXN1bHRTdGF0dXMoUlNfRklOQUwpOwogICAgICB9CiAgfQoKICByZXR1cm4gVFJVRTsKfSAgLy8gdmVyaWZ5RXh0cmFIdWJBbmRCYWNrSm9pbkNvbHVtbnMoKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIEZvciBleHRyYSBodWIgdGFibGVzLCB3ZSBub3cga25vdyB0aGUgdGFibGUgaXMgbWF0Y2hlZCBPSywKLy8gYnV0IHdlIG5lZWQgdG8gdmVyaWZ5IHRoZSBjb2x1bW4gaXMgUHJvdmlkZWQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hUZXN0Ojp2ZXJpZnlFeHRyYUh1YkNvbHVtbihSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBwZW5kaW5nKQp7CiAgUVJPdXRwdXRQdHIgbXZDb2wgPSBOVUxMOwogIGNvbnN0IFFSQ29sdW1uUHRyIHF1ZXJ5Q29sID0gcGVuZGluZy0+Z2V0QWN0dWFsUXVlcnlFbGVtZW50KCktPmRvd25DYXN0VG9RUkNvbHVtbigpOwogIGlmIChpc1Byb3ZpZGVkQ29sdW1uKHF1ZXJ5Q29sLCBtdkNvbCkgPT0gRkFMU0UpCiAgewogICAgLy8gVGhlIGNvbHVtbiBpcyBub3QgUHJvdmlkZWQsIHNvIGRpc3F1YWxpZnkgdGhlIE1WLgogICAgY29uc3QgTkFTdHJpbmcmIGNvbE5hbWUgPSBxdWVyeUNvbC0+Z2V0RnVsbHlRdWFsaWZpZWRDb2x1bW5OYW1lKCk7CiAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoImV4dHJhLWh1YiBjb2x1bW4gJXMgY2Fubm90IGJlIHByb3ZpZGVkLiIsIGNvbE5hbWUpOwogICAgcmV0dXJuIEZBTFNFOwogIH0KICBwZW5kaW5nLT5zZXRSZXN1bHRDb2RlKFJDX1BST1ZJREVEKTsKICBwZW5kaW5nLT5zZXRNdkVsZW1lbnQobXZDb2wpOwogIHBlbmRpbmctPnNldFJlc3VsdFN0YXR1cyhSU19GSU5BTCk7CgogIHJldHVybiBUUlVFOwp9ICAvLyBNYXRjaFRlc3Q6OnZlcmlmeUV4dHJhSHViQ29sdW1uKCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBBIGdlbmVyaWMgbWV0aG9kIGZvciBnZW5lcmF0aW5nIHRoZSByZXN1bHQgZGVzY3JpcHRvciBlbGVtZW50cy4KLy8gVGhlIHNwZWNpZmljIGRldGFpbHMgYXJlIGltcGxlbWVudGVkIGJ5IHN1Yi1jbGFzc2VzLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoVGVzdDo6Z2VuZXJhdGVEZXNjcmlwdG9yKFFSQ2FuZGlkYXRlUHRyIHJlc3VsdERlc2MpCnsKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbUxpc3QmIHJld3JpdGVMaXN0ID0gZ2V0TGlzdE9mRmluYWxJbnN0cnVjdGlvbnMoKTsKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8cmV3cml0ZUxpc3QuZW50cmllcygpOyBpKyspCiAgewogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IHJld3JpdGVMaXN0W2ldOwoKICAgIHN3aXRjaCAocmV3cml0ZS0+Z2V0UmVzdWx0Q29kZSgpKQogICAgewogICAgICBjYXNlIFJDX1BST1ZJREVEOgoJaWYgKGdlbmVyYXRlUHJvdmlkZWRFbGVtZW50KHJlc3VsdERlc2MsIHJld3JpdGUpID09IEZBTFNFKQoJICByZXR1cm4gRkFMU0U7CglicmVhazsKCiAgICAgIGNhc2UgUkNfTk9UUFJPVklERUQ6CglpZiAoZ2VuZXJhdGVOb3RQcm92aWRlZEVsZW1lbnQocmVzdWx0RGVzYywgcmV3cml0ZSkgPT0gRkFMU0UpCgkgIHJldHVybiBGQUxTRTsKCWJyZWFrOwoKICAgICAgY2FzZSBSQ19PVVRTSURFOgoJLy8gTm8gbmVlZCB0byBzcGVjaWZ5IE91dHNpZGUgZWxlbWVudHMgaW4gdGhlIHJlc3VsdCBkZXNjcmlwdG9yLgoJLy9pZiAoZ2VuZXJhdGVPdXRzaWRlRWxlbWVudChyZXN1bHREZXNjLCByZXdyaXRlKSA9PSBGQUxTRSkKCS8vICByZXR1cm4gRkFMU0U7CglicmVhazsKCiAgICAgIGNhc2UgUkNfU0tJUF9NRToKCWJyZWFrOwoKICAgICAgZGVmYXVsdDoKCS8vIFRoZXNlIGFyZSB0aGUgb25seSByZXN1bHQgY29kZXMgYWxsb3dlZCBmb3IgZmluYWwgcmV3cml0ZSBpbnN0cnVjdGlvbnMuCglhc3NlcnRMb2dBbmRUaHJvdyhDQVRfTUFUQ0hUU1RfTVZERVRBSUxTLCBMTF9NVlFSX0ZBSUwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgRkFMU0UsIFFSTG9naWNFeGNlcHRpb24sIAoJCQkgICJVbmV4cGVjdGVkIHJlc3VsdCBjb2RlIGZvciBhIGZpbmFsIGVsZW1lbnQuIik7IAogICAgfQogIH0KCiAgcmV0dXJuIFRSVUU7Cn0gIC8vIE1hdGNoVGVzdDo6Z2VuZXJhdGVEZXNjcmlwdG9yKCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgTWF0Y2hUZXN0OjptYXRjaENvbHVtbihjb25zdCBRUkNvbHVtblB0ciBjb2xFbGVtLCAKCQkJCQkJICBOQUJvb2xlYW4JICAgIGZyb21FeHByLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BQm9vbGVhbiAgICAgICAgIGlzQW5FcXVhbGl0eVNldCkgCnsKICBpZiAoaXNBbkVxdWFsaXR5U2V0KQogICAgcmV0dXJuIG1hdGNoU2luZ2xlQ29sdW1uKGNvbEVsZW0sIGZyb21FeHByKTsgLy8gQXZvaWQgcmVjdXJzaW9uLgoKICBpZiAoIWNhbmRpZGF0ZV8tPmdldFF1ZXJ5RGV0YWlscygpLT5pc0Zyb21Kb2luKGNvbEVsZW0pKQogICAgcmV0dXJuIG1hdGNoU2luZ2xlQ29sdW1uKGNvbEVsZW0sIGZyb21FeHByKTsKICBlbHNlIAogIHsKICAgIGNvbnN0IFFSSm9pblByZWRQdHIganAgPSBjYW5kaWRhdGVfLT5nZXRRdWVyeURldGFpbHMoKS0+Z2V0Sm9pblByZWQoY29sRWxlbSk7CiAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gbWF0Y2hFcXVhbGl0eVNldChqcCk7CiAgICBpZiAocmV3cml0ZSkKICAgIHsKICAgICAgLy8gVGhlIHJld3JpdGUgaW5zdHJ1Y3Rpb25zIHNob3VsZCByZWZlcmVuY2UgdGhlIGNvbHVtbiwgbm90IHRoZSBqb2luIHByZWQuCiAgICAgIHJld3JpdGUtPnNldFF1ZXJ5RWxlbWVudChjb2xFbGVtKTsKICAgIH0KICAgIHJldHVybiByZXdyaXRlOwogIH0KfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIE1hdGNoIGEgc2luZ2xlLCBmdWxsIChub3QgcmVmZXJlbmNpbmcpIGNvbHVtbiAoUGFzcyAxKQovLyBUaGUgb3B0aW9ucyBhcmU6Ci8vIC0gT3V0c2lkZQkgIDogVGhlIGNvbHVtbidzIHRhYmxlIGlzIG5vdCBjb3ZlcmVkIGJ5IHRoZSBNVi4KLy8gLSBFeHRyYS1odWIJICA6IFRoZSBjb2x1bW4ncyB0YWJsZSBpcyBpbiB0aGUgTVYncyBleHRyYS1odWIuIFZlcmlmeSBpbiBQYXNzIDIuCi8vIC0gUHJvdmlkZWQJICA6IFRoZSBjb2x1bW4gaXMgcHJvdmlkZWQgYnkgdGhlIE1WCi8vIC0gQmFja0pvaW5hYmxlIDogVGhlIGNvbHVtbidzIHRhYmxlIGlzIGNvdmVyZWQgYnkgdGhlIE1WLCBidXQgdGhlIGNvbHVtbiAKLy8gICAgICAgICAgICAgICAgICBpdHNlbGYgaXMgbm90IHByb3ZpZGVkIGJ5IHRoZSBNViwgaG93ZXZlciwgdGhlIHRhYmxlJ3MKLy8gICAgICAgICAgICAgICAgICBrZXkgY29sdW1ucyBhcmUgcHJvdmlkZWQsIHNvIHdlIGNhbiBnZXQgdGhlIG5lZWRlZCBjb2x1bW4gCi8vICAgICAgICAgICAgICAgICAgYnkgdXNpbmcgYSBiYWNrLWpvaW4uCi8vIC0gSW5kaXJlY3QJICA6IFRoaXMgY29sdW1uIGlzIHVzZWQgYXMgYW4gaW5wdXQgY29sdW1uIHRvIG9uZSBvZiB0aGUgTVYncwovLwkJICAgIG91dHB1dCBleHByZXNzaW9ucy4KLy8gLSBOVUxMCSAgOiBOb25lIG9mIHRoZSBhYm92ZSwgdGhlIGNvbHVtbiBjYW5ub3QgYmUgcHJvdmlkZWQgYnkgdGhlIAovLwkJICAgIE1WIGluIGFueSB3YXkuIERpc3F1YWxpZnkgdGhlIE1WLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgTWF0Y2hUZXN0OjptYXRjaFNpbmdsZUNvbHVtbihjb25zdCBRUkNvbHVtblB0ciBjb2xFbGVtLCAKCQkJCQkJICAgICAgICBOQUJvb2xlYW4JICBmcm9tRXhwcikgCnsKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gTlVMTDsKICBjb25zdCBOQVN0cmluZyogZXh0cmFIdWJJRCA9IE5VTEw7CiAgaWYoaXNPdXRzaWRlQ29sdW1uKGNvbEVsZW0sIGV4dHJhSHViSUQpKQogIHsKICAgIHJld3JpdGUgPSBuZXcoaGVhcF8pIAogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShjb2xFbGVtLCBOVUxMLCBSQ19PVVRTSURFLCBSU19GSU5BTCwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICAgIHJldHVybiByZXdyaXRlOwogIH0gCiAgZWxzZSBpZiAoZXh0cmFIdWJJRCAhPSBOVUxMKQogIHsKICAgIHJld3JpdGUgPSBuZXcoaGVhcF8pIAogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShjb2xFbGVtLCBOVUxMLCBSQ19FWFRSQUhVQiwgUlNfSU5URVJNRURJQVRFLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogICAgcmV3cml0ZS0+YWRkRXh0cmFIdWJUYWJsZShleHRyYUh1YklEKTsKICAgIHJldHVybiByZXdyaXRlOwogIH0KCiAgLy8gSWYgd2UgZ2V0IGhlcmUsIHRoZSBjb2x1bW4ncyB0YWJsZSBpcyBpbiB0aGUgTVYgaHViLgogIFFST3V0cHV0UHRyIG12Q29sID0gTlVMTDsKICBpZiAoaXNQcm92aWRlZENvbHVtbihjb2xFbGVtLCBtdkNvbCkpCiAgewogICAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGNvbEVsZW0sIG12Q29sLCBSQ19QUk9WSURFRCwgUlNfRklOQUwsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICByZXR1cm4gcmV3cml0ZTsKICB9CgogIGlmIChpc0JhY2tKb2luYWJsZUNvbHVtbihjb2xFbGVtKSkKICB7CiAgICByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0oY29sRWxlbSwgTlVMTCwgUkNfQkFDS0pPSU4sIFJTX0lOVEVSTUVESUFURSwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICAgIHJld3JpdGUtPmFkZEJhY2tKb2luVGFibGUoJmNvbEVsZW0tPmdldFRhYmxlSUQoKSk7CiAgICByZXdyaXRlLT5zZXRTZWNvbmRhcnlSZXN1bHRDb2RlKFJDX0JBQ0tKT0lOKTsKICAgIHJldHVybiByZXdyaXRlOwogIH0KCiAgaWYgKGZyb21FeHByKQogIHsKICAgIHJld3JpdGUgPSBpc0luZGlyZWN0Q29sdW1uKGNvbEVsZW0pOwogICAgaWYgKHJld3JpdGUgIT0gTlVMTCkKICAgICAgcmV0dXJuIHJld3JpdGU7CiAgICAvLyBJZiBub3QgSW5kaXJlY3QsIGZhbGwgdGhyb3VnaCB0byBmYWlsdXJlLgogIH0KCiAgLy8gVGhlIGNvbHVtbiBjYW5ub3QgYmUgcHJvdmlkZWQgYnkgdGhlIE1WLCBzbyBkaXNxdWFsaWZ5IHRoZSBNVi4KICBjb25zdCBOQVN0cmluZyYgY29sTmFtZSA9IGNvbEVsZW0tPmdldEZ1bGx5UXVhbGlmaWVkQ29sdW1uTmFtZSgpOwogIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgiY29sdW1uICVzIGNhbm5vdCBiZSBwcm92aWRlZC4iLCBjb2xOYW1lKTsKCiAgcmV0dXJuIE5VTEw7Cn0gIC8vIE1hdGNoVGVzdDo6bWF0Y2hDb2x1bW4oKQoKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBDaGVjayBpZiB0aGlzIGNvbHVtbiBvZiB0aGUgcXVlcnkgZGVzY3JpcHRvciBpcyBhbiAiT3V0c2lkZSIgY29sdW1uLAovLyB3aGljaCBtZWFucyB0aGF0IGl0cyBhIGNvbHVtbiBvZiBhIHRhYmxlIHRoYXQgaXMgbm90IGNvdmVyZWQgYnkgdGhlIE1WLgovLyAxLiBJZiB0aGUgY29sdW1uJ3MgdGFibGUgaXMgY292ZXJlZCBieSB0aGUgTVZNZW1vIHN1YmdyYXBoLCBpdHMgaW4gdGhlIE1WIAovLyAgICBodWIsIHNvIGl0cyBkZWZpbml0bHkgbm90IGFuIE91dHNpZGUgY29sdW1uLgovLyAyLiBJZiB0aGUgY29sdW1uJ3MgdGFibGUgaXMgbm90IGNvdmVyZWQgYnkgdGhlIGVudGlyZSBNViwgaXRzIGRlZmluaXRseSBPdXRzaWRlLgovLyAzLiBPdGhlcndpc2UsIGl0IGlzIGNvdmVyZWQgYnkgdGhlIE1WJ3MgZXh0cmEtaHViIHRhYmxlcywgYW5kIHdlIGRvbid0IGtub3cgCi8vICAgIHlldCBpZiB3ZSBjYW4gdXNlIHRob3NlIChtYXliZSB0aGUgam9pbiBwcmVkcyBkb24ndCBtYXRjaCkuIFNvIHJldHVybgovLyAgICBUUlVFIGZvciBub3csIGJ1dCBhbHNvIHJldHVybiB0aGUgSUQgb2YgdGhlIGV4dHJhIGh1YiB0YWJsZS4gVGhpcyB3aWxsIGJlCi8vICAgIGNoZWNrZWQgbGF0ZXIsIGFuZCBpZiBpdCBkb2VzIG5vdCBtYXRjaCwgdGhlIE1WIGNhbmRpZGF0ZSB3aWxsIGJlIGRpc3F1YWxpZmllZC4KLy8gVGhlIHJlc3VsdHMgYXJlIGNhY2hlZCBpbiB0aGUgTVZDYW5kaWRhdGUgb2JqZWN0LgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoVGVzdDo6aXNPdXRzaWRlQ29sdW1uKGNvbnN0IFFSQ29sdW1uUHRyIGNvbEVsZW0sIGNvbnN0IE5BU3RyaW5nKiYgZXh0cmFIdWJJRCkKewogIGNvbnN0IERlc2NyaXB0b3JEZXRhaWxzUHRyIHF1ZXJ5RGV0YWlscyA9IGNhbmRpZGF0ZV8tPmdldFF1ZXJ5RGV0YWlscygpOwogIGNvbnN0IE1WRGV0YWlsc1B0ciBtdkRldGFpbHMgPSBjYW5kaWRhdGVfLT5nZXRNdkRldGFpbHMoKTsKICBRUkpvaW5TdWJHcmFwaFB0ciBzdWJHcmFwaCA9IGNhbmRpZGF0ZV8tPmdldEpiYlN1YnNldCgpLT5nZXRTdWJHcmFwaCgpOwogIFFSSm9pbkdyYXBoUHRyIGpvaW5HcmFwaCA9IHN1YkdyYXBoLT5nZXRQYXJlbnRHcmFwaCgpOwoKICBjb25zdCBOQVN0cmluZyYgdGFibGVJRCA9ICBjb2xFbGVtLT5nZXRUYWJsZUlEKCk7CiAgTkFCb29sZWFuIGlzT3V0c2lkZSA9IEZBTFNFOwogIC8vIENoZWNrIGlmIHdlIGhhdmUgYWxyZWFkeSBjYWNoZWQgdGhlIHJlc3VsdCBmb3IgdGhpcyB0YWJsZS4KICBpZiAoY2FuZGlkYXRlXy0+cHJvYmVDYWNoZUZvclRhYmxlSUQoJnRhYmxlSUQsIGlzT3V0c2lkZSwgZXh0cmFIdWJJRCkpCiAgICByZXR1cm4gaXNPdXRzaWRlOwoKICAvLyBCb3RoIHRoZSBjb2x1bW4gZWxlbWVudCBhbmQgdGhlIGpvaW4gZ3JhcGggYXJlIGZyb20gdGhlIHF1ZXJ5IGRlc2NyaXB0b3IKICAvLyBTbyB3ZSBjYW4gZGlyZWN0bHkgdXNlIHRoZSBJRCBtYXBwaW5nLgogIEpvaW5HcmFwaFRhYmxlUHRyIHRhYmxlTm9kZSA9IGpvaW5HcmFwaC0+Z2V0VGFibGVCeUlEKHRhYmxlSUQpOwoKICAvLyBJZiB0aGUgdGFibGUgaXMgY292ZXJlZCBieSB0aGUgY29tbW9uIHN1YmdyYXBoLCBpdCBpcyBkZWZpbml0bHkgbm90IE91dHNpZGUuCiAgaWYgKHRhYmxlTm9kZSAhPSBOVUxMICYmIHN1YkdyYXBoLT5jb250YWlucyh0YWJsZU5vZGUpKQogIHsKICAgIGNhbmRpZGF0ZV8tPmNhY2hlVGFibGVJRCgmdGFibGVJRCwgRkFMU0UsIE5VTEwpOwogICAgcmV0dXJuIEZBTFNFOwogIH0KCiAgLy8gV2hhdCBpZiBpdHMgY292ZXJlZCBieSB0aGUgTVYgZXh0cmEtaHViIHRhYmxlcz8KICAvLyBJZiBzbywgaXRzIGEgZGlmZmVyZW50IGNhc2UgLSBhbmQgc2hvdWxkIGJlIHB1dCBpbiB0aGUgcGVuZGluZ1dvcmsgcXVldWUKICAvLyB1bnRpbCB3ZSBjaGVjayB0aGUgam9pbiBwcmVkcyB0byB0aG9zZSB0YWJsZXMuCiAgY29uc3QgTkFTdHJpbmcmIHRhYmxlTmFtZSA9IHF1ZXJ5RGV0YWlscy0+Z2V0VGFibGVOYW1lRnJvbUNvbHVtbihjb2xFbGVtKTsKICBpZiAodGFibGVOYW1lID09ICIiKQogIHsKICAgIC8vIFRoaXMgdGFibGUgaXMgaW4gYSBKQkIgdGhhdCB3YXMgb21taXR0ZWQgZnJvbSB0aGUgcXVlcnkgZGVzY3JpcHRvciwKICAgIC8vIGJlY2F1c2UgaXQgaGFzIG5vIE1WcyBvbiBpdC4gU28gaXRzIGRlZmluZXRseSBPdXRzaWRlLgogICAgY2FuZGlkYXRlXy0+Y2FjaGVUYWJsZUlEKCZ0YWJsZUlELCBUUlVFLCBOVUxMKTsKICAgIHJldHVybiBUUlVFOwogIH0KCiAgLy8gVGhpcyBpcyBvbmUgb2YgdGhlIGZldyBwbGFjZXMgd2UgY2FuIGxvb2t1cCBhIHRhYmxlIGJ5IGl0cyBuYW1lLCAKICAvLyBiZWNhdXNlIHdlIGFyZSBub3QgbG9va2luZyBmb3IgYSBzcGVjaWZpYyB0YWJsZSBpbnN0YW5jZSwganVzdCBleGlzdGFuY2UsCiAgLy8gc28gc2VsZi1qb2lucyBhcmUgbm90IGEgcHJvYmxlbS4KICBjb25zdCBRUlRhYmxlUHRyIG12VGFibGUgPSBtdkRldGFpbHMtPmdldFRhYmxlRnJvbU5hbWUodGFibGVOYW1lKTsKCiAgLy8gSWYgdGhlIHRhYmxlIGlzIG5vdCB1c2VkIGJ5IHRoZSBNViBhdCBhbGwgLSBpdHMgUkNfT1VUU0lERS4KICBpZiAobXZUYWJsZSA9PSBOVUxMKQogIHsKICAgIGNhbmRpZGF0ZV8tPmNhY2hlVGFibGVJRCgmdGFibGVJRCwgVFJVRSwgTlVMTCk7CiAgICByZXR1cm4gVFJVRTsKICB9CiAgLy8gV2UgZ2V0IGhlcmUgd2hlbiB0YWJsZSB0YWJsZSBpcyBub3QgcGFydCBvZiB0aGUgbWF0Y2hlZCBzdWJHcmFwaCwgd2hpY2ggCiAgLy8gaXMgdGhlIE1WIEh1YiwgYnV0IGl0IGlzIHVzZWQgYnkgdGhlIE1WLCBzbyBpdCBtdXN0IGJlIGluIHRoZSBNViBleHRyYS1odWIuCiAgLy8gU29tZSBtb3JlIFBhc3MgMiBtYXRjaGluZyBpcyBuZWVkZWQgdG8gdmVyaWZ5IHRoYXQgaXRzIHVzZWZ1bC4KICBleHRyYUh1YklEID0gJmNvbEVsZW0tPmdldFRhYmxlSUQoKTsKICBjYW5kaWRhdGVfLT5jYWNoZVRhYmxlSUQoJnRhYmxlSUQsIEZBTFNFLCBleHRyYUh1YklEKTsKICByZXR1cm4gRkFMU0U7Cn0gIC8vIE1hdGNoVGVzdDo6aXNPdXRzaWRlQ29sdW1uKCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBJcyB0aGlzIGNvbHVtbiBwcm92aWRlZCBieSB0aGUgTVY/Ci8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hUZXN0Ojppc1Byb3ZpZGVkQ29sdW1uKGNvbnN0IFFSQ29sdW1uUHRyIGNvbEVsZW0sIAoJCQkJICAgICAgUVJPdXRwdXRQdHImCW12Q29sKQp7CiAgY29uc3QgTVZEZXRhaWxzUHRyIG12RGV0YWlscyA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpOwoKICAvLyBHZXQgdGhlIE1WIGJhc2UgdGFibGUgb2JqZWN0IGZyb20gdGhlIHF1ZXJ5IHRhYmxlIElELgogIGNvbnN0IEJhc2VUYWJsZURldGFpbHNQdHIgYmFzZVRhYmxlID0gCiAgICBjYW5kaWRhdGVfLT5nZXRNdlRhYmxlRm9yUXVlcnlJRChjb2xFbGVtLT5nZXRUYWJsZUlEKCkpOwoKICAvLyBMb29rIGl0IHVwIGluIHRoZSBNViBoYXNoIHRhYmxlLgogIG12Q29sID0gbXZEZXRhaWxzLT5nZXRPdXRwdXRCeUNvbHVtbk5hbWUoYmFzZVRhYmxlLT5nZXRUYWJsZUVsZW1lbnQoKS0+Z2V0SUQoKSwgCgkJCQkJICAgY29sRWxlbS0+Z2V0Q29sdW1uTmFtZSgpLCBoZWFwXyk7CgogIC8vIFRoZSBjb2x1bW4gaXMgUHJvdmlkZWQgaWYgaXRzIGFuIG91dHB1dCBjb2x1bW4gb2YgdGhlIE1WLgogIHJldHVybiAobXZDb2wgIT0gIE5VTEwpOwp9ICAvLyBNYXRjaFRlc3Q6OmlzUHJvdmlkZWRDb2x1bW4oKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIENhbiB0aGUgY29sdW1uIGJlIHByb3ZpZGVkIGJ5IHVzaW5nIGEgYmFjay1qb2luPwovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoVGVzdDo6aXNCYWNrSm9pbmFibGVDb2x1bW4oY29uc3QgUVJDb2x1bW5QdHIgY29sRWxlbSkKewogIGNvbnN0IE1WRGV0YWlsc1B0ciBtdkRldGFpbHMgPSBjYW5kaWRhdGVfLT5nZXRNdkRldGFpbHMoKTsKICBjb25zdCBEZXNjcmlwdG9yRGV0YWlsc1B0ciBxdWVyeURldGFpbHMgPSBjYW5kaWRhdGVfLT5nZXRRdWVyeURldGFpbHMoKTsKCiAgLy8gR2V0IHRoZSBNViBiYXNlIHRhYmxlIG9iamVjdCBmcm9tIHRoZSBxdWVyeSB0YWJsZSBJRC4KICBjb25zdCBCYXNlVGFibGVEZXRhaWxzUHRyIGJhc2VUYWJsZSA9IGNhbmRpZGF0ZV8tPmdldE12VGFibGVGb3JRdWVyeUlEKGNvbEVsZW0tPmdldFRhYmxlSUQoKSk7CgogIC8vIE5vdyBjaGVjayBpZiB0aGUgdGFibGUgaXMgYmFjay1qb2luYWJsZSAoaWYgaXRzIGtleSBjb2x1bW5zIGFyZSAKICAvLyB2aXNpYmxlIHRocm91Z2ggdGhlIE1WKS4KICByZXR1cm4gYmFzZVRhYmxlLT5nZXRUYWJsZUVsZW1lbnQoKS0+aXNLZXlDb3ZlcmVkKCk7Cn0gIC8vIE1hdGNoVGVzdDo6aXNCYWNrSm9pbmFibGVDb2x1bW4oKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gVGhpcyBtZXRob2QgaXMgY2FsbGVkIG9ubHkgZm9yIGNvbHVtbnMgdGhhdCBhcmUgaW5wdXRzIG9mIHF1ZXJ5IAovLyBvdXRwdXQgZXhwcmVzc2lvbnMuIEl0IGNoZWNrcyBpZiB0aGlzIGNvbHVtbiBpcyBhbiBpbnB1dCBvZiBhbiAKLy8gTVYgb3V0cHV0IGV4cHJlc3Npb24sIHNvIHRoZXJlIGlzIGEgY2hhbmNlIHRoYXQgdGhlIE1WIHByb3ZpZGVzCi8vIGEgc3ViLWV4cHJlc3Npb24gb2YgdGhlIG5lZWRlZCBxdWVyeSBleHByZXNzaW9uLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBNYXRjaFRlc3Q6OmlzSW5kaXJlY3RDb2x1bW4oY29uc3QgUVJDb2x1bW5QdHIgIGNvbEVsZW0pCnsKICBjb25zdCBNVkRldGFpbHNQdHIgbXZEZXRhaWxzID0gY2FuZGlkYXRlXy0+Z2V0TXZEZXRhaWxzKCk7CgogIC8vIEdldCB0aGUgTVYgYmFzZSB0YWJsZSBvYmplY3QgZnJvbSB0aGUgcXVlcnkgdGFibGUgSUQuCiAgY29uc3QgQmFzZVRhYmxlRGV0YWlsc1B0ciBiYXNlVGFibGUgPSBjYW5kaWRhdGVfLT5nZXRNdlRhYmxlRm9yUXVlcnlJRChjb2xFbGVtLT5nZXRUYWJsZUlEKCkpOwoKICAvLyBOb3cgY2hlY2sgaWYgdGhpcyBjb2x1bW4gaXMgdXNlZCBpbiB0aGUgTVYgZGVzY3JpcHRvciBhcyBhbiBpbnB1dCB0byAKICAvLyBvbmUgb2YgdGhlIG91dHB1dCBleHByZXNzaW9ucwogIGNvbnN0IFFST3V0cHV0UHRyIG12T3V0cHV0ID0gCiAgICBtdkRldGFpbHMtPmdldE91dHB1dEJ5SW5wdXRDb2x1bW5zKGJhc2VUYWJsZS0+Z2V0VGFibGVFbGVtZW50KCktPmdldElEKCksIAoJCQkJICAgICAgIGNvbEVsZW0tPmdldENvbHVtbk5hbWUoKSwgaGVhcF8pOwoKICBpZiAobXZPdXRwdXQgPT0gTlVMTCkKICAgIHJldHVybiBOVUxMOwogIGVsc2UKICB7CiAgICAvLyBLZWVwIHRoZSBNViBvdXRwdXQgZXhwcmVzc2lvbiBmb3IgdGhlIFBhc3MgMiBhbGdvcml0aG0uCiAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0oY29sRWxlbSwgbXZPdXRwdXQsIFJDX0lORElSRUNULCBSU19JTlRFUk1FRElBVEUsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICByZXR1cm4gcmV3cml0ZTsKICB9Cn0gIC8vIE1hdGNoVGVzdDo6aXNJbmRpcmVjdENvbHVtbigpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gRmluZCBpZiB0aGUgbGlzdCBvZiBpbnB1dCBjb2x1bW5zIGZyb20gYSBxdWVyeSBleHByZXNzaW9uIGFyZSBwcm92aWRlZAovLyBieSB0aGUgTVY6Ci8vICAgIEZvciBhbGwgdGhlIGlucHV0IGNvbHVtbnMsIGNhbGwgTWF0Y2hPdXRwdXRDb2x1bW4oKQovLwlJZiBBTlkgb2YgdGhlIGlucHV0IGNvbHVtbnMgd2FzIGJsb2NrZWQKLy8JICBSZXR1cm4gTlVMTAovLwlJZiBBTEwgdGhlIGlucHV0IGNvbHVtbnMgYXJlIE91dHNpZGUKLy8JICBSZXR1cm4gT3V0c2lkZQovLyAgICAgIElmIEFMTCB0aGUgaW5wdXRzIGNvbHVtbnMgYXJlIFByb3ZpZGVkCi8vICAgICAgICBSZXR1cm4gYSBmaW5hbCBOb3RQcm92aWRlZCB3aXRoIHRoZSByZXdyaXRlIGluc3RydWN0aW9ucy4KLy8gICAgIE90aGVyd2lzZQovLyAgICAgICAgUmV0dXJuIGFuIGludGVybWVkaWF0ZSBOb3RQcm92aWRlZCB3aXRoIGFsbCB0aGUgaW50ZXJtZWRpYXRlIHJlc3VsdHMuCi8vICAgICAgICBQYXNzIDIgd2lsbCBzb3J0IHRoaW5ncyBvdXQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBNYXRjaFRlc3Q6OmZpbmRFeHByZXNzaW9uSW5wdXRzKGNvbnN0IEVsZW1lbnRQdHJMaXN0JiBxdWVyeUNvbExpc3QsCgkJCQkJCQkgICBjb25zdCBRUkVsZW1lbnRQdHIgICAgcXVlcnlFbGVtZW50KSAKewogIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUgPSBOVUxMOwoKICBpZiAocXVlcnlDb2xMaXN0LmVudHJpZXMoKSA9PSAwKQogIHsKICAgIC8vIEFuIGV4cHJlc3Npb24gd2l0aCBubyBpbnB1dHMgaXMgTm90UHJvdmlkZWQuCiAgICByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0ocXVlcnlFbGVtZW50LCBOVUxMLCBSQ19OT1RQUk9WSURFRCwgUlNfRklOQUwsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICByZXdyaXRlLT5zZXRTZWNvbmRhcnlSZXN1bHRDb2RlKFJDX05PX0lOUFVUUyk7CiAgICByZXR1cm4gcmV3cml0ZTsKICB9CgkJCiAgLy8gQW5hbHl6ZSB0aGUgZXhwcmVzaW9uIGlucHV0cwogIGNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0c1B0ciBpbnRlcm1lZGlhdGVSZXN1bHRzID0gCiAgICBuZXcoaGVhcF8pIGNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0cyhBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogIE1hdGNoSW5wdXRDb2x1bW5MaXN0KHF1ZXJ5Q29sTGlzdCwgaW50ZXJtZWRpYXRlUmVzdWx0cywgRkFMU0UpOwoKICAvLyBOb3cgY2hlY2sgdGhlIGFuYWx5c2lzIHJlc3VsdHMKICBpZiAoaW50ZXJtZWRpYXRlUmVzdWx0cy0+d2FzQmxvY2tlZENvbHVtbl8pCiAgewogICAgLy8gQXQgbGVhc3Qgb25lIG9mIHRoZSBleHByZXNzaW9uIGlucHV0cyBjYW5ub3QgYmUgcHJvdmlkZWQgYnkgdGhlIE1WLgogICAgLy8gRGlzcXVhbGlmeSB0aGUgTVYuCiAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIkV4cHJlc3Npb24gJXMgY2Fubm90IGJlIHByb3ZpZGVkLiIsIHF1ZXJ5RWxlbWVudC0+Z2V0SUQoKSk7CiAgICBkZWxldGVQdHIoaW50ZXJtZWRpYXRlUmVzdWx0cyk7CiAgICByZXR1cm4gTlVMTDsKICB9CiAgZWxzZSBpZiAoaW50ZXJtZWRpYXRlUmVzdWx0cy0+b3V0c2lkZUlucHV0c18uZW50cmllcygpID09IHF1ZXJ5Q29sTGlzdC5lbnRyaWVzKCkpCiAgewogICAgLy8gQWxsIHRoZSBjb2x1bW5zIGFyZSBSQ19PVVRTSURFCiAgICAvLyBQaWNrIHRoZSBmaXJzdCBvbmUgZm9yIHRoZSByZXdyaXRlLgogICAgcmV3cml0ZSA9IGludGVybWVkaWF0ZVJlc3VsdHMtPm91dHNpZGVJbnB1dHNfWzBdOwogICAgcmV3cml0ZS0+c2V0UXVlcnlFbGVtZW50KHF1ZXJ5RWxlbWVudCk7CgogICAgaW50ZXJtZWRpYXRlUmVzdWx0cy0+b3V0c2lkZUlucHV0c18ucmVtb3ZlQXQoMCk7CiAgfQogIGVsc2UgaWYgKGludGVybWVkaWF0ZVJlc3VsdHMtPnByb3ZpZGVkSW5wdXRzXy5lbnRyaWVzKCkgPT0gcXVlcnlDb2xMaXN0LmVudHJpZXMoKSkKICB7CiAgICAvLyBBbGwgdGhlIGV4cHJlc3Npb24gaW5wdXRzIGFyZSBkaXJlY3RseSBwcm92aWRlZCBieSB0aGUgTVYuCiAgICByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0ocXVlcnlFbGVtZW50LCBOVUxMLCBSQ19OT1RQUk9WSURFRCwgUlNfRklOQUwsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICByZXdyaXRlLT5zZXRTZWNvbmRhcnlSZXN1bHRDb2RlKFJDX0lOUFVUU19QUk9WSURFRCk7CgogICAgLy8gQ29weSB0aGUgcHJvdmlkZWQgbWVtYmVycyB0byB0aGUgcmVzdWx0CiAgICByZXdyaXRlLT5hZGRTdWJFbGVtZW50cyhpbnRlcm1lZGlhdGVSZXN1bHRzLT5wcm92aWRlZElucHV0c18sIEZBTFNFKTsKICAgIGludGVybWVkaWF0ZVJlc3VsdHMtPnByb3ZpZGVkSW5wdXRzXy5jbGVhcigpOwogIH0KICBlbHNlCiAgewogICAgLy8gVGhlIGV4cHJlc3Npb24gaXMgTm90UHJvdmlkZWQsIHdoaWNoIG1lYW5zIGl0IGNhbiBwcm9iYWJseSBiZSBjb21wdXRlZCB1c2luZyB0aGUgTVYgY29sdW1ucy4KICAgIC8vIEdpdmUgYWxsIHRoZSBpbnRlcm1lZGlhdGUgZGF0YSB0byB0aGUgUGFzcyAyIGFsZ29yaXRobS4KICAgIHJld3JpdGUgPSBuZXcoaGVhcF8pIAogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShxdWVyeUVsZW1lbnQsIE5VTEwsIFJDX05PVFBST1ZJREVELCBSU19JTlRFUk1FRElBVEUsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICByZXdyaXRlLT5zZXRTZWNvbmRhcnlSZXN1bHRDb2RlKFJDX0lOUFVUU19QUk9WSURFRCk7CgogICAgcmV3cml0ZS0+YWRkU3ViRWxlbWVudHMoaW50ZXJtZWRpYXRlUmVzdWx0cyk7CiAgICBpbnRlcm1lZGlhdGVSZXN1bHRzLT5jbGVhcigpOwogIH0KCiAgZGVsZXRlUHRyKGludGVybWVkaWF0ZVJlc3VsdHMpOwogIHJldHVybiByZXdyaXRlOwp9ICAvLyBNYXRjaFRlc3Q6OmZpbmRFeHByZXNzaW9uSW5wdXRzKCkKCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gTWF0Y2ggYW4gZXF1YWxpdHkgc2V0IHRvIGFuIE1WJ3Mgb3V0cHV0IGxpc3QuCi8vIFRoZSBydWxlcyBhcmU6Ci8vIDEuIEZpcnN0IG1hdGNoIGFsbCB0aGUgZXF1YWxpdHkgc2V0IGNvbHVtbnMKLy8gMi4gSWYgQUxMIHRoZSB0aGUgZXF1YWxpdHkgc2V0IG1lbWJlcnMgYXJlIE91dHNpZGUgCi8vICAgICAgVGhlbiB0aGUgZW50aXJlIGVxdWFsaXR5IHNldCBpcyBhIGZpbmFsIE91dHNpZGUuCi8vICAgICAgUGljayB0aGUgZmlyc3QgbWVtYmVyIGZvciB0aGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMuCi8vIDMuIElmIEFOWSBvZiB0aGUgbWVtYmVycyBpcyBhIGZpbmFsIFByb3ZpZGVkCi8vICAgICAgVGhlbiB0aGUgZW50aXJlIGVxdWFsaXR5IHNldCBpcyBQcm92aWRlZC4KLy8gICAgICBQaWNrIHRoZSBmaXJzdCBQcm92aWRlZCBtZW1iZXIgZm9yIHRoZSByZXdyaXRlIGluc3RydWN0aW9ucy4KLy8gNC4gSWYgYW55IG9mIHRoZSBtZW1iZXJzIGlzIGEgYmFjay1qb2luIG9yIGFuIGV4dHJhLWh1YgovLyAgICAgIFRoZSB0aGUgZXF1YWxpdHkgc2V0IGlzIGFuIGludGVybWVkaWF0ZSBOb3RQcm92aWRlZC4KLy8gNS4gT3RoZXJ3aXNlCi8vICAgICAgRGlzcXVhbGl0eSB0aGUgTVYuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBNYXRjaFRlc3Q6Om1hdGNoRXF1YWxpdHlTZXQoY29uc3QgUVJKb2luUHJlZFB0ciBqb2luUHJlZCkKewogIGNvbnN0IEVsZW1lbnRQdHJMaXN0JiBlcXVhbGl0eVNldCA9IGpvaW5QcmVkLT5nZXRFcXVhbGl0eUxpc3QoKTsKICBjb21wb3NpdGVNYXRjaGluZ1Jlc3VsdHNQdHIgaW50ZXJtZWRpYXRlUmVzdWx0cyA9IAogICAgbmV3KGhlYXBfKSBjb21wb3NpdGVNYXRjaGluZ1Jlc3VsdHMoQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gTlVMTDsKCiAgLy8gQW5hbHl6ZSB0aGUgZXF1YWxpdHkgc2V0IG1lbWJlcnMKICBNYXRjaElucHV0Q29sdW1uTGlzdChlcXVhbGl0eVNldCwgaW50ZXJtZWRpYXRlUmVzdWx0cywgVFJVRSk7CgogIC8vIENoZWNrIE91dHNpZGUgZmlyc3QsIGJlY2F1c2UgaXQgaGFkIEFMTCBzZW1hbnRpY3MKICBpZiAoaW50ZXJtZWRpYXRlUmVzdWx0cy0+b3V0c2lkZUlucHV0c18uZW50cmllcygpID09IGVxdWFsaXR5U2V0LmVudHJpZXMoKSkKICB7CiAgICAvLyBBbGwgdGhlIGNvbHVtbnMgYXJlIFJDX09VVFNJREUKICAgIC8vIFBpY2sgdGhlIGZpcnN0IG9uZSBmb3IgdGhlIHJld3JpdGUuCiAgICByZXdyaXRlID0gaW50ZXJtZWRpYXRlUmVzdWx0cy0+b3V0c2lkZUlucHV0c19bMF07CiAgICByZXdyaXRlLT5zZXRRdWVyeUVsZW1lbnQoam9pblByZWQpOwogICAgaW50ZXJtZWRpYXRlUmVzdWx0cy0+b3V0c2lkZUlucHV0c18ucmVtb3ZlQXQoMCk7CiAgfQogIC8vIEF0IGxlYXN0IG9uZSBvZiB0aGUgY29sdW1ucyBpbiB0aGUgZXF1YWxpdHkgc2V0IHdhcyBub3QgYW4gT3V0c2lkZSwgc28gCiAgLy8gdGhpcyBpcyBub3QgYW4gT3V0c2lkZSByZXN1bHQuIENoZWNrIHRoZSBvdGhlciBvcHRpb25zLCB0aGlzIHRpbWUgdXNpbmcgCiAgLy8gQU5ZIHNlbWFudGljcy4KICBlbHNlIGlmIChpbnRlcm1lZGlhdGVSZXN1bHRzLT5wcm92aWRlZElucHV0c18uZW50cmllcygpID4gMCkKICB7CiAgICAvLyBXZSBoYXZlIGF0IGxlYXN0IG9uZSBtZW1iZXIgdGhhdCBpcyBQcm92aWRlZC4KICAgIC8vIFBpY2sgdGhlIGZpcnN0IG9uZSBmb3IgdGhlIHJld3JpdGUuCiAgICByZXdyaXRlID0gaW50ZXJtZWRpYXRlUmVzdWx0cy0+cHJvdmlkZWRJbnB1dHNfWzBdOwogICAgcmV3cml0ZS0+c2V0UXVlcnlFbGVtZW50KGpvaW5QcmVkKTsKCiAgICBpbnRlcm1lZGlhdGVSZXN1bHRzLT5wcm92aWRlZElucHV0c18ucmVtb3ZlQXQoMCk7CiAgfQogIGVsc2UgaWYgKGludGVybWVkaWF0ZVJlc3VsdHMtPmJhY2tKb2luSW5wdXRzXy5lbnRyaWVzKCkgPiAwIHx8CiAgICAgICAgICAgaW50ZXJtZWRpYXRlUmVzdWx0cy0+ZXh0cmFodWJJbnB1dHNfLmVudHJpZXMoKSA+IDApCiAgewogICAgLy8gUHJvYmxlbWF0aWMgc2NlbmFyaW8gVEJEOgogICAgLy8gVGhpcyBlcXVhbGl0eSBzZXQgaGFzIG5vIFByb3ZpZGVkIG1lbWJlcnMsIGJ1dCBpdCBkb2VzIGhhdmUgYmFjay1qb2luCiAgICAvLyBhbmQvb3IgZXh0cmEtaHViIG1lbWJlcnMuIFdoZW4gd2UgZGVmZXIgdGhlIGRlY2lzaW9uIHRvIFBhc3MgMiwgYW5kIGFuIAogICAgLy8gZXh0cmEtaHViIHRhYmxlIGNhbm5vdCBiZSB2ZXJpZmllZCwgaXQgd2lsbCBkaXNxdWFsaWZ5IHRoZSBNViwgZXZlbiAKICAgIC8vIHRob3VnaCB0aGVyZSBtYXkgYmUgb3RoZXIgYWx0ZXJuYXRpdmVzIHN0aWxsIG9wZW4uCiAgICAvLyBBIHBvc3NpYmxlIHNvbHV0aW9uIG1heSBiZSB0byBoYXZlIGEgc2VwYXJhdGUgbGlzdCBvZiBub24tY3JpdGljYWwgCiAgICAvLyBleHRyYS1odWIgdGFibGVzLCB0aGF0IGRvIG5vdCBkaXNxdWFsaWZ5IHRoZSBNViB3aGVuIGZhaWwgdG8gdmVyaWZ5LgoKICAgIC8vIFdlIGhhdmUgYXQgbGVhc3Qgb25lIG1lbWJlciB0aGF0IGlzIGVpdGhlciBCYWNram9pbmFibGUgb3IgUkNfRVhUUkFIVUIuCiAgICAvLyBLZWVwIGFsbCB0aGUgZGF0YSBmb3IgUGFzcyAyIHByb2Nlc3NpbmcuCiAgICByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0oam9pblByZWQsIE5VTEwsIFJDX05PVFBST1ZJREVELCBSU19JTlRFUk1FRElBVEUsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CgogICAgLy8gQ29weSB0aGUgYmFja2pvaW5hYmxlIG1lbWJlcnMgdG8gdGhlIHJlc3VsdAogICAgcmV3cml0ZS0+YWRkU3ViRWxlbWVudHMoaW50ZXJtZWRpYXRlUmVzdWx0cy0+YmFja0pvaW5JbnB1dHNfLCBUUlVFKTsKICAgIC8vIENsZWFyIHRoZW0gZnJvbSB0aGUgaW50ZXJtZWRpYXRlIHJlc3VsdHMgc28gdGhleSBkb24ndCBnZXQgZGVsZXRlZCBhdCB0aGUgZW5kIG9mIHRoaXMgbWV0aG9kLgogICAgaW50ZXJtZWRpYXRlUmVzdWx0cy0+YmFja0pvaW5JbnB1dHNfLmNsZWFyKCk7CgogICAgLy8gQ29weSB0aGUgZXh0cmFodWIgbWVtYmVycyB0byB0aGUgcmVzdWx0CiAgICByZXdyaXRlLT5hZGRTdWJFbGVtZW50cyhpbnRlcm1lZGlhdGVSZXN1bHRzLT5leHRyYWh1YklucHV0c18sIFRSVUUpOwogICAgLy8gQ2xlYXIgdGhlbSBmcm9tIHRoZSBpbnRlcm1lZGlhdGUgcmVzdWx0cyBzbyB0aGV5IGRvbid0IGdldCBkZWxldGVkIGF0IHRoZSBlbmQgb2YgdGhpcyBtZXRob2QuCiAgICBpbnRlcm1lZGlhdGVSZXN1bHRzLT5leHRyYWh1YklucHV0c18uY2xlYXIoKTsKICB9CiAgZWxzZQogIHsKICAgIC8vIE5vbmUgb2YgdGhlIGVxdWFsaXR5IHNldCBtZW1iZXJzIGlzIGNvdmVyZWQgYnkgdGhlIE1WLgogICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJvdXRwdXQgZXF1YWxpdHkgc2V0ICVzIGNhbm5vdCBiZSBwcm92aWRlZC4iLCBqb2luUHJlZC0+Z2V0SUQoKSk7CiAgICByZXdyaXRlID0gTlVMTDsKICB9CgogIGRlbGV0ZVB0cihpbnRlcm1lZGlhdGVSZXN1bHRzKTsKICByZXR1cm4gcmV3cml0ZTsKCn0gIC8vIE1hdGNoVGVzdDo6bWF0Y2hFcXVhbGl0eVNldCgpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gRm9yIGEgbGlzdCBvZiBjb2x1bW5zIHRoYXQgY2FuIGJlIGVpdGhlciB0aGUgbGlzdCBvZiBleHByZXJzc2lvbiBpbnB1dHMsIAovLyBvciBhbiBlcXVhbGl0eSBzZXQgbGlzdCBvZiBtZW1iZXJzLCBtYXRjaCBldmVyeSBtZW1iZXIgb2YgdGhlIGxpc3QsIGFuZCAKLy8gYXJyYW5nZSB0aGUgcmVzdWx0cyBhY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCBjb2RlIGluIHNlcGFyYXRlIGxpc3RzLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKdm9pZCBNYXRjaFRlc3Q6Ok1hdGNoSW5wdXRDb2x1bW5MaXN0KGNvbnN0IEVsZW1lbnRQdHJMaXN0JiAgICAgICAgICBxdWVyeUNvbExpc3QsIAoJCQkJICAgICBjb21wb3NpdGVNYXRjaGluZ1Jlc3VsdHNQdHIgICAgbWF0Y2hpbmdSZXN1bHRzLAoJCQkJICAgICBOQUJvb2xlYW4JCQkgICAgaXNBbkVxdWFsaXR5U2V0KSAKewogIC8vIFRoZXNlIGxpc3RzIGFyZSBmb3IgY29sbGVjdGluZyByZXN1bHRzIGZyb20gaW5kaXZpZHVhbCBpbnB1dHMuCiAgY29uc3QgTVZEZXRhaWxzUHRyIG12RGV0YWlscyA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpOwogIGNvbnN0IERlc2NyaXB0b3JEZXRhaWxzUHRyIHF1ZXJ5RGV0YWlscyA9IGNhbmRpZGF0ZV8tPmdldFF1ZXJ5RGV0YWlscygpOwoKICBDb2xsSW5kZXggbnVtSW5wdXRzID0gcXVlcnlDb2xMaXN0LmVudHJpZXMoKTsKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8bnVtSW5wdXRzOyBpKyspCiAgewogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IE5VTEw7CgogICAgUVJFbGVtZW50UHRyIHF1ZXJ5RWxlbSA9IHF1ZXJ5Q29sTGlzdFtpXS0+Z2V0UmVmZXJlbmNlZEVsZW1lbnQoKTsKCiAgICBzd2l0Y2gocXVlcnlFbGVtLT5nZXRFbGVtZW50VHlwZSgpKQogICAgewogICAgICBjYXNlIEVUX0NvbHVtbjoKICAgICAgewoJUVJDb2x1bW5QdHIgcXVlcnlJbnB1dENvbCA9IHF1ZXJ5RWxlbS0+ZG93bkNhc3RUb1FSQ29sdW1uKCk7CgogICAgICAgIGlmIChpc0FuRXF1YWxpdHlTZXQgJiYgcXVlcnlEZXRhaWxzLT5pc0NvbHVtbkZyb21Mb2pUYWJsZShxdWVyeUlucHV0Q29sKSkKICAgICAgICB7CiAgICAgICAgICAvLyBUaGlzIGlzIGEgY29sdW1uIG9mIGFuIExPSiB0YWJsZSB3aXRoaW4gYSBKb2luUHJlZC4KICAgICAgICAgIC8vIFNraXAgaXQgaW4gc2VhcmNoIG9mIHRoZSBvdGhlciBjb2x1bW4uCiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgoJLy8gQ2FsbCB0aGUgc2luZ2xlIGNvbHVtbiBtYXRjaGluZyBtZXRob2QuCglyZXdyaXRlID0gbWF0Y2hDb2x1bW4ocXVlcnlJbnB1dENvbCwgIWlzQW5FcXVhbGl0eVNldCwgaXNBbkVxdWFsaXR5U2V0KTsKCWJyZWFrOwogICAgICB9CgogICAgICBjYXNlIEVUX0pvaW5QcmVkOgogICAgICB7CgkvLyBUaGUgaW5wdXQgY29sdW1uIGlzIGFuIGVxdWFsaXR5IHNldC4KCWFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAhaXNBbkVxdWFsaXR5U2V0LCBRUkxvZ2ljRXhjZXB0aW9uLCAKCQkJICAiRXF1YWxpdHkgc2V0cyBzaG91bGQgbm90IHJlZmVyZW5jZSBvdGhlciBlcXVhbGl0eSBzZXRzLiIpOwoJY29uc3QgUVJKb2luUHJlZFB0ciBqb2luUHJlZCA9IHF1ZXJ5RWxlbS0+ZG93bkNhc3RUb1FSSm9pblByZWQoKTsKCXJld3JpdGUgPSBtYXRjaEVxdWFsaXR5U2V0KGpvaW5QcmVkKTsKCWJyZWFrOwogICAgICB9CgogICAgICBjYXNlIEVUX0V4cHI6CiAgICAgIHsKCWFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAgICAgICBpc0FuRXF1YWxpdHlTZXQsIFFSTG9naWNFeGNlcHRpb24sIAoJCQkgICJFeHByZXNzaW9ucyBzaG91bGQgbm90IGxpc3Qgb3RoZXIgZXhwcmVzc2lvbnMgYXMgaW5wdXRzLiIpOwoJLy8gVEJEIC0gZXhwcmVzc2lvbnMgYXMgaW5wdXRzIG9mIGVxdWFsaXR5IHNldHMKCWJyZWFrOwogICAgICB9CgogICAgICBkZWZhdWx0OgogICAgICB7CgkvLyBOb3QgZXhwZWN0aW5nIGVsZW1lbnRzIG90aGVyIHRoYW4gdGhvc2UgYWJvdmUuCglhc3NlcnRMb2dBbmRUaHJvdyhDQVRfTUFUQ0hUU1RfTVZERVRBSUxTLCBMTF9NVlFSX0ZBSUwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgRkFMU0UsIFFSTG9naWNFeGNlcHRpb24sIAoJCQkgICJVbmV4cGVjdGVkIGlucHV0IGNvbHVtbiBsaXN0IG1lbWJlci4iKTsgCiAgICAgIH0KICAgIH0gLy8gY2FzZSBvbiBlbGVtZW50IHR5cGUKCiAgICBpZiAocmV3cml0ZSA9PSBOVUxMKQogICAgewogICAgICAvLyBUaGlzIGlucHV0IGNvbHVtbiBpcyBub3QgcHJvdmlkZWQgYnkgdGhlIE1WLiAKICAgICAgLy8gU28gdGhlIHF1ZXJ5IG91dHB1dCBleHByZXNzaW9uIGNhbm5vdCBiZSBjb21wdXRlZCBmcm9tIHRoaXMgTVYuCiAgICAgIG1hdGNoaW5nUmVzdWx0cy0+d2FzQmxvY2tlZENvbHVtbl8gPSBUUlVFOwogICAgICAvLyBJZiB0aGlzIGlzIGFuIGV4cHJlc3Npb24gaW5wdXQgbGlzdCAtIHF1aXQgbm93IGJlY2F1c2UgdGhlIGV4cHJlc3Npb24gY2Fubm90IGJlIHByb3ZpZGVkLgogICAgICAvLyBJZiB0aGlzIGlzIGFuIGVxdWFsaXR5IHNldCAtIGNvbnRpbnVlIGJlY2F1c2Ugd2UgY2FuIHVzZSBzb21lIG90aGVyIHNldCBtZW1iZXIuCiAgICAgIGlmICghaXNBbkVxdWFsaXR5U2V0KQoJcmV0dXJuOwogICAgICBlbHNlIAogICAgICB7CiAgICAgICAgUVJMb2dnZXI6OmxvZyhDQVRfTUFUQ0hUU1RfTVZERVRBSUxTLCBMTF9JTkZPLAogICAgICAgICAgICAgICAgICAgICAgIklnbm9yZSBsYXN0IGRpc3F1YWxpZmljYXRpb24gbWVzc2FnZS4iKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgfQoKICAgIG1hdGNoaW5nUmVzdWx0cy0+aW5zZXJ0KHJld3JpdGUpOwoKICAgIC8vIElmIHRoaXMgaXMgYW4gZXF1YWxpdHkgc2V0LCBvbmUgcHJvdmlkZWQgY29sdW1uIGlzIGFsbCB3ZSBuZWVkLgogICAgaWYgKHJld3JpdGUtPmdldFJlc3VsdENvZGUoKSA9PSBSQ19QUk9WSURFRCAmJiBpc0FuRXF1YWxpdHlTZXQpCiAgICAgIHJldHVybjsKCiAgfSAvLyBmb3IgbG9vcCBvbiBpbnB1dCBjb2x1bW5zLgoKfSAgLy8gTWF0Y2hUZXN0OjpNYXRjaElucHV0Q29sdW1uTGlzdCgpCgoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIEdlbmVyYXRlIHRoZSBRUk1WQ29sdW1uIGVsZW1lbnQgZm9yIGEgcHJvdmlkZWQgY29sdW1uLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKUVJNVkNvbHVtblB0ciBNYXRjaFRlc3Q6OmdlbmVyYXRlUHJvdmlkZWRNdkNvbHVtbihSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgLy8gQ29uc3RydWN0IHRoZSBNVkNvbHVtbiBlbGVtZW50CiAgUVJNVkNvbHVtblB0ciBtdkNvbHVtbiA9IG5ldyAoaGVhcF8pIFFSTVZDb2x1bW4oQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICAvLyBHZXQgdGhlIG5hbWUgb2YgdGhlIE1WIGNvbHVtbiBmcm9tIHRoZSBNViBvdXRwdXQgZWxlbWVudC4KICBjb25zdCBRUkVsZW1lbnRQdHIgbXZFbGVtID0gcmV3cml0ZS0+Z2V0TXZFbGVtZW50KCk7CiAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgIG12RWxlbSAhPSBOVUxMLCBRUkxvZ2ljRXhjZXB0aW9uLCAKCQkgICAgIkV4cGVjdGluZyBhbiBNViBlbGVtZW50IGZvciBhIFByb3ZpZGVkIG91dHB1dCBjb2x1bW4uIik7CgogIGNvbnN0IFFST3V0cHV0UHRyIG12Q29sID0gbXZFbGVtLT5kb3duQ2FzdFRvUVJPdXRwdXQoKTsKICBtdkNvbHVtbi0+c2V0TVZDb2xOYW1lKG12Q29sLT5nZXROYW1lKCkpOwoKICAvLyBJZiB0aGUgcXVlcnkgZWxlbWVudCBpcyBhbiBPdXRwdXQgZWxlbWVudCwgcmVmZXJlbmNlIHRoZSBJRCBvZiB0aGUgaW50ZXJuYWwKICAvLyBjb2x1bW4vZXhwcmVzc2lvbi9qb2luLXByZWQuCiAgUVJFbGVtZW50UHRyIHF1ZXJ5RWxlbSA9IHJld3JpdGUtPmdldEFjdHVhbFF1ZXJ5RWxlbWVudCgpOwogIG12Q29sdW1uLT5zZXRSZWYocXVlcnlFbGVtLT5nZXRJRCgpKTsKCiAgLy8gTGVhdmUgdGhlIE1WIGF0dHJpYnV0ZSBmb3Igbm93LiBIb3BlZnVsbHkgd2Ugd2lsbCBub3QgbmVlZCBpdC4KICByZXR1cm4gbXZDb2x1bW47Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBHZW5lcmF0ZSB0aGUgUVJDb2x1bW4gZWxlbWVudCBmb3IgYSBOb3RQcm92aWRlZCBjb2x1bW4uCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpRUkNvbHVtblB0ciBNYXRjaFRlc3Q6OmdlbmVyYXRlTm90UHJvdmlkZWRDb2x1bW4oUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSkKewogIC8vIENvbnN0cnVjdCB0aGUgTVZDb2x1bW4gZWxlbWVudAogIFFSQ29sdW1uUHRyIHJlc3VsdENvbHVtbiA9IG5ldyAoaGVhcF8pIFFSQ29sdW1uKEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgLy8gR2V0IHRoZSBuYW1lIG9mIHRoZSBjb2x1bW4gZnJvbSB0aGUgcXVlcnkgZWxlbWVudC4KICBjb25zdCBRUkVsZW1lbnRQdHIgcXVlcnlFbGVtID0gcmV3cml0ZS0+Z2V0QWN0dWFsUXVlcnlFbGVtZW50KCk7CiAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgIHF1ZXJ5RWxlbSAhPSBOVUxMLCBRUkxvZ2ljRXhjZXB0aW9uLCAKCQkgICAgIkV4cGVjdGluZyBhIHF1ZXJ5IGVsZW1lbnQgZm9yIGEgTm90UHJvdmlkZWQgb3V0cHV0IGNvbHVtbi4iKTsKICByZXN1bHRDb2x1bW4tPnNldFJlZihxdWVyeUVsZW0tPmdldElEKCkpOwoKICBpZiAocXVlcnlFbGVtLT5nZXRFbGVtZW50VHlwZSgpID09IEVUX0NvbHVtbikKICB7CiAgICBjb25zdCBRUkNvbHVtblB0ciBxdWVyeUNvbCA9IHF1ZXJ5RWxlbS0+ZG93bkNhc3RUb1FSQ29sdW1uKCk7CiAgICByZXN1bHRDb2x1bW4tPnNldEZ1bGx5UXVhbGlmaWVkQ29sdW1uTmFtZShxdWVyeUNvbC0+Z2V0RnVsbHlRdWFsaWZpZWRDb2x1bW5OYW1lKCkpOwogICAgcmVzdWx0Q29sdW1uLT5zZXRUYWJsZUlEKHF1ZXJ5Q29sLT5nZXRUYWJsZUlEKCkpOwogIH0KICBlbHNlCiAgewogICAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgICAgcXVlcnlFbGVtLT5nZXRFbGVtZW50VHlwZSgpID09IEVUX0pvaW5QcmVkLCBRUkxvZ2ljRXhjZXB0aW9uLCAKICAJCSAgICAgICJFeHBlY3RpbmcgYSBlaXRoZXIgYSBDb2x1bW4gb3IgSm9pblByZWQgaGVyZS4iKTsKICAgIAogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgc3ViUmV3cml0ZSA9IHJld3JpdGUtPmdldFN1YkVsZW1lbnRzKCktPmJhY2tKb2luSW5wdXRzX1swXTsKICAgIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAgIHN1YlJld3JpdGUsIFFSTG9naWNFeGNlcHRpb24sIAogIAkJICAgICAgIkV4cGVjdGluZyBhIGJhY2stam9pbiBzdWItZWxlbWVudC4iKTsKCiAgICBjb25zdCBRUkVsZW1lbnRQdHIgcXVlcnlTdWJFbGVtID0gc3ViUmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCk7CiAgICBjb25zdCBRUkNvbHVtblB0ciBxdWVyeUNvbCA9IHF1ZXJ5U3ViRWxlbS0+ZG93bkNhc3RUb1FSQ29sdW1uKCk7CiAgICByZXN1bHRDb2x1bW4tPnNldEZ1bGx5UXVhbGlmaWVkQ29sdW1uTmFtZShxdWVyeUNvbC0+Z2V0RnVsbHlRdWFsaWZpZWRDb2x1bW5OYW1lKCkpOwogIH0KCiAgLy8gTGVhdmUgdGhlIE1WIGF0dHJpYnV0ZSBmb3Igbm93LiBIb3BlZnVsbHkgd2Ugd2lsbCBub3QgbmVlZCBpdC4KICByZXR1cm4gcmVzdWx0Q29sdW1uOwp9CgoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIE1hdGNoIGFuIGV4cHJlc3Npb24gKFBhc3MgMSkuIEhlcmUgaXMgdGhlIGFsZ29yaXRobSBmcm9tIAovLyB0aGUgSVMgZG9jdW1lbnQ6Ci8vIDEuIElmIHRoZSBleHByZXNzaW9uIHRleHQgaXMgcHJvdmlkZWQgYnkgdGhlIE1WLCBhbmQgdGhlIGV4cHJlc3Npb24ncyAKLy8gICAgaW5wdXQgY29sdW1ucyBtYXRjaCBhcyB3ZWxsCi8vICAgICAgUmV0dXJuIFByb3ZpZGVkLgovLyAyLiBJZiBhbGwgdGhlIGlucHV0IGNvbHVtbnMgYXJlIHByb3ZpZGVkIGJ5IHRoZSBNVgovLyAgICAgIFJldHVybiBOb3RQcm92aWRlZC4KLy8gMy4gT3RoZXJ3aXNlLCByZXR1cm4gTlVMTC4KLy8KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqClJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIE1hdGNoVGVzdDo6bWF0Y2hFeHByZXNzaW9uIChjb25zdCBRUkV4cHJQdHIgZXhwcikgCnsKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gTlVMTDsKCiAgLy8gMS4gQ2hlY2sgaWYgdGhlIE1WIGhhcyBhbiBvdXRwdXQgZXhwcmVzc2lvbiB3aXRoIG1hdGNoaW5nIHRleHQKICAvLyAgICBTa2lwIHRoaXMgdGVzdCBmb3Igcm9sbHVwIGFnZ3JlZ2F0ZSBleHByZXNzaW9ucy4KICBpZiAoY2FuZGlkYXRlXy0+Z2V0QWdncmVnYXRlTWF0Y2hpbmdUeXBlKCkgIT0gQU1UX01BVl9BUV9ERyB8fAogICAgICBleHByLT5nZXRFeHByUm9vdCgpLT5jb250YWluc0FuQWdncmVnYXRlKCkgPT0gRkFMU0UpCiAgewogICAgcmV3cml0ZSA9IGZpbmRNYXRjaGluZ012RXhwcmVzc2lvbihleHByLT5nZXRFeHByUm9vdCgpKTsKICAgIGlmIChyZXdyaXRlICE9IE5VTEwpCiAgICB7CiAgICAgIHJld3JpdGUtPnNldFF1ZXJ5RWxlbWVudChleHByKTsKICAgICAgcmV0dXJuIHJld3JpdGU7CiAgICB9CiAgfQoKICAvLyAyLiBBIG1hdGNoaW5nIE1WIG91dHB1dCBleHByZXNzaW9uIHdhcyBub3QgZm91bmQuIAogIC8vIENoZWNrIGlmIGF0IGxlYXN0IHRoZSBpbnB1dCBjb2x1bW5zIGFyZSBQcm92aWRlZC4KICBjb25zdCBFbGVtZW50UHRyTGlzdCYgcXVlcnlJbnB1dHMgPSBleHByLT5nZXRJbnB1dENvbHVtbnMoaGVhcF8pOwogIGlmIChxdWVyeUlucHV0cy5lbnRyaWVzKCkgPT0gMCkKICB7CiAgICAvLyBTb21ldGltZXMgZXhwcmVzc2lvbnMgaGF2ZSBubyBjb2x1bW4gaW5wdXRzLCBsaWtlIENPVU5UKCopLgogICAgc3dpdGNoIChjYW5kaWRhdGVfLT5nZXRBZ2dyZWdhdGVNYXRjaGluZ1R5cGUoKSkKICAgIHsKICAgICAgY2FzZSBBTVRfTUFWX0FRX01HOgogICAgICAgIC8vIElmIHRoaXMgaXMgYSBtYXRjaGluZyBNQVYsIGZhaWwgYmVjYXVzZSBpdCBzaG91bGQgaGF2ZSBtYXRjaGVkIGEgTUFWIGFnZ3JlZ2F0ZSBleHByZXNzaW9uLgogICAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgib3V0cHV0IGV4cHJlc3Npb24gJXMgaXMgbm90IFByb3ZpZGVkLiIsIAoJCQkJCSAgZXhwci0+Z2V0SUQoKS5kYXRhKCkpOwogICAgICAgIHJldHVybiBOVUxMOwoKICAgICAgY2FzZSBBTVRfTUpWX0FROgogICAgICAgIC8vIElmIGl0cyBvbiBhbiBNSlYsIGl0cyBhIEZpbmFsIE91dHNpZGUgbWF0Y2gsIGJlY2F1c2UgaXQgY2FuIGJlIGNvbXB1dGVkIG9uIHRoZSBNSlYuCiAgICAgICAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShleHByLCBOVUxMLCBSQ19PVVRTSURFLCBSU19GSU5BTCwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgQU1UX01BVl9BUV9ERzoKICAgICAgICAvLyBJZiB0aGlzIGlzIGEgcm9sbHVwIG1hdGNoaW5nIGNhc2UsIGRlZmVyIHRvIFBhc3MgMi4KICAgICAgICByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGV4cHIsIE5VTEwsIFJDX05PVFBST1ZJREVELCBSU19JTlRFUk1FRElBVEUsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICAgICAgaWYgKGV4cHItPmdldEV4cHJSb290KCktPmNvbnRhaW5zQW5BZ2dyZWdhdGUoKSkKICAgICAgICAgIHJld3JpdGUtPnNldFNlY29uZGFyeVJlc3VsdENvZGUoUkNfUk9MTFVQKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBBTVRfTUpWX0pROgogICAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgib3V0cHV0IGV4cHJlc3Npb24gJXMgaXMgbm90IFByb3ZpZGVkLiIsIAoJCQkJCSAgZXhwci0+Z2V0SUQoKS5kYXRhKCkpOwogICAgICAgIGJyZWFrOwogICAgfQogIH0KICBlbHNlCiAgewogICAgLy8gVGhlIGV4cHJlc3Npb24gaGFzIGlucHV0cy4gSXMgaXQgYW4gYWdncmVnYXRlIGV4cHJlc3Npb24gb24gYSBNQVY/CiAgICBpZiAoZXhwci0+Z2V0RXhwclJvb3QoKS0+Y29udGFpbnNBbkFnZ3JlZ2F0ZSgpICYmIAogICAgICAgIGNhbmRpZGF0ZV8tPmdldEFnZ3JlZ2F0ZU1hdGNoaW5nVHlwZSgpICE9IEFNVF9NSlZfQVEpCiAgICB7CiAgICAgIC8vIFllcywgaXRzIGFuIGFnZ3JlZ2F0ZSBleHByZXNzaW9uLiBEZWFsIHdpdGggaXQgaW4gUGFzcyAyLgogICAgICByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShleHByLCBOVUxMLCBSQ19OT1RQUk9WSURFRCwgUlNfSU5URVJNRURJQVRFLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogICAgICBpZiAoY2FuZGlkYXRlXy0+Z2V0QWdncmVnYXRlTWF0Y2hpbmdUeXBlKCkgPT0gQU1UX01BVl9BUV9ERykKICAgICAgICByZXdyaXRlLT5zZXRTZWNvbmRhcnlSZXN1bHRDb2RlKFJDX1JPTExVUCk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIC8vIE5vLiBUcnkgdG8gZmluZCBpdHMgaW5wdXQgY29sdW1ucy4KICAgICAgcmV3cml0ZSA9IGZpbmRFeHByZXNzaW9uSW5wdXRzKHF1ZXJ5SW5wdXRzLCBleHByKTsKICAgIH0KICB9CgogIHJldHVybiByZXdyaXRlOwp9ICAvLyBNYXRjaFRlc3Q6Om1hdGNoRXhwcmVzc2lvbigpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gQ2hlY2sgaWYgdGhlIE1WIHByb3ZpZGVzIGEgbWF0Y2hpbmcgb3V0cHV0IGV4cHJlc3Npb24sIGluY2x1ZGluZyBpdHMgCi8vIGlucHV0IGNvbHVtbnMuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBNYXRjaFRlc3Q6OmZpbmRNYXRjaGluZ012RXhwcmVzc2lvbihjb25zdCBRUkV4cGxpY2l0RXhwclB0ciBleHByKSAKewogIC8vIENoZWNrIGlmIHRoZSBNViBoYXMgYW4gb3V0cHV0IGV4cHJlc3Npb24gd2l0aCBtYXRjaGluZyB0ZXh0CiAgY29uc3QgTVZEZXRhaWxzUHRyIG12RGV0YWlscyA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpOwogIGNvbnN0IERlc2NyaXB0b3JEZXRhaWxzUHRyIHF1ZXJ5RGV0YWlscyA9IGNhbmRpZGF0ZV8tPmdldFF1ZXJ5RGV0YWlscygpOwoKICBOQVN0cmluZyBleHByVGV4dChoZWFwXyk7CiAgZXhwci0+dW5wYXJzZShleHByVGV4dCwgRkFMU0UpOwogIGNvbnN0IFFST3V0cHV0UHRyIG12T3V0cHV0MSA9IG12RGV0YWlscy0+Z2V0T3V0cHV0QnlFeHByVGV4dChleHByVGV4dCk7CiAgaWYgKG12T3V0cHV0MSA9PSBOVUxMKQogICAgcmV0dXJuIE5VTEw7CgogIC8vIE1WIG91dHB1dCBleHByZXNzaW9uIGZvdW5kLiBOb3cgbGV0cyBtYXRjaCBpdHMgaW5wdXQgY29sdW1ucy4KICBFbGVtZW50UHRyTGlzdCBxdWVyeUNvbExpc3QoaGVhcF8pOwogIGV4cHItPmdldElucHV0Q29sdW1ucyhxdWVyeUNvbExpc3QsIGhlYXBfKTsKCiAgLy8gVGhlIE1WIG1heSBoYXZlIHNldmVyYWwgb3V0cHV0IGV4cHJlc3Npb25zIHdpdGggdGhlIHNhbWUgbm9ybWFsaXplZCAKICAvLyBleHByZXNzaW9uIHRleHQsIGJ1dCBkaWZmZXJlbnQgaW5wdXQgY29sdW1ucy4gV2UgbmVlZCB0byBsb29wIG9uIHRoZW0sIAogIC8vIHNvIGlmIG9uZSBpcyBkaXNxdWFsaWZpZWQsIHdlIGNhbiBjaGVjayB0aGUgb3RoZXJzLgogIGNvbnN0IFFSRWxlbWVudEhhc2gmIG91dHB1dEJ5RXhwclRleHQgPSBtdkRldGFpbHMtPmdldE91dHB1dEJ5RXhwclRleHRIYXNoKCk7CiAgUVJFbGVtZW50SGFzaEl0ZXJhdG9yIGl0ZXJhdG9yKG91dHB1dEJ5RXhwclRleHQsICZleHByVGV4dCk7CgogIC8vIExvb3Agb24gdGhlIGl0ZXJhdG9yIG9uIGFsbCB0aGUgb3V0cHV0IGV4cHJlc3Npb25zIHdpdGggdGhlIHNhbWUgZXhwcmVzc2lvbiB0ZXh0LgogIGNvbnN0IE5BU3RyaW5nKiBrZXk7IC8vIHdlIGRvbid0IHJlYWxseSB1c2UgdGhpcyAtIGl0IHdpbGwgYWx3YXlzIGJlIGVxdWFsIHRvIGV4cHJUZXh0LgogIFFSRWxlbWVudFB0ciBtdk91dHB1dEVsZW07CiAgZm9yICggQ29sbEluZGV4IGo9MDsgajxpdGVyYXRvci5lbnRyaWVzKCk7IGorKykgCiAgewogICAgaXRlcmF0b3IuZ2V0TmV4dCAoa2V5LCBtdk91dHB1dEVsZW0pOyAKICAgIGNvbnN0IFFST3V0cHV0UHRyIG12T3V0cHV0ID0gbXZPdXRwdXRFbGVtLT5kb3duQ2FzdFRvUVJPdXRwdXQoKTsKCiAgICAvLyBHZXQgdG8gdGhlIGFjdHVhbCBNViBleHByZXNzaW9uCiAgICBRUkV4cHJQdHIgbXZFeHByID0gbXZPdXRwdXQtPmdldE91dHB1dEl0ZW0oKS0+Z2V0UmVmZXJlbmNlZEVsZW1lbnQoKS0+ZG93bkNhc3RUb1FSRXhwcigpOwoKICAgIC8vIE5vdyBtYXRjaCB0aGUgZXhwcmVzc2lvbidzIGlucHV0IGxpc3RzCiAgICBpZiAobWF0Y2hFeHByZXNzaW9uSW5wdXRzKHF1ZXJ5Q29sTGlzdCwgbXZFeHByLT5nZXRJbnB1dENvbHVtbnMoaGVhcF8pKSkKICAgIHsKICAgICAgLy8gVGhpcyBleHByZXNzaW9uIG1hdGNoZWQganVzdCBmaW5lLgogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gTlVMTDsKCiAgICAgIC8vIExldCdzIHNlZSBpZiB3ZSBjYW4gYWxzbyBmaW5kIHJld3JpdGUgaW5zdHJ1Y3Rpb25zIGZvciB0aGUgaW5kaXZpZHVhbCBpbnB1dCBjb2x1bW5zCiAgICAgIGlmIChxdWVyeUNvbExpc3QuZW50cmllcygpID09IDApCiAgICAgIHsKCS8vIFRoaXMgZXhwcmVzc2lvbiBoYXMgbm8gaW5wdXQgY29sdW1ucyAobWF5YmUgYSBDT1VOVCgqKT8gKQoJcmV3cml0ZSA9IG5ldyhoZWFwXykgCgkgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGV4cHIsIG12T3V0cHV0LCBSQ19QUk9WSURFRCwgUlNfRklOQUwsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7ICAKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKCS8vIEZpbmQgaWYgdGhlIGlucHV0IGNvbHVtbnMgYXJlIFByb3ZpZGVkLgoJcmV3cml0ZSA9IGZpbmRFeHByZXNzaW9uSW5wdXRzKHF1ZXJ5Q29sTGlzdCwgZXhwcik7CgogICAgICAgIGlmIChyZXdyaXRlICE9IE5VTEwpCiAgICAgICAgewogICAgICAgICAgIC8vIFZlcmlmeSB0aGF0IGFsbCB0aGUgaW5wdXQgY29sdW1ucyBhcmUgUHJvdmlkZWQuIAogICAgICAgICAgIGNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0c1B0ciBzdWJFbGVtZW50cyAgPSByZXdyaXRlLT5nZXRTdWJFbGVtZW50cygpOwogICAgICAgICAgIGlmIChzdWJFbGVtZW50cy0+ZW50cmllcygpICE9IHN1YkVsZW1lbnRzLT5wcm92aWRlZElucHV0c18uZW50cmllcygpKQogICAgICAgICAgIHsKICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBpZ25vcmUgdGhlIGlucHV0IGNvbHVtbnMgKGFuZCB1c2Ugb25seSB0aGUgZW50aXJlIGV4cHJlc3Npb24pLgogICAgICAgICAgICAgZGVsZXRlUHRyKHJld3JpdGUpOwogICAgICAgICAgICAgcmV3cml0ZSA9IE5VTEw7CiAgICAgICAgICAgfQogICAgICAgIH0KCglpZiAocmV3cml0ZSA9PSBOVUxMKQoJewoJICAvLyBObyAtIE5vdCBhbGwgaW5wdXQgY29sdW1ucyBhcmUgUHJvdmlkZWQuIE5vIGJpZyBkZWFsLCBqdXN0IHJldHVybgoJICAvLyB0aGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMgZm9yIHRoZSBlbnRpcmUgZXhwcmVzc2lvbi4KICAgICAgICAgIC8vIFVuZG8gdGhlIGRpc3F1YWxpZmljYXRpb24gb2YgdGhlIE1WIHdoZW4gZmluZGluZyBleHByZXNzaW9uIGlucHV0cy4KICAgICAgICAgIGNhbmRpZGF0ZV8tPnJlUXVhbGlmeSgpOwoJICByZXdyaXRlID0gbmV3KGhlYXBfKSAKCSAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShleHByLCBtdk91dHB1dCwgUkNfUFJPVklERUQsIFJTX0ZJTkFMLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwoJfQoJZWxzZQoJewoJICAvLyBZZXMsIENvbWJpbmUgdGhlIHR3by4KCSAgcmV3cml0ZS0+c2V0TXZFbGVtZW50KG12T3V0cHV0KTsKCSAgcmV3cml0ZS0+c2V0UmVzdWx0Q29kZShSQ19QUk9WSURFRCk7CgkgIHJld3JpdGUtPnNldFJlc3VsdFN0YXR1cyhSU19GSU5BTCk7Cgl9CiAgICAgIH0KICAgICAgcmV0dXJuIHJld3JpdGU7CiAgICB9CiAgICAvLyBUaGlzIGV4cHJlc3Npb24gZmFpbGVkIHRvIG1hdGNoIG9uIHRoZSBpbnB1dCBsaXN0LiBjb250aW51ZSB0byBuZXh0IGV4cHJlc3Npb24uCgogIH0gLy8gZm9yIG9uIGl0ZXJhdG9yLgoKICAvLyBBbGwgdGhlIGV4cHJlc3Npb25zIHdpdGggdGhlIG1hdGNoaW5nIHRleHQgZmFpbGVkIG9uIHRoZWlyIGlucHV0cy4KICByZXR1cm4gTlVMTDsKCn0gIC8vIE1hdGNoT3V0cHV0OjpmaW5kTWF0Y2hpbmdNdkV4cHJlc3Npb24oKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIFRoaXMgbWV0aG9kIGFjY2VwdHMgdHdvIGV4cHJlc3Npb24gaW5wdXQgbGlzdHMgYXMgaW5wdXRzOiBvbmUgZnJvbSB0aGUgcXVlcnkgCi8vIGFuZCBvbmUgZnJvbSB0aGUgTVYuIEJvdGggYXJlIGZyb20gZXhwcmVzc2lvbnMgd2l0aCB0aGUgc2FtZSBub3JtYWxpemVkIHByZWRpY2F0ZQovLyBleHByZXNzaW9uIHRleHQuIFRoaXMgbWV0aG9kIGNoZWNrcyBpZiB0aGUgbGlzdCBvZiBpbnB1dCBjb2x1bW5zIG1hdGNoIGFzIHdlbGwuCi8vIFRoaXMgbWV0aG9kIHJldHVybnMgVFJVRSB3aGVuIGEgbWF0Y2ggaXMgZm91bmQsIGFuZiBGQUxTRSBvdGhlcndpc2UuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hUZXN0OjptYXRjaEV4cHJlc3Npb25JbnB1dHMoY29uc3QgRWxlbWVudFB0ckxpc3QmIHF1ZXJ5SW5wdXRDb2x1bW5zLAoJCQkJCSAgIGNvbnN0IEVsZW1lbnRQdHJMaXN0JiBtdklucHV0Q29sdW1ucykKewogIC8vIFRoZSBpbnB1dCBsaXN0cyBtdXN0IGhhdmUgdGhlIHNhbWUgbnVtYmVyIG9mIGVudHJpZXMgdG8gbWF0Y2guCiAgaWYgKHF1ZXJ5SW5wdXRDb2x1bW5zLmVudHJpZXMoKSAhPSBtdklucHV0Q29sdW1ucy5lbnRyaWVzKCkpCiAgICByZXR1cm4gRkFMU0U7CiAKICBDb2xsSW5kZXggbWF4RW50cmllcyA9IG12SW5wdXRDb2x1bW5zLmVudHJpZXMoKTsKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8bWF4RW50cmllczsgaSsrKQogIHsKICAgIC8vIFRoZSBNViBhbmQgcXVlcnkgaW5wdXQgbGlzdHMgbXVzdCBiZSBvcmRlcmVkIGJ5IHRoZWlyIGFwcGVhcmFuY2UgaW4gdGhlIHByZWRpY2F0ZSBleHByZXNzaW9uLgogICAgLy8gVGhlIG1hdGNoQnlOYW1lKCkgbWV0aG9kIGlzIG9ubHkgaW1wbGVtZW50ZWQgZm9yIHRoZSBRUkNvbHVtbiBhbmQgUVJKb2luUHJlZCBjbGFzc2VzLgogICAgUVJDb2x1bW5QdHIgICBxdWVyeUNvbHVtbiA9IHF1ZXJ5SW5wdXRDb2x1bW5zW2ldLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpLT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKICAgIFFSSm9pblByZWRQdHIgcXVlcnlfanAgICAgPSBjYW5kaWRhdGVfLT5nZXRRdWVyeURldGFpbHMoKS0+Z2V0Sm9pblByZWQocXVlcnlDb2x1bW4pOwogICAgUVJDb2x1bW5QdHIgICBtdkNvbHVtbiAgICA9IG12SW5wdXRDb2x1bW5zW2ldLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpLT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKICAgIFFSSm9pblByZWRQdHIgbXZfanAgICAgICAgPSBjYW5kaWRhdGVfLT5nZXRRdWVyeURldGFpbHMoKS0+Z2V0Sm9pblByZWQobXZDb2x1bW4pOwoKICAgIGlmIChxdWVyeV9qcCA9PSBOVUxMKQogICAgewogICAgICAvLyBJZiB0aGUgcXVlcnkgaW5wdXQgaGFzIG5vIGVxdWktam9pbiBwcmVkcyBvbiBpdCwgdGhlIE1WIGlucHV0CiAgICAgIC8vIG11c3Qgbm90IGhhdmUgYW55IGVpdGhlci4KICAgICAgLy8gU28gaWYgdGhlIE1WIGlucHV0IGNvbHVtbiBpcyBhIGpvaW4gcHJlZCwgaXQgbXVzdCBiZSBhIGRpZmZlcmVudCBleHByZXNzaW9uLgogICAgICBpZiAobXZfanAgIT0gTlVMTCkKCXJldHVybiBGQUxTRTsKCiAgICAgIGlmIChtYXRjaENvbHVtbnNCeU5hbWVBbmRJRChxdWVyeUNvbHVtbiwgbXZDb2x1bW4pID09IEZBTFNFKQoJcmV0dXJuIEZBTFNFOwogICAgfQogICAgZWxzZSBpZiAocXVlcnlfanApCiAgICB7CiAgICAgIC8vIExldHMgY2hlY2sgdGhlIE1WIGlucHV0LgogICAgICBpZiAobXZfanAgIT0gTlVMTCkKICAgICAgewoJLy8gSXRzIGEgam9pbiBwcmVkLiBTaW5jZSBpbiBjYXNlIG9mIGEgbWF0Y2gsIHRoZSBxdWVyeSBqb2luIHByZWQKCS8vIG11c3QgYmUgYSBzdXBlcnNldCBvZiB0aGUgTVYgam9pbiBwcmVkLCB3ZSBjYW4ganVzdCBwaWNrIHRoZSBmaXJzdCAKCS8vIGNvbHVtbiBpbiB0aGUgam9pbiBwcmVkLCBhbmQgbWF0Y2ggaXQgdG8gYW55IGNvbHVtbiBpbiB0aGUgcXVlcnkgZXF1YWxpdHkgc2V0LgoJY29uc3QgRWxlbWVudFB0ckxpc3QmIG12RXF1YWxpdHlMaXN0ID0gbXZfanAtPmdldEVxdWFsaXR5TGlzdCgpOwoJbXZDb2x1bW4gPSBtdkVxdWFsaXR5TGlzdFswXS0+ZG93bkNhc3RUb1FSQ29sdW1uKCk7CiAgICAgIH0KCiAgICAgIC8vIE9LLCB3ZSBoYXZlIHRoZSBNViBpbnB1dCBjb2x1bW4sIG5vdyBtYXRjaCBpdCBhZ2FpbnN0IHRoZSBjb2x1bW5zIAogICAgICAvLyBpbiB0aGUgcXVlcnkgZXF1YWxpdHkgc2V0LgogICAgICBjb25zdCBFbGVtZW50UHRyTGlzdCYgcXVlcnlFcXVhbGl0eUxpc3QgPSBxdWVyeV9qcC0+Z2V0RXF1YWxpdHlMaXN0KCk7CiAgICAgIENvbGxJbmRleCBtYXhFbnRyaWVzID0gcXVlcnlFcXVhbGl0eUxpc3QuZW50cmllcygpOwogICAgICBOQUJvb2xlYW4gbWF0Y2hGb3VuZCA9IEZBTFNFOwogICAgICBmb3IgKENvbGxJbmRleCBqPTA7IGo8bWF4RW50cmllczsgaisrKQogICAgICB7Cgljb25zdCBRUkNvbHVtblB0ciBxdWVyeUNvbHVtbiA9IHF1ZXJ5RXF1YWxpdHlMaXN0W2pdLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpLT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKCWlmIChtYXRjaENvbHVtbnNCeU5hbWVBbmRJRChxdWVyeUNvbHVtbiwgbXZDb2x1bW4pKQoJewoJICAvLyBGb3VuZCBhIG1hdGNoIGZvciB0aGlzIGlucHV0LiBCcmVhayBmcm9tIHRoaXMgbG9vcCwgYW5kIGNvbnRpbnVlCgkgIC8vIHdpdGggdGhlIG5leHQgaW5wdXQuCgkgIG1hdGNoRm91bmQgPSBUUlVFOwoJICBicmVhazsKCX0KICAgICAgfQogICAgICAvLyBNYXRjaCBub3QgZm91bmQgZm9yIHRoaXMgaW5wdXQuIAogICAgICBpZiAobWF0Y2hGb3VuZCA9PSBGQUxTRSkKCXJldHVybiBGQUxTRTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQogIH0gLy8gZm9yCiAgcmV0dXJuIFRSVUU7Cn0gIC8vIE1hdGNoVGVzdDo6bWF0Y2hFeHByZXNzaW9uSW5wdXRzKCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBNYXRjaCBhbiBNViBjb2x1bW4gdG8gYSBxdWVyeSBjb2x1bW4gYnkgdGFibGUgSUQgYW5kIGNvbHVtbiBuYW1lLgovLyBTaW5jZSB0aGUgdHdvIGNvbHVtbnMgYXJlIGZyb20gZGlmZmVyZW50IGRlc2NyaXB0b3JzLCB0aGUgcXVlcnkgdGFibGUgSUQKLy8gbXVzdCBmaXJzdCBiZSB0cmFuc2xhdGVkIHRvIHRoZSBjb3JyZXNwb25kaW5nIHRhYmxlIElEIGZyb20gdGhlIE1WIGRlc2NyaXB0b3IuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hUZXN0OjptYXRjaENvbHVtbnNCeU5hbWVBbmRJRChjb25zdCBRUkNvbHVtblB0ciBxdWVyeUNvbHVtbiwgY29uc3QgUVJDb2x1bW5QdHIgbXZDb2x1bW4pCnsKICAvLyBNYXRjaCB0aGUgY29sdW1uIG5hbWUgZmlyc3QuCiAgaWYgKHF1ZXJ5Q29sdW1uLT5nZXRDb2x1bW5OYW1lKCkgIT0gbXZDb2x1bW4tPmdldENvbHVtbk5hbWUoKSkKICAgIHJldHVybiBGQUxTRTsKCiAgLy8gTm93IGNoZWNrIHRoZSB0YWJsZSBJRHMuCiAgY29uc3QgTkFTdHJpbmcmIHF1ZXJ5VGFibGVJRCA9IHF1ZXJ5Q29sdW1uLT5nZXRUYWJsZUlEKCk7CiAgY29uc3QgTkFTdHJpbmcmIG12VGFibGVJRCAgICA9IG12Q29sdW1uLT5nZXRUYWJsZUlEKCk7CiAgLy8gVHJhbnNsYXRlIHRoZSBxdWVyeSB0YWJsZUlEIHRvIHRoZSBjb3JyZXNwb25kaW5nIElEIGZyb20gdGhlIE1WIGRlc2NyaXB0b3IuCiAgY29uc3QgQmFzZVRhYmxlRGV0YWlsc1B0ciBiYXNlVGFibGUgPSBjYW5kaWRhdGVfLT5nZXRNdlRhYmxlRm9yUXVlcnlJRChxdWVyeVRhYmxlSUQsIEZBTFNFKTsKICBpZiAoYmFzZVRhYmxlID09IE5VTEwpCiAgICByZXR1cm4gRkFMU0U7CgogIC8vIEFyZSB0aGV5IHRoZSBzYW1lPwogIHJldHVybiAoYmFzZVRhYmxlLT5nZXRJRCgpID09IG12VGFibGVJRCk7Cn0gLy8gTWF0Y2hUZXN0OjptYXRjaENvbHVtbnNCeU5hbWVBbmRJRCgpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gQWRkIHRoZSBQcm92aWRlZCBhbmQgQmFja0pvaW4gaW5wdXRzIGFzIG91dHB1dHMgb2YgdGhlIE1WIGNhbmRpZGF0ZS4KLy8gSW4gY2FzZSB0aGUgb3B0aW1pemVyIHdpbGwgbm90IGJlIGFibGUgdG8gdXNlIHRoZSBQcm92aWRlZCBleHByZXNzaW9uLCAKLy8gaXQgd2lsbCB0cnkgdG8gdXNlIHRoZSBpbnB1dCBjb2x1bW5zLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKdm9pZCBNYXRjaFRlc3Q6OmFkZElucHV0c1RvT3V0cHV0TGlzdChSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgaWYgKGNhbmRpZGF0ZV8tPmdldEFnZ3JlZ2F0ZU1hdGNoaW5nVHlwZSgpID09IEFNVF9NQVZfQVFfREcpCiAgICByZXR1cm47CgogIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtTGlzdCYgcHJvdmlkZWRMaXN0ID0gcmV3cml0ZS0+Z2V0U3ViRWxlbWVudHMoKS0+cHJvdmlkZWRJbnB1dHNfOwogIENvbGxJbmRleCBtYXhFbnRyaWVzID0gcHJvdmlkZWRMaXN0LmVudHJpZXMoKTsKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBjb2x1bW5SZXdyaXRlID0gTlVMTDsKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8bWF4RW50cmllczsgaSsrKQogIHsKICAgIGNhbmRpZGF0ZV8tPmFkZE91dHB1dENvbHVtbihwcm92aWRlZExpc3RbaV0pOwogIH0KCiAgaWYgKHJld3JpdGUtPmdldFJlc3VsdENvZGUoKSA9PSBSQ19QUk9WSURFRCkKICAgIHJldHVybjsKCiAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1MaXN0JiBiYWNrSm9pbkxpc3QgPSByZXdyaXRlLT5nZXRTdWJFbGVtZW50cygpLT5iYWNrSm9pbklucHV0c187CiAgbWF4RW50cmllcyA9IGJhY2tKb2luTGlzdC5lbnRyaWVzKCk7CiAgZm9yIChDb2xsSW5kZXggaj0wOyBqPG1heEVudHJpZXM7IGorKykKICB7CiAgICBjYW5kaWRhdGVfLT5hZGRPdXRwdXRDb2x1bW4oYmFja0pvaW5MaXN0W2pdKTsKICB9CgogIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtTGlzdCYgZXh0cmFIdWJMaXN0ID0gcmV3cml0ZS0+Z2V0U3ViRWxlbWVudHMoKS0+ZXh0cmFodWJJbnB1dHNfOwogIG1heEVudHJpZXMgPSBleHRyYUh1Ykxpc3QuZW50cmllcygpOwogIGZvciAoQ29sbEluZGV4IGs9MDsgazxtYXhFbnRyaWVzOyBrKyspCiAgewogICAgY2FuZGlkYXRlXy0+YWRkT3V0cHV0Q29sdW1uKGV4dHJhSHViTGlzdFtrXSk7CiAgfQoKICAvLyBJZiB0aGUgZXhwcmVzc2lvbiBpdHNlbGYgaXMgbm90IFByb3ZpZGVkLCB3ZSBtYXkgYmUgYWJsZSB0byBza2lwIGl0CiAgLy8gYW5kIGxlYXZlIG9ubHkgdGhlIGlucHV0IGNvbHVtbnMuCiAgLy8gV2UgY2FuIGRvIHRoYXQgaWYgc29tZSBvZiBpdHMgaW5wdXRzIGFyZSBPdXRzaWRlLCBvciBpZiBpdHMgYW4KICAvLyBhZ2dyZWdhdGUgZXhwcmVzc2lvbiBvbiB0b3Agb2YgYW4gTUpWLgogIFFSRXhwclB0ciBleHByID0gTlVMTDsKICBRUkVsZW1lbnRQdHIgcXVlcnlFbGVtID0gcmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCk7CiAgaWYgKHF1ZXJ5RWxlbS0+Z2V0RWxlbWVudFR5cGUoKT09IEVUX1JhbmdlUHJlZCkKICB7CiAgICBRUlJhbmdlUHJlZFB0ciBwcmVkID0gc3RhdGljX2Nhc3Q8UVJSYW5nZVByZWRQdHI+KHF1ZXJ5RWxlbSk7CiAgICBleHByID0gcHJlZC0+Z2V0UmFuZ2VJdGVtKCktPmdldFJlZmVyZW5jZWRFbGVtZW50KCktPmRvd25DYXN0VG9RUkV4cHIoKTsKICB9CiAgZWxzZQogIHsKICAgIGV4cHIgPSByZXdyaXRlLT5nZXRBY3R1YWxRdWVyeUVsZW1lbnQoKS0+ZG93bkNhc3RUb1FSRXhwcigpOwogIH0KCiAgaWYgKHJld3JpdGUtPmdldFN1YkVsZW1lbnRzKCktPm91dHNpZGVJbnB1dHNfLmVudHJpZXMoKSA+IDAgfHwKICAgICAgKCBleHByLT5nZXRFeHByUm9vdCgpLT5jb250YWluc0FuQWdncmVnYXRlKCkgJiYKCWNhbmRpZGF0ZV8tPmdldEFnZ3JlZ2F0ZU1hdGNoaW5nVHlwZSgpID09IEFNVF9NSlZfQVEpICkKICB7CiAgICByZXdyaXRlLT5zZXRSZXN1bHRDb2RlKFJDX1NLSVBfTUUpOwogIH0KfSAgLy8gIGFkZElucHV0c1RvT3V0cHV0TGlzdCgpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gVXNlIGEgdmlzaXRvciB0byBmaW5kIGFnZ3JlZ2F0ZSBmdW5jdGlvbnMsIGFuZCBzb2x2ZSBhbnkgdGhhdCBhcmUgZm91bmQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBNYXRjaFRlc3Q6OmZpbmRJbnRlcm5hbEFnZ3JlZ2F0ZUZ1bmN0aW9ucyhRUkV4cGxpY2l0RXhwclB0ciB0cmVlRXhwcikKewogIEFnZ3JlZ2F0ZUNvbGxlY3RvclZpc2l0b3JQdHIgdmlzaXRvciA9IG5ldyhoZWFwXykgCiAgICBBZ2dyZWdhdGVDb2xsZWN0b3JWaXNpdG9yKEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgdHJlZUV4cHItPnRyZWVXYWxrKHZpc2l0b3IpOwoKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKHRyZWVFeHByLCBOVUxMLCBSQ19OT1RQUk9WSURFRCwgUlNfRklOQUwsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CgogIGlmIChjYW5kaWRhdGVfLT5nZXRBZ2dyZWdhdGVNYXRjaGluZ1R5cGUoKSA9PSBBTVRfTUFWX0FRX01HKQogIHsKICAgIHJld3JpdGUtPnNldFNlY29uZGFyeVJlc3VsdENvZGUoUkNfQUdHUl9FWFBSKTsKICB9CiAgZWxzZQogIHsKICAgIHJld3JpdGUtPnNldFNlY29uZGFyeVJlc3VsdENvZGUoUkNfUk9MTFVQX0VYUFIpOwogIH0KCiAgLy8gVHJ5IHRvIGZpbmQgYWxsIHRoZSBhZ2dyZWdhdGUgZnVuY3Rpb25zIHVzZWQgYnkgdGhlIGV4cHJlc3Npb24uCiAgRnVuY3Rpb25Ob2Rlc0xpc3QmIGFnZ3JGdW5jdGlvbnMgPSB2aXNpdG9yLT5nZXRBZ2dyZWdhdGVGdW5jdGlvbkxpc3QoKTsKICBDb2xsSW5kZXggbWF4RW50cmllcyA9IGFnZ3JGdW5jdGlvbnMuZW50cmllcygpOwogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxtYXhFbnRyaWVzOyBpKyspCiAgewogICAgLy8gTG9vayBmb3IgdGhlIGNvcnJlc3BvbmRpbmcgYWdncmVnYXRlIGZ1bmN0aW9uIGFzIGFuIE1WIG91dHB1dC4KICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIGZ1bmNSZXdyaXRlID0gZmluZEFnZ3JlZ2F0ZUZ1bmN0aW9uKGFnZ3JGdW5jdGlvbnNbaV0pOwogICAgaWYgKGZ1bmNSZXdyaXRlID09IE5VTEwpCiAgICB7CiAgICAgIGRlbGV0ZVB0cih2aXNpdG9yKTsKICAgICAgZGVsZXRlUHRyKHJld3JpdGUpOwogICAgICByZXR1cm4gTlVMTDsKICAgIH0KCiAgICAvLyBBZGQgaXQgdG8gdGhlIGV4cHJlc3Npb24gcmV3cml0ZSBpbnN0cnVjdGlvbnMuCiAgICByZXdyaXRlLT5hZGRTdWJFbGVtZW50KGZ1bmNSZXdyaXRlKTsKICB9IC8vIGZvcgoKICAvLyBDaGVjayBmb3IgYW55IGNvbHVtbnMgdXNlZCBpbiB0aGUgZXhwcmVzc2lvbnMgb3V0c2lkZSB0aGUgYWdncmVnYXRlIGZ1bmN0aW9ucy4KICBDb2x1bW5Ob2Rlc0xpc3QmIHNpbXBsZUNvbHMgPSB2aXNpdG9yLT5nZXRTaW1wbGVDb2x1bW5MaXN0KCk7CiAgbWF4RW50cmllcyA9IHNpbXBsZUNvbHMuZW50cmllcygpOwogIGZvciAoQ29sbEluZGV4IGo9MDsgajxtYXhFbnRyaWVzOyBqKyspCiAgewogICAgUVJDb2x1bW5QdHIgY29sID0gc2ltcGxlQ29sc1tqXS0+Z2V0UmVmZXJlbmNlZEVsZW1lbnQoKS0+ZG93bkNhc3RUb1FSQ29sdW1uKCk7CiAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBjb2xSZXdyaXRlID0gbWF0Y2hDb2x1bW4oY29sLCBGQUxTRSk7IAogICAgaWYgKGNvbFJld3JpdGUgIT0gTlVMTCAmJiAhY29sUmV3cml0ZS0+aXNGaW5hbCgpKQogICAgewogICAgICBkZWxldGVQdHIoY29sUmV3cml0ZSk7CiAgICAgIGNvbFJld3JpdGUgPSBOVUxMOwogICAgfQogICAgaWYgKGNvbFJld3JpdGUgPT0gTlVMTCkKICAgIHsKICAgICAgZGVsZXRlUHRyKHZpc2l0b3IpOwogICAgICBkZWxldGVQdHIocmV3cml0ZSk7CiAgICAgIHJldHVybiBOVUxMOwogICAgfQoKICAgIC8vIEFkZCBpdCB0byB0aGUgZXhwcmVzc2lvbiByZXdyaXRlIGluc3RydWN0aW9ucy4KICAgIHJld3JpdGUtPmFkZFN1YkVsZW1lbnQoY29sUmV3cml0ZSk7CiAgfQoKICAvLyBDaGVjayBmb3IgYW55IGpvaW4gcHJlZHMgdXNlZCBpbiB0aGUgZXhwcmVzc2lvbnMgb3V0c2lkZSB0aGUgYWdncmVnYXRlIGZ1bmN0aW9ucy4KICBKb2luUHJlZE5vZGVzTGlzdCYgam9pbmVkQ29scyA9IHZpc2l0b3ItPmdldEpvaW5lZENvbHVtbkxpc3QoKTsKICBtYXhFbnRyaWVzID0gam9pbmVkQ29scy5lbnRyaWVzKCk7CiAgZm9yIChDb2xsSW5kZXggaz0wOyBrPG1heEVudHJpZXM7IGsrKykKICB7CiAgICBRUkpvaW5QcmVkUHRyIGNvbCA9IGpvaW5lZENvbHNba10tPmdldFJlZmVyZW5jZWRFbGVtZW50KCktPmRvd25DYXN0VG9RUkpvaW5QcmVkKCk7CiAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBjb2xSZXdyaXRlID0gbWF0Y2hFcXVhbGl0eVNldChjb2wpOyAKICAgIGlmIChjb2xSZXdyaXRlICE9IE5VTEwgJiYgIWNvbFJld3JpdGUtPmlzRmluYWwoKSkKICAgIHsKICAgICAgZGVsZXRlUHRyKGNvbFJld3JpdGUpOwogICAgICBjb2xSZXdyaXRlID0gTlVMTDsKICAgIH0KICAgIGlmIChjb2xSZXdyaXRlID09IE5VTEwpCiAgICB7CiAgICAgIGRlbGV0ZVB0cih2aXNpdG9yKTsKICAgICAgZGVsZXRlUHRyKHJld3JpdGUpOwogICAgICByZXR1cm4gTlVMTDsKICAgIH0KCiAgICAvLyBBZGQgaXQgdG8gdGhlIGV4cHJlc3Npb24gcmV3cml0ZSBpbnN0cnVjdGlvbnMuCiAgICByZXdyaXRlLT5hZGRTdWJFbGVtZW50KGNvbFJld3JpdGUpOwogIH0KCiAgZGVsZXRlUHRyKHZpc2l0b3IpOwoKICByZXR1cm4gcmV3cml0ZTsKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBNYXRjaFRlc3Q6OmZpbmRBZ2dyZWdhdGVGdW5jdGlvbihRUkZ1bmN0aW9uUHRyIGZ1bmMpCnsKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gTlVMTDsKCiAgLy8gQ29sbGVjdCB0aGUgZnVuY3Rpb24ncyBpbnB1dCBjb2x1bW5zLgogIEVsZW1lbnRQdHJMaXN0IGlucHV0TGlzdChoZWFwXyk7CiAgUVJFeHBsaWNpdEV4cHJQdHIgZnVuY0FyZ3VtZW50ID0gZnVuYy0+Z2V0QXJndW1lbnRzKClbMF07CiAgZnVuY0FyZ3VtZW50LT5nZXRJbnB1dENvbHVtbnMoaW5wdXRMaXN0LCBoZWFwXywgVFJVRSk7CgogIC8vIElzIHRoaXMgYSByb2xsdXAgY2FzZT8KICBpZiAoY2FuZGlkYXRlXy0+Z2V0QWdncmVnYXRlTWF0Y2hpbmdUeXBlKCkgPT0gQU1UX01BVl9BUV9ERykKICB7CiAgICAvLyBDaGVjayBmb3IgQ09VTlQoKikgYXMgYSBzcGVjaWFsIGNhc2UKICAgIGlmIChmdW5jLT5nZXRBZ2dyZWdhdGVGdW5jKCkgPT0gUVJGdW5jdGlvbjo6QUZUX0NPVU5UU1RBUikKICAgIHsKICAgICAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0oZnVuYywgTlVMTCwgUkNfTk9UUFJPVklERUQsIFJTX0ZJTkFMLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogICAgICByZXdyaXRlLT5zZXRTZWNvbmRhcnlSZXN1bHRDb2RlKFJDX1JPTExVUF9PTl9HUk9VUElORyk7CiAgICAgIHJldHVybiByZXdyaXRlOwogICAgfQoKICAgIC8vIE1heWJlIGl0cyBhIHJvbGx1cCBvbiBhIGdyb3VwaW5nIGNvbHVtbj8KICAgIGlmIChhcmVBbGxJbnB1dHNHcm91cGluZ0NvbHVtbnMoZnVuYywgaW5wdXRMaXN0KSkKICAgIHsKICAgICAgLy8gQWxsIHRoZSBpbnB1dCBjb2x1bW5zIGFyZSBNViBncm91cGluZyBjb2x1bW5zLgogICAgICAvLyBOb3cgY2hlY2sgdGhhdCB0aGV5IGFyZSBQcm92aWRlZCBieSB0aGUgTVYuCiAgICAgIHJld3JpdGUgPSBmaW5kRXhwcmVzc2lvbklucHV0cyhpbnB1dExpc3QsIGZ1bmMpOwogICAgICBpZiAocmV3cml0ZSA9PSBOVUxMKQogICAgICAgIHJldHVybiBOVUxMOwoKICAgICAgaWYgKCFyZXdyaXRlLT5pc0ZpbmFsKCkpCiAgICAgIHsKICAgICAgICBkZWxldGVQdHIocmV3cml0ZSk7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICAgIH0KCiAgICAgIHJld3JpdGUtPnNldFNlY29uZGFyeVJlc3VsdENvZGUoUkNfUk9MTFVQX09OX0dST1VQSU5HKTsKICAgICAgcmV0dXJuIHJld3JpdGU7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIC8vIFJvbGx1cCwgYnV0IG5vdCBvbiBNViBncm91cGluZyBjb2x1bW5zLgogICAgICAvLyBEbyBub3QgYWxsb3cgZGlzdGluY3QgYWdncmVnYXRlIGZ1bmN0aW9ucyB0byBtYXRjaC4KICAgICAgaWYgKGZ1bmMtPmlzRGlzdGluY3RBZ2dyZWdhdGUoKSApCiAgICAgIHsKICAgICAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIkRJU1RJTkNUIGFnZ3JlZ2F0ZSBmdW5jdGlvbiAlcyBjYW5ub3QgYmUgcm9sbGVkIHVwLiIsCgkJCQkgICAgICAgICAgZnVuYy0+Z2V0SUQoKS5kYXRhKCkpOwogICAgICAgIHJldHVybiBOVUxMOwogICAgICB9CiAgICB9CiAgfSAgLy8gaWYgKHJvbGx1cCkKCiAgLy8gV2UgZ2V0IGhlcmUgaWYgaXRzIG5vdCBhIHJvbGx1cCBjYXNlLCBvciBpZiBpdHMgYSByb2xsdXAgY2FzZSBidXQKICAvLyBub3Qgb24gTVYgZ3JvdXBpbmcgY29sdW1ucy4KICAvLyBMb29rIGZvciB0aGUgY29ycmVzcG9uZGluZyBhZ2dyZWdhdGUgZnVuY3Rpb24gYXMgYW4gTVYgb3V0cHV0LgogIHJld3JpdGUgPSBmaW5kTWF0Y2hpbmdNdkV4cHJlc3Npb24oZnVuYyk7CiAgaWYgKHJld3JpdGUgIT0gTlVMTCkKICB7CiAgICBpZiAocmV3cml0ZS0+aXNGaW5hbCgpKQogICAgICByZXR1cm4gcmV3cml0ZTsKICAgIGVsc2UKICAgICAgZGVsZXRlUHRyKHJld3JpdGUpOwogIH0KCiAgLy8gTGFzdCB0cnkgLSBtYXliZSB0aGlzIGlzIGEgQ09VTlQoY29sKSBvbiBhIE5PVCBOVUxMIGNvbHVtbiwKICAvLyBzbyB3ZSBjYW4gdXNlIENPVU5UKCopIGluc3RlYWQ/CiAgUVJPdXRwdXRQdHIgY291bnRTdGFyT3V0cHV0ID0gY2FuZGlkYXRlXy0+Z2V0TXZEZXRhaWxzKCktPmdldENvdW50U3RhcigpOwogIGlmIChmdW5jLT5nZXRBZ2dyZWdhdGVGdW5jKCkgPT0gUVJGdW5jdGlvbjo6QUZUX0NPVU5UICYmIGNvdW50U3Rhck91dHB1dCAhPSBOVUxMKQogIHsKICAgIC8vIE9LLCB0aGlzIGlzIGEgQ09VTlQoKSBmdW5jdGlvbiwgYW5kIHRoZSBNViBoYXMgYSBDT1VOVCgqKSBvdXRwdXQuCiAgICAvLyBDaGVjayB0aGF0IGFsbCB0aGUgaW5wdXQgY29sdW1ucyBhcmUgbm90IG51bGxhYmxlLgogICAgaWYgKGZ1bmMtPmlzQ291bnRTdGFyRXF1aXZhbGVudChoZWFwXykpCiAgICB7CiAgICAgIC8vIFllcyEgLSB3ZSBjYW4gdXNlIENPVU5UKCopIGluc3RlYWQuCiAgICAgIHJld3JpdGUgPSBuZXcoaGVhcF8pIAogICAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGZ1bmMsIGNvdW50U3Rhck91dHB1dCwgUkNfUFJPVklERUQsIFJTX0ZJTkFMLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogICAgICByZXR1cm4gcmV3cml0ZTsKICAgIH0KICB9CgogIC8vIEdpdmUgdXAgb24gdGhpcyBhZ2dyZWdhdGUgZnVuY3Rpb24uCiAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJhZ2dyZWdhdGUgZnVuY3Rpb24gJXMgY2Fubm90IGJlIG1hdGNoZWQuIiwKCQkJCSAgICBmdW5jLT5nZXRJRCgpLmRhdGEoKSk7CiAgcmV0dXJuIE5VTEw7Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBUaGUgZXh0cmEgZ3JvdXBpbmcgY29sdW1ucyBhcmUgdGhlIG9uZXMgYmVpbmcgcm9sbGVkIHVwIJYgY29sdW1ucyB0aGF0IAovLyBhcmUgaW4gdGhlIE1WknMgZ3JvdXBpbmcgbGlzdCwgYnV0IG5vdCBpbiB0aGUgcXVlcnmScyBncm91cGluZyBsaXN0LiBBbiAKLy8gYWdncmVnYXRlIGZ1bmN0aW9uIGlzIG9uIGFuIE1WIGdyb3VwaW5nIGNvbHVtbiB3aGVuIGl0cyBpbnB1dHMgYXJlIGluIHRoaXMgbGlzdC4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCk5BQm9vbGVhbiBNYXRjaFRlc3Q6OmFyZUFsbElucHV0c0dyb3VwaW5nQ29sdW1ucyhRUkZ1bmN0aW9uUHRyIGZ1bmMsIEVsZW1lbnRQdHJMaXN0JiBpbnB1dExpc3QpCnsKICAvLyBBcmUgYWxsIHRoZSBpbnB1dHMgTVYgZ3JvdXBpbmcgY29sdW1ucz8KICBmb3IgKENvbGxJbmRleCBpPTA7IGk8aW5wdXRMaXN0LmVudHJpZXMoKTsgaSsrKQogIHsKICAgIGNvbnN0IFFSQ29sdW1uUHRyIGlucHV0Q29sID0gaW5wdXRMaXN0W2ldLT5nZXRGaXJzdENvbHVtbigpOwogICAgaWYgKCFpc0V4dHJhR3JvdXBpbmdDb2x1bW4oaW5wdXRDb2wpKQogICAgICByZXR1cm4gRkFMU0U7CiAgfQoKICByZXR1cm4gVFJVRTsKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIEdlbmVyYXRlIGEgcmVzdWx0IFFSRXhwciBlbGVtZW50IGZvciBhbiBleHByZXNzaW9uIGludm9sdmluZyBhZ2dyZWdhdGUgZnVuY3Rpb25zLgovLyBUaGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMgZm9yIHRoZSBpbmRpdmlkdWFsIGFnZ3JlZ2F0ZSBmdW5jdGlvbnMgaGF2ZSBhbHJlYWR5Ci8vIGJlZW4gcHJlcGFyZWQgYXMgUHJvdmlkZWQgc3ViRWxlbWVudHMsIGJ5IHRoZSBQYXNzIDIgY29kZS4KLy8gRmlyc3Qgd2UgZ28gb3ZlciB0aGUgbGlzdCBvZiBzdWJFbGVtZW50cywgY3JlYXRpbmcgYW4gTVZDb2x1bW4gZWxlbWVudCBmb3IKLy8gZWFjaCBhZ2dyZWdhdGUgZnVuY3Rpb24gdXNlZCBpbiB0aGUgZXhwcmVzc2lvbi4gRWFjaCBNVkNvbHVtbiBlbGVtZW50IGlzIAovLyBpbnNlcnRlZCBpbnRvIGEgaGFzaCB0YWJsZSwgd2l0aCB0aGUgSUQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgcXVlcnkgc3ViLWV4cHJlc3Npb24KLy8gYXMgdGhlIGtleS4gVGhlbiB3ZSBtYWtlIGEgZGVlcCBjb3B5IG9mIHRoZSBxdWVyeSBleHByZXNzaW9uIHRyZWUsIGFuZCBpbgovLyB0aGUgcHJvY2Vzcywgc3dpdGNoIGV2ZXJ5IHN1Yi1leHByZXNzaW9uIHdob3NlIElEIHdlIGZpbmQgaW4gdGhlIGhhc2ggdGFibGUKLy8gd2l0aCB0aGUgY29ycmVzcG9uZGluZyBNVkNvbHVtbiBlbGVtZW50LgovLyBGaW5hbHksIHRoZSBvdXRwdXQgZXhwcmVzc2lvbiBpdHNlbGYgaXMgY3JlYXRlZCwgcmVmZXJlbmNpbmcgdGhlIHF1ZXJ5IG9uZS4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqClFSRXhwclB0ciBNYXRjaFRlc3Q6OmdlbmVyYXRlQWdncmVnYXRlRXhwcmVzc2lvbk91dHB1dChSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgLy8gSW5pdCB0aGUgaGFzaCB0YWJsZS4KICBzdWJFeHByZXNzaW9uUmV3cml0ZUhhc2ggc3ViRXhwckhhc2goaGFzaEtleSwgSU5JVF9IQVNIX1NJWkVfU01BTEwsIEZBTFNFLCBoZWFwXyk7CgogIGNvbXBvc2l0ZU1hdGNoaW5nUmVzdWx0c1B0ciBzdWJFeHBycyA9IHJld3JpdGUtPmdldFN1YkVsZW1lbnRzKCk7CiAgLy8gVmVyaWZ5IGFsbCB0aGUgc3ViRWxlbWVudHMgYXJlIFByb3ZpZGVkLgogIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAgICBzdWJFeHBycy0+ZW50cmllcygpID09IHN1YkV4cHJzLT5wcm92aWRlZElucHV0c18uZW50cmllcygpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyBzdWJFeHBycy0+bm90UHJvdmlkZWRJbnB1dHNfLmVudHJpZXMoKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgc3ViRXhwcnMtPmJhY2tKb2luSW5wdXRzXy5lbnRyaWVzKCksCiAgICAgICAgICAgICAgICAgICAgICAgUVJMb2dpY0V4Y2VwdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgICAiRXhwZWN0aW5nIGFsbCBzdWJleHByZXNzaW9ucyB0byBiZSBQcm92aWRlZCwgTm90UHJvdmlkZWQsIG9yIGJhY2sgam9pbi4iKTsKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbUxpc3QgcmV3cml0ZUxpc3QoaGVhcF8pOwogIHJld3JpdGVMaXN0Lmluc2VydChzdWJFeHBycy0+cHJvdmlkZWRJbnB1dHNfKTsKICByZXdyaXRlTGlzdC5pbnNlcnQoc3ViRXhwcnMtPm5vdFByb3ZpZGVkSW5wdXRzXyk7CiAgcmV3cml0ZUxpc3QuaW5zZXJ0KHN1YkV4cHJzLT5iYWNrSm9pbklucHV0c18pOwoKICAvLyBGb3IgZWFjaCBzdWJFbGVtZW50CiAgQ29sbEluZGV4IG1heEVudHJpZXMgPSBzdWJFeHBycy0+ZW50cmllcygpOwogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxtYXhFbnRyaWVzOyBpKyspCiAgewogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgc3ViRXhwclJld3JpdGUgPSByZXdyaXRlTGlzdFtpXTsKICAgIGNvbnN0IE5BU3RyaW5nJiBrZXkgPSBzdWJFeHByUmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCk7CiAgICBRUkV4cGxpY2l0RXhwclB0ciBleHByUmV3cml0ZSA9IE5VTEw7CgogICAgaWYgKGNhbmRpZGF0ZV8tPmdldEFnZ3JlZ2F0ZU1hdGNoaW5nVHlwZSgpID09IEFNVF9NQVZfQVFfREcpCiAgICB7CiAgICAgIGlmIChzdWJFeHByUmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCktPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfRnVuY3Rpb24pCiAgICAgIHsKICAgICAgICAvLyBUaGlzIGlzIGEgcm9sbGVkLXVwIGFnZ3JlZ2F0ZSBmdW5jdGlvbi4KICAgICAgICBpZiAoc3ViRXhwclJld3JpdGUtPmdldFNlY29uZGFyeVJlc3VsdENvZGUoKSAhPSBSQ19ST0xMVVBfT05fR1JPVVBJTkcpCiAgICAgICAgewogICAgICAgICAgLy8gVGhpcyBpcyBhIG5vcm1hbCBSb2xsdXAgY2FzZS4gQWRkaXRpb25hbCBhZ2dyZWdhdGlvbiBpcyBuZWVkZWQgYWJvdmUgdGhlIE1WQ29sdW1uLgogICAgICAgICAgZXhwclJld3JpdGUgPSBnZW5lcmF0ZVJvbGx1cEFnZ3JlZ2F0ZUZ1bmN0aW9uKHN1YkV4cHJSZXdyaXRlKTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgIC8vIFRoaXMgcm9sbHVwIG92ZXIgYSBncm91cGluZyBjb2x1bW4uIAogICAgICAgICAgZXhwclJld3JpdGUgPSBnZW5lcmF0ZVJvbGx1cE92ZXJHcm91cGluZ0FnZ3JlZ2F0ZUZ1bmN0aW9uKHN1YkV4cHJSZXdyaXRlKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgLy8gVGhpcyBpcyBhIGdyb3VwaW5nIGNvbHVtbiB1c2VkIGluIHRoZSBleHByZXNzaW9uLgogICAgICAgIGV4cHJSZXdyaXRlID0gZ2VuZXJhdGVQcm92aWRlZE12Q29sdW1uKHN1YkV4cHJSZXdyaXRlKTsKICAgICAgfQogICAgfQogICAgZWxzZQogICAgewogICAgICAvLyBUaGlzIGlzIGEgbWF0Y2hpbmcgZ3JvdXBpbmcgbGlzdC4gRXZlcnkgbWF0Y2hlZCBzdWItZXhwcmVzc2lvbgogICAgICAvLyBpcyBhIFByb3ZpZGVkIE1WQ29sdW1uLgogICAgICBpZiAoc3ViRXhwclJld3JpdGUtPmdldFNlY29uZGFyeVJlc3VsdENvZGUoKSA9PSBSQ19CQUNLSk9JTikKICAgICAgICBleHByUmV3cml0ZSA9IGdlbmVyYXRlTm90UHJvdmlkZWRDb2x1bW4oc3ViRXhwclJld3JpdGUpOwogICAgICBlbHNlCiAgICAgICAgZXhwclJld3JpdGUgPSBnZW5lcmF0ZVByb3ZpZGVkTXZDb2x1bW4oc3ViRXhwclJld3JpdGUpOwogICAgfQoKICAgIGlmIChleHByUmV3cml0ZSA9PSBOVUxMKQogICAgewogICAgICBjbGVhbnVwU3ViRXhwckhhc2goc3ViRXhwckhhc2gpOwogICAgICByZXR1cm4gTlVMTDsKICAgIH0KICAgIHN1YkV4cHJIYXNoLmluc2VydCgma2V5LCBleHByUmV3cml0ZSk7CiAgfQoKICAvLyBDcmVhdGUgdGhlIHJlc3VsdCBleHByZXNzaW9uIHRyZWUgZnJvbSB0aGUgcXVlcnkgZXhwcmVzc2lvbiB0cmVlLCB3aXRoIAogIC8vIHRoZSBuZWVkZWQgc3ViLWV4cHJlc3Npb25zIHN3aXRjaGVkIHRvIE1WQ29sdW1uIGVsZW1lbnRzLgogIFFSRXhwclB0ciBxdWVyeUV4cHIgPSByZXdyaXRlLT5nZXRBY3R1YWxRdWVyeUVsZW1lbnQoKS0+Z2V0UmVmZXJlbmNlZEVsZW1lbnQoKS0+ZG93bkNhc3RUb1FSRXhwcigpOwogIFFSRXhwbGljaXRFeHByUHRyIHJlc3VsdFRyZWVFeHByID0gTlVMTDsKICB0cnkKICB7CiAgICByZXN1bHRUcmVlRXhwciA9IHF1ZXJ5RXhwci0+Z2V0RXhwclJvb3QoKS0+ZGVlcENvcHlBbmRTd2l0Y2goc3ViRXhwckhhc2gsIGhlYXBfKTsKICB9CiAgY2F0Y2goUVJEZXNjcmlwdG9yRXhjZXB0aW9uIGV4KQogIHsKICAgIC8vIFdlIGdldCBoZXJlIGlmIHdlIGNhbm5vdCBwcm9wZXJseSByZXdyaXRlIGFsbCB0aGUgcXVlcnkgY29sdW1uIGVsZW1lbnRzLgogICAgLy8gUmVsZWFzZSBvYmplY3RzIHN0b3JlZCBpbiBzdWJFeHBySGFzaCBiZWZvcmUgcmV0dXJuaW5nLgogICAgY2xlYW51cFN1YkV4cHJIYXNoKHN1YkV4cHJIYXNoKTsKICAgIHJldHVybiBOVUxMOwogIH0KCiAgLy8gQ3JlYXRlIHRoZSBleHByZXNzaW9uIG9uIHRvcCBvZiBpdC4KICBRUkV4cHJQdHIgZXhwciA9IG5ldyhoZWFwXykgUVJFeHByKEZBTFNFLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogIGV4cHItPnNldEV4cHJSb290KHJlc3VsdFRyZWVFeHByKTsKICBleHByLT5zZXRSZWYocXVlcnlFeHByLT5nZXRJRCgpKTsKCiAgcmV0dXJuIGV4cHI7Cn0gIC8vIGdlbmVyYXRlQWdncmVnYXRlRXhwcmVzc2lvbk91dHB1dCgpCgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCnZvaWQgTWF0Y2hUZXN0OjpjbGVhbnVwU3ViRXhwckhhc2goc3ViRXhwcmVzc2lvblJld3JpdGVIYXNoJiBzdWJFeHBySGFzaCkKewogIHN1YkV4cHJlc3Npb25SZXdyaXRlSGFzaEl0ZXJhdG9yIGl0ZXIoc3ViRXhwckhhc2gpOwogIGNvbnN0IE5BU3RyaW5nKiBrZXk7CiAgUVJFeHBsaWNpdEV4cHJQdHIgdmFsdWU7CiAgZm9yIChDb2xsSW5kZXggeCA9IDA7IHggPCBpdGVyLmVudHJpZXMoKTsgeCsrKSAKICB7CiAgICAvLyBHZXQgdGhlIG5leHQgc3ViIGV4cHJlc3Npb24uCiAgICBpdGVyLmdldE5leHQoa2V5LCB2YWx1ZSk7IAogICAgZGVsZXRlUHRyKHZhbHVlKTsKICB9Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KTkFCb29sZWFuIE1hdGNoVGVzdDo6aXNFeHRyYUdyb3VwaW5nQ29sdW1uKFFSQ29sdW1uUHRyIGNvbCkKewogIEdyb3VwaW5nTGlzdCoJZXh0cmFzID0gY2FuZGlkYXRlXy0+Z2V0RXh0cmFHcm91cGluZ0NvbHVtbnMoKTsKICBDb2xsSW5kZXggbWF4RW50cmllcyA9IGV4dHJhcy0+ZW50cmllcygpOwoKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8bWF4RW50cmllczsgaSsrKQogIHsKICAgIFFSRWxlbWVudFB0ciBlbGVtID0gKCpleHRyYXMpW2ldLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpOwoKICAgIC8vIEhhbmRsZSBzaW1wbGUgY29sdW1ucy4KICAgIGlmIChlbGVtLT5nZXRFbGVtZW50VHlwZSgpID09IEVUX0NvbHVtbikKICAgIHsKICAgICAgUVJDb2x1bW5QdHIgZ3JvdXBpbmdDb2wgPSBlbGVtLT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKICAgICAgaWYgKG1hdGNoQ29sdW1uc0J5TmFtZUFuZElEKGNvbCwgZ3JvdXBpbmdDb2wpKQogICAgICAgIHJldHVybiBUUlVFOwogICAgfQoKICAgIC8vIEhhbmRsZSBlcXVhbGl0eSBzZXRzIC0gY2hlY2sgZXZlcnkgZWxlbWVudCBpbiB0aGUgc2V0LgogICAgaWYgKGVsZW0tPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfSm9pblByZWQpCiAgICB7CiAgICAgIGNvbnN0IFFSSm9pblByZWRQdHIgbXZKb2luUHJlZCA9IGVsZW0tPmRvd25DYXN0VG9RUkpvaW5QcmVkKCk7CiAgICAgIGNvbnN0IEVsZW1lbnRQdHJMaXN0JiBtdkVxdWFsaXR5TGlzdCA9IG12Sm9pblByZWQtPmdldEVxdWFsaXR5TGlzdCgpOwogICAgICBDb2xsSW5kZXggZXFTZXRTaXplID0gbXZFcXVhbGl0eUxpc3QuZW50cmllcygpOwogICAgICBmb3IgKENvbGxJbmRleCBqPTA7IGo8ZXFTZXRTaXplOyBqKyspCiAgICAgIHsKCWNvbnN0IFFSRWxlbWVudFB0ciBlcUVsZW1lbnQgPSBtdkVxdWFsaXR5TGlzdFtqXTsKICAgICAgICBpZiAoZXFFbGVtZW50LT5nZXRFbGVtZW50VHlwZSgpICE9IEVUX0NvbHVtbikKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIGNvbnN0IFFSQ29sdW1uUHRyIGVxQ29sID0gZXFFbGVtZW50LT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKICAgICAgICBpZiAobWF0Y2hDb2x1bW5zQnlOYW1lQW5kSUQoY29sLCBlcUNvbCkpCiAgICAgICAgICByZXR1cm4gVFJVRTsKICAgICAgfQogICAgfQogIH0KCiAgcmV0dXJuIEZBTFNFOwp9CgoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpRUkZ1bmN0aW9uUHRyIE1hdGNoVGVzdDo6Z2VuZXJhdGVSb2xsdXBBZ2dyZWdhdGVGdW5jdGlvbihSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgLy8gVGhpcyBpcyB0aGUgcXVlcnkgYWdncmVnYXRlIGZ1bmN0aW9uLgogIFFSRWxlbWVudFB0ciBxdWVyeUVsZW0gPSByZXdyaXRlLT5nZXRBY3R1YWxRdWVyeUVsZW1lbnQoKTsKICBRUkZ1bmN0aW9uUHRyIHF1ZXJ5RnVuY3Rpb247CiAgaWYgKHF1ZXJ5RWxlbS0+Z2V0RWxlbWVudFR5cGUoKSA9PSBFVF9FeHByKQogIHsKICAgIHF1ZXJ5RnVuY3Rpb24gPSBxdWVyeUVsZW0tPmRvd25DYXN0VG9RUkV4cHIoKS0+Z2V0RXhwclJvb3QoKS0+ZG93bkNhc3RUb1FSRnVuY3Rpb24oKTsKICB9CiAgZWxzZQogIHsKICAgIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5RWxlbS0+Z2V0RWxlbWVudFR5cGUoKSA9PSBFVF9GdW5jdGlvbiwgUVJMb2dpY0V4Y2VwdGlvbiwgCiAgICAJCSAgICAgICJFeHBlY3RpbmcgZWl0aGVyIGEgUVJFeHByIG9yIFFSRnVuY3Rpb24uIik7CiAgICBxdWVyeUZ1bmN0aW9uID0gcXVlcnlFbGVtLT5kb3duQ2FzdFRvUVJGdW5jdGlvbigpOwogIH0KCiAgTkFTdHJpbmcgYWdnck5hbWUoaGVhcF8pOwogIFFSRnVuY3Rpb246OkFnZ3JlZ2F0ZUZ1bmN0aW9uVHlwZSBhZ2dyVHlwZSA9IFFSRnVuY3Rpb246OkFGVF9OT05FOwogIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAhcXVlcnlGdW5jdGlvbi0+aXNEaXN0aW5jdEFnZ3JlZ2F0ZSgpLCBRUkxvZ2ljRXhjZXB0aW9uLCAKCQkgICAgIkRJU1RJTkNUIGFnZ3JlZ2F0ZSBmdWN0dGlvbnMgY2Fubm90IGJlIHJvbGxlZCB1cC4iKTsKCiAgc3dpdGNoIChxdWVyeUZ1bmN0aW9uLT5nZXRBZ2dyZWdhdGVGdW5jKCkpCiAgewogICAgY2FzZSBRUkZ1bmN0aW9uOjpBRlRfU1VNOgogICAgY2FzZSBRUkZ1bmN0aW9uOjpBRlRfTUlOOgogICAgY2FzZSBRUkZ1bmN0aW9uOjpBRlRfTUFYOgogICAgY2FzZSBRUkZ1bmN0aW9uOjpBRlRfT05FUk9XOgogICAgY2FzZSBRUkZ1bmN0aW9uOjpBRlRfQU5ZX1RSVUU6CiAgICAgIC8vIFNVTSwgTUlOIGFuZCBNQVgsIGFzIHdlbGwgYXMgT05FUk9XIGFuZCBBTllfVFJVRQogICAgICAvLyB1c2UgdGhlIHNhbWUgYWdncmVnYXRlIGZ1bmN0aW9uIGluIHRoZSByb2xsdXAuCiAgICAgIGFnZ3JOYW1lID0gcXVlcnlGdW5jdGlvbi0+Z2V0RnVuY3Rpb25OYW1lKCk7CiAgICAgIGFnZ3JUeXBlID0gcXVlcnlGdW5jdGlvbi0+Z2V0QWdncmVnYXRlRnVuYygpOwogICAgICBicmVhazsKCiAgICBjYXNlIFFSRnVuY3Rpb246OkFGVF9DT1VOVDoKICAgIGNhc2UgUVJGdW5jdGlvbjo6QUZUX0NPVU5UU1RBUjoKICAgICAgLy8gQ09VTlQgbmVlZHMgU1VNIHRvIGJlIGNhbGN1bGF0ZWQgaW4gdGhlIHJvbGx1cC4KICAgICAgYWdnck5hbWUgPSAic3VtIjsKICAgICAgYWdnclR5cGUgPSBRUkZ1bmN0aW9uOjpBRlRfU1VNOwogICAgICBicmVhazsKCiAgICBjYXNlIFFSRnVuY3Rpb246OkFGVF9PTkVfVFJVRToKICAgICAgLy8gT05FX1RSVUUgbmVlZHMgQU5ZX1RSVUUgdG8gYmUgY2FsY3VsYXRlZCBpbiB0aGUgcm9sbHVwLgogICAgICBhZ2dyTmFtZSA9ICJhbnlfdHJ1ZSI7CiAgICAgIGFnZ3JUeXBlID0gUVJGdW5jdGlvbjo6QUZUX0FOWV9UUlVFOwogICAgICBicmVhazsKCiAgICBjYXNlIFFSRnVuY3Rpb246OkFGVF9PTkVfUk9XOgogICAgICAvLyBPTkVfUk9XIGlzIHRoZSBvbGQgaW1wbGVtZW50YXRpb24gb2YgT05FUk9XLCBhbmQgY2Fubm90IGJlIHJvbGxlZCB1cC4KICAgICAgYXNzZXJ0TG9nQW5kVGhyb3cxKENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAgICAgIEZBTFNFLCBRUkxvZ2ljRXhjZXB0aW9uLCAKCSAgICAgICAgICAgICAgICAgIkFnZ3JlZ2F0ZSBmdW5jdGlvbiAlcyBjYW5ub3QgYmUgcm9sbGVkIHVwLiIsIHF1ZXJ5RnVuY3Rpb24tPmdldEZ1bmN0aW9uTmFtZSgpLmRhdGEoKSk7CiAgICAgIGJyZWFrOwogIH0KCiAgLy8gQ3JlYXRlIHRoZSBuZXcgYWdncmVnYXRlIGZ1bmN0aW9uLgogIFFSRnVuY3Rpb25QdHIgcm9sbHVwRnVuY3Rpb24gPSBuZXcoaGVhcF8pIFFSRnVuY3Rpb24oQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICByb2xsdXBGdW5jdGlvbi0+c2V0RnVuY3Rpb25OYW1lKGFnZ3JOYW1lKTsKICByb2xsdXBGdW5jdGlvbi0+c2V0QWdncmVnYXRlRnVuYyhhZ2dyVHlwZSk7CiAgLy8gVXNlIHRoZSBNViBjb2x1bW4gYXMgaXRzIGFyZ3VtZW50LgogIFFSTVZDb2x1bW5QdHIgbXZDb2x1bW4gPSBnZW5lcmF0ZVByb3ZpZGVkTXZDb2x1bW4ocmV3cml0ZSk7CiAgcm9sbHVwRnVuY3Rpb24tPmFkZEFyZ3VtZW50KG12Q29sdW1uKTsKCiAgcmV0dXJuIHJvbGx1cEZ1bmN0aW9uOwp9ICAvLyBnZW5lcmF0ZVJvbGx1cEFnZ3JlZ2F0ZUZ1bmN0aW9uKCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKUVJGdW5jdGlvblB0ciBNYXRjaFRlc3Q6OmdlbmVyYXRlUm9sbHVwT3Zlckdyb3VwaW5nQWdncmVnYXRlRnVuY3Rpb24oUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSkKewogIC8vIFRoaXMgaXMgdGhlIHF1ZXJ5IGFnZ3JlZ2F0ZSBmdW5jdGlvbi4KICBRUkVsZW1lbnRQdHIgcXVlcnlFbGVtID0gcmV3cml0ZS0+Z2V0QWN0dWFsUXVlcnlFbGVtZW50KCk7CiAgUVJGdW5jdGlvblB0ciBxdWVyeUZ1bmN0aW9uOwogIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICBxdWVyeUVsZW0tPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfRnVuY3Rpb24sIFFSTG9naWNFeGNlcHRpb24sIAogICAgCQkgICAgIkV4cGVjdGluZyBhIFFSRnVuY3Rpb24gaW4gZ2VuZXJhdGVSb2xsdXBPdmVyR3JvdXBpbmdBZ2dyZWdhdGVGdW5jdGlvbigpLiIpOwogIHF1ZXJ5RnVuY3Rpb24gPSBxdWVyeUVsZW0tPmRvd25DYXN0VG9RUkZ1bmN0aW9uKCk7CiAgLy8gV2hpY2ggYWdncmVnYXRlIHNob3VsZCB3ZSB1c2U/CiAgTkFTdHJpbmcgYWdnck5hbWUoaGVhcF8pOwogIFFSRnVuY3Rpb246OkFnZ3JlZ2F0ZUZ1bmN0aW9uVHlwZSBhZ2dyVHlwZSA9IFFSRnVuY3Rpb246OkFGVF9OT05FOwoKICAvLyBDcmVhdGUgdGhlIG5ldyBhZ2dyZWdhdGUgZnVuY3Rpb24uCiAgUVJGdW5jdGlvblB0ciByb2xsdXBGdW5jdGlvbiA9IG5ldyhoZWFwXykgUVJGdW5jdGlvbihBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogIE5BQm9vbGVhbiBuZWVkQ291bnRTdGFyQXJndW1lbnQgPSBGQUxTRTsKICBOQUJvb2xlYW4gbmVlZEFjdHVhbEFyZ3VtZW50ID0gVFJVRTsKCiAgc3dpdGNoIChxdWVyeUZ1bmN0aW9uLT5nZXRBZ2dyZWdhdGVGdW5jKCkpCiAgewogICAgY2FzZSBRUkZ1bmN0aW9uOjpBRlRfQ09VTlRTVEFSOgogICAgICAvLyBDT1VOVCgqKSB0cmFuc2xhdGVzIGludG8gU1VNKGNvdW50X3N0YXIpCiAgICAgIGFnZ3JUeXBlID0gUVJGdW5jdGlvbjo6QUZUX1NVTTsKICAgICAgYWdnck5hbWUgPSAic3VtIjsKICAgICAgbmVlZENvdW50U3RhckFyZ3VtZW50ID0gVFJVRTsKICAgICAgbmVlZEFjdHVhbEFyZ3VtZW50ID0gRkFMU0U7CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgUVJGdW5jdGlvbjo6QUZUX0NPVU5UOgogICAgICAvLyBDT1VOVChnKSB0cmFuc2xhdGVzIGludG8gQ09VTlQoIENBU0UgV0hFTiBnIElTIE5VTEwgVEhFTiAwIEVMU0UgY291bnRfc3RhciBFTkQgKQogICAgICAvLyBMZXQgdGhlIGFuYWx5emVyIGNvbnN0cnVjdCB0aGlzIGV4cHJlc3Npb24sIGp1c3QgaW5zdHJ1Y3QgaXQgdG8gZG8gaXQKICAgICAgLy8gYnkgdXNpbmcgdGhpcyBzcGVjaWFsIGFnZ3JlZ2F0ZSB0eXBlLgogICAgICBhZ2dyVHlwZSA9IFFSRnVuY3Rpb246OkFGVF9DT1VOVF9PTl9HUk9VUElORzsKICAgICAgYWdnck5hbWUgPSAiY291bnQgb24gZ3JvdXBpbmciOwogICAgICBuZWVkQ291bnRTdGFyQXJndW1lbnQgPSBUUlVFOwogICAgICBicmVhazsKCiAgICBjYXNlIFFSRnVuY3Rpb246OkFGVF9TVU06CiAgICAgIC8vIFNVTShnKSB0cmFuc2xhdGVzIGludG8gU1VNKGcqY291bnRfc3RhcikKICAgICAgLy8gTGV0IHRoZSBhbmFseXplciBjb25zdHJ1Y3QgdGhpcyBleHByZXNzaW9uLCBqdXN0IGluc3RydWN0IGl0IHRvIGRvIGl0CiAgICAgIC8vIGJ5IHVzaW5nIHRoaXMgc3BlY2lhbCBhZ2dyZWdhdGUgdHlwZS4KICAgICAgYWdnclR5cGUgPSBRUkZ1bmN0aW9uOjpBRlRfU1VNX09OX0dST1VQSU5HOwogICAgICBhZ2dyTmFtZSA9ICJzdW0gb24gZ3JvdXBpbmciOwogICAgICBuZWVkQ291bnRTdGFyQXJndW1lbnQgPSBUUlVFOwogICAgICBicmVhazsKCiAgICBjYXNlIFFSRnVuY3Rpb246OkFGVF9NSU46CiAgICBjYXNlIFFSRnVuY3Rpb246OkFGVF9NQVg6CiAgICAgIC8vIE1JTihnKSBhbmQgTUFYKGcpIGFyZSByZWd1bGFyIE1JTi9NQVguCiAgICBjYXNlIFFSRnVuY3Rpb246OkFGVF9DT1VOVF9ESVNUSU5DVDoKICAgICAgLy8gQ09VTlQoRElTVElOQ1QgZykgY2FuIGJlIHJvbGxlZCB1cCwgYW5kIHN0YXlzIHRoZSBzYW1lLgogICAgY2FzZSBRUkZ1bmN0aW9uOjpBRlRfU1VNX0RJU1RJTkNUOgogICAgICAvLyBTVU0oRElTVElOQ1QgZykgY2FuIGJlIHJvbGxlZCB1cCwgYW5kIHN0YXlzIHRoZSBzYW1lLgogICAgICBhZ2dyTmFtZSA9IHF1ZXJ5RnVuY3Rpb24tPmdldEZ1bmN0aW9uTmFtZSgpOwogICAgICBhZ2dyVHlwZSA9IHF1ZXJ5RnVuY3Rpb24tPmdldEFnZ3JlZ2F0ZUZ1bmMoKTsKICAgICAgYnJlYWs7CiAgfQoKICByb2xsdXBGdW5jdGlvbi0+c2V0RnVuY3Rpb25OYW1lKGFnZ3JOYW1lKTsKICByb2xsdXBGdW5jdGlvbi0+c2V0QWdncmVnYXRlRnVuYyhhZ2dyVHlwZSk7CgogIGlmIChuZWVkQWN0dWFsQXJndW1lbnQpCiAgewogICAgUVJFbGVtZW50UHRyIHF1ZXJ5QXJnID0gcXVlcnlGdW5jdGlvbi0+Z2V0QXJndW1lbnRzKClbMF0tPmdldFJlZmVyZW5jZWRFbGVtZW50KCk7CiAgICBpZiAocXVlcnlBcmctPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfQ29sdW1uIHx8CiAgICAgICAgcXVlcnlBcmctPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfSm9pblByZWQgKQogICAgewogICAgICAvLyBUaGUgYXJndW1lbnQgdG8gdGhlIGFnZ3JlZ2F0ZSBmdW5jdGlvbiBpcyBhIHNpbXBsZSBjb2x1bW4uCiAgICAgIC8vIFVzZSB0aGUgTVYgY29sdW1uIGFzIGl0cyBhcmd1bWVudC4KICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgY29sUmV3cml0ZSA9IHJld3JpdGUtPmdldFN1YkVsZW1lbnRzKCktPnByb3ZpZGVkSW5wdXRzX1swXTsKICAgICAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgICAgICBjb2xSZXdyaXRlICE9IE5VTEwsIFFSTG9naWNFeGNlcHRpb24sIAogICAJCSAgICAgICAgIkV4cGVjdGluZyBhIHJld3JpdGUgb2YgdGhlIGFnZ3JlZ2F0ZSBmdW5jdGlvbiBhcmd1bWVudC4iKTsKICAgICAgUVJNVkNvbHVtblB0ciBtdkNvbHVtbiA9IGdlbmVyYXRlUHJvdmlkZWRNdkNvbHVtbihjb2xSZXdyaXRlKTsKICAgICAgcm9sbHVwRnVuY3Rpb24tPmFkZEFyZ3VtZW50KG12Q29sdW1uKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQoIkNhbid0IGhhbmRsZSBhZ2dyKGV4cHIoZykpIHlldCwgZm9yIHJvbGx1cCBvdmVyIGdyb3VwaW5nIGNvbHVtbi4iKTsKICAgICAgZGVsZXRlUHRyKHJvbGx1cEZ1bmN0aW9uKTsKICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CiAgfQoKICBpZiAobmVlZENvdW50U3RhckFyZ3VtZW50KQogIHsKICAgIC8vIEZpbmQgdGhlIE1WIENPVU5UKCopIGNvbHVtbi4KICAgIFFST3V0cHV0UHRyIGNvdW50U3Rhck91dHB1dCA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpLT5nZXRDb3VudFN0YXIoKTsKICAgIGlmIChjb3VudFN0YXJPdXRwdXQgPT0gTlVMTCkKICAgIHsKICAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkKCJ0aGUgTVYgZG9lcyBub3QgaGF2ZSBhIENPVU5UKCopIGNvbHVtbi4iKTsKICAgICAgIGRlbGV0ZVB0cihyb2xsdXBGdW5jdGlvbik7CiAgICAgICByZXR1cm4gTlVMTDsKICAgIH0KCiAgICAvLyBDb25zdHJ1Y3QgdGhlIENPVU5UKCopIE1WQ29sdW1uIGVsZW1lbnQKICAgIFFSTVZDb2x1bW5QdHIgY291bnRTdGFyTVZDb2wgPSBuZXcgKGhlYXBfKSBRUk1WQ29sdW1uKEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICAvLyBHZXQgdGhlIG5hbWUgb2YgdGhlIE1WIGNvbHVtbiBmcm9tIHRoZSBNViBvdXRwdXQgZWxlbWVudC4KICAgIGNvdW50U3Rhck1WQ29sLT5zZXRNVkNvbE5hbWUoY291bnRTdGFyT3V0cHV0LT5nZXROYW1lKCkpOwogICAgLy8gQWRkIGl0IGFzIHRoZSBmaXJzdCBhcmd1bWVudC4KICAgIHJvbGx1cEZ1bmN0aW9uLT5hZGRBcmd1bWVudChjb3VudFN0YXJNVkNvbCk7CiAgfQoKICByZXR1cm4gcm9sbHVwRnVuY3Rpb247Cn0gIC8vIGdlbmVyYXRlUm9sbHVwT3Zlckdyb3VwaW5nQWdncmVnYXRlRnVuY3Rpb24oKQoKLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gIENsYXNzIE1hdGNoT3V0cHV0Ci8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIERvIHRoZSBpbml0aWFsIFBhc3MgMSBhbmFseXNpcyBvZiBhbGwgb3V0cHV0IGNvbHVtbnMvZXhwcmVzc2lvbnMuCi8vIEZvciBlYWNoIG91dHB1dCBlbGVtZW50LCB0aGlzIG1ldGhvZCBmaW5kcyB0aGUgYWN0dWFsIGNvbHVtbiBvciBleHByZXNzaW9uCi8vIEFuZCBjYWxscyB0aGUgbmV4dCBtZXRob2RzIHRvIG1hdGNoIGl0LgovLyBBbiBvdXRwdXQgZWxlbWVudCBjYW4gZmFsbCBpbnRvIG9uZSBvZiB0aGUgZm9sbG93aW5nIG9wdGlvbnM6Ci8vIDEuIEEgUVJDb2x1bW4gZWxlbWVudCwgb3IgYSByZWZlcmVuY2UgdG8gb25lLgovLyAgICBDYWxsIG1hdGNoQ29sdW1uKCkuCi8vIDIuIEFuIGV4cHJlc3Npb24gKFFSRXhwcikgb3IgYSByZWZlcmVuY2UgdG8gb25lLgovLyAgICBDYWxsIG1hdGNoRXhwcmVzc2lvbigpLgovLyAzLiBBIHJlZmVyZW5jZSB0byBhbiBlcXVhbGl0eSBzZXQuCi8vICAgIENhbGwgbWF0Y2hFcXVhbGl0eVNldCgpLgovLyBXaGVuIGFueSBvZiB0aGVzZSBtZXRob2RzIHJ0dXJuIEZBTFNFLCBpdCBtZWFucyB0aGF0IHRoZSBvdXRwdXQgZWxlbWVudCAKLy8gY2Fubm90IGJlIHByb3ZpZGVkIHVzaW5nIHRoaXMgTVYsIHNvIHRoZSBNViBpcyBkaXNxdWFsaWZpZWQsIGFuZCBpdHMgCi8vIG1hdGNoaW5nIGlzIGFib3J0ZWQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hPdXRwdXQ6Om1hdGNoUGFzczEoKSAKewogIC8vIExvb3Agb3ZlciB0aGUgb3V0cHV0cyBpbiB0aGUgUXVlcnkgZGVzY3JpcHRvcgogIGNvbnN0IERlc2NyaXB0b3JEZXRhaWxzUHRyIHF1ZXJ5RGV0YWlscyA9IGNhbmRpZGF0ZV8tPmdldFF1ZXJ5RGV0YWlscygpOwogIGNvbnN0IFFSSkJCUHRyICBxdWVyeUpiYiA9IGNhbmRpZGF0ZV8tPmdldFF1ZXJ5SmJiKCk7CiAgY29uc3QgUVJPdXRwdXRMaXN0UHRyIG91dHB1dExpc3QgPSBxdWVyeUpiYi0+Z2V0T3V0cHV0TGlzdCgpOwoKICBDb2xsSW5kZXggb3V0cHV0TGlzdEVudHJpZXMgPSAob3V0cHV0TGlzdCA/IG91dHB1dExpc3QtPmVudHJpZXMoKSA6IDApOwogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxvdXRwdXRMaXN0RW50cmllczsgaSsrKQogIHsKICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUgPSBOVUxMOwogICAgY29uc3QgUVJPdXRwdXRQdHIgb3V0cHV0ID0gKCpvdXRwdXRMaXN0KVtpXTsKICAgIFFSRWxlbWVudFB0ciBlbGVtZW50ID0gb3V0cHV0LT5nZXRPdXRwdXRJdGVtKCktPmdldFJlZmVyZW5jZWRFbGVtZW50KCk7CgogICAgLy8gTm93IGNoZWNrIHdoYXQgaXMgdGhpcyBlbGVtZW50IHRoYXQgd2UgbmVlZCB0byBtYXRjaC4KICAgIHN3aXRjaCAoZWxlbWVudC0+Z2V0RWxlbWVudFR5cGUoKSkKICAgIHsKICAgICAgY2FzZSBFVF9Db2x1bW46CiAgICAgIHsKCS8vIENhc2UgMTogQSBRUkNvbHVtbiBlbGVtZW50LgoJY29uc3QgUVJDb2x1bW5QdHIgY29sID0gZWxlbWVudC0+ZG93bkNhc3RUb1FSQ29sdW1uKCk7CglyZXdyaXRlID0gbWF0Y2hDb2x1bW4oY29sLCBGQUxTRSk7CglicmVhazsKICAgICAgfQoKICAgICAgY2FzZSBFVF9FeHByOgogICAgICB7CgkvLyBDYXNlIDI6IEEgUVJFeHByIGVsZW1lbnQuCgljb25zdCBRUkV4cHJQdHIgZXhwciA9IGVsZW1lbnQtPmRvd25DYXN0VG9RUkV4cHIoKTsKCXJld3JpdGUgPSBtYXRjaEV4cHJlc3Npb24oZXhwcik7CglpZiAocmV3cml0ZSAhPSBOVUxMKSAvLyAmJiByZXdyaXRlLT5pc0ZpbmFsKCkpCgl7CgkgIC8vIEZvciBvdXRwdXQgZXhwcmVzc2lvbnMsIGFkZCB0aGUgaW5wdXQgY29sdW1ucyB0byB0aGUgb3V0cHV0IGxpc3QgYXMgd2VsbC4KCSAgYWRkSW5wdXRzVG9PdXRwdXRMaXN0KHJld3JpdGUpOwoJfQoJYnJlYWs7CiAgICAgIH0KCiAgICAgIGNhc2UgRVRfSm9pblByZWQ6CiAgICAgIHsKCS8vIENhc2UgMyAtIEEgam9pbiBwcmVkaWNhdGUgKEVxdWFsaXR5IHNldCkuCgljb25zdCBRUkpvaW5QcmVkUHRyIGpvaW5QcmVkRWxlbWVudCA9IGVsZW1lbnQtPmRvd25DYXN0VG9RUkpvaW5QcmVkKCk7CglyZXdyaXRlID0gbWF0Y2hFcXVhbGl0eVNldChqb2luUHJlZEVsZW1lbnQpOwoJYnJlYWs7CiAgICAgIH0KCiAgICAgIGRlZmF1bHQ6CiAgICAgIHsKCS8vIE91dHB1dCBlbGVtZW50cyBjYW4gb25seSBiZSBRUkNvbHVtbiwgUVJFeHByIG9yIHJlZmVyZW5jaW5nIFFSSm9pblByZWQuCglhc3NlcnRMb2dBbmRUaHJvdyhDQVRfTUFUQ0hUU1RfTVZERVRBSUxTLCBMTF9NVlFSX0ZBSUwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgRkFMU0UsIFFSTG9naWNFeGNlcHRpb24sIAoJCQkgICJVbmV4cGVjdGVkIG91dHB1dCBsaXN0IGVsZW1lbnQuIik7IAoJcmV0dXJuIEZBTFNFOwogICAgICB9CiAgICB9IC8vIHN3aXRjaCBvbiBlbGVtZW50IHR5cGUuCgogICAgLy8gTGV0cyBjaGVjayB0aGUgbWF0Y2hpbmcgcmVzdWx0cwogICAgaWYgKHJld3JpdGUgPT0gTlVMTCkKICAgIHsKICAgICAgLy8gUmVqZWN0IHRoZSBNVi4KICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQogICAgZWxzZQogICAgewogICAgICAvLyBNYXRjaGluZyBzdWNjZXNzZnVsLiBBZGQgdGhlIHJld3JpdGUgaW5zdHJ1Y3Rpb25zIHRvIHRoZSBsaXN0LgogICAgICByZXdyaXRlLT5zZXRRdWVyeUVsZW1lbnQob3V0cHV0KTsKICAgICAgYWRkUmV3cml0ZUluc3RydWN0aW9ucyhyZXdyaXRlKTsKICAgIH0KCiAgfSAvLyBmb3IgbG9vcCBvbiBxdWVyeSBvdXRwdXRzCiAgcmV0dXJuIFRSVUU7Cn0gIC8vIE1hdGNoT3V0cHV0OjptYXRjaFBhc3MxKCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoT3V0cHV0OjptYXRjaFBhc3MyT25FbGVtZW50KFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHBlbmRpbmcpCnsKICBpZiAocGVuZGluZy0+Z2V0QWN0dWFsUXVlcnlFbGVtZW50KCktPmdldEVsZW1lbnRUeXBlKCkgIT0gRVRfRXhwcikKICB7CiAgICAvLyBzaW1wbGUgY29sdW1uIG91dHB1dHMgYXJlIG5vdCBzdXBwb3NlZCB0byBnZXQgaGVyZS4KICAgIC8vIFRCRDogQ2hhbmdlIHRvIGFzc2VydExvZ0FuZFRocm93KCkKICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgiQ29sdW1uIG91dHB1dCAlcyBnb3QgdG8gUGFzcyAyLiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZy0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCkpOwogICAgcmV0dXJuIEZBTFNFOwogIH0KCiAgaWYgKHBlbmRpbmctPmdldEFjdHVhbFF1ZXJ5RWxlbWVudCgpLT5kb3duQ2FzdFRvUVJFeHByKCktPmdldEV4cHJSb290KCktPmNvbnRhaW5zQW5BZ2dyZWdhdGUoKSkKICB7CiAgICAvLyBIYW5kbGUgcm9sbHVwIGFnZ3JlZ2F0ZXMKICAgIHJldHVybiBtYXRjaEFnZ3JlZ2F0ZUV4cHJlc3Npb25zKHBlbmRpbmcpOwogIH0KICBlbHNlCiAgewogICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJPdXRwdXQgZXhwcmVzc2lvbiAlcyBjYW5ub3QgYmUgUHJvdmlkZWQuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZy0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCkpOwoKICAgIHJldHVybiBGQUxTRTsKICB9Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBSb2xsdXAgZXhwcmVzc2lvbnMgbWVhbnMgdGhhdCBib3RoIHRoZSBNViBhbmQgdGhlIHF1ZXJ5IGFyZSBhZ2dyZWdhdGVzLCAKLy8gYW5kIHRoZSBxdWVyeSBncm91cGluZyBsaXN0IGlzIGEgc3Vic2V0IG9mIHRoZSBNVidzIGdyb3VwaW5nIGxpc3QuCi8vIEluIHRoaXMgY2FzZSBvdXRwdXQgZXhwcmVzc2lvbnMgYXJlIG5ldmVyIFByb3ZpZGVkLCBiZWNhdXNlIGV2ZW4gaWYgdGhlIAovLyB0d28gZXhwcmVzc2lvbnMgbG9vayBpZGVudGljYWwgKGZvciBleGFtcGxlIFNVTShhKSBhbmQgU1VNKGEpKSwgdGhleSByZWFsbHkgCi8vIGFyZSBub3QuCi8vIDEuIENoZWNrIGlmIHRoZSBleHByZXNzaW9uIGlzIGEgc3VwcG9ydGVkIGFnZ3JlZ2F0ZSBmdW5jdGlvbjoKLy8gICAgQ09VTlQoKiksIENPVU5UKGEpLCBTVU0oYSksIEFWRyhhKSwgTUlOKGEpLCBNQVgoYSksIGFzIHdlbGwgYXMKLy8gICAgU1REREVWKGEpLCBTVERERVYoYSxiKSBhbmQgVkFSSUFOQ0UoYSkuIAovLyAyLiBJZiBzbyAtIGNoZWNrIGlmIHRoZSBNViBQcm92aWRlcyB0aGUgbmVlZGVkIGFnZ3JlZ2F0ZXMgdG8gY2FsY3VsYXRlIAovLyAgICB0aGUgcmVxdWlyZWQgYWdncmVnYXRlcyByZXN1bHQuIFJld3JpdGUgdXNpbmcgdGhlIE1WIGFnZ3JlZ2F0ZSBjb2x1bW4uCi8vIDMuIE1heWJlIHRoaXMgZXhwcmVzc2lvbiBpcyB1c2luZyBzdXBwb3J0ZWQgYWdncmVnYXRlIGZ1bmN0aW9ucywgc28gaXRzCi8vICAgIG1vcmUgY29tcGxleCBidXQgc3RpbGwgcmV3cml0ZWFibGUuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hPdXRwdXQ6Om1hdGNoQWdncmVnYXRlRXhwcmVzc2lvbnMoUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcGVuZGluZykKewogIFFST3V0cHV0UHRyIHF1ZXJ5T3V0cHV0RXhwciA9IHBlbmRpbmctPmdldFF1ZXJ5RWxlbWVudCgpLT5kb3duQ2FzdFRvUVJPdXRwdXQoKTsKICBRUkV4cHJQdHIgcXVlcnlFeHByID0gcGVuZGluZy0+Z2V0QWN0dWFsUXVlcnlFbGVtZW50KCktPmRvd25DYXN0VG9RUkV4cHIoKTsKICBRUkV4cGxpY2l0RXhwclB0ciB0cmVlRXhwciA9IHF1ZXJ5RXhwci0+Z2V0RXhwclJvb3QoKTsKCiAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgIHRyZWVFeHByLT5jb250YWluc0FuQWdncmVnYXRlKCksIFFSTG9naWNFeGNlcHRpb24sIAoJCSAgICAiRXhwZWN0aW5nIFJvbGx1cCBhZ2dyZWF0ZSBmdW5jdGlvbnMuIik7CgogIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUgPSBOVUxMOwoKICAvLyAxLiBJcyB0aGUgdG9wIGxldmVsIGFuIGFnZ3JlZ2F0ZSBmdW5jdGlvbj8KICBpZiAodHJlZUV4cHItPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfRnVuY3Rpb24gJiYgCiAgICAgIHRyZWVFeHByLT5kb3duQ2FzdFRvUVJGdW5jdGlvbigpLT5pc0FuQWdncmVnYXRlKCkpCiAgewogICAgLy8gTG9vayBmb3IgdGhlIGNvcnJlc3BvbmRpbmcgYWdncmVnYXRlIGZ1bmN0aW9uIGFzIGFuIE1WIG91dHB1dC4KICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIGZ1bmNSZXdyaXRlID0gCiAgICAgIGZpbmRBZ2dyZWdhdGVGdW5jdGlvbihxdWVyeUV4cHItPmdldEV4cHJSb290KCktPmRvd25DYXN0VG9RUkZ1bmN0aW9uKCkpOwogICAgaWYgKGZ1bmNSZXdyaXRlID09IE5VTEwpCiAgICAgIHJldHVybiBGQUxTRTsKCiAgICAvLyBUaGUgcmVzdWx0IGNvZGUgaXMgc2V0IHRvIE5PVFBST1ZJREVELiBTZXQgaXQgdG8gUFJPVklERUQgYXMgYSBzdWItZWxlbWVudC4KICAgIGZ1bmNSZXdyaXRlLT5zZXRSZXN1bHRDb2RlKFJDX1BST1ZJREVEKTsKCiAgICAvLyBXZSBnb3QgYSBmaW5hbCByZXdyaXRlLiBIb3dldmVyLCBpdHMgbm90IHJlYWxseSBwcm92aWRlZCwgYmVjYXVzZQogICAgLy8gb2YgdGhlIHJvbGx1cC4gQ2hhbmdlIGl0IHRvIGEgTm90UHJvdmlkZWQuCiAgICByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0ocXVlcnlPdXRwdXRFeHByLCBOVUxMLCBSQ19OT1RQUk9WSURFRCwgUlNfRklOQUwsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CgogICAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgICAgY2FuZGlkYXRlXy0+Z2V0QWdncmVnYXRlTWF0Y2hpbmdUeXBlKCkgPT0gQU1UX01BVl9BUV9ERywgUVJMb2dpY0V4Y2VwdGlvbiwgCgkJICAgICAgIlNpbXBsZSBhZ2dyZWF0ZSBmdW5jdGlvbnMgZG9uJ3QgZ2V0IGhlcmUgLSB0aGV5IGFyZSBQcm92aWRlZC4iKTsKICAgIHJld3JpdGUtPmFkZFN1YkVsZW1lbnQoZnVuY1Jld3JpdGUpOwogICAgcmV3cml0ZS0+c2V0U2Vjb25kYXJ5UmVzdWx0Q29kZShSQ19ST0xMVVBfRVhQUik7CiAgfQogIGVsc2UKICB7CiAgICAvLyAyLiBVc2UgYSB2aXNpdG9yIHRvIGZpbmQgYWdncmVnYXRlIGZ1bmN0aW9ucywgYW5kIHNvbHZlIGFueSB0aGF0IGFyZSBmb3VuZC4KICAgIHJld3JpdGUgPSBmaW5kSW50ZXJuYWxBZ2dyZWdhdGVGdW5jdGlvbnModHJlZUV4cHIpOwoKICAgIGlmIChyZXdyaXRlID09IE5VTEwpCiAgICAgIHJldHVybiBGQUxTRTsKCiAgICByZXdyaXRlLT5zZXRRdWVyeUVsZW1lbnQocXVlcnlPdXRwdXRFeHByKTsKICB9CgogIC8vIEFuZCBQdXQgaXQgaW4gdGhlIEZpbmFsIGxpc3QuCiAgYWRkUmV3cml0ZUluc3RydWN0aW9ucyhyZXdyaXRlKTsKICBkZWxldGVQdHIocGVuZGluZyk7CiAgcmV0dXJuIFRSVUU7Cn0gIC8vIG1hdGNoQWdncmVnYXRlRXhwcmVzc2lvbnMoKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIENyZWF0ZSBhIG5ldyBRUk91dHB1dCBlbGVtZW50IGZvciB0aGUgcmVzdWx0IGRlc2NyaXB0b3IuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpRUk91dHB1dFB0ciBNYXRjaE91dHB1dDo6Y3JlYXRlTmV3UmVzdWx0RWxlbWVudChSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgLy8gQ29uc3RydWN0IHRoZSBuZXcgZWxlbWVudAogIFFST3V0cHV0UHRyIG91dHB1dEVsZW1lbnQgPSBuZXcoaGVhcF8pIFFST3V0cHV0KEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgLy8gU2V0IHRoZSByZXN1bHQgYXR0cmlidXRlLgogIG91dHB1dEVsZW1lbnQtPnNldFJlc3VsdChyZXdyaXRlLT5nZXREZXNjcmlwdG9yUmVzdWx0Q29kZSgpKTsKICAvLyBTZXQgdGhlIHJlZiBhdHRyaWJ1dGUuCiAgb3V0cHV0RWxlbWVudC0+c2V0UmVmKHJld3JpdGUtPmdldFF1ZXJ5RWxlbWVudCgpLT5nZXRJRCgpKTsKCiAgcmV0dXJuIG91dHB1dEVsZW1lbnQ7Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBDcmVhdGUgYSBuZXcgUVJPdXRwdXQgZWxlbWVudCBmb3IgdGhlIHJlc3VsdCBkZXNjcmlwdG9yLCBzZXQgdG8gUHJvdmlkZWQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hPdXRwdXQ6OmdlbmVyYXRlUHJvdmlkZWRFbGVtZW50KFFSQ2FuZGlkYXRlUHRyIHJlc3VsdERlc2MsIAoJCQkJCSAgICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgLy8gQ3JlYXRlIHRoZSBuZXcgT3V0cHV0IGVsZW1lbnQsIEFkZCB0aGUgTVZDb2x1bW4gdG8gaXQuCiAgUVJPdXRwdXRQdHIgb3V0cHV0RWxlbWVudCA9IGNyZWF0ZU5ld1Jlc3VsdEVsZW1lbnQocmV3cml0ZSk7CgogIFFSTVZDb2x1bW5QdHIgbXZDb2x1bW4gPSBnZW5lcmF0ZVByb3ZpZGVkTXZDb2x1bW4ocmV3cml0ZSk7CiAgb3V0cHV0RWxlbWVudC0+c2V0T3V0cHV0SXRlbShtdkNvbHVtbik7CiAgLy8gQWRkIGl0IHRvIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICByZXN1bHREZXNjLT5nZXRPdXRwdXRMaXN0KCktPmFkZEl0ZW0ob3V0cHV0RWxlbWVudCk7CiAgcmV0dXJuIFRSVUU7Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBDcmVhdGUgYSBuZXcgUVJPdXRwdXQgZWxlbWVudCBmb3IgdGhlIHJlc3VsdCBkZXNjcmlwdG9yLCBzZXQgdG8gTm90UHJvdmlkZWQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hPdXRwdXQ6OmdlbmVyYXRlTm90UHJvdmlkZWRFbGVtZW50KFFSQ2FuZGlkYXRlUHRyIHJlc3VsdERlc2MsIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUpCnsKICBSZXN1bHRDb2RlIHNlY29uZGFyeVJDID0gcmV3cml0ZS0+Z2V0U2Vjb25kYXJ5UmVzdWx0Q29kZSgpOwogIFFST3V0cHV0UHRyIG91dHB1dEVsZW1lbnQgPSBOVUxMOwogIHN3aXRjaCAoc2Vjb25kYXJ5UkMpCiAgewogICAgY2FzZSBSQ19CQUNLSk9JTjoKICAgIHsKICAgICAgY29uc3QgTkFTdHJpbmcmIGlkID0gcmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCk7CiAgICAgIFFSQ29sdW1uUHRyIHJDb2x1bW4gPSBnZW5lcmF0ZU5vdFByb3ZpZGVkQ29sdW1uKHJld3JpdGUpOwogICAgICBvdXRwdXRFbGVtZW50ID0gbmV3KGhlYXBfKSBRUk91dHB1dChBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogICAgICBvdXRwdXRFbGVtZW50LT5zZXRPdXRwdXRJdGVtKHJDb2x1bW4pOwogICAgICBvdXRwdXRFbGVtZW50LT5zZXRSZWYoaWQpOwogICAgICBvdXRwdXRFbGVtZW50LT5zZXRSZXN1bHQoUVJFbGVtZW50OjpOb3RQcm92aWRlZCk7CiAgICB9CiAgICBicmVhazsKCiAgICBjYXNlIFJDX1JPTExVUDoKICAgIHsKICAgICAgb3V0cHV0RWxlbWVudCA9IGdlbmVyYXRlUm9sbHVwQWdncmVnYXRlT3V0cHV0KHJld3JpdGUpOwogICAgICBpZiAob3V0cHV0RWxlbWVudCA9PSBOVUxMKQogICAgICB7CiAgICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJPdXRwdXQgZXhwcmVzc2lvbiAlcyBjYW5ub3QgYmUgUHJvdmlkZWQuIiwgCgkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCkuZGF0YSgpKTsKICAgICAgICByZXR1cm4gRkFMU0U7CiAgICAgIH0KICAgIH0KICAgIGJyZWFrOwoKICAgIGNhc2UgUkNfSU5QVVRTX1BST1ZJREVEOgogICAgY2FzZSBSQ19ST0xMVVBfRVhQUjoKICAgIGNhc2UgUkNfQUdHUl9FWFBSOgogICAgewogICAgICBRUkV4cHJQdHIgZXhwckVsZW1lbnQgPSBnZW5lcmF0ZUFnZ3JlZ2F0ZUV4cHJlc3Npb25PdXRwdXQocmV3cml0ZSk7CiAgICAgIGlmIChleHByRWxlbWVudCA9PSBOVUxMKQogICAgICB7CiAgICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJPdXRwdXQgZXhwcmVzc2lvbiAlcyBjYW5ub3QgYmUgUHJvdmlkZWQuIiwgCgkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCkuZGF0YSgpKTsKICAgICAgICByZXR1cm4gRkFMU0U7CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgb3V0cHV0RWxlbWVudCA9IGNyZWF0ZU5ld1Jlc3VsdEVsZW1lbnQocmV3cml0ZSk7CiAgICAgICAgb3V0cHV0RWxlbWVudC0+c2V0T3V0cHV0SXRlbShleHByRWxlbWVudCk7CiAgICAgIH0KICAgIH0KICAgIGJyZWFrOwoKICAgIGRlZmF1bHQ6CiAgICAgIC8vIE5vdCBpbXBsZW1lbnRlZCB5ZXQuCiAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgiTm90UHJvdmlkZWQgb3V0cHV0IGxpc3QgaXMgbm90IGZ1bGx5IGltcGxlbWVudGVkIGZvciAlcy4iLCAKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV3cml0ZS0+Z2V0UmVzdWx0U3RyaW5nKHNlY29uZGFyeVJDKSk7CiAgICAgIHJldHVybiBGQUxTRTsKICB9CgogIC8vIEFkZCB0aGUgbmV3IE91dHB1dCBlbGVtZW50IHRvIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICByZXN1bHREZXNjLT5nZXRPdXRwdXRMaXN0KCktPmFkZEl0ZW0ob3V0cHV0RWxlbWVudCk7CiAgcmV0dXJuIFRSVUU7Cn0gIC8vIE1hdGNoT3V0cHV0OjpnZW5lcmF0ZU5vdFByb3ZpZGVkRWxlbWVudCgpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqClFST3V0cHV0UHRyIE1hdGNoT3V0cHV0OjpnZW5lcmF0ZVJvbGx1cEFnZ3JlZ2F0ZU91dHB1dChSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgLy8gR2VuZXJhdGUgdGhlIGNvcnJlY3QgYWdncmVnYXRlIGZ1bmN0aW9uIHRvIHJvbGx1cCBvdmVyIHRoZSBNViBhZ2dyZWdhdGUgZnVuY3Rpb24uCiAgUVJGdW5jdGlvblB0ciByb2xsdXBGdW5jdGlvbiA9IGdlbmVyYXRlUm9sbHVwQWdncmVnYXRlRnVuY3Rpb24ocmV3cml0ZSk7CgogIC8vIENyZWF0ZSB0aGUgZXhwcmVzc2lvbiBvbiB0b3Agb2YgaXQuCiAgUVJFeHByUHRyIGV4cHIgPSBuZXcoaGVhcF8pIFFSRXhwcihGQUxTRSwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICBleHByLT5zZXRFeHByUm9vdChyb2xsdXBGdW5jdGlvbik7CiAgZXhwci0+c2V0UmVmKHJld3JpdGUtPmdldEFjdHVhbFF1ZXJ5RWxlbWVudCgpLT5nZXRJRCgpKTsKCiAgUVJPdXRwdXRQdHIgb3V0cHV0RWxlbWVudCA9IGNyZWF0ZU5ld1Jlc3VsdEVsZW1lbnQocmV3cml0ZSk7CiAgb3V0cHV0RWxlbWVudC0+c2V0T3V0cHV0SXRlbShleHByKTsKCiAgcmV0dXJuIG91dHB1dEVsZW1lbnQ7Cn0gIC8vIGdlbmVyYXRlUm9sbHVwQWdncmVnYXRlT3V0cHV0KCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBBcmUgdGhlIHJld3JpdGUgaW5zdHJ1Y3Rpb25zIGZvciBhbiBPdXRzaWRlIGNvbHVtbi4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCk5BQm9vbGVhbiBNYXRjaE91dHB1dDo6aXNGcm9tT3V0c2lkZShSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgY29uc3QgUVJFbGVtZW50UHRyIHF1ZXJ5RWxlbSA9IHJld3JpdGUtPmdldEFjdHVhbFF1ZXJ5RWxlbWVudCgpLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpOwogIGlmIChxdWVyeUVsZW0tPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfQ29sdW1uKQogIHsKICAgIGNvbnN0IFFSQ29sdW1uUHRyIHF1ZXJ5Q29sID0gcXVlcnlFbGVtLT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKICAgIGNvbnN0IE5BU3RyaW5nJiBxdWVyeVRhYmxlSUQgPSBxdWVyeUNvbC0+Z2V0VGFibGVJRCgpOwogICAgY29uc3QgTkFTdHJpbmcqIGV4dHJhSHViSUQ7CiAgICBpZiAoaXNPdXRzaWRlQ29sdW1uKHF1ZXJ5Q29sLCBleHRyYUh1YklEKSkKICAgICAgcmV0dXJuIFRSVUU7CiAgfQoKICByZXR1cm4gRkFMU0U7Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBSZW1vdmUgZmlyc3RSZXdyaXRlIGZyb20gdGhlIGxpc3Qgb2YgZmluYWwgcmV3cml0ZSBpbnN0cnVjdGlvbnMsIGFuZCAKLy8gcmVwbGFjZSBpdCB3aXRoIG5ld1Jld3JpdGUuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgp2b2lkIE1hdGNoT3V0cHV0Ojpzd2l0Y2hSZXdyaXRlcyhSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBuZXdSZXdyaXRlLCAKCQkJCSBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBmaXJzdFJld3JpdGUsCgkJCQkgY29uc3QgTkFTdHJpbmcmIE1WQ29sTmFtZSkKewogIGNvbnN0IE5BU3RyaW5nJiBpZCA9IG5ld1Jld3JpdGUtPmdldEFjdHVhbFF1ZXJ5RWxlbWVudCgpLT5nZXRJRCgpOwogIGNvbnN0IE5BU3RyaW5nJiBmaXJzdElEID0gZmlyc3RSZXdyaXRlLT5nZXRBY3R1YWxRdWVyeUVsZW1lbnQoKS0+Z2V0SUQoKTsKCiAgT3V0cHV0UmV3cml0ZUluc3RydWN0aW9uc0J5SURfLnJlbW92ZSgmZmlyc3RJRCk7CiAgT3V0cHV0UmV3cml0ZUluc3RydWN0aW9uc0J5SURfLmluc2VydCgmaWQsIG5ld1Jld3JpdGUpOwoKICBpZiAoTVZDb2xOYW1lICE9ICIiKQogIHsKICAgIE91dHB1dFJld3JpdGVJbnN0cnVjdGlvbnNCeU12Q29sTmFtZV8ucmVtb3ZlKCZNVkNvbE5hbWUpOwogICAgT3V0cHV0UmV3cml0ZUluc3RydWN0aW9uc0J5TXZDb2xOYW1lXy5pbnNlcnQoJk1WQ29sTmFtZSwgbmV3UmV3cml0ZSk7CiAgfQoKICBnZXRMaXN0T2ZGaW5hbEluc3RydWN0aW9ucygpLnJlbW92ZShmaXJzdFJld3JpdGUpOwogIGdldExpc3RPZkZpbmFsSW5zdHJ1Y3Rpb25zKCkuaW5zZXJ0KG5ld1Jld3JpdGUpOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gT3ZlcnJpZGUgdGhlIGRlZmF1bHQgYmVoYXZpb3VyIGluIG9yZGVyIHRvIGF2b2lkIGR1cGxpY2F0ZXMuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgp2b2lkIE1hdGNoT3V0cHV0OjphZGRSZXdyaXRlSW5zdHJ1Y3Rpb25zKFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUpCnsKICBpZiAocmV3cml0ZS0+aXNGaW5hbCgpID09IEZBTFNFKQogIHsKICAgIC8vIERvbid0IGJvdGhlciB3aXRoIGludGVybWVkaWF0ZSByZXN1bHRzLgogICAgTWF0Y2hUZXN0OjphZGRSZXdyaXRlSW5zdHJ1Y3Rpb25zKHJld3JpdGUpOwogIH0KICBlbHNlCiAgewogICAgLy8gRm9yIGZpbmFsIHJlc3VsdHMsIGNoZWNrIGlmIHRoZSBJRCBvZiB0aGUgcXVlcnkgZWxlbWVudCBpcyBhbHJlYWR5CiAgICAvLyBzdG9yZWQgaW4gdGhlIGhhc2ggdGFibGUuCiAgICBjb25zdCBOQVN0cmluZyYgaWQgPSByZXdyaXRlLT5nZXRBY3R1YWxRdWVyeUVsZW1lbnQoKS0+Z2V0SUQoKTsKICAgIGNvbnN0IFFSRWxlbWVudFB0ciBtdk91dHB1dCA9IHJld3JpdGUtPmdldE12RWxlbWVudCgpOwogICAgUVJFbGVtZW50UHRyIG12RWxlbSA9IE5VTEw7CiAgICBzdGF0aWMgTkFTdHJpbmcgZW1wdHkgPSAiIjsKICAgIE5BU3RyaW5nJiBNVkNvbE5hbWUgPSBlbXB0eTsKICAgIGlmIChtdk91dHB1dCkKICAgIHsKICAgICAgbXZFbGVtID0gbXZPdXRwdXQtPmRvd25DYXN0VG9RUk91dHB1dCgpLT5nZXRPdXRwdXRJdGVtKCktPmdldFJlZmVyZW5jZWRFbGVtZW50KCk7CiAgICAgIGlmIChtdkVsZW0tPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfQ29sdW1uKQogICAgICAgIE1WQ29sTmFtZSA9IG12RWxlbS0+ZG93bkNhc3RUb1FSQ29sdW1uKCktPmdldENvbHVtbk5hbWUoKTsKICAgIH0KCiAgICAvLyBJZiB3ZSBuZWVkIHRvIGF2b2lkIHRoaXMgSUQsIGlnbm9yZSBpdC4KICAgIGlmIChPdXRwdXRzVG9Bdm9pZEJ5SURfLmNvbnRhaW5zKCZpZCkgPT0gVFJVRSkKICAgICAgcmV0dXJuOwoKICAgIGlmIChPdXRwdXRSZXdyaXRlSW5zdHJ1Y3Rpb25zQnlJRF8uY29udGFpbnMoJmlkKSA9PSBGQUxTRSkKICAgIHsKICAgICAgLy8gSXRzIGEgbmV3IGVudHJ5CiAgICAgIGlmIChtdk91dHB1dCAmJiBtdk91dHB1dC0+Z2V0RWxlbWVudFR5cGUoKSA9PSBFVF9PdXRwdXQpCiAgICAgIHsKICAgICAgICBpZiAoT3V0cHV0UmV3cml0ZUluc3RydWN0aW9uc0J5TXZDb2xOYW1lXy5jb250YWlucygmTVZDb2xOYW1lKSkKCXsKCSAgLy8gVGhlcmUgYWxyZWFkeSBpcyBhbiBPdXRwdXQgZWxlbWVudCBmb3IgdGhpcyBNViBjb2x1bW4uCgoJICAvLyBJZiB0aGUgbmV3IHJld3JpdGUgaXMgZm9yIGFuIE91dHNpZGUgY29sdW1uLCBpZ25vcmUgaXQgYW5kIGxlYXZlIHRoZSBleGlzdGluZyBvbmUuCgkgIGlmIChpc0Zyb21PdXRzaWRlKHJld3JpdGUpKQoJICB7CgkgICAgZGVsZXRlUHRyKHJld3JpdGUpOwoJICAgIHJldHVybjsKCSAgfQoKCSAgLy8gRmluZCB0aGUgZXhpc3RpbmcgZW50cnkKICAgICAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIGZpcnN0UmV3cml0ZSA9IAoJICAgIE91dHB1dFJld3JpdGVJbnN0cnVjdGlvbnNCeU12Q29sTmFtZV8uZ2V0Rmlyc3RWYWx1ZSgmTVZDb2xOYW1lKTsKCgkgIC8vIElmIHRoZSBleGlzdGluZyByZXdyaXRlIGlzIG9uIGFuIE91dHNpZGUgY29sdW1uLCBhbmQgdGhlIG5ldyBvbmUgaXNuJ3QsIAoJICAvLyBTd2l0Y2ggYmV0d2VlbiB0aGVtLgoJICBpZiAoaXNGcm9tT3V0c2lkZShmaXJzdFJld3JpdGUpKQoJICB7CgkgICAgc3dpdGNoUmV3cml0ZXMocmV3cml0ZSwgZmlyc3RSZXdyaXRlLCBNVkNvbE5hbWUpOwoJICAgIGRlbGV0ZVB0cihmaXJzdFJld3JpdGUpOwoJICAgIHJldHVybjsKCSAgfQoJfQoJT3V0cHV0UmV3cml0ZUluc3RydWN0aW9uc0J5TXZDb2xOYW1lXy5pbnNlcnQoJk1WQ29sTmFtZSwgcmV3cml0ZSk7CiAgICAgIH0KCiAgICAgIC8vIEluc2VydCBpdCB0byB0aGUgaGFzaCB0YWJsZSwgYW5kIGtlZXAgaXQuCiAgICAgIE91dHB1dFJld3JpdGVJbnN0cnVjdGlvbnNCeUlEXy5pbnNlcnQoJmlkLCByZXdyaXRlKTsKICAgICAgTWF0Y2hUZXN0OjphZGRSZXdyaXRlSW5zdHJ1Y3Rpb25zKHJld3JpdGUpOwogICAgfQogICAgZWxzZQogICAgewogICAgICAvLyBJdHMgYSBkdXBsaWNhdGUgKGJ5IHF1ZXJ5IElEKQogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBmaXJzdFJld3JpdGUgPSBPdXRwdXRSZXdyaXRlSW5zdHJ1Y3Rpb25zQnlJRF8uZ2V0Rmlyc3RWYWx1ZSgmaWQpOwogICAgICAvLyBQcmVmZXIgdG8gcmVmZXJlbmNlIGFuIG91dHB1dCBxdWVyeSBlbGVtZW50LgogICAgICBjb25zdCBOQVN0cmluZyYgZmlyc3RJRCA9IGZpcnN0UmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCk7CiAgICAgIGNvbnN0IE5BU3RyaW5nJiBzZWNvbmRJRCA9IHJld3JpdGUtPmdldFF1ZXJ5RWxlbWVudCgpLT5nZXRJRCgpOwogICAgICBpZiAoZmlyc3RJRC5kYXRhKClbMF0gIT0gJ08nICYmIHNlY29uZElELmRhdGEoKVswXSA9PSAnTycpCiAgICAgIHsKCS8vIFN3aXRjaCBiZXR3ZWVuIHRoZW0uCiAgICAgICAgc3dpdGNoUmV3cml0ZXMocmV3cml0ZSwgZmlyc3RSZXdyaXRlLCBNVkNvbE5hbWUpOwoJZGVsZXRlUHRyKGZpcnN0UmV3cml0ZSk7CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CglkZWxldGVQdHIocmV3cml0ZSk7CiAgICAgIH0KICAgIH0KICB9Cn0gIC8vIE1hdGNoT3V0cHV0OjphZGRSZXdyaXRlSW5zdHJ1Y3Rpb25zKCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBPdmVycmlkZSB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgaW4gb3JkZXIgdG8gYXZvaWQgZHVwbGljYXRlcy4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCnZvaWQgTWF0Y2hPdXRwdXQ6OmFkZE91dHB1dFRvQXZvaWQoY29uc3QgTkFTdHJpbmcmIGlkKQp7CiAgLy8gQWRkIGl0IHRvIHRoZSBsaXN0IG9mIElEcyB0byBhdm9pZC4KICBPdXRwdXRzVG9Bdm9pZEJ5SURfLmluc2VydCgmaWQsICZpZCk7CgogIC8vIENoZWNrIGlmIHdlIGFscmVhZHkgaGF2ZSBpdCBpbiB0aGUgb3V0cHV0IGxpc3QuCiAgaWYgKE91dHB1dFJld3JpdGVJbnN0cnVjdGlvbnNCeUlEXy5jb250YWlucygmaWQpID09IFRSVUUpCiAgewogICAgLy8gWWVzLCBpdHMgaW4gdGhlcmUuIFJlbW92ZSBpdC4KICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIGV4aXN0aW5nUmV3cml0ZSA9IE91dHB1dFJld3JpdGVJbnN0cnVjdGlvbnNCeUlEXy5nZXRGaXJzdFZhbHVlKCZpZCk7CiAgICBnZXRMaXN0T2ZGaW5hbEluc3RydWN0aW9ucygpLnJlbW92ZShleGlzdGluZ1Jld3JpdGUpOwogICAgT3V0cHV0UmV3cml0ZUluc3RydWN0aW9uc0J5SURfLnJlbW92ZSgmaWQpOwogICAgZGVsZXRlUHRyKGV4aXN0aW5nUmV3cml0ZSk7CiAgfQp9CgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyAgQ2xhc3MgTWF0Y2hSYW5nZVByZWRpY2F0ZXMKLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBSdW4gdGhlIFBhc3MgMSBhbGdvcml0aG0gb2YgcmFuZ2UgcHJlZGljYXRlIHRlc3QuCi8vIDEuIEZpcnN0IGRvIHRoZSBiaXRtYXAgdGVzdCwgdG8gc2VlIGlmIHdlIGNhbiBxdWlja2x5IGRpc3F1YWxpZnkgdGhlIE1WLgovLyAyLiBDaGVjayB0aGUgcHJlZGljYXRlcyBvbmUgYnkgb25lLgovLyAgICBGb3IgZWFjaCBxdWVyeSByYW5nZSBwcmVkaWNhdGUKLy8gICAgICBJZiB0aGUgcmFuZ2UgcHJlZGljYXRlIGlzIG9uIGFuIGV4cHJlc3Npb24KLy8gICAgICAgIAovLyAgICAgIEVsc2UgKHRoZSByYW5nZSBwcmVkIGlzIG9uIGEgc2luZ2xlIGNvbHVtbiBvciBlcXVhbGl0eSBzZXQpCi8vICAgICAgICBHZXQgdGhlIGNvbHVtbgovLyAgICAgICAgRmluZCB0aGUgTVYgcHJlZGljYXRlcyBvbiB0aGlzIGNvbHVtbiB0aHJvdWdoIHRoZSBCYXNlVGFibGVEZXRhaWxzLgovLyAgICAgICAgSWYgbm8gTVYgcHJlZGljYXRlcyAtIHRoaXMgY29sdW1uIFBBU1NFRCBhcyBhIGZpbmFsIE5vdFByb3ZpZGVkLgovLyAgICAgICAgSWYgTVYgcHJlZGljYXRlcyBleGlzdCAtIE1hcmsgZm9yIFBhc3MgMi4KLy8gUmV0dXJucyBUUlVFIGlmIHRoZSBNViBwYXNzZWQgdGhpcyB0ZXN0LCBGQUxTRSBpZiBpdCB3YXMgZGlzcXVhbGlmaWVkLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoUmFuZ2VQcmVkaWNhdGVzOjptYXRjaFBhc3MxKCkKewogIGlmIChtYXRjaFByZWRpY2F0ZUJpdG1hcHMoKSA9PSBGQUxTRSkKICAgIHJldHVybiBGQUxTRTsKCiAgY29uc3QgSkJCRGV0YWlsc1B0ciBtdkpiYkRldGFpbHMgPSBjYW5kaWRhdGVfLT5nZXRNdkRldGFpbHMoKS0+Z2V0SmJiRGV0YWlscygpOwogIGNvbnN0IFFSUmFuZ2VQcmVkTGlzdFB0ciAgcXVlcnlSYW5nZVByZWRMaXN0ID0gY2FuZGlkYXRlXy0+Z2V0UXVlcnlKYmIoKS0+Z2V0SHViKCktPmdldFJhbmdlUHJlZExpc3QoKTsKCiAgaWYgKHF1ZXJ5UmFuZ2VQcmVkTGlzdD09TlVMTCB8fCBxdWVyeVJhbmdlUHJlZExpc3QtPmdldExpc3QoKS5pc0VtcHR5KCkpCiAgewogICAgaWYgKCFtdkpiYkRldGFpbHMtPmhhc05vUmFuZ2VQcmVkaWNhdGVzKCkpCiAgICB7CiAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkKCJ0aGUgTVYgaGFzIHJhbmdlIHByZWRpY2F0ZXMsIGFuZCB0aGUgcXVlcnkgZG9lcyBub3QuIik7CiAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgLy8gTm8gcmFuZ2UgcHJlZGljYXRlcyBpbiBib3RoIHRoZSBNViBhbmQgdGhlIHF1ZXJ5LiAKICAgICAgLy8gTm90aGluZyB0byBkby4KICAgICAgcmV0dXJuIFRSVUU7CiAgICB9CiAgfQoKICAvLyBDb3B5IHRoZSBsaXN0IG9mIE1WIHJhbmdlIHByZWRpY2F0ZXMuCiAgLy8gQW55IG1hdGNoZWQgcHJlZGljYXRlIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoaXMgbGlzdCwgc28gd2UgY2FuIGNoZWNrCiAgLy8gdGhhdCBubyBNViBwcmVkcyB3ZXJlIGxlZnQgb3V0LgogIGlmICghbXZKYmJEZXRhaWxzLT5oYXNOb1JhbmdlUHJlZGljYXRlcygpKQogICAgbXZGdWxsUHJlZExpc3RfLmluc2VydChtdkpiYkRldGFpbHMtPmdldEpiYkRlc2NyaXB0b3IoKS0+Z2V0SHViKCktPmdldFJhbmdlUHJlZExpc3QoKS0+Z2V0TGlzdCgpKTsKCiAgLy8gVGhlIHF1ZXJ5IGhhcyBwcmVkaWNhdGVzLCBzbyB3ZSBuZWVkIHRvIGNoZWNrIHRoZW0gb25lLWJ5LW9uZS4KICBjb25zdCBSYW5nZVByZWRQdHJMaXN0JiAgcXVlcnlSYW5nZVByZWRzID0gcXVlcnlSYW5nZVByZWRMaXN0LT5nZXRMaXN0KCk7CiAgZm9yIChDb2xsSW5kZXggaT0wOyBpPHF1ZXJ5UmFuZ2VQcmVkcy5lbnRyaWVzKCk7IGkrKykKICB7CiAgICAvL1Jld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUgPSBOVUxMOwogICAgY29uc3QgUVJSYW5nZVByZWRQdHIgcXVlcnlSYW5nZVByZWQgPSBxdWVyeVJhbmdlUHJlZHNbaV07CiAgICBRUkVsZW1lbnRQdHIgcmFuZ2VJdGVtID0gcXVlcnlSYW5nZVByZWQtPmdldFJhbmdlSXRlbSgpLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpOwogICAgRWxlbWVudFR5cGUgcmFuZ2VFbGVtVHlwZSA9IHJhbmdlSXRlbS0+Z2V0RWxlbWVudFR5cGUoKTsKICAgIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAgICggcmFuZ2VFbGVtVHlwZSA9PSBFVF9Db2x1bW4gICB8fCAKCQkgICAgICAgIHJhbmdlRWxlbVR5cGUgPT0gRVRfSm9pblByZWQgfHwgCgkJICAgICAgICByYW5nZUVsZW1UeXBlID09IEVUX0V4cHIgICAgICAgKSwgCgkJICAgICAgUVJMb2dpY0V4Y2VwdGlvbiwgCgkJICAgICAgIkV4cGVjdGluZyByYW5nZSBpdGVtcyB0byBiZSBjb2x1bW5zLCBlcXVhbGl0eSBzZXRzIG9yIGV4cHJlc3Npb25zLiIpOwoKICAgIGlmIChyYW5nZUVsZW1UeXBlID09IEVUX0V4cHIpCiAgICB7CiAgICAgIC8vIERvIHRoZSBtYXRjaGluZyB3b3JrIGZvciBhIHJhbmdlIHByZWQgb24gYW4gZXhwcmVzc2lvbi4KICAgICAgaWYgKG1hdGNoUHJlZE9uRXhwcihxdWVyeVJhbmdlUHJlZCkgPT0gRkFMU0UpCglyZXR1cm4gRkFMU0U7CiAgICB9CiAgICBlbHNlIGlmIChyYW5nZUVsZW1UeXBlID09IEVUX0NvbHVtbikKICAgIHsKICAgICAgY29uc3QgUVJDb2x1bW5QdHIgcmFuZ2VDb2x1bW4gPSByYW5nZUl0ZW0tPmRvd25DYXN0VG9RUkNvbHVtbigpOwoKICAgICAgLy8gRG8gdGhlIG1hdGNoaW5nIHdvcmsgZm9yIGEgcmFuZ2UgcHJlZCBvbiBhIENvbHVtbi4KICAgICAgaWYgKG1hdGNoUHJlZE9uQ29sdW1uKHF1ZXJ5UmFuZ2VQcmVkLCByYW5nZUNvbHVtbikgPT0gRkFMU0UpCglyZXR1cm4gRkFMU0U7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIC8vIFJhbmdlIGl0ZW0gbXVzdCBiZSBhIGpvaW4gcHJlZC4KICAgICAgUVJKb2luUHJlZFB0ciBqb2luUHJlZCA9IHJhbmdlSXRlbS0+ZG93bkNhc3RUb1FSSm9pblByZWQoKTsKCiAgICAgIGlmIChtYXRjaFByZWRPbkVxdWFsaXR5U2V0KHF1ZXJ5UmFuZ2VQcmVkLCBqb2luUHJlZCkgPT0gRkFMU0UpCiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgfSAvLyBSYW5nZSBwcmVkIGlzIG9uIGpvaW4gcHJlZGljYXRlLgoKICB9IC8vIGZvciBvbiByYW5nZSBwcmVkaWNhdGVzLgoKICBpZiAobXZGdWxsUHJlZExpc3RfLmVudHJpZXMoKSA+IDApCiAgewogICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJNViByYW5nZSBwcmVkaWNhdGUgJXMgd2FzIG5vdCBtYXRjaGVkIGJ5IHRoZSBxdWVyeS4iLCAKCQkJCSAgICAgIG12RnVsbFByZWRMaXN0X1swXS0+Z2V0SUQoKSk7CiAgICByZXR1cm4gRkFMU0U7CiAgfQoKICByZXR1cm4gVFJVRTsKfSAgLy8gTWF0Y2hSYW5nZVByZWRpY2F0ZXM6Om1hdGNoUGFzczEoKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIE1hdGNoIGEgcmFuZ2UgcHJlZGljYXRlIG9uIGFuIGVxdWFsaXR5IHNldC4KLy8gVGhlIGFsZ29yaXRobSBpczoKLy8gMS4gRm9yIGVhY2ggY29sdW1uIGluIHRoZSBlcXVhbGl0eSBzZXQ6Ci8vICAgIDEuMSBJZiBpdHMgYW4gT3V0c2lkZSBjb2x1bW4sIGlnbm9yZSBpdCAoY29udGludWUgd2l0aCB0aGUgbG9vcCkuCi8vICAgIDEuMiBPdGhlcndpc2UgY2FsbCBtYXRjaFByZWRPbkNvbHVtbigpIG9uIGl0LCByZXR1cm4gVFJVRSBpZiBpdCB3YXMgbWF0Y2hlZC4KLy8gMi4gSWYgYWxsIHRoZSBjb2x1bW5zIHdlcmUgT3V0c2lkZSAtIHJldHVybiBUUlVFLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoUmFuZ2VQcmVkaWNhdGVzOjptYXRjaFByZWRPbkVxdWFsaXR5U2V0KGNvbnN0IFFSUmFuZ2VQcmVkUHRyIHF1ZXJ5UmFuZ2VQcmVkLCBjb25zdCBRUkpvaW5QcmVkUHRyIGpvaW5QcmVkKQp7CiAgY29uc3QgRWxlbWVudFB0ckxpc3QmIGVxdWFsaXR5U2V0ID0gam9pblByZWQtPmdldEVxdWFsaXR5TGlzdCgpOwogIENvbGxJbmRleCBtYXhFbnRyaWVzID0gZXF1YWxpdHlTZXQuZW50cmllcygpOwogIE5BQm9vbGVhbiBpbnNpZGVDb2xGb3VuZCA9IEZBTFNFOwogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxtYXhFbnRyaWVzOyBpKyspCiAgewogICAgUVJFbGVtZW50UHRyIGVxTWVtYmVyID0gZXF1YWxpdHlTZXRbaV0tPmdldFJlZmVyZW5jZWRFbGVtZW50KCk7CiAgICBpZiAoZXFNZW1iZXItPmdldEVsZW1lbnRUeXBlKCkgIT0gRVRfQ29sdW1uKQogICAgICBjb250aW51ZTsKCiAgICBRUkNvbHVtblB0ciBlcUNvbHVtbiA9IGVxTWVtYmVyLT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKICAgIGNvbnN0IE5BU3RyaW5nKiBleHRyYUh1YklEID0gTlVMTDsKICAgIGlmIChpc091dHNpZGVDb2x1bW4oZXFDb2x1bW4sIGV4dHJhSHViSUQpKQogICAgICBjb250aW51ZTsKICAgIGluc2lkZUNvbEZvdW5kID0gVFJVRTsKCiAgICBpZiAobWF0Y2hQcmVkT25Db2x1bW4ocXVlcnlSYW5nZVByZWQsIGVxQ29sdW1uKSkKICAgICAgcmV0dXJuIFRSVUU7CiAgfQoKICAvLyBJZiBhbGwgZXFhbGl0eSBzZXQgY29sdW1ucyBhcmUgT3V0c2lkZSwgdGhpcyByYW5nZSBwcmVkaWNhdGUgY2FuIGJlIGlnbm9yZWQuCiAgcmV0dXJuICFpbnNpZGVDb2xGb3VuZDsKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hSYW5nZVByZWRpY2F0ZXM6Om1hdGNoUHJlZE9uRXhwcihjb25zdCBRUlJhbmdlUHJlZFB0ciBxdWVyeVJhbmdlUHJlZCkKewogIFFSRWxlbWVudFB0ciByYW5nZUl0ZW0gPSBxdWVyeVJhbmdlUHJlZC0+Z2V0UmFuZ2VJdGVtKCktPmdldFJlZmVyZW5jZWRFbGVtZW50KCk7CiAgY29uc3QgUVJFeHByUHRyIHF1ZXJ5UmFuZ2VFeHByID0gcmFuZ2VJdGVtLT5kb3duQ2FzdFRvUVJFeHByKCk7CiAgY29uc3QgRWxlbWVudFB0ckxpc3QmIHF1ZXJ5SW5wdXRDb2x1bW5zID0gcXVlcnlSYW5nZUV4cHItPmdldElucHV0Q29sdW1ucyhoZWFwXyk7CiAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IE5VTEw7CgogIC8vIElmIHRoaXMgaXMgYW4gYWdncmVnYXRlIGV4cHJlc3Npb24gaW4gYSByb2xsdXAgcXVlcnkKICAvLyBkb24ndCBib3RoZXIgbWF0Y2hpbmcgdGhlIGV4cHJlc3Npb24gdGV4dC4KICAvLyBHbyBzdHJlaWdodCB0byBQYXNzIDIuCiAgaWYgKGNhbmRpZGF0ZV8tPmdldEFnZ3JlZ2F0ZU1hdGNoaW5nVHlwZSgpID09IEFNVF9NQVZfQVFfREcgICYmCiAgICAgIHF1ZXJ5UmFuZ2VFeHByLT5nZXRFeHByUm9vdCgpLT5jb250YWluc0FuQWdncmVnYXRlKCkgKQogIHsKICAgIHJld3JpdGUgPSBuZXcoaGVhcF8pIAogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShxdWVyeVJhbmdlUHJlZCwgTlVMTCwgUkNfUk9MTFVQX0VYUFIsIFJTX0lOVEVSTUVESUFURSwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICB9CiAgZWxzZQogIHsKICAgIGNvbnN0IE5BU3RyaW5nJiBwcmVkVGV4dCA9IHF1ZXJ5UmFuZ2VFeHByLT5nZXRFeHByVGV4dCgpOwogICAgUmFuZ2VQcmVkUHRyTGlzdCogbXZQcmVkc09uRXhwciA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpLT5nZXRKYmJEZXRhaWxzKCktPmdldFJhbmdlUHJlZHNPbkV4cHJlc3Npb24ocHJlZFRleHQpOwoKICAgIGlmIChtdlByZWRzT25FeHByICE9IE5VTEwpCiAgICB7CiAgICAgIC8vIEJvdGggTVYgYW5kIHF1ZXJ5IGhhdmUgYSByYW5nZSBwcmVkIHVzaW5nIHRoaXMgdGV4dC4gTm93IG1hdGNoIHRoZSBpbnB1dCBjb2x1bW5zLgogICAgICBmb3IgKENvbGxJbmRleCBqID0gMDsgajxtdlByZWRzT25FeHByLT5lbnRyaWVzKCk7IGorKykKICAgICAgewogICAgICAgIFFSUmFuZ2VQcmVkUHRyIG12UmFuZ2VQcmVkID0gKCptdlByZWRzT25FeHByKVtqXTsKICAgICAgICBjb25zdCBRUkV4cHJQdHIgbXZSYW5nZUV4cHIgPSBtdlJhbmdlUHJlZC0+Z2V0UmFuZ2VJdGVtKCktPmRvd25DYXN0VG9RUkV4cHIoKTsKICAgICAgICBpZiAobWF0Y2hFeHByZXNzaW9uSW5wdXRzKHF1ZXJ5SW5wdXRDb2x1bW5zLCBtdlJhbmdlRXhwci0+Z2V0SW5wdXRDb2x1bW5zKGhlYXBfKSkgPT0gRkFMU0UpCgkgIGNvbnRpbnVlOyAvLyBUcnkgbmV4dCBNViByYW5nZSBwcmVkIHdpdGggc2FtZSB0ZXh0IGJ1dCBkaWZmZXJlbnQgaW5wdXQgY29sdW1ucy4KICAgICAgICBlbHNlCiAgICAgICAgewoJICAvLyBJbnB1dCBjb2x1bW5zIG1hdGNoLiBOb3cgd2UgbmVlZCB0byBtYXRjaCB0aGUgcmFuZ2UgaXRzZWxmLiBEbyB0aGF0IGluIFBhc3MgMi4KCSAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCgkgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0ocXVlcnlSYW5nZVByZWQsIG12UmFuZ2VQcmVkLCBSQ19NQVRDSF9SQU5HRSwgUlNfSU5URVJNRURJQVRFLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwoJICBtdkZ1bGxQcmVkTGlzdF8ucmVtb3ZlKG12UmFuZ2VQcmVkKTsJIAoJICBicmVhazsgLy8gV2UgZm91bmQgYSBtYXRjaCwgd2UgY2FuIHN0b3AgbG9va2luZy4KICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CgogIGlmIChyZXdyaXRlID09IE5VTEwpCiAgewogICAgLy8gVGhlIE1WIGhhcyBubyByYW5nZSBwcmVkaWNhdGUgdXNpbmcgdGhpcyB0ZXh0LCBzbyB3ZSBuZWVkIHRvIHByb3ZpZGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMuCiAgICAvLyBXZSBuZWVkIHRvIHZlcmlmeSB0aGF0IHRoZSBwcmVkIGlucHV0IGNvbHVtbnMgYXJlIGF2YWlsYWJsZSBhcyBhbiBNViBvdXRwdXQuCgogICAgaWYgKCBjYW5kaWRhdGVfLT5nZXRBZ2dyZWdhdGVNYXRjaGluZ1R5cGUoKSA9PSBBTVRfTUFWX0FRX01HICYmCiAgICAgICAgIHF1ZXJ5UmFuZ2VFeHByLT5nZXRFeHByUm9vdCgpLT5jb250YWluc0FuQWdncmVnYXRlKCkgKQogICAgewogICAgICAvLyBUaGlzIGlzIGFuIGFnZ3JlZ2F0ZSBxdWVyeSBvbiBhIG1hdGNoaW5nIE1BViwKICAgICAgLy8gVHJ5IHRvIG1hdGNoIGFnZ3JlZ2F0ZSBmdW5jdGlvbnMsIGluIFBhc3MgMi4KICAgICAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0ocXVlcnlSYW5nZVByZWQsIE5VTEwsIFJDX0FHR1JfRVhQUiwgUlNfSU5URVJNRURJQVRFLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogICAgfQogICAgZWxzZQogICAgewogICAgICAvLyBUaGlzIGlzIG9uIGFuIE1KVi4gVHJ5IHRvIGZpbmQgdGhlIGlucHV0IGNvbHVtbnMuCiAgICAgIHJld3JpdGUgPSBmaW5kRXhwcmVzc2lvbklucHV0cyhxdWVyeUlucHV0Q29sdW1ucywgcXVlcnlSYW5nZVByZWQpOwogICAgICBpZiAocmV3cml0ZSAmJgoJICByZXdyaXRlLT5pc0ZpbmFsKCkgJiYKCSAgcmV3cml0ZS0+Z2V0U2Vjb25kYXJ5UmVzdWx0Q29kZSgpID09IFJDX0lOUFVUU19QUk9WSURFRCAmJgoJICBxdWVyeVJhbmdlRXhwci0+Z2V0RXhwclJvb3QoKS0+Y29udGFpbnNBbkFnZ3JlZ2F0ZSgpKQogICAgICB7CgkvLyBBIEhBVklORyBwcmVkaWNhdGUgb24gYW4gTUpWCgkvLyBBZGQgdGhlIGV4cHJlc3Npb24gaW5wdXRzIHRvIHRoZSBvdXRwdXQgbGlzdC4KICAgICAgICBhZGRJbnB1dHNUb091dHB1dExpc3QocmV3cml0ZSk7CgkvLyBBbmQgdGhlbiB0aHJvdyBhd2F5IHRoZSBSYW5nZSBwcmVkaWNhdGUgaXRzZWxmLgoJZGVsZXRlUHRyKHJld3JpdGUpOwoJcmV0dXJuIFRSVUU7CiAgICAgIH0KICAgIH0KICB9CgogIGlmIChyZXdyaXRlID09IE5VTEwpCiAgewogICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJRdWVyeSByYW5nZSBwcmVkICVzIGNhbm5vdCBiZSBwcm92aWRlZC4iLCBxdWVyeVJhbmdlUHJlZC0+Z2V0SUQoKS5kYXRhKCkpOwogICAgcmV0dXJuIEZBTFNFOyAgLy8gTm8gbWF0Y2ggZm91bmQgZm9yIHRoaXMgcmVzaWR1YWwgcHJlZC4gRGlzcXVhbGlmeSB0aGUgTVYgY2FuZGlkYXRlLgogIH0KCiAgYWRkUmV3cml0ZUluc3RydWN0aW9ucyhyZXdyaXRlKTsKICByZXR1cm4gVFJVRTsKfSAgLy8gTWF0Y2hSYW5nZVByZWRpY2F0ZXM6Om1hdGNoUHJlZE9uRXhwcigpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCk5BQm9vbGVhbiBNYXRjaFJhbmdlUHJlZGljYXRlczo6bWF0Y2hQcmVkT25Db2x1bW4oY29uc3QgUVJSYW5nZVByZWRQdHIgcXVlcnlSYW5nZVByZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFFSQ29sdW1uUHRyICAgIHJhbmdlQ29sdW1uKQp7CiAgUVJSYW5nZVByZWRQdHIgbXZSYW5nZVByZWQgPSBOVUxMOwogIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUgPSBOVUxMOwoKICAvLyBGaW5kIHRoZSBjb3JyZXNwb25kaW5nIE1WIHJhbmdlIHByZWRpY2F0ZSAoaWYgYW55KS4KICBpZiAoY2FuZGlkYXRlXy0+Z2V0TXZEZXRhaWxzKCktPmdldEpiYkRldGFpbHMoKS0+aGFzTm9SYW5nZVByZWRpY2F0ZXMoKSA9PSBGQUxTRSkKICB7CiAgICAvLyBGaW5kIHRoZSBjb3JyZXNwb25kaW5nIE1WIHRhYmxlIChpZiBhbnkpCiAgICBCYXNlVGFibGVEZXRhaWxzUHRyIGJhc2VUYWJsZSA9IGNhbmRpZGF0ZV8tPmdldE12VGFibGVGb3JRdWVyeUlEKHJhbmdlQ29sdW1uLT5nZXRUYWJsZUlEKCksIEZBTFNFKTsKICAgIGlmIChiYXNlVGFibGUgPT0gTlVMTCkKICAgIHsKICAgICAgLy8gVGhpcyBpcyBhbiBPdXRzaWRlIHRhYmxlLgogICAgICAvLyBXZSBjYW4gaWdub3JlIHRoaXMgcmFuZ2UgcHJlZGljYXRlLgogICAgICByZXR1cm4gVFJVRTsKICAgIH0KCiAgICAvLyBHZXQgdGhlIE1WIHJhbmdlIHByZWQgb24gdGhpcyBjb2x1bW4uCiAgICBtdlJhbmdlUHJlZCA9IGJhc2VUYWJsZS0+Z2V0UmFuZ2VDb2x1bW5QcmVkaWNhdGVzRm9yKHJhbmdlQ29sdW1uLT5nZXRDb2xJbmRleCgpKTsKICB9CgogIGlmIChtdlJhbmdlUHJlZCA9PSBOVUxMKQogIHsKICAgIC8vIFRoZSBNViBoYXMgbm8gcHJlZGljYXRlIG9uIHRoaXMgY29sdW1uLCBzbyB3ZSBuZWVkIHRvIHByb3ZpZGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMuCiAgICAvLyBXZSBuZWVkIHRvIHZlcmlmeSB0aGF0IHRoZSByYW5nZSBjb2x1bW4gaXMgYXZhaWxhYmxlIGFzIGFuIE1WIG91dHB1dC4KICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIGNvbHVtblJld3JpdGUgPSBtYXRjaENvbHVtbihyYW5nZUNvbHVtbiwgRkFMU0UpOwoKICAgIC8vIFRoZSByYW5nZSBjb2x1bW4gaXMgbm90IGF2YWlsYWJsZSAtIGRpc3F1YWxpZnkgdGhlIE1WLgogICAgaWYgKGNvbHVtblJld3JpdGUgPT0gTlVMTCkKICAgICAgcmV0dXJuIEZBTFNFOwoKICAgIC8vIFRoZSBwcmltYXJ5IHJlc3VsdCBjb2RlIGlzIE5vdFBydmlkZWQuCiAgICAvLyBJdHMgZmluYWwgaWYgdGhlIGNvbHVtbiByZXdyaXRlIGlzIEZpbmFsLgogICAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKHF1ZXJ5UmFuZ2VQcmVkLCBOVUxMLCBSQ19OT1RQUk9WSURFRCwgY29sdW1uUmV3cml0ZS0+Z2V0UmVzdWx0U3RhdHVzKCksIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICByZXdyaXRlLT5hZGRTdWJFbGVtZW50KGNvbHVtblJld3JpdGUpOwogIH0KICBlbHNlCiAgewogICAgLy8gQm90aCBNViBhbmQgcXVlcnkgaGF2ZSBhIHJhbmdlIHByZWQgb24gdGhpcyBjb2x1bW4uIFdlIHdpbGwgbWF0Y2ggdGhlbSBpbiBQYXNzIDIuCiAgICBtdkZ1bGxQcmVkTGlzdF8ucmVtb3ZlKG12UmFuZ2VQcmVkKTsKICAgIHJld3JpdGUgPSBuZXcoaGVhcF8pIAogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShxdWVyeVJhbmdlUHJlZCwgbXZSYW5nZVByZWQsIFJDX01BVENIX1JBTkdFLCBSU19JTlRFUk1FRElBVEUsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgfQoKICBhZGRSZXdyaXRlSW5zdHJ1Y3Rpb25zKHJld3JpdGUpOwogIHJldHVybiBUUlVFOwp9ICAvLyBNYXRjaFJhbmdlUHJlZGljYXRlczo6bWF0Y2hQcmVkT25Db2x1bW4oKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIENoZWNrIGlmIHRoZSBxdWVyeSBwcmVkaWNhdGUgYml0bWFwcyBhcmUgYSBzdXBlcnNldCBvZiB0aGUgTVYgcHJlZGljYXRlIGJpdG1hcHMuCi8vIFRoaXMgbWV0aG9kIGNoZWNrcyB0aGUgYml0bWFwcyBmb3IgYm90aCByYW5nZSBhbmQgcmVzaWR1YWwgcHJlZGljYXRlcywgCi8vIGJlY2F1c2UgdGhlIGFsZ29yaXRobSBpcyB0aGUgc2FtZSBmb3IgYm90aCwgYW5kIGl0IGRvZXNuJ3QgbWFrZSBzZW5zZSB0byAKLy8gcmVwZWF0IHRoZSBlbnRpcmUgbG9vcCBmb3IgdGhlIHJlc2lkdWFsIHByZWRpY2F0ZXMgaW4gdGhlIE1hdGNoUmVzaWR1YWxQcmVkaWNhdGVzCi8vIGNsYXNzIGZvciB0aGUgc2FrZSBvZiBvcmdhbml6ZWQgY29kZS4KLy8gSWYgdGhlIHF1ZXJ5IHJhbmdlIHByZWRpY2F0ZSBiaXRtYXAgaXMgbm90IGEgc3VwZXJzZXQgb2YgdGhlIE1WIGJpdG1hcCBmb3IKLy8gYWxsIHRoZSBpbnZvbHZlZCB0YWJsZXMsIHRoZW4gdGhlIE1WIGhhcyBwcmVkaWNhdGVzIHRoYXQgYXJlIG5vdCBjb3ZlcmVkIGJ5Ci8vIHRoZSBxdWVyeSwgYW5kIGlzIHZlcnkgcXVpY2tseSBkaXNxdWFsaWZpZWQuCi8vIFJldHVybiBUUlVFIGlmIHRoZSBNViBwYXNzZWQsIGFuZCBGQUxTRSBpZiBpdCBpcyBkaXNxdWFsaWZpZWQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hSYW5nZVByZWRpY2F0ZXM6Om1hdGNoUHJlZGljYXRlQml0bWFwcygpCnsKICBKQkJEZXRhaWxzUHRyIG12SmJiRGV0YWlscyA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpLT5nZXRKYmJEZXRhaWxzKCk7CgogIC8vIElmIHRoZSBNViBoYXMgbm8gcmFuZ2UgYW5kIHJlc2lkdWFsIHByZWRzLCB0aGVyZSBpcyBubyBuZWVkIHRvIGNoZWNrIHRoZSBiaXRtYXBzLgogIGlmIChtdkpiYkRldGFpbHMtPmhhc05vUmFuZ2VQcmVkaWNhdGVzKCkgJiYgbXZKYmJEZXRhaWxzLT5oYXNOb1Jlc2lkdWFsUHJlZGljYXRlcygpKQogICAgcmV0dXJuIFRSVUU7CgogIC8vIEl0ZXJhdGUgb24gdGhlIHRhYmxlcyBpbiB0aGUgam9pbiBzdWItZ3JhcGgsIHdoaWNoIGNvcnJlc3BvbmQgdG8gdGhlIE1WIGh1YiB0YWJsZXMuCiAgUVJKb2luU3ViR3JhcGhQdHIgc3ViR3JhcGggPSBjYW5kaWRhdGVfLT5nZXRKYmJTdWJzZXQoKS0+Z2V0U3ViR3JhcGgoKTsKICBmb3IoIHN1YkdyYXBoLT5yZXNldCgpOyBzdWJHcmFwaC0+aGFzTmV4dCgpOyBzdWJHcmFwaC0+YWR2YW5jZSgpICkKICB7CiAgICAvLyBHZXQgdGhlIHRhYmxlIHF1ZXJ5IGRlc2NyaXB0b3IgSUQsIGFuZCBmcm9tIGl0IHRoZSBRUlRhYmxlIHBvaW50ZXIuCiAgICBjb25zdCBKb2luR3JhcGhUYWJsZVB0ciBxdWVyeUpvaW5HcmFwaFRhYmxlID0gc3ViR3JhcGgtPmdldEN1cnJlbnQoKTsKICAgIGNvbnN0IE5BU3RyaW5nJiBxdWVyeVRhYmxlSUQgPSBxdWVyeUpvaW5HcmFwaFRhYmxlLT5nZXRJRCgpOwogICAgY29uc3QgUVJUYWJsZVB0ciBxdWVyeVRhYmxlID0gY2FuZGlkYXRlXy0+Z2V0UXVlcnlEZXRhaWxzKCktPmdldEVsZW1lbnRGb3JJRChxdWVyeVRhYmxlSUQpLT5kb3duQ2FzdFRvUVJUYWJsZSgpOwoKICAgIC8vIEdldCB0aGUgcXVlcnkgcHJlZGljYXRlIGJpdG1hcHMKICAgIGNvbnN0IFhNTEJpdG1hcCYgcXVlcnlSYW5nZUJpdHMgPSBxdWVyeVRhYmxlLT5nZXRSYW5nZUJpdHMoKTsKICAgIGNvbnN0IFhNTEJpdG1hcCYgcXVlcnlSZXNpZHVhbEJpdHMgPSBxdWVyeVRhYmxlLT5nZXRSZXNpZHVhbEJpdHMoKTsKCiAgICAvLyBGaW5kIHRoZSBNViB0YWJsZSBJRCB1c2luZyB0aGUgTVZNZW1vIG1hcHBpbmcuCiAgICBCYXNlVGFibGVEZXRhaWxzUHRyIG12VGFibGVEZXRhaWxzID0gY2FuZGlkYXRlXy0+Z2V0TXZUYWJsZUZvclF1ZXJ5SUQocXVlcnlUYWJsZUlEKTsKCiAgICAvLyBHZXQgdGhlIE1WIHByZWRpY2F0ZSBiaXRtYXBzCiAgICBjb25zdCBYTUxCaXRtYXAmIG12UmFuZ2VCaXRzID0gbXZUYWJsZURldGFpbHMtPmdldFJhbmdlQml0cygpOwogICAgY29uc3QgWE1MQml0bWFwJiBtdlJlc2lkdWFsQml0cyA9IG12VGFibGVEZXRhaWxzLT5nZXRSZXNpZHVhbEJpdHMoKTsKCiAgICAvLyBQZXJmb3JtIHRoZSBhY3R1YWwgdGVzdC4KICAgIC8vIEFueSBmYWlsdXJlIGRpc3F1YWxpZmllcyB0aGUgTVYuCiAgICBpZiAocXVlcnlSYW5nZUJpdHMuY29udGFpbnMobXZSYW5nZUJpdHMpID09IEZBTFNFKQogICAgewogICAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIlRhYmxlICVzIGZhaWxlZCBvbiByYW5nZSBiaXRtYXAuIiwgcXVlcnlUYWJsZS0+Z2V0VGFibGVOYW1lKCkuZGF0YSgpKTsKICAgICAgcmV0dXJuIEZBTFNFOyAKICAgIH0KICAgIGlmIChxdWVyeVJlc2lkdWFsQml0cy5jb250YWlucyhtdlJlc2lkdWFsQml0cykgPT0gRkFMU0UpCiAgICB7CiAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgiVGFibGUgJXMgZmFpbGVkIG9uIHJlc2lkdWFsIGJpdG1hcC4iLCBxdWVyeVRhYmxlLT5nZXRUYWJsZU5hbWUoKS5kYXRhKCkpOwogICAgICByZXR1cm4gRkFMU0U7IAogICAgfQogIH0KCiAgcmV0dXJuIFRSVUU7Cn0gIC8vIE1hdGNoUmFuZ2VQcmVkaWNhdGVzOjptYXRjaFByZWRpY2F0ZUJpdG1hcHMoKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIFJ1biB0aGUgUGFzcyAyIGFsZ29yaXRobSBvZiByYW5nZSBwcmVkaWNhdGUgdGVzdC4KLy8gUmV0dXJucyBUUlVFIGlmIHRoZSBNViBwYXNzZWQgdGhpcyB0ZXN0LCBGQUxTRSBpZiBpdCB3YXMgZGlzcXVhbGlmaWVkLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoUmFuZ2VQcmVkaWNhdGVzOjptYXRjaFBhc3MyT25FbGVtZW50KFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHBlbmRpbmcpCnsKICBjb25zdCBRUlJhbmdlUHJlZFB0ciBxdWVyeVByZWQgPSBwZW5kaW5nLT5nZXRRdWVyeUVsZW1lbnQoKS0+ZG93bkNhc3RUb1FSUmFuZ2VQcmVkKCk7CgogIGlmIChwZW5kaW5nLT5nZXRSZXN1bHRDb2RlKCkgPT0gUkNfQUdHUl9FWFBSIHx8CiAgICAgIHBlbmRpbmctPmdldFJlc3VsdENvZGUoKSA9PSBSQ19ST0xMVVBfRVhQUikKICB7CiAgICBRUkVsZW1lbnRQdHIgdHJlZUVsZW0gPQogICAgICBxdWVyeVByZWQtPmdldFJhbmdlSXRlbSgpLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpLT5kb3duQ2FzdFRvUVJFeHByKCkKICAgICAgICAtPmdldEV4cHJSb290KCktPmdldFJlZmVyZW5jZWRFbGVtZW50KCk7CiAgICBRUkV4cGxpY2l0RXhwclB0ciB0cmVlRXhwciA9IHN0YXRpY19jYXN0PFFSRXhwbGljaXRFeHByUHRyPih0cmVlRWxlbSk7CiAgICAvLyBVc2UgYSB2aXNpdG9yIHRvIGZpbmQgYWdncmVnYXRlIGZ1bmN0aW9ucywgYW5kIHNvbHZlIGFueSB0aGF0IGFyZSBmb3VuZC4KICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIGV4cHJSZXdyaXRlID0gZmluZEludGVybmFsQWdncmVnYXRlRnVuY3Rpb25zKHRyZWVFeHByKTsKCiAgICBpZiAoZXhwclJld3JpdGUgPT0gTlVMTCkKICAgIHsKICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJSYW5nZSBIQVZJTkcgcHJlZGljYXRlICVzIGlzIG5vdCBQcm92aWRlZCBieSB0aGUgTVYuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5UHJlZC0+Z2V0SUQoKS5kYXRhKCkpOwogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CgogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKHF1ZXJ5UHJlZC0+Z2V0UmFuZ2VJdGVtKCksIE5VTEwsIFJDX05PVFBST1ZJREVELCBSU19GSU5BTCwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKCiAgICBleHByUmV3cml0ZS0+c2V0UXVlcnlFbGVtZW50KHF1ZXJ5UHJlZC0+Z2V0UmFuZ2VJdGVtKCkpOwogICAgcmV3cml0ZS0+YWRkU3ViRWxlbWVudChleHByUmV3cml0ZSk7CiAgICByZXdyaXRlLT5zZXRRdWVyeUVsZW1lbnQocXVlcnlQcmVkKTsKICAgIHJld3JpdGUtPnNldFNlY29uZGFyeVJlc3VsdENvZGUocGVuZGluZy0+Z2V0UmVzdWx0Q29kZSgpKTsKICAgIGFkZFJld3JpdGVJbnN0cnVjdGlvbnMocmV3cml0ZSk7CiAgICBkZWxldGVQdHIocGVuZGluZyk7CiAgICByZXR1cm4gVFJVRTsKICB9CgogIGlmIChwZW5kaW5nLT5nZXRSZXN1bHRDb2RlKCkgPT0gUkNfTk9UUFJPVklERUQpCiAgewogICAgaWYgKHBlbmRpbmctPmdldFN1YkVsZW1lbnRzKCktPmluZGlyZWN0SW5wdXRzXy5lbnRyaWVzKCkgPiAwKQogICAgewogICAgICBpZiAocXVlcnlQcmVkLT5nZXRSYW5nZUl0ZW0oKS0+Z2V0RWxlbWVudFR5cGUoKSA9PSBFVF9FeHByKSAKICAgICAgewogICAgICAgIC8vIFRoZSByYW5nZSBleHByZXNzaW9uIG1heSBiZSBhbiBvdXRwdXQgb2YgdGhlIE1WLAogICAgICAgIFFSRXhwclB0ciByYW5nZUV4cHIgPSBxdWVyeVByZWQtPmdldFJhbmdlSXRlbSgpLT5kb3duQ2FzdFRvUVJFeHByKCk7CiAgICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgZXhwclJld3JpdGUgPSBmaW5kTWF0Y2hpbmdNdkV4cHJlc3Npb24ocmFuZ2VFeHByLT5nZXRFeHByUm9vdCgpKTsKICAgICAgICBpZiAoZXhwclJld3JpdGUgPT0gTlVMTCkKICAgICAgICB7CgkgIC8vIFRoZSByYW5nZSBleHByZXNzaW9uIGNhbm5vdCBiZSBwcm92aWRlZC4gRGlzcXVhbGlmeSB0aGUgTVYuCgkgIC8vIGxvZ01WV2FzRGlzcXVhbGlmaWVkMSgpIHdhcyBhbHJlYWR5IGNhbGxlZCBieSBtYXRjaENvbHVtbigpOwoJICByZXR1cm4gTlVMTDsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoZXhwclJld3JpdGUtPmdldFJlc3VsdFN0YXR1cygpID09IFJTX0ZJTkFMICYmCiAgICAgICAgICAgICAgICAgZXhwclJld3JpdGUtPmdldFJlc3VsdENvZGUoKSA9PSBSQ19QUk9WSURFRCkKICAgICAgICB7CiAgICAgICAgICAvLyBUaGUgcmFuZ2UgZXhwcmVzc2lvbiBpcyBhbiBvdXRwdXQgb2YgdGhlIE1WLgoKICAgICAgICAgIC8vIENsZWFyIHRoZSBpbmRpcmVjdCBzdWItZWxlbWVudHMgZmlyc3QuCiAgICAgICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbUxpc3QmIGluZGlyZWN0ID0gcGVuZGluZy0+Z2V0U3ViRWxlbWVudHMoKS0+aW5kaXJlY3RJbnB1dHNfOwogICAgICAgICAgZm9yIChDb2xsSW5kZXggaT0wOyBpPGluZGlyZWN0LmVudHJpZXMoKTsgaSsrKQogICAgICAgICAgICBkZWxldGVQdHIoaW5kaXJlY3RbaV0pOwogICAgICAgICAgaW5kaXJlY3QuY2xlYXIoKTsKCiAgICAgICAgICAvLyBOb3cgYWRkIHRoZSBuZXcgcmV3cml0ZSBpbnN0cnVjdGlvbnMuCiAgICAgICAgICBleHByUmV3cml0ZS0+c2V0UXVlcnlFbGVtZW50KHJhbmdlRXhwcik7CiAJICBwZW5kaW5nLT5hZGRTdWJFbGVtZW50KGV4cHJSZXdyaXRlKTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgiUmFuZ2UgZXhwcmVzc2lvbiAlcyBpcyBub3QgUHJvdmlkZWQgYnkgdGhlIE1WLiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVlcnlQcmVkLT5nZXRJRCgpLmRhdGEoKSk7CiAgICAgICAgICBkZWxldGVQdHIoZXhwclJld3JpdGUpOwogICAgICAgICAgcmV0dXJuIE5VTEw7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgLy8gVGhpcyBtdXN0IGhhdmUgYmVlbiBhIGJhY2sgam9pbiBvciBleHRyYS1odWIgdGFibGUuCiAgICAvLyBJZiB3ZSBnb3QgaGVyZSwgaXQgbWVhbnMgaXRzIE9LLgogICAgcGVuZGluZy0+c2V0UmVzdWx0U3RhdHVzKFJTX0ZJTkFMKTsKICAgIGFkZFJld3JpdGVJbnN0cnVjdGlvbnMocGVuZGluZyk7CiAgICByZXR1cm4gVFJVRTsKICB9CgogIGFzc2VydExvZ0FuZFRocm93MShDQVRfTUFUQ0hUU1RfTVZERVRBSUxTLCBMTF9NVlFSX0ZBSUwsCiAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmctPmdldFJlc3VsdENvZGUoKSA9PSBSQ19NQVRDSF9SQU5HRSwgUVJMb2dpY0V4Y2VwdGlvbiwgCiAgICAiVW5leHBlY3RlZCBQYXNzIDIgcmFuZ2UgcHJlZCByZXN1bHQgY29kZTogJXMuIiwgcGVuZGluZy0+Z2V0UmVzdWx0U3RyaW5nKCkpOyAKCiAgLy8gR2V0IHRoZSBSYW5nZVNwZWMgb2JqZWN0IGZyb20gdGhlIFF1ZXJ5IGRlc2NyaXB0b3IKICBjb25zdCBSYW5nZVNwZWMqIHF1ZXJ5UmFuZ2VTcGVjID0gcXVlcnlQcmVkLT5nZXRSYW5nZVNwZWMoaGVhcF8pOwoKICAvLyBHZXQgdGhlIFJhbmdlU3BlYyBvYmplY3QgZnJvbSB0aGUgTVYgZGVzY3JpcHRvcgogIGNvbnN0IFFSUmFuZ2VQcmVkUHRyIG12UHJlZCA9IHBlbmRpbmctPmdldE12RWxlbWVudCgpLT5kb3duQ2FzdFRvUVJSYW5nZVByZWQoKTsKICBjb25zdCBSYW5nZVNwZWMqIG12UmFuZ2VTcGVjID0gbXZQcmVkLT5nZXRSYW5nZVNwZWMoaGVhcF8pOwoKICBpZiAocXVlcnlSYW5nZVNwZWMtPmlzRXF1YWwoKm12UmFuZ2VTcGVjKSkKICB7CiAgICAvLyBUaGUgcmFuZ2UgcHJlZGljYXRlcyBhcmUgaWRlbnRpY2FsIC0gcmV0dXJuIFByb3ZpZGVkLgogICAgcGVuZGluZy0+c2V0UmVzdWx0Q29kZShSQ19QUk9WSURFRCk7CiAgfQogIGVsc2UgaWYgKG12UHJlZC0+Z2V0TXVzdE1hdGNoKCkgfHwgcXVlcnlQcmVkLT5nZXRNdXN0TWF0Y2goKSkKICB7CiAgICAvLyBUaGUgcHJlZGljYXRlIG11c3QgbWF0Y2ggZXhhY3RseSwgYnV0IHRoZXkgZG9uJ3QKICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgiVGhlIHJhbmdlIHByZWRpY2F0ZSAlcyBkb2VzIG5vdCBleGFjdGx5IG1hdGNoIGFueSBNViBwcmVkaWNhdGUuIiwKCQkJCSAgICAgIHF1ZXJ5UHJlZC0+Z2V0SUQoKS5kYXRhKCkpOwogICAgcmV0dXJuIEZBTFNFOwogIH0KICBlbHNlCiAgewogICAgLy8gVGhlIHByZWRpY2F0ZXMgYXJlIG5vdCBpZGVudGljYWwsIGJ1dCB0aGV5IGRvbid0IG5lZWQgdG8gYmUuCiAgICBpZiAobXZSYW5nZVNwZWMtPnN1YnN1bWVzKHF1ZXJ5UmFuZ2VTcGVjKSkKICAgIHsKICAgICAgLy8gVGhlIHF1ZXJ5IHByZWRpY2F0ZSBzdWJzdW1lcyB0aGUgTVYgcHJlZGljYXRlIC0gTm90UHJvdmlkZWQuCiAgICAgIHBlbmRpbmctPnNldFJlc3VsdENvZGUoUkNfTk9UUFJPVklERUQpOwoKICAgICAgLy8gTGFzdCB0aGluZyB0byBjaGVjayAtIGlzIHRoZSByYW5nZSBjb2x1bW4gcHJvdmlkZWQgYXMgYW4gb3V0cHV0PwogICAgICAvLyBPdGhlcndpc2Ugd2UgY2FuJ3QgdXNlIHRoZSByYW5nZSBwcmVkIG9uIHRoZSBNVi4uLgogICAgICBRUkVsZW1lbnRQdHIgcmFuZ2VJdGVtID0gcXVlcnlQcmVkLT5nZXRSYW5nZUl0ZW0oKS0+Z2V0UmVmZXJlbmNlZEVsZW1lbnQoKTsKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgY29sdW1uUmV3cml0ZSA9IE5VTEw7CiAgICAgIE5BQm9vbGVhbiB3YXNBZGRlZCA9IEZBTFNFOwogICAgICBzd2l0Y2gocmFuZ2VJdGVtLT5nZXRFbGVtZW50VHlwZSgpKQogICAgICB7CiAgICAgICAgY2FzZSBFVF9Db2x1bW46CiAgICAgICAgewogICAgICAgICAgUVJDb2x1bW5QdHIgcmFuZ2VDb2wgPSByYW5nZUl0ZW0tPmRvd25DYXN0VG9RUkNvbHVtbigpOwogICAgICAgICAgY29sdW1uUmV3cml0ZSA9IG1hdGNoQ29sdW1uKHJhbmdlQ29sLCBGQUxTRSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlIEVUX0pvaW5QcmVkOgogICAgICAgIHsKICAgICAgICAgIFFSSm9pblByZWRQdHIgcmFuZ2VKb2luID0gcmFuZ2VJdGVtLT5kb3duQ2FzdFRvUVJKb2luUHJlZCgpOwogICAgICAgICAgY29sdW1uUmV3cml0ZSA9IG1hdGNoRXF1YWxpdHlTZXQocmFuZ2VKb2luKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgRVRfRXhwcjoKICAgICAgICB7CiAgICAgICAgICAvLyBJdCBtdXN0IGJlIGEgcmFuZ2UgcHJlZGljYXRlIG9uIGFuIGV4cHJlc3Npb24uCiAgICAgICAgICBRUkV4cHJQdHIgcmFuZ2VFeHByID0gcXVlcnlQcmVkLT5nZXRSYW5nZUl0ZW0oKS0+ZG93bkNhc3RUb1FSRXhwcigpOwogICAgICAgICAgY29sdW1uUmV3cml0ZSA9IG1hdGNoRXhwcmVzc2lvbihyYW5nZUV4cHIpOwogICAgICAgICAgaWYgKGNvbHVtblJld3JpdGUgIT0gTlVMTCkKICAgICAgICAgIHsKICAgICAgICAgICAgLy8gV2UgY2FuIG9ubHkgdXNlIGEgRmluYWwgcmV3cml0ZSB1c2luZyBhbiBNViBvdXRwdXQgZXhwcmVzc2lvbi4KICAgICAgICAgICAgaWYgKGNvbHVtblJld3JpdGUtPmlzRmluYWwoKSA9PSBGQUxTRSkKICAgICAgICAgICAgewogICAgICAgICAgICAgIGRlbGV0ZVB0cihjb2x1bW5SZXdyaXRlKTsKICAgICAgICAgICAgICBjb2x1bW5SZXdyaXRlID0gTlVMTDsKICAgICAgICAgICAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoInJhbmdlIHByZWRpY2F0ZSAlcyBjYW5ub3QgYmUgUHJvdmlkZWQuIiwgCgkJCQkJcXVlcnlQcmVkLT5nZXRJRCgpLmRhdGEoKSk7CiAgICAgICAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgICAgICAgICB9CgogICAgICAgICAgICBjb2x1bW5SZXdyaXRlLT5zZXRRdWVyeUVsZW1lbnQocmFuZ2VFeHByKTsKICAgICAgICAgICAgLy8gSXMgdGhlIGVudGlyZSByYW5nZSBleHByZXNzaW9uIFByb3ZpZGVkIGJ5IHRoZSBNVi4KICAgICAgICAgICAgaWYgKGNvbHVtblJld3JpdGUtPmdldE12RWxlbWVudCgpID09IE5VTEwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAvLyBObyAtIE9ubHkgdGhlIGlucHV0IGNvbHVtbnMgYXJlIFByb3ZpZGVkCgkgICAgICBwZW5kaW5nLT5hZGRTdWJFbGVtZW50cyhjb2x1bW5SZXdyaXRlLT5nZXRTdWJFbGVtZW50cygpKTsKICAgICAgICAgICAgICBjb2x1bW5SZXdyaXRlLT5nZXRTdWJFbGVtZW50cygpLT5jbGVhcigpOwogICAgICAgICAgICAgIGRlbGV0ZVB0cihjb2x1bW5SZXdyaXRlKTsKICAgICAgICAgICAgICBjb2x1bW5SZXdyaXRlID0gTlVMTDsKICAgICAgICAgICAgICB3YXNBZGRlZCA9IFRSVUU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0gLy8gZW5kIHN3aXRjaCgpCgogICAgICBpZiAoY29sdW1uUmV3cml0ZSA9PSBOVUxMKQogICAgICB7CgkvLyBUaGUgcmFuZ2UgY29sdW1uIGNhbm5vdCBiZSBwcm92aWRlZC4gRGlzcXVhbGlmeSB0aGUgTVYuCgkvLyBsb2dNVldhc0Rpc3F1YWxpZmllZDEoKSB3YXMgYWxyZWFkeSBjYWxsZWQgYnkgbWF0Y2hDb2x1bW4oKTsKICAgICAgICBpZiAoIXdhc0FkZGVkKQoJICByZXR1cm4gTlVMTDsKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKCXBlbmRpbmctPmFkZFN1YkVsZW1lbnQoY29sdW1uUmV3cml0ZSk7CiAgICAgIH0KCiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIC8vIFRoZSBNViBwcmVkaWNhdGUgZG9lcyBub3Qgc3Vic3VtZSB0aGUgcXVlcnkgcHJlZGljYXRlIC0gZGlzcXVhbGlmeSEKICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJUaGUgcXVlcnkgcmFuZ2UgcHJlZGljYXRlICVzIGlzIG5vdCBzdWJzdW1lZCBieSB0aGUgY29ycmVzcG9uZGluZyBNViBwcmVkaWNhdGUuIiwgCgkJCQkJcXVlcnlQcmVkLT5nZXRJRCgpLmRhdGEoKSk7CiAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KICB9CgogIC8vIEluc2VydCB0aGUgcmV3cml0ZSBpbnN0cnVjdGlvbiB0byB0aGUgZmluYWwgbGlzdC4KICBwZW5kaW5nLT5zZXRSZXN1bHRTdGF0dXMoUlNfRklOQUwpOwogIGFkZFJld3JpdGVJbnN0cnVjdGlvbnMocGVuZGluZyk7CiAgcmV0dXJuIFRSVUU7Cn0gIC8vIE1hdGNoUmFuZ2VQcmVkaWNhdGVzOjptYXRjaFBhc3MyT25FbGVtZW50KCkKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBDcmVhdGUgYSBuZXcgUVJSYW5nZVByZWQgZWxlbWVudCBmb3IgdGhlIHJlc3VsdCBkZXNjcmlwdG9yLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKUVJSYW5nZVByZWRQdHIgTWF0Y2hSYW5nZVByZWRpY2F0ZXM6OmNyZWF0ZU5ld1Jlc3VsdEVsZW1lbnQoUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSkKewogIC8vIENvbnN0cnVjdCB0aGUgbmV3IGVsZW1lbnQKICBRUlJhbmdlUHJlZFB0ciByYW5nZUVsZW1lbnQgPSBuZXcoaGVhcF8pIFFSUmFuZ2VQcmVkKEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgLy8gU2V0IHRoZSByZXN1bHQgYXR0cmlidXRlLgogIHJhbmdlRWxlbWVudC0+c2V0UmVzdWx0KHJld3JpdGUtPmdldERlc2NyaXB0b3JSZXN1bHRDb2RlKCkpOwogIC8vIFNldCB0aGUgcmVmIGF0dHJpYnV0ZS4KICByYW5nZUVsZW1lbnQtPnNldFJlZihyZXdyaXRlLT5nZXRRdWVyeUVsZW1lbnQoKS0+Z2V0SUQoKSk7CgogIHJldHVybiByYW5nZUVsZW1lbnQ7Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBBIFByb3ZpZGVkIHJhbmdlIHByZWRpY2F0ZSBuZWVkcyBvbmx5IHRoZSByZWZlcmVuY2UgdG8gdGhlIG1hdGNoZWQgCi8vIHF1ZXJ5IGVsZW1lbnQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hSYW5nZVByZWRpY2F0ZXM6OmdlbmVyYXRlUHJvdmlkZWRFbGVtZW50KFFSQ2FuZGlkYXRlUHRyIHJlc3VsdERlc2MsIAoJCQkJCQkJUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSkKewogIC8vIENyZWF0ZSB0aGUgbmV3IFJhbmdlIGVsZW1lbnQsIG1hcmsgaXQgYXMgUHJvdmlkZWQuCiAgUVJSYW5nZVByZWRQdHIgcmFuZ2VFbGVtZW50ID0gY3JlYXRlTmV3UmVzdWx0RWxlbWVudChyZXdyaXRlKTsKCiAgLy8gQWRkIGl0IHRvIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICByZXN1bHREZXNjLT5nZXRSYW5nZVByZWRMaXN0KCktPmFkZEl0ZW0ocmFuZ2VFbGVtZW50KTsKICByZXR1cm4gVFJVRTsKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIEEgTm90UHJvdmlkZWQgcmFuZ2UgcHJlZGljYXRlIGluY2x1ZGVzIHRoZSBhY3R1YWwgcmFuZ2UgcHJlZGljYXRlIHdpdGggCi8vIHJld3JpdGUgaW5zdHJ1Y3Rpb25zIGZvciB0aGUgaW5wdXQgY29sdW1ucy4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCk5BQm9vbGVhbiBNYXRjaFJhbmdlUHJlZGljYXRlczo6Z2VuZXJhdGVOb3RQcm92aWRlZEVsZW1lbnQoUVJDYW5kaWRhdGVQdHIgcmVzdWx0RGVzYywgCgkJCQkJCQkgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgLy8gQ3JlYXRlIHRoZSBuZXcgT3V0cHV0IGVsZW1lbnQsIG1hcmsgaXQgYXMgTm90UHJvdmlkZWQsIGFuZCByZWYgdGhlIHF1ZXJ5IHJhbmdlIHByZWQuCiAgUVJSYW5nZVByZWRQdHIgcmFuZ2VFbGVtZW50ID0gY3JlYXRlTmV3UmVzdWx0RWxlbWVudChyZXdyaXRlKTsKICBRUkVsZW1lbnRQdHIgICByYW5nZUl0ZW0gPSBOVUxMOwoKICAvLyBHZXQgdGhlIHJld3JpdGUgZm9yIHRoZSByYW5nZSBjb2x1bW4uCiAgaWYgKHJld3JpdGUtPmdldFNlY29uZGFyeVJlc3VsdENvZGUoKSA9PSBSQ19BR0dSX0VYUFIgfHwKICAgICAgcmV3cml0ZS0+Z2V0U2Vjb25kYXJ5UmVzdWx0Q29kZSgpID09IFJDX1JPTExVUF9FWFBSKQogIHsKICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIGV4cHJSZXdyaXRlID0gcmV3cml0ZS0+Z2V0U3ViRWxlbWVudHMoKS0+bm90UHJvdmlkZWRJbnB1dHNfWzBdOwogICAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgICAgZXhwclJld3JpdGUsIFFSTG9naWNFeGNlcHRpb24sIAoJCSAgICAgICJFeHBlY3RlZCBhIHNpbmdsZSBOb3RQcm92aWRlZCBzdWItZWxlbWVudCBmb3IgYWdncmVnYXRlIHJhbmdlIHByZWRpY2F0ZXMuIik7IAogICAgcmFuZ2VJdGVtID0gZ2VuZXJhdGVBZ2dyZWdhdGVFeHByZXNzaW9uT3V0cHV0KGV4cHJSZXdyaXRlKTsKICAgIGlmIChyYW5nZUl0ZW0gPT0gTlVMTCkKICAgIHsKICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJSYW5nZSBIQVZJTkcgcHJlZGljYXRlICVzIGNhbm5vdCBiZSBQcm92aWRlZC4iLCAKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCkuZGF0YSgpKTsKICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQogICAgZWxzZQogICAgewogICAgICAvLyBTZXQgdGhlIHJlc3VsdCBhdHRyaWJ1dGUuCiAgICAgIHJhbmdlRWxlbWVudC0+c2V0UmVzdWx0KHJld3JpdGUtPmdldERlc2NyaXB0b3JSZXN1bHRDb2RlKCkpOwogICAgICAvLyBTZXQgdGhlIHJlZiBhdHRyaWJ1dGUuCiAgICAgIHJhbmdlRWxlbWVudC0+c2V0UmVmKHJld3JpdGUtPmdldFF1ZXJ5RWxlbWVudCgpLT5nZXRJRCgpKTsKICAgIH0KICB9CiAgZWxzZSAKICB7CiAgICBjb21wb3NpdGVNYXRjaGluZ1Jlc3VsdHNQdHIgc3ViRWxlbWVudHMgPSByZXdyaXRlLT5nZXRTdWJFbGVtZW50cygpOwoKICAgIGlmIChyZXdyaXRlLT5nZXRTZWNvbmRhcnlSZXN1bHRDb2RlKCkgPT0gUkNfTk9fSU5QVVRTKQogICAgewogICAgICAvLyBUaGUgcmFuZ2UgaXRlbSBpcyBhbiBleHByZXNzaW9uIHdpdGggbm8gaW5wdXQgY29sdW1ucywgc3VjaCBhcyAoQ09VTlQoKikKICAgICAgLy8gQ3JlYXRlIGEgZHVwbGljYXRlIHJhbmdlIGl0ZW0gZm9yIGl0IGluIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICAgICAgc3ViRXhwcmVzc2lvblJld3JpdGVIYXNoIHN1YkV4cHJIYXNoKGhhc2hLZXksIElOSVRfSEFTSF9TSVpFX1NNQUxMLCBGQUxTRSwgaGVhcF8pOwogICAgICBRUlJhbmdlUHJlZFB0ciByYW5nZVByZWQgPSByZXdyaXRlLT5nZXRRdWVyeUVsZW1lbnQoKS0+ZG93bkNhc3RUb1FSUmFuZ2VQcmVkKCk7CiAgICAgIFFSRXhwclB0ciByYW5nZUV4cHIgPSByYW5nZVByZWQtPmdldFJhbmdlSXRlbSgpLT5kb3duQ2FzdFRvUVJFeHByKCk7CiAgICAgIFFSRXhwbGljaXRFeHByUHRyIEV4cHJSb290ID0gcmFuZ2VFeHByLT5nZXRFeHByUm9vdCgpLT5kZWVwQ29weUFuZFN3aXRjaChzdWJFeHBySGFzaCwgaGVhcF8pOwogICAgICBRUkV4cHJQdHIgcmVzdWx0RXhwciA9IG5ldyhoZWFwXykgUVJFeHByKEZBTFNFLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogICAgICByZXN1bHRFeHByLT5zZXRSZWYocmFuZ2VFeHByLT5nZXRJRCgpKTsKICAgICAgcmVzdWx0RXhwci0+c2V0RXhwclJvb3QoRXhwclJvb3QpOwoKICAgICAgcmFuZ2VJdGVtID0gcmVzdWx0RXhwcjsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgaWYgKHN1YkVsZW1lbnRzLT5wcm92aWRlZElucHV0c18uZW50cmllcygpID09IDEpCiAgICAgIHsKCVFSTVZDb2x1bW5QdHIgbXZDb2x1bW4gPSBnZW5lcmF0ZVByb3ZpZGVkTXZDb2x1bW4oc3ViRWxlbWVudHMtPnByb3ZpZGVkSW5wdXRzX1swXSk7CglyYW5nZUl0ZW0gPSBtdkNvbHVtbjsKICAgICAgfQogICAgICBlbHNlIGlmIChzdWJFbGVtZW50cy0+bm90UHJvdmlkZWRJbnB1dHNfLmVudHJpZXMoKSA9PSAxKQogICAgICB7CglRUkNvbHVtblB0ciBiYWNrSm9pbkNvbHVtbiA9IGdlbmVyYXRlTm90UHJvdmlkZWRDb2x1bW4oc3ViRWxlbWVudHMtPm5vdFByb3ZpZGVkSW5wdXRzX1swXSk7CglyYW5nZUl0ZW0gPSBiYWNrSm9pbkNvbHVtbjsKICAgICAgfQogICAgICBlbHNlIGlmIChzdWJFbGVtZW50cy0+YmFja0pvaW5JbnB1dHNfLmVudHJpZXMoKSA9PSAxKQogICAgICB7CglRUkNvbHVtblB0ciBiYWNrSm9pbkNvbHVtbiA9IGdlbmVyYXRlTm90UHJvdmlkZWRDb2x1bW4oc3ViRWxlbWVudHMtPmJhY2tKb2luSW5wdXRzX1swXSk7CglyYW5nZUl0ZW0gPSBiYWNrSm9pbkNvbHVtbjsKICAgICAgfQogICAgICBlbHNlIGlmIChzdWJFbGVtZW50cy0+b3V0c2lkZUlucHV0c18uZW50cmllcygpID09IDEpCiAgICAgIHsKCVFSQ29sdW1uUHRyIG91dHNpZGVDb2x1bW4gPSBnZW5lcmF0ZU5vdFByb3ZpZGVkQ29sdW1uKHN1YkVsZW1lbnRzLT5vdXRzaWRlSW5wdXRzX1swXSk7CglyYW5nZUl0ZW0gPSBvdXRzaWRlQ29sdW1uOwogICAgICB9CgogICAgICBhc3NlcnRMb2dBbmRUaHJvdyhDQVRfTUFUQ0hUU1RfTVZERVRBSUxTLCBMTF9NVlFSX0ZBSUwsCgkJCXJhbmdlSXRlbSAhPSBOVUxMLCBRUkxvZ2ljRXhjZXB0aW9uLCAKCQkJIkV4cGVjdGluZyBlaXRoZXIgUHJvdmlkZWQsIE91dHNpZGUgb3IgQmFja0pvaW4gaW5wdXRzLiIpOwogICAgfQogIH0KCiAgLy8gQWRkIGl0IHRvIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICByYW5nZUVsZW1lbnQtPnNldFJhbmdlSXRlbShyYW5nZUl0ZW0pOwogIHJlc3VsdERlc2MtPmdldFJhbmdlUHJlZExpc3QoKS0+YWRkSXRlbShyYW5nZUVsZW1lbnQpOwogIHJldHVybiBUUlVFOwp9ICAvLyBNYXRjaFJhbmdlUHJlZGljYXRlczo6Z2VuZXJhdGVOb3RQcm92aWRlZEVsZW1lbnQoKQoKLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gVXNlZCBieSB3b3JrbG9hZCBhbmFseXNpcy4KLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKUVJSYW5nZVByZWRQdHIgTWF0Y2hSYW5nZVByZWRpY2F0ZXM6OmNoZWNrUHJlZGljYXRlKFFSUmFuZ2VQcmVkUHRyIHF1ZXJ5U2lkZVByZWQpCnsKICBRUlJhbmdlUHJlZFB0ciBtdlJhbmdlUHJlZCA9IE5VTEw7CiAgUVJFbGVtZW50UHRyIHJhbmdlSXRlbSA9IHF1ZXJ5U2lkZVByZWQtPmdldFJhbmdlSXRlbSgpLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpOwogIEVsZW1lbnRUeXBlIHJhbmdlRWxlbVR5cGUgPSByYW5nZUl0ZW0tPmdldEVsZW1lbnRUeXBlKCk7CiAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgICggcmFuZ2VFbGVtVHlwZSA9PSBFVF9Db2x1bW4gICB8fCAKCQkgICAgICByYW5nZUVsZW1UeXBlID09IEVUX0pvaW5QcmVkIHx8IAoJCSAgICAgIHJhbmdlRWxlbVR5cGUgPT0gRVRfRXhwciAgICAgICApLCAKCQkgICAgUVJMb2dpY0V4Y2VwdGlvbiwgCgkJICAgICJFeHBlY3RpbmcgcmFuZ2UgaXRlbXMgdG8gYmUgY29sdW1ucywgZXF1YWxpdHkgc2V0cyBvciBleHByZXNzaW9ucy4iKTsKCiAgaWYgKHJhbmdlRWxlbVR5cGUgPT0gRVRfRXhwcikKICB7CiAgICAvLyBGaW5kIGFsbCB0aGUgTVYgcmFuZ2UgcHJlZHMgdXNpbmcgdGhlIHNhbWUgZXhwcmVzc2lvbiB0ZXh0CiAgICBjb25zdCBRUkV4cHJQdHIgcXVlcnlSYW5nZUV4cHIgPSByYW5nZUl0ZW0tPmRvd25DYXN0VG9RUkV4cHIoKTsKICAgIGNvbnN0IE5BU3RyaW5nJiBwcmVkVGV4dCA9IHF1ZXJ5UmFuZ2VFeHByLT5nZXRFeHByVGV4dCgpOwogICAgUmFuZ2VQcmVkUHRyTGlzdCogbXZQcmVkc09uRXhwciA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpLT5nZXRKYmJEZXRhaWxzKCktPmdldFJhbmdlUHJlZHNPbkV4cHJlc3Npb24ocHJlZFRleHQpOwogICAgaWYgKG12UHJlZHNPbkV4cHIgPT0gTlVMTCkKICAgICAgcmV0dXJuIE5VTEw7CiAgICAKICAgIC8vIEJvdGggTVYgYW5kIHF1ZXJ5IGhhdmUgYSByYW5nZSBwcmVkIHVzaW5nIHRoaXMgdGV4dC4gTm93IG1hdGNoIHRoZSBpbnB1dCBjb2x1bW5zLgogICAgY29uc3QgRWxlbWVudFB0ckxpc3QmIHF1ZXJ5SW5wdXRDb2x1bW5zID0gcXVlcnlSYW5nZUV4cHItPmdldElucHV0Q29sdW1ucyhoZWFwXyk7CiAgICBOQUJvb2xlYW4gZm91bmRNYXRjaCA9IEZBTFNFOwogICAgZm9yIChDb2xsSW5kZXggaiA9IDA7IGo8bXZQcmVkc09uRXhwci0+ZW50cmllcygpOyBqKyspCiAgICB7CiAgICAgIG12UmFuZ2VQcmVkID0gKCptdlByZWRzT25FeHByKVtqXTsKICAgICAgY29uc3QgUVJFeHByUHRyIG12UmFuZ2VFeHByID0gbXZSYW5nZVByZWQtPmdldFJhbmdlSXRlbSgpLT5kb3duQ2FzdFRvUVJFeHByKCk7CiAgICAgIGlmIChtYXRjaEV4cHJlc3Npb25JbnB1dHMocXVlcnlJbnB1dENvbHVtbnMsIG12UmFuZ2VFeHByLT5nZXRJbnB1dENvbHVtbnMoaGVhcF8pKSkKICAgICAgewogICAgICAgIGZvdW5kTWF0Y2ggPSBUUlVFOwogICAgICAgIGJyZWFrOyAgLy8gRm91bmQgYSBtYXRjaAogICAgICB9CiAgICB9CgogICAgLy8gRGlkIG5vdCBmaW5kIGEgbWF0Y2hpbmcgcmFuZ2UgcHJlZCBvbiB0aGUgc2FtZSBleHByZXNzaW9uIHRleHQgYW5kIGlucHV0IGNvbHVtbnMuCiAgICBpZiAoIWZvdW5kTWF0Y2gpCiAgICAgIHJldHVybiBOVUxMOwogIH0KICBlbHNlIAogIHsKICAgIC8vIElmIGl0cyBhIGpvaW4gcHJlZCwgZ2V0IHRoZSBmaXJzdCBjb2x1bW4uCiAgICBRUkNvbHVtblB0ciByYW5nZUNvbHVtbiA9IHJhbmdlSXRlbS0+Z2V0Rmlyc3RDb2x1bW4oKTsKCiAgICAvLyBGaW5kIHRoZSBjb3JyZXNwb25kaW5nIE1WIHJhbmdlIHByZWRpY2F0ZSAoaWYgYW55KS4KICAgIGlmIChjYW5kaWRhdGVfLT5nZXRNdkRldGFpbHMoKS0+Z2V0SmJiRGV0YWlscygpLT5oYXNOb1JhbmdlUHJlZGljYXRlcygpID09IEZBTFNFKQogICAgewogICAgICAvLyBGaW5kIHRoZSBjb3JyZXNwb25kaW5nIE1WIHRhYmxlIChpZiBhbnkpCiAgICAgIEJhc2VUYWJsZURldGFpbHNQdHIgYmFzZVRhYmxlID0gY2FuZGlkYXRlXy0+Z2V0TXZUYWJsZUZvclF1ZXJ5SUQocmFuZ2VDb2x1bW4tPmdldFRhYmxlSUQoKSwgRkFMU0UpOwogICAgICBpZiAoYmFzZVRhYmxlKQogICAgICB7CiAgICAgICAgLy8gR2V0IHRoZSBNViByYW5nZSBwcmVkIG9uIHRoaXMgY29sdW1uLgogICAgICAgIG12UmFuZ2VQcmVkID0gYmFzZVRhYmxlLT5nZXRSYW5nZUNvbHVtblByZWRpY2F0ZXNGb3IocmFuZ2VDb2x1bW4tPmdldENvbEluZGV4KCkpOwogICAgICB9CiAgICB9CiAgfSAvLyBpZiBub3QgZXhwcmVlc2lvbi4KCiAgLy8gSXMgdGhlcmUgYSBtYXRjaGluZyByYW5nZSBwcmVkaWNhdGUgb24gdGhlIHNhbWUgY29sdW1uPwogIGlmIChtdlJhbmdlUHJlZCA9PSBOVUxMKQogICAgcmV0dXJuIE5VTEw7CgogIC8vIE9LLCB3ZSBnZXQgaGVyZSB3aGVuIHdlIGZvdW5kIGFuIE1WIHNpZGUgcmFuZ2UgcHJlZGljYXRlIHdpdGggYSBtYXRjaGluZyAKICAvLyByYW5nZSBpdGVtIChjb2x1bW4gb3IgZXhwcmVzc2lvbikuCiAgLy8gTm93IHdlIG5lZWQgdG8gbWF0Y2ggdGhlIHJhbmdlIHNwZWMuCiAgLy8gRm9yIG5vdywgd2Ugb25seSBjaGVjayBmb3IgYW4gZXhhY3QgbWF0Y2guCiAgY29uc3QgUmFuZ2VTcGVjKiBtdlJhbmdlU3BlYyA9IG12UmFuZ2VQcmVkLT5nZXRSYW5nZVNwZWMoaGVhcF8pOwogIGNvbnN0IFJhbmdlU3BlYyogcXVlcnlSYW5nZVNwZWMgPSBxdWVyeVNpZGVQcmVkLT5nZXRSYW5nZVNwZWMoaGVhcF8pOwogIGlmIChxdWVyeVJhbmdlU3BlYy0+aXNFcXVhbCgqbXZSYW5nZVNwZWMpKQogICAgcmV0dXJuIG12UmFuZ2VQcmVkOwogIGVsc2UKICAgIHJldHVybiBOVUxMOwp9CgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyAgQ2xhc3MgTWF0Y2hSZXNpZHVhbFByZWRpY2F0ZXMKLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCi8vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIFJ1biB0aGUgUGFzcyAxIGFsZ29yaXRobSBvZiByZXNpZHVhbCBwcmVkaWNhdGUgdGVzdC4KLy8gVGhlIGJpdG1hcCB0ZXN0IHdhcyBhbHJlYWR5IGRvbmUgYnkgdGhlIHJhbmdlIHByZWRpY2F0ZSBjb2RlLCBzbyBub3cgCi8vIGNoZWNrIHRoZSBwcmVkaWNhdGVzIG9uZSBieSBvbmUuCi8vIEZvciBlYWNoIHF1ZXJ5IHJlc2lkdWFsIHByZWRpY2F0ZQovLyAgIFVzaW5nIHRoZSBwcmVkaWNhdGUgdGV4dCwgZmluZCBhbnkgY29ycmVzcG9uZGluZyBNViBwcmVkaWNhdGVzLgovLyAgIE1hdGNoIHRoZSBpbnB1dCBjb2x1bW5zIG9mIHRob3NlIHByZWRpY2F0ZXMuCi8vICAgSWYgYSBtYXRjaGluZyBNViBwcmVkaWNhdGUgd2FzIGZvdW5kCi8vICAgICBJdHMgYSBmaW5hbCBQcm92aWRlZC4KLy8gICBPdGhlcndpc2UKLy8gICAgIENoZWNrIGlmIHRoZSBwcmVkaWNhdGUgaW5wdXQgY29sdW1ucyBhcmUgcHJvdmlkZWQgYnkgdGhlIE1WLgovLyAgICAgSWYgdGhleSBhcmUgYmxvY2tlZAovLyAgICAgICBEaXNxdWFsaWZ5IHRoZSBNVi4KLy8gICAgIElmIHRoZSBhcmUgYWxsIFByb3ZpZGVkCi8vICAgICAgIFRoZSBwcmVkaWNhdGUgaXMgYSBmaW5hbCBOb3RQcm92aWRlZC4KLy8gICAgIE90aGVyd2lzZQovLyAgICAgICBUaGUgcHJlZGljYXRlIGlzIGFuIGludGVybWVkaWF0ZSBOb3RQcm92aWRlZCwgcG9zdHBvbmUgdG8gUGFzcyAyLgovLyAgICAgICAKLy8gUmV0dXJucyBUUlVFIGlmIHRoZSBNViBwYXNzZWQgdGhpcyB0ZXN0LCBGQUxTRSBpZiBpdCB3YXMgZGlzcXVhbGlmaWVkLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoUmVzaWR1YWxQcmVkaWNhdGVzOjptYXRjaFBhc3MxKCkKewogIGNvbnN0IEpCQkRldGFpbHNQdHIgbXZKYmJEZXRhaWxzID0gY2FuZGlkYXRlXy0+Z2V0TXZEZXRhaWxzKCktPmdldEpiYkRldGFpbHMoKTsKCiAgY29uc3QgUVJSZXNpZHVhbFByZWRMaXN0UHRyICBxdWVyeVJlc2lkdWFsUHJlZExpc3QgPSAKICAgIGNhbmRpZGF0ZV8tPmdldFF1ZXJ5SmJiKCktPmdldEh1YigpLT5nZXRSZXNpZHVhbFByZWRMaXN0KCk7CiAgaWYgKHF1ZXJ5UmVzaWR1YWxQcmVkTGlzdD09TlVMTCB8fCBxdWVyeVJlc2lkdWFsUHJlZExpc3QtPmdldExpc3QoKS5pc0VtcHR5KCkpCiAgewogICAgaWYgKCFtdkpiYkRldGFpbHMtPmhhc05vUmVzaWR1YWxQcmVkaWNhdGVzKCkpCiAgICB7CiAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkKCJpdCBoYXMgcmVzaWR1YWwgcHJlZGljYXRlcyBhbmQgdGhlIFF1ZXJ5IGRvZXMgbm90LiIpOwogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIC8vIE5vIHJlc2lkdWFsIHByZWRpY2F0ZXMgaW4gYm90aCB0aGUgTVYgYW5kIHRoZSBxdWVyeS4gCiAgICAgIC8vIE5vdGhpbmcgdG8gZG8uCiAgICAgIHJldHVybiBUUlVFOwogICAgfQogIH0KCiAgUmVzaWR1YWxQcmVkUHRyTGlzdCB1c2VkRHVwbGljYXRlczsKICBjb25zdCBSZXNpZHVhbFByZWRQdHJMaXN0JiAgcXVlcnlSZXNpZHVhbFByZWRzID0gcXVlcnlSZXNpZHVhbFByZWRMaXN0LT5nZXRMaXN0KCk7CiAgLy8gQ29weSB0aGUgbGlzdCBvZiBNViByZXNpZHVhbCBwcmVkaWNhdGVzLgogIC8vIEFueSBtYXRjaGVkIHByZWRpY2F0ZSB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGlzIGxpc3QsIHNvIHdlIGNhbiBjaGVjawogIC8vIHRoYXQgbm8gTVYgcHJlZHMgd2VyZSBsZWZ0IG91dC4KICBpZiAoIW12SmJiRGV0YWlscy0+aGFzTm9SZXNpZHVhbFByZWRpY2F0ZXMoKSkKICAgIG12RnVsbFByZWRMaXN0Xy5pbnNlcnQobXZKYmJEZXRhaWxzLT5nZXRKYmJEZXNjcmlwdG9yKCktPmdldEh1YigpLT5nZXRSZXNpZHVhbFByZWRMaXN0KCktPmdldExpc3QoKSk7CgogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxxdWVyeVJlc2lkdWFsUHJlZHMuZW50cmllcygpOyBpKyspCiAgewogICAgY29uc3QgUVJFeHByUHRyIHF1ZXJ5UmVzaWR1YWxQcmVkID0gcXVlcnlSZXNpZHVhbFByZWRzW2ldOwogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IG1hdGNoUmVzaWR1YWxQcmVkaWNhdGUocXVlcnlSZXNpZHVhbFByZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VkRHVwbGljYXRlcyk7CiAgICBpZiAocmV3cml0ZSA9PSBOVUxMKQogICAgewogICAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIlF1ZXJ5IHJlc2lkdWFsIHByZWRpY2F0ZSAlcyB3YXMgbm90IG1hdGNoZWQgYnkgdGhlIHF1ZXJ5LiIsIAoJCQkJCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5UmVzaWR1YWxQcmVkLT5nZXRJRCgpKTsKICAgICAgcmV0dXJuIEZBTFNFOyAgLy8gTm8gbWF0Y2ggZm91bmQgZm9yIHRoaXMgcmVzaWR1YWwgcHJlZC4gRGlzcXVhbGlmeSB0aGUgTVYgY2FuZGlkYXRlLgogICAgfQogICAgZWxzZQogICAgewogICAgICBpZiAocmV3cml0ZS0+Z2V0UmVzdWx0Q29kZSgpID09IFJDX1NLSVBfTUUpCglkZWxldGVQdHIocmV3cml0ZSk7CiAgICAgIGVsc2UKICAgICAgICBhZGRSZXdyaXRlSW5zdHJ1Y3Rpb25zKHJld3JpdGUpOyAgLy8gV2UgZm91bmQgYSBtYXRjaCwgc2F2ZSB0aGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMuCiAgICB9CgogIH0gLy8gZm9yCgogIGlmIChtdkZ1bGxQcmVkTGlzdF8uZW50cmllcygpID4gMCkKICB7CiAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIk1WIHJlc2lkdWFsIHByZWRpY2F0ZSAlcyB3YXMgbm90IG1hdGNoZWQgYnkgdGhlIHF1ZXJ5LiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG12RnVsbFByZWRMaXN0X1swXS0+Z2V0SUQoKSk7CiAgICByZXR1cm4gRkFMU0U7CiAgfQoKICByZXR1cm4gVFJVRTsKfSAgLy8gTWF0Y2hSZXNpZHVhbFByZWRpY2F0ZXM6Om1hdGNoUGFzczEoKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBNYXRjaFJlc2lkdWFsUHJlZGljYXRlczo6bWF0Y2hSZXNpZHVhbFByZWRpY2F0ZShjb25zdCBRUkV4cHJQdHIgcXVlcnlSZXNpZHVhbFByZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlc2lkdWFsUHJlZFB0ckxpc3QmIHVzZWREdXBNdlByZWRzKQp7CiAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IE5VTEw7CiAgTkFCb29sZWFuIGlzQWdncmVnYXRlRXhwciA9IHF1ZXJ5UmVzaWR1YWxQcmVkLT5nZXRFeHByUm9vdCgpLT5jb250YWluc0FuQWdncmVnYXRlKCk7CgogIC8vIElmIHRoaXMgaXMgYW4gYWdncmVnYXRlIGV4cHJlc3Npb24gaW4gYSByb2xsdXAgcXVlcnkKICAvLyBkb24ndCBib3RoZXIgbWF0Y2hpbmcgdGhlIGV4cHJlc3Npb24gdGV4dC4KICAvLyBHbyBzdHJhaWdodCB0byBQYXNzIDIuCiAgaWYgKGNhbmRpZGF0ZV8tPmdldEFnZ3JlZ2F0ZU1hdGNoaW5nVHlwZSgpID09IEFNVF9NQVZfQVFfREcgICYmCiAgICAgIGlzQWdncmVnYXRlRXhwciApCiAgewogICAgLy8gVGhpcyBpcyBhbiBhZ2dyZWdhdGUgcXVlcnkgaW4gYSByb2xsdXAgcXVlcnkuLAogICAgLy8gVHJ5IHRvIG1hdGNoIGFnZ3JlZ2F0ZSBmdW5jdGlvbnMsIGluIFBhc3MgMi4KICAgIHJld3JpdGUgPSBuZXcoaGVhcF8pIAogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShxdWVyeVJlc2lkdWFsUHJlZCwgTlVMTCwgUkNfTk9UUFJPVklERUQsIFJTX0lOVEVSTUVESUFURSwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICB9CiAgICAKICBjb25zdCBOQVN0cmluZyYgcHJlZFRleHQgPSBxdWVyeVJlc2lkdWFsUHJlZC0+Z2V0RXhwclRleHQoKTsKICAvLyBHZXQgdGhlIGxpc3Qgb2YgTVYgcmVzaWR1YWwgcHJlZGljYXRlcyB1c2luZyB0aGUgc2FtZSBleHByZXNzaW9uIHRleHQuCiAgUmVzaWR1YWxQcmVkUHRyTGlzdCogbXZQcmVkTGlzdCA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpLT5nZXRKYmJEZXRhaWxzKCktPmdldFJlc2lkdWFsUHJlZHMocHJlZFRleHQpOwoKICBpZiAobXZQcmVkTGlzdCAhPSBOVUxMKQogIHsKICAgIENvbGxJbmRleCBtdlByZWRDb3VudCA9IG12UHJlZExpc3QtPmVudHJpZXMoKTsKCiAgICAvLyBCb3RoIE1WIGFuZCBxdWVyeSBoYXZlIGEgcmVzaWR1YWwgcHJlZCB1c2luZyB0aGlzIHRleHQuIE5vdyBtYXRjaCB0aGUgaW5wdXQgY29sdW1ucy4KICAgIGZvciAoQ29sbEluZGV4IGogPSAwOyBqPG12UHJlZExpc3QtPmVudHJpZXMoKTsgaisrKQogICAgewogICAgICBRUkV4cHJQdHIgbXZSZXNpZHVhbFByZWQgPSAoKm12UHJlZExpc3QpW2pdOwogICAgICBpZiAobWF0Y2hFeHByZXNzaW9uSW5wdXRzKHF1ZXJ5UmVzaWR1YWxQcmVkLT5nZXRJbnB1dENvbHVtbnMoaGVhcF8pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdlJlc2lkdWFsUHJlZC0+Z2V0SW5wdXRDb2x1bW5zKGhlYXBfKSkgPT0gRkFMU0UpCiAgICAgICAgY29udGludWU7IC8vIFRyeSBuZXh0IE1WIHJlc2lkdWFsIHByZWQgd2l0aCBzYW1lIHRleHQgYnV0IGRpZmZlcmVudCBpbnB1dCBjb2x1bW5zLgogICAgICBlbHNlCiAgICAgIHsKICAgICAgICAvLyBBIHJlc2lkdWFsIHByZWQgb24gYSBqb2luIG9wZXJhbmQgd2lsbCBhcHBlYXIgaW4gZWFjaCBub2RlIG9mIGFuCiAgICAgICAgLy8gZXF1YWxpdHkgc2V0LiBJbiBzb21lIGNhc2VzLCB0aGlzIHByZWQgd2lsbCBiZSBkdXBsaWNhdGVkIHdpdGggYQogICAgICAgIC8vIGRpZmZlcmVudCB2YWx1ZSBpZCwgYW5kIHdlIG11c3QgYXZvaWQgbWF0Y2hpbmcgdGhlIHNhbWUgKHdpdGggcmVzcGVjdAogICAgICAgIC8vIHRvIHRleHQpIG12IHByZWQgdG8gdHdvIGRpc3RpbmN0IChidXQgYWxzbyB3aXRoIHNhbWUgdGV4dCkgcXVlcnkKICAgICAgICAvLyByZXNpZCBwcmVkcywgb3IgZWxzZSBvbmUgd2lsbCBiZSBsZWZ0IHVubWF0Y2hlZCBpbiBtdkZ1bGxQcmVkTGlzdF8KICAgICAgICAvLyBhbmQgcmVzdWx0IGluIGEgc3B1cmlvdXMgZGlzcXVhbGlmaWNhdGlvbiBmb3IgYW4gdW5tYXRjaGVkIHByZWQuCiAgICAgICAgaWYgKG12UHJlZENvdW50ID4gMSkgIC8vIE9ubHkgYW4gaXNzdWUgd2hlbiB0ZXh0IG1hdGNoZXMgbXVsdGlwbGUgcHJlZHMKICAgICAgICB7CiAgICAgICAgICBpZiAodXNlZER1cE12UHJlZHMuY29udGFpbnMobXZSZXNpZHVhbFByZWQpKQogICAgICAgICAgICAvLyBhbHJlYWR5IG1hdGNoZWQgdGhpcyBvbmUsIHRyeSBhbm90aGVyCiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgZWxzZQogICAgICAgICAgICAvLyBtYWtlIHN1cmUgd2UgZG9uJ3QgbWF0Y2ggdGhpcyBvbmUgYWdhaW4KICAgICAgICAgICAgdXNlZER1cE12UHJlZHMuaW5zZXJ0KG12UmVzaWR1YWxQcmVkKTsKICAgICAgICB9CiAgICAgICAgbXZGdWxsUHJlZExpc3RfLnJlbW92ZShtdlJlc2lkdWFsUHJlZCk7CSAKICAgICAgICByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKHF1ZXJ5UmVzaWR1YWxQcmVkLCBtdlJlc2lkdWFsUHJlZCwgUkNfUFJPVklERUQsIFJTX0ZJTkFMLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwogICAgICAgIGJyZWFrOyAvLyBXZSBmb3VuZCBhIG1hdGNoLCB3ZSBjYW4gc3RvcCBsb29raW5nLgogICAgICB9CiAgICB9CiAgfQoKICBpZiAocmV3cml0ZSA9PSBOVUxMKQogIHsKICAgIC8vIFRoZSBNViBoYXMgbm8gcmVzaWR1YWwgcHJlZGljYXRlIHVzaW5nIHRoaXMgdGV4dCwgc28gd2UgbmVlZCB0byBwcm92aWRlIHJld3JpdGUgaW5zdHJ1Y3Rpb25zLgogICAgLy8gV2UgbmVlZCB0byB2ZXJpZnkgdGhhdCB0aGUgcHJlZCBpbnB1dCBjb2x1bW5zIGFyZSBhdmFpbGFibGUgYXMgYW4gTVYgb3V0cHV0LgoKICAgIGlmICggY2FuZGlkYXRlXy0+Z2V0QWdncmVnYXRlTWF0Y2hpbmdUeXBlKCkgPT0gQU1UX01BVl9BUV9NRyAmJgogICAgICAgICBpc0FnZ3JlZ2F0ZUV4cHIgKQogICAgewogICAgICAvLyBUaGlzIGlzIGFuIGFnZ3JlZ2F0ZSBxdWVyeSBvbiBhIG1hdGNoaW5nIE1BViwKICAgICAgLy8gVHJ5IHRvIG1hdGNoIGFnZ3JlZ2F0ZSBmdW5jdGlvbnMsIGluIFBhc3MgMi4KICAgICAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0ocXVlcnlSZXNpZHVhbFByZWQsIE5VTEwsIFJDX05PVFBST1ZJREVELCBSU19JTlRFUk1FRElBVEUsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIC8vIFRoaXMgaXMgb24gYW4gTUpWLiBUcnkgdG8gZmluZCB0aGUgaW5wdXQgY29sdW1ucy4KICAgICAgY29uc3QgRWxlbWVudFB0ckxpc3QmIHF1ZXJ5SW5wdXRFbGVtZW50cyA9IAogICAgICAgIHF1ZXJ5UmVzaWR1YWxQcmVkLT5nZXRJbnB1dENvbHVtbnMoaGVhcF8pOwoKICAgICAgaWYgKHF1ZXJ5SW5wdXRFbGVtZW50cy5lbnRyaWVzKCkgPiAwKQogICAgICB7CiAgICAgICAgcmV3cml0ZSA9IGZpbmRFeHByZXNzaW9uSW5wdXRzKHF1ZXJ5SW5wdXRFbGVtZW50cywgcXVlcnlSZXNpZHVhbFByZWQpOwoJaWYgKHJld3JpdGUgJiYKCSAgICByZXdyaXRlLT5pc0ZpbmFsKCkgJiYKCSAgICByZXdyaXRlLT5nZXRTZWNvbmRhcnlSZXN1bHRDb2RlKCkgPT0gUkNfSU5QVVRTX1BST1ZJREVEICYmCgkgICAgaXNBZ2dyZWdhdGVFeHByKQoJewoJICAvLyBBIEhBVklORyBwcmVkaWNhdGUgb24gYW4gTUpWCgkgIC8vIEFkZCB0aGUgZXhwcmVzc2lvbiBpbnB1dHMgdG8gdGhlIG91dHB1dCBsaXN0LgoJICBhZGRJbnB1dHNUb091dHB1dExpc3QocmV3cml0ZSk7CgkgIC8vIFRoZSByZXNpZHVhbCBwcmVkaWNhdGUgaXRzZWxmIHdpbGwgYmUgaWdub3JlZAoJICByZXR1cm4gcmV3cml0ZTsKCX0KICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKICAgICAgICAvLyBUaGlzIHByZWRpY2F0ZSBoYXMgbm8gaW5wdXRzLgogICAgICAgIC8vIE1hcmsgaXQgYXMgTm90UHJvdmlkZWQuCiAgICAgICAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbShxdWVyeVJlc2lkdWFsUHJlZCwgTlVMTCwgUkNfTk9UUFJPVklERUQsIFJTX0ZJTkFMLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwoJcmV3cml0ZS0+c2V0U2Vjb25kYXJ5UmVzdWx0Q29kZShSQ19OT19JTlBVVFMpOwogICAgICB9CiAgICB9CiAgfQoKICByZXR1cm4gcmV3cml0ZTsKfSAgLy8gTWF0Y2hSZXNpZHVhbFByZWRpY2F0ZXM6Om1hdGNoUmVzaWR1YWxQcmVkaWNhdGUoKQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIFJ1biB0aGUgUGFzcyAyIGFsZ29yaXRobSBvZiByZXNpZHVhbCBwcmVkaWNhdGUgdGVzdC4KLy8gUmV0dXJucyBUUlVFIGlmIHRoZSBNViBwYXNzZWQgdGhpcyB0ZXN0LCBGQUxTRSBpZiBpdCB3YXMgZGlzcXVhbGlmaWVkLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoUmVzaWR1YWxQcmVkaWNhdGVzOjptYXRjaFBhc3MyT25FbGVtZW50KFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHBlbmRpbmcpCnsKICBpZiAocGVuZGluZy0+Z2V0UmVzdWx0Q29kZSgpID09IFJDX05PVFBST1ZJREVEKQogIHsKICAgIC8vIFRoZSByZXNpZHVhbCBleHByZXNzaW9uIG1heSBiZSBhIEhBVklORyBwcmVkaWNhdGUuCiAgICBRUkV4cHJQdHIgcmVzaWRFeHByID0gcGVuZGluZy0+Z2V0UXVlcnlFbGVtZW50KCktPmRvd25DYXN0VG9RUkV4cHIoKTsKICAgIFFSRXhwbGljaXRFeHByUHRyIHRyZWVFeHByID0gcmVzaWRFeHByLT5nZXRFeHByUm9vdCgpOwoKICAgIC8vIFVzZSBhIHZpc2l0b3IgdG8gZmluZCBhZ2dyZWdhdGUgZnVuY3Rpb25zLCBhbmQgc29sdmUgYW55IHRoYXQgYXJlIGZvdW5kLgogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IGZpbmRJbnRlcm5hbEFnZ3JlZ2F0ZUZ1bmN0aW9ucyh0cmVlRXhwcik7CgogICAgaWYgKHJld3JpdGUgPT0gTlVMTCkKICAgIHsKICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJSZXNpZHVhbCBleHByZXNzaW9uICVzIGlzIG5vdCBQcm92aWRlZCBieSB0aGUgTVYuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2lkRXhwci0+Z2V0SUQoKS5kYXRhKCkpOwogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CgogICAgcmV3cml0ZS0+c2V0UXVlcnlFbGVtZW50KHJlc2lkRXhwcik7CiAgICBhZGRSZXdyaXRlSW5zdHJ1Y3Rpb25zKHJld3JpdGUpOwoKICAgIGRlbGV0ZVB0cihwZW5kaW5nKTsKICAgIHJldHVybiBUUlVFOwogIH0KICBlbHNlCiAgewogICAgY29uc3QgY2hhciogcmVhc29uID0gcGVuZGluZy0+Z2V0UmVzdWx0U3RyaW5nKCk7CiAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIlJlc2lkdWFsIHByZWRzIGdvdCB0byBQYXNzIDIgb24gJXMuIiwgcmVhc29uKTsKCiAgICByZXR1cm4gRkFMU0U7CiAgfQp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gQ3JlYXRlIGEgbmV3IHJlc2lkdWFsIHByZWQgZWxlbWVudCAoPEV4cHI+KSBmb3IgdGhlIHJlc3VsdCBkZXNjcmlwdG9yLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKUVJFeHByUHRyIE1hdGNoUmVzaWR1YWxQcmVkaWNhdGVzOjpjcmVhdGVOZXdSZXN1bHRFbGVtZW50KFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHJld3JpdGUpCnsKICAvLyBDb25zdHJ1Y3QgdGhlIG5ldyBlbGVtZW50CiAgUVJFeHByUHRyIHJlc2lkdWFsRWxlbWVudCA9IG5ldyhoZWFwXykgUVJFeHByKFRSVUUsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgLy8gU2V0IHRoZSByZXN1bHQgYXR0cmlidXRlLgogIHJlc2lkdWFsRWxlbWVudC0+c2V0UmVzdWx0KHJld3JpdGUtPmdldERlc2NyaXB0b3JSZXN1bHRDb2RlKCkpOwogIC8vIFNldCB0aGUgcmVmIGF0dHJpYnV0ZS4KICByZXNpZHVhbEVsZW1lbnQtPnNldFJlZihyZXdyaXRlLT5nZXRRdWVyeUVsZW1lbnQoKS0+Z2V0SUQoKSk7CgogIHJldHVybiByZXNpZHVhbEVsZW1lbnQ7Cn0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBBIFByb3ZpZGVkIHJlc2lkdWFsIHByZWRpY2F0ZSByZXF1aXJlcyBubyBhZGRpdGlvbmFsIHdvcmsuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hSZXNpZHVhbFByZWRpY2F0ZXM6OmdlbmVyYXRlUHJvdmlkZWRFbGVtZW50KFFSQ2FuZGlkYXRlUHRyIHJlc3VsdERlc2MsIAoJCQkJCQkJICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSkKewogIC8vIENyZWF0ZSB0aGUgbmV3IE91dHB1dCBlbGVtZW50LCBtYXJrIGl0IGFzIFByb3ZpZGVkLgogIFFSRXhwclB0ciByZXNpZHVhbEVsZW1lbnQgPSBjcmVhdGVOZXdSZXN1bHRFbGVtZW50KHJld3JpdGUpOwoKICAvLyBBZGQgaXQgdG8gdGhlIHJlc3VsdCBkZXNjcmlwdG9yLgogIHJlc3VsdERlc2MtPmdldFJlc2lkdWFsUHJlZExpc3QoKS0+YWRkSXRlbShyZXNpZHVhbEVsZW1lbnQpOwogIHJldHVybiBUUlVFOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gQSBOb3RQcm92aWRlZCByZXNpZHVhbCBwcmVkaWNhdGUgaW5jbHVkZXMgdGhlIGFjdHVhbCByZXNpZHVhbCBwcmVkaWNhdGUgCi8vIHdpdGggcmV3cml0ZSBpbnN0cnVjdGlvbnMgZm9yIHRoZSBpbnB1dCBjb2x1bW5zLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoUmVzaWR1YWxQcmVkaWNhdGVzOjpnZW5lcmF0ZU5vdFByb3ZpZGVkRWxlbWVudChRUkNhbmRpZGF0ZVB0ciByZXN1bHREZXNjLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlKQp7CiAgUVJFeHByUHRyIHJlc2lkdWFsRWxlbWVudCA9IE5VTEw7CgogIGlmIChyZXdyaXRlLT5nZXRTZWNvbmRhcnlSZXN1bHRDb2RlKCkgPT0gUkNfQUdHUl9FWFBSIHx8CiAgICAgIHJld3JpdGUtPmdldFNlY29uZGFyeVJlc3VsdENvZGUoKSA9PSBSQ19ST0xMVVBfRVhQUikKICB7CiAgICByZXNpZHVhbEVsZW1lbnQgPSBnZW5lcmF0ZUFnZ3JlZ2F0ZUV4cHJlc3Npb25PdXRwdXQocmV3cml0ZSk7CiAgICBpZiAocmVzaWR1YWxFbGVtZW50ID09IE5VTEwpCiAgICB7CiAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgiT3V0cHV0IGV4cHJlc3Npb24gJXMgY2Fubm90IGJlIFByb3ZpZGVkLiIsIAoJICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXdyaXRlLT5nZXRRdWVyeUVsZW1lbnQoKS0+Z2V0SUQoKS5kYXRhKCkpOwogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIHJlc2lkdWFsRWxlbWVudC0+c2V0UmVzaWR1YWwoVFJVRSk7CiAgICAgIC8vIFNldCB0aGUgcmVzdWx0IGF0dHJpYnV0ZS4KICAgICAgcmVzaWR1YWxFbGVtZW50LT5zZXRSZXN1bHQocmV3cml0ZS0+Z2V0RGVzY3JpcHRvclJlc3VsdENvZGUoKSk7CiAgICAgIC8vIFNldCB0aGUgcmVmIGF0dHJpYnV0ZS4KICAgICAgcmVzaWR1YWxFbGVtZW50LT5zZXRSZWYocmV3cml0ZS0+Z2V0UXVlcnlFbGVtZW50KCktPmdldElEKCkpOwogICAgfQogIH0KICBlbHNlIAogIHsKICAgIC8vIENyZWF0ZSB0aGUgbmV3IE5vdFByb3ZpZGVkIFJlc2lkdWFsIGVsZW1lbnQsIHJlZmVyZW5jaW5nIHRoZSBxdWVyeQogICAgLy8gcmVzaWR1YWwgcHJlZC4KICAgIHJlc2lkdWFsRWxlbWVudCA9IGNyZWF0ZU5ld1Jlc3VsdEVsZW1lbnQocmV3cml0ZSk7CgogICAgLy9HZXQgdGhlIHJld3JpdGUgaW5zdHJ1Y3Rpb25zIGZvciB0aGUgc3ViZXhwcmVzc2lvbnMuCiAgICBjb21wb3NpdGVNYXRjaGluZ1Jlc3VsdHNQdHIgc3ViRXhwcnMgPSByZXdyaXRlLT5nZXRTdWJFbGVtZW50cygpOwogICAgYXNzZXJ0TG9nQW5kVGhyb3coQ0FUX01BVENIVFNUX01WREVUQUlMUywgTExfTVZRUl9GQUlMLAogICAgICAgICAgICAgICAgICAgICAgc3ViRXhwcnMtPmVudHJpZXMoKSA9PSBzdWJFeHBycy0+cHJvdmlkZWRJbnB1dHNfLmVudHJpZXMoKSArIHN1YkV4cHJzLT5iYWNrSm9pbklucHV0c18uZW50cmllcygpLCAKICAgICAgICAgICAgICAgICAgICAgIFFSTG9naWNFeGNlcHRpb24sICJFeHBlY3RpbmcgYWxsIHN1YmV4cHJlc3Npb25zIHRvIGJlIFByb3ZpZGVkIG9yIGJhY2sgam9pbnMuIik7CgogICAgLy8gQ3JlYXRlIGEgaGFzaCB0YWJsZSB0byBtYXAgcXVlcnkgY29sdW1uIGlkcyB0byB0aGUgbXZjb2xzIHRoYXQgcmVwbGFjZSB0aGVtCiAgICAvLyBpbiB0aGUgZXhwcmVzc2lvbi4gIAogICAgc3ViRXhwcmVzc2lvblJld3JpdGVIYXNoIHN1YkV4cHJIYXNoKGhhc2hLZXksIElOSVRfSEFTSF9TSVpFX1NNQUxMLCBGQUxTRSwgaGVhcF8pOwogICAgCiAgICAvLyBGb3IgZWFjaCBzdWJFbGVtZW50LCBnZXQgdGhlIGlkIG9mIHRoZSBxdWVyeSBlbGVtZW50IGFuZCB0aGUgY29ycmVzcG9uZGluZwogICAgLy8gbXYgY29sdW1uLCBhbmQgcHV0IHRoZW0gaW4gdGhlIGhhc2ggdGFibGUuCiAgICAvLyBTdGFydCB3aXRoIFByb3ZpZGVkIGlucHV0cy4KICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtTGlzdCYgcmV3cml0ZUxpc3QgPSBzdWJFeHBycy0+cHJvdmlkZWRJbnB1dHNfOwogICAgZm9yIChDb2xsSW5kZXggaT0wOyBpPHJld3JpdGVMaXN0LmVudHJpZXMoKTsgaSsrKQogICAgewogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBzdWJFeHByUmV3cml0ZSA9IHJld3JpdGVMaXN0W2ldOwogICAgICBjb25zdCBOQVN0cmluZyYga2V5ID0gc3ViRXhwclJld3JpdGUtPmdldFF1ZXJ5RWxlbWVudCgpLT5nZXRJRCgpOwogICAgICBRUk1WQ29sdW1uUHRyIG12Q29sdW1uID0gZ2VuZXJhdGVQcm92aWRlZE12Q29sdW1uKHN1YkV4cHJSZXdyaXRlKTsKICAgICAgc3ViRXhwckhhc2guaW5zZXJ0KCZrZXksIG12Q29sdW1uKTsKICAgIH0KCiAgICAvLyBOb3cgZG8gYmFjayBqb2luIGNvbHVtbnMuCiAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbUxpc3QmIGJhY2tKb2luTGlzdCA9IHN1YkV4cHJzLT5iYWNrSm9pbklucHV0c187CiAgICBmb3IgKENvbGxJbmRleCBpPTA7IGk8YmFja0pvaW5MaXN0LmVudHJpZXMoKTsgaSsrKQogICAgewogICAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciBzdWJFeHByUmV3cml0ZSA9IGJhY2tKb2luTGlzdFtpXTsKICAgICAgY29uc3QgTkFTdHJpbmcmIGtleSA9IHN1YkV4cHJSZXdyaXRlLT5nZXRRdWVyeUVsZW1lbnQoKS0+Z2V0SUQoKTsKICAgICAgUVJDb2x1bW5QdHIgYmpDb2x1bW4gPSBnZW5lcmF0ZU5vdFByb3ZpZGVkQ29sdW1uKHN1YkV4cHJSZXdyaXRlKTsKICAgICAgc3ViRXhwckhhc2guaW5zZXJ0KCZrZXksIGJqQ29sdW1uKTsKICAgIH0KCiAgICAvLyBDcmVhdGUgdGhlIHJlc3VsdCBleHByZXNzaW9uIHRyZWUgZnJvbSB0aGUgcXVlcnkgZXhwcmVzc2lvbiB0cmVlLCB3aXRoIAogICAgLy8gdGhlIG5lZWRlZCBzdWItZXhwcmVzc2lvbnMgc3dpdGNoZWQgdG8gTVZDb2x1bW4gZWxlbWVudHMuCiAgICBRUkV4cHJQdHIgcXVlcnlFeHByID0gcmV3cml0ZS0+Z2V0QWN0dWFsUXVlcnlFbGVtZW50KCktPmRvd25DYXN0VG9RUkV4cHIoKTsKICAgIFFSRXhwbGljaXRFeHByUHRyIHJlc3VsdFRyZWVFeHByID0gTlVMTDsKCiAgICB0cnkKICAgIHsKICAgICAgcmVzdWx0VHJlZUV4cHIgPSBxdWVyeUV4cHItPmdldEV4cHJSb290KCktPmRlZXBDb3B5QW5kU3dpdGNoKHN1YkV4cHJIYXNoLCBoZWFwXyk7CiAgICB9CiAgICBjYXRjaChRUkRlc2NyaXB0b3JFeGNlcHRpb24gZXgpCiAgICB7CiAgICAgIC8vIFdlIGdldCBoZXJlIGlmIHdlIGNhbm5vdCBwcm9wZXJseSByZXdyaXRlIGFsbCB0aGUgcXVlcnkgY29sdW1uIGVsZW1lbnRzLgogICAgICAvLyBDdXJyZW50bHkgd2UgYXJlIGxlYWtpbmcgdGhlIG1lbW9yeSBvZiB0aGUgZWxlbWVudHMgc3RvcmVkIGluIHN1YkV4cHJIYXNoLgogICAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIlJlc2lkdWFsIHByZWRpY2F0ZSAlcyBjYW5ub3QgYmUgcmV3cml0dGVuLiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVlcnlFeHByLT5nZXRJRCgpLmRhdGEoKSk7CiAgICAgIHJldHVybiBOVUxMOwogICAgfQoKICAgIHJlc2lkdWFsRWxlbWVudC0+c2V0RXhwclJvb3QocmVzdWx0VHJlZUV4cHIpOwogIH0KCiAgLy8gQWRkIHRoZSByZXNpZHVhbCBwcmVkaWNhdGUgdG8gdGhlIHJlc3VsdCBkZXNjcmlwdG9yLgogIHJlc3VsdERlc2MtPmdldFJlc2lkdWFsUHJlZExpc3QoKS0+YWRkSXRlbShyZXNpZHVhbEVsZW1lbnQpOwogIHJldHVybiBUUlVFOwp9CgovLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBVc2VkIGJ5IHdvcmtsb2FkIGFuYWx5c2lzLgovLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpRUkV4cHJQdHIgTWF0Y2hSZXNpZHVhbFByZWRpY2F0ZXM6OmNoZWNrUHJlZGljYXRlKFFSRXhwclB0ciBxdWVyeVNpZGVQcmVkKQp7CiAgY29uc3QgTkFTdHJpbmcmIHByZWRUZXh0ID0gcXVlcnlTaWRlUHJlZC0+Z2V0RXhwclRleHQoKTsKICAvLyBHZXQgdGhlIGxpc3Qgb2YgTVYgcmVzaWR1YWwgcHJlZGljYXRlcyB1c2luZyB0aGUgc2FtZSBleHByZXNzaW9uIHRleHQuCiAgUmVzaWR1YWxQcmVkUHRyTGlzdCogbXZQcmVkTGlzdCA9IGNhbmRpZGF0ZV8tPmdldE12RGV0YWlscygpLT5nZXRKYmJEZXRhaWxzKCktPmdldFJlc2lkdWFsUHJlZHMocHJlZFRleHQpOwoKICBpZiAobXZQcmVkTGlzdCAhPSBOVUxMKQogIHsKICAgIENvbGxJbmRleCBtdlByZWRDb3VudCA9IG12UHJlZExpc3QtPmVudHJpZXMoKTsKCiAgICAvLyBCb3RoIE1WIGFuZCBxdWVyeSBoYXZlIGEgcmVzaWR1YWwgcHJlZCB1c2luZyB0aGlzIHRleHQuIE5vdyBtYXRjaCB0aGUgaW5wdXQgY29sdW1ucy4KICAgIGZvciAoQ29sbEluZGV4IGogPSAwOyBqPG12UHJlZExpc3QtPmVudHJpZXMoKTsgaisrKQogICAgewogICAgICBRUkV4cHJQdHIgbXZSZXNpZHVhbFByZWQgPSAoKm12UHJlZExpc3QpW2pdOwogICAgICBpZiAobWF0Y2hFeHByZXNzaW9uSW5wdXRzKHF1ZXJ5U2lkZVByZWQtPmdldElucHV0Q29sdW1ucyhoZWFwXyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG12UmVzaWR1YWxQcmVkLT5nZXRJbnB1dENvbHVtbnMoaGVhcF8pKSkKICAgICAgICByZXR1cm4gbXZSZXNpZHVhbFByZWQ7CiAgICB9CiAgfQoKICByZXR1cm4gTlVMTDsKfQoKLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gIENsYXNzIE1hdGNoR3JvdXBpbmdDb2x1bW5zCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hHcm91cGluZ0NvbHVtbnM6Om1hdGNoUGFzczEoKQp7CiAgUVJHcm91cEJ5UHRyIGdyb3VwQnkgPSBOVUxMOwoKICBpZiAoY2FuZGlkYXRlXy0+Z2V0SmJiU3Vic2V0KCktPmlzSW5kaXJlY3RHcm91cEJ5KCkpCiAgewogICAgaWYgKFZlcmlmeUdyb3VwaW5nQ29sdW1ucygpID09IEZBTFNFKQogICAgICByZXR1cm4gRkFMU0U7CiAgfQogIGVsc2UKICB7CiAgICBzd2l0Y2goY2FuZGlkYXRlXy0+Z2V0QWdncmVnYXRlTWF0Y2hpbmdUeXBlKCkpCiAgICB7CiAgICAgIGNhc2UgQU1UX01KVl9KUToKICAgICAgICAvLyBObyBHcm91cGJ5IGludm9sdmVkLgogICAgICAgIGJyZWFrOwoKICAgICAgY2FzZSBBTVRfTUpWX0FROgogICAgICAgIC8vIEFnZ3JlZ2F0ZSBxdWVyeSBvbiBNSlYuCiAgICAgICAgLy8gTm8gR1JPVVBCWSBlbGVtZW50IGlzIG5lZWRlZCBpbiB0aGUgcmVzdWx0IGRlc2NyaXB0b3IsCiAgICAgICAgLy8gYnV0IHdlIGRvIG5lZWQgdG8gYWRkIHJld3JpdGUgaW5zdHJ1Y3Rpb25zIGZvciB0aGUgZ3JvdXBpbmcgY29sdW1ucwogICAgICAgIC8vIHRvIHRoZSBvdXRwdXQgbGlzdC4KICAgICAgICAvLyBSZXR1cm4gd2l0aG91dCAgR3JvdXBCeSBlbGVtZW50IGluIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICAgICAgICByZXR1cm4gVmVyaWZ5R3JvdXBpbmdDb2x1bW5zKCk7CgogICAgICBjYXNlIEFNVF9NQVZfQVFfTUc6CiAgICAgICAgLy8gTm8gZXh0cmEgZ3JvdXBpbmcgaXMgbmVlZGVkIC0gdGhlIE1WIHByb3ZpZGVkIGl0IGFsbC4KICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgQU1UX01BVl9BUV9ERzoKICAgICAgICAvLyBUaGUgTVYgZGlkIG5vdCBwcm92aWRlIGFsbCB0aGUgZ3JvdXBpbmcgY29sdW1ucyAtIGhhbmRsZSB0aGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMuCiAgICAgICAgcmV0dXJuIFZlcmlmeUdyb3VwaW5nQ29sdW1ucygpOwogICAgfQogIH0KCiAgcmV0dXJuIFRSVUU7Cn0gIC8vIE1hdGNoR3JvdXBpbmdDb2x1bW5zOjptYXRjaFBhc3MxKCkKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KTkFCb29sZWFuIE1hdGNoR3JvdXBpbmdDb2x1bW5zOjpWZXJpZnlHcm91cGluZ0NvbHVtbnMoKQp7CiAgLy8gRG8gcHJpbWFyeSBncm91cGluZyBsaXN0IG9ubHksIGZvciBub3cuCiAgLy8gVE9ETzogU2hvdWxkIGRvIGdyb3VwaW5nIGNvbHVtbnMgZnJvbSBhbGwgdGhlIHRhYmxlcyBjb3ZlcmVkIGJ5IHRoZSBNVi4KICBRUkdyb3VwQnlQdHIgcXVlcnlHcm91cEJ5ID0gY2FuZGlkYXRlXy0+Z2V0UXVlcnlKYmIoKS0+Z2V0R3JvdXBCeSgpOwogIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwgCiAgICAgICAgICAgICAgICAgICAgcXVlcnlHcm91cEJ5ICE9IE5VTEwsIFFSTG9naWNFeGNlcHRpb24sIAoJCSAgICAiRXhwZWN0aW5nIGEgcXVlcnkgZ3JvdXBpbmcgbGlzdC4iKTsKCiAgLy8gQW4gZW1wdHkgR3JvdXBCeSBtZWFucyBpdHMgYW4gYWdncmVnYXRlIHF1ZXJ5IHdpdGggbm8gR1JPVVAgQlkuCiAgLy8gSXRzIE9LLCBhbmQgdGhlcmUgYXJlIG5vIGdyb3VwaW5nIGNvbHVtbnMgdG8gdmVyaWZ5LgogIGlmIChxdWVyeUdyb3VwQnktPmlzRW1wdHkoKSkKICAgIHJldHVybiBUUlVFOwoKICBjb25zdCBHcm91cGluZ0xpc3QmIGdyb3VwaW5nTGlzdCA9IHF1ZXJ5R3JvdXBCeS0+Z2V0UHJpbWFyeUxpc3QoKS0+Z2V0TGlzdCgpOwogIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAhZ3JvdXBpbmdMaXN0LmlzRW1wdHkoKSwgUVJMb2dpY0V4Y2VwdGlvbiwgCgkJICAgICJRdWVyeSBoYXMgR3JvdXAgQnksIGJ1dCBubyBncm91cGluZyBsaXN0LiIpOwoKICAvLyBUaGUgbGlzdCBvZiBncm91cGluZyBjb2x1bW5zIGlzIHRha2VuIGZyb20gdGhlIHF1ZXJ5IGRlc2NyaXB0b3IsIAogIC8vIFNvIHdlIGNhbm5vdCB1c2UgdGhlIElEcyB0byBmaW5kIHRoZSBNViBPdXRwdXQgY29sdW1uIG5hbWVzLgogIC8vIFdlIGhhdmUgdG8gZmluZCB0aGVtIGJ5IG5hbWUuCiAgZm9yIChDb2xsSW5kZXggaT0wOyBpPGdyb3VwaW5nTGlzdC5lbnRyaWVzKCk7IGkrKykKICB7CiAgICBjb25zdCBRUkVsZW1lbnRQdHIgZ3JvdXBpbmdFbGVtID0gZ3JvdXBpbmdMaXN0W2ldLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpOwogICAgaWYgKHZlcmlmeUdyb3VwaW5nRWxlbWVudChncm91cGluZ0VsZW0pID09IEZBTFNFKQogICAgICByZXR1cm4gRkFMU0U7CiAgfQoKICAvLyBSZXR1cm4gd2l0aG91dCAgR3JvdXBCeSBlbGVtZW50IGluIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICByZXR1cm4gVFJVRTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpOQUJvb2xlYW4gTWF0Y2hHcm91cGluZ0NvbHVtbnM6OnZlcmlmeUdyb3VwaW5nRWxlbWVudChjb25zdCBRUkVsZW1lbnRQdHIgZ3JvdXBpbmdFbGVtLCBOQUJvb2xlYW4gaXNSZWN1cnNpdmUpCnsKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gTlVMTDsKICBpZiAoZ3JvdXBpbmdFbGVtLT5nZXRFbGVtZW50VHlwZSgpID09IEVUX0V4cHIpCiAgewogICAgY29uc3QgUVJFeHByUHRyIGdyb3VwaW5nRXhwciA9IGdyb3VwaW5nRWxlbS0+Z2V0UmVmZXJlbmNlZEVsZW1lbnQoKS0+ZG93bkNhc3RUb1FSRXhwcigpOwogICAgcmV3cml0ZSA9IGZpbmRNYXRjaGluZ012RXhwcmVzc2lvbihncm91cGluZ0V4cHItPmdldEV4cHJSb290KCkpOwoKICAgIGlmIChyZXdyaXRlID09IE5VTEwgfHwgIXJld3JpdGUtPmlzRmluYWwoKSkKICAgIHsKICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJncm91cGluZyBleHByZXNzaW9uICVzIGlzIG5vdCBwcm92aWRlZC4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwaW5nRXhwci0+Z2V0SUQoKS5kYXRhKCkpOwogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CiAgfQogIGVsc2UKICB7CiAgICBhc3NlcnRMb2dBbmRUaHJvdyhDQVRfTUFUQ0hUU1RfTVZERVRBSUxTLCBMTF9NVlFSX0ZBSUwsIAogICAgICAgICAgICAgICAgICAgICAgZ3JvdXBpbmdFbGVtLT5nZXRFbGVtZW50VHlwZSgpID09IEVUX0NvbHVtbiwgUVJMb2dpY0V4Y2VwdGlvbiwgCiAgCQkgICAgICAiRXhwZWN0aW5nIGEgUVJDb2x1bW4gZWxlbWVudC4iKTsKICAgIGNvbnN0IFFSQ29sdW1uUHRyIGdyb3VwaW5nQ29sID0gZ3JvdXBpbmdFbGVtLT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKCiAgICBpZiAoY2FuZGlkYXRlXy0+Z2V0UXVlcnlEZXRhaWxzKCktPmlzRnJvbUpvaW4oZ3JvdXBpbmdDb2wpICYmICFpc1JlY3Vyc2l2ZSkKICAgIHsKICAgICAgLy8gVGhpcyBncm91cGluZyBjb2x1bW4gaXMgcGFydCBvZiBhbiBlcXVhbGl0eSBzZXQuCiAgICAgIC8vIENoZWNrIGVhY2ggZWxlbWVudCBvZiB0aGUgZXF1YWxpdHkgc2V0IHRvIHNlZSBpZiBhbnkgb2YgdGhlbSBpcyBQcm92aWRlZCBieSB0aGUgTVYuCiAgICAgIGNvbnN0IFFSSm9pblByZWRQdHIganAgPSBjYW5kaWRhdGVfLT5nZXRRdWVyeURldGFpbHMoKS0+Z2V0Sm9pblByZWQoZ3JvdXBpbmdDb2wpOwogICAgICBjb25zdCBFbGVtZW50UHRyTGlzdCYgZXFMaXN0ID0ganAtPmdldEVxdWFsaXR5TGlzdCgpOwogICAgICBDb2xsSW5kZXggbWF4RW50cmllcyA9IGVxTGlzdC5lbnRyaWVzKCk7CiAgICAgIGZvciAoQ29sbEluZGV4IGk9MDsgaTxtYXhFbnRyaWVzOyBpKyspCiAgICAgIHsKICAgICAgICBjb25zdCBRUkVsZW1lbnRQdHIgZXFFbGVtID0gZXFMaXN0W2ldLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpOwogICAgICAgIGlmIChlcUVsZW0tPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfQ29sdW1uICYmCiAgICAgICAgICAgIHZlcmlmeUdyb3VwaW5nRWxlbWVudChlcUVsZW0sIFRSVUUpICkKICAgICAgICAgIHJldHVybiBUUlVFOwogICAgICB9IC8vIEVuZCBvZiBmb3IgbG9vcC4KCiAgICAgIC8vIElmIHdlIGdvdCBoZXJlLCBub25lIG9mIHRoZSBlcVNldCdzIGNvbHVtbnMgaXMgUHJvdmlkZWQgYnkgdGhlIE1WLgogICAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIlRoZSBuZWVkZWQgZ3JvdXBpbmcgY29sdW1uICVzIGlzIG5vdCBQcm92aWRlZC4iLCAKCQkJICAgICAgICAgICAgICAgIGdyb3VwaW5nRWxlbS0+Z2V0SUQoKS5kYXRhKCkpOwogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CiAgICAvLyBHZXQgdGhlIE1WIGJhc2UgdGFibGUgb2JqZWN0IGZyb20gdGhlIHF1ZXJ5IHRhYmxlIElELgogICAgY29uc3QgQmFzZVRhYmxlRGV0YWlsc1B0ciBiYXNlVGFibGUgPSBjYW5kaWRhdGVfLT5nZXRNdlRhYmxlRm9yUXVlcnlJRChncm91cGluZ0NvbC0+Z2V0VGFibGVJRCgpLCBGQUxTRSk7CgogICAgaWYgKGJhc2VUYWJsZSA9PSBOVUxMKQogICAgewogICAgICBpZiAoaXNSZWN1cnNpdmUpCiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgICBlbHNlCiAgICAgICAgcmV3cml0ZSA9IG5ldyhoZWFwXykgCgkgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGdyb3VwaW5nRWxlbSwgTlVMTCwgUkNfT1VUU0lERSwgUlNfRklOQUwsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIGNvbnN0IFFST3V0cHV0UHRyIG12T3V0cHV0ID0gCiAgICAgICAgY2FuZGlkYXRlXy0+Z2V0TXZEZXRhaWxzKCktPmdldE91dHB1dEJ5Q29sdW1uTmFtZShiYXNlVGFibGUtPmdldFRhYmxlRWxlbWVudCgpLT5nZXRJRCgpLCAKCQkJCQkJCSAgZ3JvdXBpbmdDb2wtPmdldENvbHVtbk5hbWUoKSwgaGVhcF8pOwoKICAgICAgaWYgKG12T3V0cHV0ID09IE5VTEwpCiAgICAgIHsKICAgICAgICAvLyBUaGlzIGNvbHVtbiBoYXMgYSByYW5nZSBwcmVkaWNhdGUgb24gaXQgLCB3aGVyZSBpdCBpcyBlcXVhbCB0byBhIAogICAgICAgIC8vIGNvbnN0YW50IHZhbHVlLCBzbyBpdCBkb2VzIG5vdCByZWFsbHkgbmVlZCB0byBiZSBwcm92aWRlZCBieSB0aGUgTVYuCiAgICAgICAgaWYgKGNhbmRpZGF0ZV8tPmdldFF1ZXJ5SmJiRGV0YWlscygpLT5pc0NvbnN0Q29sdW1uKCZncm91cGluZ0NvbC0+Z2V0SUQoKSkpCiAgICAgICAgICByZXR1cm4gVFJVRTsKICAgICAgfQoKICAgICAgLy8gQ2hlY2sgaWYgdGhlIGNvbHVtbiBpcyBiYWNrLWpvaW5hYmxlIG9ubHkgd2hlbiB0aGlzIGlzIG5vdCBhIHJlY3Vyc2l2ZSBjYWxsIAogICAgICAvLyB0aGF0IGNoZWNrcyBmb3IgY29sdW1ucyBvZiBhbiBlcXVhbGl0eSBzZXQuCiAgICAgIE5BQm9vbGVhbiBpc0JhY2tKb2luYWJsZSA9IEZBTFNFOwogICAgICBpZiAoIWlzUmVjdXJzaXZlKQogICAgICAgIGlzQmFja0pvaW5hYmxlID0gaXNCYWNrSm9pbmFibGVDb2x1bW4oZ3JvdXBpbmdDb2wpOwogICAgICBpZiAobXZPdXRwdXQgPT0gTlVMTCAmJiAhaXNCYWNrSm9pbmFibGUpCiAgICAgIHsKICAgICAgICBpZiAoIWlzUmVjdXJzaXZlKQogICAgICAgIHsKICAgICAgICAgIC8vIFRoZSBncm91cGluZyBjb2x1bW4gbmVlZGVkIGZvciByZXdyaXRlIGluc3RydWN0aW9ucyBpcyBub3QKICAgICAgICAgIC8vIGFuIG91dHB1dCBvZiB0aGUgTVYuIAogICAgICAgICAgLy8gRGlzcXVhbGlmeSB0aGUgTVYuCiAgICAgICAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoIlRoZSBuZWVkZWQgZ3JvdXBpbmcgY29sdW1uICVzIGlzIG5vdCBQcm92aWRlZC4iLCAKCQkJICAgICAgICAgICAgICAgICAgICBncm91cGluZ0NvbC0+Z2V0RnVsbHlRdWFsaWZpZWRDb2x1bW5OYW1lKCkuZGF0YSgpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgICB9CgogICAgICAvLyBDcmVhdGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMgZm9yIHRoZSBncm91cGluZyBjb2x1bW4uCiAgICAgIHJld3JpdGUgPSBuZXcoaGVhcF8pIAogICAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGdyb3VwaW5nQ29sLCBtdk91dHB1dCwgUkNfUFJPVklERUQsIFJTX0ZJTkFMLCBBRERfTUVNQ0hFQ0tfQVJHUyhoZWFwXykpOwoKICAgICAgaWYgKG12T3V0cHV0ID09IE5VTEwgJiYgaXNCYWNrSm9pbmFibGUpCiAgICAgIHsKICAgICAgICByZXdyaXRlLT5zZXRSZXN1bHRTdGF0dXMoUlNfSU5URVJNRURJQVRFKTsKICAgICAgICByZXdyaXRlLT5hZGRCYWNrSm9pblRhYmxlKCZncm91cGluZ0NvbC0+Z2V0VGFibGVJRCgpKTsKICAgICAgICByZXdyaXRlLT5zZXRSZXN1bHRDb2RlKFJDX0JBQ0tKT0lOKTsKICAgICAgICByZXdyaXRlLT5zZXRTZWNvbmRhcnlSZXN1bHRDb2RlKFJDX0JBQ0tKT0lOKTsKICAgICAgfQoKICAgICAgLy8gRm9yIE1KVnMsIGFkZCBpdCB0byB0aGUgb3V0cHV0IGxpc3QuCiAgICAgIGlmIChjYW5kaWRhdGVfLT5nZXRBZ2dyZWdhdGVNYXRjaGluZ1R5cGUoKSA9PSBBTVRfTUpWX0FRKQogICAgICB7CiAgICAgICAgY2FuZGlkYXRlXy0+YWRkT3V0cHV0Q29sdW1uKHJld3JpdGUpOwogICAgICB9CgogICAgfSAgLy8gZWxzZSBmb3VuZCBiYXNlVGFibGUKICB9ICAvLyBlbHNlIFFSQ29sdW1uCgogIGFkZFJld3JpdGVJbnN0cnVjdGlvbnMocmV3cml0ZSk7CgogIHJldHVybiBUUlVFOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gQSBnZW5lcmljIG1ldGhvZCBmb3IgZ2VuZXJhdGluZyB0aGUgcmVzdWx0IGRlc2NyaXB0b3IgZWxlbWVudHMuCi8vIFRoZSBzcGVjaWZpYyBkZXRhaWxzIGFyZSBpbXBsZW1lbnRlZCBieSBzdWItY2xhc3Nlcy4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCk5BQm9vbGVhbiBNYXRjaEdyb3VwaW5nQ29sdW1uczo6Z2VuZXJhdGVEZXNjcmlwdG9yKFFSQ2FuZGlkYXRlUHRyIHJlc3VsdERlc2MpCnsKICAvLyBObyBHcm91cEJ5IGVsZW1lbnQgdG8gZ2VuZXJhdGUgZm9yIE1KVnMuCiAgaWYgKGNhbmRpZGF0ZV8tPmdldEFnZ3JlZ2F0ZU1hdGNoaW5nVHlwZSgpID09IEFNVF9NSlZfQVEgfHwKICAgICAgY2FuZGlkYXRlXy0+Z2V0QWdncmVnYXRlTWF0Y2hpbmdUeXBlKCkgPT0gQU1UX01KVl9KUSkKICAgIHJldHVybiBUUlVFOwoKICBRUkdyb3VwQnlQdHIgZ3JvdXBCeSA9IG5ldyhoZWFwXykgUVJHcm91cEJ5KEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CgogIC8vIEFkZCBhIHJlZmVyZW5jZSB0byB0aGUgcXVlcnkgTm9kZUlEIG9mIHRoZSBHcm91cEJ5IG5vZGUuCiAgZ3JvdXBCeS0+c2V0UmVmKGNhbmRpZGF0ZV8tPmdldFF1ZXJ5SmJiKCktPmdldEdyb3VwQnkoKS0+Z2V0SUQoKSk7CgogIGlmIChjYW5kaWRhdGVfLT5nZXRBZ2dyZWdhdGVNYXRjaGluZ1R5cGUoKSA9PSBBTVRfTUFWX0FRX01HKQogIHsKICAgIGdyb3VwQnktPnNldFJlc3VsdChRUkVsZW1lbnQ6OlByb3ZpZGVkKTsKICB9CiAgZWxzZQogIHsKICAgIGdyb3VwQnktPnNldFJlc3VsdChRUkVsZW1lbnQ6Ok5vdFByb3ZpZGVkKTsKCiAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbUxpc3QmIHJld3JpdGVMaXN0ID0gZ2V0TGlzdE9mRmluYWxJbnN0cnVjdGlvbnMoKTsKICAgIGZvciAoQ29sbEluZGV4IGk9MDsgaTxyZXdyaXRlTGlzdC5lbnRyaWVzKCk7IGkrKykKICAgIHsKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IHJld3JpdGVMaXN0W2ldOwogICAgICBpZiAocmV3cml0ZS0+Z2V0UmVzdWx0Q29kZSgpID09IFJDX1BST1ZJREVEKQogICAgICB7CiAgICAgICAgUVJNVkNvbHVtblB0ciBtdkNvbHVtbiA9IGdlbmVyYXRlUHJvdmlkZWRNdkNvbHVtbihyZXdyaXRlKTsKICAgICAgICBncm91cEJ5LT5nZXRQcmltYXJ5TGlzdCgpLT5hZGRFbGVtZW50KG12Q29sdW1uKTsKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKICAgICAgICBhc3NlcnRMb2dBbmRUaHJvdyhDQVRfTUFUQ0hUU1RfTVZERVRBSUxTLCBMTF9NVlFSX0ZBSUwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV3cml0ZS0+Z2V0UmVzdWx0Q29kZSgpID09IFJDX09VVFNJREUsIFFSTG9naWNFeGNlcHRpb24sIAoJICAgICAgCSAgICAgICAgICAiRXhwZWN0aW5nIG9ubHkgT3V0c2lkZSBhbmQgUHJvdmlkZWQgZ3JvdXBpbmcgQ29sdW1ucy4iKTsKCiAgICAgICAgUVJDb2x1bW5QdHIgY29sdW1uID0gZ2VuZXJhdGVOb3RQcm92aWRlZENvbHVtbihyZXdyaXRlKTsKICAgICAgICBncm91cEJ5LT5nZXRQcmltYXJ5TGlzdCgpLT5hZGRFbGVtZW50KGNvbHVtbik7CiAgICAgIH0KICAgIH0KICB9CgogIHJlc3VsdERlc2MtPnNldEdyb3VwQnkoZ3JvdXBCeSk7CgogIHJldHVybiBUUlVFOwp9ICAvLyBNYXRjaEdyb3VwaW5nQ29sdW1uczo6Z2VuZXJhdGVEZXNjcmlwdG9yKCkKCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci8vICBDbGFzcyBNYXRjaEpvaW5QcmVkcwovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIFJ1biB0aGUgUGFzcyAxIGFsZ29yaXRobSBvZiBqb2luIHByZWRpY2F0ZSB0ZXN0LgovLyBUaGUgZ29hbCBpcyB0byBmaW5kIGpvaW4gcHJlZGljYXRlcyBiZXR3ZWVuIHRhYmxlcyBjb3ZlcmVkIGJ5IHRoZSBNViwgYW5kCi8vIHRhYmxlcyBub3QgY292ZXJlZCBieSB0aGUgTVYsIGFuZCB2ZXJpZnkgdGhhdCB0aGUgbmVlZGVkIGNvbHVtbnMgZnJvbSAKLy8gdGhlIE1WIHRhYmxlcyBhcmUgUHJvdmlkZWQgYnkgdGhlIE1WLgovLyBKb2luIHByZWRpY2F0ZXMgb24gdGFibGVzIGluIHRoZSBleHRyYSBodWIgdGFibGUgbGlzdCBhcmUga2VwdCBmb3IgUEFTUyAyLgovLyBSZXR1cm5zIFRSVUUgaWYgdGhlIE1WIHBhc3NlZCB0aGlzIHRlc3QsIEZBTFNFIGlmIGl0IHdhcyBkaXNxdWFsaWZpZWQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hKb2luUHJlZHM6Om1hdGNoUGFzczEoKQp7CiAgY29uc3QgUVJKb2luUHJlZExpc3RQdHIgcXVlcnlIdWJKb2luUHJlZHMgICAgICA9IGNhbmRpZGF0ZV8tPmdldFF1ZXJ5SmJiKCktPmdldEh1YigpLT5nZXRKb2luUHJlZExpc3QoKTsKICBjb25zdCBRUkpvaW5QcmVkTGlzdFB0ciBxdWVyeUV4dHJhSHViSm9pblByZWRzID0gY2FuZGlkYXRlXy0+Z2V0UXVlcnlKYmIoKS0+Z2V0RXh0cmFIdWIoKS0+Z2V0Sm9pblByZWRMaXN0KCk7CgogIC8vIEZvciBlYWNoIGpvaW4gcHJlZCBpbiB0aGUgaHViCiAgaWYgKHF1ZXJ5SHViSm9pblByZWRzICE9IE5VTEwpCiAgewogICAgQ29sbEluZGV4IG1heEVudHJpZXMgPSBxdWVyeUh1YkpvaW5QcmVkcy0+ZW50cmllcygpOwogICAgZm9yIChDb2xsSW5kZXggaT0wOyBpPG1heEVudHJpZXM7IGkrKykKICAgIHsKICAgICAgY29uc3QgUVJKb2luUHJlZFB0ciBqb2luUHJlZCA9ICgqcXVlcnlIdWJKb2luUHJlZHMpW2ldOwogICAgICBpZiAoYW5hbHl6ZUpvaW5QcmVkaWNhdGUoam9pblByZWQsIFRSVUUpID09IEZBTFNFKQogICAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KICB9CgogIC8vIEFuZCBpbiB0aGUgZXh0cmEtaHViCiAgaWYgKHF1ZXJ5RXh0cmFIdWJKb2luUHJlZHMgIT0gTlVMTCkKICB7CiAgICBDb2xsSW5kZXggbWF4RW50cmllcyA9IHF1ZXJ5RXh0cmFIdWJKb2luUHJlZHMtPmVudHJpZXMoKTsKICAgIGZvciAoQ29sbEluZGV4IGk9MDsgaTxtYXhFbnRyaWVzOyBpKyspCiAgICB7CiAgICAgIGNvbnN0IFFSSm9pblByZWRQdHIgam9pblByZWQgPSAoKnF1ZXJ5RXh0cmFIdWJKb2luUHJlZHMpW2ldOwogICAgICBpZiAoYW5hbHl6ZUpvaW5QcmVkaWNhdGUoam9pblByZWQsIFRSVUUpID09IEZBTFNFKQogICAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KICB9CgogIHJldHVybiBUUlVFOwp9ICAvLyBNYXRjaEpvaW5QcmVkczo6bWF0Y2hQYXNzMSgpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gQW5hbHl6ZSBhIHNpbmdsZSBqb2luIHByZWRpY2F0ZSB0byB2ZXJpZnkgdGhlIG5lZWRlZCBjb2x1bW5zIGFyZSBQcm92aWRlZAovLyBieSB0aGUgTVYuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hKb2luUHJlZHM6OmFuYWx5emVKb2luUHJlZGljYXRlKGNvbnN0IFFSSm9pblByZWRQdHIgam9pblByZWQsIE5BQm9vbGVhbiBpc1Bhc3MxKQp7CiAgLy8gRm9yIHRoaXMgam9pbiBwcmVkLCBhcmUgdGhlIGVxdWFsaXR5IHNldCBtZW1iZXJzIGZyb20gdGhlIE1WIGh1Yj8KICBJbnQzMiBtdlRhYmxlcyAgPSAwOyAvLyBob3cgbWFueSBhcmUgZnJvbSB0aGUgTVYgaHViPwogIEludDMyIGVoVGFibGVzICA9IDA7IC8vIGhvdyBtYW55IGFyZSBmcm9tIHRoZSBNViBleHRyYS1odWI/CiAgSW50MzIgb3V0VGFibGVzID0gMDsgLy8gaG93IG1hbnkgYXJlIGZyb20gT3V0c2lkZSB0YWJsZXM/CiAgQ29sdW1uTm9kZXNMaXN0ICBtdkNvbHVtbnMoaGVhcF8pOyAvLyBDb2x1bW5zIGZyb20gdGhlIE1WIGh1Yi4KICBOQVB0ckxpc3Q8UVJFeHByUHRyPiAgICBtdkV4cHJzKGhlYXBfKTsgICAvLyBFeHByZXNzaW9ucyBmcm9tIHRoZSBNViBodWIuCgogIGNvbnN0IEVsZW1lbnRQdHJMaXN0JiBlcUxpc3QgPSBqb2luUHJlZC0+Z2V0TGlzdCgpOwogIFFSSm9pblByZWRQdHIgcmVmZXJlbmNlZEh1YlByZWQgPSBOVUxMOwogIGZvciAoQ29sbEluZGV4IGk9MDsgaTxlcUxpc3QuZW50cmllcygpOyBpKyspCiAgewogICAgUVJFbGVtZW50UHRyIGVsZW0gPSBlcUxpc3RbaV07CiAgICAvLyBBbiBleHRyYS1odWIgam9pbiBwcmVkIG1heSByZWZlcmVuY2UgYSBodWIgam9pbiBwcmVkLgogICAgaWYgKGVsZW0tPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfSm9pblByZWQpCiAgICAgIHJlZmVyZW5jZWRIdWJQcmVkID0gZWxlbS0+ZG93bkNhc3RUb1FSSm9pblByZWQoKTsKICAgIGVsc2UKICAgICAgYW5hbHl6ZUVRTWVtYmVyKGVsZW0sIG12VGFibGVzLCBlaFRhYmxlcywgb3V0VGFibGVzLCBtdkNvbHVtbnMsIG12RXhwcnMsIGlzUGFzczEpOwogIH0gCgogIGlmIChyZWZlcmVuY2VkSHViUHJlZCAhPSBOVUxMKQogIHsKICAgIGNvbnN0IEVsZW1lbnRQdHJMaXN0JiBlcUxpc3QyID0gcmVmZXJlbmNlZEh1YlByZWQtPmdldExpc3QoKTsKICAgIGZvciAoQ29sbEluZGV4IGk9MDsgaTxlcUxpc3QyLmVudHJpZXMoKTsgaSsrKQogICAgewogICAgICBRUkVsZW1lbnRQdHIgZWxlbSA9IGVxTGlzdDJbaV07CiAgICAgIGFuYWx5emVFUU1lbWJlcihlbGVtLCBtdlRhYmxlcywgZWhUYWJsZXMsIG91dFRhYmxlcywgbXZDb2x1bW5zLCBtdkV4cHJzLCBpc1Bhc3MxKTsKICAgIH0gCiAgfQoKICAvLyBXZSB3ZW50IHRocm91Z2ggYWxsIHRoZSBlbGVtZW50cyBpbiB0aGUgZXF1YWxpdHkgc2V0LgogIC8vIE5vdyBsZXRzIGNoZWNrIHdoYXQgd2UgZm91bmQuCiAgaWYgKGVoVGFibGVzID4gMCkKICB7CiAgICAvLyBUaGlzIGpvaW4gcHJlZCB1c2VzIE1WIGV4dHJhLWh1YiB0YWJsZXMuCiAgICAvLyBQb3N0cG9zZSBkZWNpc2lvbiB0byBQQVNTIDIsIHdoZW4gd2Uga25vdyB3aGljaCBhcmUgcmVhbGx5IHVzZWQuCiAgICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbVB0ciByZXdyaXRlID0gbmV3KGhlYXBfKSAKICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW0oam9pblByZWQsIE5VTEwsIFJDX05PVFBST1ZJREVELCBSU19JTlRFUk1FRElBVEUsIEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICBhZGRSZXdyaXRlSW5zdHJ1Y3Rpb25zKHJld3JpdGUpOwogICAgcmV0dXJuIFRSVUU7CiAgfQogIGVsc2UgaWYgKG12VGFibGVzID09IDApCiAgewogICAgLy8gTm8gZXh0cmEtaHViIGFuZCBubyBodWIgdGFibGVzOgogICAgLy8gVGhpcyBqb2luIHByZWQgaXMgb25seSBvbiB0YWJsZXMgdGhhdCBhcmUgb3V0c2lkZSB0aGUgTVYuCiAgICAvLyBXZSBjYW4gaWdub3JlIGl0LgogICAgcmV0dXJuIFRSVUU7CiAgfQogIGVsc2UgaWYgKG91dFRhYmxlcyA9PSAwKQogIHsKICAgIC8vIE5vIGV4dHJhLWh1YiBhbmQgbm8gT3V0c2lkZSB0YWJsZXM6CiAgICAvLyBUaGlzIGpvaW4gcHJlZCBpcyBvbmx5IG9uIE1WIGh1YiB0YWJsZXMuCiAgICAvLyBJdCBtdXN0IGhhdmUgYmVlbiBjaGVja2VkIGJ5IE1WTWVtby4KICAgIC8vIFdlIGNhbiBpZ25vcmUgaXQgaGVyZS4KICAgIHJldHVybiBUUlVFOwogIH0KICBlbHNlCiAgewogICAgLy8gVGhpcyBqb2luIHByZWQgZXF1YXRlcyBNViBodWIgdGFibGVzIHdpdGggb3V0c2lkZSB0YWJsZXMgd2l0aCBubyBleHRyYWh1YnMuCiAgICAvLyBXZSBuZWVkIHRvIHZlcmlmeSB0aGF0IGF0IGxlYXN0IG9uZSBvZiB0aGUgY29sdW1ucyB1c2VkIGZyb20gdGhlIGh1YgogICAgLy8gaXMgcHJvdmlkZWQgYnkgdGhlIE1WLgogICAgUVJPdXRwdXRQdHIgbXZDb2wgPSBOVUxMOwogICAgTkFCb29sZWFuIGZvdW5kUHJvdmlkZWQgPSBGQUxTRTsKICAgIFFSQ29sdW1uUHRyIGh1YkNvbCA9IE5VTEw7CiAgICBmb3IgKENvbGxJbmRleCBrPTA7IGs8bXZDb2x1bW5zLmVudHJpZXMoKTsgaysrKQogICAgewogICAgICBodWJDb2wgPSBtdkNvbHVtbnNba107CiAgICAgIGlmIChpc1Byb3ZpZGVkQ29sdW1uKGh1YkNvbCwgbXZDb2wpKQogICAgICB7CiAgICAgICAgLy8gV2UgZm91bmQgYSBQcm92aWRlZCBNViBIdWIgY29sdW1uLgogICAgICAgIC8vIE1ha2Ugc3VyZSBpdHMgYWRkZWQgdG8gdGhlIE91dHB1dCBsaXN0LgogICAgICAgIC8vIFVzZSB0aGUgSUQgb2YgdGhlIGNvbHVtbiBpbnN0ZWFkIG9mIHRoZSBJRCBvZiB0aGUgam9pbiBwcmVkaWNhdGUuCiAgICAgICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IG5ldyhoZWFwXykgCgkgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGh1YkNvbCwgbXZDb2wsIFJDX1BST1ZJREVELCBSU19GSU5BTCwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKCWNhbmRpZGF0ZV8tPmFkZE91dHB1dENvbHVtbihyZXdyaXRlLCBGQUxTRSk7CiAgICAgICAgLy8gQXZvaWQgYWRkaW5nIGFuIE91dHB1dCBlbGVtZW50IHdpdGggdGhlIElEIG9mIHRoZSBqb2luIHByZWRpY2F0ZS4KICAgICAgICBjYW5kaWRhdGVfLT5hZGRPdXRwdXRUb0F2b2lkKGpvaW5QcmVkLT5nZXRJRCgpKTsKICAgICAgICBmb3VuZFByb3ZpZGVkID0gVFJVRTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKICAgICAgICAvLyBUaGlzIE1WIGh1YiBjb2x1bW4gaXMgbm90IFByb3ZpZGVkLgogICAgICAgIC8vIGNvbnRpbnVlIHRvIHRoZSBuZXh0IG9uZS4KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgfSAvLyBmb3IgKGspCiAgICAKICAgIGlmICghZm91bmRQcm92aWRlZCAmJiBtdkV4cHJzLmVudHJpZXMoKSA+IDApCiAgICB7CiAgICAgIC8vIE5vbmUgb2YgdGhlIHNpbXBsZSBjb2x1bW5zIGFyZSBQcm92aWRlZCwgbmVlZCB0byBjaGVjayBleHByZXNzaW9ucy4KICAgICAgLy8gSGVyZSB3ZSBuZWVkIGFsbCB0aGUgaW5wdXQgY29sdW1ucyB0byBiZSBQcm92aWRlZC4KICAgICAgZm9yIChDb2xsSW5kZXggbT0wOyBtPG12RXhwcnMuZW50cmllcygpOyBtKyspCiAgICAgIHsKICAgICAgICBpZiAoYW5hbHl6ZVByb3ZpZGVkRXhwcmVzc2lvbihtdkV4cHJzW21dKSkKICAgICAgICAgIGZvdW5kUHJvdmlkZWQgPSBUUlVFOwogICAgICB9IAogICAgfQoKICAgIGlmICghZm91bmRQcm92aWRlZCkKICAgIHsKICAgICAgaWYgKGh1YkNvbCAhPSBOVUxMKQogICAgICB7CiAgICAgICAgLy8gTm9uZSBvZiB0aGUgTVYgSHViIGNvbHVtbiBhcmUgUHJvdmlkZWQgYnkgdGhlIE1WLgogICAgICAgIC8vIFRoaXMgY2FuZGlkYXRlIG11c3QgYmUgZGlzcXVhbGlmaWVkLgogICAgICAgIGNvbnN0IE5BU3RyaW5nJiBjb2xOYW1lID0gaHViQ29sLT5nZXRGdWxseVF1YWxpZmllZENvbHVtbk5hbWUoKTsKICAgICAgICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoImNvbHVtbiAlcyBjYW5ub3QgYmUgcHJvdmlkZWQuIiwgY29sTmFtZSk7CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJqb2luIHByZWRpY2F0ZSAlcyBjYW5ub3QgYmUgcHJvdmlkZWQuIiwgam9pblByZWQtPmdldElEKCkuZGF0YSgpKTsKICAgICAgfQogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CiAgfSAvLyBNViBodWIgYW5kIG91dHNpZGUgdGFibGVzLCBubyBleHRyYWh1Yi4KCiAgcmV0dXJuIFRSVUU7Cn0gIC8vIE1hdGNoSm9pblByZWRzOjpjaGVja0pvaW5QcmVkaWNhdGUoKQoKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyBDaGVjayBpZiB0aGlzIGVxdWFsaXR5IHNldCBtZW1iZXIgaXMgb24gYW4gTVYgaHViLCBleHRyYWh1YiB0YWJsZSBvciAKLy8gb24gYW4gT3V0c2lkZSB0YWJsZS4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCnZvaWQgTWF0Y2hKb2luUHJlZHM6OmFuYWx5emVFUU1lbWJlcihRUkVsZW1lbnRQdHIgICBlbGVtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSW50MzImICAgICAgICAgbXZUYWJsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJbnQzMiYgICAgICAgICBlaFRhYmxlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEludDMyJiAgICAgICAgIG91dFRhYmxlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvbHVtbk5vZGVzTGlzdCYgbXZDb2x1bW5zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkFQdHJMaXN0PFFSRXhwclB0cj4mICAgbXZFeHBycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BQm9vbGVhbiAgICAgIGlzUGFzczEpCnsKICAvLyBHZXQgYSBzaW1wbGUgY29sdW1uIGZyb20gdGhpcyBlcXVhbGl0eSBzZXQgbWVtYmVyLgogIFFSQ29sdW1uUHRyIGNvbCA9IGVsZW0tPmdldEZpcnN0Q29sdW1uKCk7CgogIGNvbnN0IE5BU3RyaW5nKiBleHRyYUh1YklEID0gTlVMTDsKICBOQUJvb2xlYW4gaXNPdXRzaWRlID0gaXNPdXRzaWRlQ29sdW1uKGNvbCwgZXh0cmFIdWJJRCk7CgogIGlmIChpc1Bhc3MxID09IEZBTFNFICAgJiYKICAgICAgZXh0cmFIdWJJRCAhPSBOVUxMICYmCiAgICAgIGNhbmRpZGF0ZV8tPmlzQVVzZWRFeHRyYUh1YlRhYmxlKGV4dHJhSHViSUQpKQogIHsKICAgIC8vIFdlIGFyZSBpbiBQYXNzMiwgYW5kIHRoaXMgaXMgYW4gTVYgZXh0cmEtaHViIHRhYmxlIHRoYXQgaXMgCiAgICAvLyB1c2VkIGJ5IHRoZSBxdWVyeS4KICAgIC8vIENvbnNpZGVyIGl0IGFzIGFuIE1WIGh1YiB0YWJsZS4KICAgIGV4dHJhSHViSUQgPSBOVUxMOwogIH0KCiAgaWYgKGlzT3V0c2lkZSkKICB7CiAgICAvLyBUaGlzIHRhYmxlIGlzIE91dHNpZGUgdGhlIE1WLgogICAgb3V0VGFibGVzKys7CiAgfQogIGVsc2UgaWYgKGV4dHJhSHViSUQgIT0gTlVMTCkKICB7CiAgICAvLyBUaGlzIGlzIGFuIE1WIGV4dHJhLWh1YiB0YWJsZSwgYW5kIHdlIGFyZSBpbiBQYXNzMS4KICAgIC8vIENoZWNrIGlmIGl0cyBpbiB0aGUgdXNlZCBleHRyYSBodWIgdGFibGVzIGxpc3QuCiAgICBpZiAoY2FuZGlkYXRlXy0+aXNBVXNlZEV4dHJhSHViVGFibGUoZXh0cmFIdWJJRCkpCiAgICAgIGVoVGFibGVzKys7CiAgICBlbHNlCiAgICB7CiAgICAgIC8vIElmIGl0cyBpbiB0aGUgTVYgZXh0cmFodWIsIGJ1dCBub3QgbmVlZGVkIGJ5IHRoZSBxdWVyeSwKICAgICAgLy8gaXRzIG91dHNpZGUuCiAgICAgIG91dFRhYmxlcysrOwogICAgfQogIH0KICBlbHNlCiAgewogICAgLy8gVGhpcyBpcyBhbiBNViBodWIgdGFibGUuCiAgICBtdlRhYmxlcysrOwogICAgaWYgKGVsZW0tPmdldEVsZW1lbnRUeXBlKCkgPT0gRVRfQ29sdW1uKQogICAgICBtdkNvbHVtbnMuaW5zZXJ0KGNvbCk7CiAgICBlbHNlCiAgICB7CiAgICAgIGFzc2VydExvZ0FuZFRocm93KENBVF9NQVRDSFRTVF9NVkRFVEFJTFMsIExMX01WUVJfRkFJTCwKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS0+Z2V0RWxlbWVudFR5cGUoKSA9PSBFVF9FeHByLCBRUkxvZ2ljRXhjZXB0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgIkV4cGVjdGluZyBvbmx5IFFSRXhwciBlbGVtZW50cyBoZXJlLiIpOwogICAgICAvLyBBbGwgdGhlIGV4cHJlc3Npb24ncyBpbnB1dCBjb2x1bW5zIG11c3QgYmUgUHJvdmlkZWQuCiAgICAgIC8vIE5lZWQgdG8gYWRkIGFzIGEgZ3JvdXAuCiAgICAgIG12RXhwcnMuaW5zZXJ0KGVsZW0tPmRvd25DYXN0VG9RUkV4cHIoKSk7CiAgICB9CiAgfQp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gQW5hbHl6ZSBhbiBleHByZXNzaW9uIG9uIGFuIE1WIGh1YiB0YWJsZSwgdG8gY2hlY2sgaWYgYWxsIGl0cyBpbnB1dCAKLy8gY29sdW1ucyBhcmUgUHJvdmlkZWQgYnkgdGhlIE1WLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoSm9pblByZWRzOjphbmFseXplUHJvdmlkZWRFeHByZXNzaW9uKGNvbnN0IFFSRXhwclB0ciBleHByKQp7CiAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IG1hdGNoRXhwcmVzc2lvbihleHByKTsKCiAgaWYgKHJld3JpdGUgPT0gTlVMTCB8fCAhcmV3cml0ZS0+aXNGaW5hbCgpKQogIHsKICAgIC8vIFRoZSBleHByZXNzaW9uIGNhbm5vdCBiZSBQcm92aWRlZCBieSB0aGUgTVYuCiAgICBpZiAocmV3cml0ZSkKICAgICAgZGVsZXRlUHRyKHJld3JpdGUpOwogICAgcmV0dXJuIEZBTFNFOwogIH0KCiAgLy8gYWRkIHRoZSBpbnB1dCBjb2x1bW5zIHRvIHRoZSBvdXRwdXQgbGlzdC4KICBhZGRJbnB1dHNUb091dHB1dExpc3QocmV3cml0ZSk7CgogIC8vIFByb3ZpZGVkIG1lYW5zIHRoYXQgdGhlIGV4cHJlc3Npb24gaXRzZWxmIGlzIFByb3ZpZGVkLAogIC8vIHNvIGFkZCBpdCB0byB0aGUgT3V0cHV0IGxpc3QgYXMgd2VsbC4KICBpZiAocmV3cml0ZS0+Z2V0UmVzdWx0Q29kZSgpPT1SQ19QUk9WSURFRCkKICAgIGNhbmRpZGF0ZV8tPmFkZE91dHB1dENvbHVtbihyZXdyaXRlLCBGQUxTRSk7CgogIHJldHVybiBUUlVFOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gUnVuIHRoZSBQYXNzIDIgYWxnb3JpdGhtIG9mIGpvaW4gcHJlZGljYXRlcyB0ZXN0LgovLyBSZXR1cm5zIFRSVUUgaWYgdGhlIE1WIHBhc3NlZCB0aGlzIHRlc3QsIEZBTFNFIGlmIGl0IHdhcyBkaXNxdWFsaWZpZWQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hKb2luUHJlZHM6Om1hdGNoUGFzczJPbkVsZW1lbnQoUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcGVuZGluZykKewogIFFSSm9pblByZWRQdHIgam9pblByZWQgPSBwZW5kaW5nLT5nZXRRdWVyeUVsZW1lbnQoKS0+ZG93bkNhc3RUb1FSSm9pblByZWQoKTsKICBOQUJvb2xlYW4gcmVzdWx0ID0gYW5hbHl6ZUpvaW5QcmVkaWNhdGUoam9pblByZWQsIEZBTFNFKTsKICByZXR1cm4gcmVzdWx0Owp9ICAvLyBNYXRjaEpvaW5QcmVkczo6bWF0Y2hQYXNzMk9uRWxlbWVudCgpCgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCk5BQm9vbGVhbiBNYXRjaEpvaW5QcmVkczo6Z2VuZXJhdGVEZXNjcmlwdG9yKFFSQ2FuZGlkYXRlUHRyIHJlc3VsdERlc2MpCnsKICBJRFNldCYgYmFja0pvaW5UYWJsZXMgPSBjYW5kaWRhdGVfLT5nZXRCYWNrSm9pblRhYmxlcygpOwogIGlmIChiYWNrSm9pblRhYmxlcy5lbnRyaWVzKCkgPT0gMCkKICAgIHJldHVybiBUUlVFOwoKICAvLyBGb3IgZWFjaCBiYWNrLWpvaW4gdGFibGUKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8YmFja0pvaW5UYWJsZXMuZW50cmllcygpOyBpKyspCiAgewogICAgY29uc3QgTkFTdHJpbmcqIHRhYmxlSUQgPSBiYWNrSm9pblRhYmxlc1tpXTsKICAgIGNvbnN0IFFSVGFibGVQdHIgdGFibGUgPSBjYW5kaWRhdGVfLT5nZXRRdWVyeURldGFpbHMoKS0+Z2V0RWxlbWVudEZvcklEKCp0YWJsZUlEKS0+ZG93bkNhc3RUb1FSVGFibGUoKTsKCiAgICAvLyBBZGQgdGhlIGpvaW4gcHJlZGljYXRlIHRvIHRoZSBiYWNrLWpvaW4gdGFibGUuCiAgICBpZiAoYWRkQmFja0pvaW5QcmVkc0ZvclRhYmxlKHRhYmxlLCByZXN1bHREZXNjKSA9PSBGQUxTRSkKICAgIHsKICAgICAgLy8gaWYgdGhlIGNyZWF0aW9uIG9mIHRoZSBqb2luIHByZWQgd2FzIG5vdCBzdWNjZXNzZnVsLCAKICAgICAgLy8gRGlzcXVhbGlmeSB0aGUgTVYuCiAgICAgIGNhbmRpZGF0ZV8tPmxvZ01WV2FzRGlzcXVhbGlmaWVkMSgidGFibGUgJXMgY2Fubm90IGJlIGJhY2stam9pbmVkLiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhYmxlLT5nZXRUYWJsZU5hbWUoKS5kYXRhKCkpOwogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CgogICAgLy8gQWRkIHRoZSBUYWJsZSBlbGVtZW50IHRvIHRoZSBUYWJsZUxpc3QuCiAgICBRUlRhYmxlUHRyIG5ld1RhYmxlRWxlbWVudCA9IG5ldyAoaGVhcF8pIFFSVGFibGUoQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICAgIG5ld1RhYmxlRWxlbWVudC0+c2V0VGFibGVOYW1lKHRhYmxlLT5nZXRUYWJsZU5hbWUoKSk7CiAgICBuZXdUYWJsZUVsZW1lbnQtPnNldFJlZih0YWJsZS0+Z2V0SUQoKSk7CiAgICByZXN1bHREZXNjLT5hZGRCYWNrSm9pblRhYmxlKG5ld1RhYmxlRWxlbWVudCk7CiAgfQoKICByZXR1cm4gVFJVRTsKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hKb2luUHJlZHM6OmFkZEJhY2tKb2luUHJlZHNGb3JUYWJsZShjb25zdCBRUlRhYmxlUHRyIHRhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRUkNhbmRpZGF0ZVB0ciAgIHJlc3VsdERlc2MpCnsKICBjb25zdCBRUktleVB0ciB0aGVLZXkgPSB0YWJsZS0+Z2V0S2V5KCk7CiAgaWYgKHRoZUtleSA9PSBOVUxMKQogICAgcmV0dXJuIEZBTFNFOwoKICBjb25zdCBCYXNlVGFibGVEZXRhaWxzUHRyIGJhc2VUYWJsZSA9IGNhbmRpZGF0ZV8tPmdldE12VGFibGVGb3JRdWVyeUlEKHRhYmxlLT5nZXRJRCgpKTsKICBjb25zdCBRUlRhYmxlUHRyIG12VGFibGUgPSBiYXNlVGFibGUtPmdldFRhYmxlRWxlbWVudCgpOwogIENvbGxJbmRleCBtYXhFbnRyaWVzID0gdGhlS2V5LT5lbnRyaWVzKCk7CiAgZm9yIChDb2xsSW5kZXggaT0wOyBpPG1heEVudHJpZXM7IGkrKykKICB7CiAgICAvLyBDb25zdHJ1Y3QgdGhlIG5ldyBKb2luUHJlZCBlbGVtZW50CiAgICBRUkpvaW5QcmVkUHRyIGpvaW5QcmVkID0gbmV3KGhlYXBfKSBRUkpvaW5QcmVkKEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CgogICAgUVJDb2x1bW5QdHIga2V5Q29sID0gdGhlS2V5LT5nZXRFbGVtZW50KGkpLT5nZXRSZWZlcmVuY2VkRWxlbWVudCgpLT5kb3duQ2FzdFRvUVJDb2x1bW4oKTsKCiAgICAvLyBDcmVhdGUgdGhlIHRhYmxlIGNvbHVtbiBzaWRlIG9mIHRoZSBqb2luIHByZWQuCiAgICBRUkNvbHVtblB0ciB0YWJsZUNvbHVtbiA9IG5ldyAoaGVhcF8pIFFSQ29sdW1uKEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICB0YWJsZUNvbHVtbi0+c2V0RnVsbHlRdWFsaWZpZWRDb2x1bW5OYW1lKGtleUNvbC0+Z2V0RnVsbHlRdWFsaWZpZWRDb2x1bW5OYW1lKCkpOwogICAgdGFibGVDb2x1bW4tPnNldFJlZihrZXlDb2wtPmdldElEKCkpOwogICAgdGFibGVDb2x1bW4tPnNldFRhYmxlSUQoa2V5Q29sLT5nZXRUYWJsZUlEKCkpOwogICAgam9pblByZWQtPmFkZEVsZW1lbnQodGFibGVDb2x1bW4pOwoKICAgIC8vIENyZWF0ZSB0aGUgTVYgY29sdW1uIHNpZGUgb2YgdGhlIGpvaW4gcHJlZC4KICAgIFFST3V0cHV0UHRyIG12T3V0cHV0ID0gTlVMTDsKICAgIGlmICghaXNQcm92aWRlZENvbHVtbihrZXlDb2wsIG12T3V0cHV0KSkKICAgICAgcmV0dXJuIEZBTFNFOwoKICAgIFFSTVZDb2x1bW5QdHIgbXZDb2x1bW4gPSBuZXcgKGhlYXBfKSBRUk1WQ29sdW1uKEFERF9NRU1DSEVDS19BUkdTKGhlYXBfKSk7CiAgICBtdkNvbHVtbi0+c2V0TVZDb2xOYW1lKG12T3V0cHV0LT5nZXROYW1lKCkpOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgam9pblByZWQtPmFkZEVsZW1lbnQobXZDb2x1bW4pOwoKICAgIC8vIEFkZCB0aGUgbmV3IEpvaW5QcmVkIHRvIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICAgIHJlc3VsdERlc2MtPmFkZEpvaW5QcmVkKGpvaW5QcmVkKTsKICB9CgogIHJldHVybiBUUlVFOwp9CgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyAgQ2xhc3MgTWF0Y2hPdXRlckpvaW5zCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gR28gb3ZlciBldmVyeSB0YWJsZSBpbiB0aGUgaHViIGFuZCBleHRyYWh1YiwgaW4gYm90aCBxdWVyeSBhbmQgTVYsIAovLyBhbmQgY2hlY2sgaWYgdGhleSBhcmUgdGhlIGlubmVyIGNoaWxkIG9mIGEgbGVmdCBqb2luLgovLyBQb3NzaWJpbGl0aWVzIGFyZToKLy8gICAgIFF1ZXJ5ICBNViAgICAgQ2FzZSAgICAgICAgICAgICAgICAgICAgICAgICBSZXN1bHQKLy8gMSAgIE5vICAgICBObyAgICAgTm9ybWFsIGlubmVyIGpvaW4gICAgICAgICAgICBEbyBub3RoaW5nLgovLyAyICAgWWVzICAgIE5vICAgICBMT0ogcXVlcnkgb24gaW5uZXIgam9pbiBNViAgIERpc3F1YWxpZnkuCi8vIDMgICBObyAgICAgWWVzICAgIElubmVyIGpvaW4gcXVlcnkgb24gTE9KIE1WICAgQWRkIE5PVCBOVUxMIHByZWRpY2F0ZS4KLy8gNCAgIFllcyAgICBObyAgICAgQm90aCBxdWVyeSBhbmQgTVYgdXNlIExPSiAgICBEbyBOb3RoaW5nLgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKTkFCb29sZWFuIE1hdGNoT3V0ZXJKb2luczo6bWF0Y2hQYXNzMSgpCnsKICAvLyBRdWljayBzaG9ydGN1dCBjaGVjawogIGlmICghY2FuZGlkYXRlXy0+Z2V0TXZEZXRhaWxzKCktPmdldEpiYkRldGFpbHMoKS0+aGFzTE9KcygpICYmCiAgICAgICFjYW5kaWRhdGVfLT5nZXRRdWVyeUpiYkRldGFpbHMoKS0+aGFzTE9KcygpICkKICB7CiAgICAvLyBOZWl0aGVyIHRoZSBxdWVyeSBub3IgdGhlIE1WIGhhdmUgYW55IExPSnMuCiAgICByZXR1cm4gVFJVRTsKICB9CgogIGNvbnN0IFFSSkJCQ0xpc3RQdHIgIHF1ZXJ5SHViVGFibGVzICAgICAgPSBjYW5kaWRhdGVfLT5nZXRRdWVyeUpiYigpLT5nZXRIdWIoKS0+Z2V0SmJiY0xpc3QoKTsKICBjb25zdCBRUlRhYmxlTGlzdFB0ciBxdWVyeUV4dHJhSHViVGFibGVzID0gY2FuZGlkYXRlXy0+Z2V0UXVlcnlKYmIoKS0+Z2V0RXh0cmFIdWIoKS0+Z2V0VGFibGVMaXN0KCk7CgogIC8vIFByZXBhcmUgYSBsaXN0IG9mIGFsbCBodWIgdGFibGVzIGFuZCB1c2VkIGV4dHJhaHViIHRhYmxlcy4KICBOQVB0ckxpc3Q8UVJUYWJsZVB0cj4gYWxsVGFibGVzKGhlYXBfKTsKICAKICBDb2xsSW5kZXggbWF4RW50cmllcyA9IHF1ZXJ5SHViVGFibGVzLT5lbnRyaWVzKCk7CiAgZm9yIChDb2xsSW5kZXggaT0wOyBpPG1heEVudHJpZXM7IGkrKykKICB7CiAgICBjb25zdCBRUkVsZW1lbnRQdHIgcXVlcnlKQkJDID0gcXVlcnlIdWJUYWJsZXMtPmdldExpc3QoKVtpXTsKICAgIGlmIChxdWVyeUpCQkMtPmdldEVsZW1lbnRUeXBlKCkgIT0gRVRfVGFibGUpCiAgICAgIGNvbnRpbnVlOwogICAgY29uc3QgUVJUYWJsZVB0ciBxdWVyeVRhYmxlID0gcXVlcnlKQkJDLT5kb3duQ2FzdFRvUVJUYWJsZSgpOwogICAgYWxsVGFibGVzLmluc2VydChxdWVyeVRhYmxlKTsKICB9CiAKICBpZiAocXVlcnlFeHRyYUh1YlRhYmxlcykKICB7CiAgICBtYXhFbnRyaWVzID0gcXVlcnlFeHRyYUh1YlRhYmxlcy0+ZW50cmllcygpOwogICAgZm9yIChDb2xsSW5kZXggaT0wOyBpPG1heEVudHJpZXM7IGkrKykKICAgIHsKICAgICAgY29uc3QgUVJUYWJsZVB0ciBxdWVyeVRhYmxlID0gcXVlcnlFeHRyYUh1YlRhYmxlcy0+Z2V0TGlzdCgpW2ldOwogICAgICBpZiAoY2FuZGlkYXRlXy0+aXNBVXNlZEV4dHJhSHViVGFibGUoJnF1ZXJ5VGFibGUtPmdldElEKCkpKQogICAgICAgIGFsbFRhYmxlcy5pbnNlcnQocXVlcnlUYWJsZSk7CiAgICB9CiAgfQoKICAvLyBOb3cgZ28gb3ZlciB0aGUgdGFibGVzIGluIHRoZSBsaXN0CiAgbWF4RW50cmllcyA9IGFsbFRhYmxlcy5lbnRyaWVzKCk7CiAgZm9yIChDb2xsSW5kZXggaj0wOyBqPG1heEVudHJpZXM7IGorKykKICB7CiAgICAvLyBHZXQgdGhlIExPSiBmbGFnCiAgICBjb25zdCBRUlRhYmxlUHRyIHF1ZXJ5VGFibGUgPSBhbGxUYWJsZXNbal07CiAgICBOQUJvb2xlYW4gcXVlcnlUYWJsZUlzTE9KID0gcXVlcnlUYWJsZS0+aGFzTE9KUGFyZW50KCk7CiAgICBjb25zdCBCYXNlVGFibGVEZXRhaWxzUHRyIG12VGFibGVEZXRhaWxzID0gY2FuZGlkYXRlXy0+Z2V0TXZUYWJsZUZvclF1ZXJ5SUQocXVlcnlUYWJsZS0+Z2V0SUQoKSwgRkFMU0UpOwogICAgaWYgKG12VGFibGVEZXRhaWxzID09IE5VTEwpCiAgICAgIGNvbnRpbnVlOyAvLyBJdHMgYW4gT3V0c2lkZSB0YWJsZSAobm90IHVzZWQgYnkgdGhlIE1WKS4KCiAgICBjb25zdCBRUlRhYmxlUHRyIG12VGFibGUgPSBtdlRhYmxlRGV0YWlscy0+Z2V0VGFibGVFbGVtZW50KCk7CiAgICBOQUJvb2xlYW4gbXZUYWJsZUlzTE9KID0gbXZUYWJsZS0+aGFzTE9KUGFyZW50KCk7CiAgICAKICAgIC8vIENoZWNrIHRoZSBSZXN1bHQKICAgIGlmIChxdWVyeVRhYmxlSXNMT0ogJiYgIW12VGFibGVJc0xPSikKICAgIHsKICAgICAgY2FuZGlkYXRlXy0+bG9nTVZXYXNEaXNxdWFsaWZpZWQxKCJUYWJsZSAlcyBpcyBhbiBpbm5lciB0YWJsZSBvZiBhbiBvdXRlciBqb2luIGluIHRoZSBxdWVyeSBidXQgbm90IGluIHRoZSBNVi4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdWVyeVRhYmxlLT5nZXRUYWJsZU5hbWUoKS5kYXRhKCkpOwogICAgICByZXR1cm4gRkFMU0U7CiAgICB9CiAgICAKICAgIGlmICghcXVlcnlUYWJsZUlzTE9KICYmIG12VGFibGVJc0xPSikKICAgIHsKICAgICAgcmV0dXJuIGFkZFRoZU5vdE51bGxQcmVkKHF1ZXJ5VGFibGUsIG12VGFibGVEZXRhaWxzKTsKICAgIH0gICAgCiAgfQogIHJldHVybiBUUlVFOwp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gVGFrZSB0aGUgcXVlcnkgdGFibGUsIGdldCB0aGUga2V5IGNvbHVtbnMsIGFuZCBpdGVyYXRlIG92ZXIgdGhlbSB0byBmaW5kIAovLyBvbmUgdGhhdCBpcyBub3QgbnVsbGFibGUsIGFuZCBhbHNvIHByb3ZpZGVkIGJ5IHRoZSBNVi4KLy8gSWYgZm91bmQgLSBhZGQgdGhlIE5PVCBOT0xMIHByZWRpY2F0ZSBvbiBpdC4KLy8gT3RoZXJ3aXNlIC0gZGlzcXVhbGlmeSB0aGUgTVYuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hPdXRlckpvaW5zOjphZGRUaGVOb3ROdWxsUHJlZChjb25zdCBRUlRhYmxlUHRyIHF1ZXJ5VGFibGUsIGNvbnN0IEJhc2VUYWJsZURldGFpbHNQdHIgbXZUYWJsZURldGFpbHMpCnsKICBjb25zdCBFbGVtZW50UHRyTGlzdCYga2V5Q29sdW1ucyA9IHF1ZXJ5VGFibGUtPmdldEtleSgpLT5nZXRMaXN0KCk7CiAgQ29sbEluZGV4IG1heEVudHJpZXMgPSBrZXlDb2x1bW5zLmVudHJpZXMoKTsKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8bWF4RW50cmllczsgaSsrKQogIHsKICAgIGNvbnN0IFFSQ29sdW1uUHRyIGtleUNvbCA9IGtleUNvbHVtbnNbaV0tPmdldFJlZmVyZW5jZWRFbGVtZW50KCktPmRvd25DYXN0VG9RUkNvbHVtbigpOwogICAgaWYgKGtleUNvbC0+aXNOdWxsYWJsZSgpKSAgLy8gSnVzdCBtYWtpbmcgc3VyZS4uLgogICAgICBjb250aW51ZTsKICAgICAgCiAgICAvLyBNYXliZSB0aGVyZSBhbHJlYWR5IGlzIGEgcmFuZ2UgcHJlZGljYXRlIHRoYXQgZG9lcyBub3QgYWxsb3cgbnVsbHM/CiAgICBjb25zdCBRUlJhbmdlUHJlZFB0ciByYW5nZVByZWQgPSBtdlRhYmxlRGV0YWlscy0+Z2V0UmFuZ2VDb2x1bW5QcmVkaWNhdGVzRm9yKGtleUNvbC0+Z2V0Q29sSW5kZXgoKSk7CiAgICBpZiAocmFuZ2VQcmVkICE9IE5VTEwpCiAgICB7CiAgICAgIGNvbnN0IFJhbmdlU3BlYyogcmFuZ2VTcGVjID0gcmFuZ2VQcmVkLT5nZXRSYW5nZVNwZWMoaGVhcF8pOwogICAgICBpZiAoIXJhbmdlU3BlYy0+aXNOdWxsSW5jbHVkZWQoKSkKICAgICAgewogICAgICAJLy8gVGhlIHF1ZXJ5IGFscmVhZHkgaGFzIGEgcmFuZ2UgcHJlZGljYXRlIG9uIHRoaXMgY29sdW1uIHRoYXQgCiAgICAgIAkvLyBkb2VzIG5vdCBhbGxvdyBudWxscywgc28gdGhlcmUgaXMgbm8gbmVlZCB0byBhZGQgaXQuCiAgICAgIAlyZXR1cm4gVFJVRTsKICAgICAgfQkKICAgIH0KCiAgICAvLyBObyBzdWNoIHJhbmdlIHByZWRpY2F0ZSBmb3VuZC4gV2UgbmVlZCB0byBhZGQgdGhlIE5PVCBOVUxMIHByZWRpY2F0ZS4KICAgIC8vIElzIHRoZSBjb2x1bW4gUHJvdmlkZWQgYnkgdGhlIE1WPwogICAgUVJPdXRwdXRQdHIgbXZDb2wgPSBOVUxMOwogICAgaWYgKCFpc1Byb3ZpZGVkQ29sdW1uKGtleUNvbCwgbXZDb2wpKQogICAgICBjb250aW51ZTsKICAgIAogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IG5ldyhoZWFwXykgCiAgICAgIFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtKGtleUNvbCwgbXZDb2wsIFJDX1BST1ZJREVELCBSU19GSU5BTCwgQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICAgIGFkZFJld3JpdGVJbnN0cnVjdGlvbnMocmV3cml0ZSk7CiAgICAKICAgIHJldHVybiBUUlVFOwogIH0KICAKICBjYW5kaWRhdGVfLT5sb2dNVldhc0Rpc3F1YWxpZmllZDEoInRhYmxlICVzIGtleSBjb2x1bW5zIGFyZSBub3QgcHJvdmlkZWQgZm9yIE5PVCBOVUxMIHByZWRpY2F0ZS4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5VGFibGUtPmdldFRhYmxlTmFtZSgpLmRhdGEoKSk7CiAgcmV0dXJuIEZBTFNFOyAvLyBObyBlbGlnaWJsZSBrZXkgY29sdW1uIGZvdW5kLgp9CgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKLy8gTm90IHVzZWQuCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpOQUJvb2xlYW4gTWF0Y2hPdXRlckpvaW5zOjptYXRjaFBhc3MyT25FbGVtZW50KFJld3JpdGVJbnN0cnVjdGlvbnNJdGVtUHRyIHBlbmRpbmcpCnsKICByZXR1cm4gVFJVRTsKfQoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi8vIEZvciBlYWNoIGNvbHVtbiBpbiB0aGUgcmV3cml0ZSBpbnN0cnVjdGlvbnMsIGFkZCBhIE5PVCBOVUxMIHJhbmdlIHByZWRpY2F0ZS4KLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCk5BQm9vbGVhbiBNYXRjaE91dGVySm9pbnM6OmdlbmVyYXRlRGVzY3JpcHRvcihRUkNhbmRpZGF0ZVB0ciByZXN1bHREZXNjKQp7CiAgUVJSYW5nZVByZWRMaXN0UHRyIHJhbmdlUHJlZGljYXRlcyA9IHJlc3VsdERlc2MtPmdldFJhbmdlUHJlZExpc3QoKTsKICAKICBSZXdyaXRlSW5zdHJ1Y3Rpb25zSXRlbUxpc3QmIHJld3JpdGVMaXN0ID0gZ2V0TGlzdE9mRmluYWxJbnN0cnVjdGlvbnMoKTsKICBmb3IgKENvbGxJbmRleCBpPTA7IGk8cmV3cml0ZUxpc3QuZW50cmllcygpOyBpKyspCiAgewogICAgUmV3cml0ZUluc3RydWN0aW9uc0l0ZW1QdHIgcmV3cml0ZSA9IHJld3JpdGVMaXN0W2ldOwoKICAgIC8vIENvbnN0cnVjdCB0aGUgbmV3IFJhbmdlIGVsZW1lbnQKICAgIFFSUmFuZ2VQcmVkUHRyIHJhbmdlRWxlbWVudCA9IG5ldyhoZWFwXykgUVJSYW5nZVByZWQoQUREX01FTUNIRUNLX0FSR1MoaGVhcF8pKTsKICAgIC8vIFNldCB0aGUgcmVzdWx0IGF0dHJpYnV0ZS4KICAgIHJhbmdlRWxlbWVudC0+c2V0UmVzdWx0KFFSRWxlbWVudDo6Tm90UHJvdmlkZWQpOwogICAgLy8gRG8gdGhlIHJhbmdlIGl0ZW0gLSB0aGUgTVYgY29sdW1uLgogICAgUVJNVkNvbHVtblB0ciByYW5nZUl0ZW0gPSBnZW5lcmF0ZVByb3ZpZGVkTXZDb2x1bW4ocmV3cml0ZSk7CiAgICByYW5nZUVsZW1lbnQtPnNldFJhbmdlSXRlbShyYW5nZUl0ZW0pOwoKICAgIC8vIERvbid0IGFkZCBhIFJhbmdlU3BlYyAtIGFuIGVtcHR5IHJhbmdlIG1lYW5zIE5PVCBOVUxMLgogICAgLy8gQWRkIGl0IHRvIHRoZSByZXN1bHQgZGVzY3JpcHRvci4KICAgIHJhbmdlUHJlZGljYXRlcy0+YWRkSXRlbShyYW5nZUVsZW1lbnQpOwogIH0KICAKICByZXR1cm4gVFJVRTsKfQoKLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gIENsYXNzIEFnZ3JlZ2F0ZUNvbGxlY3RvclZpc2l0b3IKLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCi8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKVmlzaXRvcjo6VmlzaXRSZXN1bHQgQWdncmVnYXRlQ29sbGVjdG9yVmlzaXRvcjo6dmlzaXQoUVJFbGVtZW50UHRyIGNhbGxlcikKewogIHN3aXRjaChjYWxsZXItPmdldEVsZW1lbnRUeXBlKCkpCiAgewogICAgY2FzZSBFVF9GdW5jdGlvbjoKICAgIHsKICAgICAgUVJGdW5jdGlvblB0ciBmdW5jID0gY2FsbGVyLT5kb3duQ2FzdFRvUVJGdW5jdGlvbigpOwogICAgICBpZiAoZnVuYy0+aXNBbkFnZ3JlZ2F0ZSgpKQogICAgICB7CiAgICAgICAgYWdncmVnYXRlRnVuY3Rpb25zXy5pbnNlcnQoZnVuYyk7CiAgICAgICAgcmV0dXJuIFZSX1NraXA7CiAgICAgIH0KICAgIH0KICAgIGJyZWFrOwoKICAgIGNhc2UgRVRfQ29sdW1uOgogICAgICBzaW1wbGVDb2x1bW5zXy5pbnNlcnQoY2FsbGVyLT5kb3duQ2FzdFRvUVJDb2x1bW4oKSk7CiAgICAgIHJldHVybiBWUl9Ta2lwOwogICAgICBicmVhazsKCiAgICBjYXNlIEVUX0pvaW5QcmVkOgogICAgICBqb2luZWRDb2x1bW5zXy5pbnNlcnQoY2FsbGVyLT5kb3duQ2FzdFRvUVJKb2luUHJlZCgpKTsKICAgICAgcmV0dXJuIFZSX1NraXA7CiAgICAgIGJyZWFrOwogIH0KCiAgcmV0dXJuIFZSX0NvbnRpbnVlOwp9CiAK