LyoKICogQ29weXJpZ2h0IDIwMDMgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojZGVmaW5lIENPTV9OT19XSU5ET1dTX0gKI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8c3RkYXJnLmg+CgojaW5jbHVkZSAid2luZGVmLmgiCiNpbmNsdWRlICJ3aW5iYXNlLmgiCiNpbmNsdWRlICJ3aW5nZGkuaCIKI2luY2x1ZGUgIndpbnVzZXIuaCIKI2luY2x1ZGUgIndpbm5scy5oIgojaW5jbHVkZSAid2luZXJyb3IuaCIKI2luY2x1ZGUgIndpbmRvd3N4LmgiCiNpbmNsdWRlICJtbXN5c3RlbS5oIgojaW5jbHVkZSAidmZ3LmgiCgojaW5jbHVkZSAiYXZpZmlsZV9wcml2YXRlLmgiCiNpbmNsdWRlICJleHRyYWNodW5rLmgiCgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKV0lORV9ERUZBVUxUX0RFQlVHX0NIQU5ORUwoYXZpZmlsZSk7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5RdWVyeUludGVyZmFjZShJQVZJRmlsZSogaWZhY2UsUkVGSUlEIHJlZmlpZCxMUFZPSUQgKm9iaik7CnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJVG1wRmlsZV9mbkFkZFJlZihJQVZJRmlsZSogaWZhY2UpOwpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSVRtcEZpbGVfZm5SZWxlYXNlKElBVklGaWxlKiBpZmFjZSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkluZm8oSUFWSUZpbGUqaWZhY2UsQVZJRklMRUlORk9XKmFmaSxMT05HIHNpemUpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5HZXRTdHJlYW0oSUFWSUZpbGUqaWZhY2UsUEFWSVNUUkVBTSphdmlzLERXT1JEIGZjY1R5cGUsTE9ORyBsUGFyYW0pOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5DcmVhdGVTdHJlYW0oSUFWSUZpbGUqaWZhY2UsUEFWSVNUUkVBTSphdmlzLEFWSVNUUkVBTUlORk9XKmFzaSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbldyaXRlRGF0YShJQVZJRmlsZSppZmFjZSxEV09SRCBja2lkLExQVk9JRCBscERhdGEsTE9ORyBzaXplKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuUmVhZERhdGEoSUFWSUZpbGUqaWZhY2UsRFdPUkQgY2tpZCxMUFZPSUQgbHBEYXRhLExPTkcgKnNpemUpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5FbmRSZWNvcmQoSUFWSUZpbGUqaWZhY2UpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5EZWxldGVTdHJlYW0oSUFWSUZpbGUqaWZhY2UsRFdPUkQgZmNjVHlwZSxMT05HIGxQYXJhbSk7CgpzdGF0aWMgY29uc3Qgc3RydWN0IElBVklGaWxlVnRibCBpdG1wZnQgPSB7CiAgSVRtcEZpbGVfZm5RdWVyeUludGVyZmFjZSwKICBJVG1wRmlsZV9mbkFkZFJlZiwKICBJVG1wRmlsZV9mblJlbGVhc2UsCiAgSVRtcEZpbGVfZm5JbmZvLAogIElUbXBGaWxlX2ZuR2V0U3RyZWFtLAogIElUbXBGaWxlX2ZuQ3JlYXRlU3RyZWFtLAogIElUbXBGaWxlX2ZuV3JpdGVEYXRhLAogIElUbXBGaWxlX2ZuUmVhZERhdGEsCiAgSVRtcEZpbGVfZm5FbmRSZWNvcmQsCiAgSVRtcEZpbGVfZm5EZWxldGVTdHJlYW0KfTsKCnR5cGVkZWYgc3RydWN0IF9JVG1wRmlsZUltcGwgewogIC8qIElVbmtub3duIHN0dWZmICovCiAgY29uc3QgSUFWSUZpbGVWdGJsICpscFZ0Ymw7CiAgRFdPUkQgICAgICAgICByZWY7CgogIC8qIElBVklGaWxlIHN0dWZmICovCiAgQVZJRklMRUlORk9XICBmSW5mbzsKICBQQVZJU1RSRUFNICAgKnBwU3RyZWFtczsKfSBJVG1wRmlsZUltcGw7CgpQQVZJRklMRSBBVklGSUxFX0NyZWF0ZUFWSVRlbXBGaWxlKGludCBuU3RyZWFtcywgUEFWSVNUUkVBTSAqcHBTdHJlYW1zKSB7CiAgSVRtcEZpbGVJbXBsICp0bXBGaWxlOwogIGludCAgICAgICAgICAgaTsKCiAgdG1wRmlsZSA9IExvY2FsQWxsb2MoTFBUUiwgc2l6ZW9mKElUbXBGaWxlSW1wbCkpOwogIGlmICh0bXBGaWxlID09IE5VTEwpCiAgICByZXR1cm4gTlVMTDsKCiAgdG1wRmlsZS0+bHBWdGJsID0gJml0bXBmdDsKICB0bXBGaWxlLT5yZWYgICAgPSAxOwogIG1lbXNldCgmdG1wRmlsZS0+ZkluZm8sIDAsIHNpemVvZih0bXBGaWxlLT5mSW5mbykpOwoKICB0bXBGaWxlLT5mSW5mby5kd1N0cmVhbXMgPSBuU3RyZWFtczsKICB0bXBGaWxlLT5wcFN0cmVhbXMgPSBMb2NhbEFsbG9jKExQVFIsIG5TdHJlYW1zICogc2l6ZW9mKFBBVklTVFJFQU0pKTsKICBpZiAodG1wRmlsZS0+cHBTdHJlYW1zID09IE5VTEwpIHsKICAgIExvY2FsRnJlZSgoSExPQ0FMKXRtcEZpbGUpOwogICAgcmV0dXJuIE5VTEw7CiAgfQoKICBmb3IgKGkgPSAwOyBpIDwgblN0cmVhbXM7IGkrKykgewogICAgQVZJU1RSRUFNSU5GT1cgc0luZm87CgogICAgdG1wRmlsZS0+cHBTdHJlYW1zW2ldID0gcHBTdHJlYW1zW2ldOwoKICAgIEFWSVN0cmVhbUFkZFJlZihwcFN0cmVhbXNbaV0pOwogICAgQVZJU3RyZWFtSW5mb1cocHBTdHJlYW1zW2ldLCAmc0luZm8sIHNpemVvZihzSW5mbykpOwogICAgaWYgKGkgPT0gMCkgewogICAgICB0bXBGaWxlLT5mSW5mby5kd1NjYWxlID0gc0luZm8uZHdTY2FsZTsKICAgICAgdG1wRmlsZS0+ZkluZm8uZHdSYXRlICA9IHNJbmZvLmR3UmF0ZTsKICAgICAgaWYgKCFzSW5mby5kd1NjYWxlIHx8ICFzSW5mby5kd1JhdGUpIHsKCXRtcEZpbGUtPmZJbmZvLmR3U2NhbGUgPSAxOwoJdG1wRmlsZS0+ZkluZm8uZHdSYXRlICA9IDEwMDsKICAgICAgfQogICAgfQoKICAgIGlmICh0bXBGaWxlLT5mSW5mby5kd1N1Z2dlc3RlZEJ1ZmZlclNpemUgPCBzSW5mby5kd1N1Z2dlc3RlZEJ1ZmZlclNpemUpCiAgICAgIHRtcEZpbGUtPmZJbmZvLmR3U3VnZ2VzdGVkQnVmZmVyU2l6ZSA9IHNJbmZvLmR3U3VnZ2VzdGVkQnVmZmVyU2l6ZTsKCiAgICB7CiAgICAgIHJlZ2lzdGVyIERXT1JEIHRtcDsKCiAgICAgIHRtcCA9IE11bERpdihBVklTdHJlYW1TYW1wbGVUb1RpbWUocHBTdHJlYW1zW2ldLCBzSW5mby5kd0xlbmd0aCksIFwKCQkgICB0bXBGaWxlLT5mSW5mby5kd1NjYWxlLCB0bXBGaWxlLT5mSW5mby5kd1JhdGUgKiAxMDAwKTsKICAgICAgaWYgKHRtcEZpbGUtPmZJbmZvLmR3TGVuZ3RoIDwgdG1wKQoJdG1wRmlsZS0+ZkluZm8uZHdMZW5ndGggPSB0bXA7CgogICAgICB0bXAgPSBzSW5mby5yY0ZyYW1lLnJpZ2h0IC0gc0luZm8ucmNGcmFtZS5sZWZ0OwogICAgICBpZiAodG1wRmlsZS0+ZkluZm8uZHdXaWR0aCA8IHRtcCkKCXRtcEZpbGUtPmZJbmZvLmR3V2lkdGggPSB0bXA7CiAgICAgIHRtcCA9IHNJbmZvLnJjRnJhbWUuYm90dG9tIC0gc0luZm8ucmNGcmFtZS50b3A7CiAgICAgIGlmICh0bXBGaWxlLT5mSW5mby5kd0hlaWdodCA8IHRtcCkKCXRtcEZpbGUtPmZJbmZvLmR3SGVpZ2h0ID0gdG1wOwogICAgfQogIH0KCiAgcmV0dXJuIChQQVZJRklMRSl0bXBGaWxlOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5RdWVyeUludGVyZmFjZShJQVZJRmlsZSAqaWZhY2UsIFJFRklJRCByZWZpaWQsCgkJCQkJCUxQVk9JRCAqb2JqKQp7CiAgSVRtcEZpbGVJbXBsICpUaGlzID0gKElUbXBGaWxlSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVzLCVwKVxuIiwgVGhpcywgZGVidWdzdHJfZ3VpZChyZWZpaWQpLCBvYmopOwoKICBpZiAoSXNFcXVhbEdVSUQoJklJRF9JVW5rbm93biwgcmVmaWlkKSB8fAogICAgICBJc0VxdWFsR1VJRCgmSUlEX0lBVklGaWxlLCByZWZpaWQpKSB7CiAgICAqb2JqID0gaWZhY2U7CiAgICBJQVZJRmlsZV9BZGRSZWYoaWZhY2UpOwoKICAgIHJldHVybiBTX09LOwogIH0KCiAgcmV0dXJuIE9MRV9FX0VOVU1fTk9NT1JFOwp9CgpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSVRtcEZpbGVfZm5BZGRSZWYoSUFWSUZpbGUgKmlmYWNlKQp7CiAgSVRtcEZpbGVJbXBsICpUaGlzID0gKElUbXBGaWxlSW1wbCAqKWlmYWNlOwogIFVMT05HIHJlZiA9IEludGVybG9ja2VkSW5jcmVtZW50KCZUaGlzLT5yZWYpOwoKICBUUkFDRSgiKCVwKSAtPiAlbGRcbiIsIGlmYWNlLCByZWYpOwoKICByZXR1cm4gcmVmOwp9CgpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSVRtcEZpbGVfZm5SZWxlYXNlKElBVklGaWxlICppZmFjZSkKewogIElUbXBGaWxlSW1wbCAqVGhpcyA9IChJVG1wRmlsZUltcGwgKilpZmFjZTsKICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZERlY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgVFJBQ0UoIiglcCkgLT4gJWxkXG4iLCBpZmFjZSwgcmVmKTsKCiAgaWYgKCFyZWYpIHsKICAgIHVuc2lnbmVkIGludCBpOwoKICAgIGZvciAoaSA9IDA7IGkgPCBUaGlzLT5mSW5mby5kd1N0cmVhbXM7IGkrKykgewogICAgICBpZiAoVGhpcy0+cHBTdHJlYW1zW2ldICE9IE5VTEwpIHsKCUFWSVN0cmVhbVJlbGVhc2UoVGhpcy0+cHBTdHJlYW1zW2ldKTsKCglUaGlzLT5wcFN0cmVhbXNbaV0gPSBOVUxMOwogICAgICB9CiAgICB9CgogICAgTG9jYWxGcmVlKChITE9DQUwpVGhpcyk7CiAgICByZXR1cm4gMDsKICB9CgogIHJldHVybiByZWY7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkluZm8oSUFWSUZpbGUgKmlmYWNlLAoJCQkJICAgICAgQVZJRklMRUlORk9XICphZmksIExPTkcgc2l6ZSkKewogIElUbXBGaWxlSW1wbCAqVGhpcyA9IChJVG1wRmlsZUltcGwgKilpZmFjZTsKCiAgVFJBQ0UoIiglcCwlcCwlbGQpXG4iLGlmYWNlLGFmaSxzaXplKTsKCiAgaWYgKGFmaSA9PSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9CQURQQVJBTTsKICBpZiAoc2l6ZSA8IDApCiAgICByZXR1cm4gQVZJRVJSX0JBRFNJWkU7CgogIG1lbWNweShhZmksICZUaGlzLT5mSW5mbywgbWluKChEV09SRClzaXplLCBzaXplb2YoVGhpcy0+ZkluZm8pKSk7CgogIGlmICgoRFdPUkQpc2l6ZSA8IHNpemVvZihUaGlzLT5mSW5mbykpCiAgICByZXR1cm4gQVZJRVJSX0JVRkZFUlRPT1NNQUxMOwogIHJldHVybiBBVklFUlJfT0s7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkdldFN0cmVhbShJQVZJRmlsZSAqaWZhY2UsIFBBVklTVFJFQU0gKmF2aXMsCgkJCQkJICAgRFdPUkQgZmNjVHlwZSwgTE9ORyBsUGFyYW0pCnsKICBJVG1wRmlsZUltcGwgKlRoaXMgPSAoSVRtcEZpbGVJbXBsICopaWZhY2U7CgogIFVMT05HIG5TdHJlYW0gPSAoVUxPTkcpLTE7CgogIFRSQUNFKCIoJXAsJXAsMHglMDhsWCwlbGQpXG4iLCBpZmFjZSwgYXZpcywgZmNjVHlwZSwgbFBhcmFtKTsKCiAgaWYgKGF2aXMgPT0gTlVMTCB8fCBsUGFyYW0gPCAwKQogICAgcmV0dXJuIEFWSUVSUl9CQURQQVJBTTsKCiAgaWYgKGZjY1R5cGUgIT0gc3RyZWFtdHlwZUFOWSkgewogICAgLyogc2VhcmNoIHRoZSBudW1iZXIgb2YgdGhlIHNwZWNpZmllZCBzdHJlYW0gKi8KICAgIFVMT05HIGk7CgogICAgZm9yIChpID0gMDsgaSA8IFRoaXMtPmZJbmZvLmR3U3RyZWFtczsgaSsrKSB7CiAgICAgIEFWSVNUUkVBTUlORk9XIHNJbmZvOwogICAgICBIUkVTVUxUICAgICAgICBocjsKCiAgICAgIGhyID0gQVZJU3RyZWFtSW5mb1coVGhpcy0+cHBTdHJlYW1zW2ldLCAmc0luZm8sIHNpemVvZihzSW5mbykpOwogICAgICBpZiAoRkFJTEVEKGhyKSkKCXJldHVybiBocjsKCiAgICAgIGlmIChzSW5mby5mY2NUeXBlID09IGZjY1R5cGUpIHsKCWlmIChsUGFyYW0gPT0gMCkgewoJICBuU3RyZWFtID0gaTsKCSAgYnJlYWs7Cgl9IGVsc2UKCSAgbFBhcmFtLS07CiAgICAgIH0KICAgIH0KICB9IGVsc2UKICAgIG5TdHJlYW0gPSBsUGFyYW07CgogIC8qIERvZXMgdGhlIHJlcXVlc3RlZCBzdHJlYW0gZXhpc3QgPyAqLwogIGlmIChuU3RyZWFtIDwgVGhpcy0+ZkluZm8uZHdTdHJlYW1zICYmIFRoaXMtPnBwU3RyZWFtc1tuU3RyZWFtXSAhPSBOVUxMKSB7CiAgICAqYXZpcyA9IFRoaXMtPnBwU3RyZWFtc1tuU3RyZWFtXTsKICAgIEFWSVN0cmVhbUFkZFJlZigqYXZpcyk7CgogICAgcmV0dXJuIEFWSUVSUl9PSzsKICB9CgogIC8qIFNvcnJ5LCBidXQgdGhlIHNwZWNpZmllZCBzdHJlYW0gZG9lc24ndCBleGlzdCAqLwogIHJldHVybiBBVklFUlJfTk9EQVRBOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5DcmVhdGVTdHJlYW0oSUFWSUZpbGUgKmlmYWNlLFBBVklTVFJFQU0gKmF2aXMsCgkJCQkJICAgICAgQVZJU1RSRUFNSU5GT1cgKmFzaSkKewogIFRSQUNFKCIoJXAsJXAsJXApXG4iLGlmYWNlLGF2aXMsYXNpKTsKCiAgcmV0dXJuIEFWSUVSUl9VTlNVUFBPUlRFRDsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuV3JpdGVEYXRhKElBVklGaWxlICppZmFjZSwgRFdPUkQgY2tpZCwKCQkJCQkgICBMUFZPSUQgbHBEYXRhLCBMT05HIHNpemUpCnsKICBUUkFDRSgiKCVwLDB4JTA4bFgsJXAsJWxkKVxuIiwgaWZhY2UsIGNraWQsIGxwRGF0YSwgc2l6ZSk7CgogIHJldHVybiBBVklFUlJfVU5TVVBQT1JURUQ7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mblJlYWREYXRhKElBVklGaWxlICppZmFjZSwgRFdPUkQgY2tpZCwKCQkJCQkgIExQVk9JRCBscERhdGEsIExPTkcgKnNpemUpCnsKICBUUkFDRSgiKCVwLDB4JTA4bFgsJXAsJXApXG4iLCBpZmFjZSwgY2tpZCwgbHBEYXRhLCBzaXplKTsKCiAgcmV0dXJuIEFWSUVSUl9VTlNVUFBPUlRFRDsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuRW5kUmVjb3JkKElBVklGaWxlICppZmFjZSkKewogIFRSQUNFKCIoJXApXG4iLGlmYWNlKTsKCiAgcmV0dXJuIEFWSUVSUl9PSzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuRGVsZXRlU3RyZWFtKElBVklGaWxlICppZmFjZSwgRFdPUkQgZmNjVHlwZSwKCQkJCQkgICAgICBMT05HIGxQYXJhbSkKewogIFRSQUNFKCIoJXAsMHglMDhsWCwlbGQpXG4iLCBpZmFjZSwgZmNjVHlwZSwgbFBhcmFtKTsKCiAgcmV0dXJuIEFWSUVSUl9VTlNVUFBPUlRFRDsKfQo=