LyoKICogUlBDIG1lc3NhZ2VzCiAqCiAqIENvcHlyaWdodCAyMDAxLTIwMDIgT3ZlIEvldmVuLCBUcmFuc0dhbWluZyBUZWNobm9sb2dpZXMKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiAqCiAqIFRPRE86CiAqICAtIGZpZ3VyZSBvdXQgd2hldGhlciB3ZSAqcmVhbGx5KiBnb3QgdGhpcyByaWdodAogKiAgLSBjaGVjayBmb3IgZXJyb3JzIGFuZCB0aHJvdyBleGNlcHRpb25zCiAqICAtIGRlY2lkZSBpZiBPVkVSTEFQUEVEX1dPUktTCiAqLwoKI2luY2x1ZGUgPHN0ZGFyZy5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKI2luY2x1ZGUgIndpbmRlZi5oIgojaW5jbHVkZSAid2luYmFzZS5oIgojaW5jbHVkZSAid2luZXJyb3IuaCIKI2luY2x1ZGUgIndpbnJlZy5oIgoKI2luY2x1ZGUgInJwYy5oIgojaW5jbHVkZSAicnBjZGNlcC5oIgoKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKCiNpbmNsdWRlICJycGNfYmluZGluZy5oIgojaW5jbHVkZSAicnBjX21pc2MuaCIKI2luY2x1ZGUgInJwY19kZWZzLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChvbGUpOwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBJX1JwY0dldEJ1ZmZlciBbUlBDUlQ0LkBdCiAqLwpSUENfU1RBVFVTIFdJTkFQSSBJX1JwY0dldEJ1ZmZlcihQUlBDX01FU1NBR0UgcE1zZykKewogIFJwY0JpbmRpbmcqIGJpbmQgPSAoUnBjQmluZGluZyopcE1zZy0+SGFuZGxlOwogIHZvaWQqIGJ1ZjsKCiAgVFJBQ0UoIiglcCk6IEJ1ZmZlckxlbmd0aD0lZFxuIiwgcE1zZywgcE1zZy0+QnVmZmVyTGVuZ3RoKTsKICAvKiBGSVhNRTogcGZuQWxsb2NhdGU/ICovCiAgaWYgKGJpbmQtPnNlcnZlcikgewogICAgLyogaXQgdHVybnMgb3V0IHRoYXQgdGhlIG9yaWdpbmFsIGJ1ZmZlciBkYXRhIG11c3Qgc3RpbGwgYmUgYXZhaWxhYmxlCiAgICAgKiB3aGlsZSB0aGUgUlBDIHNlcnZlciBpcyBtYXJzaGFsbGluZyBhIHJlcGx5LCBzbyB3ZSBzaG91bGQgbm90IGRlYWxsb2NhdGUKICAgICAqIGl0LCB3ZSdsbCBsZWF2ZSBkZWFsbG9jYXRpbmcgdGhlIG9yaWdpbmFsIGJ1ZmZlciB0byB0aGUgUlBDIHNlcnZlciAqLwogICAgYnVmID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIDAsIHBNc2ctPkJ1ZmZlckxlbmd0aCk7CiAgfSBlbHNlIHsKICAgIGJ1ZiA9IEhlYXBSZUFsbG9jKEdldFByb2Nlc3NIZWFwKCksIDAsIHBNc2ctPkJ1ZmZlciwgcE1zZy0+QnVmZmVyTGVuZ3RoKTsKICB9CiAgVFJBQ0UoIkJ1ZmZlcj0lcFxuIiwgYnVmKTsKICBpZiAoYnVmKSBwTXNnLT5CdWZmZXIgPSBidWY7CiAgLyogRklYTUU6IHdoaWNoIGVycm9ycyB0byByZXR1cm4/ICovCiAgcmV0dXJuIGJ1ZiA/IFNfT0sgOiBFX09VVE9GTUVNT1JZOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgIElfUnBjRnJlZUJ1ZmZlciBbUlBDUlQ0LkBdCiAqLwpSUENfU1RBVFVTIFdJTkFQSSBJX1JwY0ZyZWVCdWZmZXIoUFJQQ19NRVNTQUdFIHBNc2cpCnsKICBUUkFDRSgiKCVwKSBCdWZmZXI9JXBcbiIsIHBNc2csIHBNc2ctPkJ1ZmZlcik7CiAgLyogRklYTUU6IHBmbkZyZWU/ICovCiAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgcE1zZy0+QnVmZmVyKTsKICBwTXNnLT5CdWZmZXIgPSBOVUxMOwogIHJldHVybiBTX09LOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgIElfUnBjU2VuZCBbUlBDUlQ0LkBdCiAqLwpSUENfU1RBVFVTIFdJTkFQSSBJX1JwY1NlbmQoUFJQQ19NRVNTQUdFIHBNc2cpCnsKICBScGNCaW5kaW5nKiBiaW5kID0gKFJwY0JpbmRpbmcqKXBNc2ctPkhhbmRsZTsKICBScGNDb25uZWN0aW9uKiBjb25uOwogIFJQQ19DTElFTlRfSU5URVJGQUNFKiBjaWYgPSBOVUxMOwogIFJQQ19TRVJWRVJfSU5URVJGQUNFKiBzaWYgPSBOVUxMOwogIFVVSUQqIG9iajsKICBVVUlEKiBhY3Q7CiAgUlBDX1NUQVRVUyBzdGF0dXM7CiAgUnBjUGt0SGRyIGhkcjsKCiAgVFJBQ0UoIiglcClcbiIsIHBNc2cpOwogIGlmICghYmluZCkgcmV0dXJuIFJQQ19TX0lOVkFMSURfQklORElORzsKCiAgc3RhdHVzID0gUlBDUlQ0X09wZW5CaW5kaW5nKGJpbmQsICZjb25uKTsKICBpZiAoc3RhdHVzICE9IFJQQ19TX09LKSByZXR1cm4gc3RhdHVzOwoKICBvYmogPSAmYmluZC0+T2JqZWN0VXVpZDsKICBhY3QgPSAmYmluZC0+QWN0aXZlVXVpZDsKCiAgaWYgKGJpbmQtPnNlcnZlcikgewogICAgc2lmID0gcE1zZy0+UnBjSW50ZXJmYWNlSW5mb3JtYXRpb247CiAgICBpZiAoIXNpZikgcmV0dXJuIFJQQ19TX0lOVEVSRkFDRV9OT1RfRk9VTkQ7IC8qID8gKi8KICB9IGVsc2UgewogICAgY2lmID0gcE1zZy0+UnBjSW50ZXJmYWNlSW5mb3JtYXRpb247CiAgICBpZiAoIWNpZikgcmV0dXJuIFJQQ19TX0lOVEVSRkFDRV9OT1RfRk9VTkQ7IC8qID8gKi8KICB9CgogIC8qIGluaXRpYWxpemUgcGFja2V0IGhlYWRlciAqLwogIG1lbXNldCgmaGRyLCAwLCBzaXplb2YoaGRyKSk7CiAgaGRyLnJwY192ZXIgPSA0OwogIGhkci5wdHlwZSA9IGJpbmQtPnNlcnZlcgogICAgICAgICAgICAgID8gKChwTXNnLT5ScGNGbGFncyAmIFdJTkVfUlBDRkxBR19FWENFUFRJT04pID8gUEtUX0ZBVUxUIDogUEtUX1JFU1BPTlNFKQogICAgICAgICAgICAgIDogUEtUX1JFUVVFU1Q7CiAgaGRyLm9iamVjdCA9ICpvYmo7IC8qIEZJWE1FOiBJSVJDIGlmZiBubyBvYmplY3QsIHRoZSBoZWFkZXIgc3RydWN0dXJlIGV4Y2x1ZGVzIHRoaXMgZWx0ICovCiAgaGRyLmlmX2lkID0gKGJpbmQtPnNlcnZlcikgPyBzaWYtPkludGVyZmFjZUlkLlN5bnRheEdVSUQgOiBjaWYtPkludGVyZmFjZUlkLlN5bnRheEdVSUQ7CiAgaGRyLmlmX3ZlcnMgPSAKICAgIChiaW5kLT5zZXJ2ZXIpID8KICAgIE1BS0VMT05HKHNpZi0+SW50ZXJmYWNlSWQuU3ludGF4VmVyc2lvbi5NaW5vclZlcnNpb24sIHNpZi0+SW50ZXJmYWNlSWQuU3ludGF4VmVyc2lvbi5NYWpvclZlcnNpb24pIDoKICAgIE1BS0VMT05HKGNpZi0+SW50ZXJmYWNlSWQuU3ludGF4VmVyc2lvbi5NaW5vclZlcnNpb24sIGNpZi0+SW50ZXJmYWNlSWQuU3ludGF4VmVyc2lvbi5NYWpvclZlcnNpb24pOwogIGhkci5hY3RfaWQgPSAqYWN0OwogIGhkci5vcG51bSA9IHBNc2ctPlByb2NOdW07CiAgLyogb25seSB0aGUgbG93LW9yZGVyIDMgb2N0ZXRzIG9mIHRoZSBEYXRhUmVwcmVzZW50YXRpb24gZ28gaW4gdGhlIGhlYWRlciAqLwogIGhkci5kcmVwWzBdID0gTE9CWVRFKExPV09SRChwTXNnLT5EYXRhUmVwcmVzZW50YXRpb24pKTsKICBoZHIuZHJlcFsxXSA9IEhJQllURShMT1dPUkQocE1zZy0+RGF0YVJlcHJlc2VudGF0aW9uKSk7CiAgaGRyLmRyZXBbMl0gPSBMT0JZVEUoSElXT1JEKHBNc2ctPkRhdGFSZXByZXNlbnRhdGlvbikpOwogIGhkci5sZW4gPSBwTXNnLT5CdWZmZXJMZW5ndGg7CgogIC8qIHRyYW5zbWl0IHBhY2tldCAqLwogIGlmICghV3JpdGVGaWxlKGNvbm4tPmNvbm4sICZoZHIsIHNpemVvZihoZHIpLCBOVUxMLCBOVUxMKSkgewogICAgc3RhdHVzID0gR2V0TGFzdEVycm9yKCk7CiAgICBnb3RvIGZhaWw7CiAgfQogIGlmIChwTXNnLT5CdWZmZXJMZW5ndGggJiYgIVdyaXRlRmlsZShjb25uLT5jb25uLCBwTXNnLT5CdWZmZXIsIHBNc2ctPkJ1ZmZlckxlbmd0aCwgTlVMTCwgTlVMTCkpIHsKICAgIHN0YXR1cyA9IEdldExhc3RFcnJvcigpOwogICAgZ290byBmYWlsOwogIH0KCiAgLyogc3VjY2VzcyAqLwogIGlmICghYmluZC0+c2VydmVyKSB7CiAgICAvKiBzYXZlIHRoZSBjb25uZWN0aW9uLCBzbyB0aGUgcmVzcG9uc2UgY2FuIGJlIHJlYWQgZnJvbSBpdCAqLwogICAgcE1zZy0+UmVzZXJ2ZWRGb3JSdW50aW1lID0gY29ubjsKICAgIHJldHVybiBSUENfU19PSzsKICB9CiAgUlBDUlQ0X0Nsb3NlQmluZGluZyhiaW5kLCBjb25uKTsKICBzdGF0dXMgPSBSUENfU19PSzsKZmFpbDoKCiAgcmV0dXJuIHN0YXR1czsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBJX1JwY1JlY2VpdmUgW1JQQ1JUNC5AXQogKi8KUlBDX1NUQVRVUyBXSU5BUEkgSV9ScGNSZWNlaXZlKFBSUENfTUVTU0FHRSBwTXNnKQp7CiAgUnBjQmluZGluZyogYmluZCA9IChScGNCaW5kaW5nKilwTXNnLT5IYW5kbGU7CiAgUnBjQ29ubmVjdGlvbiogY29ubjsKICBVVUlEKiBhY3Q7CiAgUlBDX1NUQVRVUyBzdGF0dXM7CiAgUnBjUGt0SGRyIGhkcjsKICBEV09SRCBkd1JlYWQ7CgogIFRSQUNFKCIoJXApXG4iLCBwTXNnKTsKICBpZiAoIWJpbmQpIHJldHVybiBSUENfU19JTlZBTElEX0JJTkRJTkc7CgogIGlmIChwTXNnLT5SZXNlcnZlZEZvclJ1bnRpbWUpIHsKICAgIGNvbm4gPSBwTXNnLT5SZXNlcnZlZEZvclJ1bnRpbWU7CiAgICBwTXNnLT5SZXNlcnZlZEZvclJ1bnRpbWUgPSBOVUxMOwogIH0gZWxzZSB7CiAgICBzdGF0dXMgPSBSUENSVDRfT3BlbkJpbmRpbmcoYmluZCwgJmNvbm4pOwogICAgaWYgKHN0YXR1cyAhPSBSUENfU19PSykgcmV0dXJuIHN0YXR1czsKICB9CgogIGFjdCA9ICZiaW5kLT5BY3RpdmVVdWlkOwoKICBmb3IgKDs7KSB7CiAgICAvKiByZWFkIHBhY2tldCBoZWFkZXIgKi8KI2lmZGVmIE9WRVJMQVBQRURfV09SS1MKICAgIGlmICghUmVhZEZpbGUoY29ubi0+Y29ubiwgJmhkciwgc2l6ZW9mKGhkciksICZkd1JlYWQsICZjb25uLT5vdmwpKSB7CiAgICAgIERXT1JEIGVyciA9IEdldExhc3RFcnJvcigpOwogICAgICBpZiAoZXJyICE9IEVSUk9SX0lPX1BFTkRJTkcpIHsKICAgICAgICBzdGF0dXMgPSBlcnI7CiAgICAgICAgZ290byBmYWlsOwogICAgICB9CiAgICAgIGlmICghR2V0T3ZlcmxhcHBlZFJlc3VsdChjb25uLT5jb25uLCAmY29ubi0+b3ZsLCAmZHdSZWFkLCBUUlVFKSkgewogICAgICAgIHN0YXR1cyA9IEdldExhc3RFcnJvcigpOwogICAgICAgIGdvdG8gZmFpbDsKICAgICAgfQogICAgfQojZWxzZQogICAgaWYgKCFSZWFkRmlsZShjb25uLT5jb25uLCAmaGRyLCBzaXplb2YoaGRyKSwgJmR3UmVhZCwgTlVMTCkpIHsKICAgICAgc3RhdHVzID0gR2V0TGFzdEVycm9yKCk7CiAgICAgIGdvdG8gZmFpbDsKICAgIH0KI2VuZGlmCiAgICBpZiAoZHdSZWFkICE9IHNpemVvZihoZHIpKSB7CiAgICAgIHN0YXR1cyA9IFJQQ19TX1BST1RPQ09MX0VSUk9SOwogICAgICBnb3RvIGZhaWw7CiAgICB9CgogICAgLyogcmVhZCBwYWNrZXQgYm9keSAqLwogICAgcE1zZy0+QnVmZmVyTGVuZ3RoID0gaGRyLmxlbjsKICAgIHN0YXR1cyA9IElfUnBjR2V0QnVmZmVyKHBNc2cpOwogICAgaWYgKHN0YXR1cyAhPSBSUENfU19PSykgZ290byBmYWlsOwogICAgaWYgKCFwTXNnLT5CdWZmZXJMZW5ndGgpIGR3UmVhZCA9IDA7IGVsc2UKI2lmZGVmIE9WRVJMQVBQRURfV09SS1MKICAgIGlmICghUmVhZEZpbGUoY29ubi0+Y29ubiwgcE1zZy0+QnVmZmVyLCBoZHIubGVuLCAmZHdSZWFkLCAmY29ubi0+b3ZsKSkgewogICAgICBEV09SRCBlcnIgPSBHZXRMYXN0RXJyb3IoKTsKICAgICAgaWYgKGVyciAhPSBFUlJPUl9JT19QRU5ESU5HKSB7CiAgICAgICAgc3RhdHVzID0gZXJyOwogICAgICAgIGdvdG8gZmFpbDsKICAgICAgfQogICAgICBpZiAoIUdldE92ZXJsYXBwZWRSZXN1bHQoY29ubi0+Y29ubiwgJmNvbm4tPm92bCwgJmR3UmVhZCwgVFJVRSkpIHsKICAgICAgICBzdGF0dXMgPSBHZXRMYXN0RXJyb3IoKTsKICAgICAgICBnb3RvIGZhaWw7CiAgICAgIH0KICAgIH0KI2Vsc2UKICAgIGlmICghUmVhZEZpbGUoY29ubi0+Y29ubiwgcE1zZy0+QnVmZmVyLCBoZHIubGVuLCAmZHdSZWFkLCBOVUxMKSkgewogICAgICBzdGF0dXMgPSBHZXRMYXN0RXJyb3IoKTsKICAgICAgZ290byBmYWlsOwogICAgfQojZW5kaWYKICAgIGlmIChkd1JlYWQgIT0gaGRyLmxlbikgewogICAgICBzdGF0dXMgPSBSUENfU19QUk9UT0NPTF9FUlJPUjsKICAgICAgZ290byBmYWlsOwogICAgfQoKICAgIHN0YXR1cyA9IFJQQ19TX1BST1RPQ09MX0VSUk9SOwoKICAgIHN3aXRjaCAoaGRyLnB0eXBlKSB7CiAgICBjYXNlIFBLVF9SRVNQT05TRToKICAgICAgaWYgKGJpbmQtPnNlcnZlcikgZ290byBmYWlsOwogICAgICBicmVhazsKICAgIGNhc2UgUEtUX1JFUVVFU1Q6CiAgICAgIGlmICghYmluZC0+c2VydmVyKSBnb3RvIGZhaWw7CiAgICAgIGJyZWFrOwogICAgY2FzZSBQS1RfRkFVTFQ6CiAgICAgIHBNc2ctPlJwY0ZsYWdzIHw9IFdJTkVfUlBDRkxBR19FWENFUFRJT047CiAgICAgIHN0YXR1cyA9IFJQQ19TX0NBTExfRkFJTEVEOyAvKiA/ICovCiAgICAgIGdvdG8gZmFpbDsKICAgIGRlZmF1bHQ6CiAgICAgIGdvdG8gZmFpbDsKICAgIH0KCiAgICAvKiBzdWNjZXNzICovCiAgICBzdGF0dXMgPSBSUENfU19PSzsKCiAgICAvKiBGSVhNRTogY2hlY2sgZGVzdGluYXRpb24sIGV0Yz8gKi8KICAgIGJyZWFrOwogIH0KZmFpbDoKICBSUENSVDRfQ2xvc2VCaW5kaW5nKGJpbmQsIGNvbm4pOwogIHJldHVybiBzdGF0dXM7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiAgICAgICAgICAgSV9ScGNTZW5kUmVjZWl2ZSBbUlBDUlQ0LkBdCiAqLwpSUENfU1RBVFVTIFdJTkFQSSBJX1JwY1NlbmRSZWNlaXZlKFBSUENfTUVTU0FHRSBwTXNnKQp7CiAgUlBDX1NUQVRVUyBzdGF0dXM7CgogIFRSQUNFKCIoJXApXG4iLCBwTXNnKTsKICBzdGF0dXMgPSBJX1JwY1NlbmQocE1zZyk7CiAgaWYgKHN0YXR1cyA9PSBSUENfU19PSykKICAgIHN0YXR1cyA9IElfUnBjUmVjZWl2ZShwTXNnKTsKICByZXR1cm4gc3RhdHVzOwp9Cg==