LyoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqIENvcHlyaWdodCAoQykgMTk5Ni0yMDAxLCBJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uIGFuZCAgICAqCiogb3RoZXJzLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqLwoKLyoKKiBGaWxlIGNvbGVpdHIuY3BwCioKKiAKKgoqIENyZWF0ZWQgYnk6IEhlbGVuYSBTaGloCioKKiBNb2RpZmljYXRpb24gSGlzdG9yeToKKgoqICBEYXRlICAgICAgTmFtZSAgICAgICAgRGVzY3JpcHRpb24KKgoqICA2LzIzLzk3ICAgaGVsZW5hICAgICAgQWRkaW5nIGNvbW1lbnRzIHRvIG1ha2UgY29kZSBtb3JlIHJlYWRhYmxlLgoqIDA4LzAzLzk4ICAgZXJtICAgICAgICAgU3luY2hlZCB3aXRoIDEuMiB2ZXJzaW9uIG9mIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvci5qYXZhCiogMTIvMTAvOTkgICBhbGl1ICAgICAgICBQb3J0ZWQgVGhhaSBjb2xsYXRpb24gc3VwcG9ydCBmcm9tIEphdmEuCiogMDEvMjUvMDEgICBzd3F1ZWsgICAgICBNb2RpZmllZCB0byBhIEMrKyB3cmFwcGVyIGNhbGxpbmcgQyBBUElzICh1Y29saXRlci5oKQoqIDAyLzE5LzAxICAgc3dxdWVrICAgICAgUmVtb3ZlZCBDb2xsYXRpb25FbGVtZW50c0l0ZXJhdG9yKCkgc2luY2UgaXQgaXMgCiogICAgICAgICAgICAgICAgICAgICAgICBwcml2YXRlIGNvbnN0cnVjdG9yIGFuZCBubyBjYWxscyBhcmUgbWFkZSB0byBpdAoqLwoKI2luY2x1ZGUgInVuaWNvZGUvY29sZWl0ci5oIgojaW5jbHVkZSAidWNvbF9pbXAuaCIKI2luY2x1ZGUgImNtZW1vcnkuaCIKI2luY2x1ZGUgInVuaWNvZGUvdXN0cmluZy5oIgoKCi8qIENvbnN0YW50cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCi8qIHN5bndlZSA6IHB1YmxpYyBjYW4ndCByZW1vdmUgKi8KaW50MzJfdCBjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUiA9IDB4ZmZmZmZmZmY7CgovKiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgcHVibGljIGNvbnN0cnVjdG9yL2Rlc3RydWN0b3IgLS0tLS0tLS0tLS0tLS0tLS0tICovCgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3ImIG90aGVyKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGlzRGF0YU93bmVkXyhUUlVFKQp7CiAgVUVycm9yQ29kZSBzdGF0dXMgPSBVX1pFUk9fRVJST1I7CiAgbV9kYXRhXyA9IHVjb2xfb3BlbkVsZW1lbnRzKG90aGVyLm1fZGF0YV8tPml0ZXJhdG9yZGF0YV8uY29sbCwgTlVMTCwgMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICZzdGF0dXMpOwogICp0aGlzID0gb3RoZXI7Cn0KCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6fkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcigpCnsKICBpZiAoaXNEYXRhT3duZWRfKSB7CiAgICB1Y29sX2Nsb3NlRWxlbWVudHMobV9kYXRhXyk7CiAgfQp9CgovKiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgcHVibGljIG1ldGhvZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCgpVVGV4dE9mZnNldCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OmdldE9mZnNldCgpIGNvbnN0CnsKICByZXR1cm4gdWNvbF9nZXRPZmZzZXQobV9kYXRhXyk7Cn0KCi8qKgoqIEdldCB0aGUgb3JkZXJpbmcgcHJpb3JpdHkgb2YgdGhlIG5leHQgY2hhcmFjdGVyIGluIHRoZSBzdHJpbmcuCiogQHJldHVybiB0aGUgbmV4dCBjaGFyYWN0ZXIncyBvcmRlcmluZy4gUmV0dXJucyBOVUxMT1JERVIgaWYgYW4gZXJyb3IgaGFzIAoqICAgICAgICAgb2NjdXJlZCBvciBpZiB0aGUgZW5kIG9mIHN0cmluZyBoYXMgYmVlbiByZWFjaGVkCiovCmludDMyX3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpuZXh0KFVFcnJvckNvZGUmIHN0YXR1cykKewogIHJldHVybiB1Y29sX25leHQobV9kYXRhXywgJnN0YXR1cyk7Cn0KClVCb29sIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6b3BlcmF0b3IhPSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciYgb3RoZXIpIGNvbnN0CnsKICByZXR1cm4gISgqdGhpcyA9PSBvdGhlcik7Cn0KClVCb29sIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6b3BlcmF0b3I9PSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yJiB0aGF0KSBjb25zdAp7CiAgaWYgKHRoaXMgPT0gJnRoYXQpCiAgICByZXR1cm4gVFJVRTsKICAKICBpZiAobV9kYXRhXyA9PSB0aGF0Lm1fZGF0YV8pCiAgICByZXR1cm4gVFJVRTsKCiAgaW50IGxlbmd0aCA9IDA7CiAgaWYgKHRoaXMtPm1fZGF0YV8tPml0ZXJhdG9yZGF0YV8uZmxhZ3MgJiBVQ09MX0lURVJfSEFTTEVOID4gMCkgewogICAgICBsZW5ndGggPSB0aGlzLT5tX2RhdGFfLT5pdGVyYXRvcmRhdGFfLmVuZHAgLQogICAgICAgICAgICAgICB0aGlzLT5tX2RhdGFfLT5pdGVyYXRvcmRhdGFfLnN0cmluZzsKICB9CiAgZWxzZSB7CiAgICAgIGxlbmd0aCA9IHVfc3RybGVuKHRoaXMtPm1fZGF0YV8tPml0ZXJhdG9yZGF0YV8uc3RyaW5nKTsKICB9CiAgCiAgcmV0dXJuICh0aGlzLT5tX2RhdGFfLT5ub3JtYWxpemF0aW9uXyA9PSB0aGF0Lm1fZGF0YV8tPm5vcm1hbGl6YXRpb25fICYmCiAgICB0aGlzLT5tX2RhdGFfLT5yZXNldF8gID09IHRoYXQubV9kYXRhXy0+cmVzZXRfICYmCiAgICB1cHJ2X21lbWNtcCh0aGlzLT5tX2RhdGFfLT5pdGVyYXRvcmRhdGFfLnN0cmluZywgCiAgICAgICAgICAgICAgICB0aGF0Lm1fZGF0YV8tPml0ZXJhdG9yZGF0YV8uc3RyaW5nLCBsZW5ndGgpID09IDAgJiYKICAgIHRoaXMtPmdldE9mZnNldCgpID09IHRoYXQuZ2V0T2Zmc2V0KCkgJiYgIAogICAgLyogdGhpcy0+bV9kYXRhXy0+aXRlcmF0b3JkYXRhXy5pc1RoYWkgPT0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5tX2RhdGFfLT5pdGVyYXRvcmRhdGFfLmlzVGhhaSAmJiAqLwogICAgdGhpcy0+bV9kYXRhXy0+aXRlcmF0b3JkYXRhXy5jb2xsID09IHRoYXQubV9kYXRhXy0+aXRlcmF0b3JkYXRhXy5jb2xsKTsKfQoKLyoqCiogR2V0IHRoZSBvcmRlcmluZyBwcmlvcml0eSBvZiB0aGUgcHJldmlvdXMgY29sbGF0aW9uIGVsZW1lbnQgaW4gdGhlIHN0cmluZy4KKiBAcGFyYW0gc3RhdHVzIHRoZSBlcnJvciBjb2RlIHN0YXR1cy4KKiBAcmV0dXJuIHRoZSBwcmV2aW91cyBlbGVtZW50J3Mgb3JkZXJpbmcuIFJldHVybnMgTlVMTE9SREVSIGlmIGFuIGVycm9yIGhhcyAKKiAgICAgICAgIG9jY3VyZWQgb3IgaWYgdGhlIHN0YXJ0IG9mIHN0cmluZyBoYXMgYmVlbiByZWFjaGVkLgoqLwppbnQzMl90IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6cHJldmlvdXMoVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgcmV0dXJuIHVjb2xfcHJldmlvdXMobV9kYXRhXywgJnN0YXR1cyk7Cn0KCi8qKgoqIFJlc2V0cyB0aGUgY3Vyc29yIHRvIHRoZSBiZWdpbm5pbmcgb2YgdGhlIHN0cmluZy4KKi8Kdm9pZCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnJlc2V0KCkKewogIHVjb2xfcmVzZXQobV9kYXRhXyk7Cn0KCnZvaWQgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzZXRPZmZzZXQoVVRleHRPZmZzZXQgbmV3T2Zmc2V0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICB1Y29sX3NldE9mZnNldChtX2RhdGFfLCBuZXdPZmZzZXQsICZzdGF0dXMpOwp9CgovKioKKiBTZXRzIHRoZSBzb3VyY2UgdG8gdGhlIG5ldyBzb3VyY2Ugc3RyaW5nLgoqLwp2b2lkIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6c2V0VGV4dChjb25zdCBVbmljb2RlU3RyaW5nJiBzb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKewogIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkgewogICAgcmV0dXJuOwogIH0KICBpbnQzMl90IGxlbmd0aCA9IHNvdXJjZS5sZW5ndGgoKTsKICBVQ2hhciAqc3RyaW5nID0gKFVDaGFyICopdXBydl9tYWxsb2Moc2l6ZW9mKFVDaGFyKSAqIGxlbmd0aCk7CiAgc291cmNlLmV4dHJhY3QoMCwgbGVuZ3RoLCBzdHJpbmcpOwoJCiAgaWYgKG1fZGF0YV8tPmlzV3JpdGFibGUgJiYgCiAgICAgIG1fZGF0YV8tPml0ZXJhdG9yZGF0YV8uc3RyaW5nICE9IE5VTEwpIHsKICAgIHVwcnZfZnJlZShtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLnN0cmluZyk7CiAgfQogIG1fZGF0YV8tPmlzV3JpdGFibGUgPSBUUlVFOwogIGluaXRfY29sbEl0ZXJhdGUobV9kYXRhXy0+aXRlcmF0b3JkYXRhXy5jb2xsLCBzdHJpbmcsIGxlbmd0aCwgCiAgICAgICAgICAgICAgICAgICAmbV9kYXRhXy0+aXRlcmF0b3JkYXRhXyk7Cn0KCi8vIFNldHMgdGhlIHNvdXJjZSB0byB0aGUgbmV3IGNoYXJhY3RlciBpdGVyYXRvci4Kdm9pZCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNldFRleHQoQ2hhcmFjdGVySXRlcmF0b3ImIHNvdXJjZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKewogIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkgCiAgICByZXR1cm47CiAgICAKICBpbnQzMl90IGxlbmd0aCA9IHNvdXJjZS5nZXRMZW5ndGgoKTsKICBVQ2hhciAqYnVmZmVyID0gKFVDaGFyICopdXBydl9tYWxsb2Moc2l6ZW9mKFVDaGFyKSAqIGxlbmd0aCk7CiAgLyogCiAgVXNpbmcgdGhpcyBjb25zdHJ1Y3RvciB3aWxsIHByZXZlbnQgYnVmZmVyIGZyb20gYmVpbmcgcmVtb3ZlZCB3aGVuCiAgc3RyaW5nIGdldHMgcmVtb3ZlZAogICovCiAgVW5pY29kZVN0cmluZyBzdHJpbmc7CiAgc291cmNlLmdldFRleHQoc3RyaW5nKTsKICBzdHJpbmcuZXh0cmFjdCgwLCBsZW5ndGgsIGJ1ZmZlcik7CiAgCiAgaWYgKG1fZGF0YV8tPmlzV3JpdGFibGUgJiYgbV9kYXRhXy0+aXRlcmF0b3JkYXRhXy5zdHJpbmcgIT0gTlVMTCkKICAgIHVwcnZfZnJlZShtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLnN0cmluZyk7CiAgbV9kYXRhXy0+aXNXcml0YWJsZSA9IFRSVUU7CiAgaW5pdF9jb2xsSXRlcmF0ZShtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLmNvbGwsIGJ1ZmZlciwgbGVuZ3RoLCAKICAgICAgICAgICAgICAgICAgICZtX2RhdGFfLT5pdGVyYXRvcmRhdGFfKTsKfQoKaW50MzJfdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnN0cmVuZ3RoT3JkZXIoaW50MzJfdCBvcmRlcikgY29uc3QKewogIFVDb2xsYXRpb25TdHJlbmd0aCBzID0gdWNvbF9nZXRTdHJlbmd0aChtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLmNvbGwpOwogIC8vIE1hc2sgb2ZmIHRoZSB1bndhbnRlZCBkaWZmZXJlbmNlcy4KICBpZiAocyA9PSBVQ09MX1BSSU1BUlkpCiAgICBvcmRlciAmPSBSdWxlQmFzZWRDb2xsYXRvcjo6UFJJTUFSWURJRkZFUkVOQ0VPTkxZOwogIGVsc2UgCiAgICBpZiAocyA9PSBVQ09MX1NFQ09OREFSWSkKICAgICAgb3JkZXIgJj0gUnVsZUJhc2VkQ29sbGF0b3I6OlNFQ09OREFSWURJRkZFUkVOQ0VPTkxZOwogICAgCiAgcmV0dXJuIG9yZGVyOwp9CgovKiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgcHJpdmF0ZSBjb25zdHJ1Y3RvcnMvZGVzdHJ1Y3RvcnMgLS0tLS0tLS0tLS0tLS0tICovCgovKiAKVGhpcyBwcml2YXRlIG1ldGhvZCB3aWxsIG5ldmVyIGJlIGNhbGxlZCwgYnV0IGl0IG1ha2VzIHRoZSBsaW5rZXIgaGFwcHkKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IoKSA6IG1fZGF0YV8oMCkKewp9CiovCgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFJ1bGVCYXNlZENvbGxhdG9yKiBvcmRlcikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogaXNEYXRhT3duZWRfKFRSVUUpCnsKICBVRXJyb3JDb2RlIHN0YXR1cyA9IFVfWkVST19FUlJPUjsKICBtX2RhdGFfID0gdWNvbF9vcGVuRWxlbWVudHMob3JkZXItPnVjb2xsYXRvciwgTlVMTCwgMCwgJnN0YXR1cyk7Cn0KCi8qKiAKKiBUaGlzIGlzIHRoZSAicmVhbCIgY29uc3RydWN0b3IgZm9yIHRoaXMgY2xhc3M7IGl0IGNvbnN0cnVjdHMgYW4gaXRlcmF0b3IKKiBvdmVyIHRoZSBzb3VyY2UgdGV4dCB1c2luZyB0aGUgc3BlY2lmaWVkIGNvbGxhdG9yCiovCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6Q29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFVuaWNvZGVTdHJpbmcmIHNvdXJjZVRleHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIG9yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGlzRGF0YU93bmVkXyhUUlVFKQp7CiAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgcmV0dXJuOwogCiAgaW50MzJfdCBsZW5ndGggPSBzb3VyY2VUZXh0Lmxlbmd0aCgpOwogIFVDaGFyICpzdHJpbmcgPSBOVUxMOwogIAogIGlmIChsZW5ndGggPiAwKSB7CiAgICAgIHN0cmluZyA9IChVQ2hhciAqKXVwcnZfbWFsbG9jKHNpemVvZihVQ2hhcikgKiBsZW5ndGgpOwogICAgICAvKiAKICAgICAgVXNpbmcgdGhpcyBjb25zdHJ1Y3RvciB3aWxsIHByZXZlbnQgYnVmZmVyIGZyb20gYmVpbmcgcmVtb3ZlZCB3aGVuCiAgICAgIHN0cmluZyBnZXRzIHJlbW92ZWQKICAgICAgKi8KICAgICAgc291cmNlVGV4dC5leHRyYWN0KDAsIGxlbmd0aCwgc3RyaW5nKTsKICB9CiAgZWxzZSB7CiAgICAgIHN0cmluZyA9IChVQ2hhciAqKXVwcnZfbWFsbG9jKHNpemVvZihVQ2hhcikpOwogICAgICAvLyBudWxsIHRlcm1pbmF0ZSBpdAogICAgICAqc3RyaW5nID0gMDsKICB9CgogIG1fZGF0YV8gPSB1Y29sX29wZW5FbGVtZW50cyhvcmRlci0+dWNvbGxhdG9yLCBzdHJpbmcsIGxlbmd0aCwgJnN0YXR1cyk7CiAgbV9kYXRhXy0+aXNXcml0YWJsZSA9IFRSVUU7Cn0KCi8qKiAKKiBUaGlzIGlzIHRoZSAicmVhbCIgY29uc3RydWN0b3IgZm9yIHRoaXMgY2xhc3M7IGl0IGNvbnN0cnVjdHMgYW4gaXRlcmF0b3Igb3ZlciAKKiB0aGUgc291cmNlIHRleHQgdXNpbmcgdGhlIHNwZWNpZmllZCBjb2xsYXRvcgoqLwpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IENoYXJhY3Rlckl0ZXJhdG9yJiBzb3VyY2VUZXh0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIG9yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBpc0RhdGFPd25lZF8oVFJVRSkKewogIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHJldHVybjsKICAgIAogIC8vICoqKiogc2hvdWxkIEkganVzdCBkcm9wIHRoaXMgdGVzdD8gKioqKgogIC8qCiAgaWYgKCBzb3VyY2VUZXh0LmVuZEluZGV4KCkgIT0gMCApCiAgewogICAgLy8gQSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgaXMgcmVhbGx5IGEgdHdvLWxheWVyZWQgYmVhc3QuCiAgICAvLyBJbnRlcm5hbGx5IGl0IHVzZXMgYSBOb3JtYWxpemVyIHRvIG11bmdlIHRoZSBzb3VyY2UgdGV4dCBpbnRvIGEgZm9ybSAKICAgIC8vIHdoZXJlIGFsbCAiY29tcG9zZWQiIFVuaWNvZGUgY2hhcmFjdGVycyAoc3VjaCBhcyD8KSBhcmUgc3BsaXQgaW50byBhIAogICAgLy8gbm9ybWFsIGNoYXJhY3RlciBhbmQgYSBjb21iaW5pbmcgYWNjZW50IGNoYXJhY3Rlci4gIAogICAgLy8gQWZ0ZXJ3YXJkLCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgZG9lcyBpdHMgb3duIHByb2Nlc3NpbmcgdG8gaGFuZGxlCiAgICAvLyBleHBhbmRpbmcgYW5kIGNvbnRyYWN0aW5nIGNvbGxhdGlvbiBzZXF1ZW5jZXMsIGlnbm9yYWJsZXMsIGFuZCBzbyBvbi4KICAgIAogICAgTm9ybWFsaXplcjo6RU1vZGUgZGVjb21wID0gb3JkZXItPmdldFN0cmVuZ3RoKCkgPT0gQ29sbGF0b3I6OklERU5USUNBTAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBOb3JtYWxpemVyOjpOT19PUCA6IG9yZGVyLT5nZXREZWNvbXBvc2l0aW9uKCk7CiAgICAgIAogICAgdGV4dCA9IG5ldyBOb3JtYWxpemVyKHNvdXJjZVRleHQsIGRlY29tcCk7CiAgICBpZiAodGV4dCA9PSBOVUxMKQogICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOyAgICAKICB9CiAgKi8KICBpbnQzMl90IGxlbmd0aCA9IHNvdXJjZVRleHQuZ2V0TGVuZ3RoKCk7CiAgVUNoYXIgKmJ1ZmZlciA9IChVQ2hhciAqKXVwcnZfbWFsbG9jKHNpemVvZihVQ2hhcikgKiBsZW5ndGgpOwogIC8qIAogIFVzaW5nIHRoaXMgY29uc3RydWN0b3Igd2lsbCBwcmV2ZW50IGJ1ZmZlciBmcm9tIGJlaW5nIHJlbW92ZWQgd2hlbgogIHN0cmluZyBnZXRzIHJlbW92ZWQKICAqLwogIFVuaWNvZGVTdHJpbmcgc3RyaW5nKGJ1ZmZlciwgbGVuZ3RoLCBsZW5ndGgpOwogICgoQ2hhcmFjdGVySXRlcmF0b3IgJilzb3VyY2VUZXh0KS5nZXRUZXh0KHN0cmluZyk7CiAgc3RyaW5nLmV4dHJhY3QoMCwgbGVuZ3RoLCBidWZmZXIpOwogIAogIG1fZGF0YV8gPSB1Y29sX29wZW5FbGVtZW50cyhvcmRlci0+dWNvbGxhdG9yLCBidWZmZXIsIGxlbmd0aCwgJnN0YXR1cyk7CiAgbV9kYXRhXy0+aXNXcml0YWJsZSA9IFRSVUU7Cn0KCi8qIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBwcm90ZWN0ZWQgbWV0aG9kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKY29uc3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yJiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Om9wZXJhdG9yPSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3ImIG90aGVyKQp7CiAgaWYgKHRoaXMgIT0gJm90aGVyKQogIHsKICAgICAgVUNvbGxhdGlvbkVsZW1lbnRzICp1Y29sZWxlbSAgICAgID0gdGhpcy0+bV9kYXRhXzsKICAgICAgVUNvbGxhdGlvbkVsZW1lbnRzICpvdGhlcnVjb2xlbGVtID0gb3RoZXIubV9kYXRhXzsKICAgICAgY29sbEl0ZXJhdGUgICAgICAgICpjb2xpdGVyICAgICAgID0gJih1Y29sZWxlbS0+aXRlcmF0b3JkYXRhXyk7CiAgICAgIGNvbGxJdGVyYXRlICAgICAgICAqb3RoZXJjb2xpdGVyICA9ICYob3RoZXJ1Y29sZWxlbS0+aXRlcmF0b3JkYXRhXyk7CiAgICAgIGludCAgICAgICAgICAgICAgICBsZW5ndGggICAgICAgICA9IG90aGVyY29saXRlci0+ZW5kcCA9PSBOVUxMID8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdV9zdHJsZW4ob3RoZXJjb2xpdGVyLT5zdHJpbmcpIDogCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG90aGVyY29saXRlci0+ZW5kcCAtIG90aGVyY29saXRlci0+c3RyaW5nOwoKICAgICAgdWNvbGVsZW0tPm5vcm1hbGl6YXRpb25fID0gb3RoZXJ1Y29sZWxlbS0+bm9ybWFsaXphdGlvbl87CiAgICAgIHVjb2xlbGVtLT5yZXNldF8gICAgICAgICA9IG90aGVydWNvbGVsZW0tPnJlc2V0XzsKICAgICAgdWNvbGVsZW0tPmlzV3JpdGFibGUgICAgID0gVFJVRTsKICAgIAogICAgICAvKiBjcmVhdGUgYSBkdXBsaWNhdGUgb2Ygc3RyaW5nICovCiAgICAgIGNvbGl0ZXItPnN0cmluZyAgID0gKFVDaGFyICopdXBydl9tYWxsb2MobGVuZ3RoICogc2l6ZW9mKFVDaGFyKSk7CiAgICAgIHVwcnZfbWVtY3B5KGNvbGl0ZXItPnN0cmluZywgb3RoZXJjb2xpdGVyLT5zdHJpbmcsCiAgICAgICAgICAgICAgICAgIGxlbmd0aCAqIHNpemVvZihVQ2hhcikpOwoKICAgICAgLyogc3RhcnQgYW5kIGVuZCBvZiBzdHJpbmcgKi8KICAgICAgY29saXRlci0+ZW5kcCA9IGNvbGl0ZXItPmVuZHAgPSBjb2xpdGVyLT5zdHJpbmcgKyBsZW5ndGg7CgogICAgICAvKiBoYW5kbGUgd3JpdGFibGUgYnVmZmVyIGhlcmUgKi8KICAgICAgY29saXRlci0+d3JpdGFibGVCdWZTaXplID0gb3RoZXJjb2xpdGVyLT53cml0YWJsZUJ1ZlNpemU7CiAgICAgIGlmIChvdGhlcmNvbGl0ZXItPnN0YWNrV3JpdGFibGVCdWZmZXIgPT0gb3RoZXJjb2xpdGVyLT53cml0YWJsZUJ1ZmZlcikgewogICAgICAgIHVwcnZfbWVtY3B5KGNvbGl0ZXItPnN0YWNrV3JpdGFibGVCdWZmZXIsIAogICAgICAgICAgICAgICAgICAgIG90aGVyY29saXRlci0+c3RhY2tXcml0YWJsZUJ1ZmZlciwgCiAgICAgICAgICAgICAgICAgICAgVUNPTF9XUklUQUJMRV9CVUZGRVJfU0laRSAqIHNpemVvZihVQ2hhcikpOwogICAgICAgIGNvbGl0ZXItPndyaXRhYmxlQnVmZmVyID0gY29saXRlci0+c3RhY2tXcml0YWJsZUJ1ZmZlcjsKICAgICAgfQogICAgICBlbHNlIHsKICAgICAgICBjb2xpdGVyLT53cml0YWJsZUJ1ZmZlciA9IChVQ2hhciAqKXVwcnZfbWFsbG9jKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29saXRlci0+d3JpdGFibGVCdWZTaXplICogc2l6ZW9mKFVDaGFyKSk7CiAgICAgICAgdXBydl9tZW1jcHkoY29saXRlci0+d3JpdGFibGVCdWZmZXIsIG90aGVyY29saXRlci0+d3JpdGFibGVCdWZmZXIsCiAgICAgICAgICAgICAgICAgICAgY29saXRlci0+d3JpdGFibGVCdWZTaXplICogc2l6ZW9mKFVDaGFyKSk7CiAgICAgIH0KICAgICAgICAgCiAgICAgIC8qIGN1cnJlbnQgcG9zaXRpb24gKi8KICAgICAgaWYgKG90aGVyY29saXRlci0+cG9zID49IG90aGVyY29saXRlci0+c3RyaW5nICYmIAogICAgICAgICAgb3RoZXJjb2xpdGVyLT5wb3MgPD0gb3RoZXJjb2xpdGVyLT5lbmRwKSB7CiAgICAgICAgICBjb2xpdGVyLT5wb3MgPSBjb2xpdGVyLT5zdHJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgKG90aGVyY29saXRlci0+cG9zIC0gb3RoZXJjb2xpdGVyLT5zdHJpbmcpOwogICAgICB9CiAgICAgIGVsc2UgewogICAgICAgIGNvbGl0ZXItPnBvcyA9IGNvbGl0ZXItPndyaXRhYmxlQnVmZmVyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIChvdGhlcmNvbGl0ZXItPnBvcyAtIG90aGVyY29saXRlci0+d3JpdGFibGVCdWZmZXIpOwogICAgICB9CgogICAgICAvKiBDRSBidWZmZXIgKi8KICAgICAgdXBydl9tZW1jcHkoY29saXRlci0+Q0VzLCBvdGhlcmNvbGl0ZXItPkNFcywgCiAgICAgICAgICAgICAgICAgIFVDT0xfRVhQQU5EX0NFX0JVRkZFUl9TSVpFICogc2l6ZW9mKHVpbnQzMl90KSk7CiAgICAgIGNvbGl0ZXItPnRvUmV0dXJuID0gY29saXRlci0+Q0VzICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAob3RoZXJjb2xpdGVyLT50b1JldHVybiAtIG90aGVyY29saXRlci0+Q0VzKTsKICAgICAgY29saXRlci0+Q0Vwb3MgICAgPSBvdGhlcmNvbGl0ZXItPkNFcyArIAogICAgICAgICAgICAgICAgICAgICAgICAgKG90aGVyY29saXRlci0+Q0Vwb3MgLSBvdGhlcmNvbGl0ZXItPkNFcyk7CiAgICAKICAgICAgY29saXRlci0+ZmNkUG9zaXRpb24gPSBjb2xpdGVyLT5zdHJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChvdGhlcmNvbGl0ZXItPmZjZFBvc2l0aW9uIC0gb3RoZXJjb2xpdGVyLT5zdHJpbmcpOwogICAgICBjb2xpdGVyLT5mbGFncyAgICAgICA9IG90aGVyY29saXRlci0+ZmxhZ3MgfCBVQ09MX0lURVJfSEFTTEVOOwogICAgICBjb2xpdGVyLT5vcmlnRmxhZ3MgICA9IG90aGVyY29saXRlci0+b3JpZ0ZsYWdzOwogICAgICBjb2xpdGVyLT5jb2xsID0gb3RoZXJjb2xpdGVyLT5jb2xsOwogICAgICB0aGlzLT5pc0RhdGFPd25lZF8gPSBUUlVFOwogIH0KCiAgcmV0dXJuICp0aGlzOwp9CgoK