LyoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqIENvcHlyaWdodCAoQykgMTk5Ni0xOTk5LCBJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uIGFuZCAgICAqCiogb3RoZXJzLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqLwoKLyoKKiBGaWxlIGNvbGVpdHIuY3BwCioKKiAKKgoqIENyZWF0ZWQgYnk6IEhlbGVuYSBTaGloCioKKiBNb2RpZmljYXRpb24gSGlzdG9yeToKKgoqICBEYXRlICAgICAgTmFtZSAgICAgICAgRGVzY3JpcHRpb24KKgoqICA2LzIzLzk3ICAgaGVsZW5hICAgICAgQWRkaW5nIGNvbW1lbnRzIHRvIG1ha2UgY29kZSBtb3JlIHJlYWRhYmxlLgoqIDA4LzAzLzk4ICAgZXJtICAgICAgICAgU3luY2hlZCB3aXRoIDEuMiB2ZXJzaW9uIG9mIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvci5qYXZhCiogMTIvMTAvOTkgICBhbGl1ICAgICAgICBQb3J0ZWQgVGhhaSBjb2xsYXRpb24gc3VwcG9ydCBmcm9tIEphdmEuCiogMDEvMjUvMDEgICBzd3F1ZWsgICAgICBNb2RpZmllZCB0byBhIEMrKyB3cmFwcGVyIGNhbGxpbmcgQyBBUElzICh1Y29saXRlci5oKQoqIDAyLzE5LzAxICAgc3dxdWVrICAgICAgUmVtb3ZlZCBDb2xsYXRpb25FbGVtZW50c0l0ZXJhdG9yKCkgc2luY2UgaXQgaXMgCiogICAgICAgICAgICAgICAgICAgICAgICBwcml2YXRlIGNvbnN0cnVjdG9yIGFuZCBubyBjYWxscyBhcmUgbWFkZSB0byBpdAoqLwoKLy8gI2luY2x1ZGUgInVuaWNvZGUvc29ydGtleS5oIgojaW5jbHVkZSAidW5pY29kZS9jb2xlaXRyLmgiCiNpbmNsdWRlICJ1Y29saW1wLmgiCiNpbmNsdWRlICJjbWVtb3J5LmgiCgovLyAjaW5jbHVkZSAidW5pY29kZS9jaGFyaXRlci5oIgovLyAjaW5jbHVkZSAidGFibGVzLmgiCi8vICNpbmNsdWRlICJ1bmljb2RlL25vcm1senIuaCIKLy8gI2luY2x1ZGUgInVuaWNvZGUvdW5pY29kZS5oIgovLyAjaW5jbHVkZSAidGNvbGRhdGEuaCIKLy8gI2luY2x1ZGUgInVjbXAzMi5oIgoKLyogQ29uc3RhbnRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKLyogc3lud2VlIDogcHVibGljIGNhbid0IHJlbW92ZSAqLwppbnQzMl90IGNvbnN0IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6TlVMTE9SREVSID0gMHhmZmZmZmZmZjsKLy8gaW50MzJfdCBjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OlVOTUFQUEVEQ0hBUlZBTFVFID0gMHg3ZmZmMDAwMDsKaW50MzJfdCBjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5PX01PUkVfQ0VTID0gMHgwMDAxMDEwMTsKCi8qIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBwdWJsaWMgY29uc3RydWN0b3IvZGVzdHJ1Y3RvciAtLS0tLS0tLS0tLS0tLS0tLS0gKi8KCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6Q29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciYgb3RoZXIpIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogaXNEYXRhT3duZWRfKFRSVUUpCnsKICAqdGhpcyA9IG90aGVyOwp9CgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6On5Db2xsYXRpb25FbGVtZW50SXRlcmF0b3IoKQp7CiAgaWYgKGlzRGF0YU93bmVkXykKICAgIHVjb2xfY2xvc2VFbGVtZW50cyhtX2RhdGFfKTsKfQoKLyogQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yIHB1YmxpYyBtZXRob2RzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKVVRleHRPZmZzZXQgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpnZXRPZmZzZXQoKSBjb25zdAp7CiAgcmV0dXJuIHVjb2xfZ2V0T2Zmc2V0KG1fZGF0YV8pOwp9CgovKioKKiBHZXQgdGhlIG9yZGVyaW5nIHByaW9yaXR5IG9mIHRoZSBuZXh0IGNoYXJhY3RlciBpbiB0aGUgc3RyaW5nLgoqIEByZXR1cm4gdGhlIG5leHQgY2hhcmFjdGVyJ3Mgb3JkZXJpbmcuIFJldHVybnMgTlVMTE9SREVSIGlmIGFuIGVycm9yIGhhcyAKKiAgICAgICAgIG9jY3VyZWQgb3RoZXJ3aXNlIGlmIHRoZSBlbmQgb2Ygc3RyaW5nIGhhcyBiZWVuIHJlYWNoZWQsIAoqICAgICAgICAgTk9fTU9SRV9DRVMgaXMgcmV0dXJuZWQuCiovCmludDMyX3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpuZXh0KFVFcnJvckNvZGUmIHN0YXR1cykKewogIC8qCiAgaWYgKHRleHQgPT0gTlVMTCB8fCBVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHJldHVybiBOVUxMT1JERVI7CiAgICAKICAvLyBVcGRhdGUgdGhlIGRlY29tcG9zaXRpb24gbW9kZSBpZiBuZWNlc3NhcnkuCiAgdGV4dC0+c2V0TW9kZShvcmRlckFsaWFzLT5nZXREZWNvbXBvc2l0aW9uKCkpOwogICAgCiAgaWYgKGJ1ZmZlckFsaWFzICE9IE5VTEwpCiAgewogICAgLy8gYnVmZmVyQWxpYXMgbmVlZHMgYSBiaXQgb2YgYW4gZXhwbGFuYXRpb24uCiAgICAvLyBXaGVuIHdlIGhpdCBhbiBleHBhbmRpbmcgY2hhcmFjdGVyIGluIHRoZSB0ZXh0LCB3ZSBjYWxsIHRoZSBvcmRlcidzCiAgICAvLyBnZXRFeHBhbmRWYWx1ZXMgbWV0aG9kIHRvIHJldHJpZXZlIGFuIGFycmF5IG9mIHRoZSBvcmRlcmluZ3MgZm9yIGFsbCBvZiAKICAgIC8vIHRoZSBjaGFyYWN0ZXJzIGluIHRoZSBleHBhbnNpb24gKHNlZSB0aGUgZW5kIG9mIHRoaXMgbWV0aG9kKS4KICAgIC8vIFRoZSBmaXJzdCBvcmRlcmluZyBpcyByZXR1cm5lZCwgYW5kIGFuIGFsaWFzIHRvIHRoZSBvcmRlcmluZ3MgYXJyYXkgaXMgCiAgICAvLyBzYXZlZCBzbyB0aGF0IHRoZSByZW1haW5pbmcgb3JkZXJpbmdzIGNhbiBiZSByZXR1cm5lZCBvbiBzdWJzZXF1ZW50IGNhbGxzIAogICAgLy8gdG8gbmV4dC4gU28sIGlmIHRoZSBleHBhbmRpbmcgYnVmZmVyIGlzIG5vdCBleGhhdXN0ZWQsIGFsbCB3ZSBoYXZlIHRvIGRvIAogICAgLy8gaGVyZSBpcyByZXR1cm4gdGhlIG5leHQgb3JkZXJpbmcgaW4gdGhlIGJ1ZmZlci4gIAogICAgaWYgKGV4cEluZGV4IDwgYnVmZmVyQWxpYXMtPnNpemUoKSkKICAgICAgcmV0dXJuIHN0cmVuZ3RoT3JkZXIoYnVmZmVyQWxpYXMtPmF0KGV4cEluZGV4KyspKTsKICAgIGVsc2UKICAgICAgYnVmZmVyQWxpYXMgPSBOVUxMOwogIH0KCiAgLy8gR2V0cyB0aGUgbmV4dCBjaGFyYWN0ZXIgZnJvbSB0aGUgc3RyaW5nIHVzaW5nIGRlY29tcG9zaXRpb24gaXRlcmF0b3IuCiAgVUNoYXIzMiBjaCA9IHRleHQtPmN1cnJlbnQoKTsKICB0ZXh0LT5uZXh0KCk7CgogIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHJldHVybiBOVUxMT1JERVI7CiAgICAKCiAgaWYgKGNoID09IE5vcm1hbGl6ZXI6OkRPTkUpCiAgICByZXR1cm4gTlVMTE9SREVSOwogICAgCiAgLy8gQXNrIHRoZSBjb2xsYXRvciBmb3IgdGhpcyBjaGFyYWN0ZXIncyBvcmRlcmluZy4KICAvLyBVc2VkIHRvIGJlIFJ1bGVCYXNlZENvbGxhdG9yLmdldFVuaWNvZGVPcmRlcigpLiAKICAvLyBJdCBjYW4ndCBiZSBpbmxpbmVkIGluIHRibGNvbGwuaCBmaWxlIHVuZm9ydHVuYXRlbHkuCiAgCiAgICBpbnQzMl90IHZhbHVlID0gdWNtcDMyX2dldChvcmRlckFsaWFzLT5kYXRhLT5tYXBwaW5nLCBjaCk7CgogIGlmICh2YWx1ZSA9PSBSdWxlQmFzZWRDb2xsYXRvcjo6VU5NQVBQRUQpCiAgewogICAgLy8gUmV0dXJuZWQgYW4gInVubWFwcGVkIiBmbGFnIGFuZCBzYXZlIHRoZSBjaGFyYWN0ZXIgc28gaXQgY2FuIGJlIAogICAgLy8gcmV0dXJuZWQgbmV4dCB0aW1lIHRoaXMgbWV0aG9kIGlzIGNhbGxlZC4KICAgIGlmIChjaCA9PSAweDAwMDApIAogICAgICByZXR1cm4gY2g7CiAgICAvLyBcdTAwMDAgaXMgbm90IHZhbGlkIGluIEMrKydzIFVuaWNvZGVTdHJpbmcKICAgIG93bkJ1ZmZlci0+YXQoMCkgPSBVTk1BUFBFRENIQVJWQUxVRTsKICAgIG93bkJ1ZmZlci0+YXQoMSkgPSBjaCA8PCAxNjsKICAgIGJ1ZmZlckFsaWFzID0gb3duQnVmZmVyOwogIH0KICBlbHNlIAogIHsKICAgIGlmICh2YWx1ZSA+PSBSdWxlQmFzZWRDb2xsYXRvcjo6Q09OVFJBQ1RDSEFSSU5ERVgpCiAgICAgIHZhbHVlID0gbmV4dENvbnRyYWN0Q2hhcihjaCwgc3RhdHVzKTsKICAgIGlmICh2YWx1ZSA+PSBSdWxlQmFzZWRDb2xsYXRvcjo6RVhQQU5EQ0hBUklOREVYKQogICAgICBidWZmZXJBbGlhcyA9IG9yZGVyQWxpYXMtPmdldEV4cGFuZFZhbHVlTGlzdCh2YWx1ZSk7CiAgICAgIAogICAgaWYgKGlzVGhhaVByZVZvd2VsKGNoKSkKICAgIHsKICAgICAgVUNoYXIzMiBjb25zb25hbnQgPSB0ZXh0LT5jdXJyZW50KCk7CiAgICAgIHRleHQtPm5leHQoKTsKICAgICAgaWYgKGlzVGhhaUJhc2VDb25zb25hbnQoY29uc29uYW50KSkKICAgICAgICBidWZmZXJBbGlhcyA9IG1ha2VSZW9yZGVyZWRCdWZmZXIoKFVDaGFyKWNvbnNvbmFudCwgdmFsdWUsIGJ1ZmZlckFsaWFzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFLCBzdGF0dXMpOwogICAgICBlbHNlCiAgICAgICAgdGV4dC0+cHJldmlvdXMoKTsKICAgIH0KICB9CgogIGlmIChidWZmZXJBbGlhcyAhPSBOVUxMKSAKICB7CiAgICBleHBJbmRleCA9IDE7CiAgICB2YWx1ZSA9IGJ1ZmZlckFsaWFzLT5hdCgwKTsKICB9CgogIHJldHVybiBzdHJlbmd0aE9yZGVyKHZhbHVlKTsKICAqLwogIHJldHVybiB1Y29sX25leHQobV9kYXRhXywgJnN0YXR1cyk7Cn0KClVCb29sIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6b3BlcmF0b3IhPSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciYgb3RoZXIpIGNvbnN0CnsKICByZXR1cm4gISgqdGhpcyA9PSBvdGhlcik7Cn0KClVCb29sIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6b3BlcmF0b3I9PSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yJiB0aGF0KSBjb25zdAp7CiAgaWYgKHRoaXMgPT0gJnRoYXQpCiAgICByZXR1cm4gVFJVRTsKICAKICAvKgogIGlmICgqdGV4dCAhPSAqKHRoYXQudGV4dCkpCiAgICByZXR1cm4gRkFMU0U7CiAgICAKICBpZiAoKChidWZmZXJBbGlhcyA9PSBOVUxMKSAhPSAodGhhdC5idWZmZXJBbGlhcyA9PSBOVUxMKSkgfHwKICAgICAgKGJ1ZmZlckFsaWFzICE9IE5VTEwgJiYgKmJ1ZmZlckFsaWFzICE9ICoodGhhdC5idWZmZXJBbGlhcykpKQogICAgcmV0dXJuIEZBTFNFOwogICAgCiAgaWYgKGV4cEluZGV4ICE9IHRoYXQuZXhwSW5kZXgpCiAgICByZXR1cm4gRkFMU0U7CiAgICAKICBpZiAob3JkZXJBbGlhcyAhPSB0aGF0Lm9yZGVyQWxpYXMpCiAgICByZXR1cm4gRkFMU0U7CiAgICAKICByZXR1cm4gVFJVRTsKICAqLwogIAogIHJldHVybiBtX2RhdGFfID09IHRoYXQubV9kYXRhXzsKfQoKLyoqCiogR2V0IHRoZSBvcmRlcmluZyBwcmlvcml0eSBvZiB0aGUgcHJldmlvdXMgY29sbGF0aW9uIGVsZW1lbnQgaW4gdGhlIHN0cmluZy4KKiBAcGFyYW0gc3RhdHVzIHRoZSBlcnJvciBjb2RlIHN0YXR1cy4KKiBAcmV0dXJuIHRoZSBwcmV2aW91cyBlbGVtZW50J3Mgb3JkZXJpbmcuIFJldHVybnMgTlVMTE9SREVSIGlmIGFuIGVycm9yIGhhcyAKKiAgICAgICAgIG9jY3VyZWQgb3RoZXJ3aXNlIGlmIHRoZSBzdGFydCBvZiBzdHJpbmcgaGFzIGJlZW4gcmVhY2hlZCwgCiogICAgICAgICBOT19NT1JFX0NFUyBpcyByZXR1cm5lZC4KKi8KaW50MzJfdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnByZXZpb3VzKFVFcnJvckNvZGUmIHN0YXR1cykKewogIC8qCiAgaWYgKHRleHQgPT0gTlVMTCB8fCBVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHJldHVybiBOVUxMT1JERVI7CiAgICAKICB0ZXh0LT5zZXRNb2RlKG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CgogIGlmIChidWZmZXJBbGlhcyAhPSBOVUxMKQogIHsKICAgIGlmIChleHBJbmRleCA+IDApCiAgICAgIHJldHVybiBzdHJlbmd0aE9yZGVyKGJ1ZmZlckFsaWFzLT5hdCgtLWV4cEluZGV4KSk7CiAgICAgIAogICAgYnVmZmVyQWxpYXMgPSBOVUxMOwogIH0KCiAgVUNoYXIzMiBjaCA9IHRleHQtPnByZXZpb3VzKCk7CgogIGlmIChjaCA9PSBOb3JtYWxpemVyOjpET05FKQogICAgcmV0dXJuIE5VTExPUkRFUjsKICAgIAogIC8vIFVzZWQgdG8gYmUgUnVsZUJhc2VkQ29sbGF0b3IuZ2V0VW5pY29kZU9yZGVyKCkuIEl0IGNhbid0IGJlIGlubGluZWQgaW4gCiAgLy8gdGJsY29sbC5oIGZpbGUgdW5mb3J0dW5hdGVseS4KICAKICBpbnQzMl90IHZhbHVlID0gdWNtcDMyX2dldChvcmRlckFsaWFzLT5kYXRhLT5tYXBwaW5nLCBjaCk7CgogIGlmICh2YWx1ZSA9PSBSdWxlQmFzZWRDb2xsYXRvcjo6VU5NQVBQRUQpCiAgewogICAgaWYgKGNoID09IDB4MDAwMCkgCiAgICAgIHJldHVybiBjaDsKICAgIAogICAgb3duQnVmZmVyLT5hdCgwKSA9IFVOTUFQUEVEQ0hBUlZBTFVFOwogICAgb3duQnVmZmVyLT5hdCgxKSA9IGNoIDw8IDE2OwogICAgYnVmZmVyQWxpYXMgPSBvd25CdWZmZXI7CiAgfQogIGVsc2UgCiAgewogICAgaWYgKHZhbHVlID49IFJ1bGVCYXNlZENvbGxhdG9yOjpDT05UUkFDVENIQVJJTkRFWCkKICAgICAgdmFsdWUgPSBwcmV2Q29udHJhY3RDaGFyKGNoLCBzdGF0dXMpOwogICAgICAKICAgIGlmICh2YWx1ZSA+PSBSdWxlQmFzZWRDb2xsYXRvcjo6RVhQQU5EQ0hBUklOREVYKQogICAgICBidWZmZXJBbGlhcyA9IG9yZGVyQWxpYXMtPmdldEV4cGFuZFZhbHVlTGlzdCh2YWx1ZSk7CiAgICAgIAogICAgaWYgKGlzVGhhaUJhc2VDb25zb25hbnQoY2gpKSAKICAgIHsKICAgICAgVUNoYXIzMiB2b3dlbCA9IHRleHQtPnByZXZpb3VzKCk7CiAgICAgIGlmIChpc1RoYWlQcmVWb3dlbCh2b3dlbCkpCiAgICAgICAgYnVmZmVyQWxpYXMgPSBtYWtlUmVvcmRlcmVkQnVmZmVyKChVQ2hhcil2b3dlbCwgdmFsdWUsIGJ1ZmZlckFsaWFzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGQUxTRSwgc3RhdHVzKTsKICAgICAgZWxzZQogICAgICAgIHRleHQtPm5leHQoKTsKICAgIH0KICB9CgogIGlmIChidWZmZXJBbGlhcyAhPSBOVUxMKSAKICB7CiAgICBleHBJbmRleCA9IGJ1ZmZlckFsaWFzLT5zaXplKCktMTsKICAgIHZhbHVlID0gYnVmZmVyQWxpYXMtPmF0KGV4cEluZGV4KTsKICB9CgogIHJldHVybiBzdHJlbmd0aE9yZGVyKHZhbHVlKTsKICAqLwogIHJldHVybiB1Y29sX3ByZXZpb3VzKG1fZGF0YV8sICZzdGF0dXMpOwp9CgovKioKKiBSZXNldHMgdGhlIGN1cnNvciB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzdHJpbmcuCiovCnZvaWQgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpyZXNldCgpCnsKICAvKgogIGlmICh0ZXh0ICE9IE5VTEwpCiAgewogICAgdGV4dC0+cmVzZXQoKTsKICAgIHRleHQtPnNldE1vZGUob3JkZXJBbGlhcy0+Z2V0RGVjb21wb3NpdGlvbigpKTsKICB9CgogIGJ1ZmZlckFsaWFzID0gTlVMTDsKICBleHBJbmRleCA9IDA7CiAgKi8KICB1Y29sX3Jlc2V0KG1fZGF0YV8pOwp9Cgp2b2lkIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6c2V0T2Zmc2V0KFVUZXh0T2Zmc2V0IG5ld09mZnNldCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgLyoKICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICByZXR1cm47CiAgICAKICBpZiAodGV4dCAhPSBOVUxMKQogICAgdGV4dC0+c2V0SW5kZXgobmV3T2Zmc2V0KTsKICAgIAogIGJ1ZmZlckFsaWFzID0gTlVMTDsKICAqLwogIHVjb2xfc2V0T2Zmc2V0KG1fZGF0YV8sIG5ld09mZnNldCwgJnN0YXR1cyk7Cn0KCi8qKgoqIFNldHMgdGhlIHNvdXJjZSB0byB0aGUgbmV3IHNvdXJjZSBzdHJpbmcuCiovCnZvaWQgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzZXRUZXh0KGNvbnN0IFVuaWNvZGVTdHJpbmcmIHNvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgcmV0dXJuOwogIC8qCiAgYnVmZmVyQWxpYXMgPSAwOwoKICBpZiAodGV4dCA9PSBOVUxMKQogICAgdGV4dCA9IG5ldyBOb3JtYWxpemVyKHNvdXJjZSwgb3JkZXJBbGlhcy0+Z2V0RGVjb21wb3NpdGlvbigpKTsKICBlbHNlCiAgewogICAgdGV4dC0+c2V0VGV4dChzb3VyY2UsIHN0YXR1cyk7CiAgICB0ZXh0LT5zZXRNb2RlKG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CiAgfQogICovCiAgaW50MzJfdCBsZW5ndGggPSBzb3VyY2UubGVuZ3RoKCk7CiAgVUNoYXIgKnN0cmluZyA9IG5ldyBVQ2hhcltsZW5ndGhdOwogIHNvdXJjZS5leHRyYWN0KDAsIGxlbmd0aCwgc3RyaW5nKTsKCQogIG1fZGF0YV8tPmxlbmd0aF8gPSBsZW5ndGg7CgogIGlmIChtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLmlzV3JpdGFibGUgJiYgCiAgICAgIG1fZGF0YV8tPml0ZXJhdG9yZGF0YV8uc3RyaW5nICE9IE5VTEwpCiAgICB1cHJ2X2ZyZWUobV9kYXRhXy0+aXRlcmF0b3JkYXRhXy5zdHJpbmcpOwogIGluaXRfY29sbEl0ZXJhdGUoc3RyaW5nLCBsZW5ndGgsICZtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLCBUUlVFKTsKfQoKLy8gU2V0cyB0aGUgc291cmNlIHRvIHRoZSBuZXcgY2hhcmFjdGVyIGl0ZXJhdG9yLgp2b2lkIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6c2V0VGV4dChDaGFyYWN0ZXJJdGVyYXRvciYgc291cmNlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKSAKICAgIHJldHVybjsKICAgIAogIC8qCiAgYnVmZmVyQWxpYXMgPSAwOwoKICBpZiAodGV4dCA9PSBOVUxMKQogICAgdGV4dCA9IG5ldyBOb3JtYWxpemVyKHNvdXJjZSwgb3JkZXJBbGlhcy0+Z2V0RGVjb21wb3NpdGlvbigpKTsKICBlbHNlCiAgewogICAgdGV4dC0+c2V0TW9kZShvcmRlckFsaWFzLT5nZXREZWNvbXBvc2l0aW9uKCkpOwogICAgdGV4dC0+c2V0VGV4dChzb3VyY2UsIHN0YXR1cyk7CiAgfQogICovCiAgaW50MzJfdCBsZW5ndGggPSBzb3VyY2UuZ2V0TGVuZ3RoKCk7CiAgVUNoYXIgKmJ1ZmZlciA9IG5ldyBVQ2hhcltsZW5ndGhdOwogIC8qIAogIFVzaW5nIHRoaXMgY29uc3RydWN0b3Igd2lsbCBwcmV2ZW50IGJ1ZmZlciBmcm9tIGJlaW5nIHJlbW92ZWQgd2hlbgogIHN0cmluZyBnZXRzIHJlbW92ZWQKICAqLwogIFVuaWNvZGVTdHJpbmcgc3RyaW5nOwogIHNvdXJjZS5nZXRUZXh0KHN0cmluZyk7CiAgc3RyaW5nLmV4dHJhY3QoMCwgbGVuZ3RoLCBidWZmZXIpOwogIG1fZGF0YV8tPmxlbmd0aF8gPSBsZW5ndGg7CgogIGlmIChtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLmlzV3JpdGFibGUgJiYgCiAgICAgIG1fZGF0YV8tPml0ZXJhdG9yZGF0YV8uc3RyaW5nICE9IE5VTEwpCiAgICB1cHJ2X2ZyZWUobV9kYXRhXy0+aXRlcmF0b3JkYXRhXy5zdHJpbmcpOwogIGluaXRfY29sbEl0ZXJhdGUoYnVmZmVyLCBsZW5ndGgsICZtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLCBUUlVFKTsKfQoKaW50MzJfdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnN0cmVuZ3RoT3JkZXIoaW50MzJfdCBvcmRlcikgY29uc3QKewogIFVDb2xsYXRpb25TdHJlbmd0aCBzID0gdWNvbF9nZXRTdHJlbmd0aChtX2RhdGFfLT5jb2xsYXRvcl8pOwogIC8vIE1hc2sgb2ZmIHRoZSB1bndhbnRlZCBkaWZmZXJlbmNlcy4KICBpZiAocyA9PSBVQ09MX1BSSU1BUlkpCiAgICBvcmRlciAmPSBSdWxlQmFzZWRDb2xsYXRvcjo6UFJJTUFSWURJRkZFUkVOQ0VPTkxZOwogIGVsc2UgCiAgICBpZiAocyA9PSBVQ09MX1NFQ09OREFSWSkKICAgICAgb3JkZXIgJj0gUnVsZUJhc2VkQ29sbGF0b3I6OlNFQ09OREFSWURJRkZFUkVOQ0VPTkxZOwogICAgCiAgcmV0dXJuIG9yZGVyOwp9CgovKiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgcHJpdmF0ZSBjb25zdHJ1Y3RvcnMvZGVzdHJ1Y3RvcnMgLS0tLS0tLS0tLS0tLS0tICovCgovKiAKVGhpcyBwcml2YXRlIG1ldGhvZCB3aWxsIG5ldmVyIGJlIGNhbGxlZCwgYnV0IGl0IG1ha2VzIHRoZSBsaW5rZXIgaGFwcHkKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IoKSA6IG1fZGF0YV8oMCkKewp9CiovCgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFJ1bGVCYXNlZENvbGxhdG9yKiBvcmRlcikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogaXNEYXRhT3duZWRfKFRSVUUpCnsKICBVRXJyb3JDb2RlIHN0YXR1cyA9IFVfWkVST19FUlJPUjsKICBtX2RhdGFfID0gdWNvbF9vcGVuRWxlbWVudHMob3JkZXItPnVjb2xsYXRvciwgTlVMTCwgMCwgJnN0YXR1cyk7Cn0KCi8qKiAKKiBUaGlzIGlzIHRoZSAicmVhbCIgY29uc3RydWN0b3IgZm9yIHRoaXMgY2xhc3M7IGl0IGNvbnN0cnVjdHMgYW4gaXRlcmF0b3IKKiBvdmVyIHRoZSBzb3VyY2UgdGV4dCB1c2luZyB0aGUgc3BlY2lmaWVkIGNvbGxhdG9yCiovCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6Q29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFVuaWNvZGVTdHJpbmcmIHNvdXJjZVRleHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIG9yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGlzRGF0YU93bmVkXyhUUlVFKQp7CiAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgcmV0dXJuOwogCiAgLyoKICBpZiAoIHNvdXJjZVRleHQubGVuZ3RoKCkgIT0gMCApIAogIHsKICAgIC8vIEEgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yIGlzIHJlYWxseSBhIHR3by1sYXllcmVkIGJlYXN0LgogICAgLy8gSW50ZXJuYWxseSBpdCB1c2VzIGEgTm9ybWFsaXplciB0byBtdW5nZSB0aGUgc291cmNlIHRleHQgaW50byBhIGZvcm0gCiAgICAvLyB3aGVyZSBhbGwgImNvbXBvc2VkIiBVbmljb2RlIGNoYXJhY3RlcnMgKHN1Y2ggYXMg/CkgYXJlIHNwbGl0IGludG8gYSAKICAgIC8vIG5vcm1hbCBjaGFyYWN0ZXIgYW5kIGEgY29tYmluaW5nIGFjY2VudCBjaGFyYWN0ZXIuICAKICAgIC8vIEFmdGVyd2FyZCwgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yIGRvZXMgaXRzIG93biBwcm9jZXNzaW5nIHRvIGhhbmRsZQogICAgLy8gZXhwYW5kaW5nIGFuZCBjb250cmFjdGluZyBjb2xsYXRpb24gc2VxdWVuY2VzLCBpZ25vcmFibGVzLCBhbmQgc28gb24uCiAgICAKICAgIE5vcm1hbGl6ZXI6OkVNb2RlIGRlY29tcCA9IChvcmRlci0+Z2V0U3RyZW5ndGgoKSA9PSBDb2xsYXRvcjo6SURFTlRJQ0FMKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBOb3JtYWxpemVyOjpOT19PUCA6IG9yZGVyLT5nZXREZWNvbXBvc2l0aW9uKCk7CiAgICAgIAogICAgdGV4dCA9IG5ldyBOb3JtYWxpemVyKHNvdXJjZVRleHQsIGRlY29tcCk7CiAgICBpZiAodGV4dCA9PSBOVUxMKQogICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogIH0KICAqLwogIGludDMyX3QgbGVuZ3RoID0gc291cmNlVGV4dC5sZW5ndGgoKTsKICBVQ2hhciAqc3RyaW5nID0gbmV3IFVDaGFyW2xlbmd0aF07CiAgLyogCiAgVXNpbmcgdGhpcyBjb25zdHJ1Y3RvciB3aWxsIHByZXZlbnQgYnVmZmVyIGZyb20gYmVpbmcgcmVtb3ZlZCB3aGVuCiAgc3RyaW5nIGdldHMgcmVtb3ZlZAogICovCiAgc291cmNlVGV4dC5leHRyYWN0KDAsIGxlbmd0aCwgc3RyaW5nKTsKCiAgbV9kYXRhXyA9IHVjb2xfb3BlbkVsZW1lbnRzKG9yZGVyLT51Y29sbGF0b3IsIHN0cmluZywgbGVuZ3RoLCAmc3RhdHVzKTsKICBtX2RhdGFfLT5pdGVyYXRvcmRhdGFfLmlzV3JpdGFibGUgPSBUUlVFOwp9CgovKiogCiogVGhpcyBpcyB0aGUgInJlYWwiIGNvbnN0cnVjdG9yIGZvciB0aGlzIGNsYXNzOyBpdCBjb25zdHJ1Y3RzIGFuIGl0ZXJhdG9yIG92ZXIgCiogdGhlIHNvdXJjZSB0ZXh0IHVzaW5nIHRoZSBzcGVjaWZpZWQgY29sbGF0b3IKKi8KQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBDaGFyYWN0ZXJJdGVyYXRvciYgc291cmNlVGV4dCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFJ1bGVCYXNlZENvbGxhdG9yKiBvcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogaXNEYXRhT3duZWRfKFRSVUUpCnsKICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICByZXR1cm47CiAgICAKICAvLyAqKioqIHNob3VsZCBJIGp1c3QgZHJvcCB0aGlzIHRlc3Q/ICoqKioKICAvKgogIGlmICggc291cmNlVGV4dC5lbmRJbmRleCgpICE9IDAgKQogIHsKICAgIC8vIEEgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yIGlzIHJlYWxseSBhIHR3by1sYXllcmVkIGJlYXN0LgogICAgLy8gSW50ZXJuYWxseSBpdCB1c2VzIGEgTm9ybWFsaXplciB0byBtdW5nZSB0aGUgc291cmNlIHRleHQgaW50byBhIGZvcm0gCiAgICAvLyB3aGVyZSBhbGwgImNvbXBvc2VkIiBVbmljb2RlIGNoYXJhY3RlcnMgKHN1Y2ggYXMg/CkgYXJlIHNwbGl0IGludG8gYSAKICAgIC8vIG5vcm1hbCBjaGFyYWN0ZXIgYW5kIGEgY29tYmluaW5nIGFjY2VudCBjaGFyYWN0ZXIuICAKICAgIC8vIEFmdGVyd2FyZCwgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yIGRvZXMgaXRzIG93biBwcm9jZXNzaW5nIHRvIGhhbmRsZQogICAgLy8gZXhwYW5kaW5nIGFuZCBjb250cmFjdGluZyBjb2xsYXRpb24gc2VxdWVuY2VzLCBpZ25vcmFibGVzLCBhbmQgc28gb24uCiAgICAKICAgIE5vcm1hbGl6ZXI6OkVNb2RlIGRlY29tcCA9IG9yZGVyLT5nZXRTdHJlbmd0aCgpID09IENvbGxhdG9yOjpJREVOVElDQUwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gTm9ybWFsaXplcjo6Tk9fT1AgOiBvcmRlci0+Z2V0RGVjb21wb3NpdGlvbigpOwogICAgICAKICAgIHRleHQgPSBuZXcgTm9ybWFsaXplcihzb3VyY2VUZXh0LCBkZWNvbXApOwogICAgaWYgKHRleHQgPT0gTlVMTCkKICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsgICAgCiAgfQogICovCiAgaW50MzJfdCBsZW5ndGggPSBzb3VyY2VUZXh0LmdldExlbmd0aCgpOwogIFVDaGFyICpidWZmZXIgPSBuZXcgVUNoYXJbbGVuZ3RoXTsKICAvKiAKICBVc2luZyB0aGlzIGNvbnN0cnVjdG9yIHdpbGwgcHJldmVudCBidWZmZXIgZnJvbSBiZWluZyByZW1vdmVkIHdoZW4KICBzdHJpbmcgZ2V0cyByZW1vdmVkCiAgKi8KICBVbmljb2RlU3RyaW5nIHN0cmluZyhidWZmZXIsIGxlbmd0aCwgbGVuZ3RoKTsKICAoKENoYXJhY3Rlckl0ZXJhdG9yICYpc291cmNlVGV4dCkuZ2V0VGV4dChzdHJpbmcpOwogIHN0cmluZy5leHRyYWN0KDAsIGxlbmd0aCwgYnVmZmVyKTsKICAKICBtX2RhdGFfID0gdWNvbF9vcGVuRWxlbWVudHMob3JkZXItPnVjb2xsYXRvciwgYnVmZmVyLCBsZW5ndGgsICZzdGF0dXMpOwogIG1fZGF0YV8tPml0ZXJhdG9yZGF0YV8uaXNXcml0YWJsZSA9IFRSVUU7Cn0KCi8qIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBwcml2YXRlIG1ldGhvZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCmNvbnN0IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciYgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpvcGVyYXRvcj0oCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yJiBvdGhlcikKewogIGlmICh0aGlzICE9ICZvdGhlcikKICB7CiAgICAvKgogICAgZXhwSW5kZXggPSBvdGhlci5leHBJbmRleDsKICAgIGRlbGV0ZSB0ZXh0OwogICAgdGV4dCA9IChOb3JtYWxpemVyKilvdGhlci50ZXh0LT5jbG9uZSgpOwoKICAgIGlmIChvdGhlci5idWZmZXJBbGlhcyA9PSBvdGhlci5vd25CdWZmZXIpIAogICAgewogICAgICAqb3duQnVmZmVyID0gKm90aGVyLm93bkJ1ZmZlcjsKICAgICAgYnVmZmVyQWxpYXMgPSBvd25CdWZmZXI7CiAgICB9IAogICAgZWxzZSAKICAgICAgaWYgKG90aGVyLmJ1ZmZlckFsaWFzICE9IE5VTEwgJiYgb3RoZXIuYnVmZmVyQWxpYXMgPT0gb3RoZXIucmVvcmRlckJ1ZmZlcikgCiAgICAgIHsKICAgICAgICBpZiAocmVvcmRlckJ1ZmZlciA9PSBOVUxMKQogICAgICAgICAgcmVvcmRlckJ1ZmZlciA9IG5ldyBWZWN0b3JPZkludCgqb3RoZXIucmVvcmRlckJ1ZmZlcik7CiAgICAgICAgZWxzZSAKICAgICAgICAgICpyZW9yZGVyQnVmZmVyID0gKm90aGVyLnJlb3JkZXJCdWZmZXI7CiAgICAgICAgICAKICAgICAgICBidWZmZXJBbGlhcyA9IHJlb3JkZXJCdWZmZXI7CiAgICAgIH0gCiAgICAgIGVsc2UgCiAgICAgICAgYnVmZmVyQWxpYXMgPSBvdGhlci5idWZmZXJBbGlhczsKICAgICAgICAKICAgICAgb3JkZXJBbGlhcyA9IG90aGVyLm9yZGVyQWxpYXM7CiAgICAqLwogICAgdGhpcy0+bV9kYXRhXyAgICAgID0gb3RoZXIubV9kYXRhXzsKICAgIHRoaXMtPmlzRGF0YU93bmVkXyA9IEZBTFNFOwogIH0KCiAgcmV0dXJuICp0aGlzOwp9CgovKioKICogR2V0IHRoZSBvcmRlcmluZyBwcmlvcml0eSBvZiB0aGUgbmV4dCBjb250cmFjdGluZyBjaGFyYWN0ZXIgaW4gdGhlCiAqIHN0cmluZy4KICogQHBhcmFtIGNoIHRoZSBzdGFydGluZyBjaGFyYWN0ZXIgb2YgYSBjb250cmFjdGluZyBjaGFyYWN0ZXIgdG9rZW4KICogQHJldHVybiB0aGUgbmV4dCBjb250cmFjdGluZyBjaGFyYWN0ZXIncyBvcmRlcmluZy4gIFJldHVybnMgTlVMTE9SREVSCiAqIGlmIHRoZSBlbmQgb2Ygc3RyaW5nIGlzIHJlYWNoZWQuCiAqLwovKgpzeW53ZWUgOiByZW1vdmVkIAppbnQzMl90CkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6bmV4dENvbnRyYWN0Q2hhcihVQ2hhcjMyIGNoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICAvLyBGaXJzdCBnZXQgdGhlIG9yZGVyaW5nIG9mIHRoaXMgc2luZ2xlIGNoYXJhY3RlcgogICAgVmVjdG9yT2ZQVG9Db250cmFjdEVsZW1lbnQgKmxpc3QgPSBvcmRlckFsaWFzLT5nZXRDb250cmFjdFZhbHVlcygoVUNoYXIpY2gpOwogICAgRW50cnlQYWlyICpwYWlyID0gKEVudHJ5UGFpciAqKWxpc3QtPmF0KDApOwogICAgaW50MzJfdCBvcmRlciA9IHBhaXItPnZhbHVlOwoKICAgIC8vIE5vdyBpdGVyYXRlIHRocm91Z2ggdGhlIGNoYXJzIGZvbGxvd2luZyBpdCBhbmQKICAgIC8vIGxvb2sgZm9yIHRoZSBsb25nZXN0IG1hdGNoCiAgICBrZXkucmVtb3ZlKCk7CiAgICBrZXkgKz0gY2g7CgogICAgd2hpbGUgKChjaCA9IHRleHQtPmN1cnJlbnQoKSkgIT0gTm9ybWFsaXplcjo6RE9ORSkKICAgIHsKICAgICAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gTlVMTE9SREVSOwogICAgICAgIH0KCiAgICAgICAga2V5ICs9IGNoOwoKICAgICAgICBpbnQzMl90IG4gPSBSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0RW50cnkobGlzdCwga2V5LCBUUlVFKTsKCiAgICAgICAgaWYgKG4gPT0gUnVsZUJhc2VkQ29sbGF0b3I6OlVOTUFQUEVEKQogICAgICAgIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHRleHQtPm5leHQoKTsKCiAgICAgICAgcGFpciA9IChFbnRyeVBhaXIgKilsaXN0LT5hdChuKTsKICAgICAgICBvcmRlciA9IHBhaXItPnZhbHVlOwogICAgfQoKICAgIHJldHVybiBvcmRlcjsKfQoqLwoKLyoqCiAqIEdldCB0aGUgb3JkZXJpbmcgcHJpb3JpdHkgb2YgdGhlIHByZXZpb3VzIGNvbnRyYWN0aW5nIGNoYXJhY3RlciBpbiB0aGUKICogc3RyaW5nLgogKiBAcGFyYW0gY2ggdGhlIHN0YXJ0aW5nIGNoYXJhY3RlciBvZiBhIGNvbnRyYWN0aW5nIGNoYXJhY3RlciB0b2tlbgogKiBAcmV0dXJuIHRoZSBuZXh0IGNvbnRyYWN0aW5nIGNoYXJhY3RlcidzIG9yZGVyaW5nLiAgUmV0dXJucyBOVUxMT1JERVIKICogaWYgdGhlIGVuZCBvZiBzdHJpbmcgaXMgcmVhY2hlZC4KICovCi8qIHN5bndlZSA6IHJlbW92ZWQKaW50MzJfdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnByZXZDb250cmFjdENoYXIoVUNoYXIzMiBjaCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSAmc3RhdHVzKQp7CiAgICAvLyBGaXJzdCBnZXQgdGhlIG9yZGVyaW5nIG9mIHRoaXMgc2luZ2xlIGNoYXJhY3RlcgogICAgVmVjdG9yT2ZQVG9Db250cmFjdEVsZW1lbnQgKmxpc3QgPSBvcmRlckFsaWFzLT5nZXRDb250cmFjdFZhbHVlcygoVUNoYXIpY2gpOwogICAgRW50cnlQYWlyICpwYWlyID0gKEVudHJ5UGFpciAqKWxpc3QtPmF0KDApOwogICAgaW50MzJfdCBvcmRlciA9IHBhaXItPnZhbHVlOwoKICAgIC8vIE5vdyBpdGVyYXRlIHRocm91Z2ggdGhlIGNoYXJzIGZvbGxvd2luZyBpdCBhbmQKICAgIC8vIGxvb2sgZm9yIHRoZSBsb25nZXN0IG1hdGNoCiAgICBrZXkucmVtb3ZlKCk7CiAgICBrZXkgKz0gY2g7CgogICAgd2hpbGUgKChjaCA9IHRleHQtPnByZXZpb3VzKCkpICE9IE5vcm1hbGl6ZXI6OkRPTkUpCiAgICB7CiAgICAgICAga2V5ICs9IGNoOwoKICAgICAgICBpbnQzMl90IG4gPSBSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0RW50cnkobGlzdCwga2V5LCBGQUxTRSk7CgogICAgICAgIGlmIChuID09IFJ1bGVCYXNlZENvbGxhdG9yOjpVTk1BUFBFRCkKICAgICAgICB7CiAgICAgICAgICAgIGNoID0gdGV4dC0+bmV4dCgpOwoKICAgICAgICAgICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXR1cm4gTlVMTE9SREVSOwogICAgICAgICAgICB9CgogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIHBhaXIgPSAoRW50cnlQYWlyICopbGlzdC0+YXQobik7CiAgICAgICAgb3JkZXIgPSBwYWlyLT52YWx1ZTsKICAgIH0KCiAgICByZXR1cm4gb3JkZXI7Cn0KKi8KCi8qKgogKiBUaGlzIG1ldGhvZCBwcm9kdWNlcyBhIGJ1ZmZlciB3aGljaCBjb250YWlucyB0aGUgY29sbGF0aW9uCiAqIGVsZW1lbnRzIGZvciB0aGUgdHdvIGNoYXJhY3RlcnMsIHdpdGggY29sRmlyc3QncyB2YWx1ZXMgcHJlY2VkaW5nCiAqIGFub3RoZXIgY2hhcmFjdGVyJ3MuICBQcmVzdW1hYmx5LCB0aGUgb3RoZXIgY2hhcmFjdGVyIHByZWNlZGVzIGNvbEZpcnN0CiAqIGluIGxvZ2ljYWwKICogb3JkZXIgKG90aGVyd2lzZSB5b3Ugd291bGRuJ3QgbmVlZCB0aGlzIG1ldGhvZCB3b3VsZCB5b3U/KS4KICogVGhlIGFzc3VtcHRpb24gaXMgdGhhdCB0aGUgb3RoZXIgY2hhcidzIHZhbHVlKHMpIGhhdmUgYWxyZWFkeSBiZWVuCiAqIGNvbXB1dGVkLiAgSWYgdGhpcyBjaGFyIGhhcyBhIHNpbmdsZSBlbGVtZW50IGl0IGlzIHBhc3NlZCB0byB0aGlzCiAqIG1ldGhvZCBhcyBsYXN0VmFsdWUsIGFuZCBsYXN0RXhwYXNpb24gaXMgbnVsbC4gIElmIGl0IGhhcyBhbgogKiBleHBhc2lvbiBpdCBpcyBwYXNzZWQgaW4gbGFzdEV4cGFuc2lvbiwgYW5kIGNvbExhc3RWYWx1ZSBpcyBpZ25vcmVkLgogKiBUaGlzIG1ldGhvZCBtYXkgcmV0dXJuIHRoZSBvd25CdWZmZXIgYXJyYXkgYXMgaXRzIHZhbHVlIHNvIG93bkJ1ZmZlcgogKiBoYWQgYmV0dGVyIG5vdCBiZSBpbiB1c2UgYW55d2hlcmUgZWxzZS4KICovCi8qClZlY3Rvck9mSW50KiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Om1ha2VSZW9yZGVyZWRCdWZmZXIoVUNoYXIgY29sRmlyc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50MzJfdCBsYXN0VmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVmVjdG9yT2ZJbnQqIGxhc3RFeHBhbnNpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUJvb2wgZm9yd2FyZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIHsKCiAgICBWZWN0b3JPZkludCogcmVzdWx0OwoKICAgIGludDMyX3QgZmlyc3RWYWx1ZSA9IHVjbXAzMl9nZXQob3JkZXJBbGlhcy0+ZGF0YS0+bWFwcGluZywgY29sRmlyc3QpOwogICAgaWYgKGZpcnN0VmFsdWUgPj0gUnVsZUJhc2VkQ29sbGF0b3I6OkNPTlRSQUNUQ0hBUklOREVYKSB7CiAgICAgICAgZmlyc3RWYWx1ZSA9IGZvcndhcmQgPyBuZXh0Q29udHJhY3RDaGFyKGNvbEZpcnN0LCBzdGF0dXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBwcmV2Q29udHJhY3RDaGFyKGNvbEZpcnN0LCBzdGF0dXMpOwogICAgfQoKICAgIFZlY3Rvck9mSW50KiBmaXJzdEV4cGFuc2lvbiA9IE5VTEw7CiAgICBpZiAoZmlyc3RWYWx1ZSA+PSBSdWxlQmFzZWRDb2xsYXRvcjo6RVhQQU5EQ0hBUklOREVYKSB7CiAgICAgICAgZmlyc3RFeHBhbnNpb24gPSBvcmRlckFsaWFzLT5nZXRFeHBhbmRWYWx1ZUxpc3QoZmlyc3RWYWx1ZSk7CiAgICB9CgogICAgaWYgKCFmb3J3YXJkKSB7CiAgICAgICAgaW50MzJfdCB0ZW1wMSA9IGZpcnN0VmFsdWU7CiAgICAgICAgZmlyc3RWYWx1ZSA9IGxhc3RWYWx1ZTsKICAgICAgICBsYXN0VmFsdWUgPSB0ZW1wMTsKICAgICAgICBWZWN0b3JPZkludCogdGVtcDIgPSBmaXJzdEV4cGFuc2lvbjsKICAgICAgICBmaXJzdEV4cGFuc2lvbiA9IGxhc3RFeHBhbnNpb247CiAgICAgICAgbGFzdEV4cGFuc2lvbiA9IHRlbXAyOwogICAgfQoKICAgIGlmIChmaXJzdEV4cGFuc2lvbiA9PSBOVUxMICYmIGxhc3RFeHBhbnNpb24gPT0gTlVMTCkgewogICAgICAgIG93bkJ1ZmZlci0+YXQoMCkgPSBmaXJzdFZhbHVlOwogICAgICAgIG93bkJ1ZmZlci0+YXQoMSkgPSBsYXN0VmFsdWU7CiAgICAgICAgcmVzdWx0ID0gb3duQnVmZmVyOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgaW50MzJfdCBmaXJzdExlbmd0aCA9IGZpcnN0RXhwYW5zaW9uPT1OVUxMPyAxIDogZmlyc3RFeHBhbnNpb24tPnNpemUoKTsKICAgICAgICBpbnQzMl90IGxhc3RMZW5ndGggPSBsYXN0RXhwYW5zaW9uPT1OVUxMPyAxIDogbGFzdEV4cGFuc2lvbi0+c2l6ZSgpOwogICAgICAgIGlmIChyZW9yZGVyQnVmZmVyID09IE5VTEwpIHsKICAgICAgICAgICAgcmVvcmRlckJ1ZmZlciA9IG5ldyBWZWN0b3JPZkludChmaXJzdExlbmd0aCtsYXN0TGVuZ3RoKTsKICAgICAgICB9CiAgICAgICAgLy8gcmVvcmRlcmRCdWZmZXIgZ2V0cyByZXVzZWQgZm9yIHRoZSBsaWZlIG9mIHRoaXMgb2JqZWN0LgogICAgICAgIC8vIFNpbmNlIGl0cyBpbnRlcm5hbCBidWZmZXIgb25seSBncm93cywgdGhlcmUgaXMgYSBkYW5nZXIKICAgICAgICAvLyB0aGF0IGl0IHdpbGwgZ2V0IHJlYWxseSwgcmVhbGx5IGJpZywgYW5kIG5ldmVyIHNocmluay4gIElmCiAgICAgICAgLy8gdGhpcyBpcyBhY3R1YWxseSBoYXBwZW5pbmcsIGluc2VydCBjb2RlIGhlcmUgdG8gY2hlY2sgZm9yCiAgICAgICAgLy8gdGhlIGNvbmRpdGlvbi4gIFNvbWV0aGluZyBhbG9uZyB0aGUgbGluZXMgb2Y6CiAgICAgICAgLy8hIGVsc2UgaWYgKHJlb3JkZXJCdWZmZXItPnNpemUoKSA+PSAyNTYgJiYKICAgICAgICAvLyEgICAgICAgICAgKGZpcnN0TGVuZ3RoK2xhc3RMZW5ndGgpIDwgMTYpIHsKICAgICAgICAvLyEgICAgIGRlbGV0ZSByZW9yZGVyQnVmZmVyOwogICAgICAgIC8vISAgICAgcmVvcmRlckJ1ZmZlciA9IG5ldyBWZWN0b3JPZkludChmaXJzdExlbmd0aCtsYXN0TGVuZ3RoKTsKICAgICAgICAvLyEgfQogICAgICAgIC8vIFRoZSBzcGVjaWZpYyBudW1lcmljIHZhbHVlcyBuZWVkIHRvIGJlIGRldGVybWluZWQKICAgICAgICAvLyBlbXBpcmljYWxseS4gW2FsaXVdCiAgICAgICAgcmVzdWx0ID0gcmVvcmRlckJ1ZmZlcjsKCiAgICAgICAgaWYgKGZpcnN0RXhwYW5zaW9uID09IE5VTEwpIHsKICAgICAgICAgICAgcmVzdWx0LT5hdFB1dCgwLCBmaXJzdFZhbHVlKTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIC8vIFN5c3RlbS5hcnJheWNvcHkoZmlyc3RFeHBhbnNpb24sIDAsIHJlc3VsdCwgMCwgZmlyc3RMZW5ndGgpOwogICAgICAgICAgICAqcmVzdWx0ID0gKmZpcnN0RXhwYW5zaW9uOwogICAgICAgIH0KCiAgICAgICAgaWYgKGxhc3RFeHBhbnNpb24gPT0gTlVMTCkgewogICAgICAgICAgICByZXN1bHQtPmF0UHV0KGZpcnN0TGVuZ3RoLCBsYXN0VmFsdWUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgLy8gU3lzdGVtLmFycmF5Y29weShsYXN0RXhwYW5zaW9uLCAwLCByZXN1bHQsIGZpcnN0TGVuZ3RoLCBsYXN0TGVuZ3RoKTsKICAgICAgICAgICAgZm9yIChpbnQzMl90IGk9MDsgaTxsYXN0TGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgIHJlc3VsdC0+YXRQdXQoZmlyc3RMZW5ndGggKyBpLCBsYXN0RXhwYW5zaW9uLT5hdChpKSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmVzdWx0LT5zZXRTaXplKGZpcnN0TGVuZ3RoK2xhc3RMZW5ndGgpOwogICAgfQoKICAgIHJldHVybiByZXN1bHQ7Cn0KKi8K