LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiBDb3B5cmlnaHQgKEMpIDIwMTggYnkgU2F2b2lyLWZhaXJlIExpbnV4ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCiAqIEF1dGhvcjogSXNhIE5hbmljIDxpc2EubmFuaWNAc2F2b2lyZmFpcmVsaW51eC5jb20+ICAgICAgICAgICAgICAgICAgICAgICoKICogQXV0aG9yOiBFZHJpYyBMYWRlbnQgTWlsYXJldCA8ZWRyaWMubGFkZW50LW1pbGFyZXRAc2F2b2lyZmFpcmVsaW51eC5jb20+KgogKiBBdXRob3I6IEFudGhvbnkgTOlvbmFyZCA8YW50aG9ueS5sZW9uYXJkQHNhdm9pcmZhaXJlbGludXguY29tPiAgICAgICAgICAqCiAqIEF1dGhvcjogT2xpdmllciBTb2xkYW5vIDxvbGl2aWVyLnNvbGRhbm9Ac2F2b2lyZmFpcmVsaW51eC5jb20+ICAgICAgICAgICoKICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKgogKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSAgICAqCiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5ICAgICoKICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgICAgICAgKgogKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsICAgICAgICAgKgogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiAgICAgICAgICAqCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgICAgICAgICAgICoKICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKgogKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlICAgICAgICoKICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW0uICBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LiAgICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwojaW5jbHVkZSA8UVBpeG1hcD4KI2luY2x1ZGUgPFFUaW1lcj4KI2luY2x1ZGUgPFFNb2RlbEluZGV4PgojaW5jbHVkZSA8UUZpbGVEaWFsb2c+CiNpbmNsdWRlIDxRSW5wdXREaWFsb2c+CiNpbmNsdWRlIDxRU3RhbmRhcmRQYXRocz4KI2luY2x1ZGUgPFFNZXNzYWdlQm94PgoKLy8gYWNjb3VudCBzZXR0aW5ncwojaW5jbHVkZSAiYXBpL25ld2RldmljZW1vZGVsLmgiCiNpbmNsdWRlICJzZXR0aW5nc2l0ZW13aWRnZXQuaCIKCiNpbmNsdWRlICJzZXR0aW5nc3dpZGdldC5oIgojaW5jbHVkZSAidWlfc2V0dGluZ3N3aWRnZXQuaCIKCiNpbmNsdWRlICJ1aV9hZHZhbmNlZHNldHRpbmdzd2lkZ2V0LmgiCgojaW5jbHVkZSAicGFzc3dvcmRkaWFsb2cuaCIKCiNpbmNsdWRlICJyZWduYW1lZGlhbG9nLmgiCiNpbmNsdWRlICJ1aV9yZWduYW1lZGlhbG9nLmgiCgojaW5jbHVkZSAic2V0YXZhdGFyZGlhbG9nLmgiCiNpbmNsdWRlICJ1aV9zZXRhdmF0YXJkaWFsb2cuaCIKCiNpbmNsdWRlICJkZWxldGVhY2NvdW50ZGlhbG9nLmgiCiNpbmNsdWRlICJ1aV9kZWxldGVhY2NvdW50ZGlhbG9nLmgiCgoKLy8gZ2VuZXJhbCBTZXR0aW5ncwojaW5jbHVkZSAid2luc3BhcmtsZS5oIgojaW5jbHVkZSAibWVkaWEvcmVjb3JkaW5nbW9kZWwuaCIKCi8vIGF2IHNldHR0aW5ncwojaW5jbHVkZSAiYXVkaW8vc2V0dGluZ3MuaCIKI2luY2x1ZGUgImF1ZGlvL291dHB1dGRldmljZW1vZGVsLmgiCiNpbmNsdWRlICJhdWRpby9pbnB1dGRldmljZW1vZGVsLmgiCgojaW5jbHVkZSAidmlkZW8vZGV2aWNlbW9kZWwuaCIKI2luY2x1ZGUgInZpZGVvL2NoYW5uZWwuaCIKI2luY2x1ZGUgInZpZGVvL3Jlc29sdXRpb24uaCIKI2luY2x1ZGUgInZpZGVvL3JhdGUuaCIKI2luY2x1ZGUgInZpZGVvL3ByZXZpZXdtYW5hZ2VyLmgiCgojaW5jbHVkZSAiY2FsbG1vZGVsLmgiCgpTZXR0aW5nc1dpZGdldDo6U2V0dGluZ3NXaWRnZXQoUVdpZGdldCogcGFyZW50KQogICAgOiBOYXZXaWRnZXQocGFyZW50KSwKICAgIHVpKG5ldyBVaTo6U2V0dGluZ3NXaWRnZXQpLAogICAgc2Nyb2xsQXJlYV8obmV3IFFTY3JvbGxBcmVhKSwKICAgIGRldmljZU1vZGVsXygmVmlkZW86OkRldmljZU1vZGVsOjppbnN0YW5jZSgpKSwKICAgIGdpZihuZXcgUU1vdmllKCI6L2ltYWdlcy9hamF4LWxvYWRlci5naWYiKSkKewogICAgdWktPnNldHVwVWkodGhpcyk7CgogICAgdWktPmFjY291bnRTZXR0aW5nc0J1dHRvbi0+c2V0QXV0b0ZpbGxCYWNrZ3JvdW5kKHRydWUpOwogICAgdWktPmdlbmVyYWxTZXR0aW5nc0J1dHRvbi0+c2V0QXV0b0ZpbGxCYWNrZ3JvdW5kKHRydWUpOwogICAgdWktPmF2U2V0dGluZ3NCdXR0b24tPnNldEF1dG9GaWxsQmFja2dyb3VuZCh0cnVlKTsKCiAgICB1aS0+YWNjb3VudFNldHRpbmdzQnV0dG9uLT5zZXRDaGVja2VkKHRydWUpOwoKICAgIHVpLT5leGl0U2V0dGluZ3NCdXR0b24tPnNldEljb25TaXplKFFTaXplKDI0LCAyNCkpOwogICAgdWktPmV4aXRTZXR0aW5nc0J1dHRvbi0+c2V0SWNvbihRUGl4bWFwKCI6L2ltYWdlcy9pY29ucy9yb3VuZC1jbG9zZS0yNHB4LnN2ZyIpKTsKCgogICAgLy8gZGlzcGxheSBuYW1lIChha2EgYWxpYXMpCiAgICB1aS0+ZGlzcGxheU5hbWVMaW5lRWRpdC0+c2V0QWxpZ25tZW50KFF0OjpBbGlnbkhDZW50ZXIpOwogICAgdWktPmRpc3BsYXlOYW1lTGluZUVkaXQtPnNldFBsYWNlaG9sZGVyVGV4dCh0cigiRW50ZXIgdGhlIGRpc3BsYXllZCBuYW1lIikpOwoKCiAgICBzZXRTZWxlY3RlZChCdXR0b246OmFjY291bnRTZXR0aW5nc0J1dHRvbik7CgogICAgdWktPmN1cnJlbnRSZWdpc3RlcmVkSUQtPnNldFJlYWRPbmx5KHRydWUpOwogICAgdWktPmN1cnJlbnRSZWdpc3RlcmVkSUQtPnNldFN0eWxlU2hlZXQoImJvcmRlciA6IDBweDsiKTsKCiAgICB1aS0+Y3VycmVudFJpbmdJRC0+c2V0UmVhZE9ubHkodHJ1ZSk7CgogICAgYXZhdGFyU2l6ZV8gPSB1aS0+Y3VycmVudEFjY291bnRBdmF0YXItPndpZHRoKCk7CgogICAgdWktPmN1cnJlbnRBY2NvdW50QXZhdGFyLT5zZXRJY29uU2l6ZShRU2l6ZShhdmF0YXJTaXplXywgYXZhdGFyU2l6ZV8pKTsKCiAgICAvLyBjcmVhdGUgZWxsaXBzZS1zZWxlY3RhYmxlIGF2YXRhciBpbWFnZQogICAgUVJlZ2lvbiBhdmF0YXJDbGlja2FibGVSZWdpb24oLTEsIC0xLAogICAgICAgIHVpLT5jdXJyZW50QWNjb3VudEF2YXRhci0+d2lkdGgoKSArIDIsIHVpLT5jdXJyZW50QWNjb3VudEF2YXRhci0+aGVpZ2h0KCkgKyAyLCBRUmVnaW9uOjpFbGxpcHNlKTsKICAgIHVpLT5jdXJyZW50QWNjb3VudEF2YXRhci0+c2V0TWFzayhhdmF0YXJDbGlja2FibGVSZWdpb24pOwoKICAgIFFTdHJpbmcgc3R5bGVTKAogICAgICAgICJRUHVzaEJ1dHRvbnsiCiAgICAgICAgIiAgYmFja2dyb3VuZC1jb2xvcjogcmdiKDI0NSwgMjQ1LCAyNDUpOyIKICAgICAgICAiICBib3JkZXI6IDBweDsiCiAgICAgICAgIn0iCiAgICAgICAgIiBRUHVzaEJ1dHRvbjpob3ZlcnsiCiAgICAgICAgIiAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiKDI1MCwgMjUwLCAyNTApOyIKICAgICAgICAiICAgICBib3JkZXI6IDBweDsiCiAgICAgICAgIiB9IgoKICAgICAgICAiUVB1c2hCdXR0b246Y2hlY2tlZHsiCiAgICAgICAgIiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiCiAgICAgICAgIiAgICBib3JkZXI6IDBweDsiCiAgICAgICAgIn0iCiAgICApOwoKICAgIHVpLT5hY2NvdW50U2V0dGluZ3NCdXR0b24tPnNldFN0eWxlU2hlZXQoc3R5bGVTKTsKICAgIHVpLT5nZW5lcmFsU2V0dGluZ3NCdXR0b24tPnNldFN0eWxlU2hlZXQoc3R5bGVTKTsKICAgIHVpLT5hdlNldHRpbmdzQnV0dG9uLT5zZXRTdHlsZVNoZWV0KHN0eWxlUyk7CgogICAgdWktPmFkdmFuY2VkQWNjb3VudFNldHRpbmdzUEJ1dHRvbi0+c2V0SWNvbihRUGl4bWFwKCI6L2ltYWdlcy9pY29ucy9yb3VuZC1hcnJvd19kcm9wX2Rvd24tMjRweC5zdmciKSk7CiAgICB1aS0+bGlua0RldlB1c2hCdXR0b24tPnNldEljb24oUVBpeG1hcCgiOi9pbWFnZXMvaWNvbnMvcm91bmQtYWRkLTI0cHguc3ZnIikpOwogICAgdWktPmJsb2NrZWRDb250YWN0c0J0bi0+c2V0SWNvbihRUGl4bWFwKCI6L2ltYWdlcy9pY29ucy9yb3VuZC1hcnJvd19kcm9wX3VwLTI0cHguc3ZnIikpOwoKICAgIHVpLT5hZHZhbmNlZFNldHRpbmdzT2Zmc2V0TGFiZWwtPnNob3coKTsKCiAgICBzZXRDb25uZWN0aW9ucygpOwp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpsZWF2ZVNldHRpbmdzU2xvdCgpCnsKICAgIGlmIChhZHZhbmNlZFNldHRpbmdzRHJvcHBlZF8pIHsKICAgICAgICB0b2dnbGVBZHZhbmNlZFNldHRpbmdzKCk7CiAgICB9CgogICAgVmlkZW86OlByZXZpZXdNYW5hZ2VyOjppbnN0YW5jZSgpLnN0b3BQcmV2aWV3KCk7CiAgICBzYXZlU2l6ZUluZGV4KCk7CgogICAgZW1pdCBOYXZpZ2F0aW9uUmVxdWVzdGVkKFNjcmVlbkVudW06OkNhbGxTY3JlZW4pOwp9CgpTZXR0aW5nc1dpZGdldDo6flNldHRpbmdzV2lkZ2V0KCkKewogICAgZGVsZXRlIGFkdmFuY2VkU2V0dGluZ3NXaWRnZXRfOwogICAgZGVsZXRlIHNjcm9sbEFyZWFfOwogICAgZGVsZXRlIHVpOwp9CgovLyBjYWxsZWQgYXQgZXZlcnkgY2FsbHdpZGdldCAtPiBzZXR0aW5nc1dpZGdldCBuYXZpZ2F0aW9uCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnVwZGF0ZVNldHRpbmdzKGludCBzaXplKQp7CiAgICBzZXRTZWxlY3RlZChCdXR0b246OmFjY291bnRTZXR0aW5nc0J1dHRvbik7CiAgICByZXNpemUoc2l6ZSk7CiAgICB1cGRhdGVBY2NvdW50SW5mb0Rpc3BsYXllZCgpOwp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpyZXNpemUoaW50IHNpemUpCnsKICAgIHVpLT5yaWdodFNldHRpbmdzV2lkZ2V0LT5zZXRHZW9tZXRyeShzaXplLCAwLCB0aGlzLT53aWR0aCgpIC0gc2l6ZSwgdGhpcy0+aGVpZ2h0KCkpOwogICAgdWktPmFjY291bnRTZXR0aW5nc0J1dHRvbi0+c2V0Rml4ZWRXaWR0aChzaXplKTsKfQoKdm9pZApTZXR0aW5nc1dpZGdldDo6c2V0U2VsZWN0ZWQoQnV0dG9uIHNlbCkKewogICAgc2F2ZVNpemVJbmRleCgpOwoKICAgIHN3aXRjaCAoc2VsKQogICAgewogICAgY2FzZSBCdXR0b246OmFjY291bnRTZXR0aW5nc0J1dHRvbjoKICAgICAgICBWaWRlbzo6UHJldmlld01hbmFnZXI6Omluc3RhbmNlKCkuc3RvcFByZXZpZXcoKTsKCiAgICAgICAgaWYgKGFkdmFuY2VkU2V0dGluZ3NEcm9wcGVkXykgeyB0b2dnbGVBZHZhbmNlZFNldHRpbmdzKCk7IH0KICAgICAgICB1aS0+c3RhY2tlZFdpZGdldC0+c2V0Q3VycmVudFdpZGdldCh1aS0+Y3VycmVudEFjY291bnRTZXR0aW5nc1Njcm9sbFdpZGdldCk7CiAgICAgICAgaWYgKHBhc3RCdXR0b25fID09IEJ1dHRvbjo6Z2VuZXJhbFNldHRpbmdzQnV0dG9uKSB7CiAgICAgICAgICAgIHVpLT5hY2NvdW50U2V0dGluZ3NCdXR0b24tPnNldENoZWNrZWQodHJ1ZSk7CiAgICAgICAgICAgIHVpLT5nZW5lcmFsU2V0dGluZ3NCdXR0b24tPnNldENoZWNrZWQoZmFsc2UpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIHVpLT5hY2NvdW50U2V0dGluZ3NCdXR0b24tPnNldENoZWNrZWQodHJ1ZSk7CiAgICAgICAgICAgIHVpLT5hdlNldHRpbmdzQnV0dG9uLT5zZXRDaGVja2VkKGZhbHNlKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgY2FzZSBCdXR0b246OmdlbmVyYWxTZXR0aW5nc0J1dHRvbjoKICAgICAgICBWaWRlbzo6UHJldmlld01hbmFnZXI6Omluc3RhbmNlKCkuc3RvcFByZXZpZXcoKTsKCiAgICAgICAgdWktPnN0YWNrZWRXaWRnZXQtPnNldEN1cnJlbnRXaWRnZXQodWktPmdlbmVyYWxTZXR0aW5ncyk7CiAgICAgICAgcG9wdWxhdGVHZW5lcmFsU2V0dGluZ3MoKTsKICAgICAgICBpZiAocGFzdEJ1dHRvbl8gPT0gQnV0dG9uOjphdlNldHRpbmdzQnV0dG9uKSB7CiAgICAgICAgICAgIHVpLT5nZW5lcmFsU2V0dGluZ3NCdXR0b24tPnNldENoZWNrZWQodHJ1ZSk7CiAgICAgICAgICAgIHVpLT5hdlNldHRpbmdzQnV0dG9uLT5zZXRDaGVja2VkKGZhbHNlKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICB1aS0+Z2VuZXJhbFNldHRpbmdzQnV0dG9uLT5zZXRDaGVja2VkKHRydWUpOwogICAgICAgICAgICB1aS0+YWNjb3VudFNldHRpbmdzQnV0dG9uLT5zZXRDaGVja2VkKGZhbHNlKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgY2FzZSBCdXR0b246OmF2U2V0dGluZ3NCdXR0b246CiAgICAgICAgdWktPnN0YWNrZWRXaWRnZXQtPnNldEN1cnJlbnRXaWRnZXQodWktPmF2U2V0dGluZ3MpOwogICAgICAgIHBvcHVsYXRlQVZTZXR0aW5ncygpOwogICAgICAgIGlmIChwYXN0QnV0dG9uXyA9PSBCdXR0b246OmFjY291bnRTZXR0aW5nc0J1dHRvbikgewogICAgICAgICAgICB1aS0+YXZTZXR0aW5nc0J1dHRvbi0+c2V0Q2hlY2tlZCh0cnVlKTsKICAgICAgICAgICAgdWktPmFjY291bnRTZXR0aW5nc0J1dHRvbi0+c2V0Q2hlY2tlZChmYWxzZSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgdWktPmF2U2V0dGluZ3NCdXR0b24tPnNldENoZWNrZWQodHJ1ZSk7CiAgICAgICAgICAgIHVpLT5nZW5lcmFsU2V0dGluZ3NCdXR0b24tPnNldENoZWNrZWQoZmFsc2UpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CiAgICBwYXN0QnV0dG9uXyA9IHNlbDsKfQoKLy8gY2FsbGVkIHRvIHVwZGF0ZSBjdXJyZW50IHNldHRpbmdzIGluZm9ybWF0aW9uIHdoZW4gbmF2aWdhdGluZyB0byBzZXR0aW5nc1dpZGdldAp2b2lkClNldHRpbmdzV2lkZ2V0Ojp1cGRhdGVBY2NvdW50SW5mb0Rpc3BsYXllZCgpCnsKICAgIHVpLT5jdXJyZW50UmVnaXN0ZXJlZElELT5zZXRUZXh0KFFTdHJpbmc6OmZyb21TdGRTdHJpbmcoTFJDSW5zdGFuY2U6OmdldEN1cnJlbnRBY2NvdW50SW5mbygpLnJlZ2lzdGVyZWROYW1lKSk7CiAgICB1aS0+Y3VycmVudFJpbmdJRC0+c2V0VGV4dChRU3RyaW5nOjpmcm9tU3RkU3RyaW5nKExSQ0luc3RhbmNlOjpnZXRDdXJyZW50QWNjb3VudEluZm8oKS5wcm9maWxlSW5mby51cmkpKTsKCiAgICB1aS0+Y3VycmVudFJlZ2lzdGVyZWRJRC0+c2V0UmVhZE9ubHkodHJ1ZSk7CgovLyBpZiBubyByZWdpc3RlcmVkIG5hbWUgaXMgZm91bmQgZm9yIGFjY291bnQKICAgIGlmIChMUkNJbnN0YW5jZTo6Z2V0Q3VycmVudEFjY291bnRJbmZvKCkucmVnaXN0ZXJlZE5hbWUuZW1wdHkoKSkgewogICAgICAgIHVpLT5jdXJyZW50UmVnaXN0ZXJlZElELT5zZXRSZWFkT25seShmYWxzZSk7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICB1aS0+Y3VycmVudFJlZ2lzdGVyZWRJRC0+c2V0UmVhZE9ubHkodHJ1ZSk7CiAgICAgICAgc2V0UmVnTmFtZVVpKFJlZ05hbWU6OkJMQU5LKTsKICAgIH0KCiAgICB1aS0+Y3VycmVudEFjY291bnRBdmF0YXItPnNldEljb24oTFJDSW5zdGFuY2U6OmdldEN1cnJBY2NQaXhtYXAoKS4KICAgICAgICBzY2FsZWRUb0hlaWdodChhdmF0YXJTaXplXywgUXQ6OlNtb290aFRyYW5zZm9ybWF0aW9uKSk7CgogICAgdWktPmFjY291bnRFbmFibGVDaGVja0JveC0+c2V0Q2hlY2tlZChMUkNJbnN0YW5jZTo6Z2V0Q3VycmVudEFjY291bnRJbmZvKCkuZW5hYmxlZCk7CgogICAgdWktPmRpc3BsYXlOYW1lTGluZUVkaXQtPnNldFRleHQoUVN0cmluZzo6ZnJvbVN0ZFN0cmluZyhMUkNJbnN0YW5jZTo6Z2V0Q3VycmVudEFjY291bnRJbmZvKCkucHJvZmlsZUluZm8uYWxpYXMpKTsKCiAgICB1cGRhdGVBbmRTaG93RGV2aWNlc1Nsb3QoKTsKICAgIGJhbm5lZENvbnRhY3RzU2hvd25fID0gZmFsc2U7CiAgICBpZiAoIUxSQ0luc3RhbmNlOjpnZXRDdXJyZW50QWNjb3VudEluZm8oKS5jb250YWN0TW9kZWwtPmdldEJhbm5lZENvbnRhY3RzKCkuc2l6ZSgpKXsKICAgICAgICB1aS0+YmxvY2tlZENvbnRhY3RzQnRuLT5oaWRlKCk7CiAgICB9IGVsc2UgewogICAgICAgIHVpLT5ibG9ja2VkQ29udGFjdHNCdG4tPnNob3coKTsKICAgIH0KfQoKdm9pZApTZXR0aW5nc1dpZGdldDo6cGFzc3dvcmRDbGlja2VkKCkKewogICAgUGFzc3dvcmREaWFsb2cgcGFzc3dkRGlhbG9nKHRoaXMpOwogICAgcGFzc3dkRGlhbG9nLmV4ZWMoKTsKfQoKdm9pZApTZXR0aW5nc1dpZGdldDo6dG9nZ2xlQWR2YW5jZWRTZXR0aW5ncygpCnsKICAgIGlmIChhZHZhbmNlZFNldHRpbmdzRHJvcHBlZF8pIHsKICAgICAgICB1aS0+YWR2YW5jZWRBY2NvdW50U2V0dGluZ3NQQnV0dG9uLT5zZXRJY29uKFFQaXhtYXAoIjovaW1hZ2VzL2ljb25zL3JvdW5kLWFycm93X2Ryb3BfZG93bi0yNHB4LnN2ZyIpKTsKICAgICAgICB1aS0+Y3VycmVudEFjY291bnRTZXR0aW5nc1Njcm9sbExheW91dC0+cmVtb3ZlV2lkZ2V0KGFkdmFuY2VkU2V0dGluZ3NXaWRnZXRfKTsKICAgICAgICB1aS0+c2Nyb2xsQmFyTGFiZWwtPnNob3coKTsKICAgICAgICB1aS0+YWR2YW5jZWRTZXR0aW5nc09mZnNldExhYmVsLT5oaWRlKCk7CiAgICAgICAgZGVsZXRlIGFkdmFuY2VkU2V0dGluZ3NXaWRnZXRfOwogICAgfQogICAgZWxzZSB7IC8vIHdpbGwgc2hvdyBhZHZhbmNlZCBzZXR0aW5ncyBuZXh0CiAgICAgICAgdWktPmFkdmFuY2VkQWNjb3VudFNldHRpbmdzUEJ1dHRvbi0+c2V0SWNvbihRUGl4bWFwKCI6L2ltYWdlcy9pY29ucy9yb3VuZC1hcnJvd19kcm9wX3VwLTI0cHguc3ZnIikpOwogICAgICAgIGFkdmFuY2VkU2V0dGluZ3NXaWRnZXRfID0gbmV3IEFkdmFuY2VkU2V0dGluZ3NXaWRnZXQodWktPnNjcm9sbEFyZWFXaWRnZXRDb250ZW50cyk7CiAgICAgICAgYWR2YW5jZWRTZXR0aW5nc1dpZGdldF8tPnNldE1heGltdW1XaWR0aCh1aS0+c2Nyb2xsQXJlYVdpZGdldENvbnRlbnRzLT53aWR0aCgpIC0gMTApOwogICAgICAgIHVpLT5jdXJyZW50QWNjb3VudFNldHRpbmdzU2Nyb2xsTGF5b3V0LT5hZGRXaWRnZXQoYWR2YW5jZWRTZXR0aW5nc1dpZGdldF8pOwogICAgICAgIHVpLT5hZHZhbmNlZFNldHRpbmdzT2Zmc2V0TGFiZWwtPnNob3coKTsKICAgICAgICB1aS0+c2Nyb2xsQmFyTGFiZWwtPmhpZGUoKTsKICAgIH0KICAgIGFkdmFuY2VkU2V0dGluZ3NEcm9wcGVkXyA9ICFhZHZhbmNlZFNldHRpbmdzRHJvcHBlZF87Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnRvZ2dsZUJhbm5lZENvbnRhY3RzKCkKewogICAgaWYgKGJhbm5lZENvbnRhY3RzU2hvd25fKSB7IC8vIHdpbGwgc2hvdyBsaW5rZWQgZGV2aWNlcyBuZXh0CiAgICAgICAgYmFubmVkQ29udGFjdHNTaG93bl8gPSBmYWxzZTsKICAgICAgICB1cGRhdGVBbmRTaG93RGV2aWNlc1Nsb3QoKTsKICAgIH0KICAgIGVsc2UgeyAvLyB3aWxsIHNob3cgYmFubmVkIGNvbnRhY3RzIG5leHQKICAgICAgICBiYW5uZWRDb250YWN0c1Nob3duXyA9IHRydWU7CiAgICAgICAgdXBkYXRlQW5kU2hvd0Jhbm5lZENvbnRhY3RzU2xvdCgpOwogICAgfQp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpyZXNpemVFdmVudChRUmVzaXplRXZlbnQqIGV2ZW50KQp7CiAgICBRV2lkZ2V0OjpyZXNpemVFdmVudChldmVudCk7CiAgICBzY3JvbGxBcmVhXy0+cmVzaXplKHVpLT5jdXJyZW50QWNjb3VudFNldHRpbmdzU2Nyb2xsV2lkZ2V0LT53aWR0aCgpLCB0aGlzLT5oZWlnaHQoKSk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OmF2YXRhckNsaWNrZWQoKQp7CiAgICBTZXRBdmF0YXJEaWFsb2cgYXZhdGFyRGlhbG9nKHRoaXMpOwoKICAgIC8vIHJldHVybiBuZXcgYXZhdGFyIHBpeG1hcCBmcm9tIHNldEF2YXRhckRpYWxvZwogICAgY29ubmVjdCgmYXZhdGFyRGlhbG9nLCAmU2V0QXZhdGFyRGlhbG9nOjpwaXhtYXBTaWduYWwsIFsmXShjb25zdCBzdGQ6OnN0cmluZyYgcGl4U3RyaW5nKSB7CiAgICAgICAgICAgIGlmICghcGl4U3RyaW5nLmVtcHR5KCkpIHsKICAgICAgICAgICAgICAgIExSQ0luc3RhbmNlOjpzZXRDdXJyQWNjQXZhdGFyKHBpeFN0cmluZyk7CiAgICAgICAgICAgICAgICB1cGRhdGVBY2NvdW50SW5mb0Rpc3BsYXllZCgpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgKTsKICAgIGF2YXRhckRpYWxvZy5leGVjKCk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnZlcmlmeVJlZ2lzdGVyZWROYW1lU2xvdCgpCnsKICAgIGlmICghTFJDSW5zdGFuY2U6OmdldEN1cnJlbnRBY2NvdW50SW5mbygpLnJlZ2lzdGVyZWROYW1lLmVtcHR5KCkpIHsKICAgICAgICBzZXRSZWdOYW1lVWkoUmVnTmFtZTo6QkxBTkspOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgcmVnaXN0ZXJlZE5hbWVfID0gdWktPmN1cnJlbnRSZWdpc3RlcmVkSUQtPnRleHQoKS5zaW1wbGlmaWVkKCk7CgogICAgICAgIGlmICghcmVnaXN0ZXJlZE5hbWVfLmlzRW1wdHkoKSkgewogICAgICAgICAgICBpZiAodmFsaWRhdGVSZWdOYW1lRm9ybShyZWdpc3RlcmVkTmFtZV8pKSB7IC8vIG5hbWUgaGFzIHZhbGlkIGZvcm0KICAgICAgICAgICAgICAgIHNldFJlZ05hbWVVaShSZWdOYW1lOjpTRUFSQ0hJTkcpOwogICAgICAgICAgICAgICAgUVRpbWVyOjpzaW5nbGVTaG90KDMwMCwgdGhpcywgU0xPVChiZWZvcmVOYW1lTG9va3VwKCkpKTsKICAgICAgICAgICAgfSBlbHNlIHsgLy8gbmFtZSBkb2VzIG5vdCBoYXZlIHZhbGlkIGZvcm0KICAgICAgICAgICAgICAgIHNldFJlZ05hbWVVaShSZWdOYW1lOjpJTlZBTElERk9STSk7CiAgICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzZXRSZWdOYW1lVWkoUmVnTmFtZTo6QkxBTkspOwogICAgICAgIH0KICAgIH0KfQoKLy8gcmV0dXJucyB0cnVlIGlmIG5hbWUgaXMgdmFsaWQgcmVnaXN0ZXJlZCBuYW1lCmJvb2wKU2V0dGluZ3NXaWRnZXQ6OnZhbGlkYXRlUmVnTmFtZUZvcm0oY29uc3QgUVN0cmluZyYgcmVnTmFtZSkKewogICAgUVJlZ3VsYXJFeHByZXNzaW9uIHJlZ0V4cCgiICIpOwogICAgaWYgKHJlZ05hbWUuc2l6ZSgpID4gMiAmJiAhcmVnTmFtZS5jb250YWlucyhyZWdFeHApKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnJlY2VpdmVSZWdOYW1lU2xvdChjb25zdCBzdGQ6OnN0cmluZyYgYWNjb3VudElELAogICAgbHJjOjphcGk6OmFjY291bnQ6Okxvb2t1cFN0YXR1cyBzdGF0dXMsIGNvbnN0IHN0ZDo6c3RyaW5nJiBhZGRyZXNzLCBjb25zdCBzdGQ6OnN0cmluZyYgbmFtZSkKewogICAgUV9VTlVTRUQoYWNjb3VudElEKTsgUV9VTlVTRUQoYWRkcmVzcyk7CiAgICBhZnRlck5hbWVMb29rdXAoc3RhdHVzLCBuYW1lKTsKfQoKdm9pZApTZXR0aW5nc1dpZGdldDo6YmVmb3JlTmFtZUxvb2t1cCgpCnsKICAgIE5hbWVEaXJlY3Rvcnk6Omluc3RhbmNlKCkubG9va3VwTmFtZShudWxscHRyLCBRU3RyaW5nKCksIHJlZ2lzdGVyZWROYW1lXyk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OmFmdGVyTmFtZUxvb2t1cChscmM6OmFwaTo6YWNjb3VudDo6TG9va3VwU3RhdHVzIHN0YXR1cywgY29uc3Qgc3RkOjpzdHJpbmcmIHJlZ05hbWUpCnsKICAgIGlmIChyZWdpc3RlcmVkTmFtZV8udG9TdGRTdHJpbmcoKSA9PSByZWdOYW1lICYmIHJlZ05hbWUubGVuZ3RoKCkgPiAyKSB7CiAgICAgICAgaWYgKHN0YXR1cyA9PSBscmM6OmFwaTo6YWNjb3VudDo6TG9va3VwU3RhdHVzOjpOT1RfRk9VTkQpIHsKICAgICAgICAgICAgc2V0UmVnTmFtZVVpKFJlZ05hbWU6OkZSRUUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgc2V0UmVnTmFtZVVpKFJlZ05hbWU6OlRBS0VOKTsKICAgICAgICB9CiAgICB9CiAgICBlbHNlIHsKICAgICAgICBzZXRSZWdOYW1lVWkoUmVnTmFtZTo6QkxBTkspOwogICAgfQp9Cgp2b2lkIFNldHRpbmdzV2lkZ2V0OjpzZXRSZWdOYW1lVWkoUmVnTmFtZSBzdGF0KQp7CiAgICBkaXNjb25uZWN0KGdpZiwgU0lHTkFMKGZyYW1lQ2hhbmdlZChpbnQpKSwgdGhpcywgU0xPVChzZXRCdXR0b25JY29uU2xvdChpbnQpKSk7CiAgICBkaXNjb25uZWN0KHVpLT5yZWdOYW1lQnV0dG9uLCAmUVB1c2hCdXR0b246OmNsaWNrZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6cmVnTmFtZVJlZ2lzdGVyZWRTbG90KTsKCiAgICBzd2l0Y2ggKHN0YXQpIHsKICAgIGNhc2UgUmVnTmFtZTo6QkxBTks6CiAgICAgICAgdWktPmN1cnJlbnRSZWdpc3RlcmVkSUQtPnNldFN0eWxlU2hlZXQoInBhZGRpbmctbGVmdDogNXB4OyBib3JkZXI6IDBweDsgYm9yZGVyLXJhZGl1czogM3B4OyBib3JkZXI6IDFweCBzb2xpZCByZ2IoMjQ1LCAyNDUsIDI0NSk7Iik7CiAgICAgICAgcmVnTmFtZUJ0bl8gPSBmYWxzZTsKICAgICAgICB1aS0+Y3VycmVudFJlZ2lzdGVyZWRJRC0+c2V0VG9vbFRpcCh0cigiIikpOwogICAgICAgIHVpLT5yZWdOYW1lQnV0dG9uLT5zZXRJY29uKFFQaXhtYXAoKSk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldEVuYWJsZWQoZmFsc2UpOwogICAgICAgIGJyZWFrOwoKICAgIGNhc2UgUmVnTmFtZTo6SU5WQUxJREZPUk06CiAgICAgICAgdWktPmN1cnJlbnRSZWdpc3RlcmVkSUQtPnNldFN0eWxlU2hlZXQoInBhZGRpbmctbGVmdDogNXB4OyBib3JkZXI6IDFweCBzb2xpZCByZWQ7IGJvcmRlci1yYWRpdXM6IDNweDsiKTsKICAgICAgICByZWdOYW1lQnRuXyA9IGZhbHNlOwogICAgICAgIHVpLT5jdXJyZW50UmVnaXN0ZXJlZElELT5zZXRUb29sVGlwKHRyKCJBIHJlZ2lzdGVyZWQgbmFtZSBzaG91bGQgbm90IGhhdmUgYW55IHNwYWNlcyBhbmQgbXVzdCBiZSBhdCBsZWFzdCB0aHJlZSBsZXR0ZXJzIGxvbmciKSk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldEljb24oUVBpeG1hcCgiOi9pbWFnZXMvaWNvbnMvcm91bmQtZXJyb3ItMjRweC5zdmciKSk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldFRvb2xUaXAodHIoIkEgcmVnaXN0ZXJlZCBuYW1lIHNob3VsZCBub3QgaGF2ZSBhbnkgc3BhY2VzIGFuZCBtdXN0IGJlIGF0IGxlYXN0IHRocmVlIGxldHRlcnMgbG9uZyIpKTsKICAgICAgICB1aS0+cmVnTmFtZUJ1dHRvbi0+c2V0RW5hYmxlZCh0cnVlKTsKICAgICAgICBicmVhazsKCiAgICBjYXNlIFJlZ05hbWU6OlRBS0VOOgogICAgICAgIHVpLT5jdXJyZW50UmVnaXN0ZXJlZElELT5zZXRTdHlsZVNoZWV0KCJwYWRkaW5nLWxlZnQ6IDVweDsgYm9yZGVyOiAxcHggc29saWQgb3JhbmdlOyBib3JkZXItcmFkaXVzOiAzcHg7Iik7CiAgICAgICAgcmVnTmFtZUJ0bl8gPSBmYWxzZTsKICAgICAgICB1aS0+Y3VycmVudFJlZ2lzdGVyZWRJRC0+c2V0VG9vbFRpcCh0cigiVGhpcyBuYW1lIGlzIGFscmVhZHkgdGFrZW4iKSk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldEljb24oUVBpeG1hcCgiOi9pbWFnZXMvaWNvbnMvcm91bmQtZXJyb3ItMjRweC5zdmciKSk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldFRvb2xUaXAodHIoIlRoaXMgcmVnaXN0ZXJlZCBuYW1lIGlzIGFscmVhZHkgdGFrZW4iKSk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldEVuYWJsZWQodHJ1ZSk7CiAgICAgICAgYnJlYWs7CgogICAgY2FzZSBSZWdOYW1lOjpGUkVFOgogICAgICAgIHVpLT5jdXJyZW50UmVnaXN0ZXJlZElELT5zZXRTdHlsZVNoZWV0KCJwYWRkaW5nLWxlZnQ6IDVweDsgYm9yZGVyOiAxcHggc29saWQgZ3JlZW47IGJvcmRlci1yYWRpdXM6IDNweDsiKTsKICAgICAgICByZWdOYW1lQnRuXyA9IHRydWU7CiAgICAgICAgdWktPmN1cnJlbnRSZWdpc3RlcmVkSUQtPnNldFRvb2xUaXAodHIoIlRoaXMgbmFtZSBpcyBhdmFpbGFibGUiKSk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldEljb24oUVBpeG1hcCgiOi9pbWFnZXMvaWNvbnMvcm91bmQtY2hlY2tfY2lyY2xlLTI0cHguc3ZnIikpOwogICAgICAgIHVpLT5yZWdOYW1lQnV0dG9uLT5zZXRUb29sVGlwKHRyKCJSZWdpc3RlciB0aGlzIG5hbWUiKSk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldEVuYWJsZWQodHJ1ZSk7CgogICAgICAgIGNvbm5lY3QodWktPnJlZ05hbWVCdXR0b24sICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgdGhpcywgJlNldHRpbmdzV2lkZ2V0OjpyZWdOYW1lUmVnaXN0ZXJlZFNsb3QpOwoKICAgICAgICBicmVhazsKCiAgICBjYXNlIFJlZ05hbWU6OlNFQVJDSElORzoKICAgICAgICB1aS0+Y3VycmVudFJlZ2lzdGVyZWRJRC0+c2V0U3R5bGVTaGVldCgicGFkZGluZy1sZWZ0OiA1cHg7IGJvcmRlcjogMXB4IHNvbGlkIHJnYigyLCAxODcsIDIxMyk7IGJvcmRlci1yYWRpdXM6IDNweDsiKTsKICAgICAgICByZWdOYW1lQnRuXyA9IGZhbHNlOwogICAgICAgIHVpLT5jdXJyZW50UmVnaXN0ZXJlZElELT5zZXRUb29sVGlwKHRyKCIiKSk7CgogICAgICAgIGNvbm5lY3QoZ2lmLCBTSUdOQUwoZnJhbWVDaGFuZ2VkKGludCkpLCB0aGlzLCBTTE9UKHNldEJ1dHRvbkljb25TbG90KGludCkpKTsKICAgICAgICBnaWYtPnN0YXJ0KCk7CiAgICAgICAgdWktPnJlZ05hbWVCdXR0b24tPnNldEVuYWJsZWQoZmFsc2UpOwoKICAgICAgICBicmVhazsKICAgIH0KfQp2b2lkIFNldHRpbmdzV2lkZ2V0OjpzZXRCdXR0b25JY29uU2xvdChpbnQgZnJhbWUpCnsKICAgIFFfVU5VU0VEKGZyYW1lKTsKICAgIHVpLT5yZWdOYW1lQnV0dG9uLT5zZXRJY29uKFFJY29uKGdpZi0+Y3VycmVudFBpeG1hcCgpKSk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnJlZ05hbWVSZWdpc3RlcmVkU2xvdCgpCnsKICAgIGlmICghcmVnTmFtZUJ0bl8pIHsgcmV0dXJuOyB9CgogICAgUmVnTmFtZURpYWxvZyByZWdOYW1lRGlhbG9nKHJlZ2lzdGVyZWROYW1lXywgdGhpcyk7CiAgICBpZiAocmVnTmFtZURpYWxvZy5leGVjKCkgPT0gUURpYWxvZzo6QWNjZXB0ZWQpIHsgLy8gaWYgdXNlciBjb25maXJtcyByZWdOYW1lIGNob2ljZQogICAgICAgIHVpLT5jdXJyZW50UmVnaXN0ZXJlZElELT5zZXRSZWFkT25seSh0cnVlKTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIHVpLT5jdXJyZW50UmVnaXN0ZXJlZElELT5zZXRUZXh0KCIiKTsKICAgICAgICByZWdpc3RlcmVkTmFtZV8gPSAiIjsKICAgIH0KICAgIHNldFJlZ05hbWVVaShSZWdOYW1lOjpCTEFOSyk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnNldEFjY0VuYWJsZVNsb3QoaW50IHN0YXRlKQp7CiAgICBMUkNJbnN0YW5jZTo6ZWRpdGFibGVBY2NvdW50TW9kZWwoKS0+ZW5hYmxlQWNjb3VudChMUkNJbnN0YW5jZTo6Z2V0Q3VyckFjY0lkKCksIChib29sKXN0YXRlKTsKCiAgICBhdXRvIGNvbmZQcm9wcyA9IExSQ0luc3RhbmNlOjphY2NvdW50TW9kZWwoKS5nZXRBY2NvdW50Q29uZmlnKExSQ0luc3RhbmNlOjpnZXRDdXJyQWNjSWQoKSk7CiAgICBMUkNJbnN0YW5jZTo6ZWRpdGFibGVBY2NvdW50TW9kZWwoKS0+c2V0QWNjb3VudENvbmZpZyhMUkNJbnN0YW5jZTo6Z2V0Q3VyckFjY0lkKCksIGNvbmZQcm9wcyk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OmRlbEFjY291bnRTbG90KCkKewogICAgRGVsZXRlQWNjb3VudERpYWxvZyBkZWxEaWFsb2codGhpcyk7CiAgICBkZWxEaWFsb2cuZXhlYygpOwoKICAgIGlmICghTFJDSW5zdGFuY2U6OmFjY291bnRNb2RlbCgpLmdldEFjY291bnRMaXN0KCkuc2l6ZSgpKSB7CiAgICAgICAgZW1pdCBOYXZpZ2F0aW9uUmVxdWVzdGVkKFNjcmVlbkVudW06OldpemFyZFNjcmVlbik7CiAgICB9Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnJlbW92ZURldmljZVNsb3QoaW50IGluZGV4KQp7CiAgICBpZiAoIWluZGV4KSB7IHJldHVybjsgfQoKICAgIGF1dG8gZGV2aWNlTGlzdCA9IExSQ0luc3RhbmNlOjpnZXRDdXJyZW50QWNjb3VudEluZm8oKS5kZXZpY2VNb2RlbC0+Z2V0QWxsRGV2aWNlcygpOwogICAgYXV0byBpdCA9IGRldmljZUxpc3QuYmVnaW4oKTsKCiAgICBzdGQ6OmFkdmFuY2UoaXQsIGluZGV4KTsKICAgIFFTdHJpbmcgcHNzd2Q7CgogICAgYm9vbCBvayA9IGZhbHNlOwogICAgaWYgKExSQ0luc3RhbmNlOjpnZXRDdXJyQWNjQ29uZmlnKCkuYXJjaGl2ZUhhc1Bhc3N3b3JkKSB7CiAgICAgICAgcHNzd2QgPSBRSW5wdXREaWFsb2c6OmdldFRleHQodGhpcywgdHIoIlJlbW92ZSBEZXZpY2UiKSwKICAgICAgICAgICAgdHIoIkVudGVyIHRoaXMgYWNjb3VudCdzIHBhc3N3b3JkIHRvIGNvbmZpcm0gdGhlIHJlbW92YWwgb2YgdGhpcyBkZXZpY2UiKSwgUUxpbmVFZGl0OjpQYXNzd29yZCwKICAgICAgICAgICAgUURpcjo6aG9tZSgpLmRpck5hbWUoKSwgJm9rKTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIHBzc3dkID0gIiI7CiAgICAgICAgUU1lc3NhZ2VCb3ggZGV2RGVsOwogICAgICAgIGRldkRlbC5zZXRUZXh0KHRyKCJQbGVhc2UgY29uZmlybSB0aGF0IHlvdSB3aXNoIHRvIHJlbW92ZSB0aGlzIGRldmljZSIpKTsKICAgICAgICBkZXZEZWwuc2V0U3RhbmRhcmRCdXR0b25zKFFNZXNzYWdlQm94OjpPayB8IFFNZXNzYWdlQm94OjpDYW5jZWwpOwogICAgICAgIGRldkRlbC5zZXREZWZhdWx0QnV0dG9uKFFNZXNzYWdlQm94OjpDYW5jZWwpOwogICAgICAgIGlmIChkZXZEZWwuZXhlYygpID09IFFNZXNzYWdlQm94OjpPaykgeyBnb3RvIGRlbGV0ZV87IH0KICAgIH0KCiAgICBpZiAob2spIHsKICAgICAgICBkZWxldGVfOgogICAgICAgIExSQ0luc3RhbmNlOjpnZXRDdXJyZW50QWNjb3VudEluZm8oKS5kZXZpY2VNb2RlbC0+cmV2b2tlRGV2aWNlKGl0LT5pZCwgcHNzd2QudG9TdGRTdHJpbmcoKSk7CiAgICAgICAgdXBkYXRlQW5kU2hvd0RldmljZXNTbG90KCk7CiAgICB9Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnVuYmFuKGludCBpbmRleCkKewogICAgYXV0byBiYW5uZWRDb250YWN0TGlzdCA9IExSQ0luc3RhbmNlOjpnZXRDdXJyZW50QWNjb3VudEluZm8oKS5jb250YWN0TW9kZWwtPmdldEJhbm5lZENvbnRhY3RzKCk7CiAgICBhdXRvIGl0ID0gYmFubmVkQ29udGFjdExpc3QuYmVnaW4oKTsKICAgIHN0ZDo6YWR2YW5jZShpdCwgaW5kZXgpOwoKICAgIGF1dG8gY29udGFjdEluZm8gPSBMUkNJbnN0YW5jZTo6Z2V0Q3VycmVudEFjY291bnRJbmZvKCkuY29udGFjdE1vZGVsLT5nZXRDb250YWN0KCppdCk7CgogICAgTFJDSW5zdGFuY2U6OmdldEN1cnJlbnRBY2NvdW50SW5mbygpLmNvbnRhY3RNb2RlbC0+YWRkQ29udGFjdChjb250YWN0SW5mbyk7CiAgICB1cGRhdGVBbmRTaG93QmFubmVkQ29udGFjdHNTbG90KCk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OmV4cG9ydEFjY291bnRTbG90KCkKewogICAgUUZpbGVEaWFsb2cgZGlhbG9nKHRoaXMpOwogICAgUVN0cmluZyBkaXIgPSBRRmlsZURpYWxvZzo6Z2V0RXhpc3RpbmdEaXJlY3RvcnkodGhpcywgdHIoIkV4cG9ydCBBY2NvdW50IEhlcmUiKSwKICAgICAgICBRRGlyOjpob21lUGF0aCgpICsgIi9EZXNrdG9wIiwgUUZpbGVEaWFsb2c6OlNob3dEaXJzT25seSB8IFFGaWxlRGlhbG9nOjpEb250UmVzb2x2ZVN5bWxpbmtzKTsKCiAgICBpZiAoIWRpci5pc0VtcHR5KCkpIHsKICAgICAgICBMUkNJbnN0YW5jZTo6YWNjb3VudE1vZGVsKCkuZXhwb3J0VG9GaWxlKExSQ0luc3RhbmNlOjpnZXRDdXJyQWNjSWQoKSwgKGRpciArICIvZXhwb3J0Lmd6IikudG9TdGRTdHJpbmcoKSk7CiAgICB9Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnVwZGF0ZUFuZFNob3dEZXZpY2VzU2xvdCgpCnsKICAgIHVpLT5zZXR0aW5nc0xpc3RXaWRnZXQtPmNsZWFyKCk7CgogICAgdWktPmxhYmVsLT5zZXRUZXh0KHRyKCJMaW5rZWQgRGV2aWNlcyIpKTsKICAgIHVpLT5ibG9ja2VkQ29udGFjdHNCdG4tPnNldFRleHQodHIoIkJsb2NrZWQgQ29udGFjdHMiKSk7CiAgICB1aS0+bGlua0RldlB1c2hCdXR0b24tPnNob3coKTsKCiAgICBhdXRvIGRldmljZUxpc3QgPSBMUkNJbnN0YW5jZTo6Z2V0Q3VycmVudEFjY291bnRJbmZvKCkuZGV2aWNlTW9kZWwtPmdldEFsbERldmljZXMoKTsKCiAgICBpbnQgaSA9IDA7CgogICAgZm9yIChhdXRvIGl0ID0gZGV2aWNlTGlzdC5iZWdpbigpOyBpdCAhPSBkZXZpY2VMaXN0LmVuZCgpOyArK2l0LCArK2kpIHsKICAgICAgICBTZXR0aW5nc0l0ZW1XaWRnZXQqIGl0ZW0gPSBuZXcgU2V0dGluZ3NJdGVtV2lkZ2V0KGl0ZW1IZWlnaHRfLCBpLCBmYWxzZSwgdWktPnNldHRpbmdzTGlzdFdpZGdldCk7CiAgICAgICAgaXRlbS0+c2V0U2l6ZUhpbnQoUVNpemUodWktPnNldHRpbmdzTGlzdFdpZGdldC0+d2lkdGgoKSwgaXRlbUhlaWdodF8pKTsKICAgICAgICB1aS0+c2V0dGluZ3NMaXN0V2lkZ2V0LT5hZGRJdGVtKGl0ZW0pOwoKICAgICAgICBpZiAoaSkgewogICAgICAgICAgICBjb25uZWN0KGl0ZW0tPmJ1dHRvbl8sICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgW3RoaXMsIGldKCkgewogICAgICAgICAgICAgICAgcmVtb3ZlRGV2aWNlU2xvdChpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICB9Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnVwZGF0ZUFuZFNob3dCYW5uZWRDb250YWN0c1Nsb3QoKQp7CiAgICBpZiAoYmFubmVkQ29udGFjdHNTaG93bl8pIHsKICAgICAgICB1aS0+c2V0dGluZ3NMaXN0V2lkZ2V0LT5jbGVhcigpOwoKICAgICAgICB1aS0+bGFiZWwtPnNldFRleHQodHIoIkJsb2NrZWQgQ29udGFjdHMiKSk7CiAgICAgICAgdWktPmJsb2NrZWRDb250YWN0c0J0bi0+c2V0VGV4dCh0cigiTGlua2VkIERldmljZXMiKSk7CiAgICAgICAgdWktPmxpbmtEZXZQdXNoQnV0dG9uLT5oaWRlKCk7CgogICAgICAgIGF1dG8gYmFubmVkQ29udGFjdExpc3QgPSBMUkNJbnN0YW5jZTo6Z2V0Q3VycmVudEFjY291bnRJbmZvKCkuY29udGFjdE1vZGVsLT5nZXRCYW5uZWRDb250YWN0cygpOwoKICAgICAgICBpbnQgaSA9IDA7CgogICAgICAgIGZvciAoYXV0byBpdCA9IGJhbm5lZENvbnRhY3RMaXN0LmJlZ2luKCk7IGl0ICE9IGJhbm5lZENvbnRhY3RMaXN0LmVuZCgpOyArK2l0LCArK2kpIHsKICAgICAgICAgICAgU2V0dGluZ3NJdGVtV2lkZ2V0KiBpdGVtID0gbmV3IFNldHRpbmdzSXRlbVdpZGdldChpdGVtSGVpZ2h0XywgaSwgdHJ1ZSwgdWktPnNldHRpbmdzTGlzdFdpZGdldCk7CiAgICAgICAgICAgIGl0ZW0tPnNldFNpemVIaW50KFFTaXplKHVpLT5zZXR0aW5nc0xpc3RXaWRnZXQtPndpZHRoKCksIGl0ZW1IZWlnaHRfKSk7CiAgICAgICAgICAgIHVpLT5zZXR0aW5nc0xpc3RXaWRnZXQtPmFkZEl0ZW0oaXRlbSk7CgogICAgICAgICAgICBjb25uZWN0KGl0ZW0tPmJ1dHRvbl8sICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgW3RoaXMsIGldKCkgewogICAgICAgICAgICAgICAgdW5iYW4oaSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFiYW5uZWRDb250YWN0TGlzdC5zaXplKCkpIHsgdXBkYXRlQW5kU2hvd0RldmljZXNTbG90KCk7IHVpLT5ibG9ja2VkQ29udGFjdHNCdG4tPmhpZGUoKTsgfQogICAgfQp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpzaG93TGlua0RldlNsb3QoKQp7CiAgICBpZiAoIWFkdmFuY2VkU2V0dGluZ3NXaWRnZXRfKSB7IGRlbGV0ZSBhZHZhbmNlZFNldHRpbmdzV2lkZ2V0XzsgfQoKICAgIGxpbmtEZXZXaWRnZXQgPSBuZXcgTGlua0RldldpZGdldCh1aS0+c2Nyb2xsQXJlYVdpZGdldENvbnRlbnRzKTsKICAgIGxpbmtEZXZXaWRnZXQtPnNldE1pbmltdW1XaWR0aCg2MDApOwoKICAgIHVpLT5hY2NvdW50SG9yTGF5b3V0LT5pbnNlcnRXaWRnZXQoMSwgbGlua0RldldpZGdldCk7CgogICAgbGlua0RldldpZGdldC0+c2hvdygpOwogICAgdWktPmNlbnRyYWxXaWRnZXQtPmhpZGUoKTsKCiAgICBjb25uZWN0KGxpbmtEZXZXaWRnZXQtPmNhbmNlbEJ0bigpLCAmUVB1c2hCdXR0b246OmNsaWNrZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6c2hvd0N1cnJlbnRBY2NvdW50U2xvdCk7CiAgICBjb25uZWN0KGxpbmtEZXZXaWRnZXQtPmVuZENhbmNlbEJ0bigpLCAmUVB1c2hCdXR0b246OmNsaWNrZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6c2hvd0N1cnJlbnRBY2NvdW50U2xvdCk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnNob3dDdXJyZW50QWNjb3VudFNsb3QoKQp7CiAgICBkaXNjb25uZWN0KGxpbmtEZXZXaWRnZXQpOwoKICAgIGRlbGV0ZSBsaW5rRGV2V2lkZ2V0OwogICAgdWktPmNlbnRyYWxXaWRnZXQtPnNob3coKTsKfQoKdm9pZApTZXR0aW5nc1dpZGdldDo6c2V0Q29ubmVjdGlvbnMoKQp7CiAgICAvLyBleGl0U2V0dGluZ3NCdXR0b24KICAgIGNvbm5lY3QodWktPmV4aXRTZXR0aW5nc0J1dHRvbiwgJlFQdXNoQnV0dG9uOjpjbGlja2VkLCB0aGlzLCAmU2V0dGluZ3NXaWRnZXQ6OmxlYXZlU2V0dGluZ3NTbG90KTsKCiAgICBjb25uZWN0KHVpLT5hY2NvdW50U2V0dGluZ3NCdXR0b24sICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgW3RoaXNdKCkgewogICAgICAgIHNldFNlbGVjdGVkKEJ1dHRvbjo6YWNjb3VudFNldHRpbmdzQnV0dG9uKTsgfQogICAgKTsKCiAgICBjb25uZWN0KHVpLT5nZW5lcmFsU2V0dGluZ3NCdXR0b24sICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgW3RoaXNdKCkgewogICAgICAgIHNldFNlbGVjdGVkKEJ1dHRvbjo6Z2VuZXJhbFNldHRpbmdzQnV0dG9uKTsgfQogICAgKTsKCiAgICBjb25uZWN0KHVpLT5hdlNldHRpbmdzQnV0dG9uLCAmUVB1c2hCdXR0b246OmNsaWNrZWQsIFt0aGlzXSgpIHsKICAgICAgICBzZXRTZWxlY3RlZChCdXR0b246OmF2U2V0dGluZ3NCdXR0b24pOyB9CiAgICApOwoKICAgIGNvbm5lY3QodWktPnBhc3N3ZFB1c2hCdXR0b24sICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgW3RoaXNdKCkgewogICAgICAgIHBhc3N3b3JkQ2xpY2tlZCgpOyB9CiAgICApOwoKICAgIGNvbm5lY3QodWktPmN1cnJlbnRBY2NvdW50QXZhdGFyLCAmUVB1c2hCdXR0b246OmNsaWNrZWQsIFt0aGlzXSgpIHsKICAgICAgICBhdmF0YXJDbGlja2VkKCk7IH0KICAgICk7CgogICAgY29ubmVjdCh1aS0+YWR2YW5jZWRBY2NvdW50U2V0dGluZ3NQQnV0dG9uLCAmUVB1c2hCdXR0b246OmNsaWNrZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6dG9nZ2xlQWR2YW5jZWRTZXR0aW5ncyk7CgogICAgY29ubmVjdCh1aS0+Y3VycmVudFJlZ2lzdGVyZWRJRCwgJlFMaW5lRWRpdDo6dGV4dENoYW5nZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6dmVyaWZ5UmVnaXN0ZXJlZE5hbWVTbG90KTsKCiAgICBjb25uZWN0KCZMUkNJbnN0YW5jZTo6YWNjb3VudE1vZGVsKCksICZscmM6OmFwaTo6TmV3QWNjb3VudE1vZGVsOjpyZWdpc3RlcmVkTmFtZUZvdW5kLAogICAgICAgIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6cmVjZWl2ZVJlZ05hbWVTbG90KTsKCiAgICAvL2Nvbm5lY3QgImV4cG9ydCBhY2NvdW50IiBidXR0b24KICAgIGNvbm5lY3QodWktPmJ0bkV4cG9ydEFjY291bnQsICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgdGhpcywgJlNldHRpbmdzV2lkZ2V0OjpleHBvcnRBY2NvdW50U2xvdCk7CgogICAgLy8gY29ubmVjdCAiZGVsZXRlIGFjY291bnQiIGJ1dHRvbgogICAgY29ubmVjdCh1aS0+YnRuRGVsZXRBY2NvdW50LCAmUVB1c2hCdXR0b246OmNsaWNrZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6ZGVsQWNjb3VudFNsb3QpOwoKICAgIC8vIGNvbm5lY3QgImJhbm5lZCBjb250YWN0cyIgYnV0dG9uCiAgICBjb25uZWN0KHVpLT5ibG9ja2VkQ29udGFjdHNCdG4sICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgdGhpcywgJlNldHRpbmdzV2lkZ2V0Ojp0b2dnbGVCYW5uZWRDb250YWN0cyk7CgogICAgLy8gY29ubmVjdCAibGluayBkZXZpY2UiIGJ1dHRvbgogICAgY29ubmVjdCh1aS0+bGlua0RldlB1c2hCdXR0b24sICZRUHVzaEJ1dHRvbjo6Y2xpY2tlZCwgdGhpcywgJlNldHRpbmdzV2lkZ2V0OjpzaG93TGlua0RldlNsb3QpOwoKICAgIC8vIHVwZGF0ZSBiYW5uZWQgYWNjb3VudHMgYXV0b21hdGljYWxseQogICAgY29ubmVjdChMUkNJbnN0YW5jZTo6Z2V0Q3VycmVudEFjY291bnRJbmZvKCkuY29udGFjdE1vZGVsLmdldCgpLCAmbHJjOjphcGk6OkNvbnRhY3RNb2RlbDo6bW9kZWxVcGRhdGVkLAogICAgICAgIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6dXBkYXRlQW5kU2hvd0Jhbm5lZENvbnRhY3RzU2xvdCk7CgogICAgLy8gdXBkYXRlIGxpbmtlZCBkZXZpY2VzIGF1dG9tYXRpY2FsbHkKICAgIFFPYmplY3Q6OmNvbm5lY3QoTFJDSW5zdGFuY2U6OmdldEN1cnJlbnRBY2NvdW50SW5mbygpLmRldmljZU1vZGVsLmdldCgpLCAmbHJjOjphcGk6Ok5ld0RldmljZU1vZGVsOjpkZXZpY2VVcGRhdGVkLAogICAgICAgIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6dXBkYXRlQW5kU2hvd0RldmljZXNTbG90KTsKCiAgICAvLyBhY2NvdW50IHNldHRpbmdzIHNldHRlcnMgewogICAgY29ubmVjdCh1aS0+YWNjb3VudEVuYWJsZUNoZWNrQm94LCAmUUFic3RyYWN0QnV0dG9uOjpjbGlja2VkLCB0aGlzLCAmU2V0dGluZ3NXaWRnZXQ6OnNldEFjY0VuYWJsZVNsb3QpOwoKICAgIGNvbm5lY3QodWktPmRpc3BsYXlOYW1lTGluZUVkaXQsICZRTGluZUVkaXQ6OnRleHRDaGFuZ2VkLCBbdGhpc10oY29uc3QgUVN0cmluZyYgZGlzcGxheU5hbWUpIHsKICAgICAgICBMUkNJbnN0YW5jZTo6c2V0Q3VyckFjY0Rpc3BsYXlOYW1lKGRpc3BsYXlOYW1lLnRvU3RkU3RyaW5nKCkpOwogICAgfQogICAgKTsKCiAgICAvLyBnZW5lcmFsIHNldHRpbmdzCgogICAgY29ubmVjdCh1aS0+bm90aWZpY2F0aW9uQ2hlY2tCb3gsICZRQWJzdHJhY3RCdXR0b246OmNsaWNrZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6c2V0Tm90aWZpY2F0aW9uc1Nsb3QpOwoKICAgIGNvbm5lY3QodWktPmNsb3NlT3JNaW5DaGVja0JveCwgJlFBYnN0cmFjdEJ1dHRvbjo6Y2xpY2tlZCwgdGhpcywgJlNldHRpbmdzV2lkZ2V0OjpzZXRDbG9zZWRPck1pblNsb3QpOwoKICAgIGNvbm5lY3QodWktPmRvd25sb2FkQnV0dG9uLCAmUUFic3RyYWN0QnV0dG9uOjpjbGlja2VkLCB0aGlzLCAmU2V0dGluZ3NXaWRnZXQ6Om9wZW5Eb3dubG9hZEZvbGRlclNsb3QpOwoKICAgIGNvbm5lY3QodWktPmFsd2F5c1JlY29yZGluZ0NoZWNrQm94LCAmUUFic3RyYWN0QnV0dG9uOjpjbGlja2VkLCB0aGlzLCAmU2V0dGluZ3NXaWRnZXQ6OnNldEFsd2F5c1JlY29yZGluZ1Nsb3QpOwoKICAgIGNvbm5lY3QodWktPmNoZWNrVXBkYXRlQnV0dG9uLCAmUUFic3RyYWN0QnV0dG9uOjpjbGlja2VkLCB0aGlzLCAmU2V0dGluZ3NXaWRnZXQ6OmNoZWNrRm9yVXBkYXRlU2xvdCk7CgogICAgY29ubmVjdCh1aS0+aW50ZXJ2YWxVcGRhdGVDaGVja1NwaW5Cb3gsIFFPdmVybG9hZDxpbnQ+OjpvZigmUVNwaW5Cb3g6OnZhbHVlQ2hhbmdlZCksIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6c2V0VXBkYXRlSW50ZXJ2YWxTbG90KTsKCiAgICBjb25uZWN0KHVpLT5hdXRvVXBkYXRlQ2hlY2tCb3gsICZRQWJzdHJhY3RCdXR0b246OmNsaWNrZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6c2V0VXBkYXRlQXV0b21hdGljU2xvdCk7CgogICAgLy8gYXVkaW8gLyB2aXN1YWwgc2V0dGluZ3MKCiAgICBjb25uZWN0KHVpLT5yZWNvcmRQYXRoQnV0dG9uLCAmUVB1c2hCdXR0b246OmNsaWNrZWQsIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6b3BlblJlY29yZEZvbGRlclNsb3QpOwp9CgoKLy8gKioqKioqKioqKioqKioqKioqKioqKioqKiAgR2VuZXJhbCBTZXR0aW5ncyAgKioqKioqKioqKioqKioqKioqKioqKioqKgoKdm9pZCBTZXR0aW5nc1dpZGdldDo6cG9wdWxhdGVHZW5lcmFsU2V0dGluZ3MoKQp7CiAgICBzZXR0aW5nc18gPSBuZXcgUVNldHRpbmdzOwoKICAgIC8vIHNldHRpbmdzCiAgICB1aS0+ZG93bmxvYWRCdXR0b24tPnNldFRleHQoc2V0dGluZ3NfLT52YWx1ZShTZXR0aW5nc0tleTo6ZG93bmxvYWRQYXRoKS50b1N0cmluZygpKTsKICAgIHVpLT5jbG9zZU9yTWluQ2hlY2tCb3gtPnNldENoZWNrZWQoc2V0dGluZ3NfLT52YWx1ZShTZXR0aW5nc0tleTo6Y2xvc2VPck1pbmltaXplZCkudG9Cb29sKCkpOwogICAgdWktPm5vdGlmaWNhdGlvbkNoZWNrQm94LT5zZXRDaGVja2VkKHNldHRpbmdzXy0+dmFsdWUoU2V0dGluZ3NLZXk6OmVuYWJsZU5vdGlmaWNhdGlvbnMpLnRvQm9vbCgpKTsKCiAgICAvL3JlY29yZGluZ3MKICAgIHVpLT5hbHdheXNSZWNvcmRpbmdDaGVja0JveC0+c2V0Q2hlY2tlZChtZWRpYTo6UmVjb3JkaW5nTW9kZWw6Omluc3RhbmNlKCkuaXNBbHdheXNSZWNvcmRpbmcoKSk7CgogICAgaWYgKG1lZGlhOjpSZWNvcmRpbmdNb2RlbDo6aW5zdGFuY2UoKS5yZWNvcmRQYXRoKCkuaXNFbXB0eSgpKSB7CiAgICAgICAgUVN0cmluZyByZWNvcmRQYXRoID0gUURpcjo6dG9OYXRpdmVTZXBhcmF0b3JzKFFTdGFuZGFyZFBhdGhzOjp3cml0YWJsZUxvY2F0aW9uKFFTdGFuZGFyZFBhdGhzOjpEb2N1bWVudHNMb2NhdGlvbikpOwogICAgICAgIG1lZGlhOjpSZWNvcmRpbmdNb2RlbDo6aW5zdGFuY2UoKS5zZXRSZWNvcmRQYXRoKHJlY29yZFBhdGgpOwogICAgfQogICAgdWktPnJlY29yZFBhdGhCdXR0b24tPnNldFRleHQobWVkaWE6OlJlY29yZGluZ01vZGVsOjppbnN0YW5jZSgpLnJlY29yZFBhdGgoKSk7CgogICAgdWktPmF1dG9VcGRhdGVDaGVja0JveC0+c2V0Q2hlY2tlZCh3aW5fc3BhcmtsZV9nZXRfYXV0b21hdGljX2NoZWNrX2Zvcl91cGRhdGVzKCkpOwogICAgdWktPmludGVydmFsVXBkYXRlQ2hlY2tTcGluQm94LT5zZXRWYWx1ZSh3aW5fc3BhcmtsZV9nZXRfdXBkYXRlX2NoZWNrX2ludGVydmFsKCkgLyA4NjQwMCk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnNldE5vdGlmaWNhdGlvbnNTbG90KGludCBzdGF0ZSkKewogICAgaWYgKHN0YXRlID09IFF0OjpDaGVja1N0YXRlOjpVbmNoZWNrZWQpIHsKICAgICAgICBzZXR0aW5nc18tPnNldFZhbHVlKFNldHRpbmdzS2V5OjplbmFibGVOb3RpZmljYXRpb25zLCBmYWxzZSk7CiAgICB9IGVsc2UgewogICAgICAgIHNldHRpbmdzXy0+c2V0VmFsdWUoU2V0dGluZ3NLZXk6OmVuYWJsZU5vdGlmaWNhdGlvbnMsIHRydWUpOwogICAgfQp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpzZXRDbG9zZWRPck1pblNsb3QoaW50IHN0YXRlKQp7CiAgICBpZiAoc3RhdGUgPT0gUXQ6OkNoZWNrU3RhdGU6OlVuY2hlY2tlZCkgewogICAgICAgIHNldHRpbmdzXy0+c2V0VmFsdWUoU2V0dGluZ3NLZXk6OmNsb3NlT3JNaW5pbWl6ZWQsIGZhbHNlKTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIHNldHRpbmdzXy0+c2V0VmFsdWUoU2V0dGluZ3NLZXk6OmNsb3NlT3JNaW5pbWl6ZWQsIHRydWUpOwogICAgfQp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpjaGVja0ZvclVwZGF0ZVNsb3QoKQp7CiAgICB3aW5fc3BhcmtsZV9jaGVja191cGRhdGVfd2l0aF91aSgpOwp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpzZXRVcGRhdGVJbnRlcnZhbFNsb3QoaW50IHZhbHVlKQp7CiAgICB3aW5fc3BhcmtsZV9zZXRfdXBkYXRlX2NoZWNrX2ludGVydmFsKHZhbHVlICogODY0MDApOwp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpzZXRVcGRhdGVBdXRvbWF0aWNTbG90KGludCBzdGF0ZSkKewogICAgaWYgKHN0YXRlID09IFF0OjpDaGVja1N0YXRlOjpVbmNoZWNrZWQpIHsKICAgICAgICB3aW5fc3BhcmtsZV9zZXRfYXV0b21hdGljX2NoZWNrX2Zvcl91cGRhdGVzKGZhbHNlKTsKICAgICAgICB1aS0+aW50ZXJ2YWxVcGRhdGVDaGVja1NwaW5Cb3gtPnNldEVuYWJsZWQoZmFsc2UpOwogICAgfSBlbHNlIHsKICAgICAgICB3aW5fc3BhcmtsZV9zZXRfYXV0b21hdGljX2NoZWNrX2Zvcl91cGRhdGVzKHRydWUpOwogICAgICAgIHVpLT5pbnRlcnZhbFVwZGF0ZUNoZWNrU3BpbkJveC0+c2V0RW5hYmxlZCh0cnVlKTsKICAgIH0KfQoKdm9pZApTZXR0aW5nc1dpZGdldDo6b3BlbkRvd25sb2FkRm9sZGVyU2xvdCgpCnsKICAgIFFTdHJpbmcgZGlyID0gUUZpbGVEaWFsb2c6OmdldEV4aXN0aW5nRGlyZWN0b3J5KHRoaXMsIHRyKCJTZWxlY3QgQSBGb2xkZXIgRm9yIFlvdXIgRG93bmxvYWRzIiksCiAgICAgICAgUVN0YW5kYXJkUGF0aHM6OndyaXRhYmxlTG9jYXRpb24oUVN0YW5kYXJkUGF0aHM6OkRvd25sb2FkTG9jYXRpb24pLCBRRmlsZURpYWxvZzo6U2hvd0RpcnNPbmx5CiAgICAgICAgfCBRRmlsZURpYWxvZzo6RG9udFJlc29sdmVTeW1saW5rcyk7CgogICAgaWYgKCFkaXIuaXNFbXB0eSgpKSB7CiAgICAgICAgdWktPmRvd25sb2FkQnV0dG9uLT5zZXRUZXh0KGRpcik7CiAgICAgICAgc2V0dGluZ3NfLT5zZXRWYWx1ZShTZXR0aW5nc0tleTo6ZG93bmxvYWRQYXRoLCBkaXIpOwogICAgICAgIExSQ0luc3RhbmNlOjplZGl0YWJsZURhdGFUcmFuc2Zlck1vZGVsKCktPmRvd25sb2FkRGlyZWN0b3J5ID0gZGlyLnRvU3RkU3RyaW5nKCkgKyAiLyI7CiAgICB9Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OnNldEFsd2F5c1JlY29yZGluZ1Nsb3QoaW50IHN0YXRlKQp7CiAgICBpZiAoc3RhdGUgPT0gUXQ6OkNoZWNrU3RhdGU6OlVuY2hlY2tlZCkgewogICAgICAgIG1lZGlhOjpSZWNvcmRpbmdNb2RlbDo6aW5zdGFuY2UoKS5zZXRBbHdheXNSZWNvcmRpbmcoZmFsc2UpOwogICAgfSBlbHNlIHsKICAgICAgICBtZWRpYTo6UmVjb3JkaW5nTW9kZWw6Omluc3RhbmNlKCkuc2V0QWx3YXlzUmVjb3JkaW5nKHRydWUpOwogICAgfQp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpvcGVuUmVjb3JkRm9sZGVyU2xvdCgpCnsKICAgIFFTdHJpbmcgZGlyID0gUUZpbGVEaWFsb2c6OmdldEV4aXN0aW5nRGlyZWN0b3J5KHRoaXMsIHRyKCJTZWxlY3QgQSBGb2xkZXIgRm9yIFlvdXIgUmVjb3JkaW5ncyIpLAogICAgICAgIG1lZGlhOjpSZWNvcmRpbmdNb2RlbDo6aW5zdGFuY2UoKS5yZWNvcmRQYXRoKCksIFFGaWxlRGlhbG9nOjpTaG93RGlyc09ubHkgfCBRRmlsZURpYWxvZzo6RG9udFJlc29sdmVTeW1saW5rcyk7CgogICAgaWYgKCFkaXIuaXNFbXB0eSgpKSB7CiAgICAgICAgbWVkaWE6OlJlY29yZGluZ01vZGVsOjppbnN0YW5jZSgpLnNldFJlY29yZFBhdGgoZGlyKTsKICAgICAgICB1aS0+cmVjb3JkUGF0aEJ1dHRvbi0+c2V0VGV4dChtZWRpYTo6UmVjb3JkaW5nTW9kZWw6Omluc3RhbmNlKCkucmVjb3JkUGF0aCgpKTsKICAgIH0KfQoKCi8vICoqKioqKioqKioqKioqKioqKioqKioqKiogIEF1ZGlvL1Zpc3VhbCBTZXR0aW5ncyAgKioqKioqKioqKioqKioqKioqKioqKioqKgoKdm9pZApTZXR0aW5nc1dpZGdldDo6cG9wdWxhdGVBVlNldHRpbmdzKCkKewogICAgdWktPmRldmljZUJveC0+c2V0TW9kZWwoZGV2aWNlTW9kZWxfKTsKICAgIGNvbm5lY3QoZGV2aWNlTW9kZWxfLCBTSUdOQUwoY3VycmVudEluZGV4Q2hhbmdlZChpbnQpKSwKICAgICAgICB0aGlzLCBTTE9UKGRldmljZUluZGV4Q2hhbmdlZChpbnQpKSk7CgogICAgaWYgKHVpLT5kZXZpY2VCb3gtPmNvdW50KCkgPiAwKSB7CiAgICAgICAgZGV2aWNlQm94Q3VycmVudEluZGV4Q2hhbmdlZFNsb3QoMCk7CiAgICB9CgogICAgaWYgKGN1cnJlbnRSZXNJbmRleCA+PSAwKSB7CiAgICAgICAgdWktPnNpemVCb3gtPnNldEN1cnJlbnRJbmRleChjdXJyZW50UmVzSW5kZXgpOwogICAgfQoKICAgIC8vIEF1ZGlvIHNldHRpbmdzCiAgICBhdXRvIGlucHV0TW9kZWwgPSBBdWRpbzo6U2V0dGluZ3M6Omluc3RhbmNlKCkuaW5wdXREZXZpY2VNb2RlbCgpOwogICAgYXV0byBvdXRwdXRNb2RlbCA9IEF1ZGlvOjpTZXR0aW5nczo6aW5zdGFuY2UoKS5vdXRwdXREZXZpY2VNb2RlbCgpOwoKICAgIHVpLT5vdXRwdXRDb21ib0JveC0+c2V0TW9kZWwob3V0cHV0TW9kZWwpOwogICAgdWktPmlucHV0Q29tYm9Cb3gtPnNldE1vZGVsKGlucHV0TW9kZWwpOwogICAgaWYgKHVpLT5vdXRwdXRDb21ib0JveC0+Y291bnQoKSA+IDApIHsKICAgICAgICB1aS0+b3V0cHV0Q29tYm9Cb3gtPnNldEN1cnJlbnRJbmRleCgwKTsKICAgIH0KICAgIGlmICh1aS0+aW5wdXRDb21ib0JveC0+Y291bnQoKSA+IDApIHsKICAgICAgICB1aS0+aW5wdXRDb21ib0JveC0+c2V0Q3VycmVudEluZGV4KDApOwogICAgfQoKICAgIGlzTG9hZGluZ18gPSB0cnVlOwoKICAgIHNob3dQcmV2aWV3KCk7CgogICAgY29ubmVjdCh1aS0+b3V0cHV0Q29tYm9Cb3gsIFFPdmVybG9hZDxpbnQ+OjpvZigmUUNvbWJvQm94OjpjdXJyZW50SW5kZXhDaGFuZ2VkKSwKICAgICAgICB0aGlzLCAmU2V0dGluZ3NXaWRnZXQ6Om91dHB1dERldkluZGV4Q2hhbmdlZFNsb3QpOwogICAgY29ubmVjdCh1aS0+aW5wdXRDb21ib0JveCwgUU92ZXJsb2FkPGludD46Om9mKCZRQ29tYm9Cb3g6OmN1cnJlbnRJbmRleENoYW5nZWQpLAogICAgICAgIHRoaXMsICZTZXR0aW5nc1dpZGdldDo6aW5wdXRkZXZJbmRleENoYW5nZWRTbG90KTsKCiAgICBjb25uZWN0KHVpLT5kZXZpY2VCb3gsIFFPdmVybG9hZDxpbnQ+OjpvZigmUUNvbWJvQm94OjpjdXJyZW50SW5kZXhDaGFuZ2VkKSwgdGhpcywKICAgICAgICAmU2V0dGluZ3NXaWRnZXQ6OmRldmljZUJveEN1cnJlbnRJbmRleENoYW5nZWRTbG90KTsKICAgIGNvbm5lY3QodWktPnNpemVCb3gsIFFPdmVybG9hZDxpbnQ+OjpvZigmUUNvbWJvQm94OjpjdXJyZW50SW5kZXhDaGFuZ2VkKSwgdGhpcywKICAgICAgICAmU2V0dGluZ3NXaWRnZXQ6OnNpemVCb3hDdXJyZW50SW5kZXhDaGFuZ2VkU2xvdCk7Cn0KCgp2b2lkClNldHRpbmdzV2lkZ2V0OjpzYXZlU2l6ZUluZGV4KCkKewogICAgY3VycmVudFJlc0luZGV4ID0gdWktPnNpemVCb3gtPmN1cnJlbnRJbmRleCgpOwp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpzaG93UHJldmlldygpCnsKICAgIGlmICghQ2FsbE1vZGVsOjppbnN0YW5jZSgpLmdldEFjdGl2ZUNhbGxzKCkuc2l6ZSgpKSB7CiAgICAgICAgdWktPnByZXZpZXdVbmF2YWlsYWJsZUxhYmVsLT5oaWRlKCk7CiAgICAgICAgdWktPnZpZGVvV2lkZ2V0LT5zaG93KCk7CiAgICAgICAgc3RhcnRWaWRlbygpOwogICAgICAgIHVpLT52aWRlb1dpZGdldC0+c2V0SXNGdWxsUHJldmlldyh0cnVlKTsKICAgIH0gZWxzZSB7CiAgICAgICAgdWktPnByZXZpZXdVbmF2YWlsYWJsZUxhYmVsLT5zaG93KCk7CiAgICAgICAgdWktPnZpZGVvV2lkZ2V0LT5oaWRlKCk7CiAgICB9Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6OmRldmljZUJveEN1cnJlbnRJbmRleENoYW5nZWRTbG90KGludCBpbmRleCkKewogICAgaWYgKGluZGV4IDwgMCkgewogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoIWlzTG9hZGluZ18pCiAgICAgICAgZGV2aWNlTW9kZWxfLT5zZXRBY3RpdmUoaW5kZXgpOwoKICAgIGF1dG8gZGV2aWNlID0gZGV2aWNlTW9kZWxfLT5hY3RpdmVEZXZpY2UoKTsKCiAgICB1aS0+c2l6ZUJveC0+Y2xlYXIoKTsKCiAgICBpc0xvYWRpbmdfID0gdHJ1ZTsKICAgIGlmIChkZXZpY2UtPmNoYW5uZWxMaXN0KCkuc2l6ZSgpID4gMCkgewogICAgICAgIGZvciAoYXV0byByZXNvbHV0aW9uIDogZGV2aWNlLT5jaGFubmVsTGlzdCgpWzBdLT52YWxpZFJlc29sdXRpb25zKCkpIHsKICAgICAgICAgICAgdWktPnNpemVCb3gtPmFkZEl0ZW0ocmVzb2x1dGlvbi0+bmFtZSgpKTsKICAgICAgICB9CiAgICB9CiAgICB1aS0+c2l6ZUJveC0+c2V0Q3VycmVudEluZGV4KAogICAgICAgIGRldmljZS0+Y2hhbm5lbExpc3QoKVswXS0+YWN0aXZlUmVzb2x1dGlvbigpLT5yZWxhdGl2ZUluZGV4KCkpOwogICAgaXNMb2FkaW5nXyA9IGZhbHNlOwp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpzaXplQm94Q3VycmVudEluZGV4Q2hhbmdlZFNsb3QoaW50IGluZGV4KQp7CiAgICBhdXRvIGRldmljZSA9IGRldmljZU1vZGVsXy0+YWN0aXZlRGV2aWNlKCk7CgogICAgaWYgKGluZGV4IDwgMCkgcmV0dXJuOwoKICAgIGRldmljZS0+Y2hhbm5lbExpc3QoKVswXS0+c2V0QWN0aXZlUmVzb2x1dGlvbihkZXZpY2UtPmNoYW5uZWxMaXN0KClbMF0tPnZhbGlkUmVzb2x1dGlvbnMoKVtpbmRleF0pOwp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpkZXZpY2VJbmRleENoYW5nZWQoaW50IGluZGV4KQp7CiAgICB1aS0+ZGV2aWNlQm94LT5zZXRDdXJyZW50SW5kZXgoaW5kZXgpOwoKICAgIHVpLT52aWRlb0xheW91dC0+dXBkYXRlKCk7Cn0KCnZvaWQKU2V0dGluZ3NXaWRnZXQ6Om91dHB1dERldkluZGV4Q2hhbmdlZFNsb3QoaW50IGluZGV4KQp7CiAgICBhdXRvIG91dHB1dE1vZGVsID0gQXVkaW86OlNldHRpbmdzOjppbnN0YW5jZSgpLm91dHB1dERldmljZU1vZGVsKCk7CiAgICBvdXRwdXRNb2RlbC0+c2VsZWN0aW9uTW9kZWwoKS0+c2V0Q3VycmVudEluZGV4KG91dHB1dE1vZGVsLT5pbmRleChpbmRleCksIFFJdGVtU2VsZWN0aW9uTW9kZWw6OkNsZWFyQW5kU2VsZWN0KTsKfQoKdm9pZApTZXR0aW5nc1dpZGdldDo6aW5wdXRkZXZJbmRleENoYW5nZWRTbG90KGludCBpbmRleCkKewogICAgYXV0byBpbnB1dE1vZGVsID0gQXVkaW86OlNldHRpbmdzOjppbnN0YW5jZSgpLmlucHV0RGV2aWNlTW9kZWwoKTsKICAgIGlucHV0TW9kZWwtPnNlbGVjdGlvbk1vZGVsKCktPnNldEN1cnJlbnRJbmRleChpbnB1dE1vZGVsLT5pbmRleChpbmRleCksIFFJdGVtU2VsZWN0aW9uTW9kZWw6OkNsZWFyQW5kU2VsZWN0KTsKfQoKdm9pZApTZXR0aW5nc1dpZGdldDo6c3RhcnRWaWRlbygpCnsKICAgIFZpZGVvOjpQcmV2aWV3TWFuYWdlcjo6aW5zdGFuY2UoKS5zdG9wUHJldmlldygpOwogICAgVmlkZW86OlByZXZpZXdNYW5hZ2VyOjppbnN0YW5jZSgpLnN0YXJ0UHJldmlldygpOwp9Cgp2b2lkClNldHRpbmdzV2lkZ2V0OjpzdG9wVmlkZW8oKQp7CiAgICBWaWRlbzo6UHJldmlld01hbmFnZXI6Omluc3RhbmNlKCkuc3RvcFByZXZpZXcoKTsKfQ==