Ly8gQ29weXJpZ2h0IDIwMTQgUERGaXVtIEF1dGhvcnMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCi8vIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGEgQlNELXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmUKLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZS4KCi8vIE9yaWdpbmFsIGNvZGUgY29weXJpZ2h0IDIwMTQgRm94aXQgU29mdHdhcmUgSW5jLiBodHRwOi8vd3d3LmZveGl0c29mdHdhcmUuY29tCgojaW5jbHVkZSAiZnBkZnNkay9pbmNsdWRlL3BkZndpbmRvdy9QREZXaW5kb3cuaCIKI2luY2x1ZGUgImZwZGZzZGsvaW5jbHVkZS9wZGZ3aW5kb3cvUFdMX0J1dHRvbi5oIgojaW5jbHVkZSAiZnBkZnNkay9pbmNsdWRlL3BkZndpbmRvdy9QV0xfQ2FyZXQuaCIKI2luY2x1ZGUgImZwZGZzZGsvaW5jbHVkZS9wZGZ3aW5kb3cvUFdMX0VkaXQuaCIKI2luY2x1ZGUgImZwZGZzZGsvaW5jbHVkZS9wZGZ3aW5kb3cvUFdMX0VkaXQuaCIKI2luY2x1ZGUgImZwZGZzZGsvaW5jbHVkZS9wZGZ3aW5kb3cvUFdMX0VkaXRDdHJsLmgiCiNpbmNsdWRlICJmcGRmc2RrL2luY2x1ZGUvcGRmd2luZG93L1BXTF9MYWJlbC5oIgojaW5jbHVkZSAiZnBkZnNkay9pbmNsdWRlL3BkZndpbmRvdy9QV0xfTGlzdEN0cmwuaCIKI2luY2x1ZGUgImZwZGZzZGsvaW5jbHVkZS9wZGZ3aW5kb3cvUFdMX05vdGUuaCIKI2luY2x1ZGUgImZwZGZzZGsvaW5jbHVkZS9wZGZ3aW5kb3cvUFdMX1Njcm9sbEJhci5oIgojaW5jbHVkZSAiZnBkZnNkay9pbmNsdWRlL3BkZndpbmRvdy9QV0xfU2Nyb2xsQmFyLmgiCiNpbmNsdWRlICJmcGRmc2RrL2luY2x1ZGUvcGRmd2luZG93L1BXTF9VdGlscy5oIgojaW5jbHVkZSAiZnBkZnNkay9pbmNsdWRlL3BkZndpbmRvdy9QV0xfV25kLmgiCgojZGVmaW5lIFBPUFVQX0lURU1fSEVBRF9CT1RUT00gMy4wZgojZGVmaW5lIFBPUFVQX0lURU1fQk9UVE9NV0lEVEggMS4wZgojZGVmaW5lIFBPUFVQX0lURU1fU0lERU1BUkdJTiAzLjBmCiNkZWZpbmUgUE9QVVBfSVRFTV9TUEFDRSA0LjBmCiNkZWZpbmUgUE9QVVBfSVRFTV9URVhUX0lOREVOVCAyLjBmCiNkZWZpbmUgUE9QVVBfSVRFTV9CT1JERVJDT0xPUiBcCiAgQ1BXTF9Db2xvcihDT0xPUlRZUEVfUkdCLCA4MCAvIDI1NS4wZiwgODAgLyAyNTUuMGYsIDgwIC8gMjU1LjBmKQoKI2RlZmluZSBJc0Zsb2F0WmVybyhmKSAoKGYpIDwgMC4wMDAxICYmIChmKSA+IC0wLjAwMDEpCiNkZWZpbmUgSXNGbG9hdEJpZ2dlcihmYSwgZmIpICgoZmEpID4gKGZiKSAmJiAhSXNGbG9hdFplcm8oKGZhKSAtIChmYikpKQojZGVmaW5lIElzRmxvYXRTbWFsbGVyKGZhLCBmYikgKChmYSkgPCAoZmIpICYmICFJc0Zsb2F0WmVybygoZmEpIC0gKGZiKSkpCiNkZWZpbmUgSXNGbG9hdEVxdWFsKGZhLCBmYikgSXNGbG9hdFplcm8oKGZhKSAtIChmYikpCgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIENQV0xfTm90ZV9PcHRpb25zCiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCkNQV0xfTm90ZV9PcHRpb25zOjpDUFdMX05vdGVfT3B0aW9ucygpIDogbV9wVGV4dChOVUxMKSB7fQoKQ1BXTF9Ob3RlX09wdGlvbnM6On5DUFdMX05vdGVfT3B0aW9ucygpIHt9Cgp2b2lkIENQV0xfTm90ZV9PcHRpb25zOjpTZXRUZXh0Q29sb3IoY29uc3QgQ1BXTF9Db2xvciYgY29sb3IpIHsKICBDUFdMX1duZDo6U2V0VGV4dENvbG9yKGNvbG9yKTsKCiAgaWYgKG1fcFRleHQpCiAgICBtX3BUZXh0LT5TZXRUZXh0Q29sb3IoY29sb3IpOwp9Cgp2b2lkIENQV0xfTm90ZV9PcHRpb25zOjpSZVBvc0NoaWxkV25kKCkgewogIGlmIChJc1ZhbGlkKCkpIHsKICAgIENQREZfUmVjdCByY0NsaWVudCA9IEdldENsaWVudFJlY3QoKTsKCiAgICBpZiAocmNDbGllbnQuV2lkdGgoKSA+IDE1LjBmKSB7CiAgICAgIHJjQ2xpZW50LnJpZ2h0IC09IDE1LjBmOwogICAgICBtX3BUZXh0LT5Nb3ZlKHJjQ2xpZW50LCBUUlVFLCBGQUxTRSk7CiAgICAgIG1fcFRleHQtPlNldFZpc2libGUoVFJVRSk7CiAgICB9IGVsc2UgewogICAgICBtX3BUZXh0LT5Nb3ZlKENQREZfUmVjdCgwLCAwLCAwLCAwKSwgVFJVRSwgRkFMU0UpOwogICAgICBtX3BUZXh0LT5TZXRWaXNpYmxlKEZBTFNFKTsKICAgIH0KICB9Cn0KCnZvaWQgQ1BXTF9Ob3RlX09wdGlvbnM6OkNyZWF0ZUNoaWxkV25kKGNvbnN0IFBXTF9DUkVBVEVQQVJBTSYgY3ApIHsKICBtX3BUZXh0ID0gbmV3IENQV0xfTGFiZWw7CiAgUFdMX0NSRUFURVBBUkFNIHRjcCA9IGNwOwogIHRjcC5wUGFyZW50V25kID0gdGhpczsKICB0Y3AuZHdGbGFncyA9IFBXU19DSElMRCB8IFBXU19WSVNJQkxFOwogIG1fcFRleHQtPkNyZWF0ZSh0Y3ApOwp9Cgp2b2lkIENQV0xfTm90ZV9PcHRpb25zOjpTZXRUZXh0KGNvbnN0IENGWF9XaWRlU3RyaW5nJiBzVGV4dCkgewogIG1fcFRleHQtPlNldFRleHQoc1RleHQuY19zdHIoKSk7Cn0KCnZvaWQgQ1BXTF9Ob3RlX09wdGlvbnM6OkRyYXdUaGlzQXBwZWFyYW5jZShDRlhfUmVuZGVyRGV2aWNlKiBwRGV2aWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0ZYX01hdHJpeCogcFVzZXIyRGV2aWNlKSB7CiAgQ1BXTF9XbmQ6OkRyYXdUaGlzQXBwZWFyYW5jZShwRGV2aWNlLCBwVXNlcjJEZXZpY2UpOwoKICBDUERGX1JlY3QgcmNDbGllbnQgPSBHZXRDbGllbnRSZWN0KCk7CiAgcmNDbGllbnQubGVmdCA9IHJjQ2xpZW50LnJpZ2h0IC0gMTUuMGY7CgogIENQREZfUG9pbnQgcHRDZW50ZXIgPSBDUERGX1BvaW50KChyY0NsaWVudC5sZWZ0ICsgcmNDbGllbnQucmlnaHQpICogMC41ZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmNDbGllbnQudG9wICsgcmNDbGllbnQuYm90dG9tKSAqIDAuNWYpOwoKICBDUERGX1BvaW50IHB0MShwdENlbnRlci54IC0gMi4wZiwgcHRDZW50ZXIueSArIDIuMGYgKiAwLjVmKTsKICBDUERGX1BvaW50IHB0MihwdENlbnRlci54ICsgMi4wZiwgcHRDZW50ZXIueSArIDIuMGYgKiAwLjVmKTsKICBDUERGX1BvaW50IHB0MyhwdENlbnRlci54LCBwdENlbnRlci55IC0gMy4wZiAqIDAuNWYpOwoKICBDRlhfUGF0aERhdGEgcGF0aDsKCiAgcGF0aC5TZXRQb2ludENvdW50KDQpOwogIHBhdGguU2V0UG9pbnQoMCwgcHQxLngsIHB0MS55LCBGWFBUX01PVkVUTyk7CiAgcGF0aC5TZXRQb2ludCgxLCBwdDIueCwgcHQyLnksIEZYUFRfTElORVRPKTsKICBwYXRoLlNldFBvaW50KDIsIHB0My54LCBwdDMueSwgRlhQVF9MSU5FVE8pOwogIHBhdGguU2V0UG9pbnQoMywgcHQxLngsIHB0MS55LCBGWFBUX0xJTkVUTyk7CgogIHBEZXZpY2UtPkRyYXdQYXRoKAogICAgICAmcGF0aCwgcFVzZXIyRGV2aWNlLCBOVUxMLAogICAgICBDUFdMX1V0aWxzOjpQV0xDb2xvclRvRlhDb2xvcihHZXRUZXh0Q29sb3IoKSwgR2V0VHJhbnNwYXJlbmN5KCkpLCAwLAogICAgICBGWEZJTExfQUxURVJOQVRFKTsKfQoKQ1BERl9SZWN0IENQV0xfTm90ZV9PcHRpb25zOjpHZXRDb250ZW50UmVjdCgpIGNvbnN0IHsKICBDUERGX1JlY3QgcmNUZXh0ID0gbV9wVGV4dC0+R2V0Q29udGVudFJlY3QoKTsKICByY1RleHQucmlnaHQgKz0gMTUuMGY7CiAgcmV0dXJuIHJjVGV4dDsKfQoKLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDUFdMX05vdGVfRWRpdCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICovCgpDUFdMX05vdGVfRWRpdDo6Q1BXTF9Ob3RlX0VkaXQoKQogICAgOiBtX2JFbmFibGVOb3RpZnkoVFJVRSksCiAgICAgIG1fZk9sZEl0ZW1IZWlnaHQoMC4wZiksCiAgICAgIG1fYlNpemVDaGFuZ2VkKEZBTFNFKSwKICAgICAgbV9mT2xkTWluKDAuMGYpLAogICAgICBtX2ZPbGRNYXgoMC4wZikge30KCkNQV0xfTm90ZV9FZGl0Ojp+Q1BXTF9Ob3RlX0VkaXQoKSB7fQoKdm9pZCBDUFdMX05vdGVfRWRpdDo6UmVQb3NDaGlsZFduZCgpIHsKICBtX2JFbmFibGVOb3RpZnkgPSBGQUxTRTsKICBDUFdMX0VkaXQ6OlJlUG9zQ2hpbGRXbmQoKTsKICBtX2JFbmFibGVOb3RpZnkgPSBUUlVFOwoKICBtX2ZPbGRJdGVtSGVpZ2h0ID0gR2V0Q29udGVudFJlY3QoKS5IZWlnaHQoKTsKfQoKdm9pZCBDUFdMX05vdGVfRWRpdDo6U2V0VGV4dChjb25zdCBGWF9XQ0hBUiogY3NUZXh0KSB7CiAgbV9iRW5hYmxlTm90aWZ5ID0gRkFMU0U7CiAgQ1BXTF9FZGl0OjpTZXRUZXh0KGNzVGV4dCk7CiAgbV9iRW5hYmxlTm90aWZ5ID0gVFJVRTsKICBtX2ZPbGRJdGVtSGVpZ2h0ID0gR2V0Q29udGVudFJlY3QoKS5IZWlnaHQoKTsKfQoKdm9pZCBDUFdMX05vdGVfRWRpdDo6T25TZXRGb2N1cygpIHsKICBtX2JFbmFibGVOb3RpZnkgPSBGQUxTRTsKICBDUFdMX0VkaXQ6Ok9uU2V0Rm9jdXMoKTsKICBtX2JFbmFibGVOb3RpZnkgPSBUUlVFOwoKICBFbmFibGVTcGVsbENoZWNrKFRSVUUpOwp9Cgp2b2lkIENQV0xfTm90ZV9FZGl0OjpPbktpbGxGb2N1cygpIHsKICBFbmFibGVTcGVsbENoZWNrKEZBTFNFKTsKCiAgaWYgKENQV0xfV25kKiBwUGFyZW50ID0gR2V0UGFyZW50V2luZG93KCkpIHsKICAgIGlmIChDUFdMX1duZCogcEdyYW5kID0gcFBhcmVudC0+R2V0UGFyZW50V2luZG93KCkpIHsKICAgICAgQVNTRVJUKHBHcmFuZC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZUl0ZW0iKTsKCiAgICAgIENQV0xfTm90ZUl0ZW0qIHBOb3RlSXRlbSA9IChDUFdMX05vdGVJdGVtKilwR3JhbmQ7CgogICAgICBwTm90ZUl0ZW0tPk9uQ29udGVudHNWYWxpZGF0ZSgpOwogICAgfQogIH0KCiAgQ1BXTF9FZGl0OjpPbktpbGxGb2N1cygpOwp9Cgp2b2lkIENQV0xfTm90ZV9FZGl0OjpPbk5vdGlmeShDUFdMX1duZCogcFduZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlhfRFdPUkQgbXNnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRwdHJfdCB3UGFyYW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludHB0cl90IGxQYXJhbSkgewogIGlmIChtX2JFbmFibGVOb3RpZnkpIHsKICAgIGlmICh3UGFyYW0gPT0gU0JUX1ZTQ1JPTEwpIHsKICAgICAgc3dpdGNoIChtc2cpIHsKICAgICAgICBjYXNlIFBOTV9TRVRTQ1JPTExJTkZPOgogICAgICAgICAgaWYgKFBXTF9TQ1JPTExfSU5GTyogcEluZm8gPSAoUFdMX1NDUk9MTF9JTkZPKilsUGFyYW0pIHsKICAgICAgICAgICAgaWYgKCFJc0Zsb2F0RXF1YWwocEluZm8tPmZDb250ZW50TWF4LCBtX2ZPbGRNYXgpIHx8CiAgICAgICAgICAgICAgICAhSXNGbG9hdEVxdWFsKHBJbmZvLT5mQ29udGVudE1pbiwgbV9mT2xkTWluKSkgewogICAgICAgICAgICAgIG1fYlNpemVDaGFuZ2VkID0gVFJVRTsKICAgICAgICAgICAgICBpZiAoQ1BXTF9XbmQqIHBQYXJlbnQgPSBHZXRQYXJlbnRXaW5kb3coKSkgewogICAgICAgICAgICAgICAgcFBhcmVudC0+T25Ob3RpZnkodGhpcywgUE5NX05PVEVFRElUQ0hBTkdFRCwgMCwgMCk7CiAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICBtX2ZPbGRNYXggPSBwSW5mby0+ZkNvbnRlbnRNYXg7CiAgICAgICAgICAgICAgbV9mT2xkTWluID0gcEluZm8tPmZDb250ZW50TWluOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQoKICBDUFdMX0VkaXQ6Ok9uTm90aWZ5KHBXbmQsIG1zZywgd1BhcmFtLCBsUGFyYW0pOwoKICBpZiAobV9iRW5hYmxlTm90aWZ5KSB7CiAgICBzd2l0Y2ggKG1zZykgewogICAgICBjYXNlIFBOTV9TRVRDQVJFVElORk86CiAgICAgICAgaWYgKFBXTF9DQVJFVF9JTkZPKiBwSW5mbyA9IChQV0xfQ0FSRVRfSU5GTyopd1BhcmFtKSB7CiAgICAgICAgICBQV0xfQ0FSRVRfSU5GTyBuZXdJbmZvID0gKnBJbmZvOwogICAgICAgICAgbmV3SW5mby5iVmlzaWJsZSA9IFRSVUU7CiAgICAgICAgICBuZXdJbmZvLnB0SGVhZCA9IENoaWxkVG9QYXJlbnQocEluZm8tPnB0SGVhZCk7CiAgICAgICAgICBuZXdJbmZvLnB0Rm9vdCA9IENoaWxkVG9QYXJlbnQocEluZm8tPnB0Rm9vdCk7CgogICAgICAgICAgaWYgKENQV0xfV25kKiBwUGFyZW50ID0gR2V0UGFyZW50V2luZG93KCkpIHsKICAgICAgICAgICAgcFBhcmVudC0+T25Ob3RpZnkodGhpcywgUE5NX1NFVENBUkVUSU5GTywgKGludHB0cl90KSZuZXdJbmZvLCAwKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQp9CgpGWF9GTE9BVCBDUFdMX05vdGVfRWRpdDo6R2V0SXRlbUhlaWdodChGWF9GTE9BVCBmTGltaXRXaWR0aCkgewogIGlmIChmTGltaXRXaWR0aCA+IDApIHsKICAgIGlmICghbV9iU2l6ZUNoYW5nZWQpCiAgICAgIHJldHVybiBtX2ZPbGRJdGVtSGVpZ2h0OwoKICAgIG1fYlNpemVDaGFuZ2VkID0gRkFMU0U7CgogICAgRW5hYmxlTm90aWZ5KEZBTFNFKTsKICAgIEVuYWJsZVJlZnJlc2goRkFMU0UpOwogICAgbV9wRWRpdC0+RW5hYmxlTm90aWZ5KEZBTFNFKTsKCiAgICBNb3ZlKENQREZfUmVjdCgwLCAwLCBmTGltaXRXaWR0aCwgMCksIFRSVUUsIEZBTFNFKTsKICAgIEZYX0ZMT0FUIGZSZXQgPSBHZXRDb250ZW50UmVjdCgpLkhlaWdodCgpOwoKICAgIG1fcEVkaXQtPkVuYWJsZU5vdGlmeShUUlVFKTsKICAgIEVuYWJsZU5vdGlmeShUUlVFKTsKICAgIEVuYWJsZVJlZnJlc2goVFJVRSk7CgogICAgcmV0dXJuIGZSZXQ7CiAgfQoKICByZXR1cm4gMDsKfQoKRlhfRkxPQVQgQ1BXTF9Ob3RlX0VkaXQ6OkdldEl0ZW1MZWZ0TWFyZ2luKCkgewogIHJldHVybiBQT1BVUF9JVEVNX1RFWFRfSU5ERU5UOwp9CgpGWF9GTE9BVCBDUFdMX05vdGVfRWRpdDo6R2V0SXRlbVJpZ2h0TWFyZ2luKCkgewogIHJldHVybiBQT1BVUF9JVEVNX1RFWFRfSU5ERU5UOwp9CgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDUFdMX05vdGVfTEJCb3gKICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwoKQ1BXTF9Ob3RlX0xCQm94OjpDUFdMX05vdGVfTEJCb3goKSB7fQoKQ1BXTF9Ob3RlX0xCQm94Ojp+Q1BXTF9Ob3RlX0xCQm94KCkge30KCnZvaWQgQ1BXTF9Ob3RlX0xCQm94OjpEcmF3VGhpc0FwcGVhcmFuY2UoQ0ZYX1JlbmRlckRldmljZSogcERldmljZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDRlhfTWF0cml4KiBwVXNlcjJEZXZpY2UpIHsKICBDUERGX1JlY3QgcmNDbGllbnQgPSBHZXRDbGllbnRSZWN0KCk7CgogIENGWF9HcmFwaFN0YXRlRGF0YSBnc2Q7CiAgZ3NkLm1fTGluZVdpZHRoID0gMS4wZjsKCiAgQ0ZYX1BhdGhEYXRhIHBhdGhDcm9zczsKCiAgcGF0aENyb3NzLlNldFBvaW50Q291bnQoNCk7CiAgcGF0aENyb3NzLlNldFBvaW50KDAsIHJjQ2xpZW50LmxlZnQsIHJjQ2xpZW50LnRvcCwgRlhQVF9NT1ZFVE8pOwogIHBhdGhDcm9zcy5TZXRQb2ludCgxLCByY0NsaWVudC5yaWdodCwgcmNDbGllbnQuYm90dG9tLCBGWFBUX0xJTkVUTyk7CiAgcGF0aENyb3NzLlNldFBvaW50KDIsIHJjQ2xpZW50LmxlZnQsCiAgICAgICAgICAgICAgICAgICAgIHJjQ2xpZW50LmJvdHRvbSArIHJjQ2xpZW50LkhlaWdodCgpICogMC41ZiwgRlhQVF9NT1ZFVE8pOwogIHBhdGhDcm9zcy5TZXRQb2ludCgzLCByY0NsaWVudC5sZWZ0ICsgcmNDbGllbnQuV2lkdGgoKSAqIDAuNWYsCiAgICAgICAgICAgICAgICAgICAgIHJjQ2xpZW50LmJvdHRvbSwgRlhQVF9MSU5FVE8pOwoKICBwRGV2aWNlLT5EcmF3UGF0aCgKICAgICAgJnBhdGhDcm9zcywgcFVzZXIyRGV2aWNlLCAmZ3NkLCAwLAogICAgICBDUFdMX1V0aWxzOjpQV0xDb2xvclRvRlhDb2xvcihHZXRUZXh0Q29sb3IoKSwgR2V0VHJhbnNwYXJlbmN5KCkpLAogICAgICBGWEZJTExfQUxURVJOQVRFKTsKfQoKLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ1BXTF9Ob3RlX1JCQm94CiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KCkNQV0xfTm90ZV9SQkJveDo6Q1BXTF9Ob3RlX1JCQm94KCkge30KCkNQV0xfTm90ZV9SQkJveDo6fkNQV0xfTm90ZV9SQkJveCgpIHt9Cgp2b2lkIENQV0xfTm90ZV9SQkJveDo6RHJhd1RoaXNBcHBlYXJhbmNlKENGWF9SZW5kZXJEZXZpY2UqIHBEZXZpY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0ZYX01hdHJpeCogcFVzZXIyRGV2aWNlKSB7CiAgQ1BERl9SZWN0IHJjQ2xpZW50ID0gR2V0Q2xpZW50UmVjdCgpOwoKICBDRlhfR3JhcGhTdGF0ZURhdGEgZ3NkOwogIGdzZC5tX0xpbmVXaWR0aCA9IDEuMGY7CgogIENGWF9QYXRoRGF0YSBwYXRoQ3Jvc3M7CgogIHBhdGhDcm9zcy5TZXRQb2ludENvdW50KDQpOwogIHBhdGhDcm9zcy5TZXRQb2ludCgwLCByY0NsaWVudC5yaWdodCwgcmNDbGllbnQudG9wLCBGWFBUX01PVkVUTyk7CiAgcGF0aENyb3NzLlNldFBvaW50KDEsIHJjQ2xpZW50LmxlZnQsIHJjQ2xpZW50LmJvdHRvbSwgRlhQVF9MSU5FVE8pOwogIHBhdGhDcm9zcy5TZXRQb2ludCgyLCByY0NsaWVudC5yaWdodCwKICAgICAgICAgICAgICAgICAgICAgcmNDbGllbnQuYm90dG9tICsgcmNDbGllbnQuSGVpZ2h0KCkgKiAwLjVmLCBGWFBUX01PVkVUTyk7CiAgcGF0aENyb3NzLlNldFBvaW50KDMsIHJjQ2xpZW50LmxlZnQgKyByY0NsaWVudC5XaWR0aCgpICogMC41ZiwKICAgICAgICAgICAgICAgICAgICAgcmNDbGllbnQuYm90dG9tLCBGWFBUX0xJTkVUTyk7CgogIHBEZXZpY2UtPkRyYXdQYXRoKAogICAgICAmcGF0aENyb3NzLCBwVXNlcjJEZXZpY2UsICZnc2QsIDAsCiAgICAgIENQV0xfVXRpbHM6OlBXTENvbG9yVG9GWENvbG9yKEdldFRleHRDb2xvcigpLCBHZXRUcmFuc3BhcmVuY3koKSksCiAgICAgIEZYRklMTF9BTFRFUk5BVEUpOwp9CgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ1BXTF9Ob3RlX0ljb24KICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKQ1BXTF9Ob3RlX0ljb246OkNQV0xfTm90ZV9JY29uKCkgOiBtX25UeXBlKDApIHt9CgpDUFdMX05vdGVfSWNvbjo6fkNQV0xfTm90ZV9JY29uKCkge30KCnZvaWQgQ1BXTF9Ob3RlX0ljb246OlNldEljb25UeXBlKGludDMyX3QgblR5cGUpIHsKICBtX25UeXBlID0gblR5cGU7Cn0KCnZvaWQgQ1BXTF9Ob3RlX0ljb246OkRyYXdUaGlzQXBwZWFyYW5jZShDRlhfUmVuZGVyRGV2aWNlKiBwRGV2aWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0ZYX01hdHJpeCogcFVzZXIyRGV2aWNlKSB7CiAgQ1BXTF9VdGlsczo6RHJhd0ljb25BcHBTdHJlYW0ocERldmljZSwgcFVzZXIyRGV2aWNlLCBtX25UeXBlLCBHZXRDbGllbnRSZWN0KCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2V0QmFja2dyb3VuZENvbG9yKCksIFBXTF9ERUZBVUxUX0JMQUNLQ09MT1IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2V0VHJhbnNwYXJlbmN5KCkpOwp9CgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ1BXTF9Ob3RlX0Nsb3NlQm94CiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCkNQV0xfTm90ZV9DbG9zZUJveDo6Q1BXTF9Ob3RlX0Nsb3NlQm94KCkgOiBtX2JNb3VzZURvd24oRkFMU0UpIHt9CgpDUFdMX05vdGVfQ2xvc2VCb3g6On5DUFdMX05vdGVfQ2xvc2VCb3goKSB7fQoKdm9pZCBDUFdMX05vdGVfQ2xvc2VCb3g6OkRyYXdUaGlzQXBwZWFyYW5jZShDRlhfUmVuZGVyRGV2aWNlKiBwRGV2aWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENGWF9NYXRyaXgqIHBVc2VyMkRldmljZSkgewogIENQV0xfQnV0dG9uOjpEcmF3VGhpc0FwcGVhcmFuY2UocERldmljZSwgcFVzZXIyRGV2aWNlKTsKCiAgQ1BERl9SZWN0IHJjQ2xpZW50ID0gR2V0Q2xpZW50UmVjdCgpOwogIHJjQ2xpZW50ID0gQ1BXTF9VdGlsczo6RGVmbGF0ZVJlY3QocmNDbGllbnQsIDIuMGYpOwoKICBDRlhfR3JhcGhTdGF0ZURhdGEgZ3NkOwogIGdzZC5tX0xpbmVXaWR0aCA9IDEuMGY7CgogIENGWF9QYXRoRGF0YSBwYXRoQ3Jvc3M7CgogIGlmIChtX2JNb3VzZURvd24pIHsKICAgIHJjQ2xpZW50LmxlZnQgKz0gMC41ZjsKICAgIHJjQ2xpZW50LnJpZ2h0ICs9IDAuNWY7CiAgICByY0NsaWVudC50b3AgLT0gMC41ZjsKICAgIHJjQ2xpZW50LmJvdHRvbSAtPSAwLjVmOwogIH0KCiAgcGF0aENyb3NzLlNldFBvaW50Q291bnQoNCk7CiAgcGF0aENyb3NzLlNldFBvaW50KDAsIHJjQ2xpZW50LmxlZnQsIHJjQ2xpZW50LmJvdHRvbSwgRlhQVF9NT1ZFVE8pOwogIHBhdGhDcm9zcy5TZXRQb2ludCgxLCByY0NsaWVudC5yaWdodCwgcmNDbGllbnQudG9wLCBGWFBUX0xJTkVUTyk7CiAgcGF0aENyb3NzLlNldFBvaW50KDIsIHJjQ2xpZW50LmxlZnQsIHJjQ2xpZW50LnRvcCwgRlhQVF9NT1ZFVE8pOwogIHBhdGhDcm9zcy5TZXRQb2ludCgzLCByY0NsaWVudC5yaWdodCwgcmNDbGllbnQuYm90dG9tLCBGWFBUX0xJTkVUTyk7CgogIHBEZXZpY2UtPkRyYXdQYXRoKAogICAgICAmcGF0aENyb3NzLCBwVXNlcjJEZXZpY2UsICZnc2QsIDAsCiAgICAgIENQV0xfVXRpbHM6OlBXTENvbG9yVG9GWENvbG9yKEdldFRleHRDb2xvcigpLCBHZXRUcmFuc3BhcmVuY3koKSksCiAgICAgIEZYRklMTF9BTFRFUk5BVEUpOwp9CgpGWF9CT09MIENQV0xfTm90ZV9DbG9zZUJveDo6T25MQnV0dG9uRG93bihjb25zdCBDUERGX1BvaW50JiBwb2ludCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlhfRFdPUkQgbkZsYWcpIHsKICBTZXRCb3JkZXJTdHlsZShQQlNfSU5TRVQpOwogIEludmFsaWRhdGVSZWN0KE5VTEwpOwoKICBtX2JNb3VzZURvd24gPSBUUlVFOwoKICByZXR1cm4gQ1BXTF9CdXR0b246Ok9uTEJ1dHRvbkRvd24ocG9pbnQsIG5GbGFnKTsKfQoKRlhfQk9PTCBDUFdMX05vdGVfQ2xvc2VCb3g6Ok9uTEJ1dHRvblVwKGNvbnN0IENQREZfUG9pbnQmIHBvaW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlhfRFdPUkQgbkZsYWcpIHsKICBtX2JNb3VzZURvd24gPSBGQUxTRTsKCiAgU2V0Qm9yZGVyU3R5bGUoUEJTX0JFVkVMRUQpOwogIEludmFsaWRhdGVSZWN0KE5VTEwpOwoKICByZXR1cm4gQ1BXTF9CdXR0b246Ok9uTEJ1dHRvblVwKHBvaW50LCBuRmxhZyk7Cn0KCi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDUFdMX05vdGVfQ29udGVudHMKICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKQ1BXTF9Ob3RlX0NvbnRlbnRzOjpDUFdMX05vdGVfQ29udGVudHMoKSA6IG1fcEVkaXQoTlVMTCkge30KCkNQV0xfTm90ZV9Db250ZW50czo6fkNQV0xfTm90ZV9Db250ZW50cygpIHt9CgpDRlhfQnl0ZVN0cmluZyBDUFdMX05vdGVfQ29udGVudHM6OkdldENsYXNzTmFtZSgpIGNvbnN0IHsKICByZXR1cm4gIkNQV0xfTm90ZV9Db250ZW50cyI7Cn0KCnZvaWQgQ1BXTF9Ob3RlX0NvbnRlbnRzOjpDcmVhdGVDaGlsZFduZChjb25zdCBQV0xfQ1JFQVRFUEFSQU0mIGNwKSB7CiAgbV9wRWRpdCA9IG5ldyBDUFdMX05vdGVfRWRpdDsKICBQV0xfQ1JFQVRFUEFSQU0gZWNwID0gY3A7CiAgZWNwLnBQYXJlbnRXbmQgPSB0aGlzOwogIGVjcC5kd0ZsYWdzID0gUFdTX1ZJU0lCTEUgfCBQV1NfQ0hJTEQgfCBQRVNfTVVMVElMSU5FIHwgUEVTX0FVVE9SRVRVUk4gfAogICAgICAgICAgICAgICAgUEVTX1RFWFRPVkVSRkxPVyB8IFBFU19VTkRPIHwgUEVTX1NQRUxMQ0hFQ0s7CgogIG1fcEVkaXQtPkVuYWJsZU5vdGlmeShGQUxTRSk7CiAgbV9wRWRpdC0+Q3JlYXRlKGVjcCk7CiAgbV9wRWRpdC0+RW5hYmxlTm90aWZ5KFRSVUUpOwp9Cgp2b2lkIENQV0xfTm90ZV9Db250ZW50czo6U2V0VGV4dChjb25zdCBDRlhfV2lkZVN0cmluZyYgc1RleHQpIHsKICBpZiAobV9wRWRpdCkgewogICAgbV9wRWRpdC0+RW5hYmxlTm90aWZ5KEZBTFNFKTsKICAgIG1fcEVkaXQtPlNldFRleHQoc1RleHQuY19zdHIoKSk7CiAgICBtX3BFZGl0LT5FbmFibGVOb3RpZnkoVFJVRSk7CiAgICBPbk5vdGlmeShtX3BFZGl0LCBQTk1fTk9URUVESVRDSEFOR0VELCAwLCAwKTsKICB9Cn0KCkNGWF9XaWRlU3RyaW5nIENQV0xfTm90ZV9Db250ZW50czo6R2V0VGV4dCgpIGNvbnN0IHsKICBpZiAobV9wRWRpdCkKICAgIHJldHVybiBtX3BFZGl0LT5HZXRUZXh0KCk7CgogIHJldHVybiBMIiI7Cn0KCkNQV0xfTm90ZUl0ZW0qIENQV0xfTm90ZV9Db250ZW50czo6Q3JlYXRlU3ViSXRlbSgpIHsKICBDUFdMX05vdGVJdGVtKiBwTm90ZUl0ZW0gPSBuZXcgQ1BXTF9Ob3RlSXRlbTsKICBQV0xfQ1JFQVRFUEFSQU0gaWNwID0gR2V0Q3JlYXRpb25QYXJhbSgpOwogIGljcC5wUGFyZW50V25kID0gdGhpczsKICBpY3AuZHdGbGFncyA9IFBXU19DSElMRCB8IFBXU19WSVNJQkxFIHwgUFdTX0JBQ0tHUk9VTkQ7CiAgcE5vdGVJdGVtLT5DcmVhdGUoaWNwKTsKCiAgcE5vdGVJdGVtLT5PbkNyZWF0ZU5vdGVJdGVtKCk7CgogIHBOb3RlSXRlbS0+UmVzZXRTdWJqZWN0TmFtZShtX2FDaGlsZHJlbi5HZXRTaXplKCkgLSAxKTsKCiAgRlhfU1lTVEVNVElNRSBzdDsKICBpZiAoSUZYX1N5c3RlbUhhbmRsZXIqIHBTSCA9IEdldFN5c3RlbUhhbmRsZXIoKSkKICAgIHN0ID0gcFNILT5HZXRMb2NhbFRpbWUoKTsKICBwTm90ZUl0ZW0tPlNldERhdGVUaW1lKHN0KTsKCiAgcE5vdGVJdGVtLT5TZXRDb250ZW50cyhMIiIpOwoKICBPbk5vdGlmeShwTm90ZUl0ZW0sIFBOTV9OT1RFRURJVENIQU5HRUQsIDAsIDApOwoKICByZXR1cm4gcE5vdGVJdGVtOwp9CgppbnQzMl90IENQV0xfTm90ZV9Db250ZW50czo6Q291bnRTdWJJdGVtcygpIGNvbnN0IHsKICByZXR1cm4gbV9hQ2hpbGRyZW4uR2V0U2l6ZSgpIC0gMTsKfQoKSVBXTF9Ob3RlSXRlbSogQ1BXTF9Ob3RlX0NvbnRlbnRzOjpHZXRTdWJJdGVtcyhpbnQzMl90IGluZGV4KSBjb25zdCB7CiAgaW50MzJfdCBuSW5kZXggPSBpbmRleCArIDE7CgogIGlmIChuSW5kZXggPiAwICYmIG5JbmRleCA8IG1fYUNoaWxkcmVuLkdldFNpemUoKSkKICAgIGlmIChDUFdMX1duZCogcENoaWxkID0gbV9hQ2hpbGRyZW4uR2V0QXQobkluZGV4KSkgewogICAgICBBU1NFUlQocENoaWxkLT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9Ob3RlSXRlbSIpOwogICAgICBDUFdMX05vdGVJdGVtKiBwSXRlbSA9IChDUFdMX05vdGVJdGVtKilwQ2hpbGQ7CiAgICAgIHJldHVybiBwSXRlbTsKICAgIH0KICByZXR1cm4gTlVMTDsKfQoKdm9pZCBDUFdMX05vdGVfQ29udGVudHM6OkRlbGV0ZVN1Ykl0ZW0oSVBXTF9Ob3RlSXRlbSogcE5vdGVJdGVtKSB7CiAgaW50MzJfdCBuSW5kZXggPSBHZXRJdGVtSW5kZXgoKENQV0xfTm90ZUl0ZW0qKXBOb3RlSXRlbSk7CgogIGlmIChuSW5kZXggPiAwKSB7CiAgICBpZiAoQ1BXTF9Ob3RlSXRlbSogcFBXTE5vdGVJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBOb3RlSXRlbSkgewogICAgICBwUFdMTm90ZUl0ZW0tPktpbGxGb2N1cygpOwogICAgICBwUFdMTm90ZUl0ZW0tPkRlc3Ryb3koKTsKICAgICAgZGVsZXRlIHBQV0xOb3RlSXRlbTsKICAgIH0KCiAgICBmb3IgKGludDMyX3QgaSA9IG5JbmRleCwgc3ogPSBtX2FDaGlsZHJlbi5HZXRTaXplKCk7IGkgPCBzejsgaSsrKSB7CiAgICAgIGlmIChDUFdMX1duZCogcENoaWxkID0gbV9hQ2hpbGRyZW4uR2V0QXQoaSkpIHsKICAgICAgICBBU1NFUlQocENoaWxkLT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9Ob3RlSXRlbSIpOwogICAgICAgIENQV0xfTm90ZUl0ZW0qIHBJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBDaGlsZDsKICAgICAgICBwSXRlbS0+UmVzZXRTdWJqZWN0TmFtZShpKTsKICAgICAgfQogICAgfQoKICAgIE9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFRURJVENIQU5HRUQsIDAsIDApOwogIH0KfQoKSVBXTF9Ob3RlSXRlbSogQ1BXTF9Ob3RlX0NvbnRlbnRzOjpHZXRIaXROb3RlSXRlbShjb25zdCBDUERGX1BvaW50JiBwb2ludCkgewogIENQREZfUG9pbnQgcHQgPSBQYXJlbnRUb0NoaWxkKHBvaW50KTsKCiAgZm9yIChpbnQzMl90IGkgPSAwLCBzeiA9IG1fYUNoaWxkcmVuLkdldFNpemUoKTsgaSA8IHN6OyBpKyspIHsKICAgIGlmIChDUFdMX1duZCogcENoaWxkID0gbV9hQ2hpbGRyZW4uR2V0QXQoaSkpIHsKICAgICAgaWYgKHBDaGlsZC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZUl0ZW0iKSB7CiAgICAgICAgQ1BXTF9Ob3RlSXRlbSogcE5vdGVJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBDaGlsZDsKICAgICAgICBpZiAoSVBXTF9Ob3RlSXRlbSogcFJldCA9IHBOb3RlSXRlbS0+R2V0SGl0Tm90ZUl0ZW0ocHQpKQogICAgICAgICAgcmV0dXJuIHBSZXQ7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIE5VTEw7Cn0KCnZvaWQgQ1BXTF9Ob3RlX0NvbnRlbnRzOjpPbk5vdGlmeShDUFdMX1duZCogcFduZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZYX0RXT1JEIG1zZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludHB0cl90IHdQYXJhbSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludHB0cl90IGxQYXJhbSkgewogIHN3aXRjaCAobXNnKSB7CiAgICBjYXNlIFBOTV9OT1RFRURJVENIQU5HRUQ6IHsKICAgICAgaW50MzJfdCBuSW5kZXggPSBHZXRJdGVtSW5kZXgocFduZCk7CiAgICAgIGlmIChuSW5kZXggPCAwKQogICAgICAgIG5JbmRleCA9IDA7CgogICAgICBtX3BFZGl0LT5FbmFibGVOb3RpZnkoRkFMU0UpOwogICAgICBSZXNldENvbnRlbnQobkluZGV4KTsKICAgICAgbV9wRWRpdC0+RW5hYmxlTm90aWZ5KFRSVUUpOwoKICAgICAgZm9yIChpbnQzMl90IGkgPSBuSW5kZXggKyAxLCBzeiA9IG1fYUNoaWxkcmVuLkdldFNpemUoKTsgaSA8IHN6OyBpKyspIHsKICAgICAgICBpZiAoQ1BXTF9XbmQqIHBDaGlsZCA9IG1fYUNoaWxkcmVuLkdldEF0KGkpKQogICAgICAgICAgcENoaWxkLT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URVJFU0VULCAwLCAwKTsKICAgICAgfQoKICAgICAgaWYgKENQV0xfV25kKiBwUGFyZW50ID0gR2V0UGFyZW50V2luZG93KCkpIHsKICAgICAgICBwUGFyZW50LT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URUVESVRDSEFOR0VELCAwLCAwKTsKICAgICAgfQogICAgfQogICAgICByZXR1cm47CiAgICBjYXNlIFBOTV9TQ1JPTExXSU5ET1c6CiAgICAgIFNldFNjcm9sbFBvcyhDUERGX1BvaW50KDAuMGYsICooRlhfRkxPQVQqKWxQYXJhbSkpOwogICAgICBSZXNldEZhY2UoKTsKICAgICAgSW52YWxpZGF0ZVJlY3QoTlVMTCk7CiAgICAgIHJldHVybjsKICAgIGNhc2UgUE5NX1NFVENBUkVUSU5GTzoKICAgICAgaWYgKFBXTF9DQVJFVF9JTkZPKiBwSW5mbyA9IChQV0xfQ0FSRVRfSU5GTyopd1BhcmFtKSB7CiAgICAgICAgUFdMX0NBUkVUX0lORk8gbmV3SW5mbyA9ICpwSW5mbzsKICAgICAgICBuZXdJbmZvLmJWaXNpYmxlID0gVFJVRTsKICAgICAgICBuZXdJbmZvLnB0SGVhZCA9IENoaWxkVG9QYXJlbnQocEluZm8tPnB0SGVhZCk7CiAgICAgICAgbmV3SW5mby5wdEZvb3QgPSBDaGlsZFRvUGFyZW50KHBJbmZvLT5wdEZvb3QpOwoKICAgICAgICBpZiAoQ1BXTF9XbmQqIHBQYXJlbnQgPSBHZXRQYXJlbnRXaW5kb3coKSkgewogICAgICAgICAgcFBhcmVudC0+T25Ob3RpZnkodGhpcywgUE5NX1NFVENBUkVUSU5GTywgKGludHB0cl90KSZuZXdJbmZvLCAwKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgY2FzZSBQTk1fTk9URVJFU0VUOiB7CiAgICAgIG1fcEVkaXQtPkVuYWJsZU5vdGlmeShGQUxTRSk7CiAgICAgIFJlc2V0Q29udGVudCgwKTsKICAgICAgbV9wRWRpdC0+RW5hYmxlTm90aWZ5KFRSVUUpOwoKICAgICAgZm9yIChpbnQzMl90IGkgPSAxLCBzeiA9IG1fYUNoaWxkcmVuLkdldFNpemUoKTsgaSA8IHN6OyBpKyspIHsKICAgICAgICBpZiAoQ1BXTF9XbmQqIHBDaGlsZCA9IG1fYUNoaWxkcmVuLkdldEF0KGkpKQogICAgICAgICAgcENoaWxkLT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URVJFU0VULCAwLCAwKTsKICAgICAgfQoKICAgICAgbV9wRWRpdC0+RW5hYmxlTm90aWZ5KEZBTFNFKTsKICAgICAgUmVzZXRDb250ZW50KDApOwogICAgICBtX3BFZGl0LT5FbmFibGVOb3RpZnkoVFJVRSk7CiAgICB9CiAgICAgIHJldHVybjsKICB9CgogIENQV0xfV25kOjpPbk5vdGlmeShwV25kLCBtc2csIHdQYXJhbSwgbFBhcmFtKTsKfQoKRlhfQk9PTCBDUFdMX05vdGVfQ29udGVudHM6Ok9uTEJ1dHRvbkRvd24oY29uc3QgQ1BERl9Qb2ludCYgcG9pbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZYX0RXT1JEIG5GbGFnKSB7CiAgaWYgKENQV0xfV25kOjpPbkxCdXR0b25Eb3duKHBvaW50LCBuRmxhZykpCiAgICByZXR1cm4gVFJVRTsKCiAgaWYgKCFtX3BFZGl0LT5Jc0ZvY3VzZWQoKSkgewogICAgbV9wRWRpdC0+U2V0Rm9jdXMoKTsKICB9CgogIHJldHVybiBUUlVFOwp9Cgp2b2lkIENQV0xfTm90ZV9Db250ZW50czo6U2V0RWRpdEZvY3VzKEZYX0JPT0wgYkxhc3QpIHsKICBpZiAoIW1fcEVkaXQtPklzRm9jdXNlZCgpKSB7CiAgICBtX3BFZGl0LT5TZXRGb2N1cygpOwogICAgbV9wRWRpdC0+U2V0Q2FyZXQoYkxhc3QgPyBtX3BFZGl0LT5HZXRUb3RhbFdvcmRzKCkgOiAwKTsKICB9Cn0KCkNQV0xfRWRpdCogQ1BXTF9Ob3RlX0NvbnRlbnRzOjpHZXRFZGl0KCkgY29uc3QgewogIHJldHVybiBtX3BFZGl0Owp9Cgp2b2lkIENQV0xfTm90ZV9Db250ZW50czo6RW5hYmxlTW9kaWZ5KEZYX0JPT0wgYkVuYWJsZWQpIHsKICBpZiAoIWJFbmFibGVkKQogICAgbV9wRWRpdC0+QWRkRmxhZyhQV1NfUkVBRE9OTFkpOwogIGVsc2UKICAgIG1fcEVkaXQtPlJlbW92ZUZsYWcoUFdTX1JFQURPTkxZKTsKCiAgZm9yIChpbnQzMl90IGkgPSAwLCBzeiA9IG1fYUNoaWxkcmVuLkdldFNpemUoKTsgaSA8IHN6OyBpKyspIHsKICAgIGlmIChDUFdMX1duZCogcENoaWxkID0gbV9hQ2hpbGRyZW4uR2V0QXQoaSkpIHsKICAgICAgaWYgKHBDaGlsZC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZUl0ZW0iKSB7CiAgICAgICAgQ1BXTF9Ob3RlSXRlbSogcE5vdGVJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBDaGlsZDsKICAgICAgICBwTm90ZUl0ZW0tPkVuYWJsZU1vZGlmeShiRW5hYmxlZCk7CiAgICAgIH0KICAgIH0KICB9Cn0KCnZvaWQgQ1BXTF9Ob3RlX0NvbnRlbnRzOjpFbmFibGVSZWFkKEZYX0JPT0wgYkVuYWJsZWQpIHsKICBpZiAoIWJFbmFibGVkKQogICAgbV9wRWRpdC0+QWRkRmxhZyhQRVNfTk9SRUFEKTsKICBlbHNlCiAgICBtX3BFZGl0LT5SZW1vdmVGbGFnKFBFU19OT1JFQUQpOwoKICBmb3IgKGludDMyX3QgaSA9IDAsIHN6ID0gbV9hQ2hpbGRyZW4uR2V0U2l6ZSgpOyBpIDwgc3o7IGkrKykgewogICAgaWYgKENQV0xfV25kKiBwQ2hpbGQgPSBtX2FDaGlsZHJlbi5HZXRBdChpKSkgewogICAgICBpZiAocENoaWxkLT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9Ob3RlSXRlbSIpIHsKICAgICAgICBDUFdMX05vdGVJdGVtKiBwTm90ZUl0ZW0gPSAoQ1BXTF9Ob3RlSXRlbSopcENoaWxkOwogICAgICAgIHBOb3RlSXRlbS0+RW5hYmxlUmVhZChiRW5hYmxlZCk7CiAgICAgIH0KICAgIH0KICB9Cn0KCi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ1BXTF9Ob3RlSXRlbQogKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCgpDUFdMX05vdGVJdGVtOjpDUFdMX05vdGVJdGVtKCkKICAgIDogbV9wU3ViamVjdChOVUxMKSwKICAgICAgbV9wRGF0ZVRpbWUoTlVMTCksCiAgICAgIG1fcENvbnRlbnRzKE5VTEwpLAogICAgICBtX3BQcml2YXRlRGF0YShOVUxMKSwKICAgICAgbV9zQXV0aG9yKEwiIiksCiAgICAgIG1fZk9sZEl0ZW1IZWlnaHQoMC4wZiksCiAgICAgIG1fYlNpemVDaGFuZ2VkKEZBTFNFKSwKICAgICAgbV9iQWxsb3dNb2RpZnkoVFJVRSkge30KCkNQV0xfTm90ZUl0ZW06On5DUFdMX05vdGVJdGVtKCkge30KCkNGWF9CeXRlU3RyaW5nIENQV0xfTm90ZUl0ZW06OkdldENsYXNzTmFtZSgpIGNvbnN0IHsKICByZXR1cm4gIkNQV0xfTm90ZUl0ZW0iOwp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OkNyZWF0ZUNoaWxkV25kKGNvbnN0IFBXTF9DUkVBVEVQQVJBTSYgY3ApIHsKICBDUFdMX0NvbG9yIHNUZXh0Q29sb3I7CgogIGlmIChDUFdMX1V0aWxzOjpJc0JsYWNrT3JXaGl0ZShHZXRCYWNrZ3JvdW5kQ29sb3IoKSkpCiAgICBzVGV4dENvbG9yID0gUFdMX0RFRkFVTFRfV0hJVEVDT0xPUjsKICBlbHNlCiAgICBzVGV4dENvbG9yID0gUFdMX0RFRkFVTFRfQkxBQ0tDT0xPUjsKCiAgbV9wU3ViamVjdCA9IG5ldyBDUFdMX0xhYmVsOwogIFBXTF9DUkVBVEVQQVJBTSBzY3AgPSBjcDsKICBzY3AucFBhcmVudFduZCA9IHRoaXM7CiAgc2NwLmR3RmxhZ3MgPSBQV1NfVklTSUJMRSB8IFBXU19DSElMRCB8IFBFU19MRUZUIHwgUEVTX1RPUDsKICBzY3Auc1RleHRDb2xvciA9IHNUZXh0Q29sb3I7CiAgbV9wU3ViamVjdC0+Q3JlYXRlKHNjcCk7CgogIG1fcERhdGVUaW1lID0gbmV3IENQV0xfTGFiZWw7CiAgUFdMX0NSRUFURVBBUkFNIGRjcCA9IGNwOwogIGRjcC5wUGFyZW50V25kID0gdGhpczsKICBkY3AuZHdGbGFncyA9IFBXU19WSVNJQkxFIHwgUFdTX0NISUxEIHwgUEVTX1JJR0hUIHwgUEVTX1RPUDsKICBkY3Auc1RleHRDb2xvciA9IHNUZXh0Q29sb3I7CiAgbV9wRGF0ZVRpbWUtPkNyZWF0ZShkY3ApOwoKICBtX3BDb250ZW50cyA9IG5ldyBDUFdMX05vdGVfQ29udGVudHM7CiAgUFdMX0NSRUFURVBBUkFNIGNjcCA9IGNwOwogIGNjcC5wUGFyZW50V25kID0gdGhpczsKICAvLyBjY3Auc0JhY2tncm91bmRDb2xvciA9IFBXTF9ERUZBVUxUX1dISVRFQ09MT1I7CiAgY2NwLnNCYWNrZ3JvdW5kQ29sb3IgPQogICAgICBDUFdMX0NvbG9yKENPTE9SVFlQRV9SR0IsIDI0MCAvIDI1NS4wZiwgMjQwIC8gMjU1LjBmLCAyNDAgLyAyNTUuMGYpOwogIGNjcC5kd0ZsYWdzID0gUFdTX1ZJU0lCTEUgfCBQV1NfQ0hJTEQgfCBQV1NfQkFDS0dST1VORDsKICBtX3BDb250ZW50cy0+Q3JlYXRlKGNjcCk7CiAgbV9wQ29udGVudHMtPlNldEl0ZW1TcGFjZShQT1BVUF9JVEVNX1NQQUNFKTsKICBtX3BDb250ZW50cy0+U2V0VG9wU3BhY2UoUE9QVVBfSVRFTV9TUEFDRSk7CiAgbV9wQ29udGVudHMtPlNldEJvdHRvbVNwYWNlKFBPUFVQX0lURU1fU1BBQ0UpOwp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OlJlUG9zQ2hpbGRXbmQoKSB7CiAgaWYgKElzVmFsaWQoKSkgewogICAgQ1BERl9SZWN0IHJjQ2xpZW50ID0gR2V0Q2xpZW50UmVjdCgpOwoKICAgIENQREZfUmVjdCByY1N1YmplY3QgPSByY0NsaWVudDsKICAgIHJjU3ViamVjdC5sZWZ0ICs9IFBPUFVQX0lURU1fVEVYVF9JTkRFTlQ7CiAgICByY1N1YmplY3QudG9wID0gcmNDbGllbnQudG9wOwogICAgcmNTdWJqZWN0LnJpZ2h0ID0KICAgICAgICBQV0xfTUlOKHJjU3ViamVjdC5sZWZ0ICsgbV9wU3ViamVjdC0+R2V0Q29udGVudFJlY3QoKS5XaWR0aCgpICsgMS4wZiwKICAgICAgICAgICAgICAgIHJjQ2xpZW50LnJpZ2h0KTsKICAgIHJjU3ViamVjdC5ib3R0b20gPSByY1N1YmplY3QudG9wIC0gbV9wU3ViamVjdC0+R2V0Q29udGVudFJlY3QoKS5IZWlnaHQoKTsKICAgIHJjU3ViamVjdC5Ob3JtYWxpemUoKTsKICAgIG1fcFN1YmplY3QtPk1vdmUocmNTdWJqZWN0LCBUUlVFLCBGQUxTRSk7CiAgICBtX3BTdWJqZWN0LT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNTdWJqZWN0KSk7CgogICAgQ1BERl9SZWN0IHJjRGF0ZSA9IHJjQ2xpZW50OwogICAgcmNEYXRlLnJpZ2h0IC09IFBPUFVQX0lURU1fVEVYVF9JTkRFTlQ7CiAgICByY0RhdGUubGVmdCA9CiAgICAgICAgUFdMX01BWChyY0RhdGUucmlnaHQgLSBtX3BEYXRlVGltZS0+R2V0Q29udGVudFJlY3QoKS5XaWR0aCgpIC0gMS4wZiwKICAgICAgICAgICAgICAgIHJjU3ViamVjdC5yaWdodCk7CiAgICByY0RhdGUuYm90dG9tID0gcmNEYXRlLnRvcCAtIG1fcERhdGVUaW1lLT5HZXRDb250ZW50UmVjdCgpLkhlaWdodCgpOwogICAgcmNEYXRlLk5vcm1hbGl6ZSgpOwogICAgbV9wRGF0ZVRpbWUtPk1vdmUocmNEYXRlLCBUUlVFLCBGQUxTRSk7CiAgICBtX3BEYXRlVGltZS0+U2V0VmlzaWJsZShDUFdMX1V0aWxzOjpDb250YWluc1JlY3QocmNDbGllbnQsIHJjRGF0ZSkpOwoKICAgIENQREZfUmVjdCByY0NvbnRlbnRzID0gcmNDbGllbnQ7CiAgICByY0NvbnRlbnRzLmxlZnQgKz0gMS4wZjsKICAgIHJjQ29udGVudHMucmlnaHQgLT0gMS4wZjsKICAgIHJjQ29udGVudHMudG9wID0gcmNEYXRlLmJvdHRvbSAtIFBPUFVQX0lURU1fSEVBRF9CT1RUT007CiAgICByY0NvbnRlbnRzLmJvdHRvbSArPSBQT1BVUF9JVEVNX0JPVFRPTVdJRFRIOwogICAgcmNDb250ZW50cy5Ob3JtYWxpemUoKTsKICAgIG1fcENvbnRlbnRzLT5Nb3ZlKHJjQ29udGVudHMsIFRSVUUsIEZBTFNFKTsKICAgIG1fcENvbnRlbnRzLT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNDb250ZW50cykpOwogIH0KCiAgU2V0Q2xpcFJlY3QoQ1BXTF9VdGlsczo6SW5mbGF0ZVJlY3QoR2V0V2luZG93UmVjdCgpLCAxLjBmKSk7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6U2V0UHJpdmF0ZURhdGEodm9pZCogcERhdGEpIHsKICBtX3BQcml2YXRlRGF0YSA9IHBEYXRhOwp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OlNldEJrQ29sb3IoY29uc3QgQ1BXTF9Db2xvciYgY29sb3IpIHsKICBDUFdMX0NvbG9yIHNCSyA9IGNvbG9yOwogIFNldEJhY2tncm91bmRDb2xvcihzQkspOwoKICBDUFdMX0NvbG9yIHNUZXh0Q29sb3I7CgogIGlmIChDUFdMX1V0aWxzOjpJc0JsYWNrT3JXaGl0ZShzQkspKQogICAgc1RleHRDb2xvciA9IFBXTF9ERUZBVUxUX1dISVRFQ09MT1I7CiAgZWxzZQogICAgc1RleHRDb2xvciA9IFBXTF9ERUZBVUxUX0JMQUNLQ09MT1I7CgogIFNldFRleHRDb2xvcihzVGV4dENvbG9yKTsKICBpZiAobV9wU3ViamVjdCkKICAgIG1fcFN1YmplY3QtPlNldFRleHRDb2xvcihzVGV4dENvbG9yKTsKICBpZiAobV9wRGF0ZVRpbWUpCiAgICBtX3BEYXRlVGltZS0+U2V0VGV4dENvbG9yKHNUZXh0Q29sb3IpOwoKICBJbnZhbGlkYXRlUmVjdChudWxscHRyKTsKCiAgaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkgewogICAgcE5vdGlmeS0+T25TZXRCa0NvbG9yKHRoaXMpOwogIH0KfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpTZXRTdWJqZWN0TmFtZShjb25zdCBDRlhfV2lkZVN0cmluZyYgc05hbWUpIHsKICBpZiAobV9wU3ViamVjdCkgewogICAgbV9wU3ViamVjdC0+U2V0VGV4dChzTmFtZS5jX3N0cigpKTsKICB9CgogIGlmIChJUFdMX05vdGVOb3RpZnkqIHBOb3RpZnkgPSBHZXROb3RlTm90aWZ5KCkpIHsKICAgIHBOb3RpZnktPk9uU2V0U3ViamVjdE5hbWUodGhpcyk7CiAgfQp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OlNldEF1dGhvck5hbWUoY29uc3QgQ0ZYX1dpZGVTdHJpbmcmIHNOYW1lKSB7CiAgbV9zQXV0aG9yID0gc05hbWU7CiAgUmVzZXRTdWJqZWN0TmFtZSgtMSk7CgogIGlmIChJUFdMX05vdGVOb3RpZnkqIHBOb3RpZnkgPSBHZXROb3RlTm90aWZ5KCkpIHsKICAgIHBOb3RpZnktPk9uU2V0QXV0aG9yTmFtZSh0aGlzKTsKICB9Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6UmVzZXRTdWJqZWN0TmFtZShpbnQzMl90IG5JdGVtSW5kZXgpIHsKICBpZiAobkl0ZW1JbmRleCA8IDApIHsKICAgIGlmIChDUFdMX1duZCogcFBhcmVudCA9IEdldFBhcmVudFdpbmRvdygpKSB7CiAgICAgIEFTU0VSVChwUGFyZW50LT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9Ob3RlX0NvbnRlbnRzIik7CgogICAgICBDUFdMX05vdGVfQ29udGVudHMqIHBDb250ZW50cyA9IChDUFdMX05vdGVfQ29udGVudHMqKXBQYXJlbnQ7CiAgICAgIG5JdGVtSW5kZXggPSBwQ29udGVudHMtPkdldEl0ZW1JbmRleCh0aGlzKTsKICAgIH0KICB9CgogIGNvbnN0IENQV0xfTm90ZSogcE5vdGUgPSBHZXROb3RlKCk7CiAgQ0ZYX1dpZGVTdHJpbmcgc1N1YmplY3Q7CiAgc1N1YmplY3QuRm9ybWF0KHBOb3RlLT5HZXRSZXBseVN0cmluZygpLmNfc3RyKCksIG5JdGVtSW5kZXgpOwoKICBpZiAoIW1fc0F1dGhvci5Jc0VtcHR5KCkpIHsKICAgIHNTdWJqZWN0ICs9IEwiIC0gIjsKICAgIHNTdWJqZWN0ICs9IG1fc0F1dGhvcjsKICB9CiAgU2V0U3ViamVjdE5hbWUoc1N1YmplY3QpOwogIFJlUG9zQ2hpbGRXbmQoKTsKfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpTZXREYXRlVGltZShGWF9TWVNURU1USU1FIHRpbWUpIHsKICBtX2R0Tm90ZSA9IHRpbWU7CgogIENGWF9XaWRlU3RyaW5nIHN3VGltZTsKICBzd1RpbWUuRm9ybWF0KEwiJTA0ZC0lMDJkLSUwMmQgJTAyZDolMDJkOiUwMmQiLCB0aW1lLndZZWFyLCB0aW1lLndNb250aCwKICAgICAgICAgICAgICAgIHRpbWUud0RheSwgdGltZS53SG91ciwgdGltZS53TWludXRlLCB0aW1lLndTZWNvbmQpOwogIGlmIChtX3BEYXRlVGltZSkgewogICAgbV9wRGF0ZVRpbWUtPlNldFRleHQoc3dUaW1lLmNfc3RyKCkpOwogIH0KCiAgUmVQb3NDaGlsZFduZCgpOwoKICBpZiAoSVBXTF9Ob3RlTm90aWZ5KiBwTm90aWZ5ID0gR2V0Tm90ZU5vdGlmeSgpKSB7CiAgICBwTm90aWZ5LT5PblNldERhdGVUaW1lKHRoaXMpOwogIH0KfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpTZXRDb250ZW50cyhjb25zdCBDRlhfV2lkZVN0cmluZyYgc0NvbnRlbnRzKSB7CiAgaWYgKG1fcENvbnRlbnRzKSB7CiAgICBtX3BDb250ZW50cy0+U2V0VGV4dChzQ29udGVudHMpOwogIH0KCiAgaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkgewogICAgcE5vdGlmeS0+T25TZXRDb250ZW50cyh0aGlzKTsKICB9Cn0KCkNQV0xfTm90ZUl0ZW0qIENQV0xfTm90ZUl0ZW06OkdldFBhcmVudE5vdGVJdGVtKCkgY29uc3QgewogIGlmIChDUFdMX1duZCogcFBhcmVudCA9IEdldFBhcmVudFdpbmRvdygpKSB7CiAgICBpZiAoQ1BXTF9XbmQqIHBHcmFuZCA9IHBQYXJlbnQtPkdldFBhcmVudFdpbmRvdygpKSB7CiAgICAgIEFTU0VSVChwR3JhbmQtPkdldENsYXNzTmFtZSgpID09ICJDUFdMX05vdGVJdGVtIik7CiAgICAgIHJldHVybiAoQ1BXTF9Ob3RlSXRlbSopcEdyYW5kOwogICAgfQogIH0KCiAgcmV0dXJuIE5VTEw7Cn0KCklQV0xfTm90ZUl0ZW0qIENQV0xfTm90ZUl0ZW06OkdldFBhcmVudEl0ZW0oKSBjb25zdCB7CiAgcmV0dXJuIEdldFBhcmVudE5vdGVJdGVtKCk7Cn0KCkNQV0xfRWRpdCogQ1BXTF9Ob3RlSXRlbTo6R2V0RWRpdCgpIGNvbnN0IHsKICBpZiAobV9wQ29udGVudHMpCiAgICByZXR1cm4gbV9wQ29udGVudHMtPkdldEVkaXQoKTsKICByZXR1cm4gTlVMTDsKfQoKdm9pZCogQ1BXTF9Ob3RlSXRlbTo6R2V0UHJpdmF0ZURhdGEoKSBjb25zdCB7CiAgcmV0dXJuIG1fcFByaXZhdGVEYXRhOwp9CgpDRlhfV2lkZVN0cmluZyBDUFdMX05vdGVJdGVtOjpHZXRBdXRob3JOYW1lKCkgY29uc3QgewogIHJldHVybiBtX3NBdXRob3I7Cn0KCkNQV0xfQ29sb3IgQ1BXTF9Ob3RlSXRlbTo6R2V0QmtDb2xvcigpIGNvbnN0IHsKICByZXR1cm4gR2V0QmFja2dyb3VuZENvbG9yKCk7Cn0KCkNGWF9XaWRlU3RyaW5nIENQV0xfTm90ZUl0ZW06OkdldENvbnRlbnRzKCkgY29uc3QgewogIGlmIChtX3BDb250ZW50cykKICAgIHJldHVybiBtX3BDb250ZW50cy0+R2V0VGV4dCgpOwoKICByZXR1cm4gTCIiOwp9CgpGWF9TWVNURU1USU1FIENQV0xfTm90ZUl0ZW06OkdldERhdGVUaW1lKCkgY29uc3QgewogIHJldHVybiBtX2R0Tm90ZTsKfQoKQ0ZYX1dpZGVTdHJpbmcgQ1BXTF9Ob3RlSXRlbTo6R2V0U3ViamVjdE5hbWUoKSBjb25zdCB7CiAgaWYgKG1fcFN1YmplY3QpCiAgICByZXR1cm4gbV9wU3ViamVjdC0+R2V0VGV4dCgpOwoKICByZXR1cm4gTCIiOwp9CgpDUFdMX05vdGVJdGVtKiBDUFdMX05vdGVJdGVtOjpDcmVhdGVOb3RlSXRlbSgpIHsKICBpZiAobV9wQ29udGVudHMpCiAgICByZXR1cm4gbV9wQ29udGVudHMtPkNyZWF0ZVN1Ykl0ZW0oKTsKCiAgcmV0dXJuIE5VTEw7Cn0KCklQV0xfTm90ZUl0ZW0qIENQV0xfTm90ZUl0ZW06OkNyZWF0ZVN1Ykl0ZW0oKSB7CiAgcmV0dXJuIENyZWF0ZU5vdGVJdGVtKCk7Cn0KCmludDMyX3QgQ1BXTF9Ob3RlSXRlbTo6Q291bnRTdWJJdGVtcygpIGNvbnN0IHsKICBpZiAobV9wQ29udGVudHMpCiAgICByZXR1cm4gbV9wQ29udGVudHMtPkNvdW50U3ViSXRlbXMoKTsKCiAgcmV0dXJuIDA7Cn0KCklQV0xfTm90ZUl0ZW0qIENQV0xfTm90ZUl0ZW06OkdldFN1Ykl0ZW1zKGludDMyX3QgaW5kZXgpIGNvbnN0IHsKICBpZiAobV9wQ29udGVudHMpCiAgICByZXR1cm4gbV9wQ29udGVudHMtPkdldFN1Ykl0ZW1zKGluZGV4KTsKCiAgcmV0dXJuIE5VTEw7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6RGVsZXRlU3ViSXRlbShJUFdMX05vdGVJdGVtKiBwTm90ZUl0ZW0pIHsKICBLaWxsRm9jdXMoKTsKCiAgaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkgewogICAgcE5vdGlmeS0+T25JdGVtRGVsZXRlKHBOb3RlSXRlbSk7CiAgfQoKICBpZiAobV9wQ29udGVudHMpCiAgICBtX3BDb250ZW50cy0+RGVsZXRlU3ViSXRlbShwTm90ZUl0ZW0pOwp9CgpJUFdMX05vdGVJdGVtKiBDUFdMX05vdGVJdGVtOjpHZXRIaXROb3RlSXRlbShjb25zdCBDUERGX1BvaW50JiBwb2ludCkgewogIENQREZfUG9pbnQgcHQgPSBQYXJlbnRUb0NoaWxkKHBvaW50KTsKCiAgaWYgKFduZEhpdFRlc3QocHQpKSB7CiAgICBpZiAobV9wQ29udGVudHMpIHsKICAgICAgaWYgKElQV0xfTm90ZUl0ZW0qIHBOb3RlSXRlbSA9IG1fcENvbnRlbnRzLT5HZXRIaXROb3RlSXRlbShwdCkpCiAgICAgICAgcmV0dXJuIHBOb3RlSXRlbTsKICAgIH0KCiAgICByZXR1cm4gdGhpczsKICB9CgogIHJldHVybiBOVUxMOwp9CgpJUFdMX05vdGVJdGVtKiBDUFdMX05vdGVJdGVtOjpHZXRGb2N1c2VkTm90ZUl0ZW0oKSBjb25zdCB7CiAgaWYgKGNvbnN0IENQV0xfV25kKiBwV25kID0gR2V0Rm9jdXNlZCgpKSB7CiAgICBpZiAocFduZC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfRWRpdCIpIHsKICAgICAgaWYgKENQV0xfV25kKiBwUGFyZW50ID0gcFduZC0+R2V0UGFyZW50V2luZG93KCkpIHsKICAgICAgICBBU1NFUlQocFBhcmVudC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZV9Db250ZW50cyIpOwoKICAgICAgICBpZiAoQ1BXTF9XbmQqIHBHcmFuZCA9IHBQYXJlbnQtPkdldFBhcmVudFdpbmRvdygpKSB7CiAgICAgICAgICBBU1NFUlQocEdyYW5kLT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9Ob3RlSXRlbSIpOwogICAgICAgICAgcmV0dXJuIChDUFdMX05vdGVJdGVtKilwR3JhbmQ7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQoKICByZXR1cm4gTlVMTDsKfQoKRlhfRkxPQVQgQ1BXTF9Ob3RlSXRlbTo6R2V0SXRlbUhlaWdodChGWF9GTE9BVCBmTGltaXRXaWR0aCkgewogIGlmIChmTGltaXRXaWR0aCA+IDApIHsKICAgIGlmICghbV9iU2l6ZUNoYW5nZWQpCiAgICAgIHJldHVybiBtX2ZPbGRJdGVtSGVpZ2h0OwoKICAgIG1fYlNpemVDaGFuZ2VkID0gRkFMU0U7CgogICAgRlhfRkxPQVQgZlJldCA9IG1fcERhdGVUaW1lLT5HZXRDb250ZW50UmVjdCgpLkhlaWdodCgpOwogICAgRlhfRkxPQVQgZkJvcmRlcldpZHRoID0gKEZYX0ZMT0FUKUdldEJvcmRlcldpZHRoKCk7CiAgICBpZiAoZkxpbWl0V2lkdGggPiBmQm9yZGVyV2lkdGggKiAyKQogICAgICBmUmV0ICs9IG1fcENvbnRlbnRzLT5HZXRDb250ZW50c0hlaWdodChmTGltaXRXaWR0aCAtIGZCb3JkZXJXaWR0aCAqIDIpOwogICAgZlJldCArPSBQT1BVUF9JVEVNX0hFQURfQk9UVE9NICsgUE9QVVBfSVRFTV9CT1RUT01XSURUSCArIGZCb3JkZXJXaWR0aCAqIDI7CgogICAgcmV0dXJuIG1fZk9sZEl0ZW1IZWlnaHQgPSBmUmV0OwogIH0KCiAgcmV0dXJuIDA7Cn0KCkZYX0ZMT0FUIENQV0xfTm90ZUl0ZW06OkdldEl0ZW1MZWZ0TWFyZ2luKCkgewogIHJldHVybiBQT1BVUF9JVEVNX1NJREVNQVJHSU47Cn0KCkZYX0ZMT0FUIENQV0xfTm90ZUl0ZW06OkdldEl0ZW1SaWdodE1hcmdpbigpIHsKICByZXR1cm4gUE9QVVBfSVRFTV9TSURFTUFSR0lOOwp9CgpGWF9CT09MIENQV0xfTm90ZUl0ZW06Ok9uTEJ1dHRvbkRvd24oY29uc3QgQ1BERl9Qb2ludCYgcG9pbnQsIEZYX0RXT1JEIG5GbGFnKSB7CiAgaWYgKCFtX3BDb250ZW50cy0+V25kSGl0VGVzdChtX3BDb250ZW50cy0+UGFyZW50VG9DaGlsZChwb2ludCkpKSB7CiAgICBTZXROb3RlRm9jdXMoRkFMU0UpOwogIH0KCiAgQ1BXTF9XbmQ6Ok9uTEJ1dHRvbkRvd24ocG9pbnQsIG5GbGFnKTsKCiAgcmV0dXJuIFRSVUU7Cn0KCkZYX0JPT0wgQ1BXTF9Ob3RlSXRlbTo6T25SQnV0dG9uVXAoY29uc3QgQ1BERl9Qb2ludCYgcG9pbnQsIEZYX0RXT1JEIG5GbGFnKSB7CiAgaWYgKCFtX3BDb250ZW50cy0+V25kSGl0VGVzdChtX3BDb250ZW50cy0+UGFyZW50VG9DaGlsZChwb2ludCkpKSB7CiAgICBTZXROb3RlRm9jdXMoRkFMU0UpOwogICAgUG9wdXBOb3RlSXRlbU1lbnUocG9pbnQpOwoKICAgIHJldHVybiBUUlVFOwogIH0KCiAgcmV0dXJuIENQV0xfV25kOjpPblJCdXR0b25VcChwb2ludCwgbkZsYWcpOwp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06Ok9uTm90aWZ5KENQV0xfV25kKiBwV25kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZYX0RXT1JEIG1zZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRwdHJfdCB3UGFyYW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50cHRyX3QgbFBhcmFtKSB7CiAgc3dpdGNoIChtc2cpIHsKICAgIGNhc2UgUE5NX05PVEVFRElUQ0hBTkdFRDoKICAgICAgbV9iU2l6ZUNoYW5nZWQgPSBUUlVFOwoKICAgICAgaWYgKENQV0xfV25kKiBwUGFyZW50ID0gR2V0UGFyZW50V2luZG93KCkpIHsKICAgICAgICBwUGFyZW50LT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URUVESVRDSEFOR0VELCAwLCAwKTsKICAgICAgfQogICAgICByZXR1cm47CiAgICBjYXNlIFBOTV9TRVRDQVJFVElORk86CiAgICAgIGlmIChQV0xfQ0FSRVRfSU5GTyogcEluZm8gPSAoUFdMX0NBUkVUX0lORk8qKXdQYXJhbSkgewogICAgICAgIFBXTF9DQVJFVF9JTkZPIG5ld0luZm8gPSAqcEluZm87CiAgICAgICAgbmV3SW5mby5iVmlzaWJsZSA9IFRSVUU7CiAgICAgICAgbmV3SW5mby5wdEhlYWQgPSBDaGlsZFRvUGFyZW50KHBJbmZvLT5wdEhlYWQpOwogICAgICAgIG5ld0luZm8ucHRGb290ID0gQ2hpbGRUb1BhcmVudChwSW5mby0+cHRGb290KTsKCiAgICAgICAgaWYgKENQV0xfV25kKiBwUGFyZW50ID0gR2V0UGFyZW50V2luZG93KCkpIHsKICAgICAgICAgIHBQYXJlbnQtPk9uTm90aWZ5KHRoaXMsIFBOTV9TRVRDQVJFVElORk8sIChpbnRwdHJfdCkmbmV3SW5mbywgMCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIGNhc2UgUE5NX05PVEVSRVNFVDoKICAgICAgbV9iU2l6ZUNoYW5nZWQgPSBUUlVFOwogICAgICBtX3BDb250ZW50cy0+T25Ob3RpZnkodGhpcywgUE5NX05PVEVSRVNFVCwgMCwgMCk7CgogICAgICByZXR1cm47CiAgfQoKICBDUFdMX1duZDo6T25Ob3RpZnkocFduZCwgbXNnLCB3UGFyYW0sIGxQYXJhbSk7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6UG9wdXBOb3RlSXRlbU1lbnUoY29uc3QgQ1BERl9Qb2ludCYgcG9pbnQpIHsKICBpZiAoSVBXTF9Ob3RlTm90aWZ5KiBwTm90aWZ5ID0gR2V0Tm90ZU5vdGlmeSgpKSB7CiAgICBpbnQzMl90IHgsIHk7CiAgICBQV0x0b1duZChwb2ludCwgeCwgeSk7CiAgICBpZiAoSUZYX1N5c3RlbUhhbmRsZXIqIHBTSCA9IEdldFN5c3RlbUhhbmRsZXIoKSkKICAgICAgcFNILT5DbGllbnRUb1NjcmVlbihHZXRBdHRhY2hlZEhXbmQoKSwgeCwgeSk7CiAgICBwTm90aWZ5LT5PblBvcHVwTWVudSh0aGlzLCB4LCB5KTsKICB9Cn0KCmNvbnN0IENQV0xfTm90ZSogQ1BXTF9Ob3RlSXRlbTo6R2V0Tm90ZSgpIGNvbnN0IHsKICBpZiAoY29uc3QgQ1BXTF9XbmQqIHBSb290ID0gR2V0Um9vdFduZCgpKSB7CiAgICBBU1NFUlQocFJvb3QtPkdldENsYXNzTmFtZSgpID09ICJDUFdMX05vdGVJdGVtIik7CiAgICBDUFdMX05vdGVJdGVtKiBwTm90ZUl0ZW0gPSAoQ1BXTF9Ob3RlSXRlbSopcFJvb3Q7CiAgICBpZiAocE5vdGVJdGVtLT5Jc1RvcEl0ZW0oKSkgewogICAgICByZXR1cm4gKENQV0xfTm90ZSopcE5vdGVJdGVtOwogICAgfQogIH0KCiAgcmV0dXJuIE5VTEw7Cn0KCklQV0xfTm90ZU5vdGlmeSogQ1BXTF9Ob3RlSXRlbTo6R2V0Tm90ZU5vdGlmeSgpIGNvbnN0IHsKICBpZiAoY29uc3QgQ1BXTF9Ob3RlKiBwTm90ZSA9IEdldE5vdGUoKSkKICAgIHJldHVybiBwTm90ZS0+R2V0Tm90ZU5vdGlmeSgpOwoKICByZXR1cm4gTlVMTDsKfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpPbkNyZWF0ZU5vdGVJdGVtKCkgewogIGlmIChJUFdMX05vdGVOb3RpZnkqIHBOb3RpZnkgPSBHZXROb3RlTm90aWZ5KCkpIHsKICAgIHBOb3RpZnktPk9uSXRlbUNyZWF0ZSh0aGlzKTsKICB9Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6T25Db250ZW50c1ZhbGlkYXRlKCkgewogIGlmIChJUFdMX05vdGVOb3RpZnkqIHBOb3RpZnkgPSBHZXROb3RlTm90aWZ5KCkpIHsKICAgIHBOb3RpZnktPk9uU2V0Q29udGVudHModGhpcyk7CiAgfQp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OlNldE5vdGVGb2N1cyhGWF9CT09MIGJMYXN0KSB7CiAgbV9wQ29udGVudHMtPlNldEVkaXRGb2N1cyhiTGFzdCk7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6RW5hYmxlTW9kaWZ5KEZYX0JPT0wgYkVuYWJsZWQpIHsKICBtX3BDb250ZW50cy0+RW5hYmxlTW9kaWZ5KGJFbmFibGVkKTsKICBtX2JBbGxvd01vZGlmeSA9IGJFbmFibGVkOwp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OkVuYWJsZVJlYWQoRlhfQk9PTCBiRW5hYmxlZCkgewogIG1fcENvbnRlbnRzLT5FbmFibGVSZWFkKGJFbmFibGVkKTsKfQoKLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDUFdMX05vdGUKICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKQ1BXTF9Ob3RlOjpDUFdMX05vdGUoSVBvcHVwX05vdGUqIHBQb3B1cE5vdGUsCiAgICAgICAgICAgICAgICAgICAgIElQV0xfTm90ZU5vdGlmeSogcE5vdGVOb3RpZnksCiAgICAgICAgICAgICAgICAgICAgIElQV0xfTm90ZUhhbmRsZXIqIHBOb3RlSGFuZGxlcikKICAgIDogbV9wQXV0aG9yKE5VTEwpLAogICAgICBtX3BJY29uKE5VTEwpLAogICAgICBtX3BDbG9zZUJveChOVUxMKSwKICAgICAgbV9wTEJCb3goTlVMTCksCiAgICAgIG1fcFJCQm94KE5VTEwpLAogICAgICBtX3BDb250ZW50c0JhcihOVUxMKSwKICAgICAgbV9wT3B0aW9ucyhOVUxMKSwKICAgICAgbV9wTm90ZU5vdGlmeShwTm90ZU5vdGlmeSksCiAgICAgIG1fYlJlc2l6aW5nKEZBTFNFKSwKICAgICAgbV9iRW5hYmxlTm90aWZ5KFRSVUUpIHt9CgpDUFdMX05vdGU6On5DUFdMX05vdGUoKSB7fQoKSVBXTF9Ob3RlSXRlbSogQ1BXTF9Ob3RlOjpSZXBseSgpIHsKICByZXR1cm4gQ3JlYXRlTm90ZUl0ZW0oKTsKfQoKdm9pZCBDUFdMX05vdGU6OkVuYWJsZU5vdGlmeShGWF9CT09MIGJFbmFibGVkKSB7CiAgbV9iRW5hYmxlTm90aWZ5ID0gYkVuYWJsZWQ7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpSZVBvc0NoaWxkV25kKCkgewogIFJlUG9zTm90ZUNoaWxkcmVuKCk7CiAgbV9wQ29udGVudHMtPk9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFUkVTRVQsIDAsIDApOwogIFJlc2V0U2Nyb2xsQmFyKCk7CiAgbV9wQ29udGVudHMtPk9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFUkVTRVQsIDAsIDApOwogIE9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFRURJVENIQU5HRUQsIDAsIDApOwogIGlmIChjb25zdCBDUFdMX1duZCogcFduZCA9IEdldEZvY3VzZWQoKSkgewogICAgaWYgKHBXbmQtPkdldENsYXNzTmFtZSgpID09ICJDUFdMX0VkaXQiKSB7CiAgICAgIENQV0xfRWRpdCogcEVkaXQgPSAoQ1BXTF9FZGl0KilwV25kOwogICAgICBwRWRpdC0+U2V0Q2FyZXQocEVkaXQtPkdldENhcmV0KCkpOwogICAgfQogIH0KfQoKRlhfQk9PTCBDUFdMX05vdGU6OlJlc2V0U2Nyb2xsQmFyKCkgewogIEZYX0JPT0wgYlNjcm9sbENoYW5nZWQgPSBGQUxTRTsKCiAgaWYgKFNjcm9sbEJhclNob3VsZFZpc2libGUoKSkgewogICAgaWYgKCFtX3BDb250ZW50c0Jhci0+SXNWaXNpYmxlKCkpIHsKICAgICAgbV9wQ29udGVudHNCYXItPlNldFZpc2libGUoVFJVRSk7CiAgICAgIGlmIChtX3BDb250ZW50c0Jhci0+SXNWaXNpYmxlKCkpIHsKICAgICAgICBtX3BDb250ZW50c0Jhci0+SW52YWxpZGF0ZVJlY3QoTlVMTCk7CiAgICAgICAgYlNjcm9sbENoYW5nZWQgPSBUUlVFOwogICAgICB9CiAgICB9CiAgfSBlbHNlIHsKICAgIGlmIChtX3BDb250ZW50c0Jhci0+SXNWaXNpYmxlKCkpIHsKICAgICAgbV9wQ29udGVudHNCYXItPlNldFZpc2libGUoRkFMU0UpOwogICAgICBtX3BDb250ZW50c0Jhci0+SW52YWxpZGF0ZVJlY3QoTlVMTCk7CgogICAgICBiU2Nyb2xsQ2hhbmdlZCA9IFRSVUU7CiAgICB9CiAgfQoKICBpZiAoYlNjcm9sbENoYW5nZWQpIHsKICAgIENQREZfUmVjdCByY05vdGUgPSBHZXRDbGllbnRSZWN0KCk7CiAgICBDUERGX1JlY3QgcmNDb250ZW50cyA9IG1fcENvbnRlbnRzLT5HZXRXaW5kb3dSZWN0KCk7CiAgICByY0NvbnRlbnRzLnJpZ2h0ID0gcmNOb3RlLnJpZ2h0IC0gMy4wZjsKICAgIGlmIChtX3BDb250ZW50c0Jhci0+SXNWaXNpYmxlKCkpCiAgICAgIHJjQ29udGVudHMucmlnaHQgLT0gUFdMX1NDUk9MTEJBUl9XSURUSDsKICAgIG1fcENvbnRlbnRzLT5Nb3ZlKHJjQ29udGVudHMsIFRSVUUsIFRSVUUpOwogICAgbV9wQ29udGVudHMtPlNldFNjcm9sbFBvcyhDUERGX1BvaW50KDAuMGYsIDAuMGYpKTsKICAgIG1fcENvbnRlbnRzLT5JbnZhbGlkYXRlUmVjdChOVUxMKTsKICB9CgogIHJldHVybiBiU2Nyb2xsQ2hhbmdlZDsKfQoKRlhfQk9PTCBDUFdMX05vdGU6OlNjcm9sbEJhclNob3VsZFZpc2libGUoKSB7CiAgQ1BERl9SZWN0IHJjQ29udGVudHNGYWN0ID0gbV9wQ29udGVudHMtPkdldFNjcm9sbEFyZWEoKTsKICBDUERGX1JlY3QgcmNDb250ZW50c0NsaWVudCA9IG1fcENvbnRlbnRzLT5HZXRDbGllbnRSZWN0KCk7CgogIHJldHVybiByY0NvbnRlbnRzRmFjdC5IZWlnaHQoKSA+IHJjQ29udGVudHNDbGllbnQuSGVpZ2h0KCk7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpTZXRPcHRpb25zVGV4dChjb25zdCBDRlhfV2lkZVN0cmluZyYgc1RleHQpIHsKICBpZiAobV9wT3B0aW9ucykKICAgIG1fcE9wdGlvbnMtPlNldFRleHQoc1RleHQpOwoKICBSZVBvc05vdGVDaGlsZHJlbigpOwp9Cgp2b2lkIENQV0xfTm90ZTo6UmVQb3NOb3RlQ2hpbGRyZW4oKSB7CiAgaWYgKG1fYlJlc2l6aW5nKQogICAgcmV0dXJuOwoKICBtX2JSZXNpemluZyA9IFRSVUU7CgogIGlmIChJc1ZhbGlkKCkpIHsKICAgIENQREZfUmVjdCByY0NsaWVudCA9IEdldENsaWVudFJlY3QoKTsKCiAgICBDUERGX1JlY3QgcmNJY29uID0gcmNDbGllbnQ7CiAgICByY0ljb24udG9wIC09IDIuMGY7CiAgICByY0ljb24ucmlnaHQgPSByY0ljb24ubGVmdCArIDE0LjBmOwogICAgcmNJY29uLmJvdHRvbSA9IHJjSWNvbi50b3AgLSAxNC4wZjsKICAgIHJjSWNvbi5Ob3JtYWxpemUoKTsKICAgIG1fcEljb24tPk1vdmUocmNJY29uLCBUUlVFLCBGQUxTRSk7CiAgICBtX3BJY29uLT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNJY29uKSk7CgogICAgQ1BERl9SZWN0IHJjQ2xvc2VCb3ggPSByY0NsaWVudDsKICAgIHJjQ2xvc2VCb3gucmlnaHQgLT0gMS4wZjsKICAgIHJjQ2xvc2VCb3gudG9wIC09IDEuMGY7CiAgICByY0Nsb3NlQm94LmxlZnQgPSByY0Nsb3NlQm94LnJpZ2h0IC0gMTQuMGY7CiAgICByY0Nsb3NlQm94LmJvdHRvbSA9IHJjQ2xvc2VCb3gudG9wIC0gMTQuMGY7CiAgICByY0Nsb3NlQm94Lk5vcm1hbGl6ZSgpOwogICAgbV9wQ2xvc2VCb3gtPk1vdmUocmNDbG9zZUJveCwgVFJVRSwgRkFMU0UpOwogICAgbV9wQ2xvc2VCb3gtPlNldFZpc2libGUoQ1BXTF9VdGlsczo6Q29udGFpbnNSZWN0KHJjQ2xpZW50LCByY0Nsb3NlQm94KSk7CgogICAgQ1BERl9SZWN0IHJjRGF0ZSA9IHJjQ2xpZW50OwogICAgcmNEYXRlLnJpZ2h0ID0gcmNDbG9zZUJveC5sZWZ0IC0gUE9QVVBfSVRFTV9URVhUX0lOREVOVDsKICAgIHJjRGF0ZS5sZWZ0ID0KICAgICAgICBQV0xfTUFYKHJjRGF0ZS5yaWdodCAtIG1fcERhdGVUaW1lLT5HZXRDb250ZW50UmVjdCgpLldpZHRoKCkgLSAxLjBmLAogICAgICAgICAgICAgICAgcmNJY29uLnJpZ2h0ICsgMS4wZik7CiAgICByY0RhdGUudG9wID0gcmNDbGllbnQudG9wIC0gMi4wZjsKICAgIHJjRGF0ZS5ib3R0b20gPSByY0RhdGUudG9wIC0gbV9wRGF0ZVRpbWUtPkdldENvbnRlbnRSZWN0KCkuSGVpZ2h0KCk7CiAgICByY0RhdGUuTm9ybWFsaXplKCk7CiAgICBtX3BEYXRlVGltZS0+TW92ZShyY0RhdGUsIFRSVUUsIEZBTFNFKTsKICAgIG1fcERhdGVUaW1lLT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNEYXRlKSk7CgogICAgQ1BERl9SZWN0IHJjU3ViamVjdCA9IHJjQ2xpZW50OwogICAgcmNTdWJqZWN0LnRvcCA9IHJjQ2xpZW50LnRvcCAtIDIuMGY7CiAgICByY1N1YmplY3QubGVmdCA9IHJjSWNvbi5yaWdodCArIFBPUFVQX0lURU1fVEVYVF9JTkRFTlQ7CiAgICByY1N1YmplY3QucmlnaHQgPQogICAgICAgIFBXTF9NSU4ocmNTdWJqZWN0LmxlZnQgKyBtX3BTdWJqZWN0LT5HZXRDb250ZW50UmVjdCgpLldpZHRoKCkgKyAxLjBmLAogICAgICAgICAgICAgICAgcmNEYXRlLmxlZnQgLSAxLjBmKTsKICAgIHJjU3ViamVjdC5ib3R0b20gPSByY1N1YmplY3QudG9wIC0gbV9wU3ViamVjdC0+R2V0Q29udGVudFJlY3QoKS5IZWlnaHQoKTsKICAgIHJjU3ViamVjdC5Ob3JtYWxpemUoKTsKICAgIG1fcFN1YmplY3QtPk1vdmUocmNTdWJqZWN0LCBUUlVFLCBGQUxTRSk7CiAgICBtX3BTdWJqZWN0LT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNTdWJqZWN0KSk7CgogICAgQ1BERl9SZWN0IHJjT3B0aW9ucyA9IHJjQ2xpZW50OwogICAgcmNPcHRpb25zLmxlZnQgPQogICAgICAgIFBXTF9NQVgocmNPcHRpb25zLnJpZ2h0IC0gbV9wT3B0aW9ucy0+R2V0Q29udGVudFJlY3QoKS5XaWR0aCgpLAogICAgICAgICAgICAgICAgcmNJY29uLnJpZ2h0ICsgMS4wZik7CiAgICByY09wdGlvbnMudG9wID0gcmNTdWJqZWN0LmJvdHRvbSAtIDQuMGY7CiAgICByY09wdGlvbnMuYm90dG9tID0gcmNPcHRpb25zLnRvcCAtIG1fcE9wdGlvbnMtPkdldENvbnRlbnRSZWN0KCkuSGVpZ2h0KCk7CiAgICByY09wdGlvbnMuTm9ybWFsaXplKCk7CiAgICBtX3BPcHRpb25zLT5Nb3ZlKHJjT3B0aW9ucywgVFJVRSwgRkFMU0UpOwogICAgbV9wT3B0aW9ucy0+U2V0VmlzaWJsZShDUFdMX1V0aWxzOjpDb250YWluc1JlY3QocmNDbGllbnQsIHJjT3B0aW9ucykpOwoKICAgIENQREZfUmVjdCByY0F1dGhvciA9IHJjQ2xpZW50OwogICAgcmNBdXRob3IudG9wID0gcmNTdWJqZWN0LmJvdHRvbSAtIDQuMGY7CiAgICByY0F1dGhvci5sZWZ0ID0gcmNTdWJqZWN0LmxlZnQ7CiAgICByY0F1dGhvci5yaWdodCA9CiAgICAgICAgUFdMX01JTihyY1N1YmplY3QubGVmdCArIG1fcEF1dGhvci0+R2V0Q29udGVudFJlY3QoKS5XaWR0aCgpICsgMS4wZiwKICAgICAgICAgICAgICAgIHJjT3B0aW9ucy5sZWZ0IC0gMS4wZik7CiAgICByY0F1dGhvci5ib3R0b20gPSByY0F1dGhvci50b3AgLSBtX3BBdXRob3ItPkdldENvbnRlbnRSZWN0KCkuSGVpZ2h0KCk7CiAgICByY0F1dGhvci5Ob3JtYWxpemUoKTsKICAgIG1fcEF1dGhvci0+TW92ZShyY0F1dGhvciwgVFJVRSwgRkFMU0UpOwogICAgbV9wQXV0aG9yLT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNBdXRob3IpKTsKCiAgICBDUERGX1JlY3QgcmNMQkJveCA9IHJjQ2xpZW50OwogICAgcmNMQkJveC50b3AgPSByY0xCQm94LmJvdHRvbSArIDcuMGY7CiAgICByY0xCQm94LnJpZ2h0ID0gcmNMQkJveC5sZWZ0ICsgNy4wZjsKICAgIHJjTEJCb3guTm9ybWFsaXplKCk7CiAgICBtX3BMQkJveC0+TW92ZShyY0xCQm94LCBUUlVFLCBGQUxTRSk7CiAgICBtX3BMQkJveC0+U2V0VmlzaWJsZShDUFdMX1V0aWxzOjpDb250YWluc1JlY3QocmNDbGllbnQsIHJjTEJCb3gpKTsKCiAgICBDUERGX1JlY3QgcmNSQkJveCA9IHJjQ2xpZW50OwogICAgcmNSQkJveC50b3AgPSByY1JCQm94LmJvdHRvbSArIDcuMGY7CiAgICByY1JCQm94LmxlZnQgPSByY1JCQm94LnJpZ2h0IC0gNy4wZjsKICAgIHJjUkJCb3guTm9ybWFsaXplKCk7CiAgICBtX3BSQkJveC0+TW92ZShyY1JCQm94LCBUUlVFLCBGQUxTRSk7CiAgICBtX3BSQkJveC0+U2V0VmlzaWJsZShDUFdMX1V0aWxzOjpDb250YWluc1JlY3QocmNDbGllbnQsIHJjUkJCb3gpKTsKCiAgICBDUERGX1JlY3QgcmNDb250ZW50cyA9IHJjQ2xpZW50OwogICAgcmNDb250ZW50cy50b3AgPSByY0F1dGhvci5ib3R0b20gLSBQT1BVUF9JVEVNX0hFQURfQk9UVE9NOwogICAgcmNDb250ZW50cy5sZWZ0ICs9IDMuMGY7CiAgICByY0NvbnRlbnRzLnJpZ2h0IC09IDMuMGY7CiAgICBpZiAobV9wQ29udGVudHNCYXItPklzVmlzaWJsZSgpKQogICAgICByY0NvbnRlbnRzLnJpZ2h0IC09IFBXTF9TQ1JPTExCQVJfV0lEVEg7CiAgICByY0NvbnRlbnRzLmJvdHRvbSArPSAxNC4wZjsKICAgIHJjQ29udGVudHMuTm9ybWFsaXplKCk7CiAgICBtX3BDb250ZW50cy0+TW92ZShyY0NvbnRlbnRzLCBGQUxTRSwgRkFMU0UpOwogICAgbV9wQ29udGVudHMtPlNldFZpc2libGUoQ1BXTF9VdGlsczo6Q29udGFpbnNSZWN0KHJjQ2xpZW50LCByY0NvbnRlbnRzKSk7CgogICAgQ1BERl9SZWN0IHJjQ29udGVudHNCYXIgPSByY0NvbnRlbnRzOwogICAgcmNDb250ZW50c0Jhci5yaWdodCA9IHJjQ2xpZW50LnJpZ2h0IC0gMy4wZjsKICAgIHJjQ29udGVudHNCYXIubGVmdCA9IHJjQ29udGVudHNCYXIucmlnaHQgLSBQV0xfU0NST0xMQkFSX1dJRFRIOwogICAgcmNDb250ZW50c0Jhci5Ob3JtYWxpemUoKTsKICAgIG1fcENvbnRlbnRzQmFyLT5Nb3ZlKHJjQ29udGVudHNCYXIsIFRSVUUsIEZBTFNFKTsKICB9CgogIG1fYlJlc2l6aW5nID0gRkFMU0U7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpDcmVhdGVDaGlsZFduZChjb25zdCBQV0xfQ1JFQVRFUEFSQU0mIGNwKSB7CiAgQ1BXTF9Ob3RlSXRlbTo6Q3JlYXRlQ2hpbGRXbmQoY3ApOwoKICBDUFdMX0NvbG9yIHNUZXh0Q29sb3I7CgogIGlmIChDUFdMX1V0aWxzOjpJc0JsYWNrT3JXaGl0ZShHZXRCYWNrZ3JvdW5kQ29sb3IoKSkpCiAgICBzVGV4dENvbG9yID0gUFdMX0RFRkFVTFRfV0hJVEVDT0xPUjsKICBlbHNlCiAgICBzVGV4dENvbG9yID0gUFdMX0RFRkFVTFRfQkxBQ0tDT0xPUjsKCiAgbV9wQXV0aG9yID0gbmV3IENQV0xfTGFiZWw7CiAgUFdMX0NSRUFURVBBUkFNIGFjcCA9IGNwOwogIGFjcC5wUGFyZW50V25kID0gdGhpczsKICBhY3AuZHdGbGFncyA9IFBXU19WSVNJQkxFIHwgUFdTX0NISUxEIHwgUEVTX0xFRlQgfCBQRVNfVE9QOwogIGFjcC5zVGV4dENvbG9yID0gc1RleHRDb2xvcjsKICBtX3BBdXRob3ItPkNyZWF0ZShhY3ApOwoKICBtX3BDbG9zZUJveCA9IG5ldyBDUFdMX05vdGVfQ2xvc2VCb3g7CiAgUFdMX0NSRUFURVBBUkFNIGNjcCA9IGNwOwogIGNjcC5wUGFyZW50V25kID0gdGhpczsKICBjY3AuZHdCb3JkZXJXaWR0aCA9IDI7CiAgY2NwLm5Cb3JkZXJTdHlsZSA9IFBCU19CRVZFTEVEOwogIGNjcC5kd0ZsYWdzID0gUFdTX1ZJU0lCTEUgfCBQV1NfQ0hJTEQgfCBQV1NfQk9SREVSOwogIGNjcC5zVGV4dENvbG9yID0gc1RleHRDb2xvcjsKICBtX3BDbG9zZUJveC0+Q3JlYXRlKGNjcCk7CgogIG1fcEljb24gPSBuZXcgQ1BXTF9Ob3RlX0ljb247CiAgUFdMX0NSRUFURVBBUkFNIGljcCA9IGNwOwogIGljcC5wUGFyZW50V25kID0gdGhpczsKICBpY3AuZHdGbGFncyA9IFBXU19WSVNJQkxFIHwgUFdTX0NISUxEOwogIG1fcEljb24tPkNyZWF0ZShpY3ApOwoKICBtX3BPcHRpb25zID0gbmV3IENQV0xfTm90ZV9PcHRpb25zOwogIFBXTF9DUkVBVEVQQVJBTSBvY3AgPSBjcDsKICBvY3AucFBhcmVudFduZCA9IHRoaXM7CiAgb2NwLmR3RmxhZ3MgPSBQV1NfQ0hJTEQgfCBQV1NfVklTSUJMRTsKICBvY3Auc1RleHRDb2xvciA9IHNUZXh0Q29sb3I7CiAgbV9wT3B0aW9ucy0+Q3JlYXRlKG9jcCk7CgogIG1fcExCQm94ID0gbmV3IENQV0xfTm90ZV9MQkJveDsKICBQV0xfQ1JFQVRFUEFSQU0gbGNwID0gY3A7CiAgbGNwLnBQYXJlbnRXbmQgPSB0aGlzOwogIGxjcC5kd0ZsYWdzID0gUFdTX1ZJU0lCTEUgfCBQV1NfQ0hJTEQ7CiAgbGNwLmVDdXJzb3JUeXBlID0gRlhDVF9ORVNXOwogIGxjcC5zVGV4dENvbG9yID0gc1RleHRDb2xvcjsKICBtX3BMQkJveC0+Q3JlYXRlKGxjcCk7CgogIG1fcFJCQm94ID0gbmV3IENQV0xfTm90ZV9SQkJveDsKICBQV0xfQ1JFQVRFUEFSQU0gcmNwID0gY3A7CiAgcmNwLnBQYXJlbnRXbmQgPSB0aGlzOwogIHJjcC5kd0ZsYWdzID0gUFdTX1ZJU0lCTEUgfCBQV1NfQ0hJTEQ7CiAgcmNwLmVDdXJzb3JUeXBlID0gRlhDVF9OV1NFOwogIHJjcC5zVGV4dENvbG9yID0gc1RleHRDb2xvcjsKICBtX3BSQkJveC0+Q3JlYXRlKHJjcCk7CgogIG1fcENvbnRlbnRzQmFyID0gbmV3IENQV0xfU2Nyb2xsQmFyKFNCVF9WU0NST0xMKTsKICBQV0xfQ1JFQVRFUEFSQU0gc2NwID0gY3A7CiAgc2NwLnBQYXJlbnRXbmQgPSB0aGlzOwogIHNjcC5zQmFja2dyb3VuZENvbG9yID0KICAgICAgQ1BXTF9Db2xvcihDT0xPUlRZUEVfUkdCLCAyNDAgLyAyNTUuMGYsIDI0MCAvIDI1NS4wZiwgMjQwIC8gMjU1LjBmKTsKICBzY3AuZHdGbGFncyA9IFBXU19DSElMRCB8IFBXU19WSVNJQkxFIHwgUFdTX0JBQ0tHUk9VTkQ7CiAgbV9wQ29udGVudHNCYXItPkNyZWF0ZShzY3ApOwogIG1fcENvbnRlbnRzQmFyLT5TZXROb3RpZnlGb3JldmVyKFRSVUUpOwp9Cgp2b2lkIENQV0xfTm90ZTo6U2V0U3ViamVjdE5hbWUoY29uc3QgQ0ZYX1dpZGVTdHJpbmcmIHNOYW1lKSB7CiAgQ1BXTF9Ob3RlSXRlbTo6U2V0U3ViamVjdE5hbWUoc05hbWUpOwogIFJlUG9zQ2hpbGRXbmQoKTsKfQoKdm9pZCBDUFdMX05vdGU6OlNldEF1dGhvck5hbWUoY29uc3QgQ0ZYX1dpZGVTdHJpbmcmIHNOYW1lKSB7CiAgaWYgKG1fcEF1dGhvcikgewogICAgbV9wQXV0aG9yLT5TZXRUZXh0KHNOYW1lLmNfc3RyKCkpOwogICAgUmVQb3NDaGlsZFduZCgpOwogIH0KCiAgaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkgewogICAgcE5vdGlmeS0+T25TZXRBdXRob3JOYW1lKHRoaXMpOwogIH0KfQoKQ0ZYX1dpZGVTdHJpbmcgQ1BXTF9Ob3RlOjpHZXRBdXRob3JOYW1lKCkgY29uc3QgewogIGlmIChtX3BBdXRob3IpCiAgICByZXR1cm4gbV9wQXV0aG9yLT5HZXRUZXh0KCk7CgogIHJldHVybiBMIiI7Cn0KCkZYX0JPT0wgQ1BXTF9Ob3RlOjpPbk1vdXNlV2hlZWwoc2hvcnQgekRlbHRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IENQREZfUG9pbnQmIHBvaW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZYX0RXT1JEIG5GbGFnKSB7CiAgQ1BERl9Qb2ludCBwdFNjcm9sbCA9IG1fcENvbnRlbnRzLT5HZXRTY3JvbGxQb3MoKTsKICBDUERGX1JlY3QgcmNTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsQXJlYSgpOwogIENQREZfUmVjdCByY0NvbnRlbnRzID0gbV9wQ29udGVudHMtPkdldENsaWVudFJlY3QoKTsKCiAgaWYgKHJjU2Nyb2xsLnRvcCAtIHJjU2Nyb2xsLmJvdHRvbSA+IHJjQ29udGVudHMuSGVpZ2h0KCkpIHsKICAgIENQREZfUG9pbnQgcHROZXcgPSBwdFNjcm9sbDsKCiAgICBpZiAoekRlbHRhID4gMCkKICAgICAgcHROZXcueSArPSAzMDsKICAgIGVsc2UKICAgICAgcHROZXcueSAtPSAzMDsKCiAgICBpZiAocHROZXcueSA+IHJjU2Nyb2xsLnRvcCkKICAgICAgcHROZXcueSA9IHJjU2Nyb2xsLnRvcDsKICAgIGlmIChwdE5ldy55IDwgcmNTY3JvbGwuYm90dG9tICsgcmNDb250ZW50cy5IZWlnaHQoKSkKICAgICAgcHROZXcueSA9IHJjU2Nyb2xsLmJvdHRvbSArIHJjQ29udGVudHMuSGVpZ2h0KCk7CiAgICBpZiAocHROZXcueSA8IHJjU2Nyb2xsLmJvdHRvbSkKICAgICAgcHROZXcueSA9IHJjU2Nyb2xsLmJvdHRvbTsKCiAgICBpZiAocHROZXcueSAhPSBwdFNjcm9sbC55KSB7CiAgICAgIG1fcENvbnRlbnRzLT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URVJFU0VULCAwLCAwKTsKICAgICAgbV9wQ29udGVudHMtPk9uTm90aWZ5KHRoaXMsIFBOTV9TQ1JPTExXSU5ET1csIFNCVF9WU0NST0xMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKGludHB0cl90KSZwdE5ldy55KTsKICAgICAgbV9wQ29udGVudHNCYXItPk9uTm90aWZ5KHRoaXMsIFBOTV9TRVRTQ1JPTExQT1MsIFNCVF9WU0NST0xMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGludHB0cl90KSZwdE5ldy55KTsKCiAgICAgIHJldHVybiBUUlVFOwogICAgfQogIH0KCiAgcmV0dXJuIEZBTFNFOwp9Cgp2b2lkIENQV0xfTm90ZTo6T25Ob3RpZnkoQ1BXTF9XbmQqIHBXbmQsCiAgICAgICAgICAgICAgICAgICAgICAgICBGWF9EV09SRCBtc2csCiAgICAgICAgICAgICAgICAgICAgICAgICBpbnRwdHJfdCB3UGFyYW0sCiAgICAgICAgICAgICAgICAgICAgICAgICBpbnRwdHJfdCBsUGFyYW0pIHsKICBzd2l0Y2ggKG1zZykgewogICAgY2FzZSBQTk1fTk9URUVESVRDSEFOR0VEOiB7CiAgICAgIENQREZfUmVjdCByY1Njcm9sbCA9IG1fcENvbnRlbnRzLT5HZXRTY3JvbGxBcmVhKCk7CgogICAgICBQV0xfU0NST0xMX0lORk8gc0luZm87CiAgICAgIHNJbmZvLmZDb250ZW50TWluID0gcmNTY3JvbGwuYm90dG9tOwogICAgICBzSW5mby5mQ29udGVudE1heCA9IHJjU2Nyb2xsLnRvcDsKICAgICAgc0luZm8uZlBsYXRlV2lkdGggPSBtX3BDb250ZW50cy0+R2V0Q2xpZW50UmVjdCgpLkhlaWdodCgpOwogICAgICBzSW5mby5mU21hbGxTdGVwID0gMTMuMGY7CiAgICAgIHNJbmZvLmZCaWdTdGVwID0gc0luZm8uZlBsYXRlV2lkdGg7CgogICAgICBpZiAoRlhTWVNfbWVtY21wKCZtX09sZFNjcm9sbEluZm8sICZzSW5mbywgc2l6ZW9mKFBXTF9TQ1JPTExfSU5GTykpICE9CiAgICAgICAgICAwKSB7CiAgICAgICAgRlhfQk9PTCBiU2Nyb2xsQ2hhbmdlZCA9IEZBTFNFOwoKICAgICAgICBpZiAobFBhcmFtIDwgMykgIC8vt8DWucvA0a27tyBtYW50aXM6MTU3NTkKICAgICAgICB7CiAgICAgICAgICBiU2Nyb2xsQ2hhbmdlZCA9IFJlc2V0U2Nyb2xsQmFyKCk7CiAgICAgICAgICBpZiAoYlNjcm9sbENoYW5nZWQpIHsKICAgICAgICAgICAgbFBhcmFtKys7CiAgICAgICAgICAgIG1fcENvbnRlbnRzLT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URVJFU0VULCAwLCAwKTsKICAgICAgICAgICAgT25Ob3RpZnkodGhpcywgUE5NX05PVEVFRElUQ0hBTkdFRCwgMCwgbFBhcmFtKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICghYlNjcm9sbENoYW5nZWQpIHsKICAgICAgICAgIGlmIChtX3BDb250ZW50c0Jhci0+SXNWaXNpYmxlKCkpIHsKICAgICAgICAgICAgbV9wQ29udGVudHNCYXItPk9uTm90aWZ5KHBXbmQsIFBOTV9TRVRTQ1JPTExJTkZPLCBTQlRfVlNDUk9MTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChpbnRwdHJfdCkmc0luZm8pOwogICAgICAgICAgICBtX09sZFNjcm9sbEluZm8gPSBzSW5mbzsKCiAgICAgICAgICAgIENQREZfUG9pbnQgcHRTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsUG9zKCk7CiAgICAgICAgICAgIENQREZfUG9pbnQgcHRPbGQgPSBwdFNjcm9sbDsKCiAgICAgICAgICAgIGlmIChwdFNjcm9sbC55ID4gc0luZm8uZkNvbnRlbnRNYXgpCiAgICAgICAgICAgICAgcHRTY3JvbGwueSA9IHNJbmZvLmZDb250ZW50TWF4OwogICAgICAgICAgICBpZiAocHRTY3JvbGwueSA8IHNJbmZvLmZDb250ZW50TWluICsgc0luZm8uZlBsYXRlV2lkdGgpCiAgICAgICAgICAgICAgcHRTY3JvbGwueSA9IHNJbmZvLmZDb250ZW50TWluICsgc0luZm8uZlBsYXRlV2lkdGg7CiAgICAgICAgICAgIGlmIChwdFNjcm9sbC55IDwgc0luZm8uZkNvbnRlbnRNaW4pCiAgICAgICAgICAgICAgcHRTY3JvbGwueSA9IHNJbmZvLmZDb250ZW50TWluOwoKICAgICAgICAgICAgaWYgKHB0T2xkLnkgIT0gcHRTY3JvbGwueSkgewogICAgICAgICAgICAgIG1fcENvbnRlbnRzQmFyLT5Pbk5vdGlmeSh0aGlzLCBQTk1fU0VUU0NST0xMUE9TLCBTQlRfVlNDUk9MTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGludHB0cl90KSZwdFNjcm9sbC55KTsKICAgICAgICAgICAgICBtX3BDb250ZW50c0Jhci0+SW52YWxpZGF0ZVJlY3QoTlVMTCk7CiAgICAgICAgICAgICAgbV9wQ29udGVudHMtPk9uTm90aWZ5KHRoaXMsIFBOTV9TQ1JPTExXSU5ET1csIFNCVF9WU0NST0xMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoaW50cHRyX3QpJnB0U2Nyb2xsLnkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgICBtX3BDb250ZW50cy0+SW52YWxpZGF0ZVJlY3QoTlVMTCk7CgogICAgICByZXR1cm47CiAgICBjYXNlIFBOTV9TQ1JPTExXSU5ET1c6CiAgICAgIGlmIChtX3BDb250ZW50cykKICAgICAgICBtX3BDb250ZW50cy0+T25Ob3RpZnkocFduZCwgbXNnLCB3UGFyYW0sIGxQYXJhbSk7CiAgICAgIHJldHVybjsKICAgIGNhc2UgUE5NX1NFVFNDUk9MTFBPUzoKICAgICAgaWYgKG1fcENvbnRlbnRzQmFyKQogICAgICAgIG1fcENvbnRlbnRzQmFyLT5Pbk5vdGlmeShwV25kLCBQTk1fU0VUU0NST0xMUE9TLCB3UGFyYW0sIGxQYXJhbSk7CiAgICAgIHJldHVybjsKICB9CgogIGlmIChtc2cgPT0gUE5NX1NFVENBUkVUSU5GTyAmJiBJc1ZhbGlkKCkpIHsKICAgIGlmIChQV0xfQ0FSRVRfSU5GTyogcEluZm8gPSAoUFdMX0NBUkVUX0lORk8qKXdQYXJhbSkgewogICAgICBpZiAobV9wQ29udGVudHMpIHsKICAgICAgICBDUERGX1JlY3QgcmNDbGllbnQgPSBtX3BDb250ZW50cy0+R2V0Q2xpZW50UmVjdCgpOwogICAgICAgIGlmIChwSW5mby0+cHRIZWFkLnkgPiByY0NsaWVudC50b3ApIHsKICAgICAgICAgIENQREZfUG9pbnQgcHQgPSBtX3BDb250ZW50cy0+T3V0VG9JbihwSW5mby0+cHRIZWFkKTsKICAgICAgICAgIG1fcENvbnRlbnRzLT5Pbk5vdGlmeSh0aGlzLCBQTk1fU0NST0xMV0lORE9XLCBTQlRfVlNDUk9MTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoaW50cHRyX3QpJnB0LnkpOwoKICAgICAgICAgIENQREZfUG9pbnQgcHRTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsUG9zKCk7CiAgICAgICAgICBtX3BDb250ZW50c0Jhci0+T25Ob3RpZnkodGhpcywgUE5NX1NFVFNDUk9MTFBPUywgU0JUX1ZTQ1JPTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGludHB0cl90KSZwdFNjcm9sbC55KTsKCiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAocEluZm8tPnB0Rm9vdC55IDwgcmNDbGllbnQuYm90dG9tKSB7CiAgICAgICAgICBDUERGX1BvaW50IHB0ID0gbV9wQ29udGVudHMtPk91dFRvSW4ocEluZm8tPnB0Rm9vdCk7CiAgICAgICAgICBwdC55ICs9IHJjQ2xpZW50LkhlaWdodCgpOwogICAgICAgICAgbV9wQ29udGVudHMtPk9uTm90aWZ5KHRoaXMsIFBOTV9TQ1JPTExXSU5ET1csIFNCVF9WU0NST0xMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChpbnRwdHJfdCkmcHQueSk7CgogICAgICAgICAgQ1BERl9Qb2ludCBwdFNjcm9sbCA9IG1fcENvbnRlbnRzLT5HZXRTY3JvbGxQb3MoKTsKICAgICAgICAgIG1fcENvbnRlbnRzQmFyLT5Pbk5vdGlmeSh0aGlzLCBQTk1fU0VUU0NST0xMUE9TLCBTQlRfVlNDUk9MTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoaW50cHRyX3QpJnB0U2Nyb2xsLnkpOwoKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CgogIENQV0xfTm90ZUl0ZW06Ok9uTm90aWZ5KHBXbmQsIG1zZywgd1BhcmFtLCBsUGFyYW0pOwp9Cgp2b2lkIENQV0xfTm90ZTo6U2V0QmtDb2xvcihjb25zdCBDUFdMX0NvbG9yJiBjb2xvcikgewogIENQV0xfTm90ZUl0ZW06OlNldEJrQ29sb3IoY29sb3IpOwoKICBDUFdMX0NvbG9yIHNCSyA9IGNvbG9yOwogIENQV0xfQ29sb3Igc1RleHRDb2xvcjsKICBpZiAoQ1BXTF9VdGlsczo6SXNCbGFja09yV2hpdGUoc0JLKSkKICAgIHNUZXh0Q29sb3IgPSBQV0xfREVGQVVMVF9XSElURUNPTE9SOwogIGVsc2UKICAgIHNUZXh0Q29sb3IgPSBQV0xfREVGQVVMVF9CTEFDS0NPTE9SOwoKICBpZiAobV9wQ2xvc2VCb3gpCiAgICBtX3BDbG9zZUJveC0+U2V0VGV4dENvbG9yKHNUZXh0Q29sb3IpOwogIGlmIChtX3BBdXRob3IpCiAgICBtX3BBdXRob3ItPlNldFRleHRDb2xvcihzVGV4dENvbG9yKTsKICBpZiAobV9wT3B0aW9ucykKICAgIG1fcE9wdGlvbnMtPlNldFRleHRDb2xvcihzVGV4dENvbG9yKTsKICBpZiAobV9wTEJCb3gpCiAgICBtX3BMQkJveC0+U2V0VGV4dENvbG9yKHNUZXh0Q29sb3IpOwogIGlmIChtX3BSQkJveCkKICAgIG1fcFJCQm94LT5TZXRUZXh0Q29sb3Ioc1RleHRDb2xvcik7Cn0KCkZYX0JPT0wgQ1BXTF9Ob3RlOjpPbkxCdXR0b25Eb3duKGNvbnN0IENQREZfUG9pbnQmIHBvaW50LCBGWF9EV09SRCBuRmxhZykgewogIGlmIChtX3BPcHRpb25zLT5XbmRIaXRUZXN0KG1fcE9wdGlvbnMtPlBhcmVudFRvQ2hpbGQocG9pbnQpKSkgewogICAgaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkgewogICAgICBpbnQzMl90IHgsIHk7CiAgICAgIFBXTHRvV25kKHBvaW50LCB4LCB5KTsKICAgICAgaWYgKElGWF9TeXN0ZW1IYW5kbGVyKiBwU0ggPSBHZXRTeXN0ZW1IYW5kbGVyKCkpCiAgICAgICAgcFNILT5DbGllbnRUb1NjcmVlbihHZXRBdHRhY2hlZEhXbmQoKSwgeCwgeSk7CiAgICAgIEtpbGxGb2N1cygpOwogICAgICBwTm90aWZ5LT5PblBvcHVwTWVudSh4LCB5KTsKCiAgICAgIHJldHVybiBUUlVFOwogICAgfQogIH0KCiAgcmV0dXJuIENQV0xfV25kOjpPbkxCdXR0b25Eb3duKHBvaW50LCBuRmxhZyk7Cn0KCkZYX0JPT0wgQ1BXTF9Ob3RlOjpPblJCdXR0b25VcChjb25zdCBDUERGX1BvaW50JiBwb2ludCwgRlhfRFdPUkQgbkZsYWcpIHsKICByZXR1cm4gQ1BXTF9XbmQ6Ok9uUkJ1dHRvblVwKHBvaW50LCBuRmxhZyk7Cn0KCmNvbnN0IENQV0xfTm90ZSogQ1BXTF9Ob3RlOjpHZXROb3RlKCkgY29uc3QgewogIHJldHVybiB0aGlzOwp9CgpJUFdMX05vdGVOb3RpZnkqIENQV0xfTm90ZTo6R2V0Tm90ZU5vdGlmeSgpIGNvbnN0IHsKICByZXR1cm4gbV9iRW5hYmxlTm90aWZ5ID8gbV9wTm90ZU5vdGlmeSA6IG51bGxwdHI7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpTZXRJY29uVHlwZShpbnQzMl90IG5UeXBlKSB7CiAgaWYgKG1fcEljb24pCiAgICBtX3BJY29uLT5TZXRJY29uVHlwZShuVHlwZSk7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpFbmFibGVNb2RpZnkoRlhfQk9PTCBiRW5hYmxlZCkgewogIG1fcENvbnRlbnRzLT5FbmFibGVNb2RpZnkoYkVuYWJsZWQpOwp9Cgp2b2lkIENQV0xfTm90ZTo6RW5hYmxlUmVhZChGWF9CT09MIGJFbmFibGVkKSB7CiAgbV9wQ29udGVudHMtPkVuYWJsZVJlYWQoYkVuYWJsZWQpOwp9CgpDRlhfV2lkZVN0cmluZyBDUFdMX05vdGU6OkdldFJlcGx5U3RyaW5nKCkgY29uc3QgewogIHJldHVybiBtX3NSZXBseVN0cmluZzsKfQoKdm9pZCBDUFdMX05vdGU6OlNldFJlcGx5U3RyaW5nKGNvbnN0IENGWF9XaWRlU3RyaW5nJiBzdHJpbmcpIHsKICBtX3NSZXBseVN0cmluZyA9IHN0cmluZzsKfQo=