LyoKICogUlBDIGVuZHBvaW50IG1hcHBlcgogKgogKiBDb3B5cmlnaHQgMjAwMiBHcmVnIFR1cm5lcgogKiBDb3B5cmlnaHQgMjAwMSBPdmUgS+V2ZW4sIFRyYW5zR2FtaW5nIFRlY2hub2xvZ2llcwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxLCBVU0EKICoKICogVE9ETzoKICogIC0gYWN0dWFsbHkgZG8gdGhpbmdzIHJpZ2h0CiAqLwoKI2luY2x1ZGUgPHN0ZGFyZy5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKI2luY2x1ZGUgIndpbmRlZi5oIgojaW5jbHVkZSAid2luYmFzZS5oIgojaW5jbHVkZSAid2luZXJyb3IuaCIKCiNpbmNsdWRlICJycGMuaCIKCiNpbmNsdWRlICJ3aW5lL2RlYnVnLmgiCgojaW5jbHVkZSAicnBjX2JpbmRpbmcuaCIKI2luY2x1ZGUgImVwbV90b3dlcnMuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKG9sZSk7CgovKiBUaGUgInJlYWwiIFJQQyBwb3J0bWFwcGVyIGVuZHBvaW50cyB0aGF0IEkga25vdyBvZiBhcmU6CiAqCiAqICBuY2FkZ19pcF91ZHA6IDEzNQogKiAgbmNhY25faXBfdGNwOiAxMzUKICogIG5jYWNuX25wOiBcXHBpcGVcZXBtYXBwZXIgKD8pCiAqICBuY2FscnBjOiBlcG1hcHBlcgogKgogKiBJZiB0aGUgdXNlcidzIG1hY2hpbmUgcmFuIGEgRENFIFJQQyBkYWVtb24sIGl0IHdvdWxkCiAqIHByb2JhYmx5IGJlIHBvc3NpYmxlIHRvIGNvbm5lY3QgdG8gaXQsIGJ1dCB0aGVyZSBhcmUgbWFueQogKiByZWFzb25zIG5vdCB0bywgbGlrZToKICogIC0gdGhlIHVzZXIgcHJvYmFibHkgZG9lcyAqbm90KiBydW4gb25lLCBhbmQgcHJvYmFibHkKICogICAgc2hvdWxkbid0IGJlIGZvcmNlZCB0byBydW4gb25lIGp1c3QgZm9yIGxvY2FsIENPTQogKiAgLSB2ZXJ5IGZldyBVbml4IHN5c3RlbXMgdXNlIERDRSBSUEMuLi4gaWYgdGhleSBydW4gYSBSUEMKICogICAgZGFlbW9uIGF0IGFsbCwgaXQncyB1c3VhbGx5IFN1biBSUEMKICogIC0gRENFIFJQQyByZWdpc3RyYXRpb25zIGFyZSBwZXJzaXN0ZW50IGFuZCBzYXZlZCBvbiBkaXNrLAogKiAgICB3aGlsZSBNUy1SUEMgcmVnaXN0cmF0aW9ucyBhcmUgZG9jdW1lbnRlZCBhcyBub24tcGVyc2lzdGVudAogKiAgICBhbmQgc3RvcmVkIG9ubHkgaW4gUkFNLCBhbmQgYXV0by1kZXN0cm95ZWQgd2hlbiB0aGUgcHJvY2VzcwogKiAgICBkaWVzIChzb21ldGhpbmcgRENFIFJQQyBjYW4ndCBkbykKICoKICogT2YgY291cnNlLCBpZiB0aGUgdXNlciAqZGlkKiB3YW50IHRvIHJ1biBhIERDRSBSUEMgZGFlbW9uIGFueXdheSwKICogdGhlcmUgd291bGQgYmUgaW50ZXJvcGVyYWJpbGl0eSBhZHZhbnRhZ2VzLCBsaWtlIHRoZSBwb3NzaWJpbGl0eQogKiBvZiBydW5uaW5nIGEgZnVsbHkgZnVuY3Rpb25hbCBEQ09NIHNlcnZlciB1c2luZyBXaW5lLi4uCiAqLwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICAgIFJwY0VwUmVnaXN0ZXJBIChSUENSVDQuQCkKICovClJQQ19TVEFUVVMgV0lOQVBJIFJwY0VwUmVnaXN0ZXJBKCBSUENfSUZfSEFORExFIElmU3BlYywgUlBDX0JJTkRJTkdfVkVDVE9SICpCaW5kaW5nVmVjdG9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVVVJRF9WRUNUT1IgKlV1aWRWZWN0b3IsIFJQQ19DU1RSIEFubm90YXRpb24gKQp7CiAgUlBDU1NfTlBfTUVTU0FHRSBtc2c7CiAgUlBDU1NfTlBfUkVQTFkgcmVwbHk7CiAgY2hhciAqdmFyZGF0YV9wYXlsb2FkLCAqdnA7CiAgUFJQQ19TRVJWRVJfSU5URVJGQUNFIElmID0gKFBSUENfU0VSVkVSX0lOVEVSRkFDRSlJZlNwZWM7CiAgdW5zaWduZWQgbG9uZyBjOwogIFJQQ19TVEFUVVMgcnNsdCA9IFJQQ19TX09LOwoKICBUUkFDRSgiKCVwLCVwLCVwLCVzKVxuIiwgSWZTcGVjLCBCaW5kaW5nVmVjdG9yLCBVdWlkVmVjdG9yLCBkZWJ1Z3N0cl9hKChjaGFyKilBbm5vdGF0aW9uKSk7CiAgVFJBQ0UoIiBpZmlkPSVzXG4iLCBkZWJ1Z3N0cl9ndWlkKCZJZi0+SW50ZXJmYWNlSWQuU3ludGF4R1VJRCkpOwogIGZvciAoYz0wOyBjPEJpbmRpbmdWZWN0b3ItPkNvdW50OyBjKyspIHsKICAgIFJwY0JpbmRpbmcqIGJpbmQgPSAoUnBjQmluZGluZyopKEJpbmRpbmdWZWN0b3ItPkJpbmRpbmdIW2NdKTsKICAgIFRSQUNFKCIgcHJvdHNlcVslbGRdPSVzXG4iLCBjLCBkZWJ1Z3N0cl9hKGJpbmQtPlByb3RzZXEpKTsKICAgIFRSQUNFKCIgZW5kcG9pbnRbJWxkXT0lc1xuIiwgYywgZGVidWdzdHJfYShiaW5kLT5FbmRwb2ludCkpOwogIH0KICBpZiAoVXVpZFZlY3RvcikgewogICAgZm9yIChjPTA7IGM8VXVpZFZlY3Rvci0+Q291bnQ7IGMrKykKICAgICAgVFJBQ0UoIiBvYmpbJWxkXT0lc1xuIiwgYywgZGVidWdzdHJfZ3VpZChVdWlkVmVjdG9yLT5VdWlkW2NdKSk7CiAgfQoKICAvKiBGSVhNRTogRG8gc29tZXRoaW5nIHdpdGggYW5ub3RhdGlvbi4gKi8KCiAgLyogY29uc3RydWN0IHRoZSBtZXNzYWdlIHRvIHJwY3NzICovCiAgbXNnLm1lc3NhZ2VfdHlwZSA9IFJQQ1NTX05QX01FU1NBR0VfVFlQRUlEX1JFR0lTVEVSRVBNU0c7CiAgbXNnLm1lc3NhZ2UucmVnaXN0ZXJlcG1zZy5pZmFjZSA9IElmLT5JbnRlcmZhY2VJZDsKICBtc2cubWVzc2FnZS5yZWdpc3RlcmVwbXNnLm5vX3JlcGxhY2UgPSAwOwoKICBtc2cubWVzc2FnZS5yZWdpc3RlcmVwbXNnLm9iamVjdF9jb3VudCA9IChVdWlkVmVjdG9yKSA/IFV1aWRWZWN0b3ItPkNvdW50IDogMDsKICBtc2cubWVzc2FnZS5yZWdpc3RlcmVwbXNnLmJpbmRpbmdfY291bnQgPSBCaW5kaW5nVmVjdG9yLT5Db3VudDsKCiAgLyogY2FsY3VsYXRlIHZhcmRhdGEgcGF5bG9hZCBzaXplICovCiAgbXNnLnZhcmRhdGFfcGF5bG9hZF9zaXplID0gbXNnLm1lc3NhZ2UucmVnaXN0ZXJlcG1zZy5vYmplY3RfY291bnQgKiBzaXplb2YoVVVJRCk7CiAgZm9yIChjPTA7IGMgPCBtc2cubWVzc2FnZS5yZWdpc3RlcmVwbXNnLmJpbmRpbmdfY291bnQ7IGMrKykgewogICAgUnBjQmluZGluZyAqYmluZCA9IChScGNCaW5kaW5nICopKEJpbmRpbmdWZWN0b3ItPkJpbmRpbmdIW2NdKTsKICAgIG1zZy52YXJkYXRhX3BheWxvYWRfc2l6ZSArPSBzdHJsZW4oYmluZC0+UHJvdHNlcSkgKyAxOwogICAgbXNnLnZhcmRhdGFfcGF5bG9hZF9zaXplICs9IHN0cmxlbihiaW5kLT5FbmRwb2ludCkgKyAxOwogIH0KCiAgLyogYWxsb2NhdGUgdGhlIHBheWxvYWQgYnVmZmVyICovCiAgdnAgPSB2YXJkYXRhX3BheWxvYWQgPSBMb2NhbEFsbG9jKExQVFIsIG1zZy52YXJkYXRhX3BheWxvYWRfc2l6ZSk7CiAgaWYgKCF2YXJkYXRhX3BheWxvYWQpCiAgICByZXR1cm4gUlBDX1NfT1VUX09GX01FTU9SWTsKCiAgLyogcG9wdWxhdGUgdGhlIHBheWxvYWQgZGF0YSAqLwogIGZvciAoYz0wOyBjIDwgbXNnLm1lc3NhZ2UucmVnaXN0ZXJlcG1zZy5vYmplY3RfY291bnQ7IGMrKykgewogICAgQ29weU1lbW9yeSh2cCwgVXVpZFZlY3Rvci0+VXVpZFtjXSwgc2l6ZW9mKFVVSUQpKTsKICAgIHZwICs9IHNpemVvZihVVUlEKTsKICB9CgogIGZvciAoYz0wOyBjIDwgbXNnLm1lc3NhZ2UucmVnaXN0ZXJlcG1zZy5iaW5kaW5nX2NvdW50OyBjKyspIHsKICAgIFJwY0JpbmRpbmcgKmJpbmQgPSAoUnBjQmluZGluZyopKEJpbmRpbmdWZWN0b3ItPkJpbmRpbmdIW2NdKTsKICAgIHVuc2lnbmVkIGxvbmcgcHNsZW4gPSBzdHJsZW4oYmluZC0+UHJvdHNlcSkgKyAxLCBlcGxlbiA9IHN0cmxlbihiaW5kLT5FbmRwb2ludCkgKyAxOwogICAgQ29weU1lbW9yeSh2cCwgYmluZC0+UHJvdHNlcSwgcHNsZW4pOwogICAgdnAgKz0gcHNsZW47CiAgICBDb3B5TWVtb3J5KHZwLCBiaW5kLT5FbmRwb2ludCwgZXBsZW4pOwogICAgdnAgKz0gZXBsZW47CiAgfQoKICAvKiBzZW5kIG91ciByZXF1ZXN0ICovCiAgaWYgKCFSUENSVDRfUlBDU1NPbkRlbWFuZENhbGwoJm1zZywgdmFyZGF0YV9wYXlsb2FkLCAmcmVwbHkpKQogICAgcnNsdCA9IFJQQ19TX09VVF9PRl9NRU1PUlk7CgogIC8qIGZyZWUgdGhlIHBheWxvYWQgYnVmZmVyICovCiAgTG9jYWxGcmVlKHZhcmRhdGFfcGF5bG9hZCk7CgogIHJldHVybiByc2x0Owp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgICAgUnBjRXBVbnJlZ2lzdGVyIChSUENSVDQuQCkKICovClJQQ19TVEFUVVMgV0lOQVBJIFJwY0VwVW5yZWdpc3RlciggUlBDX0lGX0hBTkRMRSBJZlNwZWMsIFJQQ19CSU5ESU5HX1ZFQ1RPUiAqQmluZGluZ1ZlY3RvciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVVUlEX1ZFQ1RPUiAqVXVpZFZlY3RvciApCnsKICBSUENTU19OUF9NRVNTQUdFIG1zZzsKICBSUENTU19OUF9SRVBMWSByZXBseTsKICBjaGFyICp2YXJkYXRhX3BheWxvYWQsICp2cDsKICBQUlBDX1NFUlZFUl9JTlRFUkZBQ0UgSWYgPSAoUFJQQ19TRVJWRVJfSU5URVJGQUNFKUlmU3BlYzsKICB1bnNpZ25lZCBsb25nIGM7CiAgUlBDX1NUQVRVUyByc2x0ID0gUlBDX1NfT0s7CgogIFRSQUNFKCIoJXAsJXAsJXApXG4iLCBJZlNwZWMsIEJpbmRpbmdWZWN0b3IsIFV1aWRWZWN0b3IpOwogIFRSQUNFKCIgaWZpZD0lc1xuIiwgZGVidWdzdHJfZ3VpZCgmSWYtPkludGVyZmFjZUlkLlN5bnRheEdVSUQpKTsKICBmb3IgKGM9MDsgYzxCaW5kaW5nVmVjdG9yLT5Db3VudDsgYysrKSB7CiAgICBScGNCaW5kaW5nKiBiaW5kID0gKFJwY0JpbmRpbmcqKShCaW5kaW5nVmVjdG9yLT5CaW5kaW5nSFtjXSk7CiAgICBUUkFDRSgiIHByb3RzZXFbJWxkXT0lc1xuIiwgYywgZGVidWdzdHJfYShiaW5kLT5Qcm90c2VxKSk7CiAgICBUUkFDRSgiIGVuZHBvaW50WyVsZF09JXNcbiIsIGMsIGRlYnVnc3RyX2EoYmluZC0+RW5kcG9pbnQpKTsKICB9CiAgaWYgKFV1aWRWZWN0b3IpIHsKICAgIGZvciAoYz0wOyBjPFV1aWRWZWN0b3ItPkNvdW50OyBjKyspCiAgICAgIFRSQUNFKCIgb2JqWyVsZF09JXNcbiIsIGMsIGRlYnVnc3RyX2d1aWQoVXVpZFZlY3Rvci0+VXVpZFtjXSkpOwogIH0KCiAgLyogY29uc3RydWN0IHRoZSBtZXNzYWdlIHRvIHJwY3NzICovCiAgbXNnLm1lc3NhZ2VfdHlwZSA9IFJQQ1NTX05QX01FU1NBR0VfVFlQRUlEX1VOUkVHSVNURVJFUE1TRzsKICBtc2cubWVzc2FnZS51bnJlZ2lzdGVyZXBtc2cuaWZhY2UgPSBJZi0+SW50ZXJmYWNlSWQ7CgogIG1zZy5tZXNzYWdlLnVucmVnaXN0ZXJlcG1zZy5vYmplY3RfY291bnQgPSAoVXVpZFZlY3RvcikgPyBVdWlkVmVjdG9yLT5Db3VudCA6IDA7CiAgbXNnLm1lc3NhZ2UudW5yZWdpc3RlcmVwbXNnLmJpbmRpbmdfY291bnQgPSBCaW5kaW5nVmVjdG9yLT5Db3VudDsKCiAgLyogY2FsY3VsYXRlIHZhcmRhdGEgcGF5bG9hZCBzaXplICovCiAgbXNnLnZhcmRhdGFfcGF5bG9hZF9zaXplID0gbXNnLm1lc3NhZ2UudW5yZWdpc3RlcmVwbXNnLm9iamVjdF9jb3VudCAqIHNpemVvZihVVUlEKTsKICBmb3IgKGM9MDsgYyA8IG1zZy5tZXNzYWdlLnVucmVnaXN0ZXJlcG1zZy5iaW5kaW5nX2NvdW50OyBjKyspIHsKICAgIFJwY0JpbmRpbmcgKmJpbmQgPSAoUnBjQmluZGluZyAqKShCaW5kaW5nVmVjdG9yLT5CaW5kaW5nSFtjXSk7CiAgICBtc2cudmFyZGF0YV9wYXlsb2FkX3NpemUgKz0gc3RybGVuKGJpbmQtPlByb3RzZXEpICsgMTsKICAgIG1zZy52YXJkYXRhX3BheWxvYWRfc2l6ZSArPSBzdHJsZW4oYmluZC0+RW5kcG9pbnQpICsgMTsKICB9CgogIC8qIGFsbG9jYXRlIHRoZSBwYXlsb2FkIGJ1ZmZlciAqLwogIHZwID0gdmFyZGF0YV9wYXlsb2FkID0gTG9jYWxBbGxvYyhMUFRSLCBtc2cudmFyZGF0YV9wYXlsb2FkX3NpemUpOwogIGlmICghdmFyZGF0YV9wYXlsb2FkKQogICAgcmV0dXJuIFJQQ19TX09VVF9PRl9NRU1PUlk7CgogIC8qIHBvcHVsYXRlIHRoZSBwYXlsb2FkIGRhdGEgKi8KICBmb3IgKGM9MDsgYyA8IG1zZy5tZXNzYWdlLnVucmVnaXN0ZXJlcG1zZy5vYmplY3RfY291bnQ7IGMrKykgewogICAgQ29weU1lbW9yeSh2cCwgVXVpZFZlY3Rvci0+VXVpZFtjXSwgc2l6ZW9mKFVVSUQpKTsKICAgIHZwICs9IHNpemVvZihVVUlEKTsKICB9CgogIGZvciAoYz0wOyBjIDwgbXNnLm1lc3NhZ2UudW5yZWdpc3RlcmVwbXNnLmJpbmRpbmdfY291bnQ7IGMrKykgewogICAgUnBjQmluZGluZyAqYmluZCA9IChScGNCaW5kaW5nKikoQmluZGluZ1ZlY3Rvci0+QmluZGluZ0hbY10pOwogICAgdW5zaWduZWQgbG9uZyBwc2xlbiA9IHN0cmxlbihiaW5kLT5Qcm90c2VxKSArIDEsIGVwbGVuID0gc3RybGVuKGJpbmQtPkVuZHBvaW50KSArIDE7CiAgICBDb3B5TWVtb3J5KHZwLCBiaW5kLT5Qcm90c2VxLCBwc2xlbik7CiAgICB2cCArPSBwc2xlbjsKICAgIENvcHlNZW1vcnkodnAsIGJpbmQtPkVuZHBvaW50LCBlcGxlbik7CiAgICB2cCArPSBlcGxlbjsKICB9CgogIC8qIHNlbmQgb3VyIHJlcXVlc3QgKi8KICBpZiAoIVJQQ1JUNF9SUENTU09uRGVtYW5kQ2FsbCgmbXNnLCB2YXJkYXRhX3BheWxvYWQsICZyZXBseSkpCiAgICByc2x0ID0gUlBDX1NfT1VUX09GX01FTU9SWTsKCiAgLyogZnJlZSB0aGUgcGF5bG9hZCBidWZmZXIgKi8KICBMb2NhbEZyZWUodmFyZGF0YV9wYXlsb2FkKTsKCiAgcmV0dXJuIHJzbHQ7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiAgICAgICAgICAgICBScGNFcFJlc29sdmVCaW5kaW5nIChSUENSVDQuQCkKICovClJQQ19TVEFUVVMgV0lOQVBJIFJwY0VwUmVzb2x2ZUJpbmRpbmcoIFJQQ19CSU5ESU5HX0hBTkRMRSBCaW5kaW5nLCBSUENfSUZfSEFORExFIElmU3BlYyApCnsKICBSUENTU19OUF9NRVNTQUdFIG1zZzsKICBSUENTU19OUF9SRVBMWSByZXBseTsKICBQUlBDX0NMSUVOVF9JTlRFUkZBQ0UgSWYgPSAoUFJQQ19DTElFTlRfSU5URVJGQUNFKUlmU3BlYzsKICBScGNCaW5kaW5nKiBiaW5kID0gKFJwY0JpbmRpbmcqKUJpbmRpbmc7CgogIFRSQUNFKCIoJXAsJXApXG4iLCBCaW5kaW5nLCBJZlNwZWMpOwogIFRSQUNFKCIgcHJvdHNlcT0lc1xuIiwgZGVidWdzdHJfYShiaW5kLT5Qcm90c2VxKSk7CiAgVFJBQ0UoIiBvYmo9JXNcbiIsIGRlYnVnc3RyX2d1aWQoJmJpbmQtPk9iamVjdFV1aWQpKTsKICBUUkFDRSgiIGlmaWQ9JXNcbiIsIGRlYnVnc3RyX2d1aWQoJklmLT5JbnRlcmZhY2VJZC5TeW50YXhHVUlEKSk7CgogIC8qIEZJWE1FOiB0b3RhbGx5IHVudGVzdGVkICovCgogIC8qIGp1c3QgcmV0dXJuIGZvciBmdWxseSBib3VuZCBoYW5kbGVzICovCiAgaWYgKGJpbmQtPkVuZHBvaW50ICYmIChiaW5kLT5FbmRwb2ludFswXSAhPSAnXDAnKSkKICAgIHJldHVybiBSUENfU19PSzsKCiAgLyogY29uc3RydWN0IHRoZSBtZXNzYWdlIHRvIHJwY3NzICovCiAgbXNnLm1lc3NhZ2VfdHlwZSA9IFJQQ1NTX05QX01FU1NBR0VfVFlQRUlEX1JFU09MVkVFUE1TRzsKICBtc2cubWVzc2FnZS5yZXNvbHZlZXBtc2cuaWZhY2UgPSBJZi0+SW50ZXJmYWNlSWQ7CiAgbXNnLm1lc3NhZ2UucmVzb2x2ZWVwbXNnLm9iamVjdCA9IGJpbmQtPk9iamVjdFV1aWQ7CiAKICBtc2cudmFyZGF0YV9wYXlsb2FkX3NpemUgPSBzdHJsZW4oYmluZC0+UHJvdHNlcSkgKyAxOwoKICAvKiBzZW5kIHRoZSBtZXNzYWdlICovCiAgaWYgKCFSUENSVDRfUlBDU1NPbkRlbWFuZENhbGwoJm1zZywgYmluZC0+UHJvdHNlcSwgJnJlcGx5KSkKICAgIHJldHVybiBSUENfU19PVVRfT0ZfTUVNT1JZOwoKICAvKiBlbXB0eS1zdHJpbmcgcmVzdWx0IG1lYW5zIG5vdCByZWdpc3RlcmVkICovCiAgaWYgKHJlcGx5LmFzX3N0cmluZ1swXSA9PSAnXDAnKQogICAgcmV0dXJuIEVQVF9TX05PVF9SRUdJU1RFUkVEOwogIAogIC8qIG90aGVyd2lzZSB3ZSBmdWxseSBiaW5kIHRoZSBoYW5kbGUgJiByZXR1cm4gUlBDX1NfT0sgKi8KICByZXR1cm4gUlBDUlQ0X1Jlc29sdmVCaW5kaW5nKEJpbmRpbmcsIHJlcGx5LmFzX3N0cmluZyk7Cn0KCnR5cGVkZWYgdW5zaWduZWQgaW50IHVuc2lnbmVkMzI7CnR5cGVkZWYgc3RydWN0IHR3cl90CiAgICB7CiAgICB1bnNpZ25lZDMyIHRvd2VyX2xlbmd0aDsKICAgIC8qIFtzaXplX2lzXSAqLyBCWVRFIHRvd2VyX29jdGV0X3N0cmluZ1sgMSBdOwogICAgfSAJdHdyX3Q7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgICAgVG93ZXJFeHBsb2RlIChSUENSVDQuQCkKICovClJQQ19TVEFUVVMgV0lOQVBJIFRvd2VyRXhwbG9kZSgKICAgIGNvbnN0IHR3cl90ICp0b3dlciwgUFJQQ19TWU5UQVhfSURFTlRJRklFUiBvYmplY3QsIFBSUENfU1lOVEFYX0lERU5USUZJRVIgc3ludGF4LAogICAgY2hhciAqKnByb3RzZXEsIGNoYXIgKiplbmRwb2ludCwgY2hhciAqKmFkZHJlc3MpCnsKICAgIHNpemVfdCB0b3dlcl9zaXplOwogICAgUlBDX1NUQVRVUyBzdGF0dXM7CiAgICBjb25zdCB1bnNpZ25lZCBjaGFyICpwOwogICAgdV9pbnQxNiBmbG9vcl9jb3VudDsKICAgIGNvbnN0IHR3cl91dWlkX2Zsb29yX3QgKm9iamVjdF9mbG9vcjsKICAgIGNvbnN0IHR3cl91dWlkX2Zsb29yX3QgKnN5bnRheF9mbG9vcjsKCiAgICBUUkFDRSgiKCVwLCAlcCwgJXAsICVwLCAlcCwgJXApXG4iLCB0b3dlciwgb2JqZWN0LCBzeW50YXgsIHByb3RzZXEsCiAgICAgICAgICBlbmRwb2ludCwgYWRkcmVzcyk7CgogICAgaWYgKHByb3RzZXEpCiAgICAgICAgKnByb3RzZXEgPSBOVUxMOwogICAgaWYgKGVuZHBvaW50KQogICAgICAgICplbmRwb2ludCA9IE5VTEw7CiAgICBpZiAoYWRkcmVzcykKICAgICAgICAqYWRkcmVzcyA9IE5VTEw7CgogICAgdG93ZXJfc2l6ZSA9IHRvd2VyLT50b3dlcl9sZW5ndGg7CgogICAgaWYgKHRvd2VyX3NpemUgPCBzaXplb2YodV9pbnQxNikpCiAgICAgICAgcmV0dXJuIEVQVF9TX05PVF9SRUdJU1RFUkVEOwoKICAgIHAgPSAmdG93ZXItPnRvd2VyX29jdGV0X3N0cmluZ1swXTsKCiAgICBmbG9vcl9jb3VudCA9ICooY29uc3QgdV9pbnQxNiAqKXA7CiAgICBwICs9IHNpemVvZih1X2ludDE2KTsKICAgIHRvd2VyX3NpemUgLT0gc2l6ZW9mKHVfaW50MTYpOwogICAgVFJBQ0UoImZsb29yX2NvdW50OiAlZFxuIiwgZmxvb3JfY291bnQpOwogICAgLyogRklYTUU6IHNob3VsZCB3ZSBkbyBzb21ldGhpbmcgd2l0aCB0aGUgZmxvb3IgY291bnQ/IGF0IHRoZSBtb21lbnQgd2UgZG9uJ3QgKi8KCiAgICBpZiAodG93ZXJfc2l6ZSA8IHNpemVvZigqb2JqZWN0X2Zsb29yKSArIHNpemVvZigqc3ludGF4X2Zsb29yKSkKICAgICAgICByZXR1cm4gRVBUX1NfTk9UX1JFR0lTVEVSRUQ7CgogICAgb2JqZWN0X2Zsb29yID0gKGNvbnN0IHR3cl91dWlkX2Zsb29yX3QgKilwOwogICAgcCArPSBzaXplb2YoKm9iamVjdF9mbG9vcik7CiAgICB0b3dlcl9zaXplIC09IHNpemVvZigqb2JqZWN0X2Zsb29yKTsKICAgIHN5bnRheF9mbG9vciA9IChjb25zdCB0d3JfdXVpZF9mbG9vcl90ICopcDsKICAgIHAgKz0gc2l6ZW9mKCpzeW50YXhfZmxvb3IpOwogICAgdG93ZXJfc2l6ZSAtPSBzaXplb2YoKnN5bnRheF9mbG9vcik7CgogICAgaWYgKChvYmplY3RfZmxvb3ItPmNvdW50X2xocyAhPSBzaXplb2Yob2JqZWN0X2Zsb29yLT5wcm90aWQpICsKICAgICAgICBzaXplb2Yob2JqZWN0X2Zsb29yLT51dWlkKSArIHNpemVvZihvYmplY3RfZmxvb3ItPm1ham9yX3ZlcnNpb24pKSB8fAogICAgICAgIChvYmplY3RfZmxvb3ItPnByb3RpZCAhPSBFUE1fUFJPVE9DT0xfVVVJRCkgfHwKICAgICAgICAob2JqZWN0X2Zsb29yLT5jb3VudF9yaHMgIT0gc2l6ZW9mKG9iamVjdF9mbG9vci0+bWlub3JfdmVyc2lvbikpKQogICAgICAgIHJldHVybiBFUFRfU19OT1RfUkVHSVNURVJFRDsKCiAgICBpZiAoKHN5bnRheF9mbG9vci0+Y291bnRfbGhzICE9IHNpemVvZihzeW50YXhfZmxvb3ItPnByb3RpZCkgKwogICAgICAgIHNpemVvZihzeW50YXhfZmxvb3ItPnV1aWQpICsgc2l6ZW9mKHN5bnRheF9mbG9vci0+bWFqb3JfdmVyc2lvbikpIHx8CiAgICAgICAgKHN5bnRheF9mbG9vci0+cHJvdGlkICE9IEVQTV9QUk9UT0NPTF9VVUlEKSB8fAogICAgICAgIChzeW50YXhfZmxvb3ItPmNvdW50X3JocyAhPSBzaXplb2Yoc3ludGF4X2Zsb29yLT5taW5vcl92ZXJzaW9uKSkpCiAgICAgICAgcmV0dXJuIEVQVF9TX05PVF9SRUdJU1RFUkVEOwoKICAgIHN0YXR1cyA9IFJwY1RyYW5zcG9ydF9QYXJzZVRvcE9mVG93ZXIocCwgdG93ZXJfc2l6ZSwgcHJvdHNlcSwgYWRkcmVzcywgZW5kcG9pbnQpOwogICAgaWYgKChzdGF0dXMgPT0gUlBDX1NfT0spICYmIHN5bnRheCAmJiBvYmplY3QpCiAgICB7CiAgICAgICAgc3ludGF4LT5TeW50YXhHVUlEID0gc3ludGF4X2Zsb29yLT51dWlkOwogICAgICAgIHN5bnRheC0+U3ludGF4VmVyc2lvbi5NYWpvclZlcnNpb24gPSBzeW50YXhfZmxvb3ItPm1ham9yX3ZlcnNpb247CiAgICAgICAgc3ludGF4LT5TeW50YXhWZXJzaW9uLk1pbm9yVmVyc2lvbiA9IHN5bnRheF9mbG9vci0+bWlub3JfdmVyc2lvbjsKICAgICAgICBvYmplY3QtPlN5bnRheEdVSUQgPSBvYmplY3RfZmxvb3ItPnV1aWQ7CiAgICAgICAgb2JqZWN0LT5TeW50YXhWZXJzaW9uLk1ham9yVmVyc2lvbiA9IG9iamVjdF9mbG9vci0+bWFqb3JfdmVyc2lvbjsKICAgICAgICBvYmplY3QtPlN5bnRheFZlcnNpb24uTWlub3JWZXJzaW9uID0gb2JqZWN0X2Zsb29yLT5taW5vcl92ZXJzaW9uOwogICAgfQogICAgcmV0dXJuIHN0YXR1czsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICAgIFRvd2VyQ29uc3RydWN0IChSUENSVDQuQCkKICovClJQQ19TVEFUVVMgV0lOQVBJIFRvd2VyQ29uc3RydWN0KAogICAgY29uc3QgUlBDX1NZTlRBWF9JREVOVElGSUVSICpvYmplY3QsIGNvbnN0IFJQQ19TWU5UQVhfSURFTlRJRklFUiAqc3ludGF4LAogICAgY29uc3QgY2hhciAqcHJvdHNlcSwgY29uc3QgY2hhciAqZW5kcG9pbnQsIGNvbnN0IGNoYXIgKmFkZHJlc3MsCiAgICB0d3JfdCAqKnRvd2VyKQp7CiAgICBzaXplX3QgdG93ZXJfc2l6ZTsKICAgIFJQQ19TVEFUVVMgc3RhdHVzOwogICAgdW5zaWduZWQgY2hhciAqcDsKICAgIHR3cl91dWlkX2Zsb29yX3QgKm9iamVjdF9mbG9vcjsKICAgIHR3cl91dWlkX2Zsb29yX3QgKnN5bnRheF9mbG9vcjsKCiAgICBUUkFDRSgiKCVwLCAlcCwgJXMsICVzLCAlcywgJXApXG4iLCBvYmplY3QsIHN5bnRheCwgZGVidWdzdHJfYShwcm90c2VxKSwKICAgICAgICAgIGRlYnVnc3RyX2EoZW5kcG9pbnQpLCBkZWJ1Z3N0cl9hKGFkZHJlc3MpLCB0b3dlcik7CgogICAgKnRvd2VyID0gTlVMTDsKCiAgICBzdGF0dXMgPSBScGNUcmFuc3BvcnRfR2V0VG9wT2ZUb3dlcihOVUxMLCAmdG93ZXJfc2l6ZSwgcHJvdHNlcSwgYWRkcmVzcywgZW5kcG9pbnQpOwoKICAgIGlmIChzdGF0dXMgIT0gUlBDX1NfT0spCiAgICAgICAgcmV0dXJuIHN0YXR1czsKCiAgICB0b3dlcl9zaXplICs9IHNpemVvZih1X2ludDE2KSArIHNpemVvZigqb2JqZWN0X2Zsb29yKSArIHNpemVvZigqc3ludGF4X2Zsb29yKTsKICAgICp0b3dlciA9IElfUnBjQWxsb2NhdGUoRklFTERfT0ZGU0VUKHR3cl90LCB0b3dlcl9vY3RldF9zdHJpbmdbdG93ZXJfc2l6ZV0pKTsKICAgIGlmICghKnRvd2VyKQogICAgICAgIHJldHVybiBSUENfU19PVVRfT0ZfUkVTT1VSQ0VTOwoKICAgICgqdG93ZXIpLT50b3dlcl9sZW5ndGggPSB0b3dlcl9zaXplOwogICAgcCA9ICYoKnRvd2VyKS0+dG93ZXJfb2N0ZXRfc3RyaW5nWzBdOwogICAgKih1X2ludDE2ICopcCA9IDU7IC8qIG51bWJlciBvZiBmbG9vcnMgKi8KICAgIHAgKz0gc2l6ZW9mKHVfaW50MTYpOwogICAgb2JqZWN0X2Zsb29yID0gKHR3cl91dWlkX2Zsb29yX3QgKilwOwogICAgcCArPSBzaXplb2YoKm9iamVjdF9mbG9vcik7CiAgICBzeW50YXhfZmxvb3IgPSAodHdyX3V1aWRfZmxvb3JfdCAqKXA7CiAgICBwICs9IHNpemVvZigqc3ludGF4X2Zsb29yKTsKCiAgICBvYmplY3RfZmxvb3ItPmNvdW50X2xocyA9IHNpemVvZihvYmplY3RfZmxvb3ItPnByb3RpZCkgKyBzaXplb2Yob2JqZWN0X2Zsb29yLT51dWlkKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVvZihvYmplY3RfZmxvb3ItPm1ham9yX3ZlcnNpb24pOwogICAgb2JqZWN0X2Zsb29yLT5wcm90aWQgPSBFUE1fUFJPVE9DT0xfVVVJRDsKICAgIG9iamVjdF9mbG9vci0+Y291bnRfcmhzID0gc2l6ZW9mKG9iamVjdF9mbG9vci0+bWlub3JfdmVyc2lvbik7CiAgICBvYmplY3RfZmxvb3ItPnV1aWQgPSBvYmplY3QtPlN5bnRheEdVSUQ7CiAgICBvYmplY3RfZmxvb3ItPm1ham9yX3ZlcnNpb24gPSBvYmplY3QtPlN5bnRheFZlcnNpb24uTWFqb3JWZXJzaW9uOwogICAgb2JqZWN0X2Zsb29yLT5taW5vcl92ZXJzaW9uID0gb2JqZWN0LT5TeW50YXhWZXJzaW9uLk1pbm9yVmVyc2lvbjsKCiAgICBzeW50YXhfZmxvb3ItPmNvdW50X2xocyA9IHNpemVvZihzeW50YXhfZmxvb3ItPnByb3RpZCkgKyBzaXplb2Yoc3ludGF4X2Zsb29yLT51dWlkKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVvZihzeW50YXhfZmxvb3ItPm1ham9yX3ZlcnNpb24pOwogICAgc3ludGF4X2Zsb29yLT5wcm90aWQgPSBFUE1fUFJPVE9DT0xfVVVJRDsKICAgIHN5bnRheF9mbG9vci0+Y291bnRfcmhzID0gc2l6ZW9mKHN5bnRheF9mbG9vci0+bWlub3JfdmVyc2lvbik7CiAgICBzeW50YXhfZmxvb3ItPnV1aWQgPSBzeW50YXgtPlN5bnRheEdVSUQ7CiAgICBzeW50YXhfZmxvb3ItPm1ham9yX3ZlcnNpb24gPSBzeW50YXgtPlN5bnRheFZlcnNpb24uTWFqb3JWZXJzaW9uOwogICAgc3ludGF4X2Zsb29yLT5taW5vcl92ZXJzaW9uID0gc3ludGF4LT5TeW50YXhWZXJzaW9uLk1pbm9yVmVyc2lvbjsKCiAgICBzdGF0dXMgPSBScGNUcmFuc3BvcnRfR2V0VG9wT2ZUb3dlcihwLCAmdG93ZXJfc2l6ZSwgcHJvdHNlcSwgYWRkcmVzcywgZW5kcG9pbnQpOwogICAgaWYgKHN0YXR1cyAhPSBSUENfU19PSykKICAgIHsKICAgICAgICBJX1JwY0ZyZWUoKnRvd2VyKTsKICAgICAgICAqdG93ZXIgPSBOVUxMOwogICAgICAgIHJldHVybiBzdGF0dXM7CiAgICB9CiAgICByZXR1cm4gUlBDX1NfT0s7Cn0K