LyoKVGhpcyBzb3VyY2UgZmlsZSBpcyBwYXJ0IG9mIEdJTVBBQ1QgTGlicmFyeS4KCkZvciB0aGUgbGF0ZXN0IGluZm8sIHNlZSBodHRwOi8vZ2ltcGFjdC5zb3VyY2Vmb3JnZS5uZXQvCgpDb3B5cmlnaHQgKGMpIDIwMDcgRnJhbmNpc2NvIExlb24gTmFqZXJhLiBDLkMuIDgwMDg3MzcxLgplbWFpbDogcHJvamVjdGlsZW1hbkB5YWhvby5jb20KCgpUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkICdhcy1pcycsIHdpdGhvdXQgYW55IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4KSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXMgYXJpc2luZyBmcm9tIHRoZSB1c2Ugb2YgdGhpcyBzb2Z0d2FyZS4KUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsCmluY2x1ZGluZyBjb21tZXJjaWFsIGFwcGxpY2F0aW9ucywgYW5kIHRvIGFsdGVyIGl0IGFuZCByZWRpc3RyaWJ1dGUgaXQgZnJlZWx5LApzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgcmVzdHJpY3Rpb25zOgoKMS4gVGhlIG9yaWdpbiBvZiB0aGlzIHNvZnR3YXJlIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkOyB5b3UgbXVzdCBub3QgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmUgaW4gYSBwcm9kdWN0LCBhbiBhY2tub3dsZWRnbWVudCBpbiB0aGUgcHJvZHVjdCBkb2N1bWVudGF0aW9uIHdvdWxkIGJlIGFwcHJlY2lhdGVkIGJ1dCBpcyBub3QgcmVxdWlyZWQuCjIuIEFsdGVyZWQgc291cmNlIHZlcnNpb25zIG11c3QgYmUgcGxhaW5seSBtYXJrZWQgYXMgc3VjaCwgYW5kIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkIGFzIGJlaW5nIHRoZSBvcmlnaW5hbCBzb2Z0d2FyZS4KMy4gVGhpcyBub3RpY2UgbWF5IG5vdCBiZSByZW1vdmVkIG9yIGFsdGVyZWQgZnJvbSBhbnkgc291cmNlIGRpc3RyaWJ1dGlvbi4KKi8KLyoKQXV0aG9yOiBGcmFuY2lzY28gTGV/biBO32plcmEKQ29uY2F2ZS1Db25jYXZlIENvbGxpc2lvbgoKKi8KCiNpbmNsdWRlICJCdWxsZXRDb2xsaXNpb24vQ29sbGlzaW9uRGlzcGF0Y2gvYnRNYW5pZm9sZFJlc3VsdC5oIgojaW5jbHVkZSAiTGluZWFyTWF0aC9idElEZWJ1Z0RyYXcuaCIKI2luY2x1ZGUgIkJ1bGxldENvbGxpc2lvbi9Db2xsaXNpb25EaXNwYXRjaC9idENvbGxpc2lvbk9iamVjdC5oIgojaW5jbHVkZSAiQnVsbGV0Q29sbGlzaW9uL0NvbGxpc2lvblNoYXBlcy9idEJveFNoYXBlLmgiCiNpbmNsdWRlICJCdWxsZXRDb2xsaXNpb24vR2ltcGFjdC9idEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG0uaCIKI2luY2x1ZGUgIkJ1bGxldENvbGxpc2lvbi9HaW1wYWN0L2J0Q29udGFjdFByb2Nlc3NpbmcuaCIKI2luY2x1ZGUgIkxpbmVhck1hdGgvYnRRdWlja3Byb2YuaCIKCgovLyEgQ2xhc3MgZm9yIGFjY2Vzc2luZyB0aGUgcGxhbmUgZXF1YXRpb24KY2xhc3MgYnRQbGFuZVNoYXBlIDogcHVibGljIGJ0U3RhdGljUGxhbmVTaGFwZQp7CnB1YmxpYzoKCglidFBsYW5lU2hhcGUoY29uc3QgYnRWZWN0b3IzJiB2LCBmbG9hdCBmKQoJCTpidFN0YXRpY1BsYW5lU2hhcGUodixmKQoJewoJfQoKCXZvaWQgZ2V0X3BsYW5lX2VxdWF0aW9uKGJ0VmVjdG9yNCAmZXF1YXRpb24pCgl7CgkJZXF1YXRpb25bMF0gPSBtX3BsYW5lTm9ybWFsWzBdOwoJCWVxdWF0aW9uWzFdID0gbV9wbGFuZU5vcm1hbFsxXTsKCQllcXVhdGlvblsyXSA9IG1fcGxhbmVOb3JtYWxbMl07CgkJZXF1YXRpb25bM10gPSBtX3BsYW5lQ29uc3RhbnQ7Cgl9CgoKCXZvaWQgZ2V0X3BsYW5lX2VxdWF0aW9uX3RyYW5zZm9ybWVkKGNvbnN0IGJ0VHJhbnNmb3JtICYgdHJhbnMsYnRWZWN0b3I0ICZlcXVhdGlvbikKCXsKCQllcXVhdGlvblswXSA9IHRyYW5zLmdldEJhc2lzKCkuZ2V0Um93KDApLmRvdChtX3BsYW5lTm9ybWFsKTsKCQllcXVhdGlvblsxXSA9IHRyYW5zLmdldEJhc2lzKCkuZ2V0Um93KDEpLmRvdChtX3BsYW5lTm9ybWFsKTsKCQllcXVhdGlvblsyXSA9IHRyYW5zLmdldEJhc2lzKCkuZ2V0Um93KDIpLmRvdChtX3BsYW5lTm9ybWFsKTsKCQllcXVhdGlvblszXSA9IHRyYW5zLmdldE9yaWdpbigpLmRvdChtX3BsYW5lTm9ybWFsKSArIG1fcGxhbmVDb25zdGFudDsKCX0KfTsKCgoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwojaWZkZWYgVFJJX0NPTExJU0lPTl9QUk9GSUxJTkcKCmJ0Q2xvY2sgZ190cmlhbmdsZV9jbG9jazsKCmZsb2F0IGdfYWNjdW1fdHJpYW5nbGVfY29sbGlzaW9uX3RpbWUgPSAwOwppbnQgZ19jb3VudF90cmlhbmdsZV9jb2xsaXNpb24gPSAwOwoKdm9pZCBidF9iZWdpbl9naW0wMl90cmlfdGltZSgpCnsKCWdfdHJpYW5nbGVfY2xvY2sucmVzZXQoKTsKfQoKdm9pZCBidF9lbmRfZ2ltMDJfdHJpX3RpbWUoKQp7CglnX2FjY3VtX3RyaWFuZ2xlX2NvbGxpc2lvbl90aW1lICs9IGdfdHJpYW5nbGVfY2xvY2suZ2V0VGltZU1pY3Jvc2Vjb25kcygpOwoJZ19jb3VudF90cmlhbmdsZV9jb2xsaXNpb24rKzsKfQojZW5kaWYgLy9UUklfQ09MTElTSU9OX1BST0ZJTElORwovLyEgUmV0cmlldmluZyBzaGFwZXMgc2hhcGVzCi8qIQpEZWNsYXJlZCBoZXJlIGR1ZSBvZiBpbnN1ZmljZW50IHNwYWNlIG9uIFBvb2wgYWxsb2NhdG9ycwoqLwovLyFAewpjbGFzcyBHSU1fU2hhcGVSZXRyaWV2ZXIKewpwdWJsaWM6CglidEdJbXBhY3RTaGFwZUludGVyZmFjZSAqIG1fZ2ltX3NoYXBlOwoJYnRUcmlhbmdsZVNoYXBlRXggbV90cmlzaGFwZTsKCWJ0VGV0cmFoZWRyb25TaGFwZUV4IG1fdGV0cmFzaGFwZTsKCnB1YmxpYzoKCWNsYXNzIENoaWxkU2hhcGVSZXRyaWV2ZXIKCXsKCXB1YmxpYzoKCQlHSU1fU2hhcGVSZXRyaWV2ZXIgKiBtX3BhcmVudDsKCQl2aXJ0dWFsIGJ0Q29sbGlzaW9uU2hhcGUgKiBnZXRDaGlsZFNoYXBlKGludCBpbmRleCkKCQl7CgkJCXJldHVybiBtX3BhcmVudC0+bV9naW1fc2hhcGUtPmdldENoaWxkU2hhcGUoaW5kZXgpOwoJCX0KCQl2aXJ0dWFsIH5DaGlsZFNoYXBlUmV0cmlldmVyKCkge30KCX07CgoJY2xhc3MgVHJpYW5nbGVTaGFwZVJldHJpZXZlcjpwdWJsaWMgQ2hpbGRTaGFwZVJldHJpZXZlcgoJewoJcHVibGljOgoKCQl2aXJ0dWFsIGJ0Q29sbGlzaW9uU2hhcGUgKiBnZXRDaGlsZFNoYXBlKGludCBpbmRleCkKCQl7CgkJCW1fcGFyZW50LT5tX2dpbV9zaGFwZS0+Z2V0QnVsbGV0VHJpYW5nbGUoaW5kZXgsbV9wYXJlbnQtPm1fdHJpc2hhcGUpOwoJCQlyZXR1cm4gJm1fcGFyZW50LT5tX3RyaXNoYXBlOwoJCX0KCQl2aXJ0dWFsIH5UcmlhbmdsZVNoYXBlUmV0cmlldmVyKCkge30KCX07CgoJY2xhc3MgVGV0cmFTaGFwZVJldHJpZXZlcjpwdWJsaWMgQ2hpbGRTaGFwZVJldHJpZXZlcgoJewoJcHVibGljOgoKCQl2aXJ0dWFsIGJ0Q29sbGlzaW9uU2hhcGUgKiBnZXRDaGlsZFNoYXBlKGludCBpbmRleCkKCQl7CgkJCW1fcGFyZW50LT5tX2dpbV9zaGFwZS0+Z2V0QnVsbGV0VGV0cmFoZWRyb24oaW5kZXgsbV9wYXJlbnQtPm1fdGV0cmFzaGFwZSk7CgkJCXJldHVybiAmbV9wYXJlbnQtPm1fdGV0cmFzaGFwZTsKCQl9Cgl9OwpwdWJsaWM6CglDaGlsZFNoYXBlUmV0cmlldmVyIG1fY2hpbGRfcmV0cmlldmVyOwoJVHJpYW5nbGVTaGFwZVJldHJpZXZlciBtX3RyaV9yZXRyaWV2ZXI7CglUZXRyYVNoYXBlUmV0cmlldmVyICBtX3RldHJhX3JldHJpZXZlcjsKCUNoaWxkU2hhcGVSZXRyaWV2ZXIgKiBtX2N1cnJlbnRfcmV0cmlldmVyOwoKCUdJTV9TaGFwZVJldHJpZXZlcihidEdJbXBhY3RTaGFwZUludGVyZmFjZSAqIGdpbV9zaGFwZSkKCXsKCQltX2dpbV9zaGFwZSA9IGdpbV9zaGFwZTsKCQkvL3NlbGVjdCByZXRyaWV2ZXIKCQlpZihtX2dpbV9zaGFwZS0+bmVlZHNSZXRyaWV2ZVRyaWFuZ2xlcygpKQoJCXsKCQkJbV9jdXJyZW50X3JldHJpZXZlciA9ICZtX3RyaV9yZXRyaWV2ZXI7CgkJfQoJCWVsc2UgaWYobV9naW1fc2hhcGUtPm5lZWRzUmV0cmlldmVUZXRyYWhlZHJvbnMoKSkKCQl7CgkJCW1fY3VycmVudF9yZXRyaWV2ZXIgPSAmbV90ZXRyYV9yZXRyaWV2ZXI7CgkJfQoJCWVsc2UKCQl7CgkJCW1fY3VycmVudF9yZXRyaWV2ZXIgPSAmbV9jaGlsZF9yZXRyaWV2ZXI7CgkJfQoKCQltX2N1cnJlbnRfcmV0cmlldmVyLT5tX3BhcmVudCA9IHRoaXM7Cgl9CgoJYnRDb2xsaXNpb25TaGFwZSAqIGdldENoaWxkU2hhcGUoaW50IGluZGV4KQoJewoJCXJldHVybiBtX2N1cnJlbnRfcmV0cmlldmVyLT5nZXRDaGlsZFNoYXBlKGluZGV4KTsKCX0KCgp9OwoKCgovLyFAfQoKCiNpZmRlZiBUUklfQ09MTElTSU9OX1BST0ZJTElORwoKLy8hIEdldHMgdGhlIGF2ZXJhZ2UgdGltZSBpbiBtaWxpc2Vjb25kcyBvZiB0cmVlIGNvbGxpc2lvbnMKZmxvYXQgYnRHSW1wYWN0Q29sbGlzaW9uQWxnb3JpdGhtOjpnZXRBdmVyYWdlVHJlZUNvbGxpc2lvblRpbWUoKQp7CglyZXR1cm4gYnRHSW1wYWN0Qm94U2V0OjpnZXRBdmVyYWdlVHJlZUNvbGxpc2lvblRpbWUoKTsKCn0KCi8vISBHZXRzIHRoZSBhdmVyYWdlIHRpbWUgaW4gbWlsaXNlY29uZHMgb2YgdHJpYW5nbGUgY29sbGlzaW9ucwpmbG9hdCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmdldEF2ZXJhZ2VUcmlhbmdsZUNvbGxpc2lvblRpbWUoKQp7CglpZihnX2NvdW50X3RyaWFuZ2xlX2NvbGxpc2lvbiA9PSAwKSByZXR1cm4gMDsKCglmbG9hdCBhdmd0aW1lID0gZ19hY2N1bV90cmlhbmdsZV9jb2xsaXNpb25fdGltZTsKCWF2Z3RpbWUgLz0gKGZsb2F0KWdfY291bnRfdHJpYW5nbGVfY29sbGlzaW9uOwoKCWdfYWNjdW1fdHJpYW5nbGVfY29sbGlzaW9uX3RpbWUgPSAwOwoJZ19jb3VudF90cmlhbmdsZV9jb2xsaXNpb24gPSAwOwoKCXJldHVybiBhdmd0aW1lOwp9CgojZW5kaWYgLy9UUklfQ09MTElTSU9OX1BST0ZJTElORwoKCgpidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmJ0R0ltcGFjdENvbGxpc2lvbkFsZ29yaXRobSggY29uc3QgYnRDb2xsaXNpb25BbGdvcml0aG1Db25zdHJ1Y3Rpb25JbmZvJiBjaSwgYnRDb2xsaXNpb25PYmplY3QqIGJvZHkwLGJ0Q29sbGlzaW9uT2JqZWN0KiBib2R5MSkKOiBidEFjdGl2YXRpbmdDb2xsaXNpb25BbGdvcml0aG0oY2ksYm9keTAsYm9keTEpCnsKCW1fbWFuaWZvbGRQdHIgPSBOVUxMOwoJbV9jb252ZXhfYWxnb3JpdGhtID0gTlVMTDsKfQoKYnRHSW1wYWN0Q29sbGlzaW9uQWxnb3JpdGhtOjp+YnRHSW1wYWN0Q29sbGlzaW9uQWxnb3JpdGhtKCkKewoJY2xlYXJDYWNoZSgpOwp9CgoKCgoKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmFkZENvbnRhY3RQb2ludChidENvbGxpc2lvbk9iamVjdCAqIGJvZHkwLAoJCQkJYnRDb2xsaXNpb25PYmplY3QgKiBib2R5MSwKCQkJCWNvbnN0IGJ0VmVjdG9yMyAmIHBvaW50LAoJCQkJY29uc3QgYnRWZWN0b3IzICYgbm9ybWFsLAoJCQkJYnRTY2FsYXIgZGlzdGFuY2UpCnsKCW1fcmVzdWx0T3V0LT5zZXRTaGFwZUlkZW50aWZpZXJzQShtX3BhcnQwLG1fdHJpZmFjZTApOwoJbV9yZXN1bHRPdXQtPnNldFNoYXBlSWRlbnRpZmllcnNCKG1fcGFydDEsbV90cmlmYWNlMSk7CgljaGVja01hbmlmb2xkKGJvZHkwLGJvZHkxKTsKCW1fcmVzdWx0T3V0LT5hZGRDb250YWN0UG9pbnQobm9ybWFsLHBvaW50LGRpc3RhbmNlKTsKfQoKCnZvaWQgYnRHSW1wYWN0Q29sbGlzaW9uQWxnb3JpdGhtOjpzaGFwZV92c19zaGFwZV9jb2xsaXNpb24oCgkJCQkJICBidENvbGxpc2lvbk9iamVjdCAqIGJvZHkwLAoJCQkJCSAgYnRDb2xsaXNpb25PYmplY3QgKiBib2R5MSwKCQkJCQkgIGJ0Q29sbGlzaW9uU2hhcGUgKiBzaGFwZTAsCgkJCQkJICBidENvbGxpc2lvblNoYXBlICogc2hhcGUxKQp7CgoJYnRDb2xsaXNpb25TaGFwZSogdG1wU2hhcGUwID0gYm9keTAtPmdldENvbGxpc2lvblNoYXBlKCk7CglidENvbGxpc2lvblNoYXBlKiB0bXBTaGFwZTEgPSBib2R5MS0+Z2V0Q29sbGlzaW9uU2hhcGUoKTsKCQoJYm9keTAtPmludGVybmFsU2V0VGVtcG9yYXJ5Q29sbGlzaW9uU2hhcGUoc2hhcGUwKTsKCWJvZHkxLT5pbnRlcm5hbFNldFRlbXBvcmFyeUNvbGxpc2lvblNoYXBlKHNoYXBlMSk7CgoJewoJCWJ0Q29sbGlzaW9uQWxnb3JpdGhtKiBhbGdvciA9IG5ld0FsZ29yaXRobShib2R5MCxib2R5MSk7CgkJLy8gcG9zdCA6CWNoZWNrTWFuaWZvbGQgaXMgY2FsbGVkCgoJCW1fcmVzdWx0T3V0LT5zZXRTaGFwZUlkZW50aWZpZXJzQShtX3BhcnQwLG1fdHJpZmFjZTApOwoJCW1fcmVzdWx0T3V0LT5zZXRTaGFwZUlkZW50aWZpZXJzQihtX3BhcnQxLG1fdHJpZmFjZTEpOwoKCQlhbGdvci0+cHJvY2Vzc0NvbGxpc2lvbihib2R5MCxib2R5MSwqbV9kaXNwYXRjaEluZm8sbV9yZXN1bHRPdXQpOwoKCQlhbGdvci0+fmJ0Q29sbGlzaW9uQWxnb3JpdGhtKCk7CgkJbV9kaXNwYXRjaGVyLT5mcmVlQ29sbGlzaW9uQWxnb3JpdGhtKGFsZ29yKTsKCX0KCglib2R5MC0+aW50ZXJuYWxTZXRUZW1wb3JhcnlDb2xsaXNpb25TaGFwZSh0bXBTaGFwZTApOwoJYm9keTEtPmludGVybmFsU2V0VGVtcG9yYXJ5Q29sbGlzaW9uU2hhcGUodG1wU2hhcGUxKTsKfQoKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmNvbnZleF92c19jb252ZXhfY29sbGlzaW9uKAoJCQkJCSAgYnRDb2xsaXNpb25PYmplY3QgKiBib2R5MCwKCQkJCQkgIGJ0Q29sbGlzaW9uT2JqZWN0ICogYm9keTEsCgkJCQkJICBidENvbGxpc2lvblNoYXBlICogc2hhcGUwLAoJCQkJCSAgYnRDb2xsaXNpb25TaGFwZSAqIHNoYXBlMSkKewoKCWJ0Q29sbGlzaW9uU2hhcGUqIHRtcFNoYXBlMCA9IGJvZHkwLT5nZXRDb2xsaXNpb25TaGFwZSgpOwoJYnRDb2xsaXNpb25TaGFwZSogdG1wU2hhcGUxID0gYm9keTEtPmdldENvbGxpc2lvblNoYXBlKCk7CgkKCWJvZHkwLT5pbnRlcm5hbFNldFRlbXBvcmFyeUNvbGxpc2lvblNoYXBlKHNoYXBlMCk7Cglib2R5MS0+aW50ZXJuYWxTZXRUZW1wb3JhcnlDb2xsaXNpb25TaGFwZShzaGFwZTEpOwoKCgltX3Jlc3VsdE91dC0+c2V0U2hhcGVJZGVudGlmaWVyc0EobV9wYXJ0MCxtX3RyaWZhY2UwKTsKCW1fcmVzdWx0T3V0LT5zZXRTaGFwZUlkZW50aWZpZXJzQihtX3BhcnQxLG1fdHJpZmFjZTEpOwoKCWNoZWNrQ29udmV4QWxnb3JpdGhtKGJvZHkwLGJvZHkxKTsKCW1fY29udmV4X2FsZ29yaXRobS0+cHJvY2Vzc0NvbGxpc2lvbihib2R5MCxib2R5MSwqbV9kaXNwYXRjaEluZm8sbV9yZXN1bHRPdXQpOwoKCWJvZHkwLT5pbnRlcm5hbFNldFRlbXBvcmFyeUNvbGxpc2lvblNoYXBlKHRtcFNoYXBlMCk7Cglib2R5MS0+aW50ZXJuYWxTZXRUZW1wb3JhcnlDb2xsaXNpb25TaGFwZSh0bXBTaGFwZTEpOwoKfQoKCgoKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmdpbXBhY3RfdnNfZ2ltcGFjdF9maW5kX3BhaXJzKAoJCQkJCSAgY29uc3QgYnRUcmFuc2Zvcm0gJiB0cmFuczAsCgkJCQkJICBjb25zdCBidFRyYW5zZm9ybSAmIHRyYW5zMSwKCQkJCQkgIGJ0R0ltcGFjdFNoYXBlSW50ZXJmYWNlICogc2hhcGUwLAoJCQkJCSAgYnRHSW1wYWN0U2hhcGVJbnRlcmZhY2UgKiBzaGFwZTEsYnRQYWlyU2V0ICYgcGFpcnNldCkKewoJaWYoc2hhcGUwLT5oYXNCb3hTZXQoKSAmJiBzaGFwZTEtPmhhc0JveFNldCgpKQoJewoJCWJ0R0ltcGFjdEJveFNldDo6ZmluZF9jb2xsaXNpb24oc2hhcGUwLT5nZXRCb3hTZXQoKSx0cmFuczAsc2hhcGUxLT5nZXRCb3hTZXQoKSx0cmFuczEscGFpcnNldCk7Cgl9CgllbHNlCgl7CgkJYnRBQUJCIGJveHNoYXBlMDsKCQlidEFBQkIgYm94c2hhcGUxOwoJCWludCBpID0gc2hhcGUwLT5nZXROdW1DaGlsZFNoYXBlcygpOwoKCQl3aGlsZShpLS0pCgkJewoJCQlzaGFwZTAtPmdldENoaWxkQWFiYihpLHRyYW5zMCxib3hzaGFwZTAubV9taW4sYm94c2hhcGUwLm1fbWF4KTsKCgkJCWludCBqID0gc2hhcGUxLT5nZXROdW1DaGlsZFNoYXBlcygpOwoJCQl3aGlsZShqLS0pCgkJCXsKCQkJCXNoYXBlMS0+Z2V0Q2hpbGRBYWJiKGksdHJhbnMxLGJveHNoYXBlMS5tX21pbixib3hzaGFwZTEubV9tYXgpOwoKCQkJCWlmKGJveHNoYXBlMS5oYXNfY29sbGlzaW9uKGJveHNoYXBlMCkpCgkJCQl7CgkJCQkJcGFpcnNldC5wdXNoX3BhaXIoaSxqKTsKCQkJCX0KCQkJfQoJCX0KCX0KCgp9CgoKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmdpbXBhY3RfdnNfc2hhcGVfZmluZF9wYWlycygKCQkJCQkgIGNvbnN0IGJ0VHJhbnNmb3JtICYgdHJhbnMwLAoJCQkJCSAgY29uc3QgYnRUcmFuc2Zvcm0gJiB0cmFuczEsCgkJCQkJICBidEdJbXBhY3RTaGFwZUludGVyZmFjZSAqIHNoYXBlMCwKCQkJCQkgIGJ0Q29sbGlzaW9uU2hhcGUgKiBzaGFwZTEsCgkJCQkJICBidEFsaWduZWRPYmplY3RBcnJheTxpbnQ+ICYgY29sbGlkZWRfcHJpbWl0aXZlcykKewoKCWJ0QUFCQiBib3hzaGFwZTsKCgoJaWYoc2hhcGUwLT5oYXNCb3hTZXQoKSkKCXsKCQlidFRyYW5zZm9ybSB0cmFuczF0bzAgPSB0cmFuczAuaW52ZXJzZSgpOwoJCXRyYW5zMXRvMCAqPSB0cmFuczE7CgoJCXNoYXBlMS0+Z2V0QWFiYih0cmFuczF0bzAsYm94c2hhcGUubV9taW4sYm94c2hhcGUubV9tYXgpOwoKCQlzaGFwZTAtPmdldEJveFNldCgpLT5ib3hRdWVyeShib3hzaGFwZSwgY29sbGlkZWRfcHJpbWl0aXZlcyk7Cgl9CgllbHNlCgl7CgkJc2hhcGUxLT5nZXRBYWJiKHRyYW5zMSxib3hzaGFwZS5tX21pbixib3hzaGFwZS5tX21heCk7CgoJCWJ0QUFCQiBib3hzaGFwZTA7CgkJaW50IGkgPSBzaGFwZTAtPmdldE51bUNoaWxkU2hhcGVzKCk7CgoJCXdoaWxlKGktLSkKCQl7CgkJCXNoYXBlMC0+Z2V0Q2hpbGRBYWJiKGksdHJhbnMwLGJveHNoYXBlMC5tX21pbixib3hzaGFwZTAubV9tYXgpOwoKCQkJaWYoYm94c2hhcGUuaGFzX2NvbGxpc2lvbihib3hzaGFwZTApKQoJCQl7CgkJCQljb2xsaWRlZF9wcmltaXRpdmVzLnB1c2hfYmFjayhpKTsKCQkJfQoJCX0KCgl9Cgp9CgoKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmNvbGxpZGVfZ2prX3RyaWFuZ2xlcyhidENvbGxpc2lvbk9iamVjdCAqIGJvZHkwLAoJCQkJICBidENvbGxpc2lvbk9iamVjdCAqIGJvZHkxLAoJCQkJICBidEdJbXBhY3RNZXNoU2hhcGVQYXJ0ICogc2hhcGUwLAoJCQkJICBidEdJbXBhY3RNZXNoU2hhcGVQYXJ0ICogc2hhcGUxLAoJCQkJICBjb25zdCBpbnQgKiBwYWlycywgaW50IHBhaXJfY291bnQpCnsKCWJ0VHJpYW5nbGVTaGFwZUV4IHRyaTA7CglidFRyaWFuZ2xlU2hhcGVFeCB0cmkxOwoKCXNoYXBlMC0+bG9ja0NoaWxkU2hhcGVzKCk7CglzaGFwZTEtPmxvY2tDaGlsZFNoYXBlcygpOwoKCWNvbnN0IGludCAqIHBhaXJfcG9pbnRlciA9IHBhaXJzOwoKCXdoaWxlKHBhaXJfY291bnQtLSkKCXsKCgkJbV90cmlmYWNlMCA9ICoocGFpcl9wb2ludGVyKTsKCQltX3RyaWZhY2UxID0gKihwYWlyX3BvaW50ZXIrMSk7CgkJcGFpcl9wb2ludGVyKz0yOwoKCgoJCXNoYXBlMC0+Z2V0QnVsbGV0VHJpYW5nbGUobV90cmlmYWNlMCx0cmkwKTsKCQlzaGFwZTEtPmdldEJ1bGxldFRyaWFuZ2xlKG1fdHJpZmFjZTEsdHJpMSk7CgoKCQkvL2NvbGxpZGUgdHdvIGNvbnZleCBzaGFwZXMKCQlpZih0cmkwLm92ZXJsYXBfdGVzdF9jb25zZXJ2YXRpdmUodHJpMSkpCgkJewoJCQljb252ZXhfdnNfY29udmV4X2NvbGxpc2lvbihib2R5MCxib2R5MSwmdHJpMCwmdHJpMSk7CgkJfQoKCX0KCglzaGFwZTAtPnVubG9ja0NoaWxkU2hhcGVzKCk7CglzaGFwZTEtPnVubG9ja0NoaWxkU2hhcGVzKCk7Cn0KCnZvaWQgYnRHSW1wYWN0Q29sbGlzaW9uQWxnb3JpdGhtOjpjb2xsaWRlX3NhdF90cmlhbmdsZXMoYnRDb2xsaXNpb25PYmplY3QgKiBib2R5MCwKCQkJCQkgIGJ0Q29sbGlzaW9uT2JqZWN0ICogYm9keTEsCgkJCQkJICBidEdJbXBhY3RNZXNoU2hhcGVQYXJ0ICogc2hhcGUwLAoJCQkJCSAgYnRHSW1wYWN0TWVzaFNoYXBlUGFydCAqIHNoYXBlMSwKCQkJCQkgIGNvbnN0IGludCAqIHBhaXJzLCBpbnQgcGFpcl9jb3VudCkKewoJYnRUcmFuc2Zvcm0gb3JndHJhbnMwID0gYm9keTAtPmdldFdvcmxkVHJhbnNmb3JtKCk7CglidFRyYW5zZm9ybSBvcmd0cmFuczEgPSBib2R5MS0+Z2V0V29ybGRUcmFuc2Zvcm0oKTsKCglidFByaW1pdGl2ZVRyaWFuZ2xlIHB0cmkwOwoJYnRQcmltaXRpdmVUcmlhbmdsZSBwdHJpMTsKCUdJTV9UUklBTkdMRV9DT05UQUNUIGNvbnRhY3RfZGF0YTsKCglzaGFwZTAtPmxvY2tDaGlsZFNoYXBlcygpOwoJc2hhcGUxLT5sb2NrQ2hpbGRTaGFwZXMoKTsKCgljb25zdCBpbnQgKiBwYWlyX3BvaW50ZXIgPSBwYWlyczsKCgl3aGlsZShwYWlyX2NvdW50LS0pCgl7CgoJCW1fdHJpZmFjZTAgPSAqKHBhaXJfcG9pbnRlcik7CgkJbV90cmlmYWNlMSA9ICoocGFpcl9wb2ludGVyKzEpOwoJCXBhaXJfcG9pbnRlcis9MjsKCgoJCXNoYXBlMC0+Z2V0UHJpbWl0aXZlVHJpYW5nbGUobV90cmlmYWNlMCxwdHJpMCk7CgkJc2hhcGUxLT5nZXRQcmltaXRpdmVUcmlhbmdsZShtX3RyaWZhY2UxLHB0cmkxKTsKCgkJI2lmZGVmIFRSSV9DT0xMSVNJT05fUFJPRklMSU5HCgkJYnRfYmVnaW5fZ2ltMDJfdHJpX3RpbWUoKTsKCQkjZW5kaWYKCgkJcHRyaTAuYXBwbHlUcmFuc2Zvcm0ob3JndHJhbnMwKTsKCQlwdHJpMS5hcHBseVRyYW5zZm9ybShvcmd0cmFuczEpOwoKCgkJLy9idWlsZCBwbGFuZXMKCQlwdHJpMC5idWlsZFRyaVBsYW5lKCk7CgkJcHRyaTEuYnVpbGRUcmlQbGFuZSgpOwoJCS8vIHRlc3QgY29uc2VydmF0aXZlCgoKCgkJaWYocHRyaTAub3ZlcmxhcF90ZXN0X2NvbnNlcnZhdGl2ZShwdHJpMSkpCgkJewoJCQlpZihwdHJpMC5maW5kX3RyaWFuZ2xlX2NvbGxpc2lvbl9jbGlwX21ldGhvZChwdHJpMSxjb250YWN0X2RhdGEpKQoJCQl7CgoJCQkJaW50IGogPSBjb250YWN0X2RhdGEubV9wb2ludF9jb3VudDsKCQkJCXdoaWxlKGotLSkKCQkJCXsKCgkJCQkJYWRkQ29udGFjdFBvaW50KGJvZHkwLCBib2R5MSwKCQkJCQkJCQljb250YWN0X2RhdGEubV9wb2ludHNbal0sCgkJCQkJCQkJY29udGFjdF9kYXRhLm1fc2VwYXJhdGluZ19ub3JtYWwsCgkJCQkJCQkJLWNvbnRhY3RfZGF0YS5tX3BlbmV0cmF0aW9uX2RlcHRoKTsKCQkJCX0KCQkJfQoJCX0KCgkJI2lmZGVmIFRSSV9DT0xMSVNJT05fUFJPRklMSU5HCgkJYnRfZW5kX2dpbTAyX3RyaV90aW1lKCk7CgkJI2VuZGlmCgoJfQoKCXNoYXBlMC0+dW5sb2NrQ2hpbGRTaGFwZXMoKTsKCXNoYXBlMS0+dW5sb2NrQ2hpbGRTaGFwZXMoKTsKCn0KCgp2b2lkIGJ0R0ltcGFjdENvbGxpc2lvbkFsZ29yaXRobTo6Z2ltcGFjdF92c19naW1wYWN0KAoJCQkJCQlidENvbGxpc2lvbk9iamVjdCAqIGJvZHkwLAoJCQkJCSAgIAlidENvbGxpc2lvbk9iamVjdCAqIGJvZHkxLAoJCQkJCSAgCWJ0R0ltcGFjdFNoYXBlSW50ZXJmYWNlICogc2hhcGUwLAoJCQkJCSAgCWJ0R0ltcGFjdFNoYXBlSW50ZXJmYWNlICogc2hhcGUxKQp7CgoJaWYoc2hhcGUwLT5nZXRHSW1wYWN0U2hhcGVUeXBlKCk9PUNPTlNUX0dJTVBBQ1RfVFJJTUVTSF9TSEFQRSkKCXsKCQlidEdJbXBhY3RNZXNoU2hhcGUgKiBtZXNoc2hhcGUwID0gc3RhdGljX2Nhc3Q8YnRHSW1wYWN0TWVzaFNoYXBlICo+KHNoYXBlMCk7CgkJbV9wYXJ0MCA9IG1lc2hzaGFwZTAtPmdldE1lc2hQYXJ0Q291bnQoKTsKCgkJd2hpbGUobV9wYXJ0MC0tKQoJCXsKCQkJZ2ltcGFjdF92c19naW1wYWN0KGJvZHkwLGJvZHkxLG1lc2hzaGFwZTAtPmdldE1lc2hQYXJ0KG1fcGFydDApLHNoYXBlMSk7CgkJfQoKCQlyZXR1cm47Cgl9CgoJaWYoc2hhcGUxLT5nZXRHSW1wYWN0U2hhcGVUeXBlKCk9PUNPTlNUX0dJTVBBQ1RfVFJJTUVTSF9TSEFQRSkKCXsKCQlidEdJbXBhY3RNZXNoU2hhcGUgKiBtZXNoc2hhcGUxID0gc3RhdGljX2Nhc3Q8YnRHSW1wYWN0TWVzaFNoYXBlICo+KHNoYXBlMSk7CgkJbV9wYXJ0MSA9IG1lc2hzaGFwZTEtPmdldE1lc2hQYXJ0Q291bnQoKTsKCgkJd2hpbGUobV9wYXJ0MS0tKQoJCXsKCgkJCWdpbXBhY3RfdnNfZ2ltcGFjdChib2R5MCxib2R5MSxzaGFwZTAsbWVzaHNoYXBlMS0+Z2V0TWVzaFBhcnQobV9wYXJ0MSkpOwoKCQl9CgoJCXJldHVybjsKCX0KCgoJYnRUcmFuc2Zvcm0gb3JndHJhbnMwID0gYm9keTAtPmdldFdvcmxkVHJhbnNmb3JtKCk7CglidFRyYW5zZm9ybSBvcmd0cmFuczEgPSBib2R5MS0+Z2V0V29ybGRUcmFuc2Zvcm0oKTsKCglidFBhaXJTZXQgcGFpcnNldDsKCglnaW1wYWN0X3ZzX2dpbXBhY3RfZmluZF9wYWlycyhvcmd0cmFuczAsb3JndHJhbnMxLHNoYXBlMCxzaGFwZTEscGFpcnNldCk7CgoJaWYocGFpcnNldC5zaXplKCk9PSAwKSByZXR1cm47CgoJaWYoc2hhcGUwLT5nZXRHSW1wYWN0U2hhcGVUeXBlKCkgPT0gQ09OU1RfR0lNUEFDVF9UUklNRVNIX1NIQVBFX1BBUlQgJiYKCQlzaGFwZTEtPmdldEdJbXBhY3RTaGFwZVR5cGUoKSA9PSBDT05TVF9HSU1QQUNUX1RSSU1FU0hfU0hBUEVfUEFSVCkKCXsKCQlidEdJbXBhY3RNZXNoU2hhcGVQYXJ0ICogc2hhcGVwYXJ0MCA9IHN0YXRpY19jYXN0PGJ0R0ltcGFjdE1lc2hTaGFwZVBhcnQgKiA+KHNoYXBlMCk7CgkJYnRHSW1wYWN0TWVzaFNoYXBlUGFydCAqIHNoYXBlcGFydDEgPSBzdGF0aWNfY2FzdDxidEdJbXBhY3RNZXNoU2hhcGVQYXJ0ICogPihzaGFwZTEpOwoJCS8vc3BlY2lhbGl6ZWQgZnVuY3Rpb24KCQkjaWZkZWYgQlVMTEVUX1RSSUFOR0xFX0NPTExJU0lPTgoJCWNvbGxpZGVfZ2prX3RyaWFuZ2xlcyhib2R5MCxib2R5MSxzaGFwZXBhcnQwLHNoYXBlcGFydDEsJnBhaXJzZXRbMF0ubV9pbmRleDEscGFpcnNldC5zaXplKCkpOwoJCSNlbHNlCgkJY29sbGlkZV9zYXRfdHJpYW5nbGVzKGJvZHkwLGJvZHkxLHNoYXBlcGFydDAsc2hhcGVwYXJ0MSwmcGFpcnNldFswXS5tX2luZGV4MSxwYWlyc2V0LnNpemUoKSk7CgkJI2VuZGlmCgoJCXJldHVybjsKCX0KCgkvL2dlbmVyYWwgZnVuY3Rpb24KCglzaGFwZTAtPmxvY2tDaGlsZFNoYXBlcygpOwoJc2hhcGUxLT5sb2NrQ2hpbGRTaGFwZXMoKTsKCglHSU1fU2hhcGVSZXRyaWV2ZXIgcmV0cmlldmVyMChzaGFwZTApOwoJR0lNX1NoYXBlUmV0cmlldmVyIHJldHJpZXZlcjEoc2hhcGUxKTsKCglib29sIGNoaWxkX2hhc190cmFuc2Zvcm0wID0gc2hhcGUwLT5jaGlsZHJlbkhhc1RyYW5zZm9ybSgpOwoJYm9vbCBjaGlsZF9oYXNfdHJhbnNmb3JtMSA9IHNoYXBlMS0+Y2hpbGRyZW5IYXNUcmFuc2Zvcm0oKTsKCglpbnQgaSA9IHBhaXJzZXQuc2l6ZSgpOwoJd2hpbGUoaS0tKQoJewoJCUdJTV9QQUlSICogcGFpciA9ICZwYWlyc2V0W2ldOwoJCW1fdHJpZmFjZTAgPSBwYWlyLT5tX2luZGV4MTsKCQltX3RyaWZhY2UxID0gcGFpci0+bV9pbmRleDI7CgkJYnRDb2xsaXNpb25TaGFwZSAqIGNvbHNoYXBlMCA9IHJldHJpZXZlcjAuZ2V0Q2hpbGRTaGFwZShtX3RyaWZhY2UwKTsKCQlidENvbGxpc2lvblNoYXBlICogY29sc2hhcGUxID0gcmV0cmlldmVyMS5nZXRDaGlsZFNoYXBlKG1fdHJpZmFjZTEpOwoKCQlpZihjaGlsZF9oYXNfdHJhbnNmb3JtMCkKCQl7CgkJCWJvZHkwLT5zZXRXb3JsZFRyYW5zZm9ybShvcmd0cmFuczAqc2hhcGUwLT5nZXRDaGlsZFRyYW5zZm9ybShtX3RyaWZhY2UwKSk7CgkJfQoKCQlpZihjaGlsZF9oYXNfdHJhbnNmb3JtMSkKCQl7CgkJCWJvZHkxLT5zZXRXb3JsZFRyYW5zZm9ybShvcmd0cmFuczEqc2hhcGUxLT5nZXRDaGlsZFRyYW5zZm9ybShtX3RyaWZhY2UxKSk7CgkJfQoKCQkvL2NvbGxpZGUgdHdvIGNvbnZleCBzaGFwZXMKCQljb252ZXhfdnNfY29udmV4X2NvbGxpc2lvbihib2R5MCxib2R5MSxjb2xzaGFwZTAsY29sc2hhcGUxKTsKCgoJCWlmKGNoaWxkX2hhc190cmFuc2Zvcm0wKQoJCXsKCQkJYm9keTAtPnNldFdvcmxkVHJhbnNmb3JtKG9yZ3RyYW5zMCk7CgkJfQoKCQlpZihjaGlsZF9oYXNfdHJhbnNmb3JtMSkKCQl7CgkJCWJvZHkxLT5zZXRXb3JsZFRyYW5zZm9ybShvcmd0cmFuczEpOwoJCX0KCgl9CgoJc2hhcGUwLT51bmxvY2tDaGlsZFNoYXBlcygpOwoJc2hhcGUxLT51bmxvY2tDaGlsZFNoYXBlcygpOwp9Cgp2b2lkIGJ0R0ltcGFjdENvbGxpc2lvbkFsZ29yaXRobTo6Z2ltcGFjdF92c19zaGFwZShidENvbGxpc2lvbk9iamVjdCAqIGJvZHkwLAoJCQkJICBidENvbGxpc2lvbk9iamVjdCAqIGJvZHkxLAoJCQkJICBidEdJbXBhY3RTaGFwZUludGVyZmFjZSAqIHNoYXBlMCwKCQkJCSAgYnRDb2xsaXNpb25TaGFwZSAqIHNoYXBlMSxib29sIHN3YXBwZWQpCnsKCWlmKHNoYXBlMC0+Z2V0R0ltcGFjdFNoYXBlVHlwZSgpPT1DT05TVF9HSU1QQUNUX1RSSU1FU0hfU0hBUEUpCgl7CgkJYnRHSW1wYWN0TWVzaFNoYXBlICogbWVzaHNoYXBlMCA9IHN0YXRpY19jYXN0PGJ0R0ltcGFjdE1lc2hTaGFwZSAqPihzaGFwZTApOwoJCWludCYgcGFydCA9IHN3YXBwZWQgPyBtX3BhcnQxIDogbV9wYXJ0MDsKCQlwYXJ0ID0gbWVzaHNoYXBlMC0+Z2V0TWVzaFBhcnRDb3VudCgpOwoKCQl3aGlsZShwYXJ0LS0pCgkJewoKCQkJZ2ltcGFjdF92c19zaGFwZShib2R5MCwKCQkJCSAgYm9keTEsCgkJCQkgIG1lc2hzaGFwZTAtPmdldE1lc2hQYXJ0KHBhcnQpLAoJCQkJICBzaGFwZTEsc3dhcHBlZCk7CgoJCX0KCgkJcmV0dXJuOwoJfQoKCSNpZmRlZiBHSU1QQUNUX1ZTX1BMQU5FX0NPTExJU0lPTgoJaWYoc2hhcGUwLT5nZXRHSW1wYWN0U2hhcGVUeXBlKCkgPT0gQ09OU1RfR0lNUEFDVF9UUklNRVNIX1NIQVBFX1BBUlQgJiYKCQlzaGFwZTEtPmdldFNoYXBlVHlwZSgpID09IFNUQVRJQ19QTEFORV9QUk9YWVRZUEUpCgl7CgkJYnRHSW1wYWN0TWVzaFNoYXBlUGFydCAqIHNoYXBlcGFydCA9IHN0YXRpY19jYXN0PGJ0R0ltcGFjdE1lc2hTaGFwZVBhcnQgKj4oc2hhcGUwKTsKCQlidFN0YXRpY1BsYW5lU2hhcGUgKiBwbGFuZXNoYXBlID0gc3RhdGljX2Nhc3Q8YnRTdGF0aWNQbGFuZVNoYXBlICogPihzaGFwZTEpOwoJCWdpbXBhY3R0cmltZXNocGFydF92c19wbGFuZV9jb2xsaXNpb24oYm9keTAsYm9keTEsc2hhcGVwYXJ0LHBsYW5lc2hhcGUsc3dhcHBlZCk7CgkJcmV0dXJuOwoJfQoKCSNlbmRpZgoKCgoJaWYoc2hhcGUxLT5pc0NvbXBvdW5kKCkpCgl7CgkJYnRDb21wb3VuZFNoYXBlICogY29tcG91bmRzaGFwZSA9IHN0YXRpY19jYXN0PGJ0Q29tcG91bmRTaGFwZSAqPihzaGFwZTEpOwoJCWdpbXBhY3RfdnNfY29tcG91bmRzaGFwZShib2R5MCxib2R5MSxzaGFwZTAsY29tcG91bmRzaGFwZSxzd2FwcGVkKTsKCQlyZXR1cm47Cgl9CgllbHNlIGlmKHNoYXBlMS0+aXNDb25jYXZlKCkpCgl7CgkJYnRDb25jYXZlU2hhcGUgKiBjb25jYXZlc2hhcGUgPSBzdGF0aWNfY2FzdDxidENvbmNhdmVTaGFwZSAqPihzaGFwZTEpOwoJCWdpbXBhY3RfdnNfY29uY2F2ZShib2R5MCxib2R5MSxzaGFwZTAsY29uY2F2ZXNoYXBlLHN3YXBwZWQpOwoJCXJldHVybjsKCX0KCgoJYnRUcmFuc2Zvcm0gb3JndHJhbnMwID0gYm9keTAtPmdldFdvcmxkVHJhbnNmb3JtKCk7CgoJYnRUcmFuc2Zvcm0gb3JndHJhbnMxID0gYm9keTEtPmdldFdvcmxkVHJhbnNmb3JtKCk7CgoJYnRBbGlnbmVkT2JqZWN0QXJyYXk8aW50PiBjb2xsaWRlZF9yZXN1bHRzOwoKCWdpbXBhY3RfdnNfc2hhcGVfZmluZF9wYWlycyhvcmd0cmFuczAsb3JndHJhbnMxLHNoYXBlMCxzaGFwZTEsY29sbGlkZWRfcmVzdWx0cyk7CgoJaWYoY29sbGlkZWRfcmVzdWx0cy5zaXplKCkgPT0gMCkgcmV0dXJuOwoKCglzaGFwZTAtPmxvY2tDaGlsZFNoYXBlcygpOwoKCUdJTV9TaGFwZVJldHJpZXZlciByZXRyaWV2ZXIwKHNoYXBlMCk7CgoKCWJvb2wgY2hpbGRfaGFzX3RyYW5zZm9ybTAgPSBzaGFwZTAtPmNoaWxkcmVuSGFzVHJhbnNmb3JtKCk7CgoKCWludCBpID0gY29sbGlkZWRfcmVzdWx0cy5zaXplKCk7CgoJd2hpbGUoaS0tKQoJewoJCWludCBjaGlsZF9pbmRleCA9IGNvbGxpZGVkX3Jlc3VsdHNbaV07CiAgICAgICAgaWYoc3dhcHBlZCkKICAgIAkJbV90cmlmYWNlMSA9IGNoaWxkX2luZGV4OwogICAgICAgIGVsc2UKICAgICAgICAgICAgbV90cmlmYWNlMCA9IGNoaWxkX2luZGV4OwoKCQlidENvbGxpc2lvblNoYXBlICogY29sc2hhcGUwID0gcmV0cmlldmVyMC5nZXRDaGlsZFNoYXBlKGNoaWxkX2luZGV4KTsKCgkJaWYoY2hpbGRfaGFzX3RyYW5zZm9ybTApCgkJewoJCQlib2R5MC0+c2V0V29ybGRUcmFuc2Zvcm0ob3JndHJhbnMwKnNoYXBlMC0+Z2V0Q2hpbGRUcmFuc2Zvcm0oY2hpbGRfaW5kZXgpKTsKCQl9CgoJCS8vY29sbGlkZSB0d28gc2hhcGVzCgkJaWYoc3dhcHBlZCkKCQl7CgkJCXNoYXBlX3ZzX3NoYXBlX2NvbGxpc2lvbihib2R5MSxib2R5MCxzaGFwZTEsY29sc2hhcGUwKTsKCQl9CgkJZWxzZQoJCXsKCQkJc2hhcGVfdnNfc2hhcGVfY29sbGlzaW9uKGJvZHkwLGJvZHkxLGNvbHNoYXBlMCxzaGFwZTEpOwoJCX0KCgkJLy9yZXN0b3JlIHRyYW5zZm9ybXMKCQlpZihjaGlsZF9oYXNfdHJhbnNmb3JtMCkKCQl7CgkJCWJvZHkwLT5zZXRXb3JsZFRyYW5zZm9ybShvcmd0cmFuczApOwoJCX0KCgl9CgoJc2hhcGUwLT51bmxvY2tDaGlsZFNoYXBlcygpOwoKfQoKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmdpbXBhY3RfdnNfY29tcG91bmRzaGFwZShidENvbGxpc2lvbk9iamVjdCAqIGJvZHkwLAoJCQkJICBidENvbGxpc2lvbk9iamVjdCAqIGJvZHkxLAoJCQkJICBidEdJbXBhY3RTaGFwZUludGVyZmFjZSAqIHNoYXBlMCwKCQkJCSAgYnRDb21wb3VuZFNoYXBlICogc2hhcGUxLGJvb2wgc3dhcHBlZCkKewoJYnRUcmFuc2Zvcm0gb3JndHJhbnMxID0gYm9keTEtPmdldFdvcmxkVHJhbnNmb3JtKCk7CgoJaW50IGkgPSBzaGFwZTEtPmdldE51bUNoaWxkU2hhcGVzKCk7Cgl3aGlsZShpLS0pCgl7CgoJCWJ0Q29sbGlzaW9uU2hhcGUgKiBjb2xzaGFwZTEgPSBzaGFwZTEtPmdldENoaWxkU2hhcGUoaSk7CgkJYnRUcmFuc2Zvcm0gY2hpbGR0cmFuczEgPSBvcmd0cmFuczEqc2hhcGUxLT5nZXRDaGlsZFRyYW5zZm9ybShpKTsKCgkJYm9keTEtPnNldFdvcmxkVHJhbnNmb3JtKGNoaWxkdHJhbnMxKTsKCgkJLy9jb2xsaWRlIGNoaWxkIHNoYXBlCgkJZ2ltcGFjdF92c19zaGFwZShib2R5MCwgYm9keTEsCgkJCQkJICBzaGFwZTAsY29sc2hhcGUxLHN3YXBwZWQpOwoKCgkJLy9yZXN0b3JlIHRyYW5zZm9ybXMKCQlib2R5MS0+c2V0V29ybGRUcmFuc2Zvcm0ob3JndHJhbnMxKTsKCX0KfQoKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmdpbXBhY3R0cmltZXNocGFydF92c19wbGFuZV9jb2xsaXNpb24oCgkJCQkJICBidENvbGxpc2lvbk9iamVjdCAqIGJvZHkwLAoJCQkJCSAgYnRDb2xsaXNpb25PYmplY3QgKiBib2R5MSwKCQkJCQkgIGJ0R0ltcGFjdE1lc2hTaGFwZVBhcnQgKiBzaGFwZTAsCgkJCQkJICBidFN0YXRpY1BsYW5lU2hhcGUgKiBzaGFwZTEsYm9vbCBzd2FwcGVkKQp7CgoKCWJ0VHJhbnNmb3JtIG9yZ3RyYW5zMCA9IGJvZHkwLT5nZXRXb3JsZFRyYW5zZm9ybSgpOwoJYnRUcmFuc2Zvcm0gb3JndHJhbnMxID0gYm9keTEtPmdldFdvcmxkVHJhbnNmb3JtKCk7CgoJYnRQbGFuZVNoYXBlICogcGxhbmVzaGFwZSA9IHN0YXRpY19jYXN0PGJ0UGxhbmVTaGFwZSAqPihzaGFwZTEpOwoJYnRWZWN0b3I0IHBsYW5lOwoJcGxhbmVzaGFwZS0+Z2V0X3BsYW5lX2VxdWF0aW9uX3RyYW5zZm9ybWVkKG9yZ3RyYW5zMSxwbGFuZSk7CgoJLy90ZXN0IGJveCBhZ2FpbnN0IHBsYW5lCgoJYnRBQUJCIHRyaWJveDsKCXNoYXBlMC0+Z2V0QWFiYihvcmd0cmFuczAsdHJpYm94Lm1fbWluLHRyaWJveC5tX21heCk7Cgl0cmlib3guaW5jcmVtZW50X21hcmdpbihwbGFuZXNoYXBlLT5nZXRNYXJnaW4oKSk7CgoJaWYoIHRyaWJveC5wbGFuZV9jbGFzc2lmeShwbGFuZSkhPSBCVF9DT05TVF9DT0xMSURFX1BMQU5FKSByZXR1cm47CgoJc2hhcGUwLT5sb2NrQ2hpbGRTaGFwZXMoKTsKCglidFNjYWxhciBtYXJnaW4gPSBzaGFwZTAtPmdldE1hcmdpbigpICsgcGxhbmVzaGFwZS0+Z2V0TWFyZ2luKCk7CgoJYnRWZWN0b3IzIHZlcnRleDsKCWludCB2aSA9IHNoYXBlMC0+Z2V0VmVydGV4Q291bnQoKTsKCXdoaWxlKHZpLS0pCgl7CgkJc2hhcGUwLT5nZXRWZXJ0ZXgodmksdmVydGV4KTsKCQl2ZXJ0ZXggPSBvcmd0cmFuczAodmVydGV4KTsKCgkJYnRTY2FsYXIgZGlzdGFuY2UgPSB2ZXJ0ZXguZG90KHBsYW5lKSAtIHBsYW5lWzNdIC0gbWFyZ2luOwoKCQlpZihkaXN0YW5jZTwwLjApLy9hZGQgY29udGFjdAoJCXsKCQkJaWYoc3dhcHBlZCkKCQkJewoJCQkJYWRkQ29udGFjdFBvaW50KGJvZHkxLCBib2R5MCwKCQkJCQl2ZXJ0ZXgsCgkJCQkJLXBsYW5lLAoJCQkJCWRpc3RhbmNlKTsKCQkJfQoJCQllbHNlCgkJCXsKCQkJCWFkZENvbnRhY3RQb2ludChib2R5MCwgYm9keTEsCgkJCQkJdmVydGV4LAoJCQkJCXBsYW5lLAoJCQkJCWRpc3RhbmNlKTsKCQkJfQoJCX0KCX0KCglzaGFwZTAtPnVubG9ja0NoaWxkU2hhcGVzKCk7Cn0KCgoKCmNsYXNzIGJ0R0ltcGFjdFRyaWFuZ2xlQ2FsbGJhY2s6IHB1YmxpYyBidFRyaWFuZ2xlQ2FsbGJhY2sKewpwdWJsaWM6CglidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG0gKiBhbGdvcml0aG07CglidENvbGxpc2lvbk9iamVjdCAqIGJvZHkwOwoJYnRDb2xsaXNpb25PYmplY3QgKiBib2R5MTsKCWJ0R0ltcGFjdFNoYXBlSW50ZXJmYWNlICogZ2ltcGFjdHNoYXBlMDsKCWJvb2wgc3dhcHBlZDsKCWJ0U2NhbGFyIG1hcmdpbjsKCgl2aXJ0dWFsIHZvaWQgcHJvY2Vzc1RyaWFuZ2xlKGJ0VmVjdG9yMyogdHJpYW5nbGUsIGludCBwYXJ0SWQsIGludCB0cmlhbmdsZUluZGV4KQoJewoJCWJ0VHJpYW5nbGVTaGFwZUV4IHRyaTEodHJpYW5nbGVbMF0sdHJpYW5nbGVbMV0sdHJpYW5nbGVbMl0pOwoJCXRyaTEuc2V0TWFyZ2luKG1hcmdpbik7CiAgICAgICAgaWYoc3dhcHBlZCkKICAgICAgICB7CiAgICAgICAgICAgIGFsZ29yaXRobS0+c2V0UGFydDAocGFydElkKTsKICAgICAgICAgICAgYWxnb3JpdGhtLT5zZXRGYWNlMCh0cmlhbmdsZUluZGV4KTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgYWxnb3JpdGhtLT5zZXRQYXJ0MShwYXJ0SWQpOwogICAgICAgICAgICBhbGdvcml0aG0tPnNldEZhY2UxKHRyaWFuZ2xlSW5kZXgpOwogICAgICAgIH0KCQlhbGdvcml0aG0tPmdpbXBhY3RfdnNfc2hhcGUoCgkJCQkJCQlib2R5MCxib2R5MSxnaW1wYWN0c2hhcGUwLCZ0cmkxLHN3YXBwZWQpOwoJfQp9OwoKCgoKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmdpbXBhY3RfdnNfY29uY2F2ZSgKCQkJCSAgYnRDb2xsaXNpb25PYmplY3QgKiBib2R5MCwKCQkJCSAgYnRDb2xsaXNpb25PYmplY3QgKiBib2R5MSwKCQkJCSAgYnRHSW1wYWN0U2hhcGVJbnRlcmZhY2UgKiBzaGFwZTAsCgkJCQkgIGJ0Q29uY2F2ZVNoYXBlICogc2hhcGUxLGJvb2wgc3dhcHBlZCkKewoJLy9jcmVhdGUgdGhlIGNhbGxiYWNrCglidEdJbXBhY3RUcmlhbmdsZUNhbGxiYWNrIHRyaWNhbGxiYWNrOwoJdHJpY2FsbGJhY2suYWxnb3JpdGhtID0gdGhpczsKCXRyaWNhbGxiYWNrLmJvZHkwID0gYm9keTA7Cgl0cmljYWxsYmFjay5ib2R5MSA9IGJvZHkxOwoJdHJpY2FsbGJhY2suZ2ltcGFjdHNoYXBlMCA9IHNoYXBlMDsKCXRyaWNhbGxiYWNrLnN3YXBwZWQgPSBzd2FwcGVkOwoJdHJpY2FsbGJhY2subWFyZ2luID0gc2hhcGUxLT5nZXRNYXJnaW4oKTsKCgkvL2dldHRpbmcgdGhlIHRyaW1lc2ggQUFCQgoJYnRUcmFuc2Zvcm0gZ2ltcGFjdEluQ29uY2F2ZVNwYWNlOwoKCWdpbXBhY3RJbkNvbmNhdmVTcGFjZSA9IGJvZHkxLT5nZXRXb3JsZFRyYW5zZm9ybSgpLmludmVyc2UoKSAqIGJvZHkwLT5nZXRXb3JsZFRyYW5zZm9ybSgpOwoKCWJ0VmVjdG9yMyBtaW5BQUJCLG1heEFBQkI7CglzaGFwZTAtPmdldEFhYmIoZ2ltcGFjdEluQ29uY2F2ZVNwYWNlLG1pbkFBQkIsbWF4QUFCQik7CgoJc2hhcGUxLT5wcm9jZXNzQWxsVHJpYW5nbGVzKCZ0cmljYWxsYmFjayxtaW5BQUJCLG1heEFBQkIpOwoKfQoKCgp2b2lkIGJ0R0ltcGFjdENvbGxpc2lvbkFsZ29yaXRobTo6cHJvY2Vzc0NvbGxpc2lvbiAoYnRDb2xsaXNpb25PYmplY3QqIGJvZHkwLGJ0Q29sbGlzaW9uT2JqZWN0KiBib2R5MSxjb25zdCBidERpc3BhdGNoZXJJbmZvJiBkaXNwYXRjaEluZm8sYnRNYW5pZm9sZFJlc3VsdCogcmVzdWx0T3V0KQp7CiAgICBjbGVhckNhY2hlKCk7CgogICAgbV9yZXN1bHRPdXQgPSByZXN1bHRPdXQ7CgltX2Rpc3BhdGNoSW5mbyA9ICZkaXNwYXRjaEluZm87CiAgICBidEdJbXBhY3RTaGFwZUludGVyZmFjZSAqIGdpbXBhY3RzaGFwZTA7CiAgICBidEdJbXBhY3RTaGFwZUludGVyZmFjZSAqIGdpbXBhY3RzaGFwZTE7CgoJaWYgKGJvZHkwLT5nZXRDb2xsaXNpb25TaGFwZSgpLT5nZXRTaGFwZVR5cGUoKT09R0lNUEFDVF9TSEFQRV9QUk9YWVRZUEUpCgl7CgkJZ2ltcGFjdHNoYXBlMCA9IHN0YXRpY19jYXN0PGJ0R0ltcGFjdFNoYXBlSW50ZXJmYWNlICo+KGJvZHkwLT5nZXRDb2xsaXNpb25TaGFwZSgpKTsKCgkJaWYoIGJvZHkxLT5nZXRDb2xsaXNpb25TaGFwZSgpLT5nZXRTaGFwZVR5cGUoKT09R0lNUEFDVF9TSEFQRV9QUk9YWVRZUEUgKQoJCXsKCQkJZ2ltcGFjdHNoYXBlMSA9IHN0YXRpY19jYXN0PGJ0R0ltcGFjdFNoYXBlSW50ZXJmYWNlICo+KGJvZHkxLT5nZXRDb2xsaXNpb25TaGFwZSgpKTsKCgkJCWdpbXBhY3RfdnNfZ2ltcGFjdChib2R5MCxib2R5MSxnaW1wYWN0c2hhcGUwLGdpbXBhY3RzaGFwZTEpOwoJCX0KCQllbHNlCgkJewoJCQlnaW1wYWN0X3ZzX3NoYXBlKGJvZHkwLGJvZHkxLGdpbXBhY3RzaGFwZTAsYm9keTEtPmdldENvbGxpc2lvblNoYXBlKCksZmFsc2UpOwoJCX0KCgl9CgllbHNlIGlmIChib2R5MS0+Z2V0Q29sbGlzaW9uU2hhcGUoKS0+Z2V0U2hhcGVUeXBlKCk9PUdJTVBBQ1RfU0hBUEVfUFJPWFlUWVBFICkKCXsKCQlnaW1wYWN0c2hhcGUxID0gc3RhdGljX2Nhc3Q8YnRHSW1wYWN0U2hhcGVJbnRlcmZhY2UgKj4oYm9keTEtPmdldENvbGxpc2lvblNoYXBlKCkpOwoKCQlnaW1wYWN0X3ZzX3NoYXBlKGJvZHkxLGJvZHkwLGdpbXBhY3RzaGFwZTEsYm9keTAtPmdldENvbGxpc2lvblNoYXBlKCksdHJ1ZSk7Cgl9Cn0KCgpidFNjYWxhciBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OmNhbGN1bGF0ZVRpbWVPZkltcGFjdChidENvbGxpc2lvbk9iamVjdCogYm9keTAsYnRDb2xsaXNpb25PYmplY3QqIGJvZHkxLGNvbnN0IGJ0RGlzcGF0Y2hlckluZm8mIGRpc3BhdGNoSW5mbyxidE1hbmlmb2xkUmVzdWx0KiByZXN1bHRPdXQpCnsKCXJldHVybiAxLmY7Cgp9CgovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vIFJFR0lTVEVSSU5HIEFMR09SSVRITSAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCgpidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OkNyZWF0ZUZ1bmMgZ19naW1wYWN0X2NmOwoKLy8hIFVzZSB0aGlzIGZ1bmN0aW9uIGZvciByZWdpc3RlciB0aGUgYWxnb3JpdGhtIGV4dGVybmFsbHkKdm9pZCBidEdJbXBhY3RDb2xsaXNpb25BbGdvcml0aG06OnJlZ2lzdGVyQWxnb3JpdGhtKGJ0Q29sbGlzaW9uRGlzcGF0Y2hlciAqIGRpc3BhdGNoZXIpCnsKCglpbnQgaTsKCglmb3IgKCBpID0gMDtpIDwgTUFYX0JST0FEUEhBU0VfQ09MTElTSU9OX1RZUEVTIDtpKysgKQoJewoJCWRpc3BhdGNoZXItPnJlZ2lzdGVyQ29sbGlzaW9uQ3JlYXRlRnVuYyhHSU1QQUNUX1NIQVBFX1BST1hZVFlQRSxpICwmZ19naW1wYWN0X2NmKTsKCX0KCglmb3IgKCBpID0gMDtpIDwgTUFYX0JST0FEUEhBU0VfQ09MTElTSU9OX1RZUEVTIDtpKysgKQoJewoJCWRpc3BhdGNoZXItPnJlZ2lzdGVyQ29sbGlzaW9uQ3JlYXRlRnVuYyhpLEdJTVBBQ1RfU0hBUEVfUFJPWFlUWVBFICwmZ19naW1wYWN0X2NmKTsKCX0KCn0K