LyoKICogQ29udGV4dCBhbmQgcmVuZGVyIHRhcmdldCBtYW5hZ2VtZW50IGluIHdpbmVkM2QKICoKICogQ29weXJpZ2h0IDIwMDcgU3RlZmFuIET2c2luZ2VyIGZvciBDb2RlV2VhdmVycwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxLCBVU0EKICovCgojaW5jbHVkZSAiY29uZmlnLmgiCiNpbmNsdWRlIDxzdGRpby5oPgojaWZkZWYgSEFWRV9GTE9BVF9ICiMgaW5jbHVkZSA8ZmxvYXQuaD4KI2VuZGlmCiNpbmNsdWRlICJ3aW5lZDNkX3ByaXZhdGUuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKGQzZCk7CgojZGVmaW5lIEdMSU5GT19MT0NBVElPTiBUaGlzLT5hZGFwdGVyLT5nbF9pbmZvCgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29udGV4dF9NYXJrU3RhdGVEaXJ0eQogKgogKiBNYXJrcyBhIHN0YXRlIGluIGEgY29udGV4dCBkaXJ0eS4gT25seSBvbmUgY29udGV4dCwgb3Bwb3NlZCB0bwogKiBJV2luZUQzRERldmljZUltcGxfTWFya1N0YXRlRGlydHksIHdoaWNoIG1hcmtzIHRoZSBzdGF0ZSBkaXJ0eSBpbiBhbGwKICogY29udGV4dHMKICoKICogUGFyYW1zOgogKiAgY29udGV4dDogQ29udGV4dCB0byBtYXJrIHRoZSBzdGF0ZSBkaXJ0eSBpbgogKiAgc3RhdGU6IFN0YXRlIHRvIG1hcmsgZGlydHkKICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpzdGF0aWMgdm9pZCBDb250ZXh0X01hcmtTdGF0ZURpcnR5KFdpbmVEM0RDb250ZXh0ICpjb250ZXh0LCBEV09SRCBzdGF0ZSkgewogICAgRFdPUkQgcmVwID0gU3RhdGVUYWJsZVtzdGF0ZV0ucmVwcmVzZW50YXRpdmU7CiAgICBEV09SRCBpZHg7CiAgICBCWVRFIHNoaWZ0OwoKICAgIGlmKCFyZXAgfHwgaXNTdGF0ZURpcnR5KGNvbnRleHQsIHJlcCkpIHJldHVybjsKCiAgICBjb250ZXh0LT5kaXJ0eUFycmF5W2NvbnRleHQtPm51bURpcnR5RW50cmllcysrXSA9IHJlcDsKICAgIGlkeCA9IHJlcCA+PiA1OwogICAgc2hpZnQgPSByZXAgJiAweDFmOwogICAgY29udGV4dC0+aXNTdGF0ZURpcnR5W2lkeF0gfD0gKDEgPDwgc2hpZnQpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQWRkQ29udGV4dFRvQXJyYXkKICoKICogQWRkcyBhIGNvbnRleHQgdG8gdGhlIGNvbnRleHQgYXJyYXkuIEhlbHBlciBmdW5jdGlvbiBmb3IgQ3JlYXRlQ29udGV4dAogKgogKiBUaGlzIG1ldGhvZCBpcyBub3QgY2FsbGVkIGluIHBlcmZvcm1hbmNlLWNyaXRpY2FsIGNvZGUgcGF0aHMsIG9ubHkgd2hlbiBhCiAqIG5ldyByZW5kZXIgdGFyZ2V0IG9yIHN3YXBjaGFpbiBpcyBjcmVhdGVkLiBUaHVzIHBlcmZvcm1hbmNlIGlzIG5vdCBhbiBpc3N1ZQogKiBoZXJlLgogKgogKiBQYXJhbXM6CiAqICBUaGlzOiBEZXZpY2UgdG8gYWRkIHRoZSBjb250ZXh0IGZvcgogKiAgaGRjOiBkZXZpY2UgY29udGV4dAogKiAgZ2xDdHg6IFdHTCBjb250ZXh0IHRvIGFkZAogKiAgcGJ1ZmZlcjogb3B0aW9uYWwgcGJ1ZmZlciB1c2VkIHdpdGggdGhpcyBjb250ZXh0CiAqCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8Kc3RhdGljIFdpbmVEM0RDb250ZXh0ICpBZGRDb250ZXh0VG9BcnJheShJV2luZUQzRERldmljZUltcGwgKlRoaXMsIEhXTkQgd2luX2hhbmRsZSwgSERDIGhkYywgSEdMUkMgZ2xDdHgsIEhQQlVGRkVSQVJCIHBidWZmZXIpIHsKICAgIFdpbmVEM0RDb250ZXh0ICoqb2xkQXJyYXkgPSBUaGlzLT5jb250ZXh0czsKICAgIERXT1JEIHN0YXRlOwoKICAgIFRoaXMtPmNvbnRleHRzID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIDAsIHNpemVvZigqVGhpcy0+Y29udGV4dHMpICogKFRoaXMtPm51bUNvbnRleHRzICsgMSkpOwogICAgaWYoVGhpcy0+Y29udGV4dHMgPT0gTlVMTCkgewogICAgICAgIEVSUigiVW5hYmxlIHRvIGdyb3cgdGhlIGNvbnRleHQgYXJyYXlcbiIpOwogICAgICAgIFRoaXMtPmNvbnRleHRzID0gb2xkQXJyYXk7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CiAgICBpZihvbGRBcnJheSkgewogICAgICAgIG1lbWNweShUaGlzLT5jb250ZXh0cywgb2xkQXJyYXksIHNpemVvZigqVGhpcy0+Y29udGV4dHMpICogVGhpcy0+bnVtQ29udGV4dHMpOwogICAgfQoKICAgIFRoaXMtPmNvbnRleHRzW1RoaXMtPm51bUNvbnRleHRzXSA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCBIRUFQX1pFUk9fTUVNT1JZLCBzaXplb2YoV2luZUQzRENvbnRleHQpKTsKICAgIGlmKFRoaXMtPmNvbnRleHRzW1RoaXMtPm51bUNvbnRleHRzXSA9PSBOVUxMKSB7CiAgICAgICAgRVJSKCJVbmFibGUgdG8gYWxsb2NhdGUgYSBuZXcgY29udGV4dFxuIik7CiAgICAgICAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgVGhpcy0+Y29udGV4dHMpOwogICAgICAgIFRoaXMtPmNvbnRleHRzID0gb2xkQXJyYXk7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CgogICAgVGhpcy0+Y29udGV4dHNbVGhpcy0+bnVtQ29udGV4dHNdLT5oZGMgPSBoZGM7CiAgICBUaGlzLT5jb250ZXh0c1tUaGlzLT5udW1Db250ZXh0c10tPmdsQ3R4ID0gZ2xDdHg7CiAgICBUaGlzLT5jb250ZXh0c1tUaGlzLT5udW1Db250ZXh0c10tPnBidWZmZXIgPSBwYnVmZmVyOwogICAgVGhpcy0+Y29udGV4dHNbVGhpcy0+bnVtQ29udGV4dHNdLT53aW5faGFuZGxlID0gd2luX2hhbmRsZTsKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIG9sZEFycmF5KTsKCiAgICAvKiBNYXJrIGFsbCBzdGF0ZXMgZGlydHkgdG8gZm9yY2UgYSBwcm9wZXIgaW5pdGlhbGl6YXRpb24gb2YgdGhlIHN0YXRlcyBvbiB0aGUgZmlyc3QgdXNlIG9mIHRoZSBjb250ZXh0CiAgICAgKi8KICAgIGZvcihzdGF0ZSA9IDA7IHN0YXRlIDw9IFNUQVRFX0hJR0hFU1Q7IHN0YXRlKyspIHsKICAgICAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KFRoaXMtPmNvbnRleHRzW1RoaXMtPm51bUNvbnRleHRzXSwgc3RhdGUpOwogICAgfQoKICAgIFRoaXMtPm51bUNvbnRleHRzKys7CiAgICBUUkFDRSgiQ3JlYXRlZCBjb250ZXh0ICVwXG4iLCBUaGlzLT5jb250ZXh0c1tUaGlzLT5udW1Db250ZXh0cyAtIDFdKTsKICAgIHJldHVybiBUaGlzLT5jb250ZXh0c1tUaGlzLT5udW1Db250ZXh0cyAtIDFdOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ3JlYXRlQ29udGV4dAogKgogKiBDcmVhdGVzIGEgbmV3IGNvbnRleHQgZm9yIGEgd2luZG93LCBvciBhIHBidWZmZXIgY29udGV4dC4KICoKICogKiBQYXJhbXM6CiAqICBUaGlzOiBEZXZpY2UgdG8gYWN0aXZhdGUgdGhlIGNvbnRleHQgZm9yCiAqICB0YXJnZXQ6IFN1cmZhY2UgdGhpcyBjb250ZXh0IHdpbGwgcmVuZGVyIHRvCiAqICB3aW5faGFuZGxlOiBoYW5kbGUgdG8gdGhlIHdpbmRvdyB3aGljaCB3ZSBhcmUgZHJhd2luZyB0bwogKiAgY3JlYXRlX3BidWZmZXI6IHRlbGxzIHdoZXRoZXIgdG8gY3JlYXRlIGEgcGJ1ZmZlciBvciBub3QKICogIHBQcmVzZW50UGFyYW1ldGVyczogY29udGFpbnMgdGhlIHBpeGVsZm9ybWF0cyB0byB1c2UgZm9yIG9uc2NyZWVuIHJlbmRlcmluZwogKgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCldpbmVEM0RDb250ZXh0ICpDcmVhdGVDb250ZXh0KElXaW5lRDNERGV2aWNlSW1wbCAqVGhpcywgSVdpbmVEM0RTdXJmYWNlSW1wbCAqdGFyZ2V0LCBIV05EIHdpbl9oYW5kbGUsIEJPT0wgY3JlYXRlX3BidWZmZXIsIGNvbnN0IFdJTkVEM0RQUkVTRU5UX1BBUkFNRVRFUlMgKnBQcmVzZW50UGFybXMpIHsKICAgIEhEQyBvbGREcmF3YWJsZSwgaGRjOwogICAgSFBCVUZGRVJBUkIgcGJ1ZmZlciA9IE5VTEw7CiAgICBIR0xSQyBjdHggPSBOVUxMLCBvbGRDdHg7CiAgICBXaW5lRDNEQ29udGV4dCAqcmV0ID0gTlVMTDsKICAgIGludCBzOwoKICAgIFRSQUNFKCIoJXApOiBDcmVhdGluZyBhICVzIGNvbnRleHQgZm9yIHJlbmRlciB0YXJnZXQgJXBcbiIsIFRoaXMsIGNyZWF0ZV9wYnVmZmVyID8gIm9mZnNjcmVlbiIgOiAib25zY3JlZW4iLCB0YXJnZXQpOwoKI2RlZmluZSBQVVNIMShhdHQpICAgICAgICBhdHRyaWJzW25BdHRyaWJzKytdID0gKGF0dCk7CiNkZWZpbmUgUFVTSDIoYXR0LHZhbHVlKSAgYXR0cmlic1tuQXR0cmlicysrXSA9IChhdHQpOyBhdHRyaWJzW25BdHRyaWJzKytdID0gKHZhbHVlKTsKICAgIGlmKGNyZWF0ZV9wYnVmZmVyKSB7CiAgICAgICAgSERDIGhkY19wYXJlbnQgPSBHZXREQyh3aW5faGFuZGxlKTsKICAgICAgICBpbnQgaVBpeGVsRm9ybWF0ID0gMDsKICAgICAgICBzaG9ydCByZWRCaXRzLCBncmVlbkJpdHMsIGJsdWVCaXRzLCBhbHBoYUJpdHMsIGNvbG9yQml0czsKICAgICAgICBzaG9ydCBkZXB0aEJpdHMsIHN0ZW5jaWxCaXRzOwoKICAgICAgICBJV2luZUQzRFN1cmZhY2UgKlN0ZW5jaWxTdXJmYWNlID0gVGhpcy0+c3RlbmNpbEJ1ZmZlclRhcmdldDsKICAgICAgICBXSU5FRDNERk9STUFUIFN0ZW5jaWxCdWZmZXJGb3JtYXQgPSAoTlVMTCAhPSBTdGVuY2lsU3VyZmFjZSkgPyAoKElXaW5lRDNEU3VyZmFjZUltcGwgKikgU3RlbmNpbFN1cmZhY2UpLT5yZXNvdXJjZS5mb3JtYXQgOiAwOwoKICAgICAgICBpbnQgYXR0cmlic1syNTZdOwogICAgICAgIGludCBuQXR0cmlicyA9IDA7CiAgICAgICAgdW5zaWduZWQgaW50IG5Gb3JtYXRzOwoKICAgICAgICAvKiBSZXRyaWV2ZSB0aGUgc3BlY2lmaWNhdGlvbnMgZm9yIHRoZSBwaXhlbGZvcm1hdCBmcm9tIHRoZSBiYWNrYnVmZmVyIC8gc3RlbmNpbGJ1ZmZlciAqLwogICAgICAgIGdldENvbG9yQml0cyh0YXJnZXQtPnJlc291cmNlLmZvcm1hdCwgJnJlZEJpdHMsICZncmVlbkJpdHMsICZibHVlQml0cywgJmFscGhhQml0cywgJmNvbG9yQml0cyk7CiAgICAgICAgZ2V0RGVwdGhTdGVuY2lsQml0cyhTdGVuY2lsQnVmZmVyRm9ybWF0LCAmZGVwdGhCaXRzLCAmc3RlbmNpbEJpdHMpOwogICAgICAgIFBVU0gyKFdHTF9EUkFXX1RPX1BCVUZGRVJfQVJCLCAxKTsgLyogV2UgbmVlZCBwYnVmZmVyIHN1cHBvcnQ7IGRvdWJsZWJ1ZmZlcmluZyBpc24ndCBuZWVkZWQgKi8KICAgICAgICBQVVNIMihXR0xfUElYRUxfVFlQRV9BUkIsIFdHTF9UWVBFX1JHQkFfQVJCKTsgLyogTWFrZSBzdXJlIHdlIGRvbid0IGdldCBhIGZsb2F0IG9yIGNvbG9yIGluZGV4IGZvcm1hdCAqLwogICAgICAgIFBVU0gyKFdHTF9DT0xPUl9CSVRTX0FSQiwgY29sb3JCaXRzKTsKICAgICAgICBQVVNIMihXR0xfUkVEX0JJVFNfQVJCLCByZWRCaXRzKTsKICAgICAgICBQVVNIMihXR0xfR1JFRU5fQklUU19BUkIsIGdyZWVuQml0cyk7CiAgICAgICAgUFVTSDIoV0dMX0JMVUVfQklUU19BUkIsIGJsdWVCaXRzKTsKICAgICAgICBQVVNIMihXR0xfQUxQSEFfQklUU19BUkIsIGFscGhhQml0cyk7CiAgICAgICAgUFVTSDIoV0dMX0RFUFRIX0JJVFNfQVJCLCBkZXB0aEJpdHMpOwogICAgICAgIFBVU0gyKFdHTF9TVEVOQ0lMX0JJVFNfQVJCLCBzdGVuY2lsQml0cyk7CiAgICAgICAgUFVTSDEoMCk7IC8qIGVuZCB0aGUgbGlzdCAqLwoKICAgICAgICAvKiBUcnkgdG8gZmluZCBhIHBpeGVsZm9ybWF0IHRoYXQgbWF0Y2hlcyBleGFjdGx5LiBJZiB0aGF0IGZhaWxzIGxldCBDaG9vc2VQaXhlbEZvcm1hdCB0cnkgdG8gZmluZCBhIGNsb3NlIG1hdGNoICovCiAgICAgICAgaWYoIUdMX0VYVENBTEwod2dsQ2hvb3NlUGl4ZWxGb3JtYXRBUkIoaGRjX3BhcmVudCwgKGNvbnN0IGludCopJmF0dHJpYnMsIE5VTEwsIDEsICZpUGl4ZWxGb3JtYXQsICZuRm9ybWF0cykpKQogICAgICAgIHsKICAgICAgICAgICAgUElYRUxGT1JNQVRERVNDUklQVE9SIHBmZDsKCiAgICAgICAgICAgIFRSQUNFKCJGYWxsaW5nIGJhY2sgdG8gQ2hvb3NlUGl4ZWxGb3JtYXQgYXMgd2dsQ2hvb3NlUGl4ZWxGb3JtYXRBUkIgZmFpbGVkXG4iKTsKCiAgICAgICAgICAgIFplcm9NZW1vcnkoJnBmZCwgc2l6ZW9mKHBmZCkpOwogICAgICAgICAgICBwZmQublNpemUgICAgICA9IHNpemVvZihwZmQpOwogICAgICAgICAgICBwZmQublZlcnNpb24gICA9IDE7CiAgICAgICAgICAgIHBmZC5kd0ZsYWdzICAgID0gUEZEX1NVUFBPUlRfT1BFTkdMIHwgUEZEX0RPVUJMRUJVRkZFUl9ET05UQ0FSRSB8IFBGRF9EUkFXX1RPX1dJTkRPVzsKICAgICAgICAgICAgcGZkLmlQaXhlbFR5cGUgPSBQRkRfVFlQRV9SR0JBOwogICAgICAgICAgICBwZmQuY0NvbG9yQml0cyA9IGNvbG9yQml0czsKICAgICAgICAgICAgcGZkLmNEZXB0aEJpdHMgPSBkZXB0aEJpdHM7CiAgICAgICAgICAgIHBmZC5jU3RlbmNpbEJpdHMgPSBzdGVuY2lsQml0czsKICAgICAgICAgICAgcGZkLmlMYXllclR5cGUgPSBQRkRfTUFJTl9QTEFORTsKCiAgICAgICAgICAgIGlQaXhlbEZvcm1hdCA9IENob29zZVBpeGVsRm9ybWF0KGhkY19wYXJlbnQsICZwZmQpOwogICAgICAgICAgICBpZighaVBpeGVsRm9ybWF0KSB7CiAgICAgICAgICAgICAgICAvKiBJZiB0aGlzIGhhcHBlbnMgc29tZXRoaW5nIGlzIHZlcnkgd3JvbmcgYXMgQ2hvb3NlUGl4ZWxGb3JtYXQgYmFyZWx5IGZhaWxzICovCiAgICAgICAgICAgICAgICBFUlIoIkNhbid0IGZpbmQgYSBzdWl0YWJsZSBpUGl4ZWxGb3JtYXQgZm9yIHRoZSBwYnVmZmVyXG4iKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgVFJBQ0UoIkNyZWF0aW5nIGEgcEJ1ZmZlciBkcmF3YWJsZSBmb3IgdGhlIG5ldyBjb250ZXh0XG4iKTsKICAgICAgICBwYnVmZmVyID0gR0xfRVhUQ0FMTCh3Z2xDcmVhdGVQYnVmZmVyQVJCKGhkY19wYXJlbnQsIGlQaXhlbEZvcm1hdCwgdGFyZ2V0LT5jdXJyZW50RGVzYy5XaWR0aCwgdGFyZ2V0LT5jdXJyZW50RGVzYy5IZWlnaHQsIDApKTsKICAgICAgICBpZighcGJ1ZmZlcikgewogICAgICAgICAgICBFUlIoIkNhbm5vdCBjcmVhdGUgYSBwYnVmZmVyXG4iKTsKICAgICAgICAgICAgUmVsZWFzZURDKHdpbl9oYW5kbGUsIGhkY19wYXJlbnQpOwogICAgICAgICAgICBnb3RvIG91dDsKICAgICAgICB9CgogICAgICAgIC8qIEluIFdHTCBhIHBidWZmZXIgaXMgJ3dyYXBwZWQnIGluc2lkZSBhIEhEQyB0byAnZm9vbCcgd2dsTWFrZUN1cnJlbnQgKi8KICAgICAgICBoZGMgPSBHTF9FWFRDQUxMKHdnbEdldFBidWZmZXJEQ0FSQihwYnVmZmVyKSk7CiAgICAgICAgaWYoIWhkYykgewogICAgICAgICAgICBFUlIoIkNhbm5vdCBnZXQgYSBIREMgZm9yIHBidWZmZXIgKCVwKVxuIiwgcGJ1ZmZlcik7CiAgICAgICAgICAgIEdMX0VYVENBTEwod2dsRGVzdHJveVBidWZmZXJBUkIocGJ1ZmZlcikpOwogICAgICAgICAgICBSZWxlYXNlREMod2luX2hhbmRsZSwgaGRjX3BhcmVudCk7CiAgICAgICAgICAgIGdvdG8gb3V0OwogICAgICAgIH0KICAgICAgICBSZWxlYXNlREMod2luX2hhbmRsZSwgaGRjX3BhcmVudCk7CiAgICB9IGVsc2UgewogICAgICAgIFBJWEVMRk9STUFUREVTQ1JJUFRPUiBwZmQ7CiAgICAgICAgaW50IGlQaXhlbEZvcm1hdDsKICAgICAgICBzaG9ydCByZWRCaXRzLCBncmVlbkJpdHMsIGJsdWVCaXRzLCBhbHBoYUJpdHMsIGNvbG9yQml0czsKICAgICAgICBzaG9ydCBkZXB0aEJpdHM9MCwgc3RlbmNpbEJpdHM9MDsKICAgICAgICBpbnQgcmVzOwogICAgICAgIGludCBhdHRyaWJzWzI1Nl07CiAgICAgICAgaW50IG5BdHRyaWJzID0gMDsKICAgICAgICB1bnNpZ25lZCBpbnQgbkZvcm1hdHM7CgogICAgICAgIGhkYyA9IEdldERDKHdpbl9oYW5kbGUpOwogICAgICAgIGlmKGhkYyA9PSBOVUxMKSB7CiAgICAgICAgICAgIEVSUigiQ2Fubm90IHJldHJpZXZlIGEgZGV2aWNlIGNvbnRleHQhXG4iKTsKICAgICAgICAgICAgZ290byBvdXQ7CiAgICAgICAgfQoKICAgICAgICAvKiBQaXhlbEZvcm1hdCBzZWxlY3Rpb24gKi8KICAgICAgICBQVVNIMihXR0xfRFJBV19UT19XSU5ET1dfQVJCLCBHTF9UUlVFKTsgLyogV2Ugd2FudCB0byBkcmF3IHRvIGEgd2luZG93ICovCiAgICAgICAgUFVTSDIoV0dMX0RPVUJMRV9CVUZGRVJfQVJCLCBHTF9UUlVFKTsKICAgICAgICBQVVNIMihXR0xfUElYRUxfVFlQRV9BUkIsIFdHTF9UWVBFX1JHQkFfQVJCKTsgLyogTWFrZSBzdXJlIHdlIGRvbid0IGdldCBhIGZsb2F0IG9yIGNvbG9yIGluZGV4IGZvcm1hdCAqLwogICAgICAgIFBVU0gyKFdHTF9TVVBQT1JUX09QRU5HTF9BUkIsIEdMX1RSVUUpOwogICAgICAgIFBVU0gyKFdHTF9BQ0NFTEVSQVRJT05fQVJCLCBXR0xfRlVMTF9BQ0NFTEVSQVRJT05fQVJCKTsgLyogTWFrZSBzdXJlIHdlIHJlY2VpdmUgYW4gYWNjZWxlcmF0ZWQgZm9ybWF0LiBPbiB3aW5kb3dzIChhdCBsZWFzdCBvbiBBVEkpIHRoaXMgaXMgbm90IGFsd2F5cyB0aGUgY2FzZSAqLwoKICAgICAgICBpZighZ2V0Q29sb3JCaXRzKHRhcmdldC0+cmVzb3VyY2UuZm9ybWF0LCAmcmVkQml0cywgJmdyZWVuQml0cywgJmJsdWVCaXRzLCAmYWxwaGFCaXRzLCAmY29sb3JCaXRzKSkgewogICAgICAgICAgICBFUlIoIlVuYWJsZSB0byBnZXQgY29sb3IgYml0cyBmb3IgZm9ybWF0ICUjeCFcbiIsIHRhcmdldC0+cmVzb3VyY2UuZm9ybWF0KTsKICAgICAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgICAgIH0KICAgICAgICBQVVNIMihXR0xfQ09MT1JfQklUU19BUkIsIGNvbG9yQml0cyk7CiAgICAgICAgUFVTSDIoV0dMX1JFRF9CSVRTX0FSQiwgcmVkQml0cyk7CiAgICAgICAgUFVTSDIoV0dMX0dSRUVOX0JJVFNfQVJCLCBncmVlbkJpdHMpOwogICAgICAgIFBVU0gyKFdHTF9CTFVFX0JJVFNfQVJCLCBibHVlQml0cyk7CiAgICAgICAgUFVTSDIoV0dMX0FMUEhBX0JJVFNfQVJCLCBhbHBoYUJpdHMpOwoKICAgICAgICAvKiBSZXRyaWV2ZSB0aGUgZGVwdGggc3RlbmNpbCBmb3JtYXQgZnJvbSB0aGUgcHJlc2VudCBwYXJhbWV0ZXJzLgogICAgICAgICAqIFRoZSBjaG9pY2Ugb2YgdGhlIHByb3BlciBmb3JtYXQgY2FuIGdpdmUgYSBuaWNlIHBlcmZvcm1hbmNlIGJvb3N0CiAgICAgICAgICogaW4gY2FzZSBvZiBHUFUgbGltaXRlZCBwcm9ncmFtcy4gKi8KICAgICAgICBpZihwUHJlc2VudFBhcm1zLT5FbmFibGVBdXRvRGVwdGhTdGVuY2lsKSB7CiAgICAgICAgICAgIFRSQUNFKCJwUHJlc2VudFBhcm1zLT5FbmFibGVBdXRvRGVwdGhTdGVuY2lsPWVuYWJsZWQ7IHVzaW5nIEF1dG9EZXB0aFN0ZW5jaWxGb3JtYXQ9JXNcbiIsIGRlYnVnX2QzZGZvcm1hdChwUHJlc2VudFBhcm1zLT5BdXRvRGVwdGhTdGVuY2lsRm9ybWF0KSk7CiAgICAgICAgICAgIGlmKCFnZXREZXB0aFN0ZW5jaWxCaXRzKHBQcmVzZW50UGFybXMtPkF1dG9EZXB0aFN0ZW5jaWxGb3JtYXQsICZkZXB0aEJpdHMsICZzdGVuY2lsQml0cykpIHsKICAgICAgICAgICAgICAgIEVSUigiVW5hYmxlIHRvIGdldCBkZXB0aCAvIHN0ZW5jaWwgYml0cyBmb3IgQXV0b0RlcHRoU3RlbmNpbEZvcm1hdCAlI3ghXG4iLCBwUHJlc2VudFBhcm1zLT5BdXRvRGVwdGhTdGVuY2lsRm9ybWF0KTsKICAgICAgICAgICAgICAgIHJldHVybiBGQUxTRTsKICAgICAgICAgICAgfQogICAgICAgICAgICBQVVNIMihXR0xfREVQVEhfQklUU19BUkIsIGRlcHRoQml0cyk7CiAgICAgICAgICAgIFBVU0gyKFdHTF9TVEVOQ0lMX0JJVFNfQVJCLCBzdGVuY2lsQml0cyk7CiAgICAgICAgfQoKICAgICAgICBQVVNIMSgwKTsgLyogZW5kIHRoZSBsaXN0ICovCgogICAgICAgIC8qIEluIGNhc2Ugb2YgZmFpbHVyZSBob3BlIHRoYXQgc3RhbmRhcmQgQ2hvb29zZVBpeGVsRm9ybWF0IHdpbGwgZmluZCBzb21ldGhpbmcgc3VpdGFibGUgKi8KICAgICAgICBpZighR0xfRVhUQ0FMTCh3Z2xDaG9vc2VQaXhlbEZvcm1hdEFSQihoZGMsIChjb25zdCBpbnQqKSZhdHRyaWJzLCBOVUxMLCAxLCAmaVBpeGVsRm9ybWF0LCAmbkZvcm1hdHMpKSkKICAgICAgICB7CiAgICAgICAgICAgIC8qIFBpeGVsRm9ybWF0IHNlbGVjdGlvbiAqLwogICAgICAgICAgICBaZXJvTWVtb3J5KCZwZmQsIHNpemVvZihwZmQpKTsKICAgICAgICAgICAgcGZkLm5TaXplICAgICAgPSBzaXplb2YocGZkKTsKICAgICAgICAgICAgcGZkLm5WZXJzaW9uICAgPSAxOwogICAgICAgICAgICBwZmQuZHdGbGFncyAgICA9IFBGRF9TVVBQT1JUX09QRU5HTCB8IFBGRF9ET1VCTEVCVUZGRVIgfCBQRkRfRFJBV19UT19XSU5ET1c7LypQRkRfR0VORVJJQ19BQ0NFTEVSQVRFRCovCiAgICAgICAgICAgIHBmZC5pUGl4ZWxUeXBlID0gUEZEX1RZUEVfUkdCQTsKICAgICAgICAgICAgcGZkLmNBbHBoYUJpdHMgPSBhbHBoYUJpdHM7CiAgICAgICAgICAgIHBmZC5jQ29sb3JCaXRzID0gY29sb3JCaXRzOwogICAgICAgICAgICBwZmQuY0RlcHRoQml0cyA9IGRlcHRoQml0czsKICAgICAgICAgICAgcGZkLmNTdGVuY2lsQml0cyA9IHN0ZW5jaWxCaXRzOwogICAgICAgICAgICBwZmQuaUxheWVyVHlwZSA9IFBGRF9NQUlOX1BMQU5FOwoKICAgICAgICAgICAgaVBpeGVsRm9ybWF0ID0gQ2hvb3NlUGl4ZWxGb3JtYXQoaGRjLCAmcGZkKTsKICAgICAgICAgICAgaWYoIWlQaXhlbEZvcm1hdCkgewogICAgICAgICAgICAgICAgLyogSWYgdGhpcyBoYXBwZW5zIHNvbWV0aGluZyBpcyB2ZXJ5IHdyb25nIGFzIENob29zZVBpeGVsRm9ybWF0IGJhcmVseSBmYWlscyAqLwogICAgICAgICAgICAgICAgRVJSKCJDYW4ndCBmaW5kIGEgc3VpdGFibGUgaVBpeGVsRm9ybWF0XG4iKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgRGVzY3JpYmVQaXhlbEZvcm1hdChoZGMsIGlQaXhlbEZvcm1hdCwgc2l6ZW9mKHBmZCksICZwZmQpOwogICAgICAgIHJlcyA9IFNldFBpeGVsRm9ybWF0KGhkYywgaVBpeGVsRm9ybWF0LCBOVUxMKTsKICAgICAgICBpZighcmVzKSB7CiAgICAgICAgICAgIGludCBvbGRQaXhlbEZvcm1hdCA9IEdldFBpeGVsRm9ybWF0KGhkYyk7CgogICAgICAgICAgICBpZihvbGRQaXhlbEZvcm1hdCkgewogICAgICAgICAgICAgICAgLyogT3BlbkdMIGRvZXNuJ3QgYWxsb3cgcGl4ZWwgZm9ybWF0IGFkanVzdG1lbnRzLiBQcmludCBhbiBlcnJvciBhbmQgY29udGludWUgdXNpbmcgdGhlIG9sZCBmb3JtYXQuCiAgICAgICAgICAgICAgICAgKiBUaGVyZSdzIGEgYmlnIGNoYW5jZSB0aGF0IHRoZSBvbGQgZm9ybWF0IHdvcmtzIGFsdGhvdWdoIHdpdGggYSBwZXJmb3JtYW5jZSBoaXQgYW5kIHBlcmhhcHMgcmVuZGVyaW5nIGVycm9ycy4gKi8KICAgICAgICAgICAgICAgIEVSUigiSERDPSVwIGlzIGFscmVhZHkgc2V0IHRvIGlQaXhlbEZvcm1hdD0lZCBhbmQgT3BlbkdMIGRvZXNuJ3QgYWxsb3cgY2hhbmdlcyFcbiIsIGhkYywgb2xkUGl4ZWxGb3JtYXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgRVJSKCJTZXRQaXhlbEZvcm1hdCBmYWlsZWQgb24gSERDPSVwIGZvciBpUGl4ZWxGb3JtYXQ9JWRcbiIsIGhkYywgaVBpeGVsRm9ybWF0KTsKICAgICAgICAgICAgICAgIHJldHVybiBGQUxTRTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KI3VuZGVmIFBVU0gxCiN1bmRlZiBQVVNIMgoKICAgIGN0eCA9IHB3Z2xDcmVhdGVDb250ZXh0KGhkYyk7CiAgICBpZihUaGlzLT5udW1Db250ZXh0cykgcHdnbFNoYXJlTGlzdHMoVGhpcy0+Y29udGV4dHNbMF0tPmdsQ3R4LCBjdHgpOwoKICAgIGlmKCFjdHgpIHsKICAgICAgICBFUlIoIkZhaWxlZCB0byBjcmVhdGUgYSBXR0wgY29udGV4dFxuIik7CiAgICAgICAgaWYoY3JlYXRlX3BidWZmZXIpIHsKICAgICAgICAgICAgR0xfRVhUQ0FMTCh3Z2xSZWxlYXNlUGJ1ZmZlckRDQVJCKHBidWZmZXIsIGhkYykpOwogICAgICAgICAgICBHTF9FWFRDQUxMKHdnbERlc3Ryb3lQYnVmZmVyQVJCKHBidWZmZXIpKTsKICAgICAgICB9CiAgICAgICAgZ290byBvdXQ7CiAgICB9CiAgICByZXQgPSBBZGRDb250ZXh0VG9BcnJheShUaGlzLCB3aW5faGFuZGxlLCBoZGMsIGN0eCwgcGJ1ZmZlcik7CiAgICBpZighcmV0KSB7CiAgICAgICAgRVJSKCJGYWlsZWQgdG8gYWRkIHRoZSBuZXdseSBjcmVhdGVkIGNvbnRleHQgdG8gdGhlIGNvbnRleHQgbGlzdFxuIik7CiAgICAgICAgcHdnbERlbGV0ZUNvbnRleHQoY3R4KTsKICAgICAgICBpZihjcmVhdGVfcGJ1ZmZlcikgewogICAgICAgICAgICBHTF9FWFRDQUxMKHdnbFJlbGVhc2VQYnVmZmVyRENBUkIocGJ1ZmZlciwgaGRjKSk7CiAgICAgICAgICAgIEdMX0VYVENBTEwod2dsRGVzdHJveVBidWZmZXJBUkIocGJ1ZmZlcikpOwogICAgICAgIH0KICAgICAgICBnb3RvIG91dDsKICAgIH0KICAgIHJldC0+c3VyZmFjZSA9IChJV2luZUQzRFN1cmZhY2UgKikgdGFyZ2V0OwogICAgcmV0LT5pc1BCdWZmZXIgPSBjcmVhdGVfcGJ1ZmZlcjsKICAgIHJldC0+dGlkID0gR2V0Q3VycmVudFRocmVhZElkKCk7CgogICAgVFJBQ0UoIlN1Y2Nlc3NmdWxseSBjcmVhdGVkIG5ldyBjb250ZXh0ICVwXG4iLCByZXQpOwoKICAgIC8qIFNldCB1cCB0aGUgY29udGV4dCBkZWZhdWx0cyAqLwogICAgb2xkQ3R4ICA9IHB3Z2xHZXRDdXJyZW50Q29udGV4dCgpOwogICAgb2xkRHJhd2FibGUgPSBwd2dsR2V0Q3VycmVudERDKCk7CiAgICBpZihwd2dsTWFrZUN1cnJlbnQoaGRjLCBjdHgpID09IEZBTFNFKSB7CiAgICAgICAgRVJSKCJDYW5ub3QgYWN0aXZhdGUgY29udGV4dCB0byBzZXQgdXAgZGVmYXVsdHNcbiIpOwogICAgICAgIGdvdG8gb3V0OwogICAgfQoKICAgIEVOVEVSX0dMKCk7CiAgICBUUkFDRSgiU2V0dGluZyB1cCB0aGUgc2NyZWVuXG4iKTsKICAgIC8qIENsZWFyIHRoZSBzY3JlZW4gKi8KICAgIGdsQ2xlYXJDb2xvcigxLjAsIDAuMCwgMC4wLCAwLjApOwogICAgY2hlY2tHTGNhbGwoImdsQ2xlYXJDb2xvciIpOwogICAgZ2xDbGVhckluZGV4KDApOwogICAgZ2xDbGVhckRlcHRoKDEpOwogICAgZ2xDbGVhclN0ZW5jaWwoMHhmZmZmKTsKCiAgICBjaGVja0dMY2FsbCgiZ2xDbGVhciIpOwoKICAgIGdsQ29sb3IzZigxLjAsIDEuMCwgMS4wKTsKICAgIGNoZWNrR0xjYWxsKCJnbENvbG9yM2YiKTsKCiAgICBnbEVuYWJsZShHTF9MSUdIVElORyk7CiAgICBjaGVja0dMY2FsbCgiZ2xFbmFibGUiKTsKCiAgICBnbExpZ2h0TW9kZWxpKEdMX0xJR0hUX01PREVMX0xPQ0FMX1ZJRVdFUiwgR0xfVFJVRSk7CiAgICBjaGVja0dMY2FsbCgiZ2xMaWdodE1vZGVsaShHTF9MSUdIVF9NT0RFTF9MT0NBTF9WSUVXRVIsIEdMX1RSVUUpOyIpOwoKICAgIGdsVGV4RW52ZihHTF9URVhUVVJFX0VOViwgR0xfVEVYVFVSRV9FTlZfTU9ERSwgR0xfQ09NQklORV9FWFQpOwogICAgY2hlY2tHTGNhbGwoImdsVGV4RW52ZihHTF9URVhUVVJFX0VOViwgR0xfVEVYVFVSRV9FTlZfTU9ERSwgR0xfQ09NQklORV9FWFQpOyIpOwoKICAgIGdsTGlnaHRNb2RlbGkoR0xfTElHSFRfTU9ERUxfQ09MT1JfQ09OVFJPTCwgR0xfU0VQQVJBVEVfU1BFQ1VMQVJfQ09MT1IpOwogICAgY2hlY2tHTGNhbGwoImdsTGlnaHRNb2RlbGkoR0xfTElHSFRfTU9ERUxfQ09MT1JfQ09OVFJPTCwgR0xfU0VQQVJBVEVfU1BFQ1VMQVJfQ09MT1IpOyIpOwoKICAgIGdsUGl4ZWxTdG9yZWkoR0xfUEFDS19BTElHTk1FTlQsIFRoaXMtPnN1cmZhY2VfYWxpZ25tZW50KTsKICAgIGNoZWNrR0xjYWxsKCJnbFBpeGVsU3RvcmVpKEdMX1BBQ0tfQUxJR05NRU5ULCBUaGlzLT5zdXJmYWNlX2FsaWdubWVudCk7Iik7CiAgICBnbFBpeGVsU3RvcmVpKEdMX1VOUEFDS19BTElHTk1FTlQsIFRoaXMtPnN1cmZhY2VfYWxpZ25tZW50KTsKICAgIGNoZWNrR0xjYWxsKCJnbFBpeGVsU3RvcmVpKEdMX1VOUEFDS19BTElHTk1FTlQsIFRoaXMtPnN1cmZhY2VfYWxpZ25tZW50KTsiKTsKCiAgICBpZihHTF9TVVBQT1JUKEFQUExFX0NMSUVOVF9TVE9SQUdFKSkgewogICAgICAgIC8qIE1vc3QgdGV4dHVyZXMgd2lsbCB1c2UgY2xpZW50IHN0b3JhZ2UgaWYgc3VwcG9ydGVkLiBFeGNlcHRpb25zIGFyZSBub24tbmF0aXZlIHBvd2VyIG9mIDIgdGV4dHVyZXMKICAgICAgICAgKiBhbmQgdGV4dHVyZXMgaW4gRElCIHNlY3Rpb25zKGR1ZSB0byB0aGUgbWVtb3J5IHByb3RlY3Rpb24pLgogICAgICAgICAqLwogICAgICAgIGdsUGl4ZWxTdG9yZWkoR0xfVU5QQUNLX0NMSUVOVF9TVE9SQUdFX0FQUExFLCBHTF9UUlVFKTsKICAgICAgICBjaGVja0dMY2FsbCgiZ2xQaXhlbFN0b3JlaShHTF9VTlBBQ0tfQ0xJRU5UX1NUT1JBR0VfQVBQTEUsIEdMX1RSVUUpIik7CiAgICB9CiAgICBpZihHTF9TVVBQT1JUKEFSQl9WRVJURVhfQkxFTkQpKSB7CiAgICAgICAgLyogRGlyZWN0M0QgYWx3YXlzIHVzZXMgbi0xIHdlaWdodHMgZm9yIG4gd29ybGQgbWF0cmljZXMgYW5kIHVzZXMgMSAtIHN1bSBmb3IgdGhlIGxhc3Qgb25lCiAgICAgICAgICogdGhpcyBpcyBlcXVhbCB0byBHTF9XRUlHSFRfU1VNX1VOSVRZX0FSQi4gRW5hYmxpbmcgaXQgZG9lc24ndCBkbyBhbnl0aGluZyB1bmxlc3MKICAgICAgICAgKiBHTF9WRVJURVhfQkxFTkRfQVJCIGlzbid0IGVuYWJsZWQgdG9vCiAgICAgICAgICovCiAgICAgICAgZ2xFbmFibGUoR0xfV0VJR0hUX1NVTV9VTklUWV9BUkIpOwogICAgICAgIGNoZWNrR0xjYWxsKCJnbEVuYWJsZShHTF9XRUlHSFRfU1VNX1VOSVRZX0FSQikiKTsKICAgIH0KICAgIGlmKEdMX1NVUFBPUlQoTlZfVEVYVFVSRV9TSEFERVIyKSkgewogICAgICAgIGdsRW5hYmxlKEdMX1RFWFRVUkVfU0hBREVSX05WKTsKICAgICAgICBjaGVja0dMY2FsbCgiZ2xFbmFibGUoR0xfVEVYVFVSRV9TSEFERVJfTlYpIik7CgogICAgICAgIC8qIFNldCB1cCB0aGUgcHJldmlvdXMgdGV4dHVyZSBpbnB1dCBmb3IgYWxsIHNoYWRlciB1bml0cy4gVGhpcyBhcHBsaWVzIHRvIGJ1bXAgbWFwcGluZywgYW5kIGluIGQzZAogICAgICAgICAqIHRoZSBwcmV2aW91cyB0ZXh0dXJlIHdoZXJlIHRvIHNvdXJjZSB0aGUgb2Zmc2V0IGZyb20gaXMgYWx3YXlzIHVuaXQgLSAxLgogICAgICAgICAqLwogICAgICAgIGZvcihzID0gMTsgcyA8IEdMX0xJTUlUUyh0ZXh0dXJlcyk7IHMrKykgewogICAgICAgICAgICBHTF9FWFRDQUxMKGdsQWN0aXZlVGV4dHVyZUFSQihHTF9URVhUVVJFMF9BUkIgKyBzKSk7CiAgICAgICAgICAgIGdsVGV4RW52aShHTF9URVhUVVJFX1NIQURFUl9OViwgR0xfUFJFVklPVVNfVEVYVFVSRV9JTlBVVF9OViwgR0xfVEVYVFVSRTBfQVJCICsgcyAtIDEpOwogICAgICAgICAgICBjaGVja0dMY2FsbCgiZ2xUZXhFbnZpKEdMX1RFWFRVUkVfU0hBREVSX05WLCBHTF9QUkVWSU9VU19URVhUVVJFX0lOUFVUX05WLCAuLi5cbiIpOwogICAgICAgIH0KICAgIH0KICAgIGlmKEdMX1NVUFBPUlQoQVJCX1BPSU5UX1NQUklURSkpIHsKICAgICAgICBmb3IocyA9IDA7IHMgPCBHTF9MSU1JVFModGV4dHVyZXMpOyBzKyspIHsKICAgICAgICAgICAgR0xfRVhUQ0FMTChnbEFjdGl2ZVRleHR1cmVBUkIoR0xfVEVYVFVSRTBfQVJCICsgcykpOwogICAgICAgICAgICBnbFRleEVudmkoR0xfUE9JTlRfU1BSSVRFX0FSQiwgR0xfQ09PUkRfUkVQTEFDRV9BUkIsIEdMX1RSVUUpOwogICAgICAgICAgICBjaGVja0dMY2FsbCgiZ2xUZXhFbnZpKEdMX1BPSU5UX1NQUklURV9BUkIsIEdMX0NPT1JEX1JFUExBQ0VfQVJCLCBHTF9UUlVFKVxuIik7CiAgICAgICAgfQogICAgfQogICAgTEVBVkVfR0woKTsKCiAgICBpZihvbGREcmF3YWJsZSAmJiBvbGRDdHgpIHsKICAgICAgICBwd2dsTWFrZUN1cnJlbnQob2xkRHJhd2FibGUsIG9sZEN0eCk7CiAgICB9CgpvdXQ6CiAgICByZXR1cm4gcmV0Owp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogUmVtb3ZlQ29udGV4dEZyb21BcnJheQogKgogKiBSZW1vdmVzIGEgY29udGV4dCBmcm9tIHRoZSBjb250ZXh0IG1hbmFnZXIuIFRoZSBvcGVuZ2wgY29udGV4dCBpcyBub3QKICogZGVzdHJveWVkIG9yIHVuc2V0LiBjb250ZXh0IGlzIG5vdCBhIHZhbGlkIHBvaW50ZXIgYWZ0ZXIgdGhhdCBjYWxsLgogKgogKiBTaW1pbGFyIHRvIHRoZSBmb3JtZXIgY2FsbCB0aGlzIGlzbid0IGEgcGVyZm9ybWFuY2UgY3JpdGljYWwgZnVuY3Rpb24uIEEKICogaGVscGVyIGZ1bmN0aW9uIGZvciBEZXN0cm95Q29udGV4dC4KICoKICogUGFyYW1zOgogKiAgVGhpczogRGV2aWNlIHRvIGFjdGl2YXRlIHRoZSBjb250ZXh0IGZvcgogKiAgY29udGV4dDogQ29udGV4dCB0byByZW1vdmUKICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpzdGF0aWMgdm9pZCBSZW1vdmVDb250ZXh0RnJvbUFycmF5KElXaW5lRDNERGV2aWNlSW1wbCAqVGhpcywgV2luZUQzRENvbnRleHQgKmNvbnRleHQpIHsKICAgIFVJTlQgdCwgczsKICAgIFdpbmVEM0RDb250ZXh0ICoqb2xkQXJyYXkgPSBUaGlzLT5jb250ZXh0czsKCiAgICBUUkFDRSgiUmVtb3ZpbmcgY3R4ICVwXG4iLCBjb250ZXh0KTsKCiAgICBUaGlzLT5udW1Db250ZXh0cy0tOwoKICAgIGlmKFRoaXMtPm51bUNvbnRleHRzKSB7CiAgICAgICAgVGhpcy0+Y29udGV4dHMgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgc2l6ZW9mKCpUaGlzLT5jb250ZXh0cykgKiBUaGlzLT5udW1Db250ZXh0cyk7CiAgICAgICAgaWYoIVRoaXMtPmNvbnRleHRzKSB7CiAgICAgICAgICAgIEVSUigiQ2Fubm90IGFsbG9jYXRlIGEgbmV3IGNvbnRleHQgYXJyYXksIFBBTklDISEhXG4iKTsKICAgICAgICB9CiAgICAgICAgdCA9IDA7CiAgICAgICAgZm9yKHMgPSAwOyBzIDwgVGhpcy0+bnVtQ29udGV4dHM7IHMrKykgewogICAgICAgICAgICBpZihvbGRBcnJheVtzXSA9PSBjb250ZXh0KSBjb250aW51ZTsKICAgICAgICAgICAgVGhpcy0+Y29udGV4dHNbdF0gPSBvbGRBcnJheVtzXTsKICAgICAgICAgICAgdCsrOwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgVGhpcy0+Y29udGV4dHMgPSBOVUxMOwogICAgfQoKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIGNvbnRleHQpOwogICAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgb2xkQXJyYXkpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogRGVzdHJveUNvbnRleHQKICoKICogRGVzdHJveXMgYSB3aW5lRDNEQ29udGV4dAogKgogKiBQYXJhbXM6CiAqICBUaGlzOiBEZXZpY2UgdG8gYWN0aXZhdGUgdGhlIGNvbnRleHQgZm9yCiAqICBjb250ZXh0OiBDb250ZXh0IHRvIGRlc3Ryb3kKICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwp2b2lkIERlc3Ryb3lDb250ZXh0KElXaW5lRDNERGV2aWNlSW1wbCAqVGhpcywgV2luZUQzRENvbnRleHQgKmNvbnRleHQpIHsKCiAgICAvKiBjaGVjayB0aGF0IHdlIGFyZSB0aGUgY3VycmVudCBjb250ZXh0IGZpcnN0ICovCiAgICBUUkFDRSgiRGVzdHJveWluZyBjdHggJXBcbiIsIGNvbnRleHQpOwogICAgaWYocHdnbEdldEN1cnJlbnRDb250ZXh0KCkgPT0gY29udGV4dC0+Z2xDdHgpewogICAgICAgIHB3Z2xNYWtlQ3VycmVudChOVUxMLCBOVUxMKTsKICAgIH0KCiAgICBpZihjb250ZXh0LT5pc1BCdWZmZXIpIHsKICAgICAgICBHTF9FWFRDQUxMKHdnbFJlbGVhc2VQYnVmZmVyRENBUkIoY29udGV4dC0+cGJ1ZmZlciwgY29udGV4dC0+aGRjKSk7CiAgICAgICAgR0xfRVhUQ0FMTCh3Z2xEZXN0cm95UGJ1ZmZlckFSQihjb250ZXh0LT5wYnVmZmVyKSk7CiAgICB9IGVsc2UgUmVsZWFzZURDKGNvbnRleHQtPndpbl9oYW5kbGUsIGNvbnRleHQtPmhkYyk7CiAgICBwd2dsRGVsZXRlQ29udGV4dChjb250ZXh0LT5nbEN0eCk7CgogICAgUmVtb3ZlQ29udGV4dEZyb21BcnJheShUaGlzLCBjb250ZXh0KTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqIFNldHVwRm9yQmxpdAogKgogKiBTZXRzIHVwIGEgY29udGV4dCBmb3IgRGlyZWN0RHJhdyBibGl0dGluZy4KICogQWxsIHRleHR1cmUgdW5pdHMgYXJlIGRpc2FibGVkLCB0ZXh0dXJlIHVuaXQgMCBpcyBzZXQgYXMgY3VycmVudCB1bml0CiAqIGZvZywgbGlnaHRpbmcsIGJsZW5kaW5nLCBhbHBoYSB0ZXN0LCB6IHRlc3QsIHNjaXNzb3IgdGVzdCwgY3VsbGluZyBkaWFibGVkCiAqIGNvbG9yIHdyaXRpbmcgZW5hYmxlZCBmb3IgYWxsIGNoYW5uZWxzCiAqIHJlZ2lzdGVyIGNvbWJpbmVycyBkaXNhYmxlZCwgc2hhZGVycyBkaXNhYmxlZAogKiB3b3JsZCBtYXRyaXMgaXMgc2V0IHRvIGlkZW50aXR5LCB0ZXh0dXJlIG1hdHJpeCAwIHRvbwogKiBwcm9qZWN0aW9uIG1hdHJpeCBpcyBzZXR1cCBmb3IgZHJhd2luZyBzY3JlZW4gY29vcmRpbmF0ZXMKICoKICogUGFyYW1zOgogKiAgVGhpczogRGV2aWNlIHRvIGFjdGl2YXRlIHRoZSBjb250ZXh0IGZvcgogKiAgY29udGV4dDogQ29udGV4dCB0byBzZXR1cAogKiAgd2lkdGg6IHJlbmRlciB0YXJnZXQgd2lkdGgKICogIGhlaWdodDogcmVuZGVyIHRhcmdldCBoZWlnaHQKICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpzdGF0aWMgaW5saW5lIHZvaWQgU2V0dXBGb3JCbGl0KElXaW5lRDNERGV2aWNlSW1wbCAqVGhpcywgV2luZUQzRENvbnRleHQgKmNvbnRleHQsIFVJTlQgd2lkdGgsIFVJTlQgaGVpZ2h0KSB7CiAgICBpbnQgaTsKCiAgICBUUkFDRSgiU2V0dGluZyB1cCBjb250ZXh0ICVwIGZvciBibGl0dGluZ1xuIiwgY29udGV4dCk7CiAgICBpZihjb250ZXh0LT5sYXN0X3dhc19ibGl0KSB7CiAgICAgICAgVFJBQ0UoIkNvbnRleHQgaXMgYWxyZWFkeSBzZXQgdXAgZm9yIGJsaXR0aW5nLCBub3RoaW5nIHRvIGRvXG4iKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBjb250ZXh0LT5sYXN0X3dhc19ibGl0ID0gVFJVRTsKCiAgICAvKiBUT0RPOiBVc2UgYSBkaXNwbGF5IGxpc3QgKi8KCiAgICAvKiBEaXNhYmxlIHNoYWRlcnMgKi8KICAgIFRoaXMtPnNoYWRlcl9iYWNrZW5kLT5zaGFkZXJfY2xlYW51cCgoSVdpbmVEM0REZXZpY2UgKikgVGhpcyk7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1ZTSEFERVIpOwogICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9QSVhFTFNIQURFUik7CgogICAgLyogRGlzYWJsZSBhbGwgdGV4dHVyZXMuIFRoZSBjYWxsZXIgY2FuIHRoZW4gYmluZCBhIHRleHR1cmUgaXQgd2FudHMgdG8gYmxpdAogICAgICogZnJvbQogICAgICovCiAgICBpZihHTF9TVVBQT1JUKE5WX1JFR0lTVEVSX0NPTUJJTkVSUykpIHsKICAgICAgICBnbERpc2FibGUoR0xfUkVHSVNURVJfQ09NQklORVJTX05WKTsKICAgICAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlKEdMX1JFR0lTVEVSX0NPTUJJTkVSU19OVikiKTsKICAgIH0KICAgIGlmIChHTF9TVVBQT1JUKEFSQl9NVUxUSVRFWFRVUkUpKSB7CiAgICAgICAgLyogVGhlIGJsaXR0aW5nIGNvZGUgdXNlcyAoZm9yIG5vdykgdGhlIGZpeGVkIGZ1bmN0aW9uIHBpcGVsaW5lLCBzbyBtYWtlIHN1cmUgdG8gcmVzZXQgYWxsIGZpeGVkCiAgICAgICAgICogZnVuY3Rpb24gdGV4dHVyZSB1bml0LiBObyBuZWVkIHRvIGNhcmUgZm9yIGhpZ2hlciBzYW1wbGVycwogICAgICAgICAqLwogICAgICAgIGZvcihpID0gR0xfTElNSVRTKHRleHR1cmVzKSAtIDE7IGkgPiAwIDsgaS0tKSB7CiAgICAgICAgICAgIEdMX0VYVENBTEwoZ2xBY3RpdmVUZXh0dXJlQVJCKEdMX1RFWFRVUkUwX0FSQiArIGkpKTsKICAgICAgICAgICAgY2hlY2tHTGNhbGwoImdsQWN0aXZlVGV4dHVyZUFSQiIpOwoKICAgICAgICAgICAgaWYoR0xfU1VQUE9SVChBUkJfVEVYVFVSRV9DVUJFX01BUCkpIHsKICAgICAgICAgICAgICAgIGdsRGlzYWJsZShHTF9URVhUVVJFX0NVQkVfTUFQX0FSQik7CiAgICAgICAgICAgICAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX1RFWFRVUkVfQ1VCRV9NQVBfQVJCIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZ2xEaXNhYmxlKEdMX1RFWFRVUkVfM0QpOwogICAgICAgICAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX1RFWFRVUkVfM0QiKTsKICAgICAgICAgICAgZ2xEaXNhYmxlKEdMX1RFWFRVUkVfMkQpOwogICAgICAgICAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX1RFWFRVUkVfMkQiKTsKCiAgICAgICAgICAgIGdsVGV4RW52aShHTF9URVhUVVJFX0VOViwgR0xfVEVYVFVSRV9FTlZfTU9ERSwgR0xfUkVQTEFDRSk7CiAgICAgICAgICAgIGNoZWNrR0xjYWxsKCJnbFRleEVudmkoR0xfVEVYVFVSRV9FTlYsIEdMX1RFWFRVUkVfRU5WX01PREUsIEdMX1JFUExBQ0UpOyIpOwoKICAgICAgICAgICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9URVhUVVJFU1RBR0UoaSwgV0lORUQzRFRTU19DT0xPUk9QKSk7CiAgICAgICAgICAgIENvbnRleHRfTWFya1N0YXRlRGlydHkoY29udGV4dCwgU1RBVEVfU0FNUExFUihpKSk7CiAgICAgICAgfQogICAgICAgIEdMX0VYVENBTEwoZ2xBY3RpdmVUZXh0dXJlQVJCKEdMX1RFWFRVUkUwX0FSQikpOwogICAgICAgIGNoZWNrR0xjYWxsKCJnbEFjdGl2ZVRleHR1cmVBUkIiKTsKICAgIH0KICAgIGlmKEdMX1NVUFBPUlQoQVJCX1RFWFRVUkVfQ1VCRV9NQVApKSB7CiAgICAgICAgZ2xEaXNhYmxlKEdMX1RFWFRVUkVfQ1VCRV9NQVBfQVJCKTsKICAgICAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX1RFWFRVUkVfQ1VCRV9NQVBfQVJCIik7CiAgICB9CiAgICBnbERpc2FibGUoR0xfVEVYVFVSRV8zRCk7CiAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX1RFWFRVUkVfM0QiKTsKICAgIGdsRGlzYWJsZShHTF9URVhUVVJFXzJEKTsKICAgIGNoZWNrR0xjYWxsKCJnbERpc2FibGUgR0xfVEVYVFVSRV8yRCIpOwoKICAgIGdsVGV4RW52aShHTF9URVhUVVJFX0VOViwgR0xfVEVYVFVSRV9FTlZfTU9ERSwgR0xfUkVQTEFDRSk7CgogICAgZ2xNYXRyaXhNb2RlKEdMX1RFWFRVUkUpOwogICAgY2hlY2tHTGNhbGwoImdsTWF0cml4TW9kZShHTF9URVhUVVJFKSIpOwogICAgZ2xMb2FkSWRlbnRpdHkoKTsKICAgIGNoZWNrR0xjYWxsKCJnbExvYWRJZGVudGl0eSgpIik7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1RSQU5TRk9STShXSU5FRDNEVFNfVEVYVFVSRTApKTsKCiAgICBpZiAoR0xfU1VQUE9SVChFWFRfVEVYVFVSRV9MT0RfQklBUykpIHsKICAgICAgICBnbFRleEVudmYoR0xfVEVYVFVSRV9GSUxURVJfQ09OVFJPTF9FWFQsCiAgICAgICAgICAgICAgICAgIEdMX1RFWFRVUkVfTE9EX0JJQVNfRVhULAogICAgICAgICAgICAgICAgICAwLjApOwogICAgICAgIGNoZWNrR0xjYWxsKCJnbFRleEVudmkgR0xfVEVYVFVSRV9MT0RfQklBU19FWFQgLi4uIik7CiAgICB9CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1NBTVBMRVIoMCkpOwogICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9URVhUVVJFU1RBR0UoMCwgV0lORUQzRFRTU19DT0xPUk9QKSk7CgogICAgLyogT3RoZXIgbWlzYyBzdGF0ZXMgKi8KICAgIGdsRGlzYWJsZShHTF9BTFBIQV9URVNUKTsKICAgIGNoZWNrR0xjYWxsKCJnbERpc2FibGUoR0xfQUxQSEFfVEVTVCkiKTsKICAgIENvbnRleHRfTWFya1N0YXRlRGlydHkoY29udGV4dCwgU1RBVEVfUkVOREVSKFdJTkVEM0RSU19BTFBIQVRFU1RFTkFCTEUpKTsKICAgIGdsRGlzYWJsZShHTF9MSUdIVElORyk7CiAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX0xJR0hUSU5HIik7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1JFTkRFUihXSU5FRDNEUlNfTElHSFRJTkcpKTsKICAgIGdsRGlzYWJsZShHTF9ERVBUSF9URVNUKTsKICAgIGNoZWNrR0xjYWxsKCJnbERpc2FibGUgR0xfREVQVEhfVEVTVCIpOwogICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9SRU5ERVIoV0lORUQzRFJTX1pFTkFCTEUpKTsKICAgIGdsRGlzYWJsZShHTF9GT0cpOwogICAgY2hlY2tHTGNhbGwoImdsRGlzYWJsZSBHTF9GT0ciKTsKICAgIENvbnRleHRfTWFya1N0YXRlRGlydHkoY29udGV4dCwgU1RBVEVfUkVOREVSKFdJTkVEM0RSU19GT0dFTkFCTEUpKTsKICAgIGdsRGlzYWJsZShHTF9CTEVORCk7CiAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX0JMRU5EIik7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1JFTkRFUihXSU5FRDNEUlNfQUxQSEFCTEVOREVOQUJMRSkpOwogICAgZ2xEaXNhYmxlKEdMX0NVTExfRkFDRSk7CiAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX0NVTExfRkFDRSIpOwogICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9SRU5ERVIoV0lORUQzRFJTX0NVTExNT0RFKSk7CiAgICBnbERpc2FibGUoR0xfU1RFTkNJTF9URVNUKTsKICAgIGNoZWNrR0xjYWxsKCJnbERpc2FibGUgR0xfU1RFTkNJTF9URVNUIik7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1JFTkRFUihXSU5FRDNEUlNfU1RFTkNJTEVOQUJMRSkpOwogICAgZ2xEaXNhYmxlKEdMX1NDSVNTT1JfVEVTVCk7CiAgICBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlIEdMX1NDSVNTT1JfVEVTVCIpOwogICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9SRU5ERVIoV0lORUQzRFJTX1NDSVNTT1JURVNURU5BQkxFKSk7CiAgICBpZihHTF9TVVBQT1JUKEFSQl9QT0lOVF9TUFJJVEUpKSB7CiAgICAgICAgZ2xEaXNhYmxlKEdMX1BPSU5UX1NQUklURV9BUkIpOwogICAgICAgIGNoZWNrR0xjYWxsKCJnbERpc2FibGUgR0xfUE9JTlRfU1BSSVRFX0FSQiIpOwogICAgICAgIENvbnRleHRfTWFya1N0YXRlRGlydHkoY29udGV4dCwgU1RBVEVfUkVOREVSKFdJTkVEM0RSU19QT0lOVFNQUklURUVOQUJMRSkpOwogICAgfQogICAgZ2xDb2xvck1hc2soR0xfVFJVRSwgR0xfVFJVRSxHTF9UUlVFLEdMX1RSVUUpOwogICAgY2hlY2tHTGNhbGwoImdsQ29sb3JNYXNrIik7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1JFTkRFUihXSU5FRDNEUlNfQ0xJUFBJTkcpKTsKICAgIGlmIChHTF9TVVBQT1JUKEVYVF9TRUNPTkRBUllfQ09MT1IpKSB7CiAgICAgICAgZ2xEaXNhYmxlKEdMX0NPTE9SX1NVTV9FWFQpOwogICAgICAgIENvbnRleHRfTWFya1N0YXRlRGlydHkoY29udGV4dCwgU1RBVEVfUkVOREVSKFdJTkVEM0RSU19TUEVDVUxBUkVOQUJMRSkpOwogICAgICAgIGNoZWNrR0xjYWxsKCJnbERpc2FibGUoR0xfQ09MT1JfU1VNX0VYVCkiKTsKICAgIH0KICAgIGlmIChHTF9TVVBQT1JUKE5WX1JFR0lTVEVSX0NPTUJJTkVSUykpIHsKICAgICAgICBHTF9FWFRDQUxMKGdsRmluYWxDb21iaW5lcklucHV0TlYoR0xfVkFSSUFCTEVfQl9OViwgR0xfU1BBUkUwX05WLCBHTF9VTlNJR05FRF9JREVOVElUWV9OViwgR0xfUkdCKSk7CiAgICAgICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9SRU5ERVIoV0lORUQzRFJTX1NQRUNVTEFSRU5BQkxFKSk7CiAgICAgICAgY2hlY2tHTGNhbGwoImdsRmluYWxDb21iaW5lcklucHV0TlYiKTsKICAgIH0KCiAgICAvKiBTZXR1cCB0cmFuc2Zvcm1zICovCiAgICBnbE1hdHJpeE1vZGUoR0xfTU9ERUxWSUVXKTsKICAgIGNoZWNrR0xjYWxsKCJnbE1hdHJpeE1vZGUoR0xfTU9ERUxWSUVXKSIpOwogICAgZ2xMb2FkSWRlbnRpdHkoKTsKICAgIGNoZWNrR0xjYWxsKCJnbExvYWRJZGVudGl0eSgpIik7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1RSQU5TRk9STShXSU5FRDNEVFNfV09STERNQVRSSVgoMCkpKTsKCiAgICBnbE1hdHJpeE1vZGUoR0xfUFJPSkVDVElPTik7CiAgICBjaGVja0dMY2FsbCgiZ2xNYXRyaXhNb2RlKEdMX1BST0pFQ1RJT04pIik7CiAgICBnbExvYWRJZGVudGl0eSgpOwogICAgY2hlY2tHTGNhbGwoImdsTG9hZElkZW50aXR5KCkiKTsKICAgIGdsT3J0aG8oMCwgd2lkdGgsIGhlaWdodCwgMCwgMC4wLCAtMS4wKTsKICAgIGNoZWNrR0xjYWxsKCJnbE9ydGhvIik7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1RSQU5TRk9STShXSU5FRDNEVFNfUFJPSkVDVElPTikpOwoKICAgIGNvbnRleHQtPmxhc3Rfd2FzX3JodyA9IFRSVUU7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1ZERUNMKTsgLyogYmVjYXVzZSBvZiBsYXN0X3dhc19yaHcgPSBUUlVFICovCgogICAgZ2xEaXNhYmxlKEdMX0NMSVBfUExBTkUwKTsgY2hlY2tHTGNhbGwoImdsRGlzYWJsZShjbGlwIHBsYW5lIDApIik7CiAgICBnbERpc2FibGUoR0xfQ0xJUF9QTEFORTEpOyBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlKGNsaXAgcGxhbmUgMSkiKTsKICAgIGdsRGlzYWJsZShHTF9DTElQX1BMQU5FMik7IGNoZWNrR0xjYWxsKCJnbERpc2FibGUoY2xpcCBwbGFuZSAyKSIpOwogICAgZ2xEaXNhYmxlKEdMX0NMSVBfUExBTkUzKTsgY2hlY2tHTGNhbGwoImdsRGlzYWJsZShjbGlwIHBsYW5lIDMpIik7CiAgICBnbERpc2FibGUoR0xfQ0xJUF9QTEFORTQpOyBjaGVja0dMY2FsbCgiZ2xEaXNhYmxlKGNsaXAgcGxhbmUgNCkiKTsKICAgIGdsRGlzYWJsZShHTF9DTElQX1BMQU5FNSk7IGNoZWNrR0xjYWxsKCJnbERpc2FibGUoY2xpcCBwbGFuZSA1KSIpOwogICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9SRU5ERVIoV0lORUQzRFJTX0NMSVBQSU5HKSk7CgogICAgZ2xWaWV3cG9ydCgwLCAwLCB3aWR0aCwgaGVpZ2h0KTsKICAgIGNoZWNrR0xjYWxsKCJnbFZpZXdwb3J0Iik7CiAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1ZJRVdQT1JUKTsKCiAgICBpZihHTF9TVVBQT1JUKE5WX1RFWFRVUkVfU0hBREVSMikpIHsKICAgICAgICBnbERpc2FibGUoR0xfVEVYVFVSRV9TSEFERVJfTlYpOwogICAgICAgIGNoZWNrR0xjYWxsKCJnbERpc2FibGUoR0xfVEVYVFVSRV9TSEFERVJfTlYpIik7CiAgICB9Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiBmaW5kVGhyZWFkQ29udGV4dEZvclN3YXBDaGFpbgogKgogKiBTZWFyY2hlcyBhIHN3YXBjaGFpbiBmb3IgYWxsIGNvbnRleHRzIGFuZCBwaWNrcyBvbmUgZm9yIHRoZSB0aHJlYWQgdGlkLgogKiBJZiBub25lIGNhbiBiZSBmb3VuZCB0aGUgc3dhcGNoYWluIGlzIHJlcXVlc3RlZCB0byBjcmVhdGUgYSBuZXcgY29udGV4dAogKgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCnN0YXRpYyBXaW5lRDNEQ29udGV4dCAqZmluZFRocmVhZENvbnRleHRGb3JTd2FwQ2hhaW4oSVdpbmVEM0RTd2FwQ2hhaW4gKnN3YXBjaGFpbiwgRFdPUkQgdGlkKSB7CiAgICBpbnQgaTsKCiAgICBmb3IoaSA9IDA7IGkgPCAoKElXaW5lRDNEU3dhcENoYWluSW1wbCAqKSBzd2FwY2hhaW4pLT5udW1fY29udGV4dHM7IGkrKykgewogICAgICAgIGlmKCgoSVdpbmVEM0RTd2FwQ2hhaW5JbXBsICopIHN3YXBjaGFpbiktPmNvbnRleHRbaV0tPnRpZCA9PSB0aWQpIHsKICAgICAgICAgICAgcmV0dXJuICgoSVdpbmVEM0RTd2FwQ2hhaW5JbXBsICopIHN3YXBjaGFpbiktPmNvbnRleHRbaV07CiAgICAgICAgfQoKICAgIH0KCiAgICAvKiBDcmVhdGUgYSBuZXcgY29udGV4dCBmb3IgdGhlIHRocmVhZCAqLwogICAgcmV0dXJuIElXaW5lRDNEU3dhcENoYWluSW1wbF9DcmVhdGVDb250ZXh0Rm9yVGhyZWFkKHN3YXBjaGFpbik7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiBGaW5kQ29udGV4dAogKgogKiBGaW5kcyBhIGNvbnRleHQgZm9yIHRoZSBjdXJyZW50IHJlbmRlciB0YXJnZXQgYW5kIHRocmVhZAogKgogKiBQYXJhbWV0ZXJzOgogKiAgdGFyZ2V0OiBSZW5kZXIgdGFyZ2V0IHRvIGZpbmQgdGhlIGNvbnRleHQgZm9yCiAqICB0aWQ6IFRocmVhZCB0byBhY3RpdmF0ZSB0aGUgY29udGV4dCBmb3IKICoKICogUmV0dXJuczogVGhlIG5lZWRlZCBjb250ZXh0CiAqCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8Kc3RhdGljIGlubGluZSBXaW5lRDNEQ29udGV4dCAqRmluZENvbnRleHQoSVdpbmVEM0REZXZpY2VJbXBsICpUaGlzLCBJV2luZUQzRFN1cmZhY2UgKnRhcmdldCwgRFdPUkQgdGlkLCBHTGludCAqYnVmZmVyKSB7CiAgICBJV2luZUQzRFN3YXBDaGFpbiAqc3dhcGNoYWluID0gTlVMTDsKICAgIEhSRVNVTFQgaHI7CiAgICBCT09MIHJlYWRUZXh0dXJlID0gd2luZWQzZF9zZXR0aW5ncy5vZmZzY3JlZW5fcmVuZGVyaW5nX21vZGUgIT0gT1JNX0ZCTyAmJiBUaGlzLT5yZW5kZXJfb2Zmc2NyZWVuOwogICAgV2luZUQzRENvbnRleHQgKmNvbnRleHQgPSBUaGlzLT5hY3RpdmVDb250ZXh0OwogICAgQk9PTCBvbGRSZW5kZXJPZmZzY3JlZW4gPSBUaGlzLT5yZW5kZXJfb2Zmc2NyZWVuOwogICAgY29uc3QgV0lORUQzREZPUk1BVCBvbGRGbXQgPSAoKElXaW5lRDNEU3VyZmFjZUltcGwgKikgVGhpcy0+bGFzdEFjdGl2ZVJlbmRlclRhcmdldCktPnJlc291cmNlLmZvcm1hdDsKICAgIGNvbnN0IFdJTkVEM0RGT1JNQVQgbmV3Rm10ID0gKChJV2luZUQzRFN1cmZhY2VJbXBsICopIHRhcmdldCktPnJlc291cmNlLmZvcm1hdDsKCiAgICAvKiBUbyBjb21wZW5zYXRlIHRoZSBsYWNrIG9mIGZvcm1hdCBzd2l0Y2hpbmcgd2l0aCBzb21lIG9mZnNjcmVlbiByZW5kZXJpbmcgbWV0aG9kcyBhbmQgb24gb25zY3JlZW4gYnVmZmVycwogICAgICogdGhlIGFscGhhIGJsZW5kIHN0YXRlIGNoYW5nZXMgd2l0aCBkaWZmZXJlbnQgcmVuZGVyIHRhcmdldCBmb3JtYXRzCiAgICAgKi8KICAgIGlmKG9sZEZtdCAhPSBuZXdGbXQpIHsKICAgICAgICBjb25zdCBTdGF0aWNQaXhlbEZvcm1hdERlc2MgKm9sZCA9IGdldEZvcm1hdERlc2NFbnRyeShvbGRGbXQsIE5VTEwsIE5VTEwpOwogICAgICAgIGNvbnN0IFN0YXRpY1BpeGVsRm9ybWF0RGVzYyAqbmV3ID0gZ2V0Rm9ybWF0RGVzY0VudHJ5KG9sZEZtdCwgTlVMTCwgTlVMTCk7CgogICAgICAgIGlmKChvbGQtPmFscGhhTWFzayAmJiAhbmV3LT5hbHBoYU1hc2spIHx8ICghb2xkLT5hbHBoYU1hc2sgJiYgbmV3LT5hbHBoYU1hc2spKSB7CiAgICAgICAgICAgIENvbnRleHRfTWFya1N0YXRlRGlydHkoY29udGV4dCwgU1RBVEVfUkVOREVSKFdJTkVEM0RSU19BTFBIQUJMRU5ERU5BQkxFKSk7CiAgICAgICAgfQogICAgfQoKICAgIGhyID0gSVdpbmVEM0RTdXJmYWNlX0dldENvbnRhaW5lcih0YXJnZXQsICZJSURfSVdpbmVEM0RTd2FwQ2hhaW4sICh2b2lkICoqKSAmc3dhcGNoYWluKTsKICAgIGlmKGhyID09IFdJTkVEM0RfT0sgJiYgc3dhcGNoYWluKSB7CiAgICAgICAgVFJBQ0UoIlJlbmRlcmluZyBvbnNjcmVlblxuIik7CgogICAgICAgIGNvbnRleHQgPSBmaW5kVGhyZWFkQ29udGV4dEZvclN3YXBDaGFpbihzd2FwY2hhaW4sIHRpZCk7CgogICAgICAgIFRoaXMtPnJlbmRlcl9vZmZzY3JlZW4gPSBGQUxTRTsKICAgICAgICAvKiBUaGUgY29udGV4dCAhPSBUaGlzLT5hY3RpdmVDb250ZXh0IHdpbGwgY2F0Y2ggYSBOT1AgY29udGV4dCBjaGFuZ2UuIFRoaXMgY2FuIG9jY3VyCiAgICAgICAgICogaWYgd2UgYXJlIHN3aXRjaGluZyBiYWNrIHRvIHN3YXBjaGFpbiByZW5kZXJpbmcgaW4gY2FzZSBvZiBGQk8gb3IgQmFjayBCdWZmZXIgb2Zmc2NyZWVuCiAgICAgICAgICogcmVuZGVyaW5nLiBObyBjb250ZXh0IGNoYW5nZSBpcyBuZWVkZWQgaW4gdGhhdCBjYXNlCiAgICAgICAgICovCgogICAgICAgIGlmKCgoSVdpbmVEM0RTd2FwQ2hhaW5JbXBsICopIHN3YXBjaGFpbiktPmZyb250QnVmZmVyID09IHRhcmdldCkgewogICAgICAgICAgICAqYnVmZmVyID0gR0xfRlJPTlQ7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgKmJ1ZmZlciA9IEdMX0JBQ0s7CiAgICAgICAgfQogICAgICAgIGlmKHdpbmVkM2Rfc2V0dGluZ3Mub2Zmc2NyZWVuX3JlbmRlcmluZ19tb2RlID09IE9STV9QQlVGRkVSKSB7CiAgICAgICAgICAgIGlmKFRoaXMtPnBidWZmZXJDb250ZXh0ICYmIHRpZCA9PSBUaGlzLT5wYnVmZmVyQ29udGV4dC0+dGlkKSB7CiAgICAgICAgICAgICAgICBUaGlzLT5wYnVmZmVyQ29udGV4dC0+dGlkID0gMDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBJV2luZUQzRFN3YXBDaGFpbl9SZWxlYXNlKHN3YXBjaGFpbik7CgogICAgICAgIGlmKG9sZFJlbmRlck9mZnNjcmVlbikgewogICAgICAgICAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFdJTkVEM0RUU19QUk9KRUNUSU9OKTsKICAgICAgICAgICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9WREVDTCk7CiAgICAgICAgICAgIENvbnRleHRfTWFya1N0YXRlRGlydHkoY29udGV4dCwgU1RBVEVfVklFV1BPUlQpOwogICAgICAgICAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1NDSVNTT1JSRUNUKTsKICAgICAgICAgICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9GUk9OVEZBQ0UpOwogICAgICAgIH0KCiAgICB9IGVsc2UgewogICAgICAgIFRSQUNFKCJSZW5kZXJpbmcgb2Zmc2NyZWVuXG4iKTsKICAgICAgICBUaGlzLT5yZW5kZXJfb2Zmc2NyZWVuID0gVFJVRTsKICAgICAgICAqYnVmZmVyID0gVGhpcy0+b2Zmc2NyZWVuQnVmZmVyOwoKICAgICAgICBzd2l0Y2god2luZWQzZF9zZXR0aW5ncy5vZmZzY3JlZW5fcmVuZGVyaW5nX21vZGUpIHsKICAgICAgICAgICAgY2FzZSBPUk1fRkJPOgogICAgICAgICAgICAgICAgLyogRkJPcyBkbyBub3QgbmVlZCBhIGRpZmZlcmVudCBjb250ZXh0LiBTdGF5IHdpdGggd2hhdGV2ZXIgY29udGV4dCBpcyBhY3RpdmUgYXQgdGhlIG1vbWVudCAqLwogICAgICAgICAgICAgICAgaWYoVGhpcy0+YWN0aXZlQ29udGV4dCAmJiB0aWQgPT0gVGhpcy0+bGFzdFRocmVhZCkgewogICAgICAgICAgICAgICAgICAgIGNvbnRleHQgPSBUaGlzLT5hY3RpdmVDb250ZXh0OwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAvKiBUaGlzIG1heSBoYXBwZW4gaWYgdGhlIGFwcCBqdW1wcyBzdHJlaWdodCBpbnRvIG9mZnNjcmVlbiByZW5kZXJpbmcKICAgICAgICAgICAgICAgICAgICAgKiBTdGFydCB1c2luZyB0aGUgY29udGV4dCBvZiB0aGUgcHJpbWFyeSBzd2FwY2hhaW4uIHRpZCA9PSAwIGlzIG5vIHByb2JsZW0KICAgICAgICAgICAgICAgICAgICAgKiBmb3IgZmluZFRocmVhZENvbnRleHRGb3JTd2FwQ2hhaW4uCiAgICAgICAgICAgICAgICAgICAgICoKICAgICAgICAgICAgICAgICAgICAgKiBDYW4gYWxzbyBoYXBwZW4gb24gdGhyZWFkIHN3aXRjaGVzIC0gaW4gdGhhdCBjYXNlIGZpbmRUaHJlYWRDb250ZXh0Rm9yU3dhcENoYWluCiAgICAgICAgICAgICAgICAgICAgICogaXMgcGVyZmVjdCB0byBjYWxsLgogICAgICAgICAgICAgICAgICAgICAqLwogICAgICAgICAgICAgICAgICAgIGNvbnRleHQgPSBmaW5kVGhyZWFkQ29udGV4dEZvclN3YXBDaGFpbihUaGlzLT5zd2FwY2hhaW5zWzBdLCB0aWQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlIE9STV9QQlVGRkVSOgogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBJV2luZUQzRFN1cmZhY2VJbXBsICp0YXJnZXRpbXBsID0gKElXaW5lRDNEU3VyZmFjZUltcGwgKikgdGFyZ2V0OwogICAgICAgICAgICAgICAgaWYoVGhpcy0+cGJ1ZmZlckNvbnRleHQgPT0gTlVMTCB8fAogICAgICAgICAgICAgICAgICAgVGhpcy0+cGJ1ZmZlcldpZHRoIDwgdGFyZ2V0aW1wbC0+Y3VycmVudERlc2MuV2lkdGggfHwKICAgICAgICAgICAgICAgICAgIFRoaXMtPnBidWZmZXJIZWlnaHQgPCB0YXJnZXRpbXBsLT5jdXJyZW50RGVzYy5IZWlnaHQpIHsKICAgICAgICAgICAgICAgICAgICBpZihUaGlzLT5wYnVmZmVyQ29udGV4dCkgewogICAgICAgICAgICAgICAgICAgICAgICBEZXN0cm95Q29udGV4dChUaGlzLCBUaGlzLT5wYnVmZmVyQ29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICAvKiBUaGUgZGlzcGxheSBpcyBpcnJlbGV2YW50IGhlcmUsIHRoZSB3aW5kb3cgaXMgMC4gQnV0IENyZWF0ZUNvbnRleHQgbmVlZHMgYSB2YWxpZCBYIGNvbm5lY3Rpb24uCiAgICAgICAgICAgICAgICAgICAgICogQ3JlYXRlIHRoZSBjb250ZXh0IG9uIHRoZSBzYW1lIHNlcnZlciBhcyB0aGUgcHJpbWFyeSBzd2FwY2hhaW4uIFRoZSBwcmltYXJ5IHN3YXBjaGFpbiBpcyBleGlzdHMgYXQgdGhpcyBwb2ludC4KICAgICAgICAgICAgICAgICAgICAgKi8KICAgICAgICAgICAgICAgICAgICBUaGlzLT5wYnVmZmVyQ29udGV4dCA9IENyZWF0ZUNvbnRleHQoVGhpcywgdGFyZ2V0aW1wbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgoSVdpbmVEM0RTd2FwQ2hhaW5JbXBsICopIFRoaXMtPnN3YXBjaGFpbnNbMF0pLT5jb250ZXh0WzBdLT53aW5faGFuZGxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSAvKiBwYnVmZmVyICovLCAmKChJV2luZUQzRFN3YXBDaGFpbkltcGwgKilUaGlzLT5zd2FwY2hhaW5zWzBdKS0+cHJlc2VudFBhcm1zKTsKICAgICAgICAgICAgICAgICAgICBUaGlzLT5wYnVmZmVyV2lkdGggPSB0YXJnZXRpbXBsLT5jdXJyZW50RGVzYy5XaWR0aDsKICAgICAgICAgICAgICAgICAgICBUaGlzLT5wYnVmZmVySGVpZ2h0ID0gdGFyZ2V0aW1wbC0+Y3VycmVudERlc2MuSGVpZ2h0OwogICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgIGlmKFRoaXMtPnBidWZmZXJDb250ZXh0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgaWYoVGhpcy0+cGJ1ZmZlckNvbnRleHQtPnRpZCAhPSAwICYmIFRoaXMtPnBidWZmZXJDb250ZXh0LT50aWQgIT0gdGlkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZJWE1FKCJUaGUgUEJ1ZmZyIGNvbnRleHQgaXMgb25seSBzdXBwb3J0ZWQgZm9yIG9uZSB0aHJlYWQgZm9yIG5vdyFcbiIpOwogICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICBUaGlzLT5wYnVmZmVyQ29udGV4dC0+dGlkID0gdGlkOwogICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQgPSBUaGlzLT5wYnVmZmVyQ29udGV4dDsKICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgRVJSKCJGYWlsZWQgdG8gY3JlYXRlIGEgYnVmZmVyIGNvbnRleHQgYW5kIGRyYXdhYmxlLCBmYWxsaW5nIGJhY2sgdG8gYmFjayBidWZmZXIgb2Zmc2NyZWVuIHJlbmRlcmluZ1xuIik7CiAgICAgICAgICAgICAgICAgICAgICAgd2luZWQzZF9zZXR0aW5ncy5vZmZzY3JlZW5fcmVuZGVyaW5nX21vZGUgPSBPUk1fQkFDS0JVRkZFUjsKICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY2FzZSBPUk1fQkFDS0JVRkZFUjoKICAgICAgICAgICAgICAgIC8qIFN0YXkgd2l0aCB0aGUgY3VycmVudGx5IGFjdGl2ZSBjb250ZXh0IGZvciBiYWNrIGJ1ZmZlciByZW5kZXJpbmcgKi8KICAgICAgICAgICAgICAgIGlmKFRoaXMtPmFjdGl2ZUNvbnRleHQgJiYgdGlkID09IFRoaXMtPmxhc3RUaHJlYWQpIHsKICAgICAgICAgICAgICAgICAgICBjb250ZXh0ID0gVGhpcy0+YWN0aXZlQ29udGV4dDsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgLyogVGhpcyBtYXkgaGFwcGVuIGlmIHRoZSBhcHAganVtcHMgc3RyZWlnaHQgaW50byBvZmZzY3JlZW4gcmVuZGVyaW5nCiAgICAgICAgICAgICAgICAgICAgICogU3RhcnQgdXNpbmcgdGhlIGNvbnRleHQgb2YgdGhlIHByaW1hcnkgc3dhcGNoYWluLiB0aWQgPT0gMCBpcyBubyBwcm9ibGVtCiAgICAgICAgICAgICAgICAgICAgICogZm9yIGZpbmRUaHJlYWRDb250ZXh0Rm9yU3dhcENoYWluLgogICAgICAgICAgICAgICAgICAgICAqCiAgICAgICAgICAgICAgICAgICAgICogQ2FuIGFsc28gaGFwcGVuIG9uIHRocmVhZCBzd2l0Y2hlcyAtIGluIHRoYXQgY2FzZSBmaW5kVGhyZWFkQ29udGV4dEZvclN3YXBDaGFpbgogICAgICAgICAgICAgICAgICAgICAqIGlzIHBlcmZlY3QgdG8gY2FsbC4KICAgICAgICAgICAgICAgICAgICAgKi8KICAgICAgICAgICAgICAgICAgICBjb250ZXh0ID0gZmluZFRocmVhZENvbnRleHRGb3JTd2FwQ2hhaW4oVGhpcy0+c3dhcGNoYWluc1swXSwgdGlkKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KCiAgICAgICAgaWYgKHdpbmVkM2Rfc2V0dGluZ3Mub2Zmc2NyZWVuX3JlbmRlcmluZ19tb2RlICE9IE9STV9GQk8pIHsKICAgICAgICAgICAgLyogTWFrZSBzdXJlIHdlIGhhdmUgYSBPcGVuR0wgdGV4dHVyZSBuYW1lIHNvIHRoZSBQcmVMb2FkKCkgdXNlZCB0byByZWFkIHRoZSBidWZmZXIKICAgICAgICAgICAgICogYmFjayB3aGVuIHdlIGFyZSBkb25lIHdvbid0IG1hcmsgdXMgZGlydHkuCiAgICAgICAgICAgICAqLwogICAgICAgICAgICBJV2luZUQzRFN1cmZhY2VfUHJlTG9hZCh0YXJnZXQpOwogICAgICAgIH0KCiAgICAgICAgaWYoIW9sZFJlbmRlck9mZnNjcmVlbikgewogICAgICAgICAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFdJTkVEM0RUU19QUk9KRUNUSU9OKTsKICAgICAgICAgICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9WREVDTCk7CiAgICAgICAgICAgIENvbnRleHRfTWFya1N0YXRlRGlydHkoY29udGV4dCwgU1RBVEVfVklFV1BPUlQpOwogICAgICAgICAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1NDSVNTT1JSRUNUKTsKICAgICAgICAgICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9GUk9OVEZBQ0UpOwogICAgICAgIH0KICAgIH0KICAgIGlmIChyZWFkVGV4dHVyZSkgewogICAgICAgIEJPT0wgb2xkSW5EcmF3ID0gVGhpcy0+aXNJbkRyYXc7CgogICAgICAgIC8qIFByZUxvYWQgcmVxdWlyZXMgYSBjb250ZXh0IHRvIGxvYWQgdGhlIHRleHR1cmUsIHRodXMgaXQgd2lsbCBjYWxsIEFjdGl2YXRlQ29udGV4dC4KICAgICAgICAgKiBTZXQgdGhlIGlzSW5EcmF3IHRvIHRydWUgdG8gc2lnbmFsIFByZUxvYWQgdGhhdCBpdCBoYXMgYSBjb250ZXh0LiBXaWxsIGJlIHRyaWNreQogICAgICAgICAqIHdoZW4gdXNpbmcgb2Zmc2NyZWVuIHJlbmRlcmluZyB3aXRoIG11bHRpdGhyZWFkaW5nCiAgICAgICAgICovCiAgICAgICAgVGhpcy0+aXNJbkRyYXcgPSBUUlVFOwoKICAgICAgICAvKiBEbyB0aGF0IGJlZm9yZSBzd2l0Y2hpbmcgdGhlIGNvbnRleHQ6CiAgICAgICAgICogUmVhZCB0aGUgYmFjayBidWZmZXIgb2YgdGhlIG9sZCBkcmF3YWJsZSBpbnRvIHRoZSBkZXN0aW5hdGlvbiB0ZXh0dXJlCiAgICAgICAgICovCiAgICAgICAgSVdpbmVEM0RTdXJmYWNlX1ByZUxvYWQoVGhpcy0+bGFzdEFjdGl2ZVJlbmRlclRhcmdldCk7CgogICAgICAgIC8qIEFzc3VtZSB0aGF0IHRoZSBkcmF3YWJsZSB3aWxsIGJlIG1vZGlmaWVkIGJ5IHNvbWUgb3RoZXIgdGhpbmdzIG5vdyAqLwogICAgICAgIElXaW5lRDNEU3VyZmFjZV9Nb2RpZnlMb2NhdGlvbihUaGlzLT5sYXN0QWN0aXZlUmVuZGVyVGFyZ2V0LCBTRkxBR19JTkRSQVdBQkxFLCBGQUxTRSk7CgogICAgICAgIFRoaXMtPmlzSW5EcmF3ID0gb2xkSW5EcmF3OwogICAgfQoKICAgIGlmKG9sZFJlbmRlck9mZnNjcmVlbiAhPSBUaGlzLT5yZW5kZXJfb2Zmc2NyZWVuICYmIFRoaXMtPmRlcHRoX2NvcHlfc3RhdGUgIT0gV0lORUQzRF9EQ1NfTk9fQ09QWSkgewogICAgICAgIFRoaXMtPmRlcHRoX2NvcHlfc3RhdGUgPSBXSU5FRDNEX0RDU19DT1BZOwogICAgfQogICAgcmV0dXJuIGNvbnRleHQ7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiBBY3RpdmF0ZUNvbnRleHQKICoKICogRmluZHMgYSByZW5kZXJpbmcgY29udGV4dCBhbmQgZHJhd2FibGUgbWF0Y2hpbmcgdGhlIGRldmljZSBhbmQgcmVuZGVyCiAqIHRhcmdldCBmb3IgdGhlIGN1cnJlbnQgdGhyZWFkLCBhY3RpdmF0ZXMgdGhlbSBhbmQgcHV0cyB0aGVtIGludG8gdGhlCiAqIHJlcXVlc3RlZCBzdGF0ZS4KICoKICogUGFyYW1zOgogKiAgVGhpczogRGV2aWNlIHRvIGFjdGl2YXRlIHRoZSBjb250ZXh0IGZvcgogKiAgdGFyZ2V0OiBSZXF1ZXN0ZWQgcmVuZGVyIHRhcmdldAogKiAgdXNhZ2U6IFByZXBhcmVzIHRoZSBjb250ZXh0IGZvciBibGl0dGluZywgZHJhd2luZyBvciBvdGhlciBhY3Rpb25zCiAqCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8Kdm9pZCBBY3RpdmF0ZUNvbnRleHQoSVdpbmVEM0REZXZpY2VJbXBsICpUaGlzLCBJV2luZUQzRFN1cmZhY2UgKnRhcmdldCwgQ29udGV4dFVzYWdlIHVzYWdlKSB7CiAgICBEV09SRCAgICAgICAgICAgICAgICAgICAgICAgICB0aWQgPSBHZXRDdXJyZW50VGhyZWFkSWQoKTsKICAgIGludCAgICAgICAgICAgICAgICAgICAgICAgICAgIGk7CiAgICBEV09SRCAgICAgICAgICAgICAgICAgICAgICAgICBkaXJ0eVN0YXRlLCBpZHg7CiAgICBCWVRFICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdDsKICAgIFdpbmVEM0RDb250ZXh0ICAgICAgICAgICAgICAgICpjb250ZXh0OwogICAgR0xpbnQgICAgICAgICAgICAgICAgICAgICAgICAgZHJhd0J1ZmZlcj0wOwoKICAgIFRSQUNFKCIoJXApOiBTZWxlY3RpbmcgY29udGV4dCBmb3IgcmVuZGVyIHRhcmdldCAlcCwgdGhyZWFkICVkXG4iLCBUaGlzLCB0YXJnZXQsIHRpZCk7CiAgICBpZihUaGlzLT5sYXN0QWN0aXZlUmVuZGVyVGFyZ2V0ICE9IHRhcmdldCB8fCB0aWQgIT0gVGhpcy0+bGFzdFRocmVhZCkgewogICAgICAgIGNvbnRleHQgPSBGaW5kQ29udGV4dChUaGlzLCB0YXJnZXQsIHRpZCwgJmRyYXdCdWZmZXIpOwogICAgICAgIFRoaXMtPmxhc3RBY3RpdmVSZW5kZXJUYXJnZXQgPSB0YXJnZXQ7CiAgICAgICAgVGhpcy0+bGFzdFRocmVhZCA9IHRpZDsKICAgIH0gZWxzZSB7CiAgICAgICAgLyogU3RpY2sgdG8gdGhlIG9sZCBjb250ZXh0ICovCiAgICAgICAgY29udGV4dCA9IFRoaXMtPmFjdGl2ZUNvbnRleHQ7CiAgICB9CgogICAgLyogQWN0aXZhdGUgdGhlIG9wZW5nbCBjb250ZXh0ICovCiAgICBpZihjb250ZXh0ICE9IFRoaXMtPmFjdGl2ZUNvbnRleHQpIHsKICAgICAgICBCT09MIHJldDsKCiAgICAgICAgLyogUHJldmVudCBhbiB1bm5lZWRlZCBjb250ZXh0IHN3aXRjaCBhcyB0aG9zZSBhcmUgZXhwZW5zaXZlICovCiAgICAgICAgaWYoY29udGV4dC0+Z2xDdHggJiYgKGNvbnRleHQtPmdsQ3R4ID09IHB3Z2xHZXRDdXJyZW50Q29udGV4dCgpKSkgewogICAgICAgICAgICBUUkFDRSgiQWxyZWFkeSB1c2luZyBnbCBjb250ZXh0ICVwXG4iLCBjb250ZXh0LT5nbEN0eCk7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBUUkFDRSgiU3dpdGNoaW5nIGdsIGN0eCB0byAlcCwgaGRjPSVwIGN0eD0lcFxuIiwgY29udGV4dCwgY29udGV4dC0+aGRjLCBjb250ZXh0LT5nbEN0eCk7CiAgICAgICAgICAgIHJldCA9IHB3Z2xNYWtlQ3VycmVudChjb250ZXh0LT5oZGMsIGNvbnRleHQtPmdsQ3R4KTsKICAgICAgICAgICAgaWYocmV0ID09IEZBTFNFKSB7CiAgICAgICAgICAgICAgICBFUlIoIkZhaWxlZCB0byBhY3RpdmF0ZSB0aGUgbmV3IGNvbnRleHRcbiIpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIFRoaXMtPmFjdGl2ZUNvbnRleHQgPSBjb250ZXh0OwogICAgfQoKICAgIC8qIFdlIG9ubHkgbmVlZCBFTlRFUl9HTCBmb3IgdGhlIGdsIGNhbGxzIG1hZGUgYmVsb3cgYW5kIGZvciB0aGUgaGVscGVyIGZ1bmN0aW9ucyB3aGljaCBtYWtlIEdMIGNhbGxzICovCiAgICBFTlRFUl9HTCgpOwogICAgLyogU2VsZWN0IHRoZSByaWdodCBkcmF3IGJ1ZmZlci4gSXQgaXMgc2VsZWN0ZWQgaW4gRmluZENvbnRleHQuICovCiAgICBpZihkcmF3QnVmZmVyICYmIGNvbnRleHQtPmxhc3RfZHJhd19idWZmZXIgIT0gZHJhd0J1ZmZlcikgewogICAgICAgIFRSQUNFKCJEcmF3aW5nIHRvIGJ1ZmZlcjogJSN4XG4iLCBkcmF3QnVmZmVyKTsKICAgICAgICBjb250ZXh0LT5sYXN0X2RyYXdfYnVmZmVyID0gZHJhd0J1ZmZlcjsKCiAgICAgICAgZ2xEcmF3QnVmZmVyKGRyYXdCdWZmZXIpOwogICAgICAgIGNoZWNrR0xjYWxsKCJnbERyYXdCdWZmZXIiKTsKICAgIH0KCiAgICBzd2l0Y2godXNhZ2UpIHsKICAgICAgICBjYXNlIENUWFVTQUdFX1JFU09VUkNFTE9BRDoKICAgICAgICAgICAgLyogVGhpcyBkb2VzIG5vdCByZXF1aXJlIGFueSBzcGVjaWFsIHN0YXRlcyB0byBiZSBzZXQgdXAgKi8KICAgICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgQ1RYVVNBR0VfQ0xFQVI6CiAgICAgICAgICAgIGlmKGNvbnRleHQtPmxhc3Rfd2FzX2JsaXQgJiYgR0xfU1VQUE9SVChOVl9URVhUVVJFX1NIQURFUjIpKSB7CiAgICAgICAgICAgICAgICBnbEVuYWJsZShHTF9URVhUVVJFX1NIQURFUl9OVik7CiAgICAgICAgICAgICAgICBjaGVja0dMY2FsbCgiZ2xFbmFibGUoR0xfVEVYVFVSRV9TSEFERVJfTlYpIik7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGdsRW5hYmxlKEdMX1NDSVNTT1JfVEVTVCk7CiAgICAgICAgICAgIGNoZWNrR0xjYWxsKCJnbEVuYWJsZSBHTF9TQ0lTU09SX1RFU1QiKTsKICAgICAgICAgICAgY29udGV4dC0+bGFzdF93YXNfYmxpdCA9IEZBTFNFOwogICAgICAgICAgICBDb250ZXh0X01hcmtTdGF0ZURpcnR5KGNvbnRleHQsIFNUQVRFX1JFTkRFUihXSU5FRDNEUlNfU0NJU1NPUlRFU1RFTkFCTEUpKTsKICAgICAgICAgICAgQ29udGV4dF9NYXJrU3RhdGVEaXJ0eShjb250ZXh0LCBTVEFURV9TQ0lTU09SUkVDVCk7CiAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlIENUWFVTQUdFX0RSQVdQUklNOgogICAgICAgICAgICAvKiBUaGlzIG5lZWRzIGFsbCBkaXJ0eSBzdGF0ZXMgYXBwbGllZCAqLwogICAgICAgICAgICBpZihjb250ZXh0LT5sYXN0X3dhc19ibGl0ICYmIEdMX1NVUFBPUlQoTlZfVEVYVFVSRV9TSEFERVIyKSkgewogICAgICAgICAgICAgICAgZ2xFbmFibGUoR0xfVEVYVFVSRV9TSEFERVJfTlYpOwogICAgICAgICAgICAgICAgY2hlY2tHTGNhbGwoImdsRW5hYmxlKEdMX1RFWFRVUkVfU0hBREVSX05WKSIpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBJV2luZUQzRERldmljZUltcGxfRmluZFRleFVuaXRNYXAoVGhpcyk7CgogICAgICAgICAgICBmb3IoaT0wOyBpIDwgY29udGV4dC0+bnVtRGlydHlFbnRyaWVzOyBpKyspIHsKICAgICAgICAgICAgICAgIGRpcnR5U3RhdGUgPSBjb250ZXh0LT5kaXJ0eUFycmF5W2ldOwogICAgICAgICAgICAgICAgaWR4ID0gZGlydHlTdGF0ZSA+PiA1OwogICAgICAgICAgICAgICAgc2hpZnQgPSBkaXJ0eVN0YXRlICYgMHgxZjsKICAgICAgICAgICAgICAgIGNvbnRleHQtPmlzU3RhdGVEaXJ0eVtpZHhdICY9IH4oMSA8PCBzaGlmdCk7CiAgICAgICAgICAgICAgICBTdGF0ZVRhYmxlW2RpcnR5U3RhdGVdLmFwcGx5KGRpcnR5U3RhdGUsIFRoaXMtPnN0YXRlQmxvY2ssIGNvbnRleHQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRleHQtPm51bURpcnR5RW50cmllcyA9IDA7IC8qIFRoaXMgbWFrZXMgdGhlIHdob2xlIGxpc3QgY2xlYW4gKi8KICAgICAgICAgICAgY29udGV4dC0+bGFzdF93YXNfYmxpdCA9IEZBTFNFOwogICAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSBDVFhVU0FHRV9CTElUOgogICAgICAgICAgICBTZXR1cEZvckJsaXQoVGhpcywgY29udGV4dCwKICAgICAgICAgICAgICAgICAgICAgICAgICgoSVdpbmVEM0RTdXJmYWNlSW1wbCAqKXRhcmdldCktPmN1cnJlbnREZXNjLldpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgKChJV2luZUQzRFN1cmZhY2VJbXBsICopdGFyZ2V0KS0+Y3VycmVudERlc2MuSGVpZ2h0KTsKICAgICAgICAgICAgYnJlYWs7CgogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIEZJWE1FKCJVbmV4cGVjdGVkIGNvbnRleHQgdXNhZ2UgcmVxdWVzdGVkXG4iKTsKICAgIH0KICAgIExFQVZFX0dMKCk7Cn0K