LyoKICogV2luMzIga2VybmVsIGZ1bmN0aW9ucwogKgogKiBDb3B5cmlnaHQgMTk5NSBUaG9tYXMgU2FuZGZvcmQgPHQuZC5nLnNhbmRmb3JkQHByZHMtZ3JuLmRlbW9uLmNvLnVrPgogKiBDb3B5cmlnaHQgMTk5NSBNYXJ0aW4gdm9uIEz2d2lzCiAqLwoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8c3lzL3RpbWUuaD4KI2luY2x1ZGUgPHVuaXN0ZC5oPgojaW5jbHVkZSA8c3lzL21tYW4uaD4KI2luY2x1ZGUgIndpbmRvd3MuaCIKI2luY2x1ZGUgIndpbmVycm9yLmgiCiNpbmNsdWRlICJrZXJuZWwzMi5oIgojaW5jbHVkZSAiaGFuZGxlMzIuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgInN0ZGRlYnVnLmgiCiNpbmNsdWRlICJkZWJ1Zy5oIgoKI2RlZmluZSBIRUFQX1pFUk9fTUVNT1JZCTB4OAoKLyogRklYTUU6IHRoZXNlIGZ1bmN0aW9ucyBkbyAqbm90KiBpbXBsZW1lbnQgdGhlIHdpbjMyIEFQSSBwcm9wZXJseS4gVGhleQphcmUgaGVyZSBtZXJlbHkgYXMgImdldCB5b3UgZ29pbmciIGFpZHMgKi8KLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBIZWFwQWxsb2MJCQkoS0VSTkVMMzIuMjIyKQogKgogKi8KTFBWT0lEIFNJTVBMRV9IZWFwQWxsb2MoSEFORExFIGhIZWFwLCBEV09SRCBkd0ZsYWdzLCBEV09SRCBkd0J5dGVzKQoKewoJdm9pZCAqcmVzdWx0OwoKCXJlc3VsdCA9IG1hbGxvYyhkd0J5dGVzKTsKCWlmKHJlc3VsdCAmJiAoZHdGbGFncyAmIEhFQVBfWkVST19NRU1PUlkpKQoJCW1lbXNldChyZXN1bHQsIDAsIGR3Qnl0ZXMpOwoJcmV0dXJuIHJlc3VsdDsKfQoKSEFORExFMzIgSGVhcENyZWF0ZShEV09SRCBmbE9wdGlvbnMsIERXT1JEIGR3SW5pdGlhbFNpemUsIERXT1JEIGR3TWF4aW11bVNpemUpCnsKCUxQVk9JRCBzdGFydDsKCUhFQVBfT0JKRUNUICpyZXQ7CglIRUFQSVRFTV9PQkpFQ1QgKml0ZW07CglpZihkd0luaXRpYWxTaXplPDQwOTYpCgkJcmV0dXJuIDA7CglzdGFydCA9IFZpcnR1YWxBbGxvYygwLGR3TWF4aW11bVNpemUsIE1FTV9SRVNFUlZFLCBQQUdFX1JFQURXUklURSk7CglpZighc3RhcnQpCgkJcmV0dXJuIDA7CglpZighVmlydHVhbEFsbG9jKHN0YXJ0LGR3SW5pdGlhbFNpemUsIE1FTV9DT01NSVQsIFBBR0VfUkVBRFdSSVRFKSkKCXsKCQlWaXJ0dWFsRnJlZShzdGFydCxkd01heGltdW1TaXplLE1FTV9SRUxFQVNFKTsKCQlyZXR1cm4gMDsKCX0KCXJldD1DcmVhdGVLZXJuZWxPYmplY3Qoc2l6ZW9mKEhFQVBfT0JKRUNUKSk7CglyZXQtPmNvbW1vbi5tYWdpYz1LRVJORUxfT0JKRUNUX0hFQVA7CglyZXQtPnN0YXJ0PXN0YXJ0OwoJcmV0LT5zaXplPWR3SW5pdGlhbFNpemU7CglyZXQtPm1heGltdW09ZHdNYXhpbXVtU2l6ZTsKCXJldC0+ZmxhZ3M9ZmxPcHRpb25zOwoJaXRlbT1zdGFydDsKCWl0ZW0tPmNvbW1vbi5tYWdpYz1LRVJORUxfT0JKRUNUX0hFQVBJVEVNOwoJaXRlbS0+bmV4dD1pdGVtLT5wcmV2PTA7CglpdGVtLT5oZWFwPXJldDsKCglyZXQtPmZpcnN0PXJldC0+bGFzdD1pdGVtOwoKCXJldHVybiAoSEFORExFMzIpcmV0Owp9CgpCT09MIEhlYXBEZXN0cm95KEhFQVBfT0JKRUNUICpoKQp7CgkvKiBGSVhNRTogbGFzdCBlcnJvciAqLwoJaWYoaC0+Y29tbW9uLm1hZ2ljIT1LRVJORUxfT0JKRUNUX0hFQVApCgkJcmV0dXJuIDA7CgloLT5jb21tb24ubWFnaWM9MDsKCVZpcnR1YWxGcmVlKGgtPnN0YXJ0LGgtPnNpemUsTUVNX1JFTEVBU0UpOwoJUmVsZWFzZUtlcm5lbE9iamVjdChoKTsKCXJldHVybiAxOwp9CgoKc3RhdGljIEJPT0wgSEVBUF9Hcm93SGVhcChIRUFQX09CSkVDVCAqaCxEV09SRCBzaXplKQp7CglIRUFQSVRFTV9PQkpFQ1QgKmxhc3Q7CgkvKiBGSVhNRTogbGFzdCBlcnJvciAqLwoJaWYoc2l6ZSA+IGgtPm1heGltdW0taC0+c2l6ZSkKCQlyZXR1cm4gMDsKCWlmKCFWaXJ0dWFsQWxsb2MoaC0+c3RhcnQraC0+c2l6ZSxzaXplLE1FTV9DT01NSVQsUEFHRV9SRUFEV1JJVEUpKQoJCXJldHVybiAwOwoJLyogRklYTUU6IGNvbnNvbGlkYXRlIHdpdGggcHJldmlvdXMgaXRlbSAqLwoJbGFzdD1oLT5zdGFydCtzaXplOwoJaC0+c2l6ZSs9c2l6ZTsKCWgtPmxhc3QtPm5leHQ9bGFzdDsKCWxhc3QtPnByZXY9aC0+bGFzdDsKCWxhc3QtPm5leHQ9MDsKCWgtPmxhc3Q9bGFzdDsKCWxhc3QtPmNvbW1vbi5tYWdpYz1LRVJORUxfT0JKRUNUX0hFQVBJVEVNOwoJbGFzdC0+aGVhcD1oOwoJcmV0dXJuIDE7Cn0KCgpMUFZPSUQgSGVhcEFsbG9jKEhFQVBfT0JKRUNUICpoLERXT1JEIGR3RmxhZ3MsRFdPUkQgZHdCeXRlcykKewoJSEVBUElURU1fT0JKRUNUICppdCwqbmV4dCwqcHJldjsKCS8qIEZJWE1FOiBsYXN0IGVycm9yICovCglpZighaCkKCQlyZXR1cm4gU0lNUExFX0hlYXBBbGxvYyhoLGR3RmxhZ3MsZHdCeXRlcyk7CglpZihoLT5jb21tb24ubWFnaWMhPUtFUk5FTF9PQkpFQ1RfSEVBUCkKCQlyZXR1cm4gMDsKCS8qIGFsaWduIHRvIERXT1JEICovCglkd0J5dGVzID0gKGR3Qnl0ZXMgKyAzKSAmIH4zOwoJZm9yKGl0PWgtPmZpcnN0O2l0O2l0PWl0LT5uZXh0KQoJewoJCWlmKGl0LT5zaXplPmR3Qnl0ZXMrc2l6ZW9mKEhFQVBJVEVNX09CSkVDVCkpCgkJCWJyZWFrOwoJfQoJaWYoIWl0KQoJewoJCWlmKCFIRUFQX0dyb3dIZWFwKGgsZHdCeXRlcykpCgkJCXJldHVybiAwOwoJCWl0PWgtPmxhc3Q7Cgl9CgluZXh0ID0gaXQtPm5leHQ7CglwcmV2ID0gaXQtPnByZXY7CglpZihpdC0+c2l6ZSA+IGR3Qnl0ZXMrMipzaXplb2YoSEVBUElURU1fT0JKRUNUKSkKCXsJLyogc3BsaXQgaXRlbSAqLwoJCUhFQVBJVEVNX09CSkVDVCAqbmV4dD0oSEVBUElURU1fT0JKRUNUKikoKGNoYXIqKShpdCsxKStkd0J5dGVzKTsKCQluZXh0LT5jb21tb24ubWFnaWM9S0VSTkVMX09CSkVDVF9IRUFQSVRFTTsKCQluZXh0LT5zaXplPWl0LT5zaXplLXNpemVvZihIRUFQSVRFTV9PQkpFQ1QpLWR3Qnl0ZXM7CgkJbmV4dC0+bmV4dCA9IGl0LT5uZXh0OwoJfQoJaWYobmV4dCkKCQluZXh0LT5wcmV2PXByZXY7CgllbHNlCgkJaC0+bGFzdD1wcmV2OwoJaWYocHJldikKCQlwcmV2LT5uZXh0PW5leHQ7CgllbHNlCgkJaC0+Zmlyc3Q9bmV4dDsKCS8qIEFsbG9jYXRlZCBpdGVtIGlzIGRlbm90ZWQgYnkgc2VsZi1yZWZlcmVuY2luZyAqLwoJaXQtPm5leHQ9aXQtPnByZXY9aXQ7CglyZXR1cm4gKExQVk9JRCkoaXQrMSk7Cn0KCkJPT0wgSGVhcEZyZWUoSEVBUF9PQkpFQ1QgKmgsRFdPUkQgZHdGbGFncyxMUFZPSUQgbHBNZW0pCnsKCUhFQVBJVEVNX09CSkVDVCAqaXRlbSwqcHJldiwqbmV4dDsKCWl0ZW0gPSAoSEVBUElURU1fT0JKRUNUKilscE1lbSAtIDE7CglpZihpdGVtLT5jb21tb24ubWFnaWMgIT0gS0VSTkVMX09CSkVDVF9IRUFQKQoJCXJldHVybiAwOwoJZm9yKG5leHQ9aXRlbTsoY2FkZHJfdCluZXh0PChjYWRkcl90KWgtPnN0YXJ0K2gtPnNpemU7CgkJbmV4dD0oSEVBUElURU1fT0JKRUNUKikoKGNoYXIqKW5leHQrbmV4dC0+c2l6ZSkpCgkJaWYobmV4dCE9bmV4dC0+bmV4dCkKCQkJYnJlYWs7CglpZigoY2FkZHJfdCluZXh0Pj0oY2FkZHJfdCloLT5zdGFydCtoLT5zaXplKQoJCW5leHQ9MDsKCWlmKG5leHQpCgkJcHJldj1uZXh0LT5wcmV2OwoJZWxzZQoJCXByZXY9aC0+bGFzdDsKCS8qIGNvbnNvbGlkYXRlIHdpdGggcHJldmlvdXMgKi8KCWlmKHByZXYgJiYgKGNoYXIqKXByZXYrcHJldi0+c2l6ZT09KGNoYXIqKWl0ZW0pCgl7CgkJcHJldi0+c2l6ZSs9aXRlbS0+c2l6ZTsKCQlpdGVtPXByZXY7CgkJcHJldj1pdGVtLT5wcmV2OwoJfQoJLyogY29uc29saWRhdGUgd2l0aCBuZXh0ICovCglpZihuZXh0ICYmIChjaGFyKilpdGVtK2l0ZW0tPnNpemU9PShjaGFyKiluZXh0KQoJewoJCWl0ZW0tPnNpemUrPW5leHQtPnNpemU7CgkJbmV4dD1uZXh0LT5uZXh0OwoJfQoJaWYocHJldikKCXsKCQlpdGVtLT5wcmV2PXByZXY7CgkJcHJldi0+bmV4dD1pdGVtOwoJfSBlbHNlIAoJCWgtPmZpcnN0PWl0ZW07CglpZihuZXh0KQoJewoJCWl0ZW0tPm5leHQ9bmV4dDsKCQluZXh0LT5wcmV2PWl0ZW07Cgl9ZWxzZQoJCWgtPmxhc3Q9aXRlbTsKCXJldHVybiAxOwp9Cgo=