LyoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqIENvcHlyaWdodCAoQykgMTk5Ni0xOTk5LCBJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uIGFuZCAgICAqCiogb3RoZXJzLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqLwovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci8vCi8vIEZpbGUgY29sZWl0ci5jcHAKLy8KLy8gCi8vCi8vIENyZWF0ZWQgYnk6IEhlbGVuYSBTaGloCi8vCi8vIE1vZGlmaWNhdGlvbiBIaXN0b3J5OgovLwovLyAgRGF0ZSAgICAgICAgIE5hbWUgICAgICAgICAgRGVzY3JpcHRpb24KLy8KLy8gIDYvMjMvOTcgICAgIGhlbGVuYSAgICAgIEFkZGluZyBjb21tZW50cyB0byBtYWtlIGNvZGUgbW9yZSByZWFkYWJsZS4KLy8gMDgvMDMvOTggICAgIGVybSAgICAgICAgIFN5bmNoZWQgd2l0aCAxLjIgdmVyc2lvbiBvZiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IuamF2YQovLyAxMi8xMC85OSAgICAgIGFsaXUgICAgICAgICAgUG9ydGVkIFRoYWkgY29sbGF0aW9uIHN1cHBvcnQgZnJvbSBKYXZhLgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojaW5jbHVkZSAidW5pY29kZS9zb3J0a2V5LmgiCiNpbmNsdWRlICJ1bmljb2RlL2NvbGVpdHIuaCIKCiNpbmNsdWRlICJ1bmljb2RlL2NoYXJpdGVyLmgiCiNpbmNsdWRlICJ0YWJsZXMuaCIKI2luY2x1ZGUgInVuaWNvZGUvbm9ybWx6ci5oIgojaW5jbHVkZSAidW5pY29kZS91bmljb2RlLmgiCiNpbmNsdWRlICJ0Y29sZGF0YS5oIgojaW5jbHVkZSAidWNtcDMyLmgiCgoKaW50MzJfdCBjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUiA9IDB4ZmZmZmZmZmY7CmludDMyX3QgY29uc3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpVTk1BUFBFRENIQVJWQUxVRSA9IDB4N2ZmZjAwMDA7CgoKLy8gVGhpcyBwcml2YXRlIG1ldGhvZCB3aWxsIG5ldmVyIGJlIGNhbGxlZCwgYnV0IGl0IG1ha2VzIHRoZSBsaW5rZXIgaGFwcHkKCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6Q29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKCkKOiBleHBJbmRleCgwKSwKICB0ZXh0KDApLAogIGJ1ZmZlckFsaWFzKDApLAogIG93bkJ1ZmZlcihuZXcgVmVjdG9yT2ZJbnQoMikpLAogIHJlb3JkZXJCdWZmZXIoMCksCiAgb3JkZXJBbGlhcygwKQp7Cn0KCi8vIFRoaXMgcHJpdmF0ZSBtZXRob2Qgd2lsbCBuZXZlciBiZSBjYWxsZWQsIGJ1dCBpdCBtYWtlcyB0aGUgbGlua2VyIGhhcHB5CgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcihjb25zdCBSdWxlQmFzZWRDb2xsYXRvciogb3JkZXIpCjogZXhwSW5kZXgoMCksCiAgdGV4dCgwKSwKICBidWZmZXJBbGlhcygwKSwKICBvd25CdWZmZXIobmV3IFZlY3Rvck9mSW50KDIpKSwKICByZW9yZGVyQnVmZmVyKDApLAogIG9yZGVyQWxpYXMob3JkZXIpCnsKfQoKLy8gVGhpcyBpcyB0aGUgInJlYWwiIGNvbnN0cnVjdG9yIGZvciB0aGlzIGNsYXNzOyBpdCBjb25zdHJ1Y3RzIGFuIGl0ZXJhdG9yCi8vIG92ZXIgdGhlIHNvdXJjZSB0ZXh0IHVzaW5nIHRoZSBzcGVjaWZpZWQgY29sbGF0b3IKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IoIGNvbnN0IFVuaWNvZGVTdHJpbmcmIHNvdXJjZVRleHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBSdWxlQmFzZWRDb2xsYXRvciogb3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIAo6IGV4cEluZGV4KDApLCAKICB0ZXh0KE5VTEwpLAogIGJ1ZmZlckFsaWFzKE5VTEwpLAogIG93bkJ1ZmZlcihuZXcgVmVjdG9yT2ZJbnQoMikpLAogIHJlb3JkZXJCdWZmZXIoMCksCiAgb3JkZXJBbGlhcyhvcmRlcikKewogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKSB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmICggc291cmNlVGV4dC5sZW5ndGgoKSAhPSAwICkgewogICAgICAgIC8vCiAgICAgICAgLy8gQSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgaXMgcmVhbGx5IGEgdHdvLWxheWVyZWQgYmVhc3QuCiAgICAgICAgLy8gSW50ZXJuYWxseSBpdCB1c2VzIGEgTm9ybWFsaXplciB0byBtdW5nZSB0aGUgc291cmNlIHRleHQKICAgICAgICAvLyBpbnRvIGEgZm9ybSB3aGVyZSBhbGwgImNvbXBvc2VkIiBVbmljb2RlIGNoYXJhY3RlcnMgKHN1Y2ggYXMg/CkgYXJlCiAgICAgICAgLy8gc3BsaXQgaW50byBhIG5vcm1hbCBjaGFyYWN0ZXIgYW5kIGEgY29tYmluaW5nIGFjY2VudCBjaGFyYWN0ZXIuICAKICAgICAgICAvLyBBZnRlcndhcmQsIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBkb2VzIGl0cyBvd24gcHJvY2Vzc2luZyB0byBoYW5kbGUKICAgICAgICAvLyBleHBhbmRpbmcgYW5kIGNvbnRyYWN0aW5nIGNvbGxhdGlvbiBzZXF1ZW5jZXMsIGlnbm9yYWJsZXMsIGFuZCBzbyBvbi4KICAgICAgICAvLwogICAgICBOb3JtYWxpemVyOjpFTW9kZSBkZWNvbXAgPSAob3JkZXItPmdldFN0cmVuZ3RoKCkgPT0gQ29sbGF0b3I6OklERU5USUNBTCkKICAgID8gTm9ybWFsaXplcjo6Tk9fT1AKICAgIDogb3JkZXItPmdldERlY29tcG9zaXRpb24oKTsKICAgICAgCiAgICAgIHRleHQgPSBuZXcgTm9ybWFsaXplcihzb3VyY2VUZXh0LCBkZWNvbXApOwogICAgICBpZiAodGV4dCA9PSBOVUxMKSB7CiAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICB9CiAgICB9Cn0KCgovLyBUaGlzIGlzIHRoZSAicmVhbCIgY29uc3RydWN0b3IgZm9yIHRoaXMgY2xhc3M7IGl0IGNvbnN0cnVjdHMgYW4gaXRlcmF0b3IKLy8gb3ZlciB0aGUgc291cmNlIHRleHQgdXNpbmcgdGhlIHNwZWNpZmllZCBjb2xsYXRvcgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciggY29uc3QgQ2hhcmFjdGVySXRlcmF0b3ImIHNvdXJjZVRleHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBSdWxlQmFzZWRDb2xsYXRvciogb3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIAo6IGV4cEluZGV4KDApLCAKICB0ZXh0KE5VTEwpLAogIGJ1ZmZlckFsaWFzKE5VTEwpLAogIG93bkJ1ZmZlcihuZXcgVmVjdG9yT2ZJbnQoMikpLAogIHJlb3JkZXJCdWZmZXIoMCksCiAgb3JkZXJBbGlhcyhvcmRlcikKewogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKSB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vICoqKiogc2hvdWxkIEkganVzdCBkcm9wIHRoaXMgdGVzdD8gKioqKgogICAgaWYgKCBzb3VyY2VUZXh0LmVuZEluZGV4KCkgIT0gMCApCiAgICB7CiAgICAgICAgLy8KICAgICAgICAvLyBBIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBpcyByZWFsbHkgYSB0d28tbGF5ZXJlZCBiZWFzdC4KICAgICAgICAvLyBJbnRlcm5hbGx5IGl0IHVzZXMgYSBOb3JtYWxpemVyIHRvIG11bmdlIHRoZSBzb3VyY2UgdGV4dAogICAgICAgIC8vIGludG8gYSBmb3JtIHdoZXJlIGFsbCAiY29tcG9zZWQiIFVuaWNvZGUgY2hhcmFjdGVycyAoc3VjaCBhcyD8KSBhcmUKICAgICAgICAvLyBzcGxpdCBpbnRvIGEgbm9ybWFsIGNoYXJhY3RlciBhbmQgYSBjb21iaW5pbmcgYWNjZW50IGNoYXJhY3Rlci4gIAogICAgICAgIC8vIEFmdGVyd2FyZCwgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yIGRvZXMgaXRzIG93biBwcm9jZXNzaW5nIHRvIGhhbmRsZQogICAgICAgIC8vIGV4cGFuZGluZyBhbmQgY29udHJhY3RpbmcgY29sbGF0aW9uIHNlcXVlbmNlcywgaWdub3JhYmxlcywgYW5kIHNvIG9uLgogICAgICAgIC8vCiAgICAgIE5vcm1hbGl6ZXI6OkVNb2RlIGRlY29tcCA9IG9yZGVyLT5nZXRTdHJlbmd0aCgpID09IENvbGxhdG9yOjpJREVOVElDQUwKICAgICAgICA/IE5vcm1hbGl6ZXI6Ok5PX09QCiAgICAgICAgOiBvcmRlci0+Z2V0RGVjb21wb3NpdGlvbigpOwogICAgICAKICAgICAgdGV4dCA9IG5ldyBOb3JtYWxpemVyKHNvdXJjZVRleHQsIGRlY29tcCk7CiAgICAgIGlmICh0ZXh0ID09IE5VTEwpIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICB9CiAgICB9Cn0KCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6Q29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKGNvbnN0ICAgIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciYgb3RoZXIpCiAgICA6IGV4cEluZGV4KG90aGVyLmV4cEluZGV4KSwgdGV4dCgwKSwKICAgICAgb3duQnVmZmVyKG5ldyBWZWN0b3JPZkludCgyKSksCiAgICAgIHJlb3JkZXJCdWZmZXIoMCkKewogICAgKnRoaXMgPSBvdGhlcjsKfQoKY29uc3QgICBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3ImCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6b3BlcmF0b3I9KGNvbnN0ICAgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yJiBvdGhlcikKewogICAgaWYgKHRoaXMgIT0gJm90aGVyKQogICAgewogICAgICAgIGV4cEluZGV4ID0gb3RoZXIuZXhwSW5kZXg7CgogICAgICAgIGRlbGV0ZSB0ZXh0OwogICAgICAgIHRleHQgPSAoTm9ybWFsaXplciopb3RoZXIudGV4dC0+Y2xvbmUoKTsKCiAgICAgICAgaWYgKG90aGVyLmJ1ZmZlckFsaWFzID09IG90aGVyLm93bkJ1ZmZlcikgewogICAgICAgICAgICAqb3duQnVmZmVyID0gKm90aGVyLm93bkJ1ZmZlcjsKICAgICAgICAgICAgYnVmZmVyQWxpYXMgPSBvd25CdWZmZXI7CiAgICAgICAgfSBlbHNlIGlmIChvdGhlci5idWZmZXJBbGlhcyAhPSBOVUxMICYmCiAgICAgICAgICAgICAgICAgICBvdGhlci5idWZmZXJBbGlhcyA9PSBvdGhlci5yZW9yZGVyQnVmZmVyKSB7CiAgICAgICAgICAgIGlmIChyZW9yZGVyQnVmZmVyID09IE5VTEwpIHsKICAgICAgICAgICAgICAgIHJlb3JkZXJCdWZmZXIgPSBuZXcgVmVjdG9yT2ZJbnQoKm90aGVyLnJlb3JkZXJCdWZmZXIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgKnJlb3JkZXJCdWZmZXIgPSAqb3RoZXIucmVvcmRlckJ1ZmZlcjsKICAgICAgICAgICAgfQogICAgICAgICAgICBidWZmZXJBbGlhcyA9IHJlb3JkZXJCdWZmZXI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYnVmZmVyQWxpYXMgPSBvdGhlci5idWZmZXJBbGlhczsKICAgICAgICB9CiAgICAgICAgb3JkZXJBbGlhcyA9IG90aGVyLm9yZGVyQWxpYXM7CiAgICB9CgogICAgcmV0dXJuICp0aGlzOwp9CgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6On5Db2xsYXRpb25FbGVtZW50SXRlcmF0b3IoKQp7CiAgICBkZWxldGUgdGV4dDsKICAgIHRleHQgPSBOVUxMOwogICAgYnVmZmVyQWxpYXMgPSBOVUxMOwogICAgb3JkZXJBbGlhcyA9IE5VTEw7CiAgICBkZWxldGUgb3duQnVmZmVyOwogICAgZGVsZXRlIHJlb3JkZXJCdWZmZXI7Cn0KClVCb29sCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6b3BlcmF0b3I9PShjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3ImIHRoYXQpIGNvbnN0CnsKICAgIGlmICh0aGlzID09ICZ0aGF0KQogICAgewogICAgICAgIHJldHVybiBUUlVFOwogICAgfQoKICAgIGlmICgqdGV4dCAhPSAqKHRoYXQudGV4dCkpCiAgICB7CiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQoKICAgIGlmICgoKGJ1ZmZlckFsaWFzID09IE5VTEwpICE9ICh0aGF0LmJ1ZmZlckFsaWFzID09IE5VTEwpKSB8fAogICAgICAgIChidWZmZXJBbGlhcyAhPSBOVUxMICYmICpidWZmZXJBbGlhcyAhPSAqKHRoYXQuYnVmZmVyQWxpYXMpKSkKICAgIHsKICAgICAgICByZXR1cm4gRkFMU0U7CiAgICB9CgogICAgaWYgKGV4cEluZGV4ICE9IHRoYXQuZXhwSW5kZXgpCiAgICB7CiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQoKICAgIGlmIChvcmRlckFsaWFzICE9IHRoYXQub3JkZXJBbGlhcykKICAgIHsKICAgICAgICByZXR1cm4gRkFMU0U7CiAgICB9CgogICAgcmV0dXJuIFRSVUU7Cn0KClVCb29sCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6b3BlcmF0b3IhPShjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3ImIG90aGVyKSBjb25zdAp7CiAgICByZXR1cm4gISgqdGhpcyA9PSBvdGhlcik7Cn0KCi8qKgogKiBSZXNldHMgdGhlIGN1cnNvciB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzdHJpbmcuCiAqLwp2b2lkIApDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnJlc2V0KCkKewogIGlmICh0ZXh0ICE9IE5VTEwpCiAgICB7CiAgICAgIHRleHQtPnJlc2V0KCk7CiAgICAgIHRleHQtPnNldE1vZGUob3JkZXJBbGlhcy0+Z2V0RGVjb21wb3NpdGlvbigpKTsKICAgIH0KCiAgYnVmZmVyQWxpYXMgPSBOVUxMOwogIGV4cEluZGV4ID0gMDsKfQoKLy8gU2V0cyB0aGUgc291cmNlIHRvIHRoZSBuZXcgc291cmNlIHN0cmluZy4Kdm9pZApDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNldFRleHQoY29uc3QgVW5pY29kZVN0cmluZyYgIHNvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmICAgICAgc3RhdHVzKQp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGJ1ZmZlckFsaWFzID0gMDsKCiAgICBpZiAodGV4dCA9PSBOVUxMKQogICAgewogICAgICAgIHRleHQgPSBuZXcgTm9ybWFsaXplcihzb3VyY2UsIG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgdGV4dC0+c2V0VGV4dChzb3VyY2UsIHN0YXR1cyk7CiAgICAgICAgdGV4dC0+c2V0TW9kZShvcmRlckFsaWFzLT5nZXREZWNvbXBvc2l0aW9uKCkpOwogICAgfQp9CgovLyBTZXRzIHRoZSBzb3VyY2UgdG8gdGhlIG5ldyBjaGFyYWN0ZXIgaXRlcmF0b3IuCnZvaWQKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzZXRUZXh0KENoYXJhY3Rlckl0ZXJhdG9yJiAgc291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkgewogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBidWZmZXJBbGlhcyA9IDA7CgogICAgaWYgKHRleHQgPT0gTlVMTCkgewogICAgICAgIHRleHQgPSBuZXcgTm9ybWFsaXplcihzb3VyY2UsIG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgdGV4dC0+c2V0TW9kZShvcmRlckFsaWFzLT5nZXREZWNvbXBvc2l0aW9uKCkpOwogICAgICAgIHRleHQtPnNldFRleHQoc291cmNlLCBzdGF0dXMpOwogICAgfQp9CgovKioKICogR2V0IHRoZSBvcmRlcmluZyBwcmlvcml0eSBvZiB0aGUgbmV4dCBjaGFyYWN0ZXIgaW4gdGhlIHN0cmluZy4KICogQHJldHVybiB0aGUgbmV4dCBjaGFyYWN0ZXIncyBvcmRlcmluZy4gIFJldHVybnMgTlVMTE9SREVSIGlmCiAqIHRoZSBlbmQgb2Ygc3RyaW5nIGlzIHJlYWNoZWQuCiAqLwppbnQzMl90CkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6bmV4dChVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmICh0ZXh0ID09IE5VTEwgfHwgVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIE5VTExPUkRFUjsKICAgIH0KCiAgICAvLyBVcGRhdGUgdGhlIGRlY29tcG9zaXRpb24gbW9kZSBpZiBuZWNlc3NhcnkuCiAgICB0ZXh0LT5zZXRNb2RlKG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CiAgICAKICAgIGlmIChidWZmZXJBbGlhcyAhPSBOVUxMKQogICAgewogICAgICAgIC8vIGJ1ZmZlckFsaWFzIG5lZWRzIGEgYml0IG9mIGFuIGV4cGxhbmF0aW9uLgogICAgICAgIC8vIFdoZW4gd2UgaGl0IGFuIGV4cGFuZGluZyBjaGFyYWN0ZXIgaW4gdGhlIHRleHQsIHdlIGNhbGwgdGhlIG9yZGVyJ3MKICAgICAgICAvLyBnZXRFeHBhbmRWYWx1ZXMgbWV0aG9kIHRvIHJldHJpZXZlIGFuIGFycmF5IG9mIHRoZSBvcmRlcmluZ3MgZm9yIGFsbAogICAgICAgIC8vIG9mIHRoZSBjaGFyYWN0ZXJzIGluIHRoZSBleHBhbnNpb24gKHNlZSB0aGUgZW5kIG9mIHRoaXMgbWV0aG9kKS4KICAgICAgICAvLyBUaGUgZmlyc3Qgb3JkZXJpbmcgaXMgcmV0dXJuZWQsIGFuZCBhbiBhbGlhcyB0byB0aGUgb3JkZXJpbmdzIGFycmF5CiAgICAgICAgLy8gaXMgc2F2ZWQgc28gdGhhdCB0aGUgcmVtYWluaW5nIG9yZGVyaW5ncyBjYW4gYmUgcmV0dXJuZWQgb24gc3Vic2VxdWVudAogICAgICAgIC8vIGNhbGxzIHRvIG5leHQuICBTbywgaWYgdGhlIGV4cGFuZGluZyBidWZmZXIgaXMgbm90IGV4aGF1c3RlZCwgCiAgICAgICAgLy8gYWxsIHdlIGhhdmUgdG8gZG8gaGVyZSBpcyByZXR1cm4gdGhlIG5leHQgb3JkZXJpbmcgaW4gdGhlIGJ1ZmZlci4gIAogICAgICAgIGlmIChleHBJbmRleCA8IGJ1ZmZlckFsaWFzLT5zaXplKCkpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gc3RyZW5ndGhPcmRlcihidWZmZXJBbGlhcy0+YXQoZXhwSW5kZXgrKykpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBidWZmZXJBbGlhcyA9IE5VTEw7CiAgICAgICAgfQogICAgfQoKICAgIC8vIEdldHMgdGhlIG5leHQgY2hhcmFjdGVyIGZyb20gdGhlIHN0cmluZyB1c2luZyBkZWNvbXBvc2l0aW9uIGl0ZXJhdG9yLgogICAgVUNoYXIzMiBjaCA9IHRleHQtPmN1cnJlbnQoKTsKICAgIHRleHQtPm5leHQoKTsKCiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIE5VTExPUkRFUjsKICAgIH0KCiAgICBpZiAoY2ggPT0gTm9ybWFsaXplcjo6RE9ORSkKICAgIHsKICAgICAgICByZXR1cm4gTlVMTE9SREVSOwogICAgfQogICAgCiAgICAvLyBBc2sgdGhlIGNvbGxhdG9yIGZvciB0aGlzIGNoYXJhY3RlcidzIG9yZGVyaW5nLgogICAgLyogVXNlZCB0byBiZSBSdWxlQmFzZWRDb2xsYXRvci5nZXRVbmljb2RlT3JkZXIoKS4gIEl0IAogICAgICAgY2FuJ3QgYmUgaW5saW5lZCBpbiB0Ymxjb2xsLmggZmlsZSB1bmZvcnR1bmF0ZWx5LiAqLwogICAgaW50MzJfdCB2YWx1ZSA9IHVjbXAzMl9nZXQob3JkZXJBbGlhcy0+ZGF0YS0+bWFwcGluZywgY2gpOwoKICAgIGlmICh2YWx1ZSA9PSBSdWxlQmFzZWRDb2xsYXRvcjo6VU5NQVBQRUQpCiAgICB7CiAgICAgICAgLy8gUmV0dXJuZWQgYW4gInVubWFwcGVkIiBmbGFnIGFuZCBzYXZlIHRoZSBjaGFyYWN0ZXIgc28gaXQgY2FuIGJlIAogICAgICAgIC8vIHJldHVybmVkIG5leHQgdGltZSB0aGlzIG1ldGhvZCBpcyBjYWxsZWQuCiAgICAgICAgaWYgKGNoID09IDB4MDAwMCkgcmV0dXJuIGNoOwogICAgICAgIC8vIFx1MDAwMCBpcyBub3QgdmFsaWQgaW4gQysrJ3MgVW5pY29kZVN0cmluZwogICAgICAgIG93bkJ1ZmZlci0+YXQoMCkgPSBVTk1BUFBFRENIQVJWQUxVRTsKICAgICAgICBvd25CdWZmZXItPmF0KDEpID0gY2ggPDwgMTY7CiAgICAgICAgYnVmZmVyQWxpYXMgPSBvd25CdWZmZXI7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICBpZiAodmFsdWUgPj0gUnVsZUJhc2VkQ29sbGF0b3I6OkNPTlRSQUNUQ0hBUklOREVYKSB7CiAgICAgICAgICAgIHZhbHVlID0gbmV4dENvbnRyYWN0Q2hhcihjaCwgc3RhdHVzKTsKICAgICAgICB9CiAgICAgICAgaWYgKHZhbHVlID49IFJ1bGVCYXNlZENvbGxhdG9yOjpFWFBBTkRDSEFSSU5ERVgpIHsKICAgICAgICAgICAgYnVmZmVyQWxpYXMgPSBvcmRlckFsaWFzLT5nZXRFeHBhbmRWYWx1ZUxpc3QodmFsdWUpOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBpZiAoaXNUaGFpUHJlVm93ZWwoY2gpKSB7CiAgICAgICAgICAgIFVDaGFyMzIgY29uc29uYW50ID0gdGV4dC0+bmV4dCgpOwogICAgICAgICAgICBpZiAoaXNUaGFpQmFzZUNvbnNvbmFudChjb25zb25hbnQpKSB7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGJ1ZmZlckFsaWFzID0gbWFrZVJlb3JkZXJlZEJ1ZmZlcigoVUNoYXIpY29uc29uYW50LCB2YWx1ZSwgYnVmZmVyQWxpYXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSwgc3RhdHVzKTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdGV4dC0+cHJldmlvdXMoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBpZiAoYnVmZmVyQWxpYXMgIT0gTlVMTCkgewogICAgICAgIGV4cEluZGV4ID0gMTsKICAgICAgICB2YWx1ZSA9IGJ1ZmZlckFsaWFzLT5hdCgwKTsKICAgIH0KCiAgICByZXR1cm4gc3RyZW5ndGhPcmRlcih2YWx1ZSk7Cn0KCiAvKioKICAqIEdldCB0aGUgb3JkZXJpbmcgcHJpb3JpdHkgb2YgdGhlIHByZXZpb3VzIGNvbGxhdGlvbiBlbGVtZW50IGluIHRoZSBzdHJpbmcuCiAgKiBAcGFyYW0gc3RhdHVzIHRoZSBlcnJvciBjb2RlIHN0YXR1cy4KICAqIEByZXR1cm4gdGhlIHByZXZpb3VzIGVsZW1lbnQncyBvcmRlcmluZy4gIFJldHVybnMgTlVMTE9SREVSIGlmCiAgKiB0aGUgYmVnaW5uaW5nIG9mIHN0cmluZyBpcyByZWFjaGVkLgogICovCmludDMyX3QKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmV2aW91cyhVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmICh0ZXh0ID09IE5VTEwgfHwgVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIE5VTExPUkRFUjsKICAgIH0KCiAgICB0ZXh0LT5zZXRNb2RlKG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CgogICAgaWYgKGJ1ZmZlckFsaWFzICE9IE5VTEwpCiAgICB7CiAgICAgICAgaWYgKGV4cEluZGV4ID4gMCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBzdHJlbmd0aE9yZGVyKGJ1ZmZlckFsaWFzLT5hdCgtLWV4cEluZGV4KSk7CiAgICAgICAgfQoKICAgICAgICBidWZmZXJBbGlhcyA9IE5VTEw7CiAgICB9CgogICAgVUNoYXIzMiBjaCA9IHRleHQtPnByZXZpb3VzKCk7CgogICAgaWYgKGNoID09IE5vcm1hbGl6ZXI6OkRPTkUpCiAgICB7CiAgICAgICAgcmV0dXJuIE5VTExPUkRFUjsKICAgIH0KICAgIC8qIFVzZWQgdG8gYmUgUnVsZUJhc2VkQ29sbGF0b3IuZ2V0VW5pY29kZU9yZGVyKCkuICBJdCAKICAgICAgIGNhbid0IGJlIGlubGluZWQgaW4gdGJsY29sbC5oIGZpbGUgdW5mb3J0dW5hdGVseS4gKi8KICAgIGludDMyX3QgdmFsdWUgPSB1Y21wMzJfZ2V0KG9yZGVyQWxpYXMtPmRhdGEtPm1hcHBpbmcsIGNoKTsKCiAgICBpZiAodmFsdWUgPT0gUnVsZUJhc2VkQ29sbGF0b3I6OlVOTUFQUEVEKQogICAgewogICAgICAgIGlmIChjaCA9PSAweDAwMDApIHJldHVybiBjaDsKICAgICAgICBvd25CdWZmZXItPmF0KDApID0gVU5NQVBQRURDSEFSVkFMVUU7CiAgICAgICAgb3duQnVmZmVyLT5hdCgxKSA9IGNoIDw8IDE2OwogICAgICAgIGJ1ZmZlckFsaWFzID0gb3duQnVmZmVyOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgaWYgKHZhbHVlID49IFJ1bGVCYXNlZENvbGxhdG9yOjpDT05UUkFDVENIQVJJTkRFWCkgewogICAgICAgICAgICB2YWx1ZSA9IHByZXZDb250cmFjdENoYXIoY2gsIHN0YXR1cyk7CiAgICAgICAgfQogICAgICAgIGlmICh2YWx1ZSA+PSBSdWxlQmFzZWRDb2xsYXRvcjo6RVhQQU5EQ0hBUklOREVYKSB7CiAgICAgICAgICAgIGJ1ZmZlckFsaWFzID0gb3JkZXJBbGlhcy0+Z2V0RXhwYW5kVmFsdWVMaXN0KHZhbHVlKTsKICAgICAgICB9CgogICAgICAgIGlmIChpc1RoYWlCYXNlQ29uc29uYW50KGNoKSkgewoKICAgICAgICAgICAgVUNoYXIzMiB2b3dlbCA9IHRleHQtPnByZXZpb3VzKCk7CiAgICAgICAgICAgIGlmIChpc1RoYWlQcmVWb3dlbCh2b3dlbCkpIHsKICAgICAgICAgICAgICAgIGJ1ZmZlckFsaWFzID0gbWFrZVJlb3JkZXJlZEJ1ZmZlcigoVUNoYXIpdm93ZWwsIHZhbHVlLCBidWZmZXJBbGlhcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGQUxTRSwgc3RhdHVzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRleHQtPm5leHQoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBpZiAoYnVmZmVyQWxpYXMgIT0gTlVMTCkgewogICAgICAgIGV4cEluZGV4ID0gYnVmZmVyQWxpYXMtPnNpemUoKS0xOwogICAgICAgIHZhbHVlID0gYnVmZmVyQWxpYXMtPmF0KGV4cEluZGV4KTsKICAgIH0KCiAgICByZXR1cm4gc3RyZW5ndGhPcmRlcih2YWx1ZSk7Cn0KCmludDMyX3QKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzdHJlbmd0aE9yZGVyKGludDMyX3Qgb3JkZXIpIGNvbnN0CnsKICAgIENvbGxhdG9yOjpFQ29sbGF0aW9uU3RyZW5ndGggcyA9IG9yZGVyQWxpYXMtPmdldFN0cmVuZ3RoKCk7CiAgICAvLyBNYXNrIG9mZiB0aGUgdW53YW50ZWQgZGlmZmVyZW5jZXMuCiAgICBpZiAocyA9PSBDb2xsYXRvcjo6UFJJTUFSWSkKICAgIHsKICAgICAgICBvcmRlciAmPSBSdWxlQmFzZWRDb2xsYXRvcjo6UFJJTUFSWURJRkZFUkVOQ0VPTkxZOwogICAgfSBlbHNlIGlmIChzID09IENvbGxhdG9yOjpTRUNPTkRBUlkpCiAgICB7CiAgICAgICAgb3JkZXIgJj0gUnVsZUJhc2VkQ29sbGF0b3I6OlNFQ09OREFSWURJRkZFUkVOQ0VPTkxZOwogICAgfQogICAgcmV0dXJuIG9yZGVyOwp9CgpVVGV4dE9mZnNldApDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OmdldE9mZnNldCgpIGNvbnN0CnsKICAgIC8vIFNpbmNlIHRoZSBEZWNvbXBvc2l0aW9uSXRlcmF0b3IgaXMgZG9pbmcgdGhlIHdvcmsgb2YgaXRlcmF0aW5nIHRocm91Z2gKICAgIC8vIHRoZSB0ZXh0IHN0cmluZywgd2UgY2FuIGp1c3QgYXNrIGl0IHdoYXQgaXRzIG9mZnNldCBpcy4KICAgIHJldHVybiAodGV4dCAhPSBOVUxMKSA/IHRleHQtPmdldEluZGV4KCkgOiAwOwp9Cgp2b2lkIApDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNldE9mZnNldChVVGV4dE9mZnNldCBuZXdPZmZzZXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHRleHQgIT0gTlVMTCkKICAgIHsKICAgICAgICB0ZXh0LT5zZXRJbmRleChuZXdPZmZzZXQpOwogICAgfQoKICAgIGJ1ZmZlckFsaWFzID0gTlVMTDsKfQoKLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gcHJpdmF0ZXMKLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCi8qKgogKiBHZXQgdGhlIG9yZGVyaW5nIHByaW9yaXR5IG9mIHRoZSBuZXh0IGNvbnRyYWN0aW5nIGNoYXJhY3RlciBpbiB0aGUKICogc3RyaW5nLgogKiBAcGFyYW0gY2ggdGhlIHN0YXJ0aW5nIGNoYXJhY3RlciBvZiBhIGNvbnRyYWN0aW5nIGNoYXJhY3RlciB0b2tlbgogKiBAcmV0dXJuIHRoZSBuZXh0IGNvbnRyYWN0aW5nIGNoYXJhY3RlcidzIG9yZGVyaW5nLiAgUmV0dXJucyBOVUxMT1JERVIKICogaWYgdGhlIGVuZCBvZiBzdHJpbmcgaXMgcmVhY2hlZC4KICovCmludDMyX3QKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpuZXh0Q29udHJhY3RDaGFyKFVDaGFyMzIgY2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIC8vIEZpcnN0IGdldCB0aGUgb3JkZXJpbmcgb2YgdGhpcyBzaW5nbGUgY2hhcmFjdGVyCiAgICBWZWN0b3JPZlBUb0NvbnRyYWN0RWxlbWVudCAqbGlzdCA9IG9yZGVyQWxpYXMtPmdldENvbnRyYWN0VmFsdWVzKChVQ2hhciljaCk7CiAgICBFbnRyeVBhaXIgKnBhaXIgPSAoRW50cnlQYWlyICopbGlzdC0+YXQoMCk7CiAgICBpbnQzMl90IG9yZGVyID0gcGFpci0+dmFsdWU7CgogICAgLy8gTm93IGl0ZXJhdGUgdGhyb3VnaCB0aGUgY2hhcnMgZm9sbG93aW5nIGl0IGFuZAogICAgLy8gbG9vayBmb3IgdGhlIGxvbmdlc3QgbWF0Y2gKICAgIGtleS5yZW1vdmUoKTsKICAgIGtleSArPSBjaDsKCiAgICB3aGlsZSAoKGNoID0gdGV4dC0+Y3VycmVudCgpKSAhPSBOb3JtYWxpemVyOjpET05FKQogICAgewogICAgICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBOVUxMT1JERVI7CiAgICAgICAgfQoKICAgICAgICBrZXkgKz0gY2g7CgogICAgICAgIGludDMyX3QgbiA9IFJ1bGVCYXNlZENvbGxhdG9yOjpnZXRFbnRyeShsaXN0LCBrZXksIFRSVUUpOwoKICAgICAgICBpZiAobiA9PSBSdWxlQmFzZWRDb2xsYXRvcjo6VU5NQVBQRUQpCiAgICAgICAgewogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdGV4dC0+bmV4dCgpOwoKICAgICAgICBwYWlyID0gKEVudHJ5UGFpciAqKWxpc3QtPmF0KG4pOwogICAgICAgIG9yZGVyID0gcGFpci0+dmFsdWU7CiAgICB9CgogICAgcmV0dXJuIG9yZGVyOwp9CgovKioKICogR2V0IHRoZSBvcmRlcmluZyBwcmlvcml0eSBvZiB0aGUgcHJldmlvdXMgY29udHJhY3RpbmcgY2hhcmFjdGVyIGluIHRoZQogKiBzdHJpbmcuCiAqIEBwYXJhbSBjaCB0aGUgc3RhcnRpbmcgY2hhcmFjdGVyIG9mIGEgY29udHJhY3RpbmcgY2hhcmFjdGVyIHRva2VuCiAqIEByZXR1cm4gdGhlIG5leHQgY29udHJhY3RpbmcgY2hhcmFjdGVyJ3Mgb3JkZXJpbmcuICBSZXR1cm5zIE5VTExPUkRFUgogKiBpZiB0aGUgZW5kIG9mIHN0cmluZyBpcyByZWFjaGVkLgogKi8KaW50MzJfdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnByZXZDb250cmFjdENoYXIoVUNoYXIzMiBjaCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSAmc3RhdHVzKQp7CiAgICAvLyBGaXJzdCBnZXQgdGhlIG9yZGVyaW5nIG9mIHRoaXMgc2luZ2xlIGNoYXJhY3RlcgogICAgVmVjdG9yT2ZQVG9Db250cmFjdEVsZW1lbnQgKmxpc3QgPSBvcmRlckFsaWFzLT5nZXRDb250cmFjdFZhbHVlcygoVUNoYXIpY2gpOwogICAgRW50cnlQYWlyICpwYWlyID0gKEVudHJ5UGFpciAqKWxpc3QtPmF0KDApOwogICAgaW50MzJfdCBvcmRlciA9IHBhaXItPnZhbHVlOwoKICAgIC8vIE5vdyBpdGVyYXRlIHRocm91Z2ggdGhlIGNoYXJzIGZvbGxvd2luZyBpdCBhbmQKICAgIC8vIGxvb2sgZm9yIHRoZSBsb25nZXN0IG1hdGNoCiAgICBrZXkucmVtb3ZlKCk7CiAgICBrZXkgKz0gY2g7CgogICAgd2hpbGUgKChjaCA9IHRleHQtPnByZXZpb3VzKCkpICE9IE5vcm1hbGl6ZXI6OkRPTkUpCiAgICB7CiAgICAgICAga2V5ICs9IGNoOwoKICAgICAgICBpbnQzMl90IG4gPSBSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0RW50cnkobGlzdCwga2V5LCBGQUxTRSk7CgogICAgICAgIGlmIChuID09IFJ1bGVCYXNlZENvbGxhdG9yOjpVTk1BUFBFRCkKICAgICAgICB7CiAgICAgICAgICAgIGNoID0gdGV4dC0+bmV4dCgpOwoKICAgICAgICAgICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXR1cm4gTlVMTE9SREVSOwogICAgICAgICAgICB9CgogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIHBhaXIgPSAoRW50cnlQYWlyICopbGlzdC0+YXQobik7CiAgICAgICAgb3JkZXIgPSBwYWlyLT52YWx1ZTsKICAgIH0KCiAgICByZXR1cm4gb3JkZXI7Cn0KCi8qKgogKiBUaGlzIG1ldGhvZCBwcm9kdWNlcyBhIGJ1ZmZlciB3aGljaCBjb250YWlucyB0aGUgY29sbGF0aW9uCiAqIGVsZW1lbnRzIGZvciB0aGUgdHdvIGNoYXJhY3RlcnMsIHdpdGggY29sRmlyc3QncyB2YWx1ZXMgcHJlY2VkaW5nCiAqIGFub3RoZXIgY2hhcmFjdGVyJ3MuICBQcmVzdW1hYmx5LCB0aGUgb3RoZXIgY2hhcmFjdGVyIHByZWNlZGVzIGNvbEZpcnN0CiAqIGluIGxvZ2ljYWwKICogb3JkZXIgKG90aGVyd2lzZSB5b3Ugd291bGRuJ3QgbmVlZCB0aGlzIG1ldGhvZCB3b3VsZCB5b3U/KS4KICogVGhlIGFzc3VtcHRpb24gaXMgdGhhdCB0aGUgb3RoZXIgY2hhcidzIHZhbHVlKHMpIGhhdmUgYWxyZWFkeSBiZWVuCiAqIGNvbXB1dGVkLiAgSWYgdGhpcyBjaGFyIGhhcyBhIHNpbmdsZSBlbGVtZW50IGl0IGlzIHBhc3NlZCB0byB0aGlzCiAqIG1ldGhvZCBhcyBsYXN0VmFsdWUsIGFuZCBsYXN0RXhwYXNpb24gaXMgbnVsbC4gIElmIGl0IGhhcyBhbgogKiBleHBhc2lvbiBpdCBpcyBwYXNzZWQgaW4gbGFzdEV4cGFuc2lvbiwgYW5kIGNvbExhc3RWYWx1ZSBpcyBpZ25vcmVkLgogKiBUaGlzIG1ldGhvZCBtYXkgcmV0dXJuIHRoZSBvd25CdWZmZXIgYXJyYXkgYXMgaXRzIHZhbHVlIHNvIG93bkJ1ZmZlcgogKiBoYWQgYmV0dGVyIG5vdCBiZSBpbiB1c2UgYW55d2hlcmUgZWxzZS4KICovClZlY3Rvck9mSW50KiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Om1ha2VSZW9yZGVyZWRCdWZmZXIoVUNoYXIgY29sRmlyc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50MzJfdCBsYXN0VmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVmVjdG9yT2ZJbnQqIGxhc3RFeHBhbnNpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUJvb2wgZm9yd2FyZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIHsKCiAgICBWZWN0b3JPZkludCogcmVzdWx0OwoKICAgIGludDMyX3QgZmlyc3RWYWx1ZSA9IHVjbXAzMl9nZXQob3JkZXJBbGlhcy0+ZGF0YS0+bWFwcGluZywgY29sRmlyc3QpOwogICAgaWYgKGZpcnN0VmFsdWUgPj0gUnVsZUJhc2VkQ29sbGF0b3I6OkNPTlRSQUNUQ0hBUklOREVYKSB7CiAgICAgICAgZmlyc3RWYWx1ZSA9IGZvcndhcmQgPyBuZXh0Q29udHJhY3RDaGFyKGNvbEZpcnN0LCBzdGF0dXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBwcmV2Q29udHJhY3RDaGFyKGNvbEZpcnN0LCBzdGF0dXMpOwogICAgfQoKICAgIFZlY3Rvck9mSW50KiBmaXJzdEV4cGFuc2lvbiA9IE5VTEw7CiAgICBpZiAoZmlyc3RWYWx1ZSA+PSBSdWxlQmFzZWRDb2xsYXRvcjo6RVhQQU5EQ0hBUklOREVYKSB7CiAgICAgICAgZmlyc3RFeHBhbnNpb24gPSBvcmRlckFsaWFzLT5nZXRFeHBhbmRWYWx1ZUxpc3QoZmlyc3RWYWx1ZSk7CiAgICB9CgogICAgaWYgKCFmb3J3YXJkKSB7CiAgICAgICAgaW50MzJfdCB0ZW1wMSA9IGZpcnN0VmFsdWU7CiAgICAgICAgZmlyc3RWYWx1ZSA9IGxhc3RWYWx1ZTsKICAgICAgICBsYXN0VmFsdWUgPSB0ZW1wMTsKICAgICAgICBWZWN0b3JPZkludCogdGVtcDIgPSBmaXJzdEV4cGFuc2lvbjsKICAgICAgICBmaXJzdEV4cGFuc2lvbiA9IGxhc3RFeHBhbnNpb247CiAgICAgICAgbGFzdEV4cGFuc2lvbiA9IHRlbXAyOwogICAgfQoKICAgIGlmIChmaXJzdEV4cGFuc2lvbiA9PSBOVUxMICYmIGxhc3RFeHBhbnNpb24gPT0gTlVMTCkgewogICAgICAgIG93bkJ1ZmZlci0+YXQoMCkgPSBmaXJzdFZhbHVlOwogICAgICAgIG93bkJ1ZmZlci0+YXQoMSkgPSBsYXN0VmFsdWU7CiAgICAgICAgcmVzdWx0ID0gb3duQnVmZmVyOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgaW50MzJfdCBmaXJzdExlbmd0aCA9IGZpcnN0RXhwYW5zaW9uPT1OVUxMPyAxIDogZmlyc3RFeHBhbnNpb24tPnNpemUoKTsKICAgICAgICBpbnQzMl90IGxhc3RMZW5ndGggPSBsYXN0RXhwYW5zaW9uPT1OVUxMPyAxIDogbGFzdEV4cGFuc2lvbi0+c2l6ZSgpOwogICAgICAgIGlmIChyZW9yZGVyQnVmZmVyID09IE5VTEwpIHsKICAgICAgICAgICAgcmVvcmRlckJ1ZmZlciA9IG5ldyBWZWN0b3JPZkludChmaXJzdExlbmd0aCtsYXN0TGVuZ3RoKTsKICAgICAgICB9CiAgICAgICAgLy8gcmVvcmRlcmRCdWZmZXIgZ2V0cyByZXVzZWQgZm9yIHRoZSBsaWZlIG9mIHRoaXMgb2JqZWN0LgogICAgICAgIC8vIFNpbmNlIGl0cyBpbnRlcm5hbCBidWZmZXIgb25seSBncm93cywgdGhlcmUgaXMgYSBkYW5nZXIKICAgICAgICAvLyB0aGF0IGl0IHdpbGwgZ2V0IHJlYWxseSwgcmVhbGx5IGJpZywgYW5kIG5ldmVyIHNocmluay4gIElmCiAgICAgICAgLy8gdGhpcyBpcyBhY3R1YWxseSBoYXBwZW5pbmcsIGluc2VydCBjb2RlIGhlcmUgdG8gY2hlY2sgZm9yCiAgICAgICAgLy8gdGhlIGNvbmRpdGlvbi4gIFNvbWV0aGluZyBhbG9uZyB0aGUgbGluZXMgb2Y6CiAgICAgICAgLy8hIGVsc2UgaWYgKHJlb3JkZXJCdWZmZXItPnNpemUoKSA+PSAyNTYgJiYKICAgICAgICAvLyEgICAgICAgICAgKGZpcnN0TGVuZ3RoK2xhc3RMZW5ndGgpIDwgMTYpIHsKICAgICAgICAvLyEgICAgIGRlbGV0ZSByZW9yZGVyQnVmZmVyOwogICAgICAgIC8vISAgICAgcmVvcmRlckJ1ZmZlciA9IG5ldyBWZWN0b3JPZkludChmaXJzdExlbmd0aCtsYXN0TGVuZ3RoKTsKICAgICAgICAvLyEgfQogICAgICAgIC8vIFRoZSBzcGVjaWZpYyBudW1lcmljIHZhbHVlcyBuZWVkIHRvIGJlIGRldGVybWluZWQKICAgICAgICAvLyBlbXBpcmljYWxseS4gW2FsaXVdCiAgICAgICAgcmVzdWx0ID0gcmVvcmRlckJ1ZmZlcjsKCiAgICAgICAgaWYgKGZpcnN0RXhwYW5zaW9uID09IE5VTEwpIHsKICAgICAgICAgICAgcmVzdWx0LT5hdFB1dCgwLCBmaXJzdFZhbHVlKTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIC8vIFN5c3RlbS5hcnJheWNvcHkoZmlyc3RFeHBhbnNpb24sIDAsIHJlc3VsdCwgMCwgZmlyc3RMZW5ndGgpOwogICAgICAgICAgICAqcmVzdWx0ID0gKmZpcnN0RXhwYW5zaW9uOwogICAgICAgIH0KCiAgICAgICAgaWYgKGxhc3RFeHBhbnNpb24gPT0gTlVMTCkgewogICAgICAgICAgICByZXN1bHQtPmF0UHV0KGZpcnN0TGVuZ3RoLCBsYXN0VmFsdWUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgLy8gU3lzdGVtLmFycmF5Y29weShsYXN0RXhwYW5zaW9uLCAwLCByZXN1bHQsIGZpcnN0TGVuZ3RoLCBsYXN0TGVuZ3RoKTsKICAgICAgICAgICAgZm9yIChpbnQzMl90IGk9MDsgaTxsYXN0TGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgIHJlc3VsdC0+YXRQdXQoZmlyc3RMZW5ndGggKyBpLCBsYXN0RXhwYW5zaW9uLT5hdChpKSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmVzdWx0LT5zZXRTaXplKGZpcnN0TGVuZ3RoK2xhc3RMZW5ndGgpOwogICAgfQoKICAgIHJldHVybiByZXN1bHQ7Cn0K