LyoKICogQ29weXJpZ2h0IDIwMDIgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxLCBVU0EKICovCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CgojaW5jbHVkZSAiZXh0cmFjaHVuay5oIgojaW5jbHVkZSAid2luYmFzZS5oIgojaW5jbHVkZSAid2luZ2RpLmgiCiNpbmNsdWRlICJ3aW51c2VyLmgiCiNpbmNsdWRlICJ2ZncuaCIKCiNpbmNsdWRlICJ3aW5lL2RlYnVnLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChhdmlmaWxlKTsKCi8qIHJlYWRzIGEgY2h1bmsgb3V0b2YgdGhlIGV4dHJhY2h1bmstc3RydWN0dXJlICovCkhSRVNVTFQgUmVhZEV4dHJhQ2h1bmsoTFBFWFRSQUNIVU5LUyBleHRyYSxGT1VSQ0MgY2tpZCxMUFZPSUQgbHBEYXRhLAoJCSAgICAgICBMUExPTkcgc2l6ZSkKewogIExQQllURSBscDsKICBEV09SRCAgY2I7CgogIC8qIHByZS1jb25kaXRpb25zICovCiAgYXNzZXJ0KGV4dHJhICE9IE5VTEwpOwogIGFzc2VydChzaXplICE9IE5VTEwpOwoKICBscCA9IGV4dHJhLT5scDsKICBjYiA9IGV4dHJhLT5jYjsKCiAgaWYgKGxwICE9IE5VTEwpIHsKICAgIHdoaWxlIChjYiA+IDApIHsKICAgICAgaWYgKCgoRk9VUkNDKilscClbMF0gPT0gY2tpZCkgewoJLyogZm91bmQgY29ycmVjdCBjaHVuayAqLwoJaWYgKGxwRGF0YSAhPSBOVUxMICYmICpzaXplID4gMCkKCSAgbWVtY3B5KGxwRGF0YSwgbHAgKyAyICogc2l6ZW9mKERXT1JEKSwKCQkgbWluKCgoTFBEV09SRClscClbMV0sICooTFBEV09SRClzaXplKSk7CgoJKihMUERXT1JEKXNpemUgPSAoKExQRFdPUkQpbHApWzFdOwoKCXJldHVybiBBVklFUlJfT0s7CiAgICAgIH0gZWxzZSB7CgkvKiBza2lwIHRvIG5leHQgY2h1bmsgKi8KCWNiIC09ICgoTFBEV09SRClscClbMV0gKyAyICogc2l6ZW9mKERXT1JEKTsKCWxwICs9ICgoTFBEV09SRClscClbMV0gKyAyICogc2l6ZW9mKERXT1JEKTsKICAgICAgfQogICAgfQogIH0KCiAgLyogd2FudGVkIGNodW5rIGRvZXNuJ3QgZXhpc3QgKi8KICAqc2l6ZSA9IDA7CgogIHJldHVybiBBVklFUlJfTk9EQVRBOwp9CgovKiB3cml0ZXMgYSBjaHVuayBpbnRvIHRoZSBleHRyYWNodW5rLXN0cnVjdHVyZSAqLwpIUkVTVUxUIFdyaXRlRXh0cmFDaHVuayhMUEVYVFJBQ0hVTktTIGV4dHJhLEZPVVJDQyBja2lkLExQVk9JRCBscERhdGEsCgkJCUxPTkcgc2l6ZSkKewogIExQRFdPUkQgbHA7CgogIC8qIHByZS1jb25kaXRpb25zICovCiAgYXNzZXJ0KGV4dHJhICE9IE5VTEwpOwogIGFzc2VydChscERhdGEgIT0gTlVMTCk7CiAgYXNzZXJ0KHNpemUgPiAwKTsKCiAgaWYgKGV4dHJhLT5scCkKICAgIGxwID0gSGVhcFJlQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgSEVBUF9aRVJPX01FTU9SWSwgZXh0cmEtPmxwLCBleHRyYS0+Y2IgKyBzaXplICsgMiAqIHNpemVvZihEV09SRCkpOwogIGVsc2UKICAgIGxwID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIEhFQVBfWkVST19NRU1PUlksIHNpemUgKyAyICogc2l6ZW9mKERXT1JEKSk7CgogIGlmIChscCA9PSBOVUxMKQogICAgcmV0dXJuIEFWSUVSUl9NRU1PUlk7CgogIGV4dHJhLT5scCAgPSBscDsKICBscCA9IChMUERXT1JEKSAoKExQQllURSlscCArIGV4dHJhLT5jYik7CiAgZXh0cmEtPmNiICs9IHNpemUgKyAyICogc2l6ZW9mKERXT1JEKTsKCiAgLyogaW5zZXJ0IGNodW5rLWhlYWRlciBpbiBibG9jayAqLwogIGxwWzBdID0gY2tpZDsKICBscFsxXSA9IHNpemU7CgogIGlmIChscERhdGEgIT0gTlVMTCAmJiBzaXplID4gMCkKICAgIG1lbWNweShscCArIDIsIGxwRGF0YSwgc2l6ZSk7CgogIHJldHVybiBBVklFUlJfT0s7Cn0KCi8qIHJlYWRzIGEgY2h1bmsgZm9tciB0aGUgSE1NSU8gaW50byB0aGUgZXh0cmFjaHVuay1zdHJ1Y3R1cmUgKi8KSFJFU1VMVCBSZWFkQ2h1bmtJbnRvRXh0cmEoTFBFWFRSQUNIVU5LUyBleHRyYSxITU1JTyBobW1pbyxNTUNLSU5GTyAqbHBjaykKewogIExQRFdPUkQgbHA7CiAgRFdPUkQgICBjYjsKCiAgLyogcHJlLWNvbmRpdGlvbnMgKi8KICBhc3NlcnQoZXh0cmEgIT0gTlVMTCk7CiAgYXNzZXJ0KGhtbWlvICE9IE5VTEwpOwogIGFzc2VydChscGNrICAhPSBOVUxMKTsKCiAgY2IgID0gbHBjay0+Y2tzaXplICsgMiAqIHNpemVvZihEV09SRCk7CiAgY2IgKz0gKGNiICYgMSk7CgogIGlmIChleHRyYS0+bHAgIT0gTlVMTCkKICAgIGxwID0gSGVhcFJlQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgSEVBUF9aRVJPX01FTU9SWSwgZXh0cmEtPmxwLCBleHRyYS0+Y2IgKyBjYik7CiAgZWxzZQogICAgbHAgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgSEVBUF9aRVJPX01FTU9SWSwgY2IpOwoKICBpZiAobHAgPT0gTlVMTCkKICAgIHJldHVybiBBVklFUlJfTUVNT1JZOwoKICBleHRyYS0+bHAgID0gbHA7CiAgbHAgPSAoTFBEV09SRCkgKChMUEJZVEUpbHAgKyBleHRyYS0+Y2IpOwogIGV4dHJhLT5jYiArPSBjYjsKCiAgLyogaW5zZXJ0IGNodW5rLWhlYWRlciBpbiBibG9jayAqLwogIGxwWzBdID0gbHBjay0+Y2tpZDsKICBscFsxXSA9IGxwY2stPmNrc2l6ZTsKCiAgaWYgKGxwY2stPmNrc2l6ZSA+IDApIHsKICAgIGlmIChtbWlvU2VlayhobW1pbywgbHBjay0+ZHdEYXRhT2Zmc2V0LCBTRUVLX1NFVCkgPT0gLTEpCiAgICAgIHJldHVybiBBVklFUlJfRklMRVJFQUQ7CiAgICBpZiAobW1pb1JlYWQoaG1taW8sIChIUFNUUikmbHBbMl0sIGxwY2stPmNrc2l6ZSkgIT0gKExPTkcpbHBjay0+Y2tzaXplKQogICAgICByZXR1cm4gQVZJRVJSX0ZJTEVSRUFEOwogIH0KCiAgcmV0dXJuIEFWSUVSUl9PSzsKfQoKLyogcmVhZHMgYWxsIG5vbi1qdW5rIGNodW5rcyBpbnRvIHRoZSBleHRyYWNodW5rLXN0cnVjdHVyZSB1bnRpbCBpdCBmaW5kcwogKiB0aGUgZ2l2ZW4gY2h1bmsgb3IgdGhlIG9wdGlvbmFsIHBhcmVudC1jaHVuayBpcyBhdCB0aGUgZW5kICovCkhSRVNVTFQgRmluZENodW5rQW5kS2VlcEV4dHJhcyhMUEVYVFJBQ0hVTktTIGV4dHJhLEhNTUlPIGhtbWlvLE1NQ0tJTkZPICpscGNrLAoJCQkgICAgICAgTU1DS0lORk8gKmxwY2tQYXJlbnQsVUlOVCBmbGFncykKewogIEZPVVJDQyAgY2tpZDsKICBGT1VSQ0MgIGZjY1R5cGU7CiAgSFJFU1VMVCBocjsKCiAgLyogcHJlLWNvbmRpdGlvbnMgKi8KICBhc3NlcnQoZXh0cmEgIT0gTlVMTCk7CiAgYXNzZXJ0KGhtbWlvICE9IE5VTEwpOwogIGFzc2VydChscGNrICAhPSBOVUxMKTsKCiAgVFJBQ0UoIih7JXAsJXV9LCVwLCVwLCVwLDB4JVgpXG4iLCBleHRyYS0+bHAsIGV4dHJhLT5jYiwgaG1taW8sIGxwY2ssCglscGNrUGFyZW50LCBmbGFncyk7CgogIC8qIHdoYXQgY2h1bmsgaWQgYW5kIGZvcm0vbGlzdCB0eXBlIHNob3VsZCB3ZSBzZWFyY2g/ICovCiAgaWYgKGZsYWdzICYgTU1JT19GSU5EQ0hVTkspIHsKICAgIGNraWQgICAgPSBscGNrLT5ja2lkOwogICAgZmNjVHlwZSA9IDA7CiAgfSBlbHNlIGlmIChmbGFncyAmIE1NSU9fRklORExJU1QpIHsKICAgIGNraWQgICAgPSBGT1VSQ0NfTElTVDsKICAgIGZjY1R5cGUgPSBscGNrLT5mY2NUeXBlOwogIH0gZWxzZSBpZiAoZmxhZ3MgJiBNTUlPX0ZJTkRSSUZGKSB7CiAgICBja2lkICAgID0gRk9VUkNDX1JJRkY7CiAgICBmY2NUeXBlID0gbHBjay0+ZmNjVHlwZTsKICB9IGVsc2UKICAgIGNraWQgPSBmY2NUeXBlID0gKEZPVVJDQyktMTsgLyogY29sbGVjdCBldmVyeXRoaW5nIGludG8gZXh0cmEhICovCgogIFRSQUNFKCI6IGZpbmQgY2tpZD0weCUwOFggZmNjVHlwZT0weCUwOFhcbiIsIGNraWQsIGZjY1R5cGUpOwoKICBmb3IgKDs7KSB7CiAgICBociA9IG1taW9EZXNjZW5kKGhtbWlvLCBscGNrLCBscGNrUGFyZW50LCAwKTsKICAgIGlmIChociAhPSBTX09LKSB7CiAgICAgIC8qIE5vIGV4dHJhIGNodW5rcyBpbiBmcm9udCBvZiBkZXNpcmVkIGNodW5rPyAqLwogICAgICBpZiAoZmxhZ3MgPT0gMCAmJiBociA9PSBNTUlPRVJSX0NIVU5LTk9URk9VTkQpCglociA9IEFWSUVSUl9PSzsKICAgICAgcmV0dXJuIGhyOwogICAgfQoKICAgIC8qIEhhdmUgd2UgZm91bmQgd2hhdCB3ZSBzZWFyY2ggZm9yPyAqLwogICAgaWYgKChscGNrLT5ja2lkID09IGNraWQpICYmCgkoZmNjVHlwZSA9PSAoRk9VUkNDKTAgfHwgbHBjay0+ZmNjVHlwZSA9PSBmY2NUeXBlKSkKICAgICAgcmV0dXJuIEFWSUVSUl9PSzsKCiAgICAvKiBTa2lwIHBhZGRpbmcgY2h1bmtzLCB0aGUgb3RoZXJzIHB1dCBpbnRvIHRoZSBleHRyYWNodW5rLXN0cnVjdHVyZSAqLwogICAgaWYgKGxwY2stPmNraWQgPT0gY2tpZEFWSVBBRERJTkcgfHwKCWxwY2stPmNraWQgPT0gbW1pb0ZPVVJDQygncCcsJ2EnLCdkJywnZCcpKQogICAgICBociA9IG1taW9Bc2NlbmQoaG1taW8sIGxwY2ssIDApOwogICAgZWxzZQogICAgICBociA9IFJlYWRDaHVua0ludG9FeHRyYShleHRyYSwgaG1taW8sIGxwY2spOwogICAgaWYgKEZBSUxFRChocikpCiAgICAgIHJldHVybiBocjsKICB9Cn0K