LyoKICogSVdpbmVEM0RUZXh0dXJlIGltcGxlbWVudGF0aW9uCiAqCiAqIENvcHlyaWdodCAyMDAyLTIwMDUgSmFzb24gRWRtZWFkZXMKICogQ29weXJpZ2h0IDIwMDItMjAwNSBSYXBoYWVsIEp1bnF1ZWlyYQogKiBDb3B5cmlnaHQgMjAwNSBPbGl2ZXIgU3RpZWJlcgogKiBDb3B5cmlnaHQgMjAwNy0yMDA4IFN0ZWZhbiBE9nNpbmdlciBmb3IgQ29kZVdlYXZlcnMKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSwgVVNBCiAqLwoKI2luY2x1ZGUgImNvbmZpZy5oIgojaW5jbHVkZSAid2luZWQzZF9wcml2YXRlLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChkM2RfdGV4dHVyZSk7CiNkZWZpbmUgR0xJTkZPX0xPQ0FUSU9OIFRoaXMtPnJlc291cmNlLndpbmVEM0REZXZpY2UtPmFkYXB0ZXItPmdsX2luZm8KCi8qICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAgSVdpbmVEM0RUZXh0dXJlIElVbmtub3duIHBhcnRzIGZvbGxvdwogICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX1F1ZXJ5SW50ZXJmYWNlKElXaW5lRDNEVGV4dHVyZSAqaWZhY2UsIFJFRklJRCByaWlkLCBMUFZPSUQgKnBwb2JqKQp7CiAgICBJV2luZUQzRFRleHR1cmVJbXBsICpUaGlzID0gKElXaW5lRDNEVGV4dHVyZUltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXApLT4oJXMsJXApXG4iLFRoaXMsZGVidWdzdHJfZ3VpZChyaWlkKSxwcG9iaik7CiAgICBpZiAoSXNFcXVhbEdVSUQocmlpZCwgJklJRF9JVW5rbm93bikKICAgICAgICB8fCBJc0VxdWFsR1VJRChyaWlkLCAmSUlEX0lXaW5lRDNEQmFzZSkKICAgICAgICB8fCBJc0VxdWFsR1VJRChyaWlkLCAmSUlEX0lXaW5lRDNEUmVzb3VyY2UpCiAgICAgICAgfHwgSXNFcXVhbEdVSUQocmlpZCwgJklJRF9JV2luZUQzREJhc2VUZXh0dXJlKQogICAgICAgIHx8IElzRXF1YWxHVUlEKHJpaWQsICZJSURfSVdpbmVEM0RUZXh0dXJlKSl7CiAgICAgICAgSVVua25vd25fQWRkUmVmKGlmYWNlKTsKICAgICAgICAqcHBvYmogPSBUaGlzOwogICAgICAgIHJldHVybiBXSU5FRDNEX09LOwogICAgfQogICAgKnBwb2JqID0gTlVMTDsKICAgIHJldHVybiBFX05PSU5URVJGQUNFOwp9CgpzdGF0aWMgVUxPTkcgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfQWRkUmVmKElXaW5lRDNEVGV4dHVyZSAqaWZhY2UpIHsKICAgIElXaW5lRDNEVGV4dHVyZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RUZXh0dXJlSW1wbCAqKWlmYWNlOwogICAgVFJBQ0UoIiglcCkgOiBBZGRSZWYgaW5jcmVhc2luZyBmcm9tICVkXG4iLCBUaGlzLCBUaGlzLT5yZXNvdXJjZS5yZWYpOwogICAgcmV0dXJuIEludGVybG9ja2VkSW5jcmVtZW50KCZUaGlzLT5yZXNvdXJjZS5yZWYpOwp9CgpzdGF0aWMgVUxPTkcgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfUmVsZWFzZShJV2luZUQzRFRleHR1cmUgKmlmYWNlKSB7CiAgICBJV2luZUQzRFRleHR1cmVJbXBsICpUaGlzID0gKElXaW5lRDNEVGV4dHVyZUltcGwgKilpZmFjZTsKICAgIFVMT05HIHJlZjsKICAgIFRSQUNFKCIoJXApIDogUmVsZWFzaW5nIGZyb20gJWRcbiIsIFRoaXMsIFRoaXMtPnJlc291cmNlLnJlZik7CiAgICByZWYgPSBJbnRlcmxvY2tlZERlY3JlbWVudCgmVGhpcy0+cmVzb3VyY2UucmVmKTsKICAgIGlmIChyZWYgPT0gMCkgewogICAgICAgIElXaW5lRDNEVGV4dHVyZV9EZXN0cm95KGlmYWNlLCBEM0RDQl9EZWZhdWx0RGVzdHJveVN1cmZhY2UpOwogICAgfQogICAgcmV0dXJuIHJlZjsKfQoKCi8qICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAgSVdpbmVEM0RUZXh0dXJlIElXaW5lRDNEUmVzb3VyY2UgcGFydHMgZm9sbG93CiAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi8Kc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0RGV2aWNlKElXaW5lRDNEVGV4dHVyZSAqaWZhY2UsIElXaW5lRDNERGV2aWNlKiogcHBEZXZpY2UpIHsKICAgIHJldHVybiBJV2luZUQzRFJlc291cmNlSW1wbF9HZXREZXZpY2UoKElXaW5lRDNEUmVzb3VyY2UgKilpZmFjZSwgcHBEZXZpY2UpOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVdpbmVEM0RUZXh0dXJlSW1wbF9TZXRQcml2YXRlRGF0YShJV2luZUQzRFRleHR1cmUgKmlmYWNlLCBSRUZHVUlEIHJlZmd1aWQsIENPTlNUIHZvaWQqIHBEYXRhLCBEV09SRCBTaXplT2ZEYXRhLCBEV09SRCBGbGFncykgewogICAgcmV0dXJuIElXaW5lRDNEUmVzb3VyY2VJbXBsX1NldFByaXZhdGVEYXRhKChJV2luZUQzRFJlc291cmNlICopaWZhY2UsIHJlZmd1aWQsIHBEYXRhLCBTaXplT2ZEYXRhLCBGbGFncyk7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0dldFByaXZhdGVEYXRhKElXaW5lRDNEVGV4dHVyZSAqaWZhY2UsIFJFRkdVSUQgcmVmZ3VpZCwgdm9pZCogcERhdGEsIERXT1JEKiBwU2l6ZU9mRGF0YSkgewogICAgcmV0dXJuIElXaW5lRDNEUmVzb3VyY2VJbXBsX0dldFByaXZhdGVEYXRhKChJV2luZUQzRFJlc291cmNlICopaWZhY2UsIHJlZmd1aWQsIHBEYXRhLCBwU2l6ZU9mRGF0YSk7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0ZyZWVQcml2YXRlRGF0YShJV2luZUQzRFRleHR1cmUgKmlmYWNlLCBSRUZHVUlEIHJlZmd1aWQpIHsKICAgIHJldHVybiBJV2luZUQzRFJlc291cmNlSW1wbF9GcmVlUHJpdmF0ZURhdGEoKElXaW5lRDNEUmVzb3VyY2UgKilpZmFjZSwgcmVmZ3VpZCk7Cn0KCnN0YXRpYyBEV09SRCBXSU5BUEkgSVdpbmVEM0RUZXh0dXJlSW1wbF9TZXRQcmlvcml0eShJV2luZUQzRFRleHR1cmUgKmlmYWNlLCBEV09SRCBQcmlvcml0eU5ldykgewogICAgcmV0dXJuIElXaW5lRDNEUmVzb3VyY2VJbXBsX1NldFByaW9yaXR5KChJV2luZUQzRFJlc291cmNlICopaWZhY2UsIFByaW9yaXR5TmV3KTsKfQoKc3RhdGljIERXT1JEIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0dldFByaW9yaXR5KElXaW5lRDNEVGV4dHVyZSAqaWZhY2UpIHsKICAgIHJldHVybiBJV2luZUQzRFJlc291cmNlSW1wbF9HZXRQcmlvcml0eSgoSVdpbmVEM0RSZXNvdXJjZSAqKWlmYWNlKTsKfQoKc3RhdGljIHZvaWQgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfUHJlTG9hZChJV2luZUQzRFRleHR1cmUgKmlmYWNlKSB7CgogICAgLyogT3ZlcnJpZGUgdGhlIElXaW5lRDNEUmVzb3VyY2UgUHJlTG9hZCBtZXRob2QgKi8KICAgIHVuc2lnbmVkIGludCBpOwogICAgSVdpbmVEM0RUZXh0dXJlSW1wbCAqVGhpcyA9IChJV2luZUQzRFRleHR1cmVJbXBsICopaWZhY2U7CiAgICBJV2luZUQzRERldmljZUltcGwgKmRldmljZSA9IFRoaXMtPnJlc291cmNlLndpbmVEM0REZXZpY2U7CiAgICBCT09MIHNyZ2JfbW9kZSA9IFRoaXMtPmJhc2VUZXh0dXJlLmlzX3NyZ2I7CiAgICBCT09MIHNyZ2Jfd2FzX3RvZ2dsZWQgPSBGQUxTRTsKCiAgICBUUkFDRSgiKCVwKSA6IEFib3V0IHRvIGxvYWQgdGV4dHVyZVxuIiwgVGhpcyk7CgogICAgaWYoIWRldmljZS0+aXNJbkRyYXcpIHsKICAgICAgICAvKiBBY3RpdmF0ZUNvbnRleHQgc2V0cyBpc0luRHJhdyB0byBUUlVFIHdoZW4gbG9hZGluZyBhIHBidWZmZXIgaW50byBhIHRleHR1cmUsIHRodXMgbm8gZGFuZ2VyIG9mCiAgICAgICAgICogcmVjdXJzaXZlIGNhbGxzCiAgICAgICAgICovCiAgICAgICAgQWN0aXZhdGVDb250ZXh0KGRldmljZSwgZGV2aWNlLT5sYXN0QWN0aXZlUmVuZGVyVGFyZ2V0LCBDVFhVU0FHRV9SRVNPVVJDRUxPQUQpOwogICAgfSBlbHNlIGlmIChHTF9TVVBQT1JUKEVYVF9URVhUVVJFX1NSR0IpICYmIFRoaXMtPmJhc2VUZXh0dXJlLmJpbmRDb3VudCA+IDApIHsKICAgICAgICBzcmdiX21vZGUgPSBkZXZpY2UtPnN0YXRlQmxvY2stPnNhbXBsZXJTdGF0ZVtUaGlzLT5iYXNlVGV4dHVyZS5zYW1wbGVyXVtXSU5FRDNEU0FNUF9TUkdCVEVYVFVSRV07CiAgICAgICAgc3JnYl93YXNfdG9nZ2xlZCA9IFRoaXMtPmJhc2VUZXh0dXJlLmlzX3NyZ2IgIT0gc3JnYl9tb2RlOwogICAgICAgIFRoaXMtPmJhc2VUZXh0dXJlLmlzX3NyZ2IgPSBzcmdiX21vZGU7CiAgICB9CgogICAgSVdpbmVEM0RUZXh0dXJlX0JpbmRUZXh0dXJlKGlmYWNlKTsKCiAgICBpZiAoVGhpcy0+cmVzb3VyY2UuZm9ybWF0ID09IFdJTkVEM0RGTVRfUDggfHwgVGhpcy0+cmVzb3VyY2UuZm9ybWF0ID09IFdJTkVEM0RGTVRfQThQOCkgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCBUaGlzLT5iYXNlVGV4dHVyZS5sZXZlbHM7IGkrKykgewogICAgICAgICAgICBpZihwYWxldHRlOV9jaGFuZ2VkKChJV2luZUQzRFN1cmZhY2VJbXBsICopVGhpcy0+c3VyZmFjZXNbaV0pKSB7CiAgICAgICAgICAgICAgICBUUkFDRSgiUmVsb2FkaW5nIHN1cmZhY2UgYmVjYXVzZSB0aGUgZDNkOC85IHBhbGV0dGUgd2FzIGNoYW5nZWRcbiIpOwogICAgICAgICAgICAgICAgLyogVE9ETzogVGhpcyBpcyBub3QgbmVjZXNzYXJpbHkgbmVlZGVkIHdpdGggaHcgcGFsZXR0aXplZCB0ZXh0dXJlIHN1cHBvcnQgKi8KICAgICAgICAgICAgICAgIElXaW5lRDNEU3VyZmFjZV9Mb2FkTG9jYXRpb24oVGhpcy0+c3VyZmFjZXNbaV0sIFNGTEFHX0lOU1lTTUVNLCBOVUxMKTsKICAgICAgICAgICAgICAgIC8qIE1ha2Ugc3VyZSB0aGUgdGV4dHVyZSBpcyByZWxvYWRlZCBiZWNhdXNlIG9mIHRoZSBwYWxldHRlIGNoYW5nZSwgdGhpcyBraWxscyBwZXJmb3JtYW5jZSB0aG91Z2ggOiggKi8KICAgICAgICAgICAgICAgIElXaW5lRDNEU3VyZmFjZV9Nb2RpZnlMb2NhdGlvbihUaGlzLT5zdXJmYWNlc1tpXSwgU0ZMQUdfSU5URVhUVVJFLCBGQUxTRSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICAvKiBJZiB0aGUgdGV4dHVyZSBpcyBtYXJrZWQgZGlydHkgb3IgdGhlIHNyZ2Igc2FtcGxlciBzZXR0aW5nIGhhcyBjaGFuZ2VkIHNpbmNlIHRoZSBsYXN0IGxvYWQgdGhlbiByZWxvYWQgdGhlIHN1cmZhY2VzICovCiAgICBpZiAoVGhpcy0+YmFzZVRleHR1cmUuZGlydHkpIHsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgVGhpcy0+YmFzZVRleHR1cmUubGV2ZWxzOyBpKyspIHsKICAgICAgICAgICAgSVdpbmVEM0RTdXJmYWNlX0xvYWRUZXh0dXJlKFRoaXMtPnN1cmZhY2VzW2ldLCBzcmdiX21vZGUpOwogICAgICAgIH0KICAgIH0gZWxzZSBpZiAoc3JnYl93YXNfdG9nZ2xlZCkgewogICAgICAgIGlmIChUaGlzLT5iYXNlVGV4dHVyZS5zcmdiX21vZGVfY2hhbmdlX2NvdW50IDwgMjApCiAgICAgICAgICAgICsrVGhpcy0+YmFzZVRleHR1cmUuc3JnYl9tb2RlX2NoYW5nZV9jb3VudDsKICAgICAgICBlbHNlCiAgICAgICAgICAgIEZJWE1FKCJUZXh0dXJlICglcCkgaGFzIGJlZW4gcmVsb2FkZWQgYXQgbGVhc3QgMjAgdGltZXMgZHVlIHRvIFdJTkVEM0RTQU1QX1NSR0JURVhUVVJFIGNoYW5nZXMgb24gaXRcJ3Mgc2FtcGxlclxuIiwgVGhpcyk7CgogICAgICAgIGZvciAoaSA9IDA7IGkgPCBUaGlzLT5iYXNlVGV4dHVyZS5sZXZlbHM7IGkrKykgewogICAgICAgICAgICBJV2luZUQzRFN1cmZhY2VfQWRkRGlydHlSZWN0KFRoaXMtPnN1cmZhY2VzW2ldLCBOVUxMKTsKICAgICAgICAgICAgSVdpbmVEM0RTdXJmYWNlX1NldEdsVGV4dHVyZURlc2MoVGhpcy0+c3VyZmFjZXNbaV0sIFRoaXMtPmJhc2VUZXh0dXJlLnRleHR1cmVOYW1lLCBJV2luZUQzRFRleHR1cmVfR2V0VGV4dHVyZURpbWVuc2lvbnMoaWZhY2UpKTsKICAgICAgICAgICAgSVdpbmVEM0RTdXJmYWNlX0xvYWRUZXh0dXJlKFRoaXMtPnN1cmZhY2VzW2ldLCBzcmdiX21vZGUpOwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgVFJBQ0UoIiglcCkgVGV4dHVyZSBub3QgZGlydHksIG5vdGhpbmcgdG8gZG9cbiIgLCBpZmFjZSk7CiAgICB9CgogICAgLyogTm8gbG9uZ2VyIGRpcnR5ICovCiAgICBUaGlzLT5iYXNlVGV4dHVyZS5kaXJ0eSA9IEZBTFNFOwoKICAgIHJldHVybiA7Cn0KCnN0YXRpYyB2b2lkIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX1VuTG9hZChJV2luZUQzRFRleHR1cmUgKmlmYWNlKSB7CiAgICB1bnNpZ25lZCBpbnQgaTsKICAgIElXaW5lRDNEVGV4dHVyZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RUZXh0dXJlSW1wbCAqKWlmYWNlOwogICAgVFJBQ0UoIiglcClcbiIsIFRoaXMpOwoKICAgIC8qIFVubG9hZCBhbGwgdGhlIHN1cmZhY2VzIGFuZCByZXNldCB0aGUgdGV4dHVyZSBuYW1lLiBJZiBVbkxvYWQgd2FzIGNhbGxlZCBvbiB0aGUKICAgICAqIHN1cmZhY2UgYmVmb3JlLCB0aGlzIG9uZSB3aWxsIGJlIGEgTk9QIGFuZCB2aWNlIHZlcnNhLiBVbmxvYWRpbmcgYW4gdW5sb2FkZWQKICAgICAqIHN1cmZhY2UgaXMgZmluZQogICAgICovCiAgICBmb3IgKGkgPSAwOyBpIDwgVGhpcy0+YmFzZVRleHR1cmUubGV2ZWxzOyBpKyspIHsKICAgICAgICBJV2luZUQzRFN1cmZhY2VfVW5Mb2FkKFRoaXMtPnN1cmZhY2VzW2ldKTsKICAgICAgICBJV2luZUQzRFN1cmZhY2VfU2V0R2xUZXh0dXJlRGVzYyhUaGlzLT5zdXJmYWNlc1tpXSwgMCwgSVdpbmVEM0RUZXh0dXJlX0dldFRleHR1cmVEaW1lbnNpb25zKGlmYWNlKSk7CiAgICB9CgogICAgSVdpbmVEM0RCYXNlVGV4dHVyZUltcGxfVW5Mb2FkKChJV2luZUQzREJhc2VUZXh0dXJlICopIGlmYWNlKTsKfQoKc3RhdGljIFdJTkVEM0RSRVNPVVJDRVRZUEUgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0VHlwZShJV2luZUQzRFRleHR1cmUgKmlmYWNlKSB7CiAgICByZXR1cm4gSVdpbmVEM0RSZXNvdXJjZUltcGxfR2V0VHlwZSgoSVdpbmVEM0RSZXNvdXJjZSAqKWlmYWNlKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0UGFyZW50KElXaW5lRDNEVGV4dHVyZSAqaWZhY2UsIElVbmtub3duICoqcFBhcmVudCkgewogICAgcmV0dXJuIElXaW5lRDNEUmVzb3VyY2VJbXBsX0dldFBhcmVudCgoSVdpbmVEM0RSZXNvdXJjZSAqKWlmYWNlLCBwUGFyZW50KTsKfQoKLyogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAgIElXaW5lRDNEVGV4dHVyZSBJV2luZUQzREJhc2VUZXh0dXJlIHBhcnRzIGZvbGxvdwogICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi8Kc3RhdGljIERXT1JEIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX1NldExPRChJV2luZUQzRFRleHR1cmUgKmlmYWNlLCBEV09SRCBMT0ROZXcpIHsKICAgIHJldHVybiBJV2luZUQzREJhc2VUZXh0dXJlSW1wbF9TZXRMT0QoKElXaW5lRDNEQmFzZVRleHR1cmUgKilpZmFjZSwgTE9ETmV3KTsKfQoKc3RhdGljIERXT1JEIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0dldExPRChJV2luZUQzRFRleHR1cmUgKmlmYWNlKSB7CiAgICByZXR1cm4gSVdpbmVEM0RCYXNlVGV4dHVyZUltcGxfR2V0TE9EKChJV2luZUQzREJhc2VUZXh0dXJlICopaWZhY2UpOwp9CgpzdGF0aWMgRFdPUkQgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0TGV2ZWxDb3VudChJV2luZUQzRFRleHR1cmUgKmlmYWNlKSB7CiAgICByZXR1cm4gSVdpbmVEM0RCYXNlVGV4dHVyZUltcGxfR2V0TGV2ZWxDb3VudCgoSVdpbmVEM0RCYXNlVGV4dHVyZSAqKWlmYWNlKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfU2V0QXV0b0dlbkZpbHRlclR5cGUoSVdpbmVEM0RUZXh0dXJlICppZmFjZSwgV0lORUQzRFRFWFRVUkVGSUxURVJUWVBFIEZpbHRlclR5cGUpIHsKICByZXR1cm4gSVdpbmVEM0RCYXNlVGV4dHVyZUltcGxfU2V0QXV0b0dlbkZpbHRlclR5cGUoKElXaW5lRDNEQmFzZVRleHR1cmUgKilpZmFjZSwgRmlsdGVyVHlwZSk7Cn0KCnN0YXRpYyBXSU5FRDNEVEVYVFVSRUZJTFRFUlRZUEUgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0QXV0b0dlbkZpbHRlclR5cGUoSVdpbmVEM0RUZXh0dXJlICppZmFjZSkgewogIHJldHVybiBJV2luZUQzREJhc2VUZXh0dXJlSW1wbF9HZXRBdXRvR2VuRmlsdGVyVHlwZSgoSVdpbmVEM0RCYXNlVGV4dHVyZSAqKWlmYWNlKTsKfQoKc3RhdGljIHZvaWQgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfR2VuZXJhdGVNaXBTdWJMZXZlbHMoSVdpbmVEM0RUZXh0dXJlICppZmFjZSkgewogICAgSVdpbmVEM0RCYXNlVGV4dHVyZUltcGxfR2VuZXJhdGVNaXBTdWJMZXZlbHMoKElXaW5lRDNEQmFzZVRleHR1cmUgKilpZmFjZSk7Cn0KCi8qIEludGVybmFsIGZ1bmN0aW9uLCBObyBkM2QgbWFwcGluZyAqLwpzdGF0aWMgQk9PTCBXSU5BUEkgSVdpbmVEM0RUZXh0dXJlSW1wbF9TZXREaXJ0eShJV2luZUQzRFRleHR1cmUgKmlmYWNlLCBCT09MIGRpcnR5KSB7CiAgICByZXR1cm4gSVdpbmVEM0RCYXNlVGV4dHVyZUltcGxfU2V0RGlydHkoKElXaW5lRDNEQmFzZVRleHR1cmUgKilpZmFjZSwgZGlydHkpOwp9CgpzdGF0aWMgQk9PTCBXSU5BUEkgSVdpbmVEM0RUZXh0dXJlSW1wbF9HZXREaXJ0eShJV2luZUQzRFRleHR1cmUgKmlmYWNlKSB7CiAgICByZXR1cm4gSVdpbmVEM0RCYXNlVGV4dHVyZUltcGxfR2V0RGlydHkoKElXaW5lRDNEQmFzZVRleHR1cmUgKilpZmFjZSk7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0JpbmRUZXh0dXJlKElXaW5lRDNEVGV4dHVyZSAqaWZhY2UpIHsKICAgIElXaW5lRDNEVGV4dHVyZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RUZXh0dXJlSW1wbCAqKWlmYWNlOwogICAgQk9PTCBzZXRfZ2xfdGV4dHVyZV9kZXNjID0gVGhpcy0+YmFzZVRleHR1cmUudGV4dHVyZU5hbWUgPT0gMDsKICAgIEhSRVNVTFQgaHI7CgogICAgVFJBQ0UoIiglcCkgOiByZWxheSB0byBCYXNlVGV4dHVyZVxuIiwgVGhpcyk7CgogICAgaHIgPSBJV2luZUQzREJhc2VUZXh0dXJlSW1wbF9CaW5kVGV4dHVyZSgoSVdpbmVEM0RCYXNlVGV4dHVyZSAqKWlmYWNlKTsKICAgIGlmIChzZXRfZ2xfdGV4dHVyZV9kZXNjICYmIFNVQ0NFRURFRChocikpIHsKICAgICAgICBVSU5UIGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IFRoaXMtPmJhc2VUZXh0dXJlLmxldmVsczsgKytpKSB7CiAgICAgICAgICAgIElXaW5lRDNEU3VyZmFjZV9TZXRHbFRleHR1cmVEZXNjKFRoaXMtPnN1cmZhY2VzW2ldLCBUaGlzLT5iYXNlVGV4dHVyZS50ZXh0dXJlTmFtZSwgSVdpbmVEM0RUZXh0dXJlX0dldFRleHR1cmVEaW1lbnNpb25zKGlmYWNlKSk7CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiBocjsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfVW5CaW5kVGV4dHVyZShJV2luZUQzRFRleHR1cmUgKmlmYWNlKSB7CiAgICBJV2luZUQzRFRleHR1cmVJbXBsICpUaGlzID0gKElXaW5lRDNEVGV4dHVyZUltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXApIDogcmVsYXkgdG8gQmFzZVRleHR1cmVcbiIsIFRoaXMpOwogICAgcmV0dXJuIElXaW5lRDNEQmFzZVRleHR1cmVJbXBsX1VuQmluZFRleHR1cmUoKElXaW5lRDNEQmFzZVRleHR1cmUgKilpZmFjZSk7Cn0KCnN0YXRpYyBVSU5UIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0dldFRleHR1cmVEaW1lbnNpb25zKElXaW5lRDNEVGV4dHVyZSAqaWZhY2UpIHsKICAgIElXaW5lRDNEVGV4dHVyZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RUZXh0dXJlSW1wbCAqKWlmYWNlOwogICAgVFJBQ0UoIiglcClcbiIsIFRoaXMpOwoKICAgIHJldHVybiBUaGlzLT50YXJnZXQ7Cn0KCnN0YXRpYyB2b2lkIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0FwcGx5U3RhdGVDaGFuZ2VzKElXaW5lRDNEVGV4dHVyZSAqaWZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IERXT1JEIHRleHR1cmVTdGF0ZXNbV0lORUQzRF9ISUdIRVNUX1RFWFRVUkVfU1RBVEUgKyAxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgRFdPUkQgc2FtcGxlclN0YXRlc1tXSU5FRDNEX0hJR0hFU1RfU0FNUExFUl9TVEFURSArIDFdKSB7CiAgICBUUkFDRSgiKCVwKSA6IHJlbGF5IHRvIEJhc2VUZXh0dXJlXG4iLCBpZmFjZSk7CiAgICBJV2luZUQzREJhc2VUZXh0dXJlSW1wbF9BcHBseVN0YXRlQ2hhbmdlcygoSVdpbmVEM0RCYXNlVGV4dHVyZSAqKWlmYWNlLCB0ZXh0dXJlU3RhdGVzLCBzYW1wbGVyU3RhdGVzKTsKfQoKLyogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogICBJV2luZUQzRFRleHR1cmUgSVdpbmVEM0RUZXh0dXJlIHBhcnRzIGZvbGxvdwogICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovCnN0YXRpYyB2b2lkIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0Rlc3Ryb3koSVdpbmVEM0RUZXh0dXJlICppZmFjZSwgRDNEQ0JfREVTVFJPWVNVUkZBQ0VGTiBEM0RDQl9EZXN0cm95U3VyZmFjZSkgewogICAgSVdpbmVEM0RUZXh0dXJlSW1wbCAqVGhpcyA9IChJV2luZUQzRFRleHR1cmVJbXBsICopaWZhY2U7CiAgICBpbnQgaTsKCiAgICBUUkFDRSgiKCVwKSA6IENsZWFuaW5nIHVwXG4iLFRoaXMpOwogICAgZm9yIChpID0gMDsgaSA8IFRoaXMtPmJhc2VUZXh0dXJlLmxldmVsczsgaSsrKSB7CiAgICAgICAgaWYgKFRoaXMtPnN1cmZhY2VzW2ldICE9IE5VTEwpIHsKICAgICAgICAgICAgLyogQ2xlYW4gb3V0IHRoZSB0ZXh0dXJlIG5hbWUgd2UgZ2F2ZSB0byB0aGUgc3VyZmFjZSBzbyB0aGF0IHRoZSBzdXJmYWNlIGRvZXNuJ3QgdHJ5IGFuZCByZWxlYXNlIGl0ICovCiAgICAgICAgICAgIElXaW5lRDNEU3VyZmFjZV9TZXRHbFRleHR1cmVEZXNjKFRoaXMtPnN1cmZhY2VzW2ldLCAwLCAwKTsKICAgICAgICAgICAgSVdpbmVEM0RTdXJmYWNlX1NldENvbnRhaW5lcihUaGlzLT5zdXJmYWNlc1tpXSwgMCk7CiAgICAgICAgICAgIEQzRENCX0Rlc3Ryb3lTdXJmYWNlKFRoaXMtPnN1cmZhY2VzW2ldKTsKICAgICAgICB9CiAgICB9CiAgICBUUkFDRSgiKCVwKSA6IGNsZWFuaW5nIHVwIGJhc2UgdGV4dHVyZVxuIiwgVGhpcyk7CiAgICBJV2luZUQzREJhc2VUZXh0dXJlSW1wbF9DbGVhblVwKChJV2luZUQzREJhc2VUZXh0dXJlICopaWZhY2UpOwogICAgLyogZnJlZSB0aGUgb2JqZWN0ICovCiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0TGV2ZWxEZXNjKElXaW5lRDNEVGV4dHVyZSAqaWZhY2UsIFVJTlQgTGV2ZWwsIFdJTkVEM0RTVVJGQUNFX0RFU0MqIHBEZXNjKSB7CiAgICBJV2luZUQzRFRleHR1cmVJbXBsICpUaGlzID0gKElXaW5lRDNEVGV4dHVyZUltcGwgKilpZmFjZTsKCiAgICBpZiAoTGV2ZWwgPCBUaGlzLT5iYXNlVGV4dHVyZS5sZXZlbHMpIHsKICAgICAgICBUUkFDRSgiKCVwKSBMZXZlbCAoJWQpXG4iLCBUaGlzLCBMZXZlbCk7CiAgICAgICAgcmV0dXJuIElXaW5lRDNEU3VyZmFjZV9HZXREZXNjKFRoaXMtPnN1cmZhY2VzW0xldmVsXSwgcERlc2MpOwogICAgfQogICAgRklYTUUoIiglcCkgbGV2ZWwoJWQpIG92ZXJmbG93IExldmVscyglZClcbiIsIFRoaXMsIExldmVsLCBUaGlzLT5iYXNlVGV4dHVyZS5sZXZlbHMpOwogICAgcmV0dXJuIFdJTkVEM0RFUlJfSU5WQUxJRENBTEw7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0dldFN1cmZhY2VMZXZlbChJV2luZUQzRFRleHR1cmUgKmlmYWNlLCBVSU5UIExldmVsLCBJV2luZUQzRFN1cmZhY2UqKiBwcFN1cmZhY2VMZXZlbCkgewogICAgSVdpbmVEM0RUZXh0dXJlSW1wbCAqVGhpcyA9IChJV2luZUQzRFRleHR1cmVJbXBsICopaWZhY2U7CiAgICBIUkVTVUxUIGhyID0gV0lORUQzREVSUl9JTlZBTElEQ0FMTDsKCiAgICBpZiAoTGV2ZWwgPCBUaGlzLT5iYXNlVGV4dHVyZS5sZXZlbHMpIHsKICAgICAgICAqcHBTdXJmYWNlTGV2ZWwgPSBUaGlzLT5zdXJmYWNlc1tMZXZlbF07CiAgICAgICAgSVdpbmVEM0RTdXJmYWNlX0FkZFJlZihUaGlzLT5zdXJmYWNlc1tMZXZlbF0pOwogICAgICAgIGhyID0gV0lORUQzRF9PSzsKICAgICAgICBUUkFDRSgiKCVwKSA6IHJldHVybmluZyAlcCBmb3IgbGV2ZWwgJWRcbiIsIFRoaXMsICpwcFN1cmZhY2VMZXZlbCwgTGV2ZWwpOwogICAgfQogICAgaWYgKFdJTkVEM0RfT0sgIT0gaHIpIHsKICAgICAgICBXQVJOKCIoJXApIGxldmVsKCVkKSBvdmVyZmxvdyBMZXZlbHMoJWQpXG4iLCBUaGlzLCBMZXZlbCwgVGhpcy0+YmFzZVRleHR1cmUubGV2ZWxzKTsKICAgICAgICAqcHBTdXJmYWNlTGV2ZWwgPSBOVUxMOyAvKiBKdXN0IHRvIGJlIG9uIHRoZSBzYWZlIHNpZGUuLiAqLwogICAgfQogICAgcmV0dXJuIGhyOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVdpbmVEM0RUZXh0dXJlSW1wbF9Mb2NrUmVjdChJV2luZUQzRFRleHR1cmUgKmlmYWNlLCBVSU5UIExldmVsLCBXSU5FRDNETE9DS0VEX1JFQ1QgKnBMb2NrZWRSZWN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENPTlNUIFJFQ1QgKnBSZWN0LCBEV09SRCBGbGFncykgewogICAgSVdpbmVEM0RUZXh0dXJlSW1wbCAqVGhpcyA9IChJV2luZUQzRFRleHR1cmVJbXBsICopaWZhY2U7CiAgICBIUkVTVUxUIGhyID0gV0lORUQzREVSUl9JTlZBTElEQ0FMTDsKCiAgICBpZiAoTGV2ZWwgPCBUaGlzLT5iYXNlVGV4dHVyZS5sZXZlbHMpIHsKICAgICAgICBociA9IElXaW5lRDNEU3VyZmFjZV9Mb2NrUmVjdChUaGlzLT5zdXJmYWNlc1tMZXZlbF0sIHBMb2NrZWRSZWN0LCBwUmVjdCwgRmxhZ3MpOwogICAgfQogICAgaWYgKFdJTkVEM0RfT0sgPT0gaHIpIHsKICAgICAgICBUUkFDRSgiKCVwKSBMZXZlbCAoJWQpIHN1Y2Nlc3NcbiIsIFRoaXMsIExldmVsKTsKICAgIH0gZWxzZSB7CiAgICAgICAgV0FSTigiKCVwKSBsZXZlbCglZCkgb3ZlcmZsb3cgTGV2ZWxzKCVkKVxuIiwgVGhpcywgTGV2ZWwsIFRoaXMtPmJhc2VUZXh0dXJlLmxldmVscyk7CiAgICB9CgogICAgcmV0dXJuIGhyOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVdpbmVEM0RUZXh0dXJlSW1wbF9VbmxvY2tSZWN0KElXaW5lRDNEVGV4dHVyZSAqaWZhY2UsIFVJTlQgTGV2ZWwpIHsKICAgSVdpbmVEM0RUZXh0dXJlSW1wbCAqVGhpcyA9IChJV2luZUQzRFRleHR1cmVJbXBsICopaWZhY2U7CiAgICBIUkVTVUxUIGhyID0gV0lORUQzREVSUl9JTlZBTElEQ0FMTDsKCiAgICBpZiAoTGV2ZWwgPCBUaGlzLT5iYXNlVGV4dHVyZS5sZXZlbHMpIHsKICAgICAgICBociA9IElXaW5lRDNEU3VyZmFjZV9VbmxvY2tSZWN0KFRoaXMtPnN1cmZhY2VzW0xldmVsXSk7CiAgICB9CiAgICBpZiAoIFdJTkVEM0RfT0sgPT0gaHIpIHsKICAgICAgICBUUkFDRSgiKCVwKSBMZXZlbCAoJWQpIHN1Y2Nlc3NcbiIsIFRoaXMsIExldmVsKTsKICAgIH0gZWxzZSB7CiAgICAgICAgV0FSTigiKCVwKSBsZXZlbCglZCkgb3ZlcmZsb3cgTGV2ZWxzKCVkKVxuIiwgVGhpcywgTGV2ZWwsIFRoaXMtPmJhc2VUZXh0dXJlLmxldmVscyk7CiAgICB9CiAgICByZXR1cm4gaHI7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJV2luZUQzRFRleHR1cmVJbXBsX0FkZERpcnR5UmVjdChJV2luZUQzRFRleHR1cmUgKmlmYWNlLCBDT05TVCBSRUNUKiBwRGlydHlSZWN0KSB7CiAgICBJV2luZUQzRFRleHR1cmVJbXBsICpUaGlzID0gKElXaW5lRDNEVGV4dHVyZUltcGwgKilpZmFjZTsKICAgIFRoaXMtPmJhc2VUZXh0dXJlLmRpcnR5ID0gVFJVRTsKICAgIFRSQUNFKCIoJXApIDogZGlydHlmaWNhdGlvbiBvZiBzdXJmYWNlIExldmVsICgwKVxuIiwgVGhpcyk7CiAgICByZXR1cm4gSVdpbmVEM0RTdXJmYWNlX0FkZERpcnR5UmVjdChUaGlzLT5zdXJmYWNlc1swXSwgcERpcnR5UmVjdCk7Cn0KCmNvbnN0IElXaW5lRDNEVGV4dHVyZVZ0YmwgSVdpbmVEM0RUZXh0dXJlX1Z0YmwgPQp7CiAgICAvKiBJVW5rbm93biAqLwogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9RdWVyeUludGVyZmFjZSwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfQWRkUmVmLAogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9SZWxlYXNlLAogICAgLyogSVdpbmVEM0RSZXNvdXJjZSAqLwogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9HZXRQYXJlbnQsCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX0dldERldmljZSwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfU2V0UHJpdmF0ZURhdGEsCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX0dldFByaXZhdGVEYXRhLAogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9GcmVlUHJpdmF0ZURhdGEsCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX1NldFByaW9yaXR5LAogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9HZXRQcmlvcml0eSwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfUHJlTG9hZCwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfVW5Mb2FkLAogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9HZXRUeXBlLAogICAgLyogSVdpbmVEM0RCYXNlVGV4dHVyZSAqLwogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9TZXRMT0QsCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX0dldExPRCwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0TGV2ZWxDb3VudCwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfU2V0QXV0b0dlbkZpbHRlclR5cGUsCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX0dldEF1dG9HZW5GaWx0ZXJUeXBlLAogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9HZW5lcmF0ZU1pcFN1YkxldmVscywKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfU2V0RGlydHksCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX0dldERpcnR5LAogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9CaW5kVGV4dHVyZSwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfVW5CaW5kVGV4dHVyZSwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0VGV4dHVyZURpbWVuc2lvbnMsCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX0FwcGx5U3RhdGVDaGFuZ2VzLAogICAgLyogSVdpbmVEM0RUZXh0dXJlICovCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX0Rlc3Ryb3ksCiAgICBJV2luZUQzRFRleHR1cmVJbXBsX0dldExldmVsRGVzYywKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfR2V0U3VyZmFjZUxldmVsLAogICAgSVdpbmVEM0RUZXh0dXJlSW1wbF9Mb2NrUmVjdCwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfVW5sb2NrUmVjdCwKICAgIElXaW5lRDNEVGV4dHVyZUltcGxfQWRkRGlydHlSZWN0Cn07Cg==