LyoKICogQ29weXJpZ2h0IDIwMDMgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxLCBVU0EKICovCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRhcmcuaD4KCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmdkaS5oIgojaW5jbHVkZSAid2ludXNlci5oIgojaW5jbHVkZSAid2lubmxzLmgiCiNpbmNsdWRlICJ3aW5lcnJvci5oIgojaW5jbHVkZSAibW1zeXN0ZW0uaCIKI2luY2x1ZGUgInZmdy5oIgoKI2luY2x1ZGUgImF2aWZpbGVfcHJpdmF0ZS5oIgojaW5jbHVkZSAiZXh0cmFjaHVuay5oIgoKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKGF2aWZpbGUpOwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuUXVlcnlJbnRlcmZhY2UoSUFWSUZpbGUqIGlmYWNlLFJFRklJRCByZWZpaWQsTFBWT0lEICpvYmopOwpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSVRtcEZpbGVfZm5BZGRSZWYoSUFWSUZpbGUqIGlmYWNlKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIElUbXBGaWxlX2ZuUmVsZWFzZShJQVZJRmlsZSogaWZhY2UpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5JbmZvKElBVklGaWxlKmlmYWNlLEFWSUZJTEVJTkZPVyphZmksTE9ORyBzaXplKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuR2V0U3RyZWFtKElBVklGaWxlKmlmYWNlLFBBVklTVFJFQU0qYXZpcyxEV09SRCBmY2NUeXBlLExPTkcgbFBhcmFtKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuQ3JlYXRlU3RyZWFtKElBVklGaWxlKmlmYWNlLFBBVklTVFJFQU0qYXZpcyxBVklTVFJFQU1JTkZPVyphc2kpOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5Xcml0ZURhdGEoSUFWSUZpbGUqaWZhY2UsRFdPUkQgY2tpZCxMUFZPSUQgbHBEYXRhLExPTkcgc2l6ZSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mblJlYWREYXRhKElBVklGaWxlKmlmYWNlLERXT1JEIGNraWQsTFBWT0lEIGxwRGF0YSxMT05HICpzaXplKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuRW5kUmVjb3JkKElBVklGaWxlKmlmYWNlKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuRGVsZXRlU3RyZWFtKElBVklGaWxlKmlmYWNlLERXT1JEIGZjY1R5cGUsTE9ORyBsUGFyYW0pOwoKc3RhdGljIGNvbnN0IHN0cnVjdCBJQVZJRmlsZVZ0YmwgaXRtcGZ0ID0gewogIElUbXBGaWxlX2ZuUXVlcnlJbnRlcmZhY2UsCiAgSVRtcEZpbGVfZm5BZGRSZWYsCiAgSVRtcEZpbGVfZm5SZWxlYXNlLAogIElUbXBGaWxlX2ZuSW5mbywKICBJVG1wRmlsZV9mbkdldFN0cmVhbSwKICBJVG1wRmlsZV9mbkNyZWF0ZVN0cmVhbSwKICBJVG1wRmlsZV9mbldyaXRlRGF0YSwKICBJVG1wRmlsZV9mblJlYWREYXRhLAogIElUbXBGaWxlX2ZuRW5kUmVjb3JkLAogIElUbXBGaWxlX2ZuRGVsZXRlU3RyZWFtCn07Cgp0eXBlZGVmIHN0cnVjdCBfSVRtcEZpbGVJbXBsIHsKICAvKiBJVW5rbm93biBzdHVmZiAqLwogIGNvbnN0IElBVklGaWxlVnRibCAqbHBWdGJsOwogIExPTkcgICAgICAgICByZWY7CgogIC8qIElBVklGaWxlIHN0dWZmICovCiAgQVZJRklMRUlORk9XICBmSW5mbzsKICBQQVZJU1RSRUFNICAgKnBwU3RyZWFtczsKfSBJVG1wRmlsZUltcGw7CgpQQVZJRklMRSBBVklGSUxFX0NyZWF0ZUFWSVRlbXBGaWxlKGludCBuU3RyZWFtcywgUEFWSVNUUkVBTSAqcHBTdHJlYW1zKSB7CiAgSVRtcEZpbGVJbXBsICp0bXBGaWxlOwogIGludCAgICAgICAgICAgaTsKCiAgdG1wRmlsZSA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCBIRUFQX1pFUk9fTUVNT1JZLCBzaXplb2YoSVRtcEZpbGVJbXBsKSk7CiAgaWYgKHRtcEZpbGUgPT0gTlVMTCkKICAgIHJldHVybiBOVUxMOwoKICB0bXBGaWxlLT5scFZ0YmwgPSAmaXRtcGZ0OwogIHRtcEZpbGUtPnJlZiAgICA9IDE7CiAgbWVtc2V0KCZ0bXBGaWxlLT5mSW5mbywgMCwgc2l6ZW9mKHRtcEZpbGUtPmZJbmZvKSk7CgogIHRtcEZpbGUtPmZJbmZvLmR3U3RyZWFtcyA9IG5TdHJlYW1zOwogIHRtcEZpbGUtPnBwU3RyZWFtcyA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCAwLCBuU3RyZWFtcyAqIHNpemVvZihQQVZJU1RSRUFNKSk7CiAgaWYgKHRtcEZpbGUtPnBwU3RyZWFtcyA9PSBOVUxMKSB7CiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCB0bXBGaWxlKTsKICAgIHJldHVybiBOVUxMOwogIH0KCiAgZm9yIChpID0gMDsgaSA8IG5TdHJlYW1zOyBpKyspIHsKICAgIEFWSVNUUkVBTUlORk9XIHNJbmZvOwoKICAgIHRtcEZpbGUtPnBwU3RyZWFtc1tpXSA9IHBwU3RyZWFtc1tpXTsKCiAgICBBVklTdHJlYW1BZGRSZWYocHBTdHJlYW1zW2ldKTsKICAgIEFWSVN0cmVhbUluZm9XKHBwU3RyZWFtc1tpXSwgJnNJbmZvLCBzaXplb2Yoc0luZm8pKTsKICAgIGlmIChpID09IDApIHsKICAgICAgdG1wRmlsZS0+ZkluZm8uZHdTY2FsZSA9IHNJbmZvLmR3U2NhbGU7CiAgICAgIHRtcEZpbGUtPmZJbmZvLmR3UmF0ZSAgPSBzSW5mby5kd1JhdGU7CiAgICAgIGlmICghc0luZm8uZHdTY2FsZSB8fCAhc0luZm8uZHdSYXRlKSB7Cgl0bXBGaWxlLT5mSW5mby5kd1NjYWxlID0gMTsKCXRtcEZpbGUtPmZJbmZvLmR3UmF0ZSAgPSAxMDA7CiAgICAgIH0KICAgIH0KCiAgICBpZiAodG1wRmlsZS0+ZkluZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplIDwgc0luZm8uZHdTdWdnZXN0ZWRCdWZmZXJTaXplKQogICAgICB0bXBGaWxlLT5mSW5mby5kd1N1Z2dlc3RlZEJ1ZmZlclNpemUgPSBzSW5mby5kd1N1Z2dlc3RlZEJ1ZmZlclNpemU7CgogICAgewogICAgICByZWdpc3RlciBEV09SRCB0bXA7CgogICAgICB0bXAgPSBNdWxEaXYoQVZJU3RyZWFtU2FtcGxlVG9UaW1lKHBwU3RyZWFtc1tpXSwgc0luZm8uZHdMZW5ndGgpLCBcCgkJICAgdG1wRmlsZS0+ZkluZm8uZHdTY2FsZSwgdG1wRmlsZS0+ZkluZm8uZHdSYXRlICogMTAwMCk7CiAgICAgIGlmICh0bXBGaWxlLT5mSW5mby5kd0xlbmd0aCA8IHRtcCkKCXRtcEZpbGUtPmZJbmZvLmR3TGVuZ3RoID0gdG1wOwoKICAgICAgdG1wID0gc0luZm8ucmNGcmFtZS5yaWdodCAtIHNJbmZvLnJjRnJhbWUubGVmdDsKICAgICAgaWYgKHRtcEZpbGUtPmZJbmZvLmR3V2lkdGggPCB0bXApCgl0bXBGaWxlLT5mSW5mby5kd1dpZHRoID0gdG1wOwogICAgICB0bXAgPSBzSW5mby5yY0ZyYW1lLmJvdHRvbSAtIHNJbmZvLnJjRnJhbWUudG9wOwogICAgICBpZiAodG1wRmlsZS0+ZkluZm8uZHdIZWlnaHQgPCB0bXApCgl0bXBGaWxlLT5mSW5mby5kd0hlaWdodCA9IHRtcDsKICAgIH0KICB9CgogIHJldHVybiAoUEFWSUZJTEUpdG1wRmlsZTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuUXVlcnlJbnRlcmZhY2UoSUFWSUZpbGUgKmlmYWNlLCBSRUZJSUQgcmVmaWlkLAoJCQkJCQlMUFZPSUQgKm9iaikKewogIElUbXBGaWxlSW1wbCAqVGhpcyA9IChJVG1wRmlsZUltcGwgKilpZmFjZTsKCiAgVFJBQ0UoIiglcCwlcywlcClcbiIsIFRoaXMsIGRlYnVnc3RyX2d1aWQocmVmaWlkKSwgb2JqKTsKCiAgaWYgKElzRXF1YWxHVUlEKCZJSURfSVVua25vd24sIHJlZmlpZCkgfHwKICAgICAgSXNFcXVhbEdVSUQoJklJRF9JQVZJRmlsZSwgcmVmaWlkKSkgewogICAgKm9iaiA9IGlmYWNlOwogICAgSUFWSUZpbGVfQWRkUmVmKGlmYWNlKTsKCiAgICByZXR1cm4gU19PSzsKICB9CgogIHJldHVybiBPTEVfRV9FTlVNX05PTU9SRTsKfQoKc3RhdGljIFVMT05HICAgV0lOQVBJIElUbXBGaWxlX2ZuQWRkUmVmKElBVklGaWxlICppZmFjZSkKewogIElUbXBGaWxlSW1wbCAqVGhpcyA9IChJVG1wRmlsZUltcGwgKilpZmFjZTsKICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZEluY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgVFJBQ0UoIiglcCkgLT4gJWRcbiIsIGlmYWNlLCByZWYpOwoKICByZXR1cm4gcmVmOwp9CgpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSVRtcEZpbGVfZm5SZWxlYXNlKElBVklGaWxlICppZmFjZSkKewogIElUbXBGaWxlSW1wbCAqVGhpcyA9IChJVG1wRmlsZUltcGwgKilpZmFjZTsKICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZERlY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgVFJBQ0UoIiglcCkgLT4gJWRcbiIsIGlmYWNlLCByZWYpOwoKICBpZiAoIXJlZikgewogICAgdW5zaWduZWQgaW50IGk7CgogICAgZm9yIChpID0gMDsgaSA8IFRoaXMtPmZJbmZvLmR3U3RyZWFtczsgaSsrKSB7CiAgICAgIGlmIChUaGlzLT5wcFN0cmVhbXNbaV0gIT0gTlVMTCkgewoJQVZJU3RyZWFtUmVsZWFzZShUaGlzLT5wcFN0cmVhbXNbaV0pOwoKCVRoaXMtPnBwU3RyZWFtc1tpXSA9IE5VTEw7CiAgICAgIH0KICAgIH0KCiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBUaGlzKTsKICAgIHJldHVybiAwOwogIH0KCiAgcmV0dXJuIHJlZjsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElUbXBGaWxlX2ZuSW5mbyhJQVZJRmlsZSAqaWZhY2UsCgkJCQkgICAgICBBVklGSUxFSU5GT1cgKmFmaSwgTE9ORyBzaXplKQp7CiAgSVRtcEZpbGVJbXBsICpUaGlzID0gKElUbXBGaWxlSW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVwLCVkKVxuIixpZmFjZSxhZmksc2l6ZSk7CgogIGlmIChhZmkgPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfQkFEUEFSQU07CiAgaWYgKHNpemUgPCAwKQogICAgcmV0dXJuIEFWSUVSUl9CQURTSVpFOwoKICBtZW1jcHkoYWZpLCAmVGhpcy0+ZkluZm8sIG1pbigoRFdPUkQpc2l6ZSwgc2l6ZW9mKFRoaXMtPmZJbmZvKSkpOwoKICBpZiAoKERXT1JEKXNpemUgPCBzaXplb2YoVGhpcy0+ZkluZm8pKQogICAgcmV0dXJuIEFWSUVSUl9CVUZGRVJUT09TTUFMTDsKICByZXR1cm4gQVZJRVJSX09LOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5HZXRTdHJlYW0oSUFWSUZpbGUgKmlmYWNlLCBQQVZJU1RSRUFNICphdmlzLAoJCQkJCSAgIERXT1JEIGZjY1R5cGUsIExPTkcgbFBhcmFtKQp7CiAgSVRtcEZpbGVJbXBsICpUaGlzID0gKElUbXBGaWxlSW1wbCAqKWlmYWNlOwoKICBVTE9ORyBuU3RyZWFtID0gKFVMT05HKS0xOwoKICBUUkFDRSgiKCVwLCVwLDB4JTA4WCwlZClcbiIsIGlmYWNlLCBhdmlzLCBmY2NUeXBlLCBsUGFyYW0pOwoKICBpZiAoYXZpcyA9PSBOVUxMIHx8IGxQYXJhbSA8IDApCiAgICByZXR1cm4gQVZJRVJSX0JBRFBBUkFNOwoKICBpZiAoZmNjVHlwZSAhPSBzdHJlYW10eXBlQU5ZKSB7CiAgICAvKiBzZWFyY2ggdGhlIG51bWJlciBvZiB0aGUgc3BlY2lmaWVkIHN0cmVhbSAqLwogICAgVUxPTkcgaTsKCiAgICBmb3IgKGkgPSAwOyBpIDwgVGhpcy0+ZkluZm8uZHdTdHJlYW1zOyBpKyspIHsKICAgICAgQVZJU1RSRUFNSU5GT1cgc0luZm87CiAgICAgIEhSRVNVTFQgICAgICAgIGhyOwoKICAgICAgaHIgPSBBVklTdHJlYW1JbmZvVyhUaGlzLT5wcFN0cmVhbXNbaV0sICZzSW5mbywgc2l6ZW9mKHNJbmZvKSk7CiAgICAgIGlmIChGQUlMRUQoaHIpKQoJcmV0dXJuIGhyOwoKICAgICAgaWYgKHNJbmZvLmZjY1R5cGUgPT0gZmNjVHlwZSkgewoJaWYgKGxQYXJhbSA9PSAwKSB7CgkgIG5TdHJlYW0gPSBpOwoJICBicmVhazsKCX0gZWxzZQoJICBsUGFyYW0tLTsKICAgICAgfQogICAgfQogIH0gZWxzZQogICAgblN0cmVhbSA9IGxQYXJhbTsKCiAgLyogRG9lcyB0aGUgcmVxdWVzdGVkIHN0cmVhbSBleGlzdCA/ICovCiAgaWYgKG5TdHJlYW0gPCBUaGlzLT5mSW5mby5kd1N0cmVhbXMgJiYgVGhpcy0+cHBTdHJlYW1zW25TdHJlYW1dICE9IE5VTEwpIHsKICAgICphdmlzID0gVGhpcy0+cHBTdHJlYW1zW25TdHJlYW1dOwogICAgQVZJU3RyZWFtQWRkUmVmKCphdmlzKTsKCiAgICByZXR1cm4gQVZJRVJSX09LOwogIH0KCiAgLyogU29ycnksIGJ1dCB0aGUgc3BlY2lmaWVkIHN0cmVhbSBkb2Vzbid0IGV4aXN0ICovCiAgcmV0dXJuIEFWSUVSUl9OT0RBVEE7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mbkNyZWF0ZVN0cmVhbShJQVZJRmlsZSAqaWZhY2UsUEFWSVNUUkVBTSAqYXZpcywKCQkJCQkgICAgICBBVklTVFJFQU1JTkZPVyAqYXNpKQp7CiAgVFJBQ0UoIiglcCwlcCwlcClcbiIsaWZhY2UsYXZpcyxhc2kpOwoKICByZXR1cm4gQVZJRVJSX1VOU1VQUE9SVEVEOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5Xcml0ZURhdGEoSUFWSUZpbGUgKmlmYWNlLCBEV09SRCBja2lkLAoJCQkJCSAgIExQVk9JRCBscERhdGEsIExPTkcgc2l6ZSkKewogIFRSQUNFKCIoJXAsMHglMDhYLCVwLCVkKVxuIiwgaWZhY2UsIGNraWQsIGxwRGF0YSwgc2l6ZSk7CgogIHJldHVybiBBVklFUlJfVU5TVVBQT1JURUQ7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJVG1wRmlsZV9mblJlYWREYXRhKElBVklGaWxlICppZmFjZSwgRFdPUkQgY2tpZCwKCQkJCQkgIExQVk9JRCBscERhdGEsIExPTkcgKnNpemUpCnsKICBUUkFDRSgiKCVwLDB4JTA4WCwlcCwlcClcbiIsIGlmYWNlLCBja2lkLCBscERhdGEsIHNpemUpOwoKICByZXR1cm4gQVZJRVJSX1VOU1VQUE9SVEVEOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5FbmRSZWNvcmQoSUFWSUZpbGUgKmlmYWNlKQp7CiAgVFJBQ0UoIiglcClcbiIsaWZhY2UpOwoKICByZXR1cm4gQVZJRVJSX09LOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSVRtcEZpbGVfZm5EZWxldGVTdHJlYW0oSUFWSUZpbGUgKmlmYWNlLCBEV09SRCBmY2NUeXBlLAoJCQkJCSAgICAgIExPTkcgbFBhcmFtKQp7CiAgVFJBQ0UoIiglcCwweCUwOFgsJWQpXG4iLCBpZmFjZSwgZmNjVHlwZSwgbFBhcmFtKTsKCiAgcmV0dXJuIEFWSUVSUl9VTlNVUFBPUlRFRDsKfQo=