LyoKICogUlBDIG1lc3NhZ2VzCiAqCiAqIENvcHlyaWdodCAyMDAxLTIwMDIgT3ZlIEvldmVuLCBUcmFuc0dhbWluZyBUZWNobm9sb2dpZXMKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiAqCiAqIFRPRE86CiAqICAtIGZpZ3VyZSBvdXQgd2hldGhlciB3ZSAqcmVhbGx5KiBnb3QgdGhpcyByaWdodAogKiAgLSBjaGVjayBmb3IgZXJyb3JzIGFuZCB0aHJvdyBleGNlcHRpb25zCiAqICAtIGRlY2lkZSBpZiBPVkVSTEFQUEVEX1dPUktTCiAqLwoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmVycm9yLmgiCiNpbmNsdWRlICJ3aW5yZWcuaCIKCiNpbmNsdWRlICJycGMuaCIKI2luY2x1ZGUgInJwY2RjZXAuaCIKCiNpbmNsdWRlICJ3aW5lL2RlYnVnLmgiCgojaW5jbHVkZSAicnBjX2JpbmRpbmcuaCIKI2luY2x1ZGUgInJwY19taXNjLmgiCiNpbmNsdWRlICJycGNfZGVmcy5oIgoKV0lORV9ERUZBVUxUX0RFQlVHX0NIQU5ORUwob2xlKTsKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiAgICAgICAgICAgSV9ScGNHZXRCdWZmZXIgW1JQQ1JUNC5AXQogKi8KUlBDX1NUQVRVUyBXSU5BUEkgSV9ScGNHZXRCdWZmZXIoUFJQQ19NRVNTQUdFIHBNc2cpCnsKICBScGNCaW5kaW5nKiBiaW5kID0gKFJwY0JpbmRpbmcqKXBNc2ctPkhhbmRsZTsKICB2b2lkKiBidWY7CgogIFRSQUNFKCIoJXApOiBCdWZmZXJMZW5ndGg9JWRcbiIsIHBNc2csIHBNc2ctPkJ1ZmZlckxlbmd0aCk7CiAgLyogRklYTUU6IHBmbkFsbG9jYXRlPyAqLwogIGlmIChiaW5kLT5zZXJ2ZXIpIHsKICAgIC8qIGl0IHR1cm5zIG91dCB0aGF0IHRoZSBvcmlnaW5hbCBidWZmZXIgZGF0YSBtdXN0IHN0aWxsIGJlIGF2YWlsYWJsZQogICAgICogd2hpbGUgdGhlIFJQQyBzZXJ2ZXIgaXMgbWFyc2hhbGxpbmcgYSByZXBseSwgc28gd2Ugc2hvdWxkIG5vdCBkZWFsbG9jYXRlCiAgICAgKiBpdCwgd2UnbGwgbGVhdmUgZGVhbGxvY2F0aW5nIHRoZSBvcmlnaW5hbCBidWZmZXIgdG8gdGhlIFJQQyBzZXJ2ZXIgKi8KICAgIGJ1ZiA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCAwLCBwTXNnLT5CdWZmZXJMZW5ndGgpOwogIH0gZWxzZSB7CiAgICBidWYgPSBIZWFwUmVBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCAwLCBwTXNnLT5CdWZmZXIsIHBNc2ctPkJ1ZmZlckxlbmd0aCk7CiAgfQogIFRSQUNFKCJCdWZmZXI9JXBcbiIsIGJ1Zik7CiAgaWYgKGJ1ZikgcE1zZy0+QnVmZmVyID0gYnVmOwogIC8qIEZJWE1FOiB3aGljaCBlcnJvcnMgdG8gcmV0dXJuPyAqLwogIHJldHVybiBidWYgPyBTX09LIDogRV9PVVRPRk1FTU9SWTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBJX1JwY0ZyZWVCdWZmZXIgW1JQQ1JUNC5AXQogKi8KUlBDX1NUQVRVUyBXSU5BUEkgSV9ScGNGcmVlQnVmZmVyKFBSUENfTUVTU0FHRSBwTXNnKQp7CiAgVFJBQ0UoIiglcCkgQnVmZmVyPSVwXG4iLCBwTXNnLCBwTXNnLT5CdWZmZXIpOwogIC8qIEZJWE1FOiBwZm5GcmVlPyAqLwogIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIHBNc2ctPkJ1ZmZlcik7CiAgcE1zZy0+QnVmZmVyID0gTlVMTDsKICByZXR1cm4gU19PSzsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBJX1JwY1NlbmQgW1JQQ1JUNC5AXQogKi8KUlBDX1NUQVRVUyBXSU5BUEkgSV9ScGNTZW5kKFBSUENfTUVTU0FHRSBwTXNnKQp7CiAgUnBjQmluZGluZyogYmluZCA9IChScGNCaW5kaW5nKilwTXNnLT5IYW5kbGU7CiAgUnBjQ29ubmVjdGlvbiogY29ubjsKICBSUENfQ0xJRU5UX0lOVEVSRkFDRSogY2lmID0gTlVMTDsKICBSUENfU0VSVkVSX0lOVEVSRkFDRSogc2lmID0gTlVMTDsKICBVVUlEKiBvYmo7CiAgVVVJRCogYWN0OwogIFJQQ19TVEFUVVMgc3RhdHVzOwogIFJwY1BrdEhkciBoZHI7CgogIFRSQUNFKCIoJXApXG4iLCBwTXNnKTsKICBpZiAoIWJpbmQpIHJldHVybiBSUENfU19JTlZBTElEX0JJTkRJTkc7CgogIHN0YXR1cyA9IFJQQ1JUNF9PcGVuQmluZGluZyhiaW5kLCAmY29ubik7CiAgaWYgKHN0YXR1cyAhPSBSUENfU19PSykgcmV0dXJuIHN0YXR1czsKCiAgb2JqID0gJmJpbmQtPk9iamVjdFV1aWQ7CiAgYWN0ID0gJmJpbmQtPkFjdGl2ZVV1aWQ7CgogIGlmIChiaW5kLT5zZXJ2ZXIpIHsKICAgIHNpZiA9IHBNc2ctPlJwY0ludGVyZmFjZUluZm9ybWF0aW9uOwogICAgaWYgKCFzaWYpIHJldHVybiBSUENfU19JTlRFUkZBQ0VfTk9UX0ZPVU5EOyAvKiA/ICovCiAgfSBlbHNlIHsKICAgIGNpZiA9IHBNc2ctPlJwY0ludGVyZmFjZUluZm9ybWF0aW9uOwogICAgaWYgKCFjaWYpIHJldHVybiBSUENfU19JTlRFUkZBQ0VfTk9UX0ZPVU5EOyAvKiA/ICovCiAgfQoKICAvKiBpbml0aWFsaXplIHBhY2tldCBoZWFkZXIgKi8KICBtZW1zZXQoJmhkciwgMCwgc2l6ZW9mKGhkcikpOwogIGhkci5ycGNfdmVyID0gNDsKICBoZHIucHR5cGUgPSBiaW5kLT5zZXJ2ZXIKICAgICAgICAgICAgICA/ICgocE1zZy0+UnBjRmxhZ3MgJiBXSU5FX1JQQ0ZMQUdfRVhDRVBUSU9OKSA/IFBLVF9GQVVMVCA6IFBLVF9SRVNQT05TRSkKICAgICAgICAgICAgICA6IFBLVF9SRVFVRVNUOwogIGhkci5vYmplY3QgPSAqb2JqOyAvKiBGSVhNRTogSUlSQyBpZmYgbm8gb2JqZWN0LCB0aGUgaGVhZGVyIHN0cnVjdHVyZSBleGNsdWRlcyB0aGlzIGVsdCAqLwogIGhkci5pZl9pZCA9IChiaW5kLT5zZXJ2ZXIpID8gc2lmLT5JbnRlcmZhY2VJZC5TeW50YXhHVUlEIDogY2lmLT5JbnRlcmZhY2VJZC5TeW50YXhHVUlEOwogIGhkci5pZl92ZXJzID0gCiAgICAoYmluZC0+c2VydmVyKSA/CiAgICBNQUtFTE9ORyhzaWYtPkludGVyZmFjZUlkLlN5bnRheFZlcnNpb24uTWlub3JWZXJzaW9uLCBzaWYtPkludGVyZmFjZUlkLlN5bnRheFZlcnNpb24uTWFqb3JWZXJzaW9uKSA6CiAgICBNQUtFTE9ORyhjaWYtPkludGVyZmFjZUlkLlN5bnRheFZlcnNpb24uTWlub3JWZXJzaW9uLCBjaWYtPkludGVyZmFjZUlkLlN5bnRheFZlcnNpb24uTWFqb3JWZXJzaW9uKTsKICBoZHIuYWN0X2lkID0gKmFjdDsKICBoZHIub3BudW0gPSBwTXNnLT5Qcm9jTnVtOwogIC8qIG9ubHkgdGhlIGxvdy1vcmRlciAzIG9jdGV0cyBvZiB0aGUgRGF0YVJlcHJlc2VudGF0aW9uIGdvIGluIHRoZSBoZWFkZXIgKi8KICBoZHIuZHJlcFswXSA9IExPQllURShMT1dPUkQocE1zZy0+RGF0YVJlcHJlc2VudGF0aW9uKSk7CiAgaGRyLmRyZXBbMV0gPSBISUJZVEUoTE9XT1JEKHBNc2ctPkRhdGFSZXByZXNlbnRhdGlvbikpOwogIGhkci5kcmVwWzJdID0gTE9CWVRFKEhJV09SRChwTXNnLT5EYXRhUmVwcmVzZW50YXRpb24pKTsKICBoZHIubGVuID0gcE1zZy0+QnVmZmVyTGVuZ3RoOwoKICAvKiB0cmFuc21pdCBwYWNrZXQgKi8KICBpZiAoIVdyaXRlRmlsZShjb25uLT5jb25uLCAmaGRyLCBzaXplb2YoaGRyKSwgTlVMTCwgTlVMTCkpIHsKICAgIHN0YXR1cyA9IEdldExhc3RFcnJvcigpOwogICAgZ290byBmYWlsOwogIH0KICBpZiAocE1zZy0+QnVmZmVyTGVuZ3RoICYmICFXcml0ZUZpbGUoY29ubi0+Y29ubiwgcE1zZy0+QnVmZmVyLCBwTXNnLT5CdWZmZXJMZW5ndGgsIE5VTEwsIE5VTEwpKSB7CiAgICBzdGF0dXMgPSBHZXRMYXN0RXJyb3IoKTsKICAgIGdvdG8gZmFpbDsKICB9CgogIC8qIHN1Y2Nlc3MgKi8KICBpZiAoIWJpbmQtPnNlcnZlcikgewogICAgLyogc2F2ZSB0aGUgY29ubmVjdGlvbiwgc28gdGhlIHJlc3BvbnNlIGNhbiBiZSByZWFkIGZyb20gaXQgKi8KICAgIHBNc2ctPlJlc2VydmVkRm9yUnVudGltZSA9IGNvbm47CiAgICByZXR1cm4gUlBDX1NfT0s7CiAgfQogIFJQQ1JUNF9DbG9zZUJpbmRpbmcoYmluZCwgY29ubik7CiAgc3RhdHVzID0gUlBDX1NfT0s7CmZhaWw6CgogIHJldHVybiBzdGF0dXM7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiAgICAgICAgICAgSV9ScGNSZWNlaXZlIFtSUENSVDQuQF0KICovClJQQ19TVEFUVVMgV0lOQVBJIElfUnBjUmVjZWl2ZShQUlBDX01FU1NBR0UgcE1zZykKewogIFJwY0JpbmRpbmcqIGJpbmQgPSAoUnBjQmluZGluZyopcE1zZy0+SGFuZGxlOwogIFJwY0Nvbm5lY3Rpb24qIGNvbm47CiAgVVVJRCogYWN0OwogIFJQQ19TVEFUVVMgc3RhdHVzOwogIFJwY1BrdEhkciBoZHI7CiAgRFdPUkQgZHdSZWFkOwoKICBUUkFDRSgiKCVwKVxuIiwgcE1zZyk7CiAgaWYgKCFiaW5kKSByZXR1cm4gUlBDX1NfSU5WQUxJRF9CSU5ESU5HOwoKICBpZiAocE1zZy0+UmVzZXJ2ZWRGb3JSdW50aW1lKSB7CiAgICBjb25uID0gcE1zZy0+UmVzZXJ2ZWRGb3JSdW50aW1lOwogICAgcE1zZy0+UmVzZXJ2ZWRGb3JSdW50aW1lID0gTlVMTDsKICB9IGVsc2UgewogICAgc3RhdHVzID0gUlBDUlQ0X09wZW5CaW5kaW5nKGJpbmQsICZjb25uKTsKICAgIGlmIChzdGF0dXMgIT0gUlBDX1NfT0spIHJldHVybiBzdGF0dXM7CiAgfQoKICBhY3QgPSAmYmluZC0+QWN0aXZlVXVpZDsKCiAgZm9yICg7OykgewogICAgLyogcmVhZCBwYWNrZXQgaGVhZGVyICovCiNpZmRlZiBPVkVSTEFQUEVEX1dPUktTCiAgICBpZiAoIVJlYWRGaWxlKGNvbm4tPmNvbm4sICZoZHIsIHNpemVvZihoZHIpLCAmZHdSZWFkLCAmY29ubi0+b3ZsKSkgewogICAgICBEV09SRCBlcnIgPSBHZXRMYXN0RXJyb3IoKTsKICAgICAgaWYgKGVyciAhPSBFUlJPUl9JT19QRU5ESU5HKSB7CiAgICAgICAgc3RhdHVzID0gZXJyOwogICAgICAgIGdvdG8gZmFpbDsKICAgICAgfQogICAgICBpZiAoIUdldE92ZXJsYXBwZWRSZXN1bHQoY29ubi0+Y29ubiwgJmNvbm4tPm92bCwgJmR3UmVhZCwgVFJVRSkpIHsKICAgICAgICBzdGF0dXMgPSBHZXRMYXN0RXJyb3IoKTsKICAgICAgICBnb3RvIGZhaWw7CiAgICAgIH0KICAgIH0KI2Vsc2UKICAgIGlmICghUmVhZEZpbGUoY29ubi0+Y29ubiwgJmhkciwgc2l6ZW9mKGhkciksICZkd1JlYWQsIE5VTEwpKSB7CiAgICAgIHN0YXR1cyA9IEdldExhc3RFcnJvcigpOwogICAgICBnb3RvIGZhaWw7CiAgICB9CiNlbmRpZgogICAgaWYgKGR3UmVhZCAhPSBzaXplb2YoaGRyKSkgewogICAgICBzdGF0dXMgPSBSUENfU19QUk9UT0NPTF9FUlJPUjsKICAgICAgZ290byBmYWlsOwogICAgfQoKICAgIC8qIHJlYWQgcGFja2V0IGJvZHkgKi8KICAgIHBNc2ctPkJ1ZmZlckxlbmd0aCA9IGhkci5sZW47CiAgICBzdGF0dXMgPSBJX1JwY0dldEJ1ZmZlcihwTXNnKTsKICAgIGlmIChzdGF0dXMgIT0gUlBDX1NfT0spIGdvdG8gZmFpbDsKICAgIGlmICghcE1zZy0+QnVmZmVyTGVuZ3RoKSBkd1JlYWQgPSAwOyBlbHNlCiNpZmRlZiBPVkVSTEFQUEVEX1dPUktTCiAgICBpZiAoIVJlYWRGaWxlKGNvbm4tPmNvbm4sIHBNc2ctPkJ1ZmZlciwgaGRyLmxlbiwgJmR3UmVhZCwgJmNvbm4tPm92bCkpIHsKICAgICAgRFdPUkQgZXJyID0gR2V0TGFzdEVycm9yKCk7CiAgICAgIGlmIChlcnIgIT0gRVJST1JfSU9fUEVORElORykgewogICAgICAgIHN0YXR1cyA9IGVycjsKICAgICAgICBnb3RvIGZhaWw7CiAgICAgIH0KICAgICAgaWYgKCFHZXRPdmVybGFwcGVkUmVzdWx0KGNvbm4tPmNvbm4sICZjb25uLT5vdmwsICZkd1JlYWQsIFRSVUUpKSB7CiAgICAgICAgc3RhdHVzID0gR2V0TGFzdEVycm9yKCk7CiAgICAgICAgZ290byBmYWlsOwogICAgICB9CiAgICB9CiNlbHNlCiAgICBpZiAoIVJlYWRGaWxlKGNvbm4tPmNvbm4sIHBNc2ctPkJ1ZmZlciwgaGRyLmxlbiwgJmR3UmVhZCwgTlVMTCkpIHsKICAgICAgc3RhdHVzID0gR2V0TGFzdEVycm9yKCk7CiAgICAgIGdvdG8gZmFpbDsKICAgIH0KI2VuZGlmCiAgICBpZiAoZHdSZWFkICE9IGhkci5sZW4pIHsKICAgICAgc3RhdHVzID0gUlBDX1NfUFJPVE9DT0xfRVJST1I7CiAgICAgIGdvdG8gZmFpbDsKICAgIH0KCiAgICBzdGF0dXMgPSBSUENfU19QUk9UT0NPTF9FUlJPUjsKCiAgICBzd2l0Y2ggKGhkci5wdHlwZSkgewogICAgY2FzZSBQS1RfUkVTUE9OU0U6CiAgICAgIGlmIChiaW5kLT5zZXJ2ZXIpIGdvdG8gZmFpbDsKICAgICAgYnJlYWs7CiAgICBjYXNlIFBLVF9SRVFVRVNUOgogICAgICBpZiAoIWJpbmQtPnNlcnZlcikgZ290byBmYWlsOwogICAgICBicmVhazsKICAgIGNhc2UgUEtUX0ZBVUxUOgogICAgICBwTXNnLT5ScGNGbGFncyB8PSBXSU5FX1JQQ0ZMQUdfRVhDRVBUSU9OOwogICAgICBzdGF0dXMgPSBSUENfU19DQUxMX0ZBSUxFRDsgLyogPyAqLwogICAgICBnb3RvIGZhaWw7CiAgICBkZWZhdWx0OgogICAgICBnb3RvIGZhaWw7CiAgICB9CgogICAgLyogc3VjY2VzcyAqLwogICAgc3RhdHVzID0gUlBDX1NfT0s7CgogICAgLyogRklYTUU6IGNoZWNrIGRlc3RpbmF0aW9uLCBldGM/ICovCiAgICBicmVhazsKICB9CmZhaWw6CiAgUlBDUlQ0X0Nsb3NlQmluZGluZyhiaW5kLCBjb25uKTsKICByZXR1cm4gc3RhdHVzOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgIElfUnBjU2VuZFJlY2VpdmUgW1JQQ1JUNC5AXQogKi8KUlBDX1NUQVRVUyBXSU5BUEkgSV9ScGNTZW5kUmVjZWl2ZShQUlBDX01FU1NBR0UgcE1zZykKewogIFJQQ19TVEFUVVMgc3RhdHVzOwoKICBUUkFDRSgiKCVwKVxuIiwgcE1zZyk7CiAgc3RhdHVzID0gSV9ScGNTZW5kKHBNc2cpOwogIGlmIChzdGF0dXMgPT0gUlBDX1NfT0spCiAgICBzdGF0dXMgPSBJX1JwY1JlY2VpdmUocE1zZyk7CiAgcmV0dXJuIHN0YXR1czsKfQo=