LyoKICogQ09NIHByb3h5IGltcGxlbWVudGF0aW9uCiAqCiAqIENvcHlyaWdodCAyMDAxIE92ZSBL5XZlbiwgVHJhbnNHYW1pbmcgVGVjaG5vbG9naWVzCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIKICogdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVQogKiBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3QsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEsIFVTQQogKiAKICogVE9ETzogSGFuZGxlIG5vbi1pMzg2IGFyY2hpdGVjdHVyZXMKICovCgojaW5jbHVkZSA8c3RkYXJnLmg+CgojZGVmaW5lIENPQkpNQUNST1MKCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmVycm9yLmgiCgojaW5jbHVkZSAib2JqYmFzZS5oIgojaW5jbHVkZSAicnBjcHJveHkuaCIKCiNpbmNsdWRlICJjcHNmLmgiCiNpbmNsdWRlICJuZHJfbWlzYy5oIgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKV0lORV9ERUZBVUxUX0RFQlVHX0NIQU5ORUwob2xlKTsKCnN0cnVjdCBTdHVibGVzc1RodW5rOwoKLyogSSBkb24ndCBrbm93IHdoYXQgTVMncyBzdGQgcHJveHkgc3RydWN0dXJlIGxvb2tzIGxpa2UsCiAgIHNvIHRoaXMgcHJvYmFibHkgZG9lc24ndCBtYXRjaCwgYnV0IHRoYXQgc2hvdWxkbid0IG1hdHRlciAqLwp0eXBlZGVmIHN0cnVjdCB7CiAgY29uc3QgSVJwY1Byb3h5QnVmZmVyVnRibCAqbHBWdGJsOwogIExQVk9JRCAqUFZ0Ymw7CiAgTE9ORyBSZWZDb3VudDsKICBjb25zdCBNSURMX1NUVUJMRVNTX1BST1hZX0lORk8gKnN0dWJsZXNzOwogIGNvbnN0IElJRCogcGlpZDsKICBMUFVOS05PV04gcFVua091dGVyOwogIFBDSW50ZXJmYWNlTmFtZSBuYW1lOwogIExQUFNGQUNUT1JZQlVGRkVSIHBQU0ZhY3Rvcnk7CiAgTFBSUENDSEFOTkVMQlVGRkVSIHBDaGFubmVsOwogIHN0cnVjdCBTdHVibGVzc1RodW5rICp0aHVua3M7Cn0gU3RkUHJveHlJbXBsOwoKc3RhdGljIGNvbnN0IElScGNQcm94eUJ1ZmZlclZ0YmwgU3RkUHJveHlfVnRibDsKCiNkZWZpbmUgSUNPTV9USElTX01VTFRJKGltcGwsZmllbGQsaWZhY2UpIGltcGwqIGNvbnN0IFRoaXM9KGltcGwqKSgoY2hhciopKGlmYWNlKSAtIG9mZnNldG9mKGltcGwsZmllbGQpKQoKI2lmIGRlZmluZWQoX19pMzg2X18pCgojaW5jbHVkZSAicHNocGFjazEuaCIKCnN0cnVjdCBTdHVibGVzc1RodW5rIHsKICBCWVRFIHB1c2g7CiAgRFdPUkQgaW5kZXg7CiAgQllURSBjYWxsOwogIExPTkcgaGFuZGxlcjsKICBCWVRFIHJldDsKICBXT1JEIGJ5dGVzOwogIEJZVEUgcGFkWzNdOwp9OwoKI2luY2x1ZGUgInBvcHBhY2suaCIKCi8qIGFkanVzdCB0aGUgc3RhY2sgc2l6ZSBzaW5jZSB3ZSBkb24ndCB1c2UgV2luZG93cydzIG1ldGhvZCAqLwojZGVmaW5lIFNUQUNLX0FESlVTVCBzaXplb2YoRFdPUkQpCgojZGVmaW5lIEZJTExfU1RVQkxFU1MoeCxpZHgsc3RrKSBcCiB4LT5wdXNoID0gMHg2ODsgLyogcHVzaGwgW2ltbWVkaWF0ZV0gKi8gXAogeC0+aW5kZXggPSAoaWR4KTsgXAogeC0+Y2FsbCA9IDB4ZTg7IC8qIGNhbGwgW25lYXJdICovIFwKIHgtPmhhbmRsZXIgPSAoY2hhciopT2JqZWN0U3R1Ymxlc3MgLSAoY2hhciopJngtPnJldDsgXAogeC0+cmV0ID0gMHhjMjsgLyogcmV0IFtpbW1lZGlhdGVdICovIFwKIHgtPmJ5dGVzID0gc3RrOyBcCiB4LT5wYWRbMF0gPSAweDhkOyAvKiBsZWFsICglZXNpKSwlZXNpICovIFwKIHgtPnBhZFsxXSA9IDB4NzY7IFwKIHgtPnBhZFsyXSA9IDB4MDA7CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgT2JqZWN0U3R1Ymxlc3MoRFdPUkQgaW5kZXgpCnsKICBjaGFyICphcmdzID0gKGNoYXIqKSgmaW5kZXggKyAyKTsKICBMUFZPSUQgaWZhY2UgPSAqKExQVk9JRCopYXJnczsKCiAgSUNPTV9USElTX01VTFRJKFN0ZFByb3h5SW1wbCxQVnRibCxpZmFjZSk7CgogIFBGT1JNQVRfU1RSSU5HIGZzID0gVGhpcy0+c3R1Ymxlc3MtPlByb2NGb3JtYXRTdHJpbmcgKyBUaGlzLT5zdHVibGVzcy0+Rm9ybWF0U3RyaW5nT2Zmc2V0W2luZGV4XTsKICB1bnNpZ25lZCBieXRlcyA9ICooY29uc3QgV09SRCopKGZzKzgpIC0gU1RBQ0tfQURKVVNUOwogIFRSQUNFKCIoJXApLT4oJWQpKFslZCBieXRlc10pIHJldD0lMDh4XG4iLCBpZmFjZSwgaW5kZXgsIGJ5dGVzLCAqKERXT1JEKikoYXJncytieXRlcykpOwoKICByZXR1cm4gTmRyQ2xpZW50Q2FsbDIoVGhpcy0+c3R1Ymxlc3MtPnBTdHViRGVzYywgZnMsIGFyZ3MpOwp9CgojZWxzZSAgLyogX19pMzg2X18gKi8KCi8qIGNhbid0IGRvIHRoYXQgb24gdGhpcyBhcmNoICovCnN0cnVjdCBTdHVibGVzc1RodW5rIHsgaW50IGR1bW15OyB9OwojZGVmaW5lIEZJTExfU1RVQkxFU1MoeCxpZHgsc3RrKSBcCiBFUlIoInN0dWJsZXNzIHByb3hpZXMgYXJlIG5vdCBzdXBwb3J0ZWQgb24gdGhpcyBhcmNoaXRlY3R1cmVcbiIpOwojZGVmaW5lIFNUQUNLX0FESlVTVCAwCgojZW5kaWYgIC8qIF9faTM4Nl9fICovCgpIUkVTVUxUIFdJTkFQSSBTdGRQcm94eV9Db25zdHJ1Y3QoUkVGSUlEIHJpaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQVU5LTk9XTiBwVW5rT3V0ZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFByb3h5RmlsZUluZm8gKlByb3h5SW5mbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IEluZGV4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFBTRkFDVE9SWUJVRkZFUiBwUFNGYWN0b3J5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFJQQ1BST1hZQlVGRkVSICpwcFByb3h5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFZPSUQgKnBwdk9iaikKewogIFN0ZFByb3h5SW1wbCAqVGhpczsKICBjb25zdCBNSURMX1NUVUJMRVNTX1BST1hZX0lORk8gKnN0dWJsZXNzID0gTlVMTDsKICBQQ0ludGVyZmFjZU5hbWUgbmFtZSA9IFByb3h5SW5mby0+cE5hbWVzQXJyYXlbSW5kZXhdOwogIENJbnRlcmZhY2VQcm94eVZ0YmwgKnZ0YmwgPSBQcm94eUluZm8tPnBQcm94eVZ0YmxMaXN0W0luZGV4XTsKCiAgVFJBQ0UoIiglcCwlcCwlcCwlcCwlcCkgJXNcbiIsIHBVbmtPdXRlciwgdnRibCwgcFBTRmFjdG9yeSwgcHBQcm94eSwgcHB2T2JqLCBuYW1lKTsKCiAgLyogVGFibGVWZXJzaW9uID0gMiBtZWFucyBpdCBpcyB0aGUgc3R1Ymxlc3MgdmVyc2lvbiBvZiBDSW50ZXJmYWNlUHJveHlWdGJsICovCiAgaWYgKFByb3h5SW5mby0+VGFibGVWZXJzaW9uID4gMSkgewogICAgc3R1Ymxlc3MgPSAqKGNvbnN0IHZvaWQgKiopdnRibDsKICAgIHZ0YmwgPSAoQ0ludGVyZmFjZVByb3h5VnRibCAqKSgoY29uc3Qgdm9pZCAqKil2dGJsICsgMSk7CiAgICBUUkFDRSgic3R1Ymxlc3M9JXBcbiIsIHN0dWJsZXNzKTsKICB9CgogIFRSQUNFKCJpaWQ9JXNcbiIsIGRlYnVnc3RyX2d1aWQodnRibC0+aGVhZGVyLnBpaWQpKTsKICBUUkFDRSgidnRibD0lcFxuIiwgdnRibC0+VnRibCk7CgogIGlmICghSXNFcXVhbEdVSUQodnRibC0+aGVhZGVyLnBpaWQsIHJpaWQpKSB7CiAgICBFUlIoIklJRCBtaXNtYXRjaCBkdXJpbmcgcHJveHkgY3JlYXRpb25cbiIpOwogICAgcmV0dXJuIFJQQ19FX1VORVhQRUNURUQ7CiAgfQoKICBUaGlzID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksSEVBUF9aRVJPX01FTU9SWSxzaXplb2YoU3RkUHJveHlJbXBsKSk7CiAgaWYgKCFUaGlzKSByZXR1cm4gRV9PVVRPRk1FTU9SWTsKCiAgaWYgKHN0dWJsZXNzKSB7CiAgICBDSW50ZXJmYWNlU3R1YlZ0YmwgKnN2dGJsID0gUHJveHlJbmZvLT5wU3R1YlZ0YmxMaXN0W0luZGV4XTsKICAgIHVuc2lnbmVkIGxvbmcgaSwgY291bnQgPSBzdnRibC0+aGVhZGVyLkRpc3BhdGNoVGFibGVDb3VudDsKICAgIC8qIE1heWJlIHRoZSBvcmlnaW5hbCB2dGJsIGlzIGp1c3QgbW9kaWZpZWQgZGlyZWN0bHkgdG8gcG9pbnQgYXQKICAgICAqIE9iamVjdFN0dWJsZXNzQ2xpZW50WFhYIHRodW5rcyBpbiByZWFsIFdpbmRvd3MsIGJ1dCBJIGRvbid0IGxpa2UgaXQKICAgICAqLwogICAgVFJBQ0UoInN0dWJsZXNzIHRodW5rczogY291bnQ9JWxkXG4iLCBjb3VudCk7CiAgICBUaGlzLT50aHVua3MgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwwLHNpemVvZihzdHJ1Y3QgU3R1Ymxlc3NUaHVuaykqY291bnQpOwogICAgVGhpcy0+UFZ0YmwgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwwLHNpemVvZihMUFZPSUQpKmNvdW50KTsKICAgIGZvciAoaT0wOyBpPGNvdW50OyBpKyspIHsKICAgICAgc3RydWN0IFN0dWJsZXNzVGh1bmsgKnRodW5rID0gJlRoaXMtPnRodW5rc1tpXTsKICAgICAgaWYgKHZ0YmwtPlZ0YmxbaV0gPT0gKExQVk9JRCktMSkgewogICAgICAgIFBGT1JNQVRfU1RSSU5HIGZzID0gc3R1Ymxlc3MtPlByb2NGb3JtYXRTdHJpbmcgKyBzdHVibGVzcy0+Rm9ybWF0U3RyaW5nT2Zmc2V0W2ldOwogICAgICAgIHVuc2lnbmVkIGJ5dGVzID0gKihjb25zdCBXT1JEKikoZnMrOCkgLSBTVEFDS19BREpVU1Q7CiAgICAgICAgVFJBQ0UoIm1ldGhvZCAlbGQ6IHN0YWNrc2l6ZT0lZFxuIiwgaSwgYnl0ZXMpOwogICAgICAgIEZJTExfU1RVQkxFU1ModGh1bmssIGksIGJ5dGVzKQogICAgICAgIFRoaXMtPlBWdGJsW2ldID0gdGh1bms7CiAgICAgIH0KICAgICAgZWxzZSB7CiAgICAgICAgbWVtc2V0KHRodW5rLCAwLCBzaXplb2Yoc3RydWN0IFN0dWJsZXNzVGh1bmspKTsKICAgICAgICBUaGlzLT5QVnRibFtpXSA9IHZ0YmwtPlZ0YmxbaV07CiAgICAgIH0KICAgIH0KICB9CiAgZWxzZSAKICAgIFRoaXMtPlBWdGJsID0gdnRibC0+VnRibDsKCiAgVGhpcy0+bHBWdGJsID0gJlN0ZFByb3h5X1Z0Ymw7CiAgLyogb25lIHJlZmVyZW5jZSBmb3IgdGhlIHByb3h5ICovCiAgVGhpcy0+UmVmQ291bnQgPSAxOwogIFRoaXMtPnN0dWJsZXNzID0gc3R1Ymxlc3M7CiAgVGhpcy0+cGlpZCA9IHZ0YmwtPmhlYWRlci5waWlkOwogIFRoaXMtPnBVbmtPdXRlciA9IHBVbmtPdXRlcjsKICBUaGlzLT5uYW1lID0gbmFtZTsKICBUaGlzLT5wUFNGYWN0b3J5ID0gcFBTRmFjdG9yeTsKICBUaGlzLT5wQ2hhbm5lbCA9IE5VTEw7CiAgKnBwUHJveHkgPSAoTFBSUENQUk9YWUJVRkZFUikmVGhpcy0+bHBWdGJsOwogICpwcHZPYmogPSAmVGhpcy0+UFZ0Ymw7CiAgLyogaWYgdGhlcmUgaXMgbm8gb3V0ZXIgdW5rbm93biB0aGVuIHRoZSBjYWxsZXIgd2lsbCBjb250cm9sIHRoZSBsaWZldGltZQogICAqIG9mIHRoZSBwcm94eSBvYmplY3QgdGhyb3VnaCB0aGUgcHJveHkgYnVmZmVyLCBzbyBubyBuZWVkIHRvIGluY3JlbWVudCB0aGUKICAgKiByZWYgY291bnQgb2YgdGhlIHByb3h5IG9iamVjdCAqLwogIGlmIChwVW5rT3V0ZXIpCiAgICBJVW5rbm93bl9BZGRSZWYoKElVbmtub3duICopKnBwdk9iaik7CiAgSVBTRmFjdG9yeUJ1ZmZlcl9BZGRSZWYocFBTRmFjdG9yeSk7CgogIHJldHVybiBTX09LOwp9CgpzdGF0aWMgdm9pZCBXSU5BUEkgU3RkUHJveHlfRGVzdHJ1Y3QoTFBSUENQUk9YWUJVRkZFUiBpZmFjZSkKewogIElDT01fVEhJU19NVUxUSShTdGRQcm94eUltcGwsbHBWdGJsLGlmYWNlKTsKCiAgaWYgKFRoaXMtPnBDaGFubmVsKQogICAgSVJwY1Byb3h5QnVmZmVyX0Rpc2Nvbm5lY3QoaWZhY2UpOwoKICBJUFNGYWN0b3J5QnVmZmVyX1JlbGVhc2UoVGhpcy0+cFBTRmFjdG9yeSk7CiAgaWYgKFRoaXMtPnRodW5rcykgewogICAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwwLFRoaXMtPlBWdGJsKTsKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksMCxUaGlzLT50aHVua3MpOwogIH0KICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLDAsVGhpcyk7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBTdGRQcm94eV9RdWVyeUludGVyZmFjZShMUFJQQ1BST1hZQlVGRkVSIGlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRUZJSUQgcmlpZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTFBWT0lEICpvYmopCnsKICBJQ09NX1RISVNfTVVMVEkoU3RkUHJveHlJbXBsLGxwVnRibCxpZmFjZSk7CiAgVFJBQ0UoIiglcCktPlF1ZXJ5SW50ZXJmYWNlKCVzLCVwKVxuIixUaGlzLGRlYnVnc3RyX2d1aWQocmlpZCksb2JqKTsKCiAgaWYgKElzRXF1YWxHVUlEKCZJSURfSVVua25vd24scmlpZCkgfHwKICAgICAgSXNFcXVhbEdVSUQoVGhpcy0+cGlpZCxyaWlkKSkgewogICAgKm9iaiA9ICZUaGlzLT5QVnRibDsKICAgIEludGVybG9ja2VkSW5jcmVtZW50KCZUaGlzLT5SZWZDb3VudCk7CiAgICByZXR1cm4gU19PSzsKICB9CgogIGlmIChJc0VxdWFsR1VJRCgmSUlEX0lScGNQcm94eUJ1ZmZlcixyaWlkKSkgewogICAgKm9iaiA9ICZUaGlzLT5scFZ0Ymw7CiAgICBJbnRlcmxvY2tlZEluY3JlbWVudCgmVGhpcy0+UmVmQ291bnQpOwogICAgcmV0dXJuIFNfT0s7CiAgfQoKICByZXR1cm4gRV9OT0lOVEVSRkFDRTsKfQoKc3RhdGljIFVMT05HIFdJTkFQSSBTdGRQcm94eV9BZGRSZWYoTFBSUENQUk9YWUJVRkZFUiBpZmFjZSkKewogIElDT01fVEhJU19NVUxUSShTdGRQcm94eUltcGwsbHBWdGJsLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+QWRkUmVmKClcbiIsVGhpcyk7CgogIHJldHVybiBJbnRlcmxvY2tlZEluY3JlbWVudCgmVGhpcy0+UmVmQ291bnQpOwp9CgpzdGF0aWMgVUxPTkcgV0lOQVBJIFN0ZFByb3h5X1JlbGVhc2UoTFBSUENQUk9YWUJVRkZFUiBpZmFjZSkKewogIFVMT05HIHJlZnM7CiAgSUNPTV9USElTX01VTFRJKFN0ZFByb3h5SW1wbCxscFZ0YmwsaWZhY2UpOwogIFRSQUNFKCIoJXApLT5SZWxlYXNlKClcbiIsVGhpcyk7CgogIHJlZnMgPSBJbnRlcmxvY2tlZERlY3JlbWVudCgmVGhpcy0+UmVmQ291bnQpOwogIGlmICghcmVmcykKICAgIFN0ZFByb3h5X0Rlc3RydWN0KChMUFJQQ1BST1hZQlVGRkVSKSZUaGlzLT5scFZ0YmwpOwogIHJldHVybiByZWZzOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgU3RkUHJveHlfQ29ubmVjdChMUFJQQ1BST1hZQlVGRkVSIGlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQUlBDQ0hBTk5FTEJVRkZFUiBwQ2hhbm5lbCkKewogIElDT01fVEhJU19NVUxUSShTdGRQcm94eUltcGwsbHBWdGJsLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+Q29ubmVjdCglcClcbiIsVGhpcyxwQ2hhbm5lbCk7CgogIFRoaXMtPnBDaGFubmVsID0gcENoYW5uZWw7CiAgSVJwY0NoYW5uZWxCdWZmZXJfQWRkUmVmKHBDaGFubmVsKTsKICByZXR1cm4gU19PSzsKfQoKc3RhdGljIFZPSUQgV0lOQVBJIFN0ZFByb3h5X0Rpc2Nvbm5lY3QoTFBSUENQUk9YWUJVRkZFUiBpZmFjZSkKewogIElDT01fVEhJU19NVUxUSShTdGRQcm94eUltcGwsbHBWdGJsLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+RGlzY29ubmVjdCgpXG4iLFRoaXMpOwoKICBJUnBjQ2hhbm5lbEJ1ZmZlcl9SZWxlYXNlKFRoaXMtPnBDaGFubmVsKTsKICBUaGlzLT5wQ2hhbm5lbCA9IE5VTEw7Cn0KCnN0YXRpYyBjb25zdCBJUnBjUHJveHlCdWZmZXJWdGJsIFN0ZFByb3h5X1Z0YmwgPQp7CiAgU3RkUHJveHlfUXVlcnlJbnRlcmZhY2UsCiAgU3RkUHJveHlfQWRkUmVmLAogIFN0ZFByb3h5X1JlbGVhc2UsCiAgU3RkUHJveHlfQ29ubmVjdCwKICBTdGRQcm94eV9EaXNjb25uZWN0Cn07CgpzdGF0aWMgdm9pZCBTdGRQcm94eV9HZXRDaGFubmVsKExQVk9JRCBpZmFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFJQQ0NIQU5ORUxCVUZGRVIgKnBwQ2hhbm5lbCkKewogIElDT01fVEhJU19NVUxUSShTdGRQcm94eUltcGwsUFZ0YmwsaWZhY2UpOwogIFRSQUNFKCIoJXApLT5HZXRDaGFubmVsKCVwKSAlc1xuIixUaGlzLHBwQ2hhbm5lbCxUaGlzLT5uYW1lKTsKCiAgKnBwQ2hhbm5lbCA9IFRoaXMtPnBDaGFubmVsOwp9CgpzdGF0aWMgdm9pZCBTdGRQcm94eV9HZXRJSUQoTFBWT0lEIGlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgSUlEICoqcHBpaWQpCnsKICBJQ09NX1RISVNfTVVMVEkoU3RkUHJveHlJbXBsLFBWdGJsLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+R2V0SUlEKCVwKSAlc1xuIixUaGlzLHBwaWlkLFRoaXMtPm5hbWUpOwoKICAqcHBpaWQgPSBUaGlzLT5waWlkOwp9CgpIUkVTVUxUIFdJTkFQSSBJVW5rbm93bl9RdWVyeUludGVyZmFjZV9Qcm94eShMUFVOS05PV04gaWZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVGSUlEIHJpaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTFBWT0lEICpwcHZPYmopCnsKICBJQ09NX1RISVNfTVVMVEkoU3RkUHJveHlJbXBsLFBWdGJsLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+UXVlcnlJbnRlcmZhY2UoJXMsJXApICVzXG4iLFRoaXMsZGVidWdzdHJfZ3VpZChyaWlkKSxwcHZPYmosVGhpcy0+bmFtZSk7CiAgcmV0dXJuIElVbmtub3duX1F1ZXJ5SW50ZXJmYWNlKFRoaXMtPnBVbmtPdXRlcixyaWlkLHBwdk9iaik7Cn0KClVMT05HIFdJTkFQSSBJVW5rbm93bl9BZGRSZWZfUHJveHkoTFBVTktOT1dOIGlmYWNlKQp7CiAgSUNPTV9USElTX01VTFRJKFN0ZFByb3h5SW1wbCxQVnRibCxpZmFjZSk7CiAgVFJBQ0UoIiglcCktPkFkZFJlZigpICVzXG4iLFRoaXMsVGhpcy0+bmFtZSk7CiAgcmV0dXJuIElVbmtub3duX0FkZFJlZihUaGlzLT5wVW5rT3V0ZXIpOwp9CgpVTE9ORyBXSU5BUEkgSVVua25vd25fUmVsZWFzZV9Qcm94eShMUFVOS05PV04gaWZhY2UpCnsKICBJQ09NX1RISVNfTVVMVEkoU3RkUHJveHlJbXBsLFBWdGJsLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+UmVsZWFzZSgpICVzXG4iLFRoaXMsVGhpcy0+bmFtZSk7CiAgcmV0dXJuIElVbmtub3duX1JlbGVhc2UoVGhpcy0+cFVua091dGVyKTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBOZHJQcm94eUluaXRpYWxpemUgW1JQQ1JUNC5AXQogKi8Kdm9pZCBXSU5BUEkgTmRyUHJveHlJbml0aWFsaXplKHZvaWQgKlRoaXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBSUENfTUVTU0FHRSBwUnBjTXNnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQTUlETF9TVFVCX01FU1NBR0UgcFN0dWJNc2csCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBNSURMX1NUVUJfREVTQyBwU3R1YkRlc2NyaXB0b3IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGludCBQcm9jTnVtKQp7CiAgVFJBQ0UoIiglcCwlcCwlcCwlcCwlZClcbiIsIFRoaXMsIHBScGNNc2csIHBTdHViTXNnLCBwU3R1YkRlc2NyaXB0b3IsIFByb2NOdW0pOwogIE5kckNsaWVudEluaXRpYWxpemVOZXcocFJwY01zZywgcFN0dWJNc2csIHBTdHViRGVzY3JpcHRvciwgUHJvY051bSk7CiAgU3RkUHJveHlfR2V0Q2hhbm5lbChUaGlzLCAmcFN0dWJNc2ctPnBScGNDaGFubmVsQnVmZmVyKTsKICBJUnBjQ2hhbm5lbEJ1ZmZlcl9HZXREZXN0Q3R4KHBTdHViTXNnLT5wUnBjQ2hhbm5lbEJ1ZmZlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICZwU3R1Yk1zZy0+ZHdEZXN0Q29udGV4dCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICZwU3R1Yk1zZy0+cHZEZXN0Q29udGV4dCk7CiAgVFJBQ0UoImNoYW5uZWw9JXBcbiIsIHBTdHViTXNnLT5wUnBjQ2hhbm5lbEJ1ZmZlcik7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiAgICAgICAgICAgTmRyUHJveHlHZXRCdWZmZXIgW1JQQ1JUNC5AXQogKi8Kdm9pZCBXSU5BUEkgTmRyUHJveHlHZXRCdWZmZXIodm9pZCAqVGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQTUlETF9TVFVCX01FU1NBR0UgcFN0dWJNc2cpCnsKICBIUkVTVUxUIGhyOwogIGNvbnN0IElJRCAqcmlpZCA9IE5VTEw7CgogIFRSQUNFKCIoJXAsJXApXG4iLCBUaGlzLCBwU3R1Yk1zZyk7CiAgcFN0dWJNc2ctPlJwY01zZy0+QnVmZmVyTGVuZ3RoID0gcFN0dWJNc2ctPkJ1ZmZlckxlbmd0aDsKICBwU3R1Yk1zZy0+ZHdTdHViUGhhc2UgPSBQUk9YWV9HRVRCVUZGRVI7CiAgU3RkUHJveHlfR2V0SUlEKFRoaXMsICZyaWlkKTsKICBociA9IElScGNDaGFubmVsQnVmZmVyX0dldEJ1ZmZlcihwU3R1Yk1zZy0+cFJwY0NoYW5uZWxCdWZmZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoUlBDT0xFTUVTU0FHRSopcFN0dWJNc2ctPlJwY01zZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpaWQpOwogIGlmIChGQUlMRUQoaHIpKQogIHsKICAgIFJwY1JhaXNlRXhjZXB0aW9uKGhyKTsKICAgIHJldHVybjsKICB9CiAgcFN0dWJNc2ctPmZCdWZmZXJWYWxpZCA9IFRSVUU7CiAgcFN0dWJNc2ctPkJ1ZmZlclN0YXJ0ID0gcFN0dWJNc2ctPlJwY01zZy0+QnVmZmVyOwogIHBTdHViTXNnLT5CdWZmZXJFbmQgPSBwU3R1Yk1zZy0+QnVmZmVyU3RhcnQgKyBwU3R1Yk1zZy0+QnVmZmVyTGVuZ3RoOwogIHBTdHViTXNnLT5CdWZmZXIgPSBwU3R1Yk1zZy0+QnVmZmVyU3RhcnQ7CiAgcFN0dWJNc2ctPmR3U3R1YlBoYXNlID0gUFJPWFlfTUFSU0hBTDsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBOZHJQcm94eVNlbmRSZWNlaXZlIFtSUENSVDQuQF0KICovCnZvaWQgV0lOQVBJIE5kclByb3h5U2VuZFJlY2VpdmUodm9pZCAqVGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBNSURMX1NUVUJfTUVTU0FHRSBwU3R1Yk1zZykKewogIFVMT05HIFN0YXR1cyA9IDA7CiAgSFJFU1VMVCBocjsKCiAgVFJBQ0UoIiglcCwlcClcbiIsIFRoaXMsIHBTdHViTXNnKTsKCiAgaWYgKCFwU3R1Yk1zZy0+cFJwY0NoYW5uZWxCdWZmZXIpCiAgewogICAgV0FSTigiVHJ5aW5nIHRvIHVzZSBkaXNjb25uZWN0ZWQgcHJveHkgJXBcbiIsIFRoaXMpOwogICAgUnBjUmFpc2VFeGNlcHRpb24oUlBDX0VfRElTQ09OTkVDVEVEKTsKICB9CgogIHBTdHViTXNnLT5kd1N0dWJQaGFzZSA9IFBST1hZX1NFTkRSRUNFSVZFOwogIGhyID0gSVJwY0NoYW5uZWxCdWZmZXJfU2VuZFJlY2VpdmUocFN0dWJNc2ctPnBScGNDaGFubmVsQnVmZmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoUlBDT0xFTUVTU0FHRSopcFN0dWJNc2ctPlJwY01zZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJlN0YXR1cyk7CiAgcFN0dWJNc2ctPmR3U3R1YlBoYXNlID0gUFJPWFlfVU5NQVJTSEFMOwogIHBTdHViTXNnLT5CdWZmZXJMZW5ndGggPSBwU3R1Yk1zZy0+UnBjTXNnLT5CdWZmZXJMZW5ndGg7CiAgcFN0dWJNc2ctPkJ1ZmZlclN0YXJ0ID0gcFN0dWJNc2ctPlJwY01zZy0+QnVmZmVyOwogIHBTdHViTXNnLT5CdWZmZXJFbmQgPSBwU3R1Yk1zZy0+QnVmZmVyU3RhcnQgKyBwU3R1Yk1zZy0+QnVmZmVyTGVuZ3RoOwogIHBTdHViTXNnLT5CdWZmZXIgPSBwU3R1Yk1zZy0+QnVmZmVyU3RhcnQ7CgogIC8qIHJhaXNlIGV4Y2VwdGlvbiBpZiBjYWxsIGZhaWxlZCAqLwogIGlmIChociA9PSBSUENfU19DQUxMX0ZBSUxFRCkgUnBjUmFpc2VFeGNlcHRpb24oKihEV09SRCopcFN0dWJNc2ctPkJ1ZmZlcik7CiAgZWxzZSBpZiAoRkFJTEVEKGhyKSkgUnBjUmFpc2VFeGNlcHRpb24oaHIpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgIE5kclByb3h5RnJlZUJ1ZmZlciBbUlBDUlQ0LkBdCiAqLwp2b2lkIFdJTkFQSSBOZHJQcm94eUZyZWVCdWZmZXIodm9pZCAqVGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUE1JRExfU1RVQl9NRVNTQUdFIHBTdHViTXNnKQp7CiAgVFJBQ0UoIiglcCwlcClcbiIsIFRoaXMsIHBTdHViTXNnKTsKCiAgaWYgKHBTdHViTXNnLT5mQnVmZmVyVmFsaWQpCiAgewogICAgSVJwY0NoYW5uZWxCdWZmZXJfRnJlZUJ1ZmZlcihwU3R1Yk1zZy0+cFJwY0NoYW5uZWxCdWZmZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChSUENPTEVNRVNTQUdFKilwU3R1Yk1zZy0+UnBjTXNnKTsKICAgIHBTdHViTXNnLT5mQnVmZmVyVmFsaWQgPSBUUlVFOwogIH0KfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBOZHJQcm94eUVycm9ySGFuZGxlciBbUlBDUlQ0LkBdCiAqLwpIUkVTVUxUIFdJTkFQSSBOZHJQcm94eUVycm9ySGFuZGxlcihEV09SRCBkd0V4Y2VwdGlvbkNvZGUpCnsKICBXQVJOKCIoMHglMDh4KTogYSBwcm94eSBjYWxsIGZhaWxlZFxuIiwgZHdFeGNlcHRpb25Db2RlKTsKCiAgaWYgKEZBSUxFRChkd0V4Y2VwdGlvbkNvZGUpKQogICAgcmV0dXJuIGR3RXhjZXB0aW9uQ29kZTsKICBlbHNlCiAgICByZXR1cm4gSFJFU1VMVF9GUk9NX1dJTjMyKGR3RXhjZXB0aW9uQ29kZSk7Cn0KCkhSRVNVTFQgV0lOQVBJCkNyZWF0ZVByb3h5RnJvbVR5cGVJbmZvKCBMUFRZUEVJTkZPIHBUeXBlSW5mbywgTFBVTktOT1dOIHBVbmtPdXRlciwgUkVGSUlEIHJpaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICBMUFJQQ1BST1hZQlVGRkVSICpwcFByb3h5LCBMUFZPSUQgKnBwdiApCnsKICAgIHR5cGVkZWYgSU5UIChXSU5BUEkgKk1lc3NhZ2VCb3hBKShIV05ELExQQ1NUUixMUENTVFIsVUlOVCk7CiAgICBITU9EVUxFIGhVc2VyMzIgPSBMb2FkTGlicmFyeUEoInVzZXIzMiIpOwogICAgTWVzc2FnZUJveEEgcE1lc3NhZ2VCb3hBID0gKHZvaWQgKilHZXRQcm9jQWRkcmVzcyhoVXNlcjMyLCAiTWVzc2FnZUJveEEiKTsKCiAgICBGSVhNRSgiJXAgJXAgJXMgJXAgJXBcbiIsIHBUeXBlSW5mbywgcFVua091dGVyLCBkZWJ1Z3N0cl9ndWlkKHJpaWQpLCBwcFByb3h5LCBwcHYpOwogICAgaWYgKHBNZXNzYWdlQm94QSkKICAgIHsKICAgICAgICBwTWVzc2FnZUJveEEoTlVMTCwKICAgICAgICAgICAgIlRoZSBuYXRpdmUgaW1wbGVtZW50YXRpb24gb2YgT0xFQVVUMzIuRExMIGNhbm5vdCBiZSB1c2VkICIKICAgICAgICAgICAgIndpdGggV2luZSdzIFJQQ1JUNC5ETEwuIFJlbW92ZSBPTEVBVVQzMi5ETEwgYW5kIHRyeSBhZ2Fpbi5cbiIsCiAgICAgICAgICAgICJXaW5lOiBVbmltcGxlbWVudGVkIENyZWF0ZVByb3h5RnJvbVR5cGVJbmZvIiwKICAgICAgICAgICAgMHgxMCk7CiAgICAgICAgRXhpdFByb2Nlc3MoMSk7CiAgICB9CiAgICByZXR1cm4gRV9OT1RJTVBMOwp9Cg==