LyoKICogQ09NIHN0dWIgKENTdGRTdHViQnVmZmVyKSBpbXBsZW1lbnRhdGlvbgogKgogKiBDb3B5cmlnaHQgMjAwMSBPdmUgS+V2ZW4sIFRyYW5zR2FtaW5nIFRlY2hub2xvZ2llcwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojaW5jbHVkZSAid2luZGVmLmgiCiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5lcnJvci5oIgoKI2luY2x1ZGUgIm9iamJhc2UuaCIKCiNpbmNsdWRlICJycGNwcm94eS5oIgoKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKCiNpbmNsdWRlICJjcHNmLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChvbGUpOwoKI2RlZmluZSBTVFVCX0hFQURFUihUaGlzKSAoKChDSW50ZXJmYWNlU3R1YkhlYWRlciopKChUaGlzKS0+bHBWdGJsKSlbLTFdKQoKSFJFU1VMVCBXSU5BUEkgQ1N0ZFN0dWJCdWZmZXJfQ29uc3RydWN0KFJFRklJRCByaWlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFVOS05PV04gcFVua1NlcnZlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUENJbnRlcmZhY2VOYW1lIG5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENJbnRlcmZhY2VTdHViVnRibCAqdnRibCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTFBQU0ZBQ1RPUllCVUZGRVIgcFBTRmFjdG9yeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTFBSUENTVFVCQlVGRkVSICpwcFN0dWIpCnsKICBDU3RkU3R1YkJ1ZmZlciAqVGhpczsKCiAgVFJBQ0UoIiglcCwlcCwlcCwlcCkgJXNcbiIsIHBVbmtTZXJ2ZXIsIHZ0YmwsIHBQU0ZhY3RvcnksIHBwU3R1YiwgbmFtZSk7CiAgVFJBQ0UoImlpZD0lc1xuIiwgZGVidWdzdHJfZ3VpZCh2dGJsLT5oZWFkZXIucGlpZCkpOwogIFRSQUNFKCJ2dGJsPSVwXG4iLCAmdnRibC0+VnRibCk7CgogIGlmICghSXNFcXVhbEdVSUQodnRibC0+aGVhZGVyLnBpaWQsIHJpaWQpKSB7CiAgICBFUlIoIklJRCBtaXNtYXRjaCBkdXJpbmcgc3R1YiBjcmVhdGlvblxuIik7CiAgICByZXR1cm4gUlBDX0VfVU5FWFBFQ1RFRDsKICB9CgogIFRoaXMgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSxIRUFQX1pFUk9fTUVNT1JZLHNpemVvZihDU3RkU3R1YkJ1ZmZlcikpOwogIGlmICghVGhpcykgcmV0dXJuIEVfT1VUT0ZNRU1PUlk7CgogIFRoaXMtPmxwVnRibCA9ICZ2dGJsLT5WdGJsOwogIFRoaXMtPlJlZkNvdW50ID0gMTsKICBUaGlzLT5wdlNlcnZlck9iamVjdCA9IHBVbmtTZXJ2ZXI7CiAgVGhpcy0+cFBTRmFjdG9yeSA9IHBQU0ZhY3Rvcnk7CiAgKnBwU3R1YiA9IChMUFJQQ1NUVUJCVUZGRVIpVGhpczsKCiAgSVVua25vd25fQWRkUmVmKFRoaXMtPnB2U2VydmVyT2JqZWN0KTsKICBJUFNGYWN0b3J5QnVmZmVyX0FkZFJlZihwUFNGYWN0b3J5KTsKICByZXR1cm4gU19PSzsKfQoKSFJFU1VMVCBXSU5BUEkgQ1N0ZFN0dWJCdWZmZXJfUXVlcnlJbnRlcmZhY2UoTFBSUENTVFVCQlVGRkVSIGlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFRklJRCByaWlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQVk9JRCAqb2JqKQp7CiAgSUNPTV9USElTKENTdGRTdHViQnVmZmVyLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+UXVlcnlJbnRlcmZhY2UoJXMsJXApXG4iLFRoaXMsZGVidWdzdHJfZ3VpZChyaWlkKSxvYmopOwoKICBpZiAoSXNFcXVhbEdVSUQoJklJRF9JVW5rbm93bixyaWlkKSB8fAogICAgICBJc0VxdWFsR1VJRCgmSUlEX0lScGNTdHViQnVmZmVyLHJpaWQpKSB7CiAgICAqb2JqID0gVGhpczsKICAgIFRoaXMtPlJlZkNvdW50Kys7CiAgICByZXR1cm4gU19PSzsKICB9CiAgcmV0dXJuIEVfTk9JTlRFUkZBQ0U7Cn0KClVMT05HIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9BZGRSZWYoTFBSUENTVFVCQlVGRkVSIGlmYWNlKQp7CiAgSUNPTV9USElTKENTdGRTdHViQnVmZmVyLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+QWRkUmVmKClcbiIsVGhpcyk7CiAgcmV0dXJuICsrKFRoaXMtPlJlZkNvdW50KTsKfQoKVUxPTkcgV0lOQVBJIE5kckNTdGRTdHViQnVmZmVyX1JlbGVhc2UoTFBSUENTVFVCQlVGRkVSIGlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQUFNGQUNUT1JZQlVGRkVSIHBQU0YpCnsKICBJQ09NX1RISVMoQ1N0ZFN0dWJCdWZmZXIsaWZhY2UpOwogIFRSQUNFKCIoJXApLT5SZWxlYXNlKClcbiIsVGhpcyk7CgogIGlmICghLS0oVGhpcy0+UmVmQ291bnQpKSB7CiAgICBpZihUaGlzLT5wdlNlcnZlck9iamVjdCkKICAgICAgICBJVW5rbm93bl9SZWxlYXNlKFRoaXMtPnB2U2VydmVyT2JqZWN0KTsKICAgIGlmKFRoaXMtPnBQU0ZhY3RvcnkpCiAgICAgICAgSVBTRmFjdG9yeUJ1ZmZlcl9SZWxlYXNlKFRoaXMtPnBQU0ZhY3RvcnkpOwogICAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwwLFRoaXMpOwogICAgcmV0dXJuIDA7CiAgfQogIHJldHVybiBUaGlzLT5SZWZDb3VudDsKfQoKSFJFU1VMVCBXSU5BUEkgQ1N0ZFN0dWJCdWZmZXJfQ29ubmVjdChMUFJQQ1NUVUJCVUZGRVIgaWZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFVOS05PV04gbHBVbmtTZXJ2ZXIpCnsKICBJQ09NX1RISVMoQ1N0ZFN0dWJCdWZmZXIsaWZhY2UpOwogIFRSQUNFKCIoJXApLT5Db25uZWN0KCVwKVxuIixUaGlzLGxwVW5rU2VydmVyKTsKICBUaGlzLT5wdlNlcnZlck9iamVjdCA9IGxwVW5rU2VydmVyOwogIHJldHVybiBTX09LOwp9Cgp2b2lkIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9EaXNjb25uZWN0KExQUlBDU1RVQkJVRkZFUiBpZmFjZSkKewogIElDT01fVEhJUyhDU3RkU3R1YkJ1ZmZlcixpZmFjZSk7CiAgVFJBQ0UoIiglcCktPkRpc2Nvbm5lY3QoKVxuIixUaGlzKTsKICBUaGlzLT5wdlNlcnZlck9iamVjdCA9IE5VTEw7Cn0KCkhSRVNVTFQgV0lOQVBJIENTdGRTdHViQnVmZmVyX0ludm9rZShMUFJQQ1NUVUJCVUZGRVIgaWZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBSUENPTEVNRVNTQUdFIHBNc2csCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQUlBDQ0hBTk5FTEJVRkZFUiBwQ2hhbm5lbCkKewogIElDT01fVEhJUyhDU3RkU3R1YkJ1ZmZlcixpZmFjZSk7CiAgRFdPUkQgZHdQaGFzZSA9IFNUVUJfVU5NQVJTSEFMOwogIFRSQUNFKCIoJXApLT5JbnZva2UoJXAsJXApXG4iLFRoaXMscE1zZyxwQ2hhbm5lbCk7CgogIFNUVUJfSEVBREVSKFRoaXMpLnBEaXNwYXRjaFRhYmxlW3BNc2ctPmlNZXRob2RdKGlmYWNlLCBwQ2hhbm5lbCwgKFBSUENfTUVTU0FHRSlwTXNnLCAmZHdQaGFzZSk7CiAgcmV0dXJuIFNfT0s7Cn0KCkxQUlBDU1RVQkJVRkZFUiBXSU5BUEkgQ1N0ZFN0dWJCdWZmZXJfSXNJSURTdXBwb3J0ZWQoTFBSUENTVFVCQlVGRkVSIGlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVGSUlEIHJpaWQpCnsKICBJQ09NX1RISVMoQ1N0ZFN0dWJCdWZmZXIsaWZhY2UpOwogIFRSQUNFKCIoJXApLT5Jc0lJRFN1cHBvcnRlZCglcylcbiIsVGhpcyxkZWJ1Z3N0cl9ndWlkKHJpaWQpKTsKICByZXR1cm4gSXNFcXVhbEdVSUQoU1RVQl9IRUFERVIoVGhpcykucGlpZCwgcmlpZCkgPyBpZmFjZSA6IE5VTEw7Cn0KClVMT05HIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9Db3VudFJlZnMoTFBSUENTVFVCQlVGRkVSIGlmYWNlKQp7CiAgSUNPTV9USElTKENTdGRTdHViQnVmZmVyLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+Q291bnRSZWZzKClcbiIsVGhpcyk7CiAgcmV0dXJuIFRoaXMtPlJlZkNvdW50Owp9CgpIUkVTVUxUIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9EZWJ1Z1NlcnZlclF1ZXJ5SW50ZXJmYWNlKExQUlBDU1RVQkJVRkZFUiBpZmFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExQVk9JRCAqcHB2KQp7CiAgSUNPTV9USElTKENTdGRTdHViQnVmZmVyLGlmYWNlKTsKICBUUkFDRSgiKCVwKS0+RGVidWdTZXJ2ZXJRdWVyeUludGVyZmFjZSglcClcbiIsVGhpcyxwcHYpOwogIHJldHVybiBTX09LOwp9Cgp2b2lkIFdJTkFQSSBDU3RkU3R1YkJ1ZmZlcl9EZWJ1Z1NlcnZlclJlbGVhc2UoTFBSUENTVFVCQlVGRkVSIGlmYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMUFZPSUQgcHYpCnsKICBJQ09NX1RISVMoQ1N0ZFN0dWJCdWZmZXIsaWZhY2UpOwogIFRSQUNFKCIoJXApLT5EZWJ1Z1NlcnZlclJlbGVhc2UoJXApXG4iLFRoaXMscHYpOwp9Cg==