LyoJCURpcmVjdERyYXcgLSBJRGlyZWN0UGFsZXR0ZSBiYXNlIGludGVyZmFjZQogKgogKiBDb3B5cmlnaHQgMTk5Ny0yMDAwIE1hcmN1cyBNZWlzc25lcgogKiBDb3B5cmlnaHQgMjAwMC0yMDAxIFRyYW5zR2FtaW5nIFRlY2hub2xvZ2llcyBJbmMuCiAqIENvcHlyaWdodCAyMDA2IFN0ZWZhbiBE9nNpbmdlciBmb3IgQ29kZVdlYXZlcnMKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiAqLwojaW5jbHVkZSAiY29uZmlnLmgiCiNpbmNsdWRlICJ3aW5lcnJvci5oIgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSAid2luZWQzZF9wcml2YXRlLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChkM2QpOwoKI2RlZmluZSBTSVpFX0JJVFMgKEREUENBUFNfMUJJVCB8IEREUENBUFNfMkJJVCB8IEREUENBUFNfNEJJVCB8IEREUENBUFNfOEJJVCkKCkhSRVNVTFQgV0lOQVBJIElXaW5lRDNEUGFsZXR0ZUltcGxfUXVlcnlJbnRlcmZhY2UoSVdpbmVEM0RQYWxldHRlICppZmFjZSwgUkVGSUlEIHJlZmlpZCwgdm9pZCAqKm9iaikgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBUUkFDRSgiKCVwKS0+KCVzLCVwKVxuIixUaGlzLGRlYnVnc3RyX2d1aWQocmVmaWlkKSxvYmopOwoKICAgIGlmIChJc0VxdWFsR1VJRChyZWZpaWQsICZJSURfSVVua25vd24pCiAgICAgICAgfHwgSXNFcXVhbEdVSUQocmVmaWlkLCAmSUlEX0lXaW5lRDNEUGFsZXR0ZSkpIHsKICAgICAgICAqb2JqID0gaWZhY2U7CiAgICAgICAgSVdpbmVEM0RQYWxldHRlX0FkZFJlZihpZmFjZSk7CiAgICAgICAgcmV0dXJuIFNfT0s7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICAqb2JqID0gTlVMTDsKICAgICAgICByZXR1cm4gRV9OT0lOVEVSRkFDRTsKICAgIH0KfQoKVUxPTkcgV0lOQVBJIElXaW5lRDNEUGFsZXR0ZUltcGxfQWRkUmVmKElXaW5lRDNEUGFsZXR0ZSAqaWZhY2UpIHsKICAgIElXaW5lRDNEUGFsZXR0ZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RQYWxldHRlSW1wbCAqKWlmYWNlOwogICAgVUxPTkcgcmVmID0gSW50ZXJsb2NrZWRJbmNyZW1lbnQoJlRoaXMtPnJlZik7CgogICAgVFJBQ0UoIiglcCktPigpIGluY3JlbWVudGluZyBmcm9tICVsdS5cbiIsIFRoaXMsIHJlZiAtIDEpOwoKICAgIHJldHVybiByZWY7Cn0KClVMT05HIFdJTkFQSSBJV2luZUQzRFBhbGV0dGVJbXBsX1JlbGVhc2UoSVdpbmVEM0RQYWxldHRlICppZmFjZSkgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZERlY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgICBUUkFDRSgiKCVwKS0+KCkgZGVjcmVtZW50aW5nIGZyb20gJWx1LlxuIiwgVGhpcywgcmVmICsgMSk7CgogICAgaWYgKCFyZWYpIHsKICAgICAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzKTsKICAgICAgICByZXR1cm4gMDsKICAgIH0KCiAgICByZXR1cm4gcmVmOwp9CgovKiBOb3QgY2FsbGVkIGZyb20gdGhlIHZ0YWJsZSAqLwpEV09SRCBJV2luZUQzRFBhbGV0dGVJbXBsX1NpemUoRFdPUkQgZHdGbGFncykgewogICAgc3dpdGNoIChkd0ZsYWdzICYgU0laRV9CSVRTKSB7CiAgICAgICAgY2FzZSBERFBDQVBTXzFCSVQ6IHJldHVybiAyOwogICAgICAgIGNhc2UgRERQQ0FQU18yQklUOiByZXR1cm4gNDsKICAgICAgICBjYXNlIEREUENBUFNfNEJJVDogcmV0dXJuIDE2OwogICAgICAgIGNhc2UgRERQQ0FQU184QklUOiByZXR1cm4gMjU2OwogICAgICAgIGRlZmF1bHQ6IGFzc2VydCgwKTsgcmV0dXJuIDI1NjsKICAgIH0KfQoKSFJFU1VMVCBXSU5BUEkgSVdpbmVEM0RQYWxldHRlSW1wbF9HZXRFbnRyaWVzKElXaW5lRDNEUGFsZXR0ZSAqaWZhY2UsIERXT1JEIEZsYWdzLCBEV09SRCBTdGFydCwgRFdPUkQgQ291bnQsIFBBTEVUVEVFTlRSWSAqUGFsRW50KSB7CiAgICBJV2luZUQzRFBhbGV0dGVJbXBsICpUaGlzID0gKElXaW5lRDNEUGFsZXR0ZUltcGwgKilpZmFjZTsKCiAgICBUUkFDRSgiKCVwKS0+KCUwOGx4LCVsZCwlbGQsJXApXG4iLFRoaXMsRmxhZ3MsU3RhcnQsQ291bnQsUGFsRW50KTsKCiAgICBpZiAoRmxhZ3MgIT0gMCkgcmV0dXJuIFdJTkVEM0RFUlJfSU5WQUxJRENBTEw7IC8qIHVuY2hlY2tlZCAqLwogICAgaWYgKFN0YXJ0ICsgQ291bnQgPiBJV2luZUQzRFBhbGV0dGVJbXBsX1NpemUoVGhpcy0+RmxhZ3MpKQogICAgICAgIHJldHVybiBXSU5FRDNERVJSX0lOVkFMSURDQUxMOwoKICAgIGlmIChUaGlzLT5GbGFncyAmIEREUENBUFNfOEJJVEVOVFJJRVMpCiAgICB7CiAgICAgICAgdW5zaWduZWQgaW50IGk7CiAgICAgICAgTFBCWVRFIGVudHJ5ID0gKExQQllURSlQYWxFbnQ7CgogICAgICAgIGZvciAoaT1TdGFydDsgaSA8IENvdW50K1N0YXJ0OyBpKyspCiAgICAgICAgICAgICplbnRyeSsrID0gVGhpcy0+cGFsZW50c1tpXS5wZVJlZDsKICAgIH0KICAgIGVsc2UKICAgICAgICBtZW1jcHkoUGFsRW50LCBUaGlzLT5wYWxlbnRzK1N0YXJ0LCBDb3VudCAqIHNpemVvZihQQUxFVFRFRU5UUlkpKTsKCiAgICByZXR1cm4gV0lORUQzRF9PSzsKfQoKSFJFU1VMVCBXSU5BUEkgSVdpbmVEM0RQYWxldHRlSW1wbF9TZXRFbnRyaWVzKElXaW5lRDNEUGFsZXR0ZSAqaWZhY2UsIERXT1JEIEZsYWdzLCBEV09SRCBTdGFydCwgRFdPUkQgQ291bnQsIFBBTEVUVEVFTlRSWSAqUGFsRW50KQp7CiAgICBJV2luZUQzRFBhbGV0dGVJbXBsICpUaGlzID0gKElXaW5lRDNEUGFsZXR0ZUltcGwgKilpZmFjZTsKICAgIFJlc291cmNlTGlzdCAqcmVzOwoKICAgIFRSQUNFKCIoJXApLT4oJTA4bHgsJWxkLCVsZCwlcClcbiIsVGhpcyxGbGFncyxTdGFydCxDb3VudCxQYWxFbnQpOwoKICAgIGlmIChUaGlzLT5GbGFncyAmIEREUENBUFNfOEJJVEVOVFJJRVMpIHsKICAgICAgICB1bnNpZ25lZCBpbnQgaTsKICAgICAgICBjb25zdCBCWVRFKiBlbnRyeSA9IChjb25zdCBCWVRFKilQYWxFbnQ7CgogICAgICAgIGZvciAoaT1TdGFydDsgaSA8IENvdW50K1N0YXJ0OyBpKyspCiAgICAgICAgICAgIFRoaXMtPnBhbGVudHNbaV0ucGVSZWQgPSAqZW50cnkrKzsKICAgIH0KICAgIGVsc2UgewogICAgICAgIG1lbWNweShUaGlzLT5wYWxlbnRzK1N0YXJ0LCBQYWxFbnQsIENvdW50ICogc2l6ZW9mKFBBTEVUVEVFTlRSWSkpOwoKICAgICAgICBpZiAoVGhpcy0+aHBhbCkKICAgICAgICAgICAgU2V0UGFsZXR0ZUVudHJpZXMoVGhpcy0+aHBhbCwgU3RhcnQsIENvdW50LCBUaGlzLT5wYWxlbnRzK1N0YXJ0KTsKICAgIH0KCiNpZiAwCiAgICAvKiBOb3csIGlmIHdlIGFyZSBpbiAnZGVwdGggY29udmVyc2lvbiBtb2RlJywgdXBkYXRlIHRoZSBzY3JlZW4gcGFsZXR0ZSAqLwogICAgLyogRklYTUU6IHdlIG5lZWQgdG8gdXBkYXRlIHRoZSBpbWFnZSBvciB3ZSB3b24ndCBnZXQgcGFsZXR0ZSBmYWRpbmcuICovCiAgICBpZiAoVGhpcy0+ZGRyYXctPmQtPnBhbGV0dGVfY29udmVydCAhPSBOVUxMKQogICAgICAgIFRoaXMtPmRkcmF3LT5kLT5wYWxldHRlX2NvbnZlcnQocGFsZW50LFRoaXMtPnNjcmVlbl9wYWxlbnRzLHN0YXJ0LGNvdW50KTsKI2VuZGlmCgogICAgLyogSWYgdGhlIHBhbGV0dGUgaXMgYXR0YWNoZWQgdG8gdGhlIHJlbmRlciB0YXJnZXQsIHVwZGF0ZSBhbGwgcmVuZGVyIHRhcmdldHMgKi8KCiAgICBmb3IocmVzID0gVGhpcy0+d2luZUQzRERldmljZS0+cmVzb3VyY2VzOyByZXMgIT0gTlVMTDsgcmVzPXJlcy0+bmV4dCkgewogICAgICAgIGlmKElXaW5lRDNEUmVzb3VyY2VfR2V0VHlwZShyZXMtPnJlc291cmNlKSA9PSBEM0RSVFlQRV9TVVJGQUNFKSB7CiAgICAgICAgICAgIElXaW5lRDNEU3VyZmFjZUltcGwgKmltcGwgPSAoSVdpbmVEM0RTdXJmYWNlSW1wbCAqKSByZXMtPnJlc291cmNlOwogICAgICAgICAgICBpZihpbXBsLT5wYWxldHRlID09IFRoaXMpCiAgICAgICAgICAgICAgICBJV2luZUQzRFN1cmZhY2VfUmVhbGl6ZVBhbGV0dGUoIChJV2luZUQzRFN1cmZhY2UgKikgcmVzLT5yZXNvdXJjZSk7CiAgICAgICAgfQogICAgfQoKICAgIC8qIElmIHRoZSBwYWxldHRlIGlzIHRoZSBwcmltYXJ5IHBhbGV0dGUsIHNldCB0aGUgZW50cmllcyB0byB0aGUgZGV2aWNlICovCiAgICBpZihUaGlzLT5GbGFncyAmIEREUENBUFNfUFJJTUFSWVNVUkZBQ0UpIHsKICAgICAgICB1bnNpZ25lZCBpbnQgaTsKICAgICAgICBJV2luZUQzRERldmljZUltcGwgKmRldmljZSA9IFRoaXMtPndpbmVEM0REZXZpY2U7CiAgICAgICAgUEFMRVRURUVOVFJZICplbnRyeSA9IFBhbEVudDsKCiAgICAgICAgZm9yKGkgPSBTdGFydDsgaSA8IFN0YXJ0K0NvdW50OyBpKyspIHsKICAgICAgICAgICAgZGV2aWNlLT5wYWxldHRlc1tkZXZpY2UtPmN1cnJlbnRQYWxldHRlXVtpXSA9ICplbnRyeSsrOwogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gV0lORUQzRF9PSzsKfQoKSFJFU1VMVCBXSU5BUEkgSVdpbmVEM0RQYWxldHRlSW1wbF9HZXRDYXBzKElXaW5lRDNEUGFsZXR0ZSAqaWZhY2UsIERXT1JEICpDYXBzKSB7CiAgICBJV2luZUQzRFBhbGV0dGVJbXBsICpUaGlzID0gKElXaW5lRDNEUGFsZXR0ZUltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXApLT4oJXApXG4iLCBUaGlzLCBDYXBzKTsKCiAgICAqQ2FwcyA9IFRoaXMtPkZsYWdzOwogICAgcmV0dXJuIFdJTkVEM0RfT0s7Cn0KCkhSRVNVTFQgV0lOQVBJIElXaW5lRDNEUGFsZXR0ZUltcGxfR2V0UGFyZW50KElXaW5lRDNEUGFsZXR0ZSAqaWZhY2UsIElVbmtub3duICoqUGFyZW50KSB7CiAgICBJV2luZUQzRFBhbGV0dGVJbXBsICpUaGlzID0gKElXaW5lRDNEUGFsZXR0ZUltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXApLT4oJXApXG4iLCBUaGlzLCBQYXJlbnQpOwoKICAgICpQYXJlbnQgPSAoSVVua25vd24gKikgVGhpcy0+cGFyZW50OwogICAgSVVua25vd25fQWRkUmVmKCAoSVVua25vd24gKikgVGhpcy0+cGFyZW50KTsKICAgIHJldHVybiBXSU5FRDNEX09LOwp9Cgpjb25zdCBJV2luZUQzRFBhbGV0dGVWdGJsIElXaW5lRDNEUGFsZXR0ZV9WdGJsID0KewogICAgLyoqKiBJVW5rbm93biAqKiovCiAgICBJV2luZUQzRFBhbGV0dGVJbXBsX1F1ZXJ5SW50ZXJmYWNlLAogICAgSVdpbmVEM0RQYWxldHRlSW1wbF9BZGRSZWYsCiAgICBJV2luZUQzRFBhbGV0dGVJbXBsX1JlbGVhc2UsCiAgICAvKioqIElXaW5lRDNEUGFsZXR0ZSAqKiovCiAgICBJV2luZUQzRFBhbGV0dGVJbXBsX0dldFBhcmVudCwKICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfR2V0RW50cmllcywKICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfR2V0Q2FwcywKICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfU2V0RW50cmllcwp9Owo=