LyoKICogQ29weXJpZ2h0IDIwMDMgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxLCBVU0EKICovCgojaW5jbHVkZSA8c3RkYXJnLmg+CgojaW5jbHVkZSAid2luZGVmLmgiCiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5nZGkuaCIKI2luY2x1ZGUgIndpbnVzZXIuaCIKI2luY2x1ZGUgIndpbmVycm9yLmgiCiNpbmNsdWRlICJ2ZncuaCIKCiNpbmNsdWRlICJhdmlmaWxlX3ByaXZhdGUuaCIKI2luY2x1ZGUgImV4dHJhY2h1bmsuaCIKCiNpbmNsdWRlICJ3aW5lL2RlYnVnLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChhdmlmaWxlKTsKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mblF1ZXJ5SW50ZXJmYWNlKElBVklGaWxlKiBpZmFjZSxSRUZJSUQgcmVmaWlkLExQVk9JRCAqb2JqKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIElUbXBGaWxlX2ZuQWRkUmVmKElBVklGaWxlKiBpZmFjZSk7CnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJVG1wRmlsZV9mblJlbGVhc2UoSUFWSUZpbGUqIGlmYWNlKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuSW5mbyhJQVZJRmlsZSppZmFjZSxBVklGSUxFSU5GT1cqYWZpLExPTkcgc2l6ZSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkdldFN0cmVhbShJQVZJRmlsZSppZmFjZSxQQVZJU1RSRUFNKmF2aXMsRFdPUkQgZmNjVHlwZSxMT05HIGxQYXJhbSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkNyZWF0ZVN0cmVhbShJQVZJRmlsZSppZmFjZSxQQVZJU1RSRUFNKmF2aXMsQVZJU1RSRUFNSU5GT1cqYXNpKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuV3JpdGVEYXRhKElBVklGaWxlKmlmYWNlLERXT1JEIGNraWQsTFBWT0lEIGxwRGF0YSxMT05HIHNpemUpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5SZWFkRGF0YShJQVZJRmlsZSppZmFjZSxEV09SRCBja2lkLExQVk9JRCBscERhdGEsTE9ORyAqc2l6ZSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkVuZFJlY29yZChJQVZJRmlsZSppZmFjZSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkRlbGV0ZVN0cmVhbShJQVZJRmlsZSppZmFjZSxEV09SRCBmY2NUeXBlLExPTkcgbFBhcmFtKTsKCnN0YXRpYyBjb25zdCBzdHJ1Y3QgSUFWSUZpbGVWdGJsIGl0bXBmdCA9IHsKICBJVG1wRmlsZV9mblF1ZXJ5SW50ZXJmYWNlLAogIElUbXBGaWxlX2ZuQWRkUmVmLAogIElUbXBGaWxlX2ZuUmVsZWFzZSwKICBJVG1wRmlsZV9mbkluZm8sCiAgSVRtcEZpbGVfZm5HZXRTdHJlYW0sCiAgSVRtcEZpbGVfZm5DcmVhdGVTdHJlYW0sCiAgSVRtcEZpbGVfZm5Xcml0ZURhdGEsCiAgSVRtcEZpbGVfZm5SZWFkRGF0YSwKICBJVG1wRmlsZV9mbkVuZFJlY29yZCwKICBJVG1wRmlsZV9mbkRlbGV0ZVN0cmVhbQp9OwoKdHlwZWRlZiBzdHJ1Y3QgX0lUbXBGaWxlSW1wbCB7CiAgLyogSVVua25vd24gc3R1ZmYgKi8KICBjb25zdCBJQVZJRmlsZVZ0YmwgKmxwVnRibDsKICBMT05HICAgICAgICAgcmVmOwoKICAvKiBJQVZJRmlsZSBzdHVmZiAqLwogIEFWSUZJTEVJTkZPVyAgZkluZm87CiAgUEFWSVNUUkVBTSAgICpwcFN0cmVhbXM7Cn0gSVRtcEZpbGVJbXBsOwoKUEFWSUZJTEUgQVZJRklMRV9DcmVhdGVBVklUZW1wRmlsZShpbnQgblN0cmVhbXMsIGNvbnN0IFBBVklTVFJFQU0gKnBwU3RyZWFtcykgewogIElUbXBGaWxlSW1wbCAqdG1wRmlsZTsKICBpbnQgICAgICAgICAgIGk7CgogIHRtcEZpbGUgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgSEVBUF9aRVJPX01FTU9SWSwgc2l6ZW9mKElUbXBGaWxlSW1wbCkpOwogIGlmICh0bXBGaWxlID09IE5VTEwpCiAgICByZXR1cm4gTlVMTDsKCiAgdG1wRmlsZS0+bHBWdGJsID0gJml0bXBmdDsKICB0bXBGaWxlLT5yZWYgICAgPSAxOwogIG1lbXNldCgmdG1wRmlsZS0+ZkluZm8sIDAsIHNpemVvZih0bXBGaWxlLT5mSW5mbykpOwoKICB0bXBGaWxlLT5mSW5mby5kd1N0cmVhbXMgPSBuU3RyZWFtczsKICB0bXBGaWxlLT5wcFN0cmVhbXMgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgblN0cmVhbXMgKiBzaXplb2YoUEFWSVNUUkVBTSkpOwogIGlmICh0bXBGaWxlLT5wcFN0cmVhbXMgPT0gTlVMTCkgewogICAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgdG1wRmlsZSk7CiAgICByZXR1cm4gTlVMTDsKICB9CgogIGZvciAoaSA9IDA7IGkgPCBuU3RyZWFtczsgaSsrKSB7CiAgICBBVklTVFJFQU1JTkZPVyBzSW5mbzsKCiAgICB0bXBGaWxlLT5wcFN0cmVhbXNbaV0gPSBwcFN0cmVhbXNbaV07CgogICAgQVZJU3RyZWFtQWRkUmVmKHBwU3RyZWFtc1tpXSk7CiAgICBBVklTdHJlYW1JbmZvVyhwcFN0cmVhbXNbaV0sICZzSW5mbywgc2l6ZW9mKHNJbmZvKSk7CiAgICBpZiAoaSA9PSAwKSB7CiAgICAgIHRtcEZpbGUtPmZJbmZvLmR3U2NhbGUgPSBzSW5mby5kd1NjYWxlOwogICAgICB0bXBGaWxlLT5mSW5mby5kd1JhdGUgID0gc0luZm8uZHdSYXRlOwogICAgICBpZiAoIXNJbmZvLmR3U2NhbGUgfHwgIXNJbmZvLmR3UmF0ZSkgewoJdG1wRmlsZS0+ZkluZm8uZHdTY2FsZSA9IDE7Cgl0bXBGaWxlLT5mSW5mby5kd1JhdGUgID0gMTAwOwogICAgICB9CiAgICB9CgogICAgaWYgKHRtcEZpbGUtPmZJbmZvLmR3U3VnZ2VzdGVkQnVmZmVyU2l6ZSA8IHNJbmZvLmR3U3VnZ2VzdGVkQnVmZmVyU2l6ZSkKICAgICAgdG1wRmlsZS0+ZkluZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplID0gc0luZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplOwoKICAgIHsKICAgICAgcmVnaXN0ZXIgRFdPUkQgdG1wOwoKICAgICAgdG1wID0gTXVsRGl2KEFWSVN0cmVhbVNhbXBsZVRvVGltZShwcFN0cmVhbXNbaV0sIHNJbmZvLmR3TGVuZ3RoKSwKCQkgICB0bXBGaWxlLT5mSW5mby5kd1NjYWxlLCB0bXBGaWxlLT5mSW5mby5kd1JhdGUgKiAxMDAwKTsKICAgICAgaWYgKHRtcEZpbGUtPmZJbmZvLmR3TGVuZ3RoIDwgdG1wKQoJdG1wRmlsZS0+ZkluZm8uZHdMZW5ndGggPSB0bXA7CgogICAgICB0bXAgPSBzSW5mby5yY0ZyYW1lLnJpZ2h0IC0gc0luZm8ucmNGcmFtZS5sZWZ0OwogICAgICBpZiAodG1wRmlsZS0+ZkluZm8uZHdXaWR0aCA8IHRtcCkKCXRtcEZpbGUtPmZJbmZvLmR3V2lkdGggPSB0bXA7CiAgICAgIHRtcCA9IHNJbmZvLnJjRnJhbWUuYm90dG9tIC0gc0luZm8ucmNGcmFtZS50b3A7CiAgICAgIGlmICh0bXBGaWxlLT5mSW5mby5kd0hlaWdodCA8IHRtcCkKCXRtcEZpbGUtPmZJbmZvLmR3SGVpZ2h0ID0gdG1wOwogICAgfQogIH0KCiAgcmV0dXJuIChQQVZJRklMRSl0bXBGaWxlOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5RdWVyeUludGVyZmFjZShJQVZJRmlsZSAqaWZhY2UsIFJFRklJRCByZWZpaWQsCgkJCQkJCUxQVk9JRCAqb2JqKQp7CiAgSVRtcEZpbGVJbXBsICpUaGlzID0gKElUbXBGaWxlSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVzLCVwKVxuIiwgVGhpcywgZGVidWdzdHJfZ3VpZChyZWZpaWQpLCBvYmopOwoKICBpZiAoSXNFcXVhbEdVSUQoJklJRF9JVW5rbm93biwgcmVmaWlkKSB8fAogICAgICBJc0VxdWFsR1VJRCgmSUlEX0lBVklGaWxlLCByZWZpaWQpKSB7CiAgICAqb2JqID0gaWZhY2U7CiAgICBJQVZJRmlsZV9BZGRSZWYoaWZhY2UpOwoKICAgIHJldHVybiBTX09LOwogIH0KCiAgcmV0dXJuIE9MRV9FX0VOVU1fTk9NT1JFOwp9CgpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSVRtcEZpbGVfZm5BZGRSZWYoSUFWSUZpbGUgKmlmYWNlKQp7CiAgSVRtcEZpbGVJbXBsICpUaGlzID0gKElUbXBGaWxlSW1wbCAqKWlmYWNlOwogIFVMT05HIHJlZiA9IEludGVybG9ja2VkSW5jcmVtZW50KCZUaGlzLT5yZWYpOwoKICBUUkFDRSgiKCVwKSAtPiAlZFxuIiwgaWZhY2UsIHJlZik7CgogIHJldHVybiByZWY7Cn0KCnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJVG1wRmlsZV9mblJlbGVhc2UoSUFWSUZpbGUgKmlmYWNlKQp7CiAgSVRtcEZpbGVJbXBsICpUaGlzID0gKElUbXBGaWxlSW1wbCAqKWlmYWNlOwogIFVMT05HIHJlZiA9IEludGVybG9ja2VkRGVjcmVtZW50KCZUaGlzLT5yZWYpOwoKICBUUkFDRSgiKCVwKSAtPiAlZFxuIiwgaWZhY2UsIHJlZik7CgogIGlmICghcmVmKSB7CiAgICB1bnNpZ25lZCBpbnQgaTsKCiAgICBmb3IgKGkgPSAwOyBpIDwgVGhpcy0+ZkluZm8uZHdTdHJlYW1zOyBpKyspIHsKICAgICAgaWYgKFRoaXMtPnBwU3RyZWFtc1tpXSAhPSBOVUxMKSB7CglBVklTdHJlYW1SZWxlYXNlKFRoaXMtPnBwU3RyZWFtc1tpXSk7CgoJVGhpcy0+cHBTdHJlYW1zW2ldID0gTlVMTDsKICAgICAgfQogICAgfQoKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIFRoaXMpOwogICAgcmV0dXJuIDA7CiAgfQoKICByZXR1cm4gcmVmOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5JbmZvKElBVklGaWxlICppZmFjZSwKCQkJCSAgICAgIEFWSUZJTEVJTkZPVyAqYWZpLCBMT05HIHNpemUpCnsKICBJVG1wRmlsZUltcGwgKlRoaXMgPSAoSVRtcEZpbGVJbXBsICopaWZhY2U7CgogIFRSQUNFKCIoJXAsJXAsJWQpXG4iLGlmYWNlLGFmaSxzaXplKTsKCiAgaWYgKGFmaSA9PSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9CQURQQVJBTTsKICBpZiAoc2l6ZSA8IDApCiAgICByZXR1cm4gQVZJRVJSX0JBRFNJWkU7CgogIG1lbWNweShhZmksICZUaGlzLT5mSW5mbywgbWluKChEV09SRClzaXplLCBzaXplb2YoVGhpcy0+ZkluZm8pKSk7CgogIGlmICgoRFdPUkQpc2l6ZSA8IHNpemVvZihUaGlzLT5mSW5mbykpCiAgICByZXR1cm4gQVZJRVJSX0JVRkZFUlRPT1NNQUxMOwogIHJldHVybiBBVklFUlJfT0s7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkdldFN0cmVhbShJQVZJRmlsZSAqaWZhY2UsIFBBVklTVFJFQU0gKmF2aXMsCgkJCQkJICAgRFdPUkQgZmNjVHlwZSwgTE9ORyBsUGFyYW0pCnsKICBJVG1wRmlsZUltcGwgKlRoaXMgPSAoSVRtcEZpbGVJbXBsICopaWZhY2U7CgogIFVMT05HIG5TdHJlYW0gPSAoVUxPTkcpLTE7CgogIFRSQUNFKCIoJXAsJXAsMHglMDhYLCVkKVxuIiwgaWZhY2UsIGF2aXMsIGZjY1R5cGUsIGxQYXJhbSk7CgogIGlmIChhdmlzID09IE5VTEwgfHwgbFBhcmFtIDwgMCkKICAgIHJldHVybiBBVklFUlJfQkFEUEFSQU07CgogIGlmIChmY2NUeXBlICE9IHN0cmVhbXR5cGVBTlkpIHsKICAgIC8qIHNlYXJjaCB0aGUgbnVtYmVyIG9mIHRoZSBzcGVjaWZpZWQgc3RyZWFtICovCiAgICBVTE9ORyBpOwoKICAgIGZvciAoaSA9IDA7IGkgPCBUaGlzLT5mSW5mby5kd1N0cmVhbXM7IGkrKykgewogICAgICBBVklTVFJFQU1JTkZPVyBzSW5mbzsKICAgICAgSFJFU1VMVCAgICAgICAgaHI7CgogICAgICBociA9IEFWSVN0cmVhbUluZm9XKFRoaXMtPnBwU3RyZWFtc1tpXSwgJnNJbmZvLCBzaXplb2Yoc0luZm8pKTsKICAgICAgaWYgKEZBSUxFRChocikpCglyZXR1cm4gaHI7CgogICAgICBpZiAoc0luZm8uZmNjVHlwZSA9PSBmY2NUeXBlKSB7CglpZiAobFBhcmFtID09IDApIHsKCSAgblN0cmVhbSA9IGk7CgkgIGJyZWFrOwoJfSBlbHNlCgkgIGxQYXJhbS0tOwogICAgICB9CiAgICB9CiAgfSBlbHNlCiAgICBuU3RyZWFtID0gbFBhcmFtOwoKICAvKiBEb2VzIHRoZSByZXF1ZXN0ZWQgc3RyZWFtIGV4aXN0ID8gKi8KICBpZiAoblN0cmVhbSA8IFRoaXMtPmZJbmZvLmR3U3RyZWFtcyAmJiBUaGlzLT5wcFN0cmVhbXNbblN0cmVhbV0gIT0gTlVMTCkgewogICAgKmF2aXMgPSBUaGlzLT5wcFN0cmVhbXNbblN0cmVhbV07CiAgICBBVklTdHJlYW1BZGRSZWYoKmF2aXMpOwoKICAgIHJldHVybiBBVklFUlJfT0s7CiAgfQoKICAvKiBTb3JyeSwgYnV0IHRoZSBzcGVjaWZpZWQgc3RyZWFtIGRvZXNuJ3QgZXhpc3QgKi8KICByZXR1cm4gQVZJRVJSX05PREFUQTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuQ3JlYXRlU3RyZWFtKElBVklGaWxlICppZmFjZSxQQVZJU1RSRUFNICphdmlzLAoJCQkJCSAgICAgIEFWSVNUUkVBTUlORk9XICphc2kpCnsKICBUUkFDRSgiKCVwLCVwLCVwKVxuIixpZmFjZSxhdmlzLGFzaSk7CgogIHJldHVybiBBVklFUlJfVU5TVVBQT1JURUQ7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbldyaXRlRGF0YShJQVZJRmlsZSAqaWZhY2UsIERXT1JEIGNraWQsCgkJCQkJICAgTFBWT0lEIGxwRGF0YSwgTE9ORyBzaXplKQp7CiAgVFJBQ0UoIiglcCwweCUwOFgsJXAsJWQpXG4iLCBpZmFjZSwgY2tpZCwgbHBEYXRhLCBzaXplKTsKCiAgcmV0dXJuIEFWSUVSUl9VTlNVUFBPUlRFRDsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuUmVhZERhdGEoSUFWSUZpbGUgKmlmYWNlLCBEV09SRCBja2lkLAoJCQkJCSAgTFBWT0lEIGxwRGF0YSwgTE9ORyAqc2l6ZSkKewogIFRSQUNFKCIoJXAsMHglMDhYLCVwLCVwKVxuIiwgaWZhY2UsIGNraWQsIGxwRGF0YSwgc2l6ZSk7CgogIHJldHVybiBBVklFUlJfVU5TVVBQT1JURUQ7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkVuZFJlY29yZChJQVZJRmlsZSAqaWZhY2UpCnsKICBUUkFDRSgiKCVwKVxuIixpZmFjZSk7CgogIHJldHVybiBBVklFUlJfT0s7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkRlbGV0ZVN0cmVhbShJQVZJRmlsZSAqaWZhY2UsIERXT1JEIGZjY1R5cGUsCgkJCQkJICAgICAgTE9ORyBsUGFyYW0pCnsKICBUUkFDRSgiKCVwLDB4JTA4WCwlZClcbiIsIGlmYWNlLCBmY2NUeXBlLCBsUGFyYW0pOwoKICByZXR1cm4gQVZJRVJSX1VOU1VQUE9SVEVEOwp9Cg==