I2luY2x1ZGUgIlZpZGVvRHJpdmVyUHJpdmF0ZS5oIgojaW5jbHVkZSAiVmlkZW9Ecml2ZXJQcm90b3R5cGVzLmgiCiNpbmNsdWRlICJEcml2ZXJRRENhbGxzLmgiCiNpbmNsdWRlICJRZW11VmdhLmgiCgojZGVmaW5lIE1BWF9ERVBUSF9NT0RFCWtEZXB0aE1vZGUzCgpzdGF0aWMgVUludDggRGVwdGhUb0RlcHRoTW9kZShVSW50OCBkZXB0aCkKewoJc3dpdGNoIChkZXB0aCkgewoJY2FzZSA4OgoJCXJldHVybiBrRGVwdGhNb2RlMTsKCWNhc2UgMTU6CgljYXNlIDE2OgoJCXJldHVybiBrRGVwdGhNb2RlMjsKCWNhc2UgMjQ6CgljYXNlIDMyOgoJCXJldHVybiBrRGVwdGhNb2RlMzsKCWRlZmF1bHQ6CgkJcmV0dXJuIGtEZXB0aE1vZGUxOwoJfQp9CgpzdGF0aWMgVUludDggRGVwdGhNb2RlVG9EZXB0aChVSW50OCBtb2RlKQp7Cglzd2l0Y2ggKG1vZGUpIHsKCWNhc2Uga0RlcHRoTW9kZTE6CgkJcmV0dXJuIDMyOwoJY2FzZSBrRGVwdGhNb2RlMjoKCQlyZXR1cm4gMTU7CgljYXNlIGtEZXB0aE1vZGUzOgoJCXJldHVybiAzMjsKCWRlZmF1bHQ6CgkJcmV0dXJuIDg7Cgl9Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKiogQ29sb3IgVGFibGUgU3R1ZmYgKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCnN0YXRpYyBPU1N0YXR1cwpHcmFwaGljc0NvcmVEb1NldEVudHJpZXMoVkRTZXRFbnRyeVJlY29yZCAqZW50cnlSZWNvcmQsIEJvb2xlYW4gZGlyZWN0RGV2aWNlLCBVSW50MzIgc3RhcnQsIFVJbnQzMiBzdG9wLCBCb29sZWFuIHVzZVZhbHVlKQp7CglVSW50MzIgaTsKCQoJQ0hFQ0tfT1BFTiggY29udHJvbEVyciApOwoJaWYgKEdMT0JBTC5kZXB0aCAhPSA4KQoJCXJldHVybiBjb250cm9sRXJyOwoJaWYgKE5VTEwgPT0gZW50cnlSZWNvcmQtPmNzVGFibGUpCgkJcmV0dXJuIGNvbnRyb2xFcnI7CgkKCS8qIE5vdGUgdGhhdCBzdG9wIHZhbHVlIGlzIGluY2x1ZGVkIGluIHRoZSByYW5nZSAqLwoJZm9yKGk9c3RhcnQ7aTw9c3RvcDtpKyspIHsKCQlVSW50MzIJY29sb3JJbmRleCA9IHVzZVZhbHVlID8gZW50cnlSZWNvcmQtPmNzVGFibGVbaV0udmFsdWUgOiBpOwoJCVFlbXVWZ2FfU2V0Q29sb3JFbnRyeShjb2xvckluZGV4LCAmZW50cnlSZWNvcmQtPmNzVGFibGVbaV0ucmdiKTsKCX0KCQoJcmV0dXJuIG5vRXJyOwp9CgpPU1N0YXR1cwpHcmFwaGljc0NvcmVTZXRFbnRyaWVzKFZEU2V0RW50cnlSZWNvcmQgKmVudHJ5UmVjb3JkKQp7CglCb29sZWFuIHVzZVZhbHVlCT0gKGVudHJ5UmVjb3JkLT5jc1N0YXJ0IDwgMCk7CglVSW50MzIJc3RhcnQJCT0gdXNlVmFsdWUgPyAwVUwgOiAoVUludDMyKWVudHJ5UmVjb3JkLT5jc1N0YXJ0OwoJVUludDMyCXN0b3AJCT0gc3RhcnQgKyBlbnRyeVJlY29yZC0+Y3NDb3VudDsKCglUcmFjZShHcmFwaGljc0NvcmVTZXRFbnRyaWVzKTsKCglyZXR1cm4gR3JhcGhpY3NDb3JlRG9TZXRFbnRyaWVzKGVudHJ5UmVjb3JkLCBmYWxzZSwgc3RhcnQsIHN0b3AsIHVzZVZhbHVlKTsKfQoJCQkJCQkKT1NTdGF0dXMKR3JhcGhpY3NDb3JlRGlyZWN0U2V0RW50cmllcyhWRFNldEVudHJ5UmVjb3JkICplbnRyeVJlY29yZCkKewoJQm9vbGVhbiB1c2VWYWx1ZQk9IChlbnRyeVJlY29yZC0+Y3NTdGFydCA8IDApOwoJVUludDMyCXN0YXJ0CQk9IHVzZVZhbHVlID8gMCA6IGVudHJ5UmVjb3JkLT5jc1N0YXJ0OwoJVUludDMyCXN0b3AJCT0gc3RhcnQgKyBlbnRyeVJlY29yZC0+Y3NDb3VudDsKCglUcmFjZShHcmFwaGljc0NvcmVEaXJlY3RTZXRFbnRyaWVzKTsKCQoJcmV0dXJuIEdyYXBoaWNzQ29yZURvU2V0RW50cmllcyhlbnRyeVJlY29yZCwgdHJ1ZSwgc3RhcnQsIHN0b3AsIHVzZVZhbHVlKTsKfQoKT1NTdGF0dXMKR3JhcGhpY3NDb3JlR2V0RW50cmllcyhWRFNldEVudHJ5UmVjb3JkICplbnRyeVJlY29yZCkKewoJQm9vbGVhbiB1c2VWYWx1ZQk9IChlbnRyeVJlY29yZC0+Y3NTdGFydCA8IDApOwoJVUludDMyCXN0YXJ0CQk9IHVzZVZhbHVlID8gMFVMIDogKFVJbnQzMillbnRyeVJlY29yZC0+Y3NTdGFydDsKCVVJbnQzMglzdG9wCQk9IHN0YXJ0ICsgZW50cnlSZWNvcmQtPmNzQ291bnQ7CglVSW50MzIJaTsKCQoJVHJhY2UoR3JhcGhpY3NDb3JlR2V0RW50cmllcyk7CgoJaWYgKEdMT0JBTC5kZXB0aCAhPSA4KQoJCXJldHVybiBjb250cm9sRXJyOwoJZm9yKGk9c3RhcnQ7aTw9c3RvcDtpKyspIHsKCQlVSW50MzIJY29sb3JJbmRleCA9IHVzZVZhbHVlID8gZW50cnlSZWNvcmQtPmNzVGFibGVbaV0udmFsdWUgOiBpOwoJCVFlbXVWZ2FfR2V0Q29sb3JFbnRyeShjb2xvckluZGV4LCAmZW50cnlSZWNvcmQtPmNzVGFibGVbaV0ucmdiKTsKCX0KCglyZXR1cm4gbm9FcnI7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKiogR2FtbWEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCk9TU3RhdHVzCkdyYXBoaWNzQ29yZVNldEdhbW1hKFZER2FtbWFSZWNvcmQgKmdhbW1hUmVjKQp7CglDSEVDS19PUEVOKCBjb250cm9sRXJyICk7CgkJCglyZXR1cm4gbm9FcnI7Cn0KCk9TU3RhdHVzCkdyYXBoaWNzQ29yZUdldEdhbW1hSW5mb0xpc3QoVkRHZXRHYW1tYUxpc3RSZWMgKmdhbW1hTGlzdCkKewoJVHJhY2UoR3JhcGhpY3NDb3JlR2FtbWFJbmZvTGlzdCk7CgoJcmV0dXJuIHN0YXR1c0VycjsKfQoKT1NTdGF0dXMKR3JhcGhpY3NDb3JlUmV0cmlldmVHYW1tYVRhYmxlKFZEUmV0cmlldmVHYW1tYVJlYyAqZ2FtbWFSZWMpCnsKCVRyYWNlKEdyYXBoaWNzQ29yZVJldHJpZXZlR2FtbWFUYWJsZSk7CgoJcmV0dXJuIHN0YXR1c0VycjsKfQoKT1NTdGF0dXMKR3JhcGhpY3NDb3JlR2V0R2FtbWEoVkRHYW1tYVJlY29yZCAqZ2FtbWFSZWNvcmQpCnsKCUNIRUNLX09QRU4oIHN0YXR1c0VyciApOwoJCQoJVHJhY2UoR3JhcGhpY3NDb3JlR2V0R2FtbWEpOwoKCWdhbW1hUmVjb3JkLT5jc0dUYWJsZSA9IE5VTEw7CgoJcmV0dXJuIG5vRXJyOwp9CgoKLyoqKioqKioqKioqKioqKioqKioqKioqKiBHcmF5IHBhZ2VzICoqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgkJCQpPU1N0YXR1cwpHcmFwaGljc0NvcmVHcmF5UGFnZShWRFBhZ2VJbmZvICpwYWdlSW5mbykKewoJVUludDMyIHBhZ2VDb3VudDsKCglDSEVDS19PUEVOKCBjb250cm9sRXJyICk7CgkJCglUcmFjZShHcmFwaGljc0NvcmVHcmF5UGFnZSk7CgoJUWVtdVZnYV9HZXRNb2RlUGFnZXMoR0xPQkFMLmN1ck1vZGUsIEdMT0JBTC5kZXB0aCwgTlVMTCwgJnBhZ2VDb3VudCk7CglpZiAocGFnZUluZm8tPmNzUGFnZSA+PSBwYWdlQ291bnQpCgkJcmV0dXJuIHBhcmFtRXJyOwoJCgkvKiBYWFggTWFrZSBpdCBncmF5ICEgKi8KCXJldHVybiBub0VycjsKfQoJCQkKT1NTdGF0dXMKR3JhcGhpY3NDb3JlU2V0R3JheShWREdyYXlSZWNvcmQgKmdyYXlSZWNvcmQpCnsKCUNIRUNLX09QRU4oIGNvbnRyb2xFcnIgKTsKCQoJVHJhY2UoR3JhcGhpY3NDb3JlU2V0R3JheSk7CgoJR0xPQkFMLnFkTHVtaW5hbmNlTWFwcGluZwk9IGdyYXlSZWNvcmQtPmNzTW9kZTsKCXJldHVybiBub0VycjsKfQoKCk9TU3RhdHVzCkdyYXBoaWNzQ29yZUdldFBhZ2VzKFZEUGFnZUluZm8gKnBhZ2VJbmZvKQp7CglVSW50MzIgcGFnZUNvdW50LCBkZXB0aDsKCglDSEVDS19PUEVOKCBzdGF0dXNFcnIgKTsKCglUcmFjZShHcmFwaGljc0NvcmVHZXRQYWdlcyk7CgoJZGVwdGggPSBEZXB0aE1vZGVUb0RlcHRoKHBhZ2VJbmZvLT5jc01vZGUpOwoJUWVtdVZnYV9HZXRNb2RlUGFnZXMoR0xPQkFMLmN1ck1vZGUsIGRlcHRoLCBOVUxMLCAmcGFnZUNvdW50KTsKCXBhZ2VJbmZvLT5jc1BhZ2UgPSBwYWdlQ291bnQ7CgoJcmV0dXJuIG5vRXJyOwp9CgoJCQkKT1NTdGF0dXMKR3JhcGhpY3NDb3JlR2V0R3JheShWREdyYXlSZWNvcmQgKmdyYXlSZWNvcmQpCnsKCUNIRUNLX09QRU4oIHN0YXR1c0VyciApOwoJCQoJVHJhY2UoR3JhcGhpY3NDb3JlR2V0R3JheSk7CgkJCglncmF5UmVjb3JkLT5jc01vZGUgPSAoR0xPQkFMLnFkTHVtaW5hbmNlTWFwcGluZyk7CgkKCXJldHVybiBub0VycjsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKiBIYXJkd2FyZSBDdXJzb3IgKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCk9TU3RhdHVzCkdyYXBoaWNzQ29yZVN1cHBvcnRzSGFyZHdhcmVDdXJzb3IoVkRTdXBwb3J0c0hhcmR3YXJlQ3Vyc29yUmVjICpod0N1cnNSZWMpCnsKCUNIRUNLX09QRU4oIHN0YXR1c0VyciApOwoJCQoJVHJhY2UoR3JhcGhpY3NDb3JlU3VwcG9ydHNIYXJkd2FyZUN1cnNvcik7CgoJaHdDdXJzUmVjLT5jc1Jlc2VydmVkMSA9IDA7Cglod0N1cnNSZWMtPmNzUmVzZXJ2ZWQyID0gMDsKCglod0N1cnNSZWMtPmNzU3VwcG9ydHNIYXJkd2FyZUN1cnNvciA9IGZhbHNlOwoKCXJldHVybiBub0VycjsKfQoKT1NTdGF0dXMKR3JhcGhpY3NDb3JlU2V0SGFyZHdhcmVDdXJzb3IoVkRTZXRIYXJkd2FyZUN1cnNvclJlYyAqc2V0SHdDdXJzUmVjKQp7CglUcmFjZShHcmFwaGljc0NvcmVTZXRIYXJkd2FyZUN1cnNvcik7CgoJcmV0dXJuIGNvbnRyb2xFcnI7Cn0KCk9TU3RhdHVzCkdyYXBoaWNzQ29yZURyYXdIYXJkd2FyZUN1cnNvcihWRERyYXdIYXJkd2FyZUN1cnNvclJlYyAqZHJhd0h3Q3Vyc1JlYykKewoJVHJhY2UoR3JhcGhpY3NDb3JlRHJhd0hhcmR3YXJlQ3Vyc29yKTsKCglyZXR1cm4gY29udHJvbEVycjsKfQoKT1NTdGF0dXMKR3JhcGhpY3NDb3JlR2V0SGFyZHdhcmVDdXJzb3JEcmF3U3RhdGUoVkRIYXJkd2FyZUN1cnNvckRyYXdTdGF0ZVJlYyAqaHdDdXJzRFN0YXRlUmVjKQp7CglUcmFjZShHcmFwaGljc0NvcmVHZXRIYXJkd2FyZUN1cnNvckRyYXdTdGF0ZSk7CgoJcmV0dXJuIHN0YXR1c0VycjsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKiBNaXNjICoqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpPU1N0YXR1cwpHcmFwaGljc0NvcmVTZXRJbnRlcnJ1cHQoVkRGbGFnUmVjb3JkICpmbGFnUmVjb3JkKQp7CglDSEVDS19PUEVOKCBjb250cm9sRXJyICk7CgoJVHJhY2UoR3JhcGhpY3NDb3JlU2V0SW50ZXJydXB0KTsKCglpZiAoIWZsYWdSZWNvcmQtPmNzTW9kZSkKCSAgICBRZW11VmdhX0VuYWJsZUludGVycnVwdHMoKTsKCWVsc2UKCSAgICBRZW11VmdhX0Rpc2FibGVJbnRlcnJ1cHRzKCk7CgoJcmV0dXJuIG5vRXJyOwp9CgpPU1N0YXR1cwpHcmFwaGljc0NvcmVHZXRJbnRlcnJ1cHQoVkRGbGFnUmVjb3JkICpmbGFnUmVjb3JkKQp7CglUcmFjZShHcmFwaGljc0NvcmVHZXRJbnRlcnJ1cHQpOwoKCUNIRUNLX09QRU4oIHN0YXR1c0VyciApOwoJCQoJZmxhZ1JlY29yZC0+Y3NNb2RlID0gIUdMT0JBTC5xZEludGVycnVwdHNFbmFibGU7CglyZXR1cm4gbm9FcnI7Cn0KCk9TU3RhdHVzCkdyYXBoaWNzQ29yZVNldFN5bmMoVkRTeW5jSW5mb1JlYyAqc3luY0luZm8pCnsKCVVJbnQ4IHN5bmMsIG1hc2s7CgoJVHJhY2UoR3JhcGhpY3NDb3JlU2V0U3luYyk7CgoJQ0hFQ0tfT1BFTiggY29udHJvbEVyciApOwoKCXN5bmMgPSBzeW5jSW5mby0+Y3NNb2RlOwoJbWFzayA9IHN5bmNJbmZvLT5jc0ZsYWdzOwkKCgkvKiBVbmJsYW5rIHNob3J0Y3V0ICovCglpZiAoc3luYyA9PSAwICYmIG1hc2sgPT0gMCkgewoJCXN5bmMgPSAwOwoJCW1hc2sgPSBrRFBNU1N5bmNNYXNrOwoJfQoJLyogQmxhbmsgc2hvcnRjdXQgKi8KCWlmIChzeW5jID09IDB4ZmYgJiYgbWFzayA9PSAweGZmKSB7CgkJc3luYyA9IDB4NzsKCQltYXNrID0ga0RQTVNTeW5jTWFzazsKCX0KCQoJbHByaW50ZigiU2V0U3luYyByZXE6IHN5bmM9JXggbWFzaz0leFxuIiwgc3luYywgbWFzayk7CgkKCS8qIE9ubHkgY2FyZSBhYm91dCB0aGUgRFBNUyBtb2RlICovCglpZiAoKG1hc2sgJiBrRFBNU1N5bmNNYXNrKSA9PSAwKQoJCXJldHVybiBub0VycjsKCQoJLyogSWYgYW55IHN5bmMgaXMgZGlzYWJsZWQsIGJsYW5rICovCglpZiAoc3luYyAmIGtEUE1TU3luY01hc2spCgkJUWVtdVZnYV9CbGFuayh0cnVlKTsKCWVsc2UKCQlRZW11VmdhX0JsYW5rKGZhbHNlKTsKCglyZXR1cm4gbm9FcnI7Cn0KCk9TU3RhdHVzCkdyYXBoaWNzQ29yZUdldFN5bmMoVkRTeW5jSW5mb1JlYyAqc3luY0luZm8pCnsKCVRyYWNlKEdyYXBoaWNzQ29yZUdldFN5bmMpOwoKCWlmIChzeW5jSW5mby0+Y3NNb2RlID09IDB4ZmYpIHsKCQkvKiBSZXR1cm4gSFcgY2FwcyAqLwoJCXN5bmNJbmZvLT5jc01vZGUgPSAoMSA8PCBrRGlzYWJsZUhvcml6b250YWxTeW5jQml0KSB8CgkJCQkJCSAgICgxIDw8IGtEaXNhYmxlVmVydGljYWxTeW5jQml0KSB8CgkJCQkJCSAgICgxIDw8IGtEaXNhYmxlQ29tcG9zaXRlU3luY0JpdCkgfAoJCQkJCQkgICAoMSA8PCBrTm9TZXBhcmF0ZVN5bmNDb250cm9sQml0KTsKCX0gZWxzZSBpZiAoc3luY0luZm8tPmNzTW9kZSA9PSAweDAwKXsKCQlzeW5jSW5mby0+Y3NNb2RlID0gR0xPQkFMLmJsYW5rZWQgPyBrRFBNU1N5bmNNYXNrIDogMDsKCX0gZWxzZQoJCXJldHVybiBzdGF0dXNFcnI7CgoJc3luY0luZm8tPmNzRmxhZ3MgPSAwOwoKCXJldHVybiBub0VycjsKfQoKT1NTdGF0dXMKR3JhcGhpY3NDb3JlU2V0UG93ZXJTdGF0ZShWRFBvd2VyU3RhdGVSZWMgKnBvd2VyU3RhdGVSZWMpCnsKCVRyYWNlKEdyYXBoaWNzQ29yZVNldFBvd2VyU3RhdGUpOwoKCXJldHVybiBwYXJhbUVycjsKfQoKT1NTdGF0dXMKR3JhcGhpY3NDb3JlR2V0UG93ZXJTdGF0ZShWRFBvd2VyU3RhdGVSZWMgKnBvd2VyU3RhdGVSZWMpCnsKCVRyYWNlKEdyYXBoaWNzQ29yZUdldFBvd2VyU3RhdGUpOwoKCXJldHVybiBwYXJhbUVycjsKfQoJCQpPU1N0YXR1cwpHcmFwaGljc0NvcmVTZXRQcmVmZXJyZWRDb25maWd1cmF0aW9uKFZEU3dpdGNoSW5mb1JlYyAqc3dpdGNoSW5mbykKewoJVHJhY2UoR3JhcGhpY3NDb3JlU2V0UHJlZmVycmVkQ29uZmlndXJhdGlvbik7CgoJQ0hFQ0tfT1BFTiggY29udHJvbEVyciApOwoJCglyZXR1cm4gbm9FcnI7Cn0KCgpPU1N0YXR1cwpHcmFwaGljc0NvcmVHZXRQcmVmZXJyZWRDb25maWd1cmF0aW9uKFZEU3dpdGNoSW5mb1JlYyAqc3dpdGNoSW5mbykKewoJVHJhY2UoR3JhcGhpY3NDb3JlR2V0UHJlZmVycmVkQ29uZmlndXJhdGlvbik7CgoJQ0hFQ0tfT1BFTiggc3RhdHVzRXJyICk7CgkKCXN3aXRjaEluZm8tPmNzTW9kZSAJIAk9IERlcHRoVG9EZXB0aE1vZGUoR0xPQkFMLmJvb3REZXB0aCk7Cglzd2l0Y2hJbmZvLT5jc0RhdGEJCT0gR0xPQkFMLmJvb3RNb2RlICsgMTsgLyogTW9kZXMgYXJlIDEgYmFzZWQgKi8KCXN3aXRjaEluZm8tPmNzUGFnZQkJPSAwOwoJc3dpdGNoSW5mby0+Y3NCYXNlQWRkcgk9IEZCX1NUQVJUOwoKCXJldHVybiBub0VycjsKfQoKLy8ggCoqKioqKioqKioqKioqKioqIE1pc2Mgc3RhdHVzIGNhbGxzICoqKioqKioqKioqKioqKioqKioqKi8KCk9TU3RhdHVzCkdyYXBoaWNzQ29yZUdldEJhc2VBZGRyZXNzKFZEUGFnZUluZm8gKnBhZ2VJbmZvKQp7CglVSW50MzIgcGFnZUNvdW50LCBwYWdlU2l6ZTsKCglUcmFjZShHcmFwaGljc0NvcmVHZXRCYXNlQWRkcmVzcyk7CgoJQ0hFQ0tfT1BFTiggc3RhdHVzRXJyICk7CgoJUWVtdVZnYV9HZXRNb2RlUGFnZXMoR0xPQkFMLmN1ck1vZGUsIEdMT0JBTC5kZXB0aCwgJnBhZ2VTaXplLCAmcGFnZUNvdW50KTsKCWlmIChwYWdlSW5mby0+Y3NQYWdlID49IHBhZ2VDb3VudCkKCQlyZXR1cm4gcGFyYW1FcnI7CgkJCglwYWdlSW5mby0+Y3NCYXNlQWRkciA9IEZCX1NUQVJUICsgcGFnZUluZm8tPmNzUGFnZSAqIHBhZ2VTaXplOwoKCXJldHVybiBub0VycjsKfQoJCQkKT1NTdGF0dXMKR3JhcGhpY3NDb3JlR2V0Q29ubmVjdGlvbihWRERpc3BsYXlDb25uZWN0SW5mb1JlYyAqY29ubmVjdEluZm8pCnsKCVRyYWNlKEdyYXBoaWNzQ29yZUdldENvbm5lY3Rpb24pOwoKCUNIRUNLX09QRU4oIHN0YXR1c0VyciApOwoJCQoJY29ubmVjdEluZm8tPmNzRGlzcGxheVR5cGUJCQk9IGtWR0FDb25uZWN0OwoJY29ubmVjdEluZm8tPmNzQ29ubmVjdFRhZ2dlZFR5cGUJPSAwOwoJY29ubmVjdEluZm8tPmNzQ29ubmVjdFRhZ2dlZERhdGEJPSAwOwoKCWNvbm5lY3RJbmZvLT5jc0Nvbm5lY3RGbGFncwkJPQoJCSgxIDw8IGtUYWdnaW5nSW5mb05vblN0YW5kYXJkKSB8ICgxIDw8IGtVbmNlcnRhaW5Db25uZWN0aW9uKTsKCQkKCWNvbm5lY3RJbmZvLT5jc0Rpc3BsYXlDb21wb25lbnQJCT0gMDsKCQoJcmV0dXJuIG5vRXJyOwp9CgpPU1N0YXR1cwpHcmFwaGljc0NvcmVHZXRNb2RlKFZEUGFnZUluZm8gKnBhZ2VJbmZvKQp7CglUcmFjZShHcmFwaGljc0NvcmVHZXRNb2RlKTsKCglDSEVDS19PUEVOKCBzdGF0dXNFcnIgKTsKCQoJcGFnZUluZm8tPmNzTW9kZQkJPSBEZXB0aFRvRGVwdGhNb2RlKEdMT0JBTC5kZXB0aCk7CglwYWdlSW5mby0+Y3NQYWdlCQk9IEdMT0JBTC5jdXJQYWdlOwoJcGFnZUluZm8tPmNzQmFzZUFkZHIJPSBHTE9CQUwuY3VyQmFzZUFkZHJlc3M7CgoJcmV0dXJuIG5vRXJyOwp9CgpPU1N0YXR1cwpHcmFwaGljc0NvcmVHZXRDdXJyZW50TW9kZShWRFN3aXRjaEluZm9SZWMgKnN3aXRjaEluZm8pCnsKCVRyYWNlKEdyYXBoaWNzQ29yZUdldEN1cnJlbnRNb2RlKTsKCglDSEVDS19PUEVOKCBzdGF0dXNFcnIgKTsKCQoJLy9scHJpbnRmKCJHZXRDdXJyZW50TW9kZVxuIik7Cglzd2l0Y2hJbmZvLT5jc01vZGUJCT0gRGVwdGhUb0RlcHRoTW9kZShHTE9CQUwuZGVwdGgpOwoJc3dpdGNoSW5mby0+Y3NEYXRhCQk9IEdMT0JBTC5jdXJNb2RlICsgMTsKCXN3aXRjaEluZm8tPmNzUGFnZQkJPSBHTE9CQUwuY3VyUGFnZTsKCXN3aXRjaEluZm8tPmNzQmFzZUFkZHIJPSBHTE9CQUwuY3VyQmFzZUFkZHJlc3M7CgoJcmV0dXJuIG5vRXJyOwp9CgovKioqKioqKioqKioqKioqKioqKioqKiBWaWRlbyBtb2RlICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwoJCQkJCQkKT1NTdGF0dXMKR3JhcGhpY3NDb3JlR2V0TW9kZVRpbWluZyhWRFRpbWluZ0luZm9SZWMgKnRpbWluZ0luZm8pCnsKCVRyYWNlKEdyYXBoaWNzQ29yZUdldE1vZGVUaW1pbmcpOwoKCUNIRUNLX09QRU4oIHN0YXR1c0VyciApOwoKCWlmICh0aW1pbmdJbmZvLT5jc1RpbWluZ01vZGUgPCAxIHx8IHRpbWluZ0luZm8tPmNzVGltaW5nTW9kZSA+IEdMT0JBTC5udW1Nb2RlcyApCgkJcmV0dXJuIHBhcmFtRXJyOwoJCgl0aW1pbmdJbmZvLT5jc1RpbWluZ0ZsYWdzCT0KCQkoMSA8PCBrTW9kZVZhbGlkKSB8ICgxIDw8IGtNb2RlRGVmYXVsdCkgfCAoMSA8PGtNb2RlU2FmZSk7CgoJdGltaW5nSW5mby0+Y3NUaW1pbmdGb3JtYXQJPSBrRGVjbFJPTXRhYmxlczsKCXRpbWluZ0luZm8tPmNzVGltaW5nRGF0YQk9IHRpbWluZ1ZFU0FfNjQweDQ4MF82MGh6OwoKCXJldHVybiBub0VycjsKfQoKCk9TU3RhdHVzCkdyYXBoaWNzQ29yZVNldE1vZGUoVkRQYWdlSW5mbyAqcGFnZUluZm8pCnsKCVVJbnQzMiBuZXdEZXB0aCwgbmV3UGFnZSwgcGFnZUNvdW50OwoKCVRyYWNlKEdyYXBoaWNzQ29yZVNldE1vZGUpOwoKCUNIRUNLX09QRU4oY29udHJvbEVycik7CgoJbmV3RGVwdGggPSBEZXB0aE1vZGVUb0RlcHRoKHBhZ2VJbmZvLT5jc01vZGUpOwoJbmV3UGFnZSA9IHBhZ2VJbmZvLT5jc1BhZ2U7CglRZW11VmdhX0dldE1vZGVQYWdlcyhHTE9CQUwuY3VyTW9kZSwgbmV3RGVwdGgsIE5VTEwsICZwYWdlQ291bnQpOwoKCWxwcmludGYoIlJlcXVlc3RlZCBkZXB0aD0lZCBwYWdlPSVkXG4iLCBuZXdEZXB0aCwgbmV3UGFnZSk7CglpZiAocGFnZUluZm8tPmNzUGFnZSA+PSBwYWdlQ291bnQpCgkJcmV0dXJuIHBhcmFtRXJyOwoJCglpZiAobmV3RGVwdGggIT0gR0xPQkFMLmRlcHRoIHx8IG5ld1BhZ2UgIT0gR0xPQkFMLmN1clBhZ2UpCgkJUWVtdVZnYV9TZXRNb2RlKEdMT0JBTC5jdXJNb2RlLCBuZXdEZXB0aCwgbmV3UGFnZSk7CgkKCXBhZ2VJbmZvLT5jc0Jhc2VBZGRyID0gR0xPQkFMLmN1ckJhc2VBZGRyZXNzOwoJbHByaW50ZigiUmV0dXJuaW5nIEJBOiAlbHhcbiIsIHBhZ2VJbmZvLT5jc0Jhc2VBZGRyKTsKCglyZXR1cm4gbm9FcnI7Cn0JCQkKCgpPU1N0YXR1cwpHcmFwaGljc0NvcmVTd2l0Y2hNb2RlKFZEU3dpdGNoSW5mb1JlYyAqc3dpdGNoSW5mbykKewoJVUludDMyIG5ld01vZGUsIG5ld0RlcHRoLCBuZXdQYWdlLCBwYWdlQ291bnQ7CgoJVHJhY2UoR3JhcGhpY3NDb3JlU3dpdGNoTW9kZSk7CgoJQ0hFQ0tfT1BFTihjb250cm9sRXJyKTsKCQoJbmV3TW9kZSA9IHN3aXRjaEluZm8tPmNzRGF0YSAtIDE7CgluZXdEZXB0aCA9IERlcHRoTW9kZVRvRGVwdGgoc3dpdGNoSW5mby0+Y3NNb2RlKTsKCW5ld1BhZ2UgPSBzd2l0Y2hJbmZvLT5jc1BhZ2U7CglRZW11VmdhX0dldE1vZGVQYWdlcyhHTE9CQUwuY3VyTW9kZSwgbmV3RGVwdGgsIE5VTEwsICZwYWdlQ291bnQpOwoKCWlmIChuZXdQYWdlID49IHBhZ2VDb3VudCkKCQlyZXR1cm4gcGFyYW1FcnI7CgoJaWYgKG5ld01vZGUgIT0gR0xPQkFMLmN1ck1vZGUgfHwgbmV3RGVwdGggIT0gR0xPQkFMLmRlcHRoIHx8CgkgICAgbmV3UGFnZSAhPSBHTE9CQUwuY3VyUGFnZSkgewoJCWlmIChRZW11VmdhX1NldE1vZGUobmV3TW9kZSwgbmV3RGVwdGgsIG5ld1BhZ2UpKQoJCQlyZXR1cm4gY29udHJvbEVycjsKCX0KCXN3aXRjaEluZm8tPmNzQmFzZUFkZHIgPSBHTE9CQUwuY3VyQmFzZUFkZHJlc3M7CgoJcmV0dXJuIG5vRXJyOwp9CgpPU1N0YXR1cwpHcmFwaGljc0NvcmVHZXROZXh0UmVzb2x1dGlvbihWRFJlc29sdXRpb25JbmZvUmVjICpyZXNJbmZvKQp7CglVSW50MzIgd2lkdGgsIGhlaWdodDsKCWludCBpZCA9IHJlc0luZm8tPmNzUHJldmlvdXNEaXNwbGF5TW9kZUlEOwoKCVRyYWNlKEdyYXBoaWNzQ29yZUdldE5leHRSZXNvbHV0aW9uKTsKCglDSEVDS19PUEVOKHN0YXR1c0Vycik7CgoJaWYgKGlkID09IGtEaXNwbGF5TW9kZUlERmluZEZpcnN0UmVzb2x1dGlvbikKCQlpZCA9IDA7CgllbHNlIGlmIChpZCA9PSBrRGlzcGxheU1vZGVJREN1cnJlbnQpCgkJaWQgPSBHTE9CQUwuY3VyTW9kZTsKCWlkKys7CgkKCWlmIChpZCA9PSBHTE9CQUwubnVtTW9kZXMgKyAxKSB7CgkJcmVzSW5mby0+Y3NEaXNwbGF5TW9kZUlEID0ga0Rpc3BsYXlNb2RlSUROb01vcmVSZXNvbHV0aW9uczsKCQlyZXR1cm4gbm9FcnI7Cgl9CglpZiAoaWQgPCAxIHx8IGlkID4gR0xPQkFMLm51bU1vZGVzKQoJCXJldHVybiBwYXJhbUVycjsKCQoJaWYgKFFlbXVWZ2FfR2V0TW9kZUluZm8oaWQgLSAxLCAmd2lkdGgsICZoZWlnaHQpKQoJCXJldHVybiBwYXJhbUVycjsKCglyZXNJbmZvLT5jc0Rpc3BsYXlNb2RlSUQJPSBpZDsKCXJlc0luZm8tPmNzSG9yaXpvbnRhbFBpeGVscwk9IHdpZHRoOwoJcmVzSW5mby0+Y3NWZXJ0aWNhbExpbmVzCT0gaGVpZ2h0OwoJcmVzSW5mby0+Y3NSZWZyZXNoUmF0ZQkJPSA2MDsKCXJlc0luZm8tPmNzTWF4RGVwdGhNb2RlCQk9IE1BWF9ERVBUSF9NT0RFOyAvKiBYWFggQ2FsY3VsYXRlIGlmIGl0IGZpdHMgISAqLwoKCXJldHVybiBub0VycjsKfQoKLy8gTG9va3MgcXVpdGUgYSBiaXQgaGFyZC1jb2RlZCwgaXNuJ3QgaXQgPwpPU1N0YXR1cwpHcmFwaGljc0NvcmVHZXRWaWRlb1BhcmFtcyhWRFZpZGVvUGFyYW1ldGVyc0luZm9SZWMgKnZpZGVvUGFyYW1zKQp7CglVSW50MzIgd2lkdGgsIGhlaWdodCwgZGVwdGgsIHJvd0J5dGVzLCBwYWdlQ291bnQ7CglPU1N0YXR1cyBlcnIgPSBub0VycjsKCQoJVHJhY2UoR3JhcGhpY3NDb3JlR2V0VmlkZW9QYXJhbXMpOwoKCUNIRUNLX09QRU4oc3RhdHVzRXJyKTsKIAkJCglpZiAodmlkZW9QYXJhbXMtPmNzRGlzcGxheU1vZGVJRCA8IDEgfHwgdmlkZW9QYXJhbXMtPmNzRGlzcGxheU1vZGVJRCA+IEdMT0JBTC5udW1Nb2RlcykKCQlyZXR1cm4gcGFyYW1FcnI7CglpZiAodmlkZW9QYXJhbXMtPmNzRGVwdGhNb2RlID4gTUFYX0RFUFRIX01PREUpCgkJcmV0dXJuIHBhcmFtRXJyOwoJaWYgKFFlbXVWZ2FfR2V0TW9kZUluZm8odmlkZW9QYXJhbXMtPmNzRGlzcGxheU1vZGVJRCAtIDEsICZ3aWR0aCwgJmhlaWdodCkpCgkJcmV0dXJuIHBhcmFtRXJyOwoJCglkZXB0aCA9IERlcHRoTW9kZVRvRGVwdGgodmlkZW9QYXJhbXMtPmNzRGVwdGhNb2RlKTsKCVFlbXVWZ2FfR2V0TW9kZVBhZ2VzKHZpZGVvUGFyYW1zLT5jc0Rpc3BsYXlNb2RlSUQgLSAxLCBkZXB0aCwgTlVMTCwgJnBhZ2VDb3VudCk7Cgl2aWRlb1BhcmFtcy0+Y3NQYWdlQ291bnQgPSBwYWdlQ291bnQ7CglscHJpbnRmKCJWaWRlbyBQYXJhbXMgc2F5cyAlZCBwYWdlc1xuIiwgcGFnZUNvdW50KTsKCQoJcm93Qnl0ZXMgPSB3aWR0aCAqICgoZGVwdGggKyA3KSAvIDgpOwoJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cEJhc2VPZmZzZXQgCQk9IDA7CQkJLy8gRm9yIHVzLCBpdCdzIGFsd2F5cyAwCgkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwQm91bmRzLnRvcCAJCT0gMDsJCQkvLyBBbHdheXMgMAoJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cEJvdW5kcy5sZWZ0IAkJPSAwOwkJCS8vIEFsd2F5cyAwCgkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwVmVyc2lvbiAJCQk9IDA7CQkJLy8gQWx3YXlzIDAKCSh2aWRlb1BhcmFtcy0+Y3NWUEJsb2NrUHRyKS0+dnBQYWNrVHlwZSAJCT0gMDsJCQkvLyBBbHdheXMgMAoJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cFBhY2tTaXplIAkJPSAwOwkJCS8vIEFsd2F5cyAwCgkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwSFJlcyAJCQk9IDB4MDA0ODAwMDA7CS8vIEhhcmQgY29kZWQgdG8gNzIgZHBpCgkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwVlJlcyAJCQk9IDB4MDA0ODAwMDA7CS8vIEhhcmQgY29kZWQgdG8gNzIgZHBpCgkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwUGxhbmVCeXRlcyAJCT0gMDsJCQkvLyBBbHdheXMgMAoJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cEJvdW5kcy5ib3R0b20JPSBoZWlnaHQ7CgkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwQm91bmRzLnJpZ2h0CQk9IHdpZHRoOwoJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cFJvd0J5dGVzCQkJPSByb3dCeXRlczsKCglzd2l0Y2ggKGRlcHRoKSB7CgljYXNlIDg6CgkJdmlkZW9QYXJhbXMtPmNzRGV2aWNlVHlwZSAJCQkJCQk9IGNsdXRUeXBlOwoJCSh2aWRlb1BhcmFtcy0+Y3NWUEJsb2NrUHRyKS0+dnBQaXhlbFR5cGUgCQk9IDA7CgkJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cFBpeGVsU2l6ZSAJCT0gODsKCQkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwQ21wQ291bnQgCQk9IDE7CgkJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cENtcFNpemUgCQkJPSA4OwoJCSh2aWRlb1BhcmFtcy0+Y3NWUEJsb2NrUHRyKS0+dnBQbGFuZUJ5dGVzIAkJPSAwOwoJCWJyZWFrOwoJY2FzZSAxNToKCWNhc2UgMTY6CgkJdmlkZW9QYXJhbXMtPmNzRGV2aWNlVHlwZSAJCQkJCQk9IGRpcmVjdFR5cGU7CgkJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cFBpeGVsVHlwZSAJCT0gMTY7CgkJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cFBpeGVsU2l6ZSAJCT0gMTY7CgkJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cENtcENvdW50IAkJPSAzOwoJCSh2aWRlb1BhcmFtcy0+Y3NWUEJsb2NrUHRyKS0+dnBDbXBTaXplIAkJCT0gNTsKCQkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwUGxhbmVCeXRlcyAJCT0gMDsKCQlicmVhazsKCWNhc2UgMzI6CgkJdmlkZW9QYXJhbXMtPmNzRGV2aWNlVHlwZSAJCQkJCQk9IGRpcmVjdFR5cGU7CgkJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cFBpeGVsVHlwZSAJCT0gMTY7CgkJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cFBpeGVsU2l6ZSAJCT0gMzI7CgkJKHZpZGVvUGFyYW1zLT5jc1ZQQmxvY2tQdHIpLT52cENtcENvdW50IAkJPSAzOwoJCSh2aWRlb1BhcmFtcy0+Y3NWUEJsb2NrUHRyKS0+dnBDbXBTaXplIAkJCT0gODsKCQkodmlkZW9QYXJhbXMtPmNzVlBCbG9ja1B0ciktPnZwUGxhbmVCeXRlcyAJCT0gMDsKCQlicmVhazsKCWRlZmF1bHQ6CgkJZXJyID0gcGFyYW1FcnI7CgkJYnJlYWs7Cgl9CgoJcmV0dXJuIGVycjsKfQo=