Ly8gQ29weXJpZ2h0IDIwMTQgUERGaXVtIEF1dGhvcnMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCi8vIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGEgQlNELXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmUKLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZS4KCi8vIE9yaWdpbmFsIGNvZGUgY29weXJpZ2h0IDIwMTQgRm94aXQgU29mdHdhcmUgSW5jLiBodHRwOi8vd3d3LmZveGl0c29mdHdhcmUuY29tCgojaW5jbHVkZSAiLi4vLi4vaW5jbHVkZS9wZGZ3aW5kb3cvUERGV2luZG93LmgiCiNpbmNsdWRlICIuLi8uLi9pbmNsdWRlL3BkZndpbmRvdy9QV0xfV25kLmgiCiNpbmNsdWRlICIuLi8uLi9pbmNsdWRlL3BkZndpbmRvdy9QV0xfQnV0dG9uLmgiCiNpbmNsdWRlICIuLi8uLi9pbmNsdWRlL3BkZndpbmRvdy9QV0xfRWRpdEN0cmwuaCIKI2luY2x1ZGUgIi4uLy4uL2luY2x1ZGUvcGRmd2luZG93L1BXTF9FZGl0LmgiCiNpbmNsdWRlICIuLi8uLi9pbmNsdWRlL3BkZndpbmRvdy9QV0xfTGlzdEN0cmwuaCIKI2luY2x1ZGUgIi4uLy4uL2luY2x1ZGUvcGRmd2luZG93L1BXTF9TY3JvbGxCYXIuaCIKI2luY2x1ZGUgIi4uLy4uL2luY2x1ZGUvcGRmd2luZG93L1BXTF9Ob3RlLmgiCiNpbmNsdWRlICIuLi8uLi9pbmNsdWRlL3BkZndpbmRvdy9QV0xfTGFiZWwuaCIKI2luY2x1ZGUgIi4uLy4uL2luY2x1ZGUvcGRmd2luZG93L1BXTF9FZGl0LmgiCiNpbmNsdWRlICIuLi8uLi9pbmNsdWRlL3BkZndpbmRvdy9QV0xfU2Nyb2xsQmFyLmgiCiNpbmNsdWRlICIuLi8uLi9pbmNsdWRlL3BkZndpbmRvdy9QV0xfVXRpbHMuaCIKI2luY2x1ZGUgIi4uLy4uL2luY2x1ZGUvcGRmd2luZG93L1BXTF9DYXJldC5oIgoKI2RlZmluZSBQT1BVUF9JVEVNX0hFQURfQk9UVE9NCQkJCQkzLjBmCiNkZWZpbmUgUE9QVVBfSVRFTV9CT1RUT01XSURUSAkJCQkJMS4wZgojZGVmaW5lIFBPUFVQX0lURU1fU0lERU1BUkdJTgkJCQkJMy4wZgojZGVmaW5lIFBPUFVQX0lURU1fU1BBQ0UJCQkJCQk0LjBmCiNkZWZpbmUgUE9QVVBfSVRFTV9URVhUX0lOREVOVAkJCQkJMi4wZgojZGVmaW5lIFBPUFVQX0lURU1fQk9SREVSQ09MT1IJCQkJCUNQV0xfQ29sb3IoQ09MT1JUWVBFX1JHQiwgODAvMjU1LjBmLCA4MC8yNTUuMGYsIDgwLzI1NS4wZikKCiNkZWZpbmUgSXNGbG9hdFplcm8oZikJCQkJCQkoKGYpIDwgMC4wMDAxICYmIChmKSA+IC0wLjAwMDEpCiNkZWZpbmUgSXNGbG9hdEJpZ2dlcihmYSxmYikJCQkJKChmYSkgPiAoZmIpICYmICFJc0Zsb2F0WmVybygoZmEpIC0gKGZiKSkpCiNkZWZpbmUgSXNGbG9hdFNtYWxsZXIoZmEsZmIpCQkJCSgoZmEpIDwgKGZiKSAmJiAhSXNGbG9hdFplcm8oKGZhKSAtIChmYikpKQojZGVmaW5lIElzRmxvYXRFcXVhbChmYSxmYikJCQkJCUlzRmxvYXRaZXJvKChmYSktKGZiKSkKCgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIENQV0xfTm90ZV9PcHRpb25zIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCkNQV0xfTm90ZV9PcHRpb25zOjpDUFdMX05vdGVfT3B0aW9ucygpIDogbV9wVGV4dChOVUxMKQp7Cn0KCkNQV0xfTm90ZV9PcHRpb25zOjp+Q1BXTF9Ob3RlX09wdGlvbnMoKQp7Cn0KCnZvaWQgQ1BXTF9Ob3RlX09wdGlvbnM6OlNldFRleHRDb2xvcihjb25zdCBDUFdMX0NvbG9yICYgY29sb3IpCnsKCUNQV0xfV25kOjpTZXRUZXh0Q29sb3IoY29sb3IpOwoKCWlmIChtX3BUZXh0KQoJCW1fcFRleHQtPlNldFRleHRDb2xvcihjb2xvcik7Cn0KCnZvaWQgQ1BXTF9Ob3RlX09wdGlvbnM6OlJlUG9zQ2hpbGRXbmQoKQp7CglpZiAoSXNWYWxpZCgpKQoJewoJCUFTU0VSVChtX3BUZXh0ICE9IE5VTEwpOwoKCQlDUERGX1JlY3QgcmNDbGllbnQgPSBHZXRDbGllbnRSZWN0KCk7CgoJCWlmIChyY0NsaWVudC5XaWR0aCgpID4gMTUuMGYpCgkJewoJCQlyY0NsaWVudC5yaWdodCAtPSAxNS4wZjsKCQkJbV9wVGV4dC0+TW92ZShyY0NsaWVudCwgdHJ1ZSwgZmFsc2UpOwoJCQltX3BUZXh0LT5TZXRWaXNpYmxlKHRydWUpOwoJCX0KCQllbHNlCgkJewoJCQltX3BUZXh0LT5Nb3ZlKENQREZfUmVjdCgwLDAsMCwwKSwgdHJ1ZSwgZmFsc2UpOwoJCQltX3BUZXh0LT5TZXRWaXNpYmxlKGZhbHNlKTsKCQl9Cgl9Cn0KCnZvaWQgQ1BXTF9Ob3RlX09wdGlvbnM6OkNyZWF0ZUNoaWxkV25kKGNvbnN0IFBXTF9DUkVBVEVQQVJBTSAmIGNwKQp7CgltX3BUZXh0ID0gbmV3IENQV0xfTGFiZWw7CglQV0xfQ1JFQVRFUEFSQU0gdGNwID0gY3A7Cgl0Y3AucFBhcmVudFduZCA9IHRoaXM7Cgl0Y3AuZHdGbGFncyA9IFBXU19DSElMRCB8IFBXU19WSVNJQkxFOwoJbV9wVGV4dC0+Q3JlYXRlKHRjcCk7Cn0KCnZvaWQgQ1BXTF9Ob3RlX09wdGlvbnM6OlNldFRleHQoY29uc3QgQ0ZYX1dpZGVTdHJpbmcmIHNUZXh0KQp7CgltX3BUZXh0LT5TZXRUZXh0KHNUZXh0LmNfc3RyKCkpOwp9Cgp2b2lkIENQV0xfTm90ZV9PcHRpb25zOjpEcmF3VGhpc0FwcGVhcmFuY2UoQ0ZYX1JlbmRlckRldmljZSogcERldmljZSwgQ1BERl9NYXRyaXgqIHBVc2VyMkRldmljZSkKewoJQ1BXTF9XbmQ6OkRyYXdUaGlzQXBwZWFyYW5jZShwRGV2aWNlLCBwVXNlcjJEZXZpY2UpOwoKCUNQREZfUmVjdCByY0NsaWVudCA9IEdldENsaWVudFJlY3QoKTsKCXJjQ2xpZW50LmxlZnQgPSByY0NsaWVudC5yaWdodCAtIDE1LjBmOwoKCUNQREZfUG9pbnQgcHRDZW50ZXIgPSBDUERGX1BvaW50KChyY0NsaWVudC5sZWZ0ICsgcmNDbGllbnQucmlnaHQpICogMC41ZiwgKHJjQ2xpZW50LnRvcCArIHJjQ2xpZW50LmJvdHRvbSkgKiAwLjVmKTsKCglDUERGX1BvaW50IHB0MShwdENlbnRlci54IC0gMi4wZiwgcHRDZW50ZXIueSArIDIuMGYgKiAwLjVmKTsKCUNQREZfUG9pbnQgcHQyKHB0Q2VudGVyLnggKyAyLjBmLCBwdENlbnRlci55ICsgMi4wZiAqIDAuNWYpOwoJQ1BERl9Qb2ludCBwdDMocHRDZW50ZXIueCwgcHRDZW50ZXIueSAtIDMuMGYgKiAwLjVmKTsKCglDRlhfUGF0aERhdGEgcGF0aDsKCglwYXRoLlNldFBvaW50Q291bnQoNCk7CglwYXRoLlNldFBvaW50KDAsIHB0MS54LCBwdDEueSwgRlhQVF9NT1ZFVE8pOwoJcGF0aC5TZXRQb2ludCgxLCBwdDIueCwgcHQyLnksIEZYUFRfTElORVRPKTsKCXBhdGguU2V0UG9pbnQoMiwgcHQzLngsIHB0My55LCBGWFBUX0xJTkVUTyk7CglwYXRoLlNldFBvaW50KDMsIHB0MS54LCBwdDEueSwgRlhQVF9MSU5FVE8pOwoKCXBEZXZpY2UtPkRyYXdQYXRoKCZwYXRoLCBwVXNlcjJEZXZpY2UsIE5VTEwsCgkJQ1BXTF9VdGlsczo6UFdMQ29sb3JUb0ZYQ29sb3IoR2V0VGV4dENvbG9yKCksR2V0VHJhbnNwYXJlbmN5KCkpLAoJCTAsIEZYRklMTF9BTFRFUk5BVEUpOwp9CgpDUERGX1JlY3QgQ1BXTF9Ob3RlX09wdGlvbnM6OkdldENvbnRlbnRSZWN0KCkgY29uc3QKewoJQVNTRVJUKG1fcFRleHQgIT0gTlVMTCk7CgoJQ1BERl9SZWN0IHJjVGV4dCA9IG1fcFRleHQtPkdldENvbnRlbnRSZWN0KCk7CglyY1RleHQucmlnaHQgKz0gMTUuMGY7CglyZXR1cm4gcmNUZXh0Owp9CgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIENQV0xfTm90ZV9FZGl0IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKQ1BXTF9Ob3RlX0VkaXQ6OkNQV0xfTm90ZV9FZGl0KCkgOiBtX2JFbmFibGVOb3RpZnkodHJ1ZSksCgltX2ZPbGRJdGVtSGVpZ2h0KDAuMGYpLAoJbV9iU2l6ZUNoYW5nZWQoZmFsc2UpLAoJbV9mT2xkTWluKDAuMGYpLAoJbV9mT2xkTWF4KDAuMGYpCnsKfQoKQ1BXTF9Ob3RlX0VkaXQ6On5DUFdMX05vdGVfRWRpdCgpCnsKfQoKdm9pZCBDUFdMX05vdGVfRWRpdDo6UmVQb3NDaGlsZFduZCgpCnsKCW1fYkVuYWJsZU5vdGlmeSA9IGZhbHNlOwoJQ1BXTF9FZGl0OjpSZVBvc0NoaWxkV25kKCk7CgltX2JFbmFibGVOb3RpZnkgPSB0cnVlOwoKCW1fZk9sZEl0ZW1IZWlnaHQgPSBHZXRDb250ZW50UmVjdCgpLkhlaWdodCgpOwp9Cgp2b2lkIENQV0xfTm90ZV9FZGl0OjpTZXRUZXh0KGNvbnN0IEZYX1dDSEFSKiBjc1RleHQpCnsKCW1fYkVuYWJsZU5vdGlmeSA9IGZhbHNlOwoJQ1BXTF9FZGl0OjpTZXRUZXh0KGNzVGV4dCk7CgltX2JFbmFibGVOb3RpZnkgPSB0cnVlOwoJbV9mT2xkSXRlbUhlaWdodCA9IEdldENvbnRlbnRSZWN0KCkuSGVpZ2h0KCk7Cn0KCnZvaWQgQ1BXTF9Ob3RlX0VkaXQ6Ok9uU2V0Rm9jdXMoKQp7CgltX2JFbmFibGVOb3RpZnkgPSBmYWxzZTsKCUNQV0xfRWRpdDo6T25TZXRGb2N1cygpOwoJbV9iRW5hYmxlTm90aWZ5ID0gdHJ1ZTsKCglFbmFibGVTcGVsbENoZWNrKHRydWUpOwp9Cgp2b2lkIENQV0xfTm90ZV9FZGl0OjpPbktpbGxGb2N1cygpCnsKCUVuYWJsZVNwZWxsQ2hlY2soZmFsc2UpOwoKCWlmIChDUFdMX1duZCogcFBhcmVudCA9IEdldFBhcmVudFdpbmRvdygpKQoJewoJCWlmIChDUFdMX1duZCogcEdyYW5kID0gcFBhcmVudC0+R2V0UGFyZW50V2luZG93KCkpCgkJewoJCQlBU1NFUlQocEdyYW5kLT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9Ob3RlSXRlbSIpOwoKCQkJQ1BXTF9Ob3RlSXRlbSogcE5vdGVJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBHcmFuZDsKCgkJCXBOb3RlSXRlbS0+T25Db250ZW50c1ZhbGlkYXRlKCk7CgkJfQoJfQoKCUNQV0xfRWRpdDo6T25LaWxsRm9jdXMoKTsKfQoKdm9pZCBDUFdMX05vdGVfRWRpdDo6T25Ob3RpZnkoQ1BXTF9XbmQqIHBXbmQsIEZYX0RXT1JEIG1zZywgaW50cHRyX3Qgd1BhcmFtLCBpbnRwdHJfdCBsUGFyYW0pCnsKCWlmIChtX2JFbmFibGVOb3RpZnkpCgl7CgkJaWYgKHdQYXJhbSA9PSBTQlRfVlNDUk9MTCkKCQl7CgkJCXN3aXRjaCAobXNnKQoJCQl7CgkJCWNhc2UgUE5NX1NFVFNDUk9MTElORk86CgkJCQlpZiAoUFdMX1NDUk9MTF9JTkZPKiBwSW5mbyA9IChQV0xfU0NST0xMX0lORk8qKWxQYXJhbSkKCQkJCXsKCQkJCQlpZiAoIUlzRmxvYXRFcXVhbChwSW5mby0+ZkNvbnRlbnRNYXgsIG1fZk9sZE1heCkgfHwKCQkJCQkJIUlzRmxvYXRFcXVhbChwSW5mby0+ZkNvbnRlbnRNaW4sIG1fZk9sZE1pbikpCgkJCQkJewoJCQkJCQltX2JTaXplQ2hhbmdlZCA9IHRydWU7CgkJCQkJCWlmIChDUFdMX1duZCAqIHBQYXJlbnQgPSBHZXRQYXJlbnRXaW5kb3coKSkKCQkJCQkJewoJCQkJCQkJcFBhcmVudC0+T25Ob3RpZnkodGhpcywgUE5NX05PVEVFRElUQ0hBTkdFRCwgMCwgMCk7CgkJCQkJCX0KCgkJCQkJCW1fZk9sZE1heCA9IHBJbmZvLT5mQ29udGVudE1heDsKCQkJCQkJbV9mT2xkTWluID0gcEluZm8tPmZDb250ZW50TWluOwoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJfQoKCUNQV0xfRWRpdDo6T25Ob3RpZnkocFduZCwgbXNnLCB3UGFyYW0sIGxQYXJhbSk7CgoJaWYgKG1fYkVuYWJsZU5vdGlmeSkKCXsKCQlzd2l0Y2ggKG1zZykKCQl7CgkJY2FzZSBQTk1fU0VUQ0FSRVRJTkZPOgoJCQlpZiAoUFdMX0NBUkVUX0lORk8gKiBwSW5mbyA9IChQV0xfQ0FSRVRfSU5GTyopd1BhcmFtKQoJCQl7CgkJCQlQV0xfQ0FSRVRfSU5GTyBuZXdJbmZvID0gKnBJbmZvOwoJCQkJbmV3SW5mby5iVmlzaWJsZSA9IHRydWU7CgkJCQluZXdJbmZvLnB0SGVhZCA9IENoaWxkVG9QYXJlbnQocEluZm8tPnB0SGVhZCk7CgkJCQluZXdJbmZvLnB0Rm9vdCA9IENoaWxkVG9QYXJlbnQocEluZm8tPnB0Rm9vdCk7CgoJCQkJaWYgKENQV0xfV25kICogcFBhcmVudCA9IEdldFBhcmVudFdpbmRvdygpKQoJCQkJewoJCQkJCXBQYXJlbnQtPk9uTm90aWZ5KHRoaXMsIFBOTV9TRVRDQVJFVElORk8sIChpbnRwdHJfdCkmbmV3SW5mbywgMCk7CgkJCQl9CgkJCX0KCQkJYnJlYWs7CgkJfQoJfQp9CgpGWF9GTE9BVCBDUFdMX05vdGVfRWRpdDo6R2V0SXRlbUhlaWdodChGWF9GTE9BVCBmTGltaXRXaWR0aCkKewoJaWYgKGZMaW1pdFdpZHRoID4gMCkKCXsKCQlpZiAoIW1fYlNpemVDaGFuZ2VkKQoJCQlyZXR1cm4gbV9mT2xkSXRlbUhlaWdodDsKCgkJbV9iU2l6ZUNoYW5nZWQgPSBmYWxzZTsKCgkJRW5hYmxlTm90aWZ5KGZhbHNlKTsKCQlFbmFibGVSZWZyZXNoKGZhbHNlKTsKCQltX3BFZGl0LT5FbmFibGVOb3RpZnkoZmFsc2UpOwoKCQlNb3ZlKENQREZfUmVjdCgwLDAsZkxpbWl0V2lkdGgsMCksIHRydWUsIGZhbHNlKTsKCQlGWF9GTE9BVCBmUmV0ID0gR2V0Q29udGVudFJlY3QoKS5IZWlnaHQoKTsKCgkJbV9wRWRpdC0+RW5hYmxlTm90aWZ5KHRydWUpOwoJCUVuYWJsZU5vdGlmeSh0cnVlKTsKCQlFbmFibGVSZWZyZXNoKHRydWUpOwoKCQlyZXR1cm4gZlJldDsKCX0KCglyZXR1cm4gMDsKfQoKRlhfRkxPQVQgQ1BXTF9Ob3RlX0VkaXQ6OkdldEl0ZW1MZWZ0TWFyZ2luKCkKewoJcmV0dXJuIFBPUFVQX0lURU1fVEVYVF9JTkRFTlQ7Cn0KCkZYX0ZMT0FUIENQV0xfTm90ZV9FZGl0OjpHZXRJdGVtUmlnaHRNYXJnaW4oKQp7CglyZXR1cm4gUE9QVVBfSVRFTV9URVhUX0lOREVOVDsKfQoKLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ1BXTF9Ob3RlX0xCQm94IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KCkNQV0xfTm90ZV9MQkJveDo6Q1BXTF9Ob3RlX0xCQm94KCkKewp9CgpDUFdMX05vdGVfTEJCb3g6On5DUFdMX05vdGVfTEJCb3goKQp7Cn0KCnZvaWQgQ1BXTF9Ob3RlX0xCQm94OjpEcmF3VGhpc0FwcGVhcmFuY2UoQ0ZYX1JlbmRlckRldmljZSogcERldmljZSwgQ1BERl9NYXRyaXgqIHBVc2VyMkRldmljZSkKewoJQ1BERl9SZWN0IHJjQ2xpZW50ID0gR2V0Q2xpZW50UmVjdCgpOwoKCUNGWF9HcmFwaFN0YXRlRGF0YSBnc2Q7Cglnc2QubV9MaW5lV2lkdGggPSAxLjBmOwoKCUNGWF9QYXRoRGF0YSBwYXRoQ3Jvc3M7CgoJcGF0aENyb3NzLlNldFBvaW50Q291bnQoNCk7CglwYXRoQ3Jvc3MuU2V0UG9pbnQoMCwgcmNDbGllbnQubGVmdCwgcmNDbGllbnQudG9wLCBGWFBUX01PVkVUTyk7CglwYXRoQ3Jvc3MuU2V0UG9pbnQoMSwgcmNDbGllbnQucmlnaHQsIHJjQ2xpZW50LmJvdHRvbSwgRlhQVF9MSU5FVE8pOwoJcGF0aENyb3NzLlNldFBvaW50KDIsIHJjQ2xpZW50LmxlZnQsIHJjQ2xpZW50LmJvdHRvbSArIHJjQ2xpZW50LkhlaWdodCgpICogMC41ZiwgRlhQVF9NT1ZFVE8pOwoJcGF0aENyb3NzLlNldFBvaW50KDMsIHJjQ2xpZW50LmxlZnQgKyByY0NsaWVudC5XaWR0aCgpICogMC41ZiwgcmNDbGllbnQuYm90dG9tLCBGWFBUX0xJTkVUTyk7CgoJcERldmljZS0+RHJhd1BhdGgoJnBhdGhDcm9zcywgcFVzZXIyRGV2aWNlLCAmZ3NkLAoJCTAsIENQV0xfVXRpbHM6OlBXTENvbG9yVG9GWENvbG9yKEdldFRleHRDb2xvcigpLCBHZXRUcmFuc3BhcmVuY3koKSksIEZYRklMTF9BTFRFUk5BVEUpOwp9CgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDUFdMX05vdGVfUkJCb3ggLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwoKQ1BXTF9Ob3RlX1JCQm94OjpDUFdMX05vdGVfUkJCb3goKQp7Cn0KCkNQV0xfTm90ZV9SQkJveDo6fkNQV0xfTm90ZV9SQkJveCgpCnsKfQoKdm9pZCBDUFdMX05vdGVfUkJCb3g6OkRyYXdUaGlzQXBwZWFyYW5jZShDRlhfUmVuZGVyRGV2aWNlKiBwRGV2aWNlLCBDUERGX01hdHJpeCogcFVzZXIyRGV2aWNlKQp7CglDUERGX1JlY3QgcmNDbGllbnQgPSBHZXRDbGllbnRSZWN0KCk7CgoJQ0ZYX0dyYXBoU3RhdGVEYXRhIGdzZDsKCWdzZC5tX0xpbmVXaWR0aCA9IDEuMGY7CgoJQ0ZYX1BhdGhEYXRhIHBhdGhDcm9zczsKCglwYXRoQ3Jvc3MuU2V0UG9pbnRDb3VudCg0KTsKCXBhdGhDcm9zcy5TZXRQb2ludCgwLCByY0NsaWVudC5yaWdodCwgcmNDbGllbnQudG9wLCBGWFBUX01PVkVUTyk7CglwYXRoQ3Jvc3MuU2V0UG9pbnQoMSwgcmNDbGllbnQubGVmdCwgcmNDbGllbnQuYm90dG9tLCBGWFBUX0xJTkVUTyk7CglwYXRoQ3Jvc3MuU2V0UG9pbnQoMiwgcmNDbGllbnQucmlnaHQsIHJjQ2xpZW50LmJvdHRvbSArIHJjQ2xpZW50LkhlaWdodCgpICogMC41ZiwgRlhQVF9NT1ZFVE8pOwoJcGF0aENyb3NzLlNldFBvaW50KDMsIHJjQ2xpZW50LmxlZnQgKyByY0NsaWVudC5XaWR0aCgpICogMC41ZiwgcmNDbGllbnQuYm90dG9tLCBGWFBUX0xJTkVUTyk7CgoJcERldmljZS0+RHJhd1BhdGgoJnBhdGhDcm9zcywgcFVzZXIyRGV2aWNlLCAmZ3NkLAoJCTAsIENQV0xfVXRpbHM6OlBXTENvbG9yVG9GWENvbG9yKEdldFRleHRDb2xvcigpLCBHZXRUcmFuc3BhcmVuY3koKSksIEZYRklMTF9BTFRFUk5BVEUpOwp9CgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ1BXTF9Ob3RlX0ljb24gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKQ1BXTF9Ob3RlX0ljb246OkNQV0xfTm90ZV9JY29uKCkgOiBtX25UeXBlKDApCnsKfQoKQ1BXTF9Ob3RlX0ljb246On5DUFdMX05vdGVfSWNvbigpCnsKfQoKdm9pZCBDUFdMX05vdGVfSWNvbjo6U2V0SWNvblR5cGUoaW50MzJfdCBuVHlwZSkKewoJbV9uVHlwZSA9IG5UeXBlOwp9Cgp2b2lkIENQV0xfTm90ZV9JY29uOjpEcmF3VGhpc0FwcGVhcmFuY2UoQ0ZYX1JlbmRlckRldmljZSogcERldmljZSwgQ1BERl9NYXRyaXgqIHBVc2VyMkRldmljZSkKewoJQ1BXTF9VdGlsczo6RHJhd0ljb25BcHBTdHJlYW0ocERldmljZSwgcFVzZXIyRGV2aWNlLCBtX25UeXBlLCBHZXRDbGllbnRSZWN0KCksCgkJR2V0QmFja2dyb3VuZENvbG9yKCksIFBXTF9ERUZBVUxUX0JMQUNLQ09MT1IsIEdldFRyYW5zcGFyZW5jeSgpKTsKfQoKLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIENQV0xfTm90ZV9DbG9zZUJveCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCgpDUFdMX05vdGVfQ2xvc2VCb3g6OkNQV0xfTm90ZV9DbG9zZUJveCgpIDogbV9iTW91c2VEb3duKGZhbHNlKQp7Cn0KCkNQV0xfTm90ZV9DbG9zZUJveDo6fkNQV0xfTm90ZV9DbG9zZUJveCgpCnsKfQoKdm9pZCBDUFdMX05vdGVfQ2xvc2VCb3g6OkRyYXdUaGlzQXBwZWFyYW5jZShDRlhfUmVuZGVyRGV2aWNlKiBwRGV2aWNlLCBDUERGX01hdHJpeCogcFVzZXIyRGV2aWNlKQp7CglDUFdMX0J1dHRvbjo6RHJhd1RoaXNBcHBlYXJhbmNlKHBEZXZpY2UsIHBVc2VyMkRldmljZSk7CgoJQ1BERl9SZWN0IHJjQ2xpZW50ID0gR2V0Q2xpZW50UmVjdCgpOwoJcmNDbGllbnQgPSBDUFdMX1V0aWxzOjpEZWZsYXRlUmVjdChyY0NsaWVudCwgMi4wZik7CgoJQ0ZYX0dyYXBoU3RhdGVEYXRhIGdzZDsKCWdzZC5tX0xpbmVXaWR0aCA9IDEuMGY7CgoJQ0ZYX1BhdGhEYXRhIHBhdGhDcm9zczsKCglpZiAobV9iTW91c2VEb3duKQoJewoJCXJjQ2xpZW50LmxlZnQgKz0gMC41ZjsKCQlyY0NsaWVudC5yaWdodCArPSAwLjVmOwoJCXJjQ2xpZW50LnRvcCAtPSAwLjVmOwoJCXJjQ2xpZW50LmJvdHRvbSAtPSAwLjVmOwoJfQoKCXBhdGhDcm9zcy5TZXRQb2ludENvdW50KDQpOwoJcGF0aENyb3NzLlNldFBvaW50KDAsIHJjQ2xpZW50LmxlZnQsIHJjQ2xpZW50LmJvdHRvbSwgRlhQVF9NT1ZFVE8pOwoJcGF0aENyb3NzLlNldFBvaW50KDEsIHJjQ2xpZW50LnJpZ2h0LCByY0NsaWVudC50b3AsIEZYUFRfTElORVRPKTsKCXBhdGhDcm9zcy5TZXRQb2ludCgyLCByY0NsaWVudC5sZWZ0LCByY0NsaWVudC50b3AsIEZYUFRfTU9WRVRPKTsKCXBhdGhDcm9zcy5TZXRQb2ludCgzLCByY0NsaWVudC5yaWdodCwgcmNDbGllbnQuYm90dG9tLCBGWFBUX0xJTkVUTyk7CgoJcERldmljZS0+RHJhd1BhdGgoJnBhdGhDcm9zcywgcFVzZXIyRGV2aWNlLCAmZ3NkLAoJCTAsIENQV0xfVXRpbHM6OlBXTENvbG9yVG9GWENvbG9yKEdldFRleHRDb2xvcigpLCBHZXRUcmFuc3BhcmVuY3koKSksIEZYRklMTF9BTFRFUk5BVEUpOwp9Cgpib29sIENQV0xfTm90ZV9DbG9zZUJveDo6T25MQnV0dG9uRG93bihjb25zdCBDUERGX1BvaW50ICYgcG9pbnQsIEZYX0RXT1JEIG5GbGFnKQp7CglTZXRCb3JkZXJTdHlsZShQQlNfSU5TRVQpOwoJSW52YWxpZGF0ZVJlY3QoTlVMTCk7CgoJbV9iTW91c2VEb3duID0gdHJ1ZTsKCglyZXR1cm4gQ1BXTF9CdXR0b246Ok9uTEJ1dHRvbkRvd24ocG9pbnQsbkZsYWcpOwp9Cgpib29sCUNQV0xfTm90ZV9DbG9zZUJveDo6T25MQnV0dG9uVXAoY29uc3QgQ1BERl9Qb2ludCAmIHBvaW50LCBGWF9EV09SRCBuRmxhZykKewoJbV9iTW91c2VEb3duID0gZmFsc2U7CgoJU2V0Qm9yZGVyU3R5bGUoUEJTX0JFVkVMRUQpOwoJSW52YWxpZGF0ZVJlY3QoTlVMTCk7CgoJcmV0dXJuIENQV0xfQnV0dG9uOjpPbkxCdXR0b25VcChwb2ludCxuRmxhZyk7Cn0KCi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDUFdMX05vdGVfQ29udGVudHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKQ1BXTF9Ob3RlX0NvbnRlbnRzOjpDUFdMX05vdGVfQ29udGVudHMoKSA6IG1fcEVkaXQoTlVMTCkKewp9CgpDUFdMX05vdGVfQ29udGVudHM6On5DUFdMX05vdGVfQ29udGVudHMoKQp7Cn0KCkNGWF9CeXRlU3RyaW5nIENQV0xfTm90ZV9Db250ZW50czo6R2V0Q2xhc3NOYW1lKCkgY29uc3QKewoJcmV0dXJuICJDUFdMX05vdGVfQ29udGVudHMiOwp9Cgp2b2lkIENQV0xfTm90ZV9Db250ZW50czo6Q3JlYXRlQ2hpbGRXbmQoY29uc3QgUFdMX0NSRUFURVBBUkFNICYgY3ApCnsKCW1fcEVkaXQgPSBuZXcgQ1BXTF9Ob3RlX0VkaXQ7CglQV0xfQ1JFQVRFUEFSQU0gZWNwID0gY3A7CgllY3AucFBhcmVudFduZCA9IHRoaXM7CgllY3AuZHdGbGFncyA9IFBXU19WSVNJQkxFIHwgUFdTX0NISUxEIHwgUEVTX01VTFRJTElORSB8IFBFU19BVVRPUkVUVVJOIHwgUEVTX1RFWFRPVkVSRkxPVyB8IFBFU19VTkRPIHwgUEVTX1NQRUxMQ0hFQ0s7CgoJbV9wRWRpdC0+RW5hYmxlTm90aWZ5KGZhbHNlKTsKCW1fcEVkaXQtPkNyZWF0ZShlY3ApOwoJbV9wRWRpdC0+RW5hYmxlTm90aWZ5KHRydWUpOwp9Cgp2b2lkIENQV0xfTm90ZV9Db250ZW50czo6U2V0VGV4dChjb25zdCBDRlhfV2lkZVN0cmluZyYgc1RleHQpCnsKCWlmIChtX3BFZGl0KQoJewoJCW1fcEVkaXQtPkVuYWJsZU5vdGlmeShmYWxzZSk7CgkJbV9wRWRpdC0+U2V0VGV4dChzVGV4dC5jX3N0cigpKTsKCQltX3BFZGl0LT5FbmFibGVOb3RpZnkodHJ1ZSk7CgkJT25Ob3RpZnkobV9wRWRpdCwgUE5NX05PVEVFRElUQ0hBTkdFRCwgMCwgMCk7Cgl9Cn0KCkNGWF9XaWRlU3RyaW5nIENQV0xfTm90ZV9Db250ZW50czo6R2V0VGV4dCgpIGNvbnN0CnsKCWlmIChtX3BFZGl0KQoJCXJldHVybiBtX3BFZGl0LT5HZXRUZXh0KCk7CgoJcmV0dXJuIEwiIjsKfQoKQ1BXTF9Ob3RlSXRlbSogQ1BXTF9Ob3RlX0NvbnRlbnRzOjpDcmVhdGVTdWJJdGVtKCkKewoJQ1BXTF9Ob3RlSXRlbSogcE5vdGVJdGVtID0gbmV3IENQV0xfTm90ZUl0ZW07CglQV0xfQ1JFQVRFUEFSQU0gaWNwID0gR2V0Q3JlYXRpb25QYXJhbSgpOwoJaWNwLnBQYXJlbnRXbmQgPSB0aGlzOwoJaWNwLmR3RmxhZ3MgPSAgUFdTX0NISUxEIHwgUFdTX1ZJU0lCTEUgfCBQV1NfQkFDS0dST1VORDsKCXBOb3RlSXRlbS0+Q3JlYXRlKGljcCk7CgoJcE5vdGVJdGVtLT5PbkNyZWF0ZU5vdGVJdGVtKCk7CgoJcE5vdGVJdGVtLT5SZXNldFN1YmplY3ROYW1lKG1fYUNoaWxkcmVuLkdldFNpemUoKSAtIDEpOwoKCUZYX1NZU1RFTVRJTUUgc3Q7CglpZiAoSUZYX1N5c3RlbUhhbmRsZXIqIHBTSCA9IEdldFN5c3RlbUhhbmRsZXIoKSkKCQlzdCA9IHBTSC0+R2V0TG9jYWxUaW1lKCk7CglwTm90ZUl0ZW0tPlNldERhdGVUaW1lKHN0KTsKCglwTm90ZUl0ZW0tPlNldENvbnRlbnRzKEwiIik7CgoJT25Ob3RpZnkocE5vdGVJdGVtLCBQTk1fTk9URUVESVRDSEFOR0VELCAwLCAwKTsKCglyZXR1cm4gcE5vdGVJdGVtOwp9CgppbnQzMl90IENQV0xfTm90ZV9Db250ZW50czo6Q291bnRTdWJJdGVtcygpIGNvbnN0CnsKCXJldHVybiBtX2FDaGlsZHJlbi5HZXRTaXplKCkgLSAxOwp9CgpJUFdMX05vdGVJdGVtKiBDUFdMX05vdGVfQ29udGVudHM6OkdldFN1Ykl0ZW1zKGludDMyX3QgaW5kZXgpIGNvbnN0CnsKCWludDMyX3QgbkluZGV4ID0gaW5kZXggKyAxOwoKCWlmIChuSW5kZXggPiAwICYmIG5JbmRleCA8IG1fYUNoaWxkcmVuLkdldFNpemUoKSkKCQlpZiAoQ1BXTF9XbmQqIHBDaGlsZCA9IG1fYUNoaWxkcmVuLkdldEF0KG5JbmRleCkpCgkJewoJCQlBU1NFUlQocENoaWxkLT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9Ob3RlSXRlbSIpOwoJCQlDUFdMX05vdGVJdGVtKiBwSXRlbSA9IChDUFdMX05vdGVJdGVtKilwQ2hpbGQ7CgkJCXJldHVybiBwSXRlbTsKCQl9CglyZXR1cm4gTlVMTDsKfQoKdm9pZCBDUFdMX05vdGVfQ29udGVudHM6OkRlbGV0ZVN1Ykl0ZW0oSVBXTF9Ob3RlSXRlbSogcE5vdGVJdGVtKQp7CglpbnQzMl90IG5JbmRleCA9IEdldEl0ZW1JbmRleCgoQ1BXTF9Ob3RlSXRlbSopcE5vdGVJdGVtKTsKCglpZiAobkluZGV4ID4gMCkKCXsKCQlpZiAoQ1BXTF9Ob3RlSXRlbSogcFBXTE5vdGVJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBOb3RlSXRlbSkKCQl7CgkJCXBQV0xOb3RlSXRlbS0+S2lsbEZvY3VzKCk7CgkJCXBQV0xOb3RlSXRlbS0+RGVzdHJveSgpOwoJCQlkZWxldGUgcFBXTE5vdGVJdGVtOwoJCX0KCgkJZm9yIChpbnQzMl90IGk9bkluZGV4LHN6PW1fYUNoaWxkcmVuLkdldFNpemUoKTsgaTxzejsgaSsrKQoJCXsKCQkJaWYgKENQV0xfV25kKiBwQ2hpbGQgPSBtX2FDaGlsZHJlbi5HZXRBdChpKSkKCQkJewoJCQkJQVNTRVJUKHBDaGlsZC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZUl0ZW0iKTsKCQkJCUNQV0xfTm90ZUl0ZW0qIHBJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBDaGlsZDsKCQkJCXBJdGVtLT5SZXNldFN1YmplY3ROYW1lKGkpOwoJCQl9CgkJfQoKCQlPbk5vdGlmeSh0aGlzLCBQTk1fTk9URUVESVRDSEFOR0VELCAwLCAwKTsKCX0KfQoKSVBXTF9Ob3RlSXRlbSogQ1BXTF9Ob3RlX0NvbnRlbnRzOjpHZXRIaXROb3RlSXRlbShjb25zdCBDUERGX1BvaW50JiBwb2ludCkKewoJQ1BERl9Qb2ludCBwdCA9IFBhcmVudFRvQ2hpbGQocG9pbnQpOwoKCWZvciAoaW50MzJfdCBpPTAsc3o9bV9hQ2hpbGRyZW4uR2V0U2l6ZSgpOyBpPHN6OyBpKyspCgl7CgkJaWYgKENQV0xfV25kKiBwQ2hpbGQgPSBtX2FDaGlsZHJlbi5HZXRBdChpKSkKCQl7CgkJCWlmIChwQ2hpbGQtPkdldENsYXNzTmFtZSgpID09ICJDUFdMX05vdGVJdGVtIikKCQkJewoJCQkJQ1BXTF9Ob3RlSXRlbSogcE5vdGVJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBDaGlsZDsKCQkJCWlmIChJUFdMX05vdGVJdGVtKiBwUmV0ID0gcE5vdGVJdGVtLT5HZXRIaXROb3RlSXRlbShwdCkpCgkJCQkJcmV0dXJuIHBSZXQ7CgkJCX0KCQl9Cgl9CglyZXR1cm4gTlVMTDsKfQoKdm9pZCBDUFdMX05vdGVfQ29udGVudHM6Ok9uTm90aWZ5KENQV0xfV25kKiBwV25kLCBGWF9EV09SRCBtc2csIGludHB0cl90IHdQYXJhbSwgaW50cHRyX3QgbFBhcmFtKQp7Cglzd2l0Y2ggKG1zZykKCXsKCWNhc2UgUE5NX05PVEVFRElUQ0hBTkdFRDoKCQl7CgkJCWludDMyX3QgbkluZGV4ID0gR2V0SXRlbUluZGV4KHBXbmQpOwoJCQlpZiAobkluZGV4IDwgMCkgbkluZGV4ID0gMDsKCgkJCW1fcEVkaXQtPkVuYWJsZU5vdGlmeShmYWxzZSk7CgkJCVJlc2V0Q29udGVudChuSW5kZXgpOwoJCQltX3BFZGl0LT5FbmFibGVOb3RpZnkodHJ1ZSk7CgoJCQlmb3IgKGludDMyX3QgaT1uSW5kZXgrMSwgc3o9bV9hQ2hpbGRyZW4uR2V0U2l6ZSgpOyBpPHN6OyBpKyspCgkJCXsKCQkJCWlmIChDUFdMX1duZCogcENoaWxkID0gbV9hQ2hpbGRyZW4uR2V0QXQoaSkpCgkJCQkJcENoaWxkLT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URVJFU0VULCAwLCAwKTsKCQkJfQoKCQkJaWYgKENQV0xfV25kICogcFBhcmVudCA9IEdldFBhcmVudFdpbmRvdygpKQoJCQl7CgkJCQlwUGFyZW50LT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URUVESVRDSEFOR0VELCAwLCAwKTsKCQkJfQoJCX0KCQlyZXR1cm47CgljYXNlIFBOTV9TQ1JPTExXSU5ET1c6CgkJU2V0U2Nyb2xsUG9zKENQREZfUG9pbnQoMC4wZiwgKihGWF9GTE9BVCopbFBhcmFtKSk7CgkJUmVzZXRGYWNlKCk7CgkJSW52YWxpZGF0ZVJlY3QoTlVMTCk7CgkJcmV0dXJuOwoJY2FzZSBQTk1fU0VUQ0FSRVRJTkZPOgoJCWlmIChQV0xfQ0FSRVRfSU5GTyAqIHBJbmZvID0gKFBXTF9DQVJFVF9JTkZPKil3UGFyYW0pCgkJewoJCQlQV0xfQ0FSRVRfSU5GTyBuZXdJbmZvID0gKnBJbmZvOwoJCQluZXdJbmZvLmJWaXNpYmxlID0gdHJ1ZTsKCQkJbmV3SW5mby5wdEhlYWQgPSBDaGlsZFRvUGFyZW50KHBJbmZvLT5wdEhlYWQpOwoJCQluZXdJbmZvLnB0Rm9vdCA9IENoaWxkVG9QYXJlbnQocEluZm8tPnB0Rm9vdCk7CgoJCQlpZiAoQ1BXTF9XbmQgKiBwUGFyZW50ID0gR2V0UGFyZW50V2luZG93KCkpCgkJCXsKCQkJCXBQYXJlbnQtPk9uTm90aWZ5KHRoaXMsIFBOTV9TRVRDQVJFVElORk8sIChpbnRwdHJfdCkmbmV3SW5mbywgMCk7CgkJCX0KCQl9CgkJcmV0dXJuOwoJY2FzZSBQTk1fTk9URVJFU0VUOgoJCXsKCQkJbV9wRWRpdC0+RW5hYmxlTm90aWZ5KGZhbHNlKTsKCQkJUmVzZXRDb250ZW50KDApOwoJCQltX3BFZGl0LT5FbmFibGVOb3RpZnkodHJ1ZSk7CgoJCQlmb3IgKGludDMyX3QgaT0xLCBzej1tX2FDaGlsZHJlbi5HZXRTaXplKCk7IGk8c3o7IGkrKykKCQkJewoJCQkJaWYgKENQV0xfV25kKiBwQ2hpbGQgPSBtX2FDaGlsZHJlbi5HZXRBdChpKSkKCQkJCQlwQ2hpbGQtPk9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFUkVTRVQsIDAsIDApOwoJCQl9CgoJCQltX3BFZGl0LT5FbmFibGVOb3RpZnkoZmFsc2UpOwoJCQlSZXNldENvbnRlbnQoMCk7CgkJCW1fcEVkaXQtPkVuYWJsZU5vdGlmeSh0cnVlKTsKCQl9CgkJcmV0dXJuOwoJfQoKCUNQV0xfV25kOjpPbk5vdGlmeShwV25kLCBtc2csIHdQYXJhbSwgbFBhcmFtKTsKfQoKYm9vbAlDUFdMX05vdGVfQ29udGVudHM6Ok9uTEJ1dHRvbkRvd24oY29uc3QgQ1BERl9Qb2ludCAmIHBvaW50LCBGWF9EV09SRCBuRmxhZykKewoJaWYgKENQV0xfV25kOjpPbkxCdXR0b25Eb3duKHBvaW50LG5GbGFnKSkgcmV0dXJuIHRydWU7CgoJaWYgKCFtX3BFZGl0LT5Jc0ZvY3VzZWQoKSkKCXsKCQltX3BFZGl0LT5TZXRGb2N1cygpOwoJfQoKCXJldHVybiB0cnVlOwp9Cgp2b2lkIENQV0xfTm90ZV9Db250ZW50czo6U2V0RWRpdEZvY3VzKGJvb2wgYkxhc3QpCnsKCWlmICghbV9wRWRpdC0+SXNGb2N1c2VkKCkpCgl7CgkJbV9wRWRpdC0+U2V0Rm9jdXMoKTsKCQltX3BFZGl0LT5TZXRDYXJldChiTGFzdCA/IG1fcEVkaXQtPkdldFRvdGFsV29yZHMoKSA6IDApOwoJfQp9CgpDUFdMX0VkaXQqIENQV0xfTm90ZV9Db250ZW50czo6R2V0RWRpdCgpIGNvbnN0CnsKCXJldHVybiBtX3BFZGl0Owp9Cgp2b2lkIENQV0xfTm90ZV9Db250ZW50czo6RW5hYmxlTW9kaWZ5KGJvb2wgYkVuYWJsZWQpCnsKCWlmICghYkVuYWJsZWQpCgkJbV9wRWRpdC0+QWRkRmxhZyhQV1NfUkVBRE9OTFkpOwoJZWxzZQoJCW1fcEVkaXQtPlJlbW92ZUZsYWcoUFdTX1JFQURPTkxZKTsKCglmb3IgKGludDMyX3QgaT0wLHN6PW1fYUNoaWxkcmVuLkdldFNpemUoKTsgaTxzejsgaSsrKQoJewoJCWlmIChDUFdMX1duZCogcENoaWxkID0gbV9hQ2hpbGRyZW4uR2V0QXQoaSkpCgkJewoJCQlpZiAocENoaWxkLT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9Ob3RlSXRlbSIpCgkJCXsKCQkJCUNQV0xfTm90ZUl0ZW0qIHBOb3RlSXRlbSA9IChDUFdMX05vdGVJdGVtKilwQ2hpbGQ7CgkJCQlwTm90ZUl0ZW0tPkVuYWJsZU1vZGlmeShiRW5hYmxlZCk7CgkJCX0KCQl9Cgl9Cn0KCnZvaWQgQ1BXTF9Ob3RlX0NvbnRlbnRzOjpFbmFibGVSZWFkKGJvb2wgYkVuYWJsZWQpCnsKCWlmICghYkVuYWJsZWQpCgkJbV9wRWRpdC0+QWRkRmxhZyhQRVNfTk9SRUFEKTsKCWVsc2UKCQltX3BFZGl0LT5SZW1vdmVGbGFnKFBFU19OT1JFQUQpOwoKCWZvciAoaW50MzJfdCBpPTAsc3o9bV9hQ2hpbGRyZW4uR2V0U2l6ZSgpOyBpPHN6OyBpKyspCgl7CgkJaWYgKENQV0xfV25kKiBwQ2hpbGQgPSBtX2FDaGlsZHJlbi5HZXRBdChpKSkKCQl7CgkJCWlmIChwQ2hpbGQtPkdldENsYXNzTmFtZSgpID09ICJDUFdMX05vdGVJdGVtIikKCQkJewoJCQkJQ1BXTF9Ob3RlSXRlbSogcE5vdGVJdGVtID0gKENQV0xfTm90ZUl0ZW0qKXBDaGlsZDsKCQkJCXBOb3RlSXRlbS0+RW5hYmxlUmVhZChiRW5hYmxlZCk7CgkJCX0KCQl9Cgl9Cn0KCi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ1BXTF9Ob3RlSXRlbSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCgpDUFdMX05vdGVJdGVtOjpDUFdMX05vdGVJdGVtKCkgOgoJbV9wU3ViamVjdChOVUxMKSwKCW1fcERhdGVUaW1lKE5VTEwpLAoJbV9wQ29udGVudHMoTlVMTCksCgltX3BQcml2YXRlRGF0YShOVUxMKSwKCW1fc0F1dGhvcihMIiIpLAoJbV9mT2xkSXRlbUhlaWdodCgwLjBmKSwKCW1fYlNpemVDaGFuZ2VkKGZhbHNlKSwKCW1fYkFsbG93TW9kaWZ5KHRydWUpCnsKfQoKQ1BXTF9Ob3RlSXRlbTo6fkNQV0xfTm90ZUl0ZW0oKQp7Cn0KCkNGWF9CeXRlU3RyaW5nIENQV0xfTm90ZUl0ZW06OkdldENsYXNzTmFtZSgpIGNvbnN0CnsKCXJldHVybiAiQ1BXTF9Ob3RlSXRlbSI7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6Q3JlYXRlQ2hpbGRXbmQoY29uc3QgUFdMX0NSRUFURVBBUkFNICYgY3ApCnsKCUNQV0xfQ29sb3Igc1RleHRDb2xvcjsKCglpZiAoQ1BXTF9VdGlsczo6SXNCbGFja09yV2hpdGUoR2V0QmFja2dyb3VuZENvbG9yKCkpKQoJCXNUZXh0Q29sb3IgPSBQV0xfREVGQVVMVF9XSElURUNPTE9SOwoJZWxzZQoJCXNUZXh0Q29sb3IgPSBQV0xfREVGQVVMVF9CTEFDS0NPTE9SOwoKCW1fcFN1YmplY3QgPSBuZXcgQ1BXTF9MYWJlbDsKCVBXTF9DUkVBVEVQQVJBTSBzY3AgPSBjcDsKCXNjcC5wUGFyZW50V25kID0gdGhpczsKCXNjcC5kd0ZsYWdzID0gUFdTX1ZJU0lCTEUgfCBQV1NfQ0hJTEQgfCBQRVNfTEVGVCB8IFBFU19UT1A7CglzY3Auc1RleHRDb2xvciA9IHNUZXh0Q29sb3I7CgltX3BTdWJqZWN0LT5DcmVhdGUoc2NwKTsKCgltX3BEYXRlVGltZSA9IG5ldyBDUFdMX0xhYmVsOwoJUFdMX0NSRUFURVBBUkFNIGRjcCA9IGNwOwoJZGNwLnBQYXJlbnRXbmQgPSB0aGlzOwoJZGNwLmR3RmxhZ3MgPSBQV1NfVklTSUJMRSB8IFBXU19DSElMRCB8IFBFU19SSUdIVCB8IFBFU19UT1A7CglkY3Auc1RleHRDb2xvciA9IHNUZXh0Q29sb3I7CgltX3BEYXRlVGltZS0+Q3JlYXRlKGRjcCk7CgoJbV9wQ29udGVudHMgPSBuZXcgQ1BXTF9Ob3RlX0NvbnRlbnRzOwoJUFdMX0NSRUFURVBBUkFNIGNjcCA9IGNwOwoJY2NwLnBQYXJlbnRXbmQgPSB0aGlzOwoJLy9jY3Auc0JhY2tncm91bmRDb2xvciA9IFBXTF9ERUZBVUxUX1dISVRFQ09MT1I7CgljY3Auc0JhY2tncm91bmRDb2xvciA9IENQV0xfQ29sb3IoQ09MT1JUWVBFX1JHQiwgMjQwLzI1NS4wZiwgMjQwLzI1NS4wZiwgMjQwLzI1NS4wZik7CgljY3AuZHdGbGFncyA9IFBXU19WSVNJQkxFIHwgUFdTX0NISUxEIHwgUFdTX0JBQ0tHUk9VTkQ7CgltX3BDb250ZW50cy0+Q3JlYXRlKGNjcCk7CgltX3BDb250ZW50cy0+U2V0SXRlbVNwYWNlKFBPUFVQX0lURU1fU1BBQ0UpOwoJbV9wQ29udGVudHMtPlNldFRvcFNwYWNlKFBPUFVQX0lURU1fU1BBQ0UpOwoJbV9wQ29udGVudHMtPlNldEJvdHRvbVNwYWNlKFBPUFVQX0lURU1fU1BBQ0UpOwp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OlJlUG9zQ2hpbGRXbmQoKQp7CglpZiAoSXNWYWxpZCgpKQoJewoJCUFTU0VSVChtX3BTdWJqZWN0ICE9IE5VTEwpOwoJCUFTU0VSVChtX3BEYXRlVGltZSAhPSBOVUxMKTsKCQlBU1NFUlQobV9wQ29udGVudHMgIT0gTlVMTCk7CgoJCUNQREZfUmVjdCByY0NsaWVudCA9IEdldENsaWVudFJlY3QoKTsKCgkJQ1BERl9SZWN0IHJjU3ViamVjdCA9IHJjQ2xpZW50OwoJCXJjU3ViamVjdC5sZWZ0ICs9IFBPUFVQX0lURU1fVEVYVF9JTkRFTlQ7CgkJcmNTdWJqZWN0LnRvcCA9IHJjQ2xpZW50LnRvcDsKCQlyY1N1YmplY3QucmlnaHQgPSBQV0xfTUlOKHJjU3ViamVjdC5sZWZ0ICsgbV9wU3ViamVjdC0+R2V0Q29udGVudFJlY3QoKS5XaWR0aCgpICsgMS4wZiwgcmNDbGllbnQucmlnaHQpOwoJCXJjU3ViamVjdC5ib3R0b20gPSByY1N1YmplY3QudG9wIC0gbV9wU3ViamVjdC0+R2V0Q29udGVudFJlY3QoKS5IZWlnaHQoKTsKCQlyY1N1YmplY3QuTm9ybWFsaXplKCk7CgkJbV9wU3ViamVjdC0+TW92ZShyY1N1YmplY3QsIHRydWUsIGZhbHNlKTsKCQltX3BTdWJqZWN0LT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNTdWJqZWN0KSk7CgoJCUNQREZfUmVjdCByY0RhdGUgPSByY0NsaWVudDsKCQlyY0RhdGUucmlnaHQgLT0gUE9QVVBfSVRFTV9URVhUX0lOREVOVDsKCQlyY0RhdGUubGVmdCA9IFBXTF9NQVgocmNEYXRlLnJpZ2h0IC0gbV9wRGF0ZVRpbWUtPkdldENvbnRlbnRSZWN0KCkuV2lkdGgoKSAtIDEuMGYsIHJjU3ViamVjdC5yaWdodCk7CgkJcmNEYXRlLmJvdHRvbSA9IHJjRGF0ZS50b3AgLSBtX3BEYXRlVGltZS0+R2V0Q29udGVudFJlY3QoKS5IZWlnaHQoKTsKCQlyY0RhdGUuTm9ybWFsaXplKCk7CgkJbV9wRGF0ZVRpbWUtPk1vdmUocmNEYXRlLCB0cnVlLCBmYWxzZSk7CgkJbV9wRGF0ZVRpbWUtPlNldFZpc2libGUoQ1BXTF9VdGlsczo6Q29udGFpbnNSZWN0KHJjQ2xpZW50LCByY0RhdGUpKTsKCgkJQ1BERl9SZWN0IHJjQ29udGVudHMgPSByY0NsaWVudDsKCQlyY0NvbnRlbnRzLmxlZnQgKz0gMS4wZjsKCQlyY0NvbnRlbnRzLnJpZ2h0IC09IDEuMGY7CgkJcmNDb250ZW50cy50b3AgPSByY0RhdGUuYm90dG9tIC0gUE9QVVBfSVRFTV9IRUFEX0JPVFRPTTsKCQlyY0NvbnRlbnRzLmJvdHRvbSArPSBQT1BVUF9JVEVNX0JPVFRPTVdJRFRIOwoJCXJjQ29udGVudHMuTm9ybWFsaXplKCk7CgkJbV9wQ29udGVudHMtPk1vdmUocmNDb250ZW50cywgdHJ1ZSwgZmFsc2UpOwoJCW1fcENvbnRlbnRzLT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNDb250ZW50cykpOwoJfQoKCVNldENsaXBSZWN0KENQV0xfVXRpbHM6OkluZmxhdGVSZWN0KEdldFdpbmRvd1JlY3QoKSwxLjBmKSk7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6U2V0UHJpdmF0ZURhdGEodm9pZCogcERhdGEpCnsKCW1fcFByaXZhdGVEYXRhID0gcERhdGE7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6U2V0QmtDb2xvcihjb25zdCBDUFdMX0NvbG9yJiBjb2xvcikKewoJQ1BXTF9Db2xvciBzQksgPSBjb2xvcjsKCVNldEJhY2tncm91bmRDb2xvcihzQkspOwoKCUNQV0xfQ29sb3Igc1RleHRDb2xvcjsKCglpZiAoQ1BXTF9VdGlsczo6SXNCbGFja09yV2hpdGUoc0JLKSkKCQlzVGV4dENvbG9yID0gUFdMX0RFRkFVTFRfV0hJVEVDT0xPUjsKCWVsc2UKCQlzVGV4dENvbG9yID0gUFdMX0RFRkFVTFRfQkxBQ0tDT0xPUjsKCglTZXRUZXh0Q29sb3Ioc1RleHRDb2xvcik7CglpZiAobV9wU3ViamVjdCkKCQltX3BTdWJqZWN0LT5TZXRUZXh0Q29sb3Ioc1RleHRDb2xvcik7CglpZiAobV9wRGF0ZVRpbWUpCgkJbV9wRGF0ZVRpbWUtPlNldFRleHRDb2xvcihzVGV4dENvbG9yKTsKCglJbnZhbGlkYXRlUmVjdChudWxscHRyKTsKCglpZiAoSVBXTF9Ob3RlTm90aWZ5KiBwTm90aWZ5ID0gR2V0Tm90ZU5vdGlmeSgpKQoJewoJCXBOb3RpZnktPk9uU2V0QmtDb2xvcih0aGlzKTsKCX0KfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpTZXRTdWJqZWN0TmFtZShjb25zdCBDRlhfV2lkZVN0cmluZyYgc05hbWUpCnsKCWlmIChtX3BTdWJqZWN0KQoJewoJCW1fcFN1YmplY3QtPlNldFRleHQoc05hbWUuY19zdHIoKSk7Cgl9CgoJaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkKCXsKCQlwTm90aWZ5LT5PblNldFN1YmplY3ROYW1lKHRoaXMpOwoJfQp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OlNldEF1dGhvck5hbWUoY29uc3QgQ0ZYX1dpZGVTdHJpbmcmIHNOYW1lKQp7CgltX3NBdXRob3IgPSBzTmFtZTsKCVJlc2V0U3ViamVjdE5hbWUoLTEpOwoKCWlmIChJUFdMX05vdGVOb3RpZnkqIHBOb3RpZnkgPSBHZXROb3RlTm90aWZ5KCkpCgl7CgkJcE5vdGlmeS0+T25TZXRBdXRob3JOYW1lKHRoaXMpOwoJfQp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OlJlc2V0U3ViamVjdE5hbWUoaW50MzJfdCBuSXRlbUluZGV4KQp7CglpZiAobkl0ZW1JbmRleCA8IDApCgl7CgkJaWYgKENQV0xfV25kKiBwUGFyZW50ID0gR2V0UGFyZW50V2luZG93KCkpCgkJewoJCQlBU1NFUlQocFBhcmVudC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZV9Db250ZW50cyIpOwoKCQkJQ1BXTF9Ob3RlX0NvbnRlbnRzKiBwQ29udGVudHMgPSAoQ1BXTF9Ob3RlX0NvbnRlbnRzKilwUGFyZW50OwoJCQluSXRlbUluZGV4ID0gcENvbnRlbnRzLT5HZXRJdGVtSW5kZXgodGhpcyk7CgkJfQoJfQoKCWNvbnN0IENQV0xfTm90ZSogcE5vdGUgPSBHZXROb3RlKCk7CglBU1NFUlQocE5vdGUgIT0gTlVMTCk7CgoJQ0ZYX1dpZGVTdHJpbmcgc1N1YmplY3Q7CglzU3ViamVjdC5Gb3JtYXQocE5vdGUtPkdldFJlcGx5U3RyaW5nKCkuY19zdHIoKSwgbkl0ZW1JbmRleCk7CgoJaWYgKCFtX3NBdXRob3IuSXNFbXB0eSgpKQoJewoJCXNTdWJqZWN0ICs9IEwiIC0gIjsKCQlzU3ViamVjdCArPSBtX3NBdXRob3I7Cgl9CglTZXRTdWJqZWN0TmFtZShzU3ViamVjdCk7CglSZVBvc0NoaWxkV25kKCk7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6U2V0RGF0ZVRpbWUoRlhfU1lTVEVNVElNRSB0aW1lKQp7CgltX2R0Tm90ZSA9IHRpbWU7CgoJQ0ZYX1dpZGVTdHJpbmcgc3dUaW1lOwoJc3dUaW1lLkZvcm1hdChMIiUwNGQtJTAyZC0lMDJkICUwMmQ6JTAyZDolMDJkIiwgdGltZS53WWVhciwgdGltZS53TW9udGgsIHRpbWUud0RheSwgdGltZS53SG91ciwgdGltZS53TWludXRlLCB0aW1lLndTZWNvbmQpOwoJaWYgKG1fcERhdGVUaW1lKQoJewoJCW1fcERhdGVUaW1lLT5TZXRUZXh0KHN3VGltZS5jX3N0cigpKTsKCX0KCglSZVBvc0NoaWxkV25kKCk7CgoJaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkKCXsKCQlwTm90aWZ5LT5PblNldERhdGVUaW1lKHRoaXMpOwoJfQp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OlNldENvbnRlbnRzKGNvbnN0IENGWF9XaWRlU3RyaW5nJiBzQ29udGVudHMpCnsKCWlmIChtX3BDb250ZW50cykKCXsKCQltX3BDb250ZW50cy0+U2V0VGV4dChzQ29udGVudHMpOwoJfQoKCWlmIChJUFdMX05vdGVOb3RpZnkqIHBOb3RpZnkgPSBHZXROb3RlTm90aWZ5KCkpCgl7CgkJcE5vdGlmeS0+T25TZXRDb250ZW50cyh0aGlzKTsKCX0KfQoKQ1BXTF9Ob3RlSXRlbSogQ1BXTF9Ob3RlSXRlbTo6R2V0UGFyZW50Tm90ZUl0ZW0oKSBjb25zdAp7CglpZiAoQ1BXTF9XbmQqIHBQYXJlbnQgPSBHZXRQYXJlbnRXaW5kb3coKSkKCXsKCQlpZiAoQ1BXTF9XbmQqIHBHcmFuZCA9IHBQYXJlbnQtPkdldFBhcmVudFdpbmRvdygpKQoJCXsKCQkJQVNTRVJUKHBHcmFuZC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZUl0ZW0iKTsKCQkJcmV0dXJuIChDUFdMX05vdGVJdGVtKilwR3JhbmQ7CgkJfQoJfQoKCXJldHVybiBOVUxMOwp9CgpJUFdMX05vdGVJdGVtKiBDUFdMX05vdGVJdGVtOjpHZXRQYXJlbnRJdGVtKCkgY29uc3QKewoJcmV0dXJuIEdldFBhcmVudE5vdGVJdGVtKCk7Cn0KCkNQV0xfRWRpdCogQ1BXTF9Ob3RlSXRlbTo6R2V0RWRpdCgpIGNvbnN0CnsKCWlmIChtX3BDb250ZW50cykKCQlyZXR1cm4gbV9wQ29udGVudHMtPkdldEVkaXQoKTsKCXJldHVybiBOVUxMOwp9Cgp2b2lkKiBDUFdMX05vdGVJdGVtOjpHZXRQcml2YXRlRGF0YSgpIGNvbnN0CnsKCXJldHVybiBtX3BQcml2YXRlRGF0YTsKfQoKQ0ZYX1dpZGVTdHJpbmcgQ1BXTF9Ob3RlSXRlbTo6R2V0QXV0aG9yTmFtZSgpIGNvbnN0CnsKCXJldHVybiBtX3NBdXRob3I7Cn0KCkNQV0xfQ29sb3IgQ1BXTF9Ob3RlSXRlbTo6R2V0QmtDb2xvcigpIGNvbnN0CnsKCXJldHVybiBHZXRCYWNrZ3JvdW5kQ29sb3IoKTsKfQoKQ0ZYX1dpZGVTdHJpbmcgQ1BXTF9Ob3RlSXRlbTo6R2V0Q29udGVudHMoKSBjb25zdAp7CglpZiAobV9wQ29udGVudHMpCgkJcmV0dXJuIG1fcENvbnRlbnRzLT5HZXRUZXh0KCk7CgoJcmV0dXJuIEwiIjsKfQoKRlhfU1lTVEVNVElNRSBDUFdMX05vdGVJdGVtOjpHZXREYXRlVGltZSgpIGNvbnN0CnsKCXJldHVybiBtX2R0Tm90ZTsKfQoKQ0ZYX1dpZGVTdHJpbmcgQ1BXTF9Ob3RlSXRlbTo6R2V0U3ViamVjdE5hbWUoKSBjb25zdAp7CglpZiAobV9wU3ViamVjdCkKCQlyZXR1cm4gbV9wU3ViamVjdC0+R2V0VGV4dCgpOwoKCXJldHVybiBMIiI7Cn0KCkNQV0xfTm90ZUl0ZW0qIENQV0xfTm90ZUl0ZW06OkNyZWF0ZU5vdGVJdGVtKCkKewoJaWYgKG1fcENvbnRlbnRzKQoJCXJldHVybiBtX3BDb250ZW50cy0+Q3JlYXRlU3ViSXRlbSgpOwoKCXJldHVybiBOVUxMOwp9CgpJUFdMX05vdGVJdGVtKiBDUFdMX05vdGVJdGVtOjpDcmVhdGVTdWJJdGVtKCkKewoJcmV0dXJuIENyZWF0ZU5vdGVJdGVtKCk7Cn0KCmludDMyX3QgQ1BXTF9Ob3RlSXRlbTo6Q291bnRTdWJJdGVtcygpIGNvbnN0CnsKCWlmIChtX3BDb250ZW50cykKCQlyZXR1cm4gbV9wQ29udGVudHMtPkNvdW50U3ViSXRlbXMoKTsKCglyZXR1cm4gMDsKfQoKSVBXTF9Ob3RlSXRlbSogQ1BXTF9Ob3RlSXRlbTo6R2V0U3ViSXRlbXMoaW50MzJfdCBpbmRleCkgY29uc3QKewoJaWYgKG1fcENvbnRlbnRzKQoJCXJldHVybiBtX3BDb250ZW50cy0+R2V0U3ViSXRlbXMoaW5kZXgpOwoKCXJldHVybiBOVUxMOwp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06OkRlbGV0ZVN1Ykl0ZW0oSVBXTF9Ob3RlSXRlbSogcE5vdGVJdGVtKQp7CglLaWxsRm9jdXMoKTsKCglpZiAoSVBXTF9Ob3RlTm90aWZ5KiBwTm90aWZ5ID0gR2V0Tm90ZU5vdGlmeSgpKQoJewoJCXBOb3RpZnktPk9uSXRlbURlbGV0ZShwTm90ZUl0ZW0pOwoJfQoKCWlmIChtX3BDb250ZW50cykKCQltX3BDb250ZW50cy0+RGVsZXRlU3ViSXRlbShwTm90ZUl0ZW0pOwp9CgpJUFdMX05vdGVJdGVtKiBDUFdMX05vdGVJdGVtOjpHZXRIaXROb3RlSXRlbShjb25zdCBDUERGX1BvaW50JiBwb2ludCkKewoJQ1BERl9Qb2ludCBwdCA9IFBhcmVudFRvQ2hpbGQocG9pbnQpOwoKCWlmIChXbmRIaXRUZXN0KHB0KSkKCXsKCQlpZiAobV9wQ29udGVudHMpCgkJewoJCQlpZiAoSVBXTF9Ob3RlSXRlbSogcE5vdGVJdGVtID0gbV9wQ29udGVudHMtPkdldEhpdE5vdGVJdGVtKHB0KSkKCQkJCXJldHVybiBwTm90ZUl0ZW07CgkJfQoKCQlyZXR1cm4gdGhpczsKCX0KCglyZXR1cm4gTlVMTDsKfQoKSVBXTF9Ob3RlSXRlbSogQ1BXTF9Ob3RlSXRlbTo6R2V0Rm9jdXNlZE5vdGVJdGVtKCkgY29uc3QKewoJaWYgKGNvbnN0IENQV0xfV25kKiBwV25kID0gR2V0Rm9jdXNlZCgpKQoJewoJCWlmIChwV25kLT5HZXRDbGFzc05hbWUoKSA9PSAiQ1BXTF9FZGl0IikKCQl7CgkJCWlmIChDUFdMX1duZCogcFBhcmVudCA9IHBXbmQtPkdldFBhcmVudFdpbmRvdygpKQoJCQl7CgkJCQlBU1NFUlQocFBhcmVudC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZV9Db250ZW50cyIpOwoKCQkJCWlmIChDUFdMX1duZCogcEdyYW5kID0gcFBhcmVudC0+R2V0UGFyZW50V2luZG93KCkpCgkJCQl7CgkJCQkJQVNTRVJUKHBHcmFuZC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZUl0ZW0iKTsKCQkJCQlyZXR1cm4gKENQV0xfTm90ZUl0ZW0qKXBHcmFuZDsKCQkJCX0KCQkJfQoJCX0KCX0KCglyZXR1cm4gTlVMTDsKfQoKRlhfRkxPQVQgQ1BXTF9Ob3RlSXRlbTo6R2V0SXRlbUhlaWdodChGWF9GTE9BVCBmTGltaXRXaWR0aCkKewoJaWYgKGZMaW1pdFdpZHRoID4gMCkKCXsKCQlpZiAoIW1fYlNpemVDaGFuZ2VkKQoJCQlyZXR1cm4gbV9mT2xkSXRlbUhlaWdodDsKCgkJbV9iU2l6ZUNoYW5nZWQgPSBmYWxzZTsKCgkJQVNTRVJUKG1fcFN1YmplY3QgIT0gTlVMTCk7CgkJQVNTRVJUKG1fcERhdGVUaW1lICE9IE5VTEwpOwoJCUFTU0VSVChtX3BDb250ZW50cyAhPSBOVUxMKTsKCgkJRlhfRkxPQVQgZlJldCA9IG1fcERhdGVUaW1lLT5HZXRDb250ZW50UmVjdCgpLkhlaWdodCgpOwoJCUZYX0ZMT0FUIGZCb3JkZXJXaWR0aCA9IChGWF9GTE9BVClHZXRCb3JkZXJXaWR0aCgpOwoJCWlmIChmTGltaXRXaWR0aCA+IGZCb3JkZXJXaWR0aCAqIDIpCgkJCWZSZXQgKz0gbV9wQ29udGVudHMtPkdldENvbnRlbnRzSGVpZ2h0KGZMaW1pdFdpZHRoIC0gZkJvcmRlcldpZHRoICogMik7CgkJZlJldCArPSBQT1BVUF9JVEVNX0hFQURfQk9UVE9NICsgUE9QVVBfSVRFTV9CT1RUT01XSURUSCArIGZCb3JkZXJXaWR0aCAqIDI7CgoJCXJldHVybiBtX2ZPbGRJdGVtSGVpZ2h0ID0gZlJldDsKCX0KCglyZXR1cm4gMDsKfQoKRlhfRkxPQVQgQ1BXTF9Ob3RlSXRlbTo6R2V0SXRlbUxlZnRNYXJnaW4oKQp7CglyZXR1cm4gUE9QVVBfSVRFTV9TSURFTUFSR0lOOwp9CgpGWF9GTE9BVCBDUFdMX05vdGVJdGVtOjpHZXRJdGVtUmlnaHRNYXJnaW4oKQp7CglyZXR1cm4gUE9QVVBfSVRFTV9TSURFTUFSR0lOOwp9Cgpib29sCUNQV0xfTm90ZUl0ZW06Ok9uTEJ1dHRvbkRvd24oY29uc3QgQ1BERl9Qb2ludCYgcG9pbnQsIEZYX0RXT1JEIG5GbGFnKQp7CglpZiAoIW1fcENvbnRlbnRzLT5XbmRIaXRUZXN0KG1fcENvbnRlbnRzLT5QYXJlbnRUb0NoaWxkKHBvaW50KSkpCgl7CgkJU2V0Tm90ZUZvY3VzKGZhbHNlKTsKCX0KCglDUFdMX1duZDo6T25MQnV0dG9uRG93bihwb2ludCxuRmxhZyk7CgoJcmV0dXJuIHRydWU7Cn0KCmJvb2wJQ1BXTF9Ob3RlSXRlbTo6T25SQnV0dG9uVXAoY29uc3QgQ1BERl9Qb2ludCAmIHBvaW50LCBGWF9EV09SRCBuRmxhZykKewoJaWYgKCFtX3BDb250ZW50cy0+V25kSGl0VGVzdChtX3BDb250ZW50cy0+UGFyZW50VG9DaGlsZChwb2ludCkpKQoJewoJCVNldE5vdGVGb2N1cyhmYWxzZSk7CgkJUG9wdXBOb3RlSXRlbU1lbnUocG9pbnQpOwoKCQlyZXR1cm4gdHJ1ZTsKCX0KCglyZXR1cm4gQ1BXTF9XbmQ6Ok9uUkJ1dHRvblVwKHBvaW50LG5GbGFnKTsKfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpPbk5vdGlmeShDUFdMX1duZCogcFduZCwgRlhfRFdPUkQgbXNnLCBpbnRwdHJfdCB3UGFyYW0sIGludHB0cl90IGxQYXJhbSkKewoJc3dpdGNoIChtc2cpCgl7CgljYXNlIFBOTV9OT1RFRURJVENIQU5HRUQ6CgkJbV9iU2l6ZUNoYW5nZWQgPSB0cnVlOwoKCQlpZiAoQ1BXTF9XbmQqIHBQYXJlbnQgPSBHZXRQYXJlbnRXaW5kb3coKSkKCQl7CgkJCXBQYXJlbnQtPk9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFRURJVENIQU5HRUQsIDAsIDApOwoJCX0KCQlyZXR1cm47CgljYXNlIFBOTV9TRVRDQVJFVElORk86CgkJaWYgKFBXTF9DQVJFVF9JTkZPICogcEluZm8gPSAoUFdMX0NBUkVUX0lORk8qKXdQYXJhbSkKCQl7CgkJCVBXTF9DQVJFVF9JTkZPIG5ld0luZm8gPSAqcEluZm87CgkJCW5ld0luZm8uYlZpc2libGUgPSB0cnVlOwoJCQluZXdJbmZvLnB0SGVhZCA9IENoaWxkVG9QYXJlbnQocEluZm8tPnB0SGVhZCk7CgkJCW5ld0luZm8ucHRGb290ID0gQ2hpbGRUb1BhcmVudChwSW5mby0+cHRGb290KTsKCgkJCWlmIChDUFdMX1duZCAqIHBQYXJlbnQgPSBHZXRQYXJlbnRXaW5kb3coKSkKCQkJewoJCQkJcFBhcmVudC0+T25Ob3RpZnkodGhpcywgUE5NX1NFVENBUkVUSU5GTywgKGludHB0cl90KSZuZXdJbmZvLCAwKTsKCQkJfQoJCX0KCQlyZXR1cm47CgljYXNlIFBOTV9OT1RFUkVTRVQ6CgkJbV9iU2l6ZUNoYW5nZWQgPSB0cnVlOwoJCW1fcENvbnRlbnRzLT5Pbk5vdGlmeSh0aGlzLCBQTk1fTk9URVJFU0VULCAwLCAwKTsKCgkJcmV0dXJuOwoJfQoKCUNQV0xfV25kOjpPbk5vdGlmeShwV25kLCBtc2csIHdQYXJhbSwgbFBhcmFtKTsKfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpQb3B1cE5vdGVJdGVtTWVudShjb25zdCBDUERGX1BvaW50JiBwb2ludCkKewoJaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkKCXsKCQlpbnQzMl90IHgseTsKCQlQV0x0b1duZChwb2ludCwgeCwgeSk7CgkJaWYgKElGWF9TeXN0ZW1IYW5kbGVyKiBwU0ggPSBHZXRTeXN0ZW1IYW5kbGVyKCkpCgkJCXBTSC0+Q2xpZW50VG9TY3JlZW4oR2V0QXR0YWNoZWRIV25kKCksIHgsIHkpOwoJCXBOb3RpZnktPk9uUG9wdXBNZW51KHRoaXMsIHgsIHkpOwoJfQp9Cgpjb25zdCBDUFdMX05vdGUqIENQV0xfTm90ZUl0ZW06OkdldE5vdGUoKSBjb25zdAp7CglpZiAoY29uc3QgQ1BXTF9XbmQqIHBSb290ID0gR2V0Um9vdFduZCgpKQoJewoJCUFTU0VSVChwUm9vdC0+R2V0Q2xhc3NOYW1lKCkgPT0gIkNQV0xfTm90ZUl0ZW0iKTsKCQlDUFdMX05vdGVJdGVtKiBwTm90ZUl0ZW0gPSAoQ1BXTF9Ob3RlSXRlbSopcFJvb3Q7CgkJaWYgKHBOb3RlSXRlbS0+SXNUb3BJdGVtKCkpCgkJewoJCQlyZXR1cm4gKENQV0xfTm90ZSopcE5vdGVJdGVtOwoJCX0KCX0KCglyZXR1cm4gTlVMTDsKfQoKSVBXTF9Ob3RlTm90aWZ5KiBDUFdMX05vdGVJdGVtOjpHZXROb3RlTm90aWZ5KCkgY29uc3QKewoJaWYgKGNvbnN0IENQV0xfTm90ZSogcE5vdGUgPSBHZXROb3RlKCkpCgkJcmV0dXJuIHBOb3RlLT5HZXROb3RlTm90aWZ5KCk7CgoJcmV0dXJuIE5VTEw7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6T25DcmVhdGVOb3RlSXRlbSgpCnsKCWlmIChJUFdMX05vdGVOb3RpZnkqIHBOb3RpZnkgPSBHZXROb3RlTm90aWZ5KCkpCgl7CgkJcE5vdGlmeS0+T25JdGVtQ3JlYXRlKHRoaXMpOwoJfQp9Cgp2b2lkIENQV0xfTm90ZUl0ZW06Ok9uQ29udGVudHNWYWxpZGF0ZSgpCnsKCWlmIChJUFdMX05vdGVOb3RpZnkqIHBOb3RpZnkgPSBHZXROb3RlTm90aWZ5KCkpCgl7CgkJcE5vdGlmeS0+T25TZXRDb250ZW50cyh0aGlzKTsKCX0KfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpTZXROb3RlRm9jdXMoYm9vbCBiTGFzdCkKewoJbV9wQ29udGVudHMtPlNldEVkaXRGb2N1cyhiTGFzdCk7Cn0KCnZvaWQgQ1BXTF9Ob3RlSXRlbTo6RW5hYmxlTW9kaWZ5KGJvb2wgYkVuYWJsZWQpCnsKCW1fcENvbnRlbnRzLT5FbmFibGVNb2RpZnkoYkVuYWJsZWQpOwoJbV9iQWxsb3dNb2RpZnkgPSBiRW5hYmxlZDsKfQoKdm9pZCBDUFdMX05vdGVJdGVtOjpFbmFibGVSZWFkKGJvb2wgYkVuYWJsZWQpCnsKCW1fcENvbnRlbnRzLT5FbmFibGVSZWFkKGJFbmFibGVkKTsKfQoKLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDUFdMX05vdGUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKQ1BXTF9Ob3RlOjpDUFdMX05vdGUoSVBvcHVwX05vdGUqIHBQb3B1cE5vdGUsIElQV0xfTm90ZU5vdGlmeSogcE5vdGVOb3RpZnksIElQV0xfTm90ZUhhbmRsZXIqIHBOb3RlSGFuZGxlcikgOgoJbV9wQXV0aG9yKE5VTEwpLAoJbV9wSWNvbihOVUxMKSwKCW1fcENsb3NlQm94KE5VTEwpLAoJbV9wTEJCb3goTlVMTCksCgltX3BSQkJveChOVUxMKSwKCW1fcENvbnRlbnRzQmFyKE5VTEwpLAoJbV9wT3B0aW9ucyhOVUxMKSwKCW1fcE5vdGVOb3RpZnkocE5vdGVOb3RpZnkpLAoJbV9iUmVzaXppbmcoZmFsc2UpLAoJbV9yY0NhcHRpb24oMCwwLDAsMCksCgltX2JFbmFsYmxlTm90aWZ5KHRydWUpLAoJbV9wUG9wdXBOb3RlKHBQb3B1cE5vdGUpCnsKfQoKQ1BXTF9Ob3RlOjp+Q1BXTF9Ob3RlKCkKewp9CgpJUFdMX05vdGVJdGVtKiBDUFdMX05vdGU6OlJlcGx5KCkKewoJcmV0dXJuIENyZWF0ZU5vdGVJdGVtKCk7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpFbmFibGVOb3RpZnkoYm9vbCBiRW5hYmxlZCkKewoJbV9iRW5hbGJsZU5vdGlmeSA9IGJFbmFibGVkOwp9Cgp2b2lkIENQV0xfTm90ZTo6UmVQb3NDaGlsZFduZCgpCnsKCVJlUG9zTm90ZUNoaWxkcmVuKCk7CgltX3BDb250ZW50cy0+T25Ob3RpZnkodGhpcywgUE5NX05PVEVSRVNFVCwgMCwgMCk7CglSZXNldFNjcm9sbEJhcigpOwoJbV9wQ29udGVudHMtPk9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFUkVTRVQsIDAsIDApOwoJT25Ob3RpZnkodGhpcywgUE5NX05PVEVFRElUQ0hBTkdFRCwgMCwgMCk7CglpZiAoY29uc3QgQ1BXTF9XbmQqIHBXbmQgPSBHZXRGb2N1c2VkKCkpCgl7CgkJaWYgKHBXbmQtPkdldENsYXNzTmFtZSgpID09ICJDUFdMX0VkaXQiKQoJCXsKCQkJQ1BXTF9FZGl0KiBwRWRpdCA9IChDUFdMX0VkaXQqKXBXbmQ7CgkJCXBFZGl0LT5TZXRDYXJldChwRWRpdC0+R2V0Q2FyZXQoKSk7CgkJfQoJfQp9Cgpib29sIENQV0xfTm90ZTo6UmVzZXRTY3JvbGxCYXIoKQp7Cglib29sIGJTY3JvbGxDaGFuZ2VkID0gZmFsc2U7CgoJaWYgKFNjcm9sbEJhclNob3VsZFZpc2libGUoKSkKCXsKCQlpZiAoIW1fcENvbnRlbnRzQmFyLT5Jc1Zpc2libGUoKSkKCQl7CgkJCW1fcENvbnRlbnRzQmFyLT5TZXRWaXNpYmxlKHRydWUpOwoJCQlpZiAobV9wQ29udGVudHNCYXItPklzVmlzaWJsZSgpKQoJCQl7CgkJCQltX3BDb250ZW50c0Jhci0+SW52YWxpZGF0ZVJlY3QoTlVMTCk7CgkJCQliU2Nyb2xsQ2hhbmdlZCA9IHRydWU7CgkJCX0KCQl9Cgl9CgllbHNlCgl7CgkJaWYgKG1fcENvbnRlbnRzQmFyLT5Jc1Zpc2libGUoKSkKCQl7CgkJCW1fcENvbnRlbnRzQmFyLT5TZXRWaXNpYmxlKGZhbHNlKTsKCQkJbV9wQ29udGVudHNCYXItPkludmFsaWRhdGVSZWN0KE5VTEwpOwoKCQkJYlNjcm9sbENoYW5nZWQgPSB0cnVlOwoJCX0KCX0KCglpZiAoYlNjcm9sbENoYW5nZWQpCgl7CgkJQ1BERl9SZWN0IHJjTm90ZSA9IEdldENsaWVudFJlY3QoKTsKCQlDUERGX1JlY3QgcmNDb250ZW50cyA9IG1fcENvbnRlbnRzLT5HZXRXaW5kb3dSZWN0KCk7CgkJcmNDb250ZW50cy5yaWdodCA9IHJjTm90ZS5yaWdodCAtIDMuMGY7CgkJaWYgKG1fcENvbnRlbnRzQmFyLT5Jc1Zpc2libGUoKSkKCQkJcmNDb250ZW50cy5yaWdodCAtPSBQV0xfU0NST0xMQkFSX1dJRFRIOwoJCW1fcENvbnRlbnRzLT5Nb3ZlKHJjQ29udGVudHMsIHRydWUsIHRydWUpOwoJCW1fcENvbnRlbnRzLT5TZXRTY3JvbGxQb3MoQ1BERl9Qb2ludCgwLjBmLDAuMGYpKTsKCQltX3BDb250ZW50cy0+SW52YWxpZGF0ZVJlY3QoTlVMTCk7Cgl9CgoJcmV0dXJuIGJTY3JvbGxDaGFuZ2VkOwp9Cgpib29sIENQV0xfTm90ZTo6U2Nyb2xsQmFyU2hvdWxkVmlzaWJsZSgpCnsKCUNQREZfUmVjdCByY0NvbnRlbnRzRmFjdCA9IG1fcENvbnRlbnRzLT5HZXRTY3JvbGxBcmVhKCk7CglDUERGX1JlY3QgcmNDb250ZW50c0NsaWVudCA9IG1fcENvbnRlbnRzLT5HZXRDbGllbnRSZWN0KCk7CgoJcmV0dXJuIHJjQ29udGVudHNGYWN0LkhlaWdodCgpID4gcmNDb250ZW50c0NsaWVudC5IZWlnaHQoKTsKfQoKdm9pZCBDUFdMX05vdGU6OlNldE9wdGlvbnNUZXh0KGNvbnN0IENGWF9XaWRlU3RyaW5nJiBzVGV4dCkKewoJaWYgKG1fcE9wdGlvbnMpCgkJbV9wT3B0aW9ucy0+U2V0VGV4dChzVGV4dCk7CgoJUmVQb3NOb3RlQ2hpbGRyZW4oKTsKfQoKdm9pZCBDUFdMX05vdGU6OlJlUG9zTm90ZUNoaWxkcmVuKCkKewoJaWYgKG1fYlJlc2l6aW5nKSByZXR1cm47CgoJbV9iUmVzaXppbmcgPSB0cnVlOwoKCWlmIChJc1ZhbGlkKCkpCgl7CgkJQVNTRVJUKG1fcFN1YmplY3QgIT0gTlVMTCk7CgkJQVNTRVJUKG1fcERhdGVUaW1lICE9IE5VTEwpOwoJCUFTU0VSVChtX3BDb250ZW50cyAhPSBOVUxMKTsKCQlBU1NFUlQobV9wQXV0aG9yICE9IE5VTEwpOwoJCUFTU0VSVChtX3BDbG9zZUJveCAhPSBOVUxMKTsKCQlBU1NFUlQobV9wSWNvbiAhPSBOVUxMKTsKCQlBU1NFUlQobV9wTEJCb3ggIT0gTlVMTCk7CgkJQVNTRVJUKG1fcFJCQm94ICE9IE5VTEwpOwoJCUFTU0VSVChtX3BDb250ZW50c0JhciAhPSBOVUxMKTsKCQlBU1NFUlQobV9wT3B0aW9ucyAhPSBOVUxMKTsKCgkJQ1BERl9SZWN0IHJjQ2xpZW50ID0gR2V0Q2xpZW50UmVjdCgpOwoKCQlDUERGX1JlY3QgcmNJY29uID0gcmNDbGllbnQ7CgkJcmNJY29uLnRvcCAtPSAyLjBmOwoJCXJjSWNvbi5yaWdodCA9IHJjSWNvbi5sZWZ0ICsgMTQuMGY7CgkJcmNJY29uLmJvdHRvbSA9IHJjSWNvbi50b3AgLSAxNC4wZjsKCQlyY0ljb24uTm9ybWFsaXplKCk7CgkJbV9wSWNvbi0+TW92ZShyY0ljb24sIHRydWUsIGZhbHNlKTsKCQltX3BJY29uLT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNJY29uKSk7CgoJCUNQREZfUmVjdCByY0Nsb3NlQm94ID0gcmNDbGllbnQ7CgkJcmNDbG9zZUJveC5yaWdodCAtPSAxLjBmOwoJCXJjQ2xvc2VCb3gudG9wIC09IDEuMGY7CgkJcmNDbG9zZUJveC5sZWZ0ID0gcmNDbG9zZUJveC5yaWdodCAtIDE0LjBmOwoJCXJjQ2xvc2VCb3guYm90dG9tID0gcmNDbG9zZUJveC50b3AgLSAxNC4wZjsKCQlyY0Nsb3NlQm94Lk5vcm1hbGl6ZSgpOwoJCW1fcENsb3NlQm94LT5Nb3ZlKHJjQ2xvc2VCb3gsIHRydWUsIGZhbHNlKTsKCQltX3BDbG9zZUJveC0+U2V0VmlzaWJsZShDUFdMX1V0aWxzOjpDb250YWluc1JlY3QocmNDbGllbnQsIHJjQ2xvc2VCb3gpKTsKCgkJQ1BERl9SZWN0IHJjRGF0ZSA9IHJjQ2xpZW50OwoJCXJjRGF0ZS5yaWdodCA9IHJjQ2xvc2VCb3gubGVmdCAtIFBPUFVQX0lURU1fVEVYVF9JTkRFTlQ7CgkJcmNEYXRlLmxlZnQgPSBQV0xfTUFYKHJjRGF0ZS5yaWdodCAtIG1fcERhdGVUaW1lLT5HZXRDb250ZW50UmVjdCgpLldpZHRoKCkgLSAxLjBmLCByY0ljb24ucmlnaHQgKyAxLjBmKTsKCQlyY0RhdGUudG9wID0gcmNDbGllbnQudG9wIC0gMi4wZjsKCQlyY0RhdGUuYm90dG9tID0gcmNEYXRlLnRvcCAtIG1fcERhdGVUaW1lLT5HZXRDb250ZW50UmVjdCgpLkhlaWdodCgpOwoJCXJjRGF0ZS5Ob3JtYWxpemUoKTsKCQltX3BEYXRlVGltZS0+TW92ZShyY0RhdGUsIHRydWUsIGZhbHNlKTsKCQltX3BEYXRlVGltZS0+U2V0VmlzaWJsZShDUFdMX1V0aWxzOjpDb250YWluc1JlY3QocmNDbGllbnQsIHJjRGF0ZSkpOwoKCQlDUERGX1JlY3QgcmNTdWJqZWN0ID0gcmNDbGllbnQ7CgkJcmNTdWJqZWN0LnRvcCA9IHJjQ2xpZW50LnRvcCAtIDIuMGY7CgkJcmNTdWJqZWN0LmxlZnQgPSByY0ljb24ucmlnaHQgKyBQT1BVUF9JVEVNX1RFWFRfSU5ERU5UOwoJCXJjU3ViamVjdC5yaWdodCA9IFBXTF9NSU4ocmNTdWJqZWN0LmxlZnQgKyBtX3BTdWJqZWN0LT5HZXRDb250ZW50UmVjdCgpLldpZHRoKCkgKyAxLjBmLCByY0RhdGUubGVmdCAtIDEuMGYpOwoJCXJjU3ViamVjdC5ib3R0b20gPSByY1N1YmplY3QudG9wIC0gbV9wU3ViamVjdC0+R2V0Q29udGVudFJlY3QoKS5IZWlnaHQoKTsKCQlyY1N1YmplY3QuTm9ybWFsaXplKCk7CgkJbV9wU3ViamVjdC0+TW92ZShyY1N1YmplY3QsIHRydWUsIGZhbHNlKTsKCQltX3BTdWJqZWN0LT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNTdWJqZWN0KSk7CgoJCUNQREZfUmVjdCByY09wdGlvbnMgPSByY0NsaWVudDsKCQlyY09wdGlvbnMubGVmdCA9IFBXTF9NQVgocmNPcHRpb25zLnJpZ2h0IC0gbV9wT3B0aW9ucy0+R2V0Q29udGVudFJlY3QoKS5XaWR0aCgpLCByY0ljb24ucmlnaHQgKyAxLjBmKTsKCQlyY09wdGlvbnMudG9wID0gcmNTdWJqZWN0LmJvdHRvbSAtIDQuMGY7CgkJcmNPcHRpb25zLmJvdHRvbSA9IHJjT3B0aW9ucy50b3AgLSBtX3BPcHRpb25zLT5HZXRDb250ZW50UmVjdCgpLkhlaWdodCgpOwoJCXJjT3B0aW9ucy5Ob3JtYWxpemUoKTsKCQltX3BPcHRpb25zLT5Nb3ZlKHJjT3B0aW9ucywgdHJ1ZSwgZmFsc2UpOwoJCW1fcE9wdGlvbnMtPlNldFZpc2libGUoQ1BXTF9VdGlsczo6Q29udGFpbnNSZWN0KHJjQ2xpZW50LCByY09wdGlvbnMpKTsKCgkJQ1BERl9SZWN0IHJjQXV0aG9yID0gcmNDbGllbnQ7CgkJcmNBdXRob3IudG9wID0gcmNTdWJqZWN0LmJvdHRvbSAtIDQuMGY7CgkJcmNBdXRob3IubGVmdCA9IHJjU3ViamVjdC5sZWZ0OwoJCXJjQXV0aG9yLnJpZ2h0ID0gUFdMX01JTihyY1N1YmplY3QubGVmdCArIG1fcEF1dGhvci0+R2V0Q29udGVudFJlY3QoKS5XaWR0aCgpICsgMS4wZiwgcmNPcHRpb25zLmxlZnQgLSAxLjBmKTsKCQlyY0F1dGhvci5ib3R0b20gPSByY0F1dGhvci50b3AgLSBtX3BBdXRob3ItPkdldENvbnRlbnRSZWN0KCkuSGVpZ2h0KCk7CgkJcmNBdXRob3IuTm9ybWFsaXplKCk7CgkJbV9wQXV0aG9yLT5Nb3ZlKHJjQXV0aG9yLCB0cnVlLCBmYWxzZSk7CgkJbV9wQXV0aG9yLT5TZXRWaXNpYmxlKENQV0xfVXRpbHM6OkNvbnRhaW5zUmVjdChyY0NsaWVudCwgcmNBdXRob3IpKTsKCgkJQ1BERl9SZWN0IHJjTEJCb3ggPSByY0NsaWVudDsKCQlyY0xCQm94LnRvcCA9IHJjTEJCb3guYm90dG9tICsgNy4wZjsKCQlyY0xCQm94LnJpZ2h0ID0gcmNMQkJveC5sZWZ0ICsgNy4wZjsKCQlyY0xCQm94Lk5vcm1hbGl6ZSgpOwoJCW1fcExCQm94LT5Nb3ZlKHJjTEJCb3gsIHRydWUsIGZhbHNlKTsKCQltX3BMQkJveC0+U2V0VmlzaWJsZShDUFdMX1V0aWxzOjpDb250YWluc1JlY3QocmNDbGllbnQsIHJjTEJCb3gpKTsKCgkJQ1BERl9SZWN0IHJjUkJCb3ggPSByY0NsaWVudDsKCQlyY1JCQm94LnRvcCA9IHJjUkJCb3guYm90dG9tICsgNy4wZjsKCQlyY1JCQm94LmxlZnQgPSByY1JCQm94LnJpZ2h0IC0gNy4wZjsKCQlyY1JCQm94Lk5vcm1hbGl6ZSgpOwoJCW1fcFJCQm94LT5Nb3ZlKHJjUkJCb3gsIHRydWUsIGZhbHNlKTsKCQltX3BSQkJveC0+U2V0VmlzaWJsZShDUFdMX1V0aWxzOjpDb250YWluc1JlY3QocmNDbGllbnQsIHJjUkJCb3gpKTsKCgkJQ1BERl9SZWN0IHJjQ29udGVudHMgPSByY0NsaWVudDsKCQlyY0NvbnRlbnRzLnRvcCA9IHJjQXV0aG9yLmJvdHRvbSAtIFBPUFVQX0lURU1fSEVBRF9CT1RUT007CgkJcmNDb250ZW50cy5sZWZ0ICs9IDMuMGY7CgkJcmNDb250ZW50cy5yaWdodCAtPSAzLjBmOwoJCWlmIChtX3BDb250ZW50c0Jhci0+SXNWaXNpYmxlKCkpCgkJCXJjQ29udGVudHMucmlnaHQgLT0gUFdMX1NDUk9MTEJBUl9XSURUSDsKCQlyY0NvbnRlbnRzLmJvdHRvbSArPSAxNC4wZjsKCQlyY0NvbnRlbnRzLk5vcm1hbGl6ZSgpOwoJCW1fcENvbnRlbnRzLT5Nb3ZlKHJjQ29udGVudHMsIGZhbHNlLCBmYWxzZSk7CgkJbV9wQ29udGVudHMtPlNldFZpc2libGUoQ1BXTF9VdGlsczo6Q29udGFpbnNSZWN0KHJjQ2xpZW50LCByY0NvbnRlbnRzKSk7CgoJCUNQREZfUmVjdCByY0NvbnRlbnRzQmFyID0gcmNDb250ZW50czsKCQlyY0NvbnRlbnRzQmFyLnJpZ2h0ID0gcmNDbGllbnQucmlnaHQgLSAzLjBmOwoJCXJjQ29udGVudHNCYXIubGVmdCA9IHJjQ29udGVudHNCYXIucmlnaHQgLSBQV0xfU0NST0xMQkFSX1dJRFRIOwoJCXJjQ29udGVudHNCYXIuTm9ybWFsaXplKCk7CgkJbV9wQ29udGVudHNCYXItPk1vdmUocmNDb250ZW50c0JhciwgdHJ1ZSwgZmFsc2UpOwoKCQltX3JjQ2FwdGlvbiA9IHJjQ2xpZW50OwoJCW1fcmNDYXB0aW9uLmJvdHRvbSA9IHJjQ29udGVudHMudG9wOwoJfQoKCW1fYlJlc2l6aW5nID0gZmFsc2U7Cn0KCi8vMC1ub3JtYWwgLyAxLWNhcHRpb24gLyAyLWxlZnRib3R0b20gY29ybmVyIC8gMy1yaWdodGJvdHRvbSBjb3JuZXIgLyA0LWNsb3NlIC8gNS1vcHRpb25zCmludDMyX3QgQ1BXTF9Ob3RlOjpOb3RlSGl0VGVzdChjb25zdCBDUERGX1BvaW50JiBwb2ludCkgY29uc3QKewoJQVNTRVJUKG1fcFN1YmplY3QgIT0gTlVMTCk7CglBU1NFUlQobV9wRGF0ZVRpbWUgIT0gTlVMTCk7CglBU1NFUlQobV9wQ29udGVudHMgIT0gTlVMTCk7CglBU1NFUlQobV9wQXV0aG9yICE9IE5VTEwpOwoJQVNTRVJUKG1fcEljb24gIT0gTlVMTCk7CglBU1NFUlQobV9wQ29udGVudHNCYXIgIT0gTlVMTCk7CgoJQVNTRVJUKG1fcENsb3NlQm94ICE9IE5VTEwpOwoJQVNTRVJUKG1fcExCQm94ICE9IE5VTEwpOwoJQVNTRVJUKG1fcFJCQm94ICE9IE5VTEwpOwoJQVNTRVJUKG1fcE9wdGlvbnMgIT0gTlVMTCk7CgoJR2V0Q2xpZW50UmVjdCgpOwoKCWlmIChtX3BTdWJqZWN0LT5XbmRIaXRUZXN0KG1fcFN1YmplY3QtPlBhcmVudFRvQ2hpbGQocG9pbnQpKSkgcmV0dXJuIDE7CglpZiAobV9wRGF0ZVRpbWUtPlduZEhpdFRlc3QobV9wRGF0ZVRpbWUtPlBhcmVudFRvQ2hpbGQocG9pbnQpKSkgcmV0dXJuIDE7CglpZiAobV9wQXV0aG9yLT5XbmRIaXRUZXN0KG1fcEF1dGhvci0+UGFyZW50VG9DaGlsZChwb2ludCkpKSByZXR1cm4gMTsKCWlmIChtX3BJY29uLT5XbmRIaXRUZXN0KG1fcEljb24tPlBhcmVudFRvQ2hpbGQocG9pbnQpKSkgcmV0dXJuIDE7CgoJaWYgKG1fcENvbnRlbnRzLT5XbmRIaXRUZXN0KG1fcENvbnRlbnRzLT5QYXJlbnRUb0NoaWxkKHBvaW50KSkpIHJldHVybiAwOwoJaWYgKG1fcENvbnRlbnRzQmFyLT5XbmRIaXRUZXN0KG1fcENvbnRlbnRzQmFyLT5QYXJlbnRUb0NoaWxkKHBvaW50KSkpIHJldHVybiAwOwoKCWlmIChtX3BDbG9zZUJveC0+V25kSGl0VGVzdChtX3BDbG9zZUJveC0+UGFyZW50VG9DaGlsZChwb2ludCkpKSByZXR1cm4gNDsKCWlmIChtX3BMQkJveC0+V25kSGl0VGVzdChtX3BMQkJveC0+UGFyZW50VG9DaGlsZChwb2ludCkpKSByZXR1cm4gMjsKCWlmIChtX3BSQkJveC0+V25kSGl0VGVzdChtX3BSQkJveC0+UGFyZW50VG9DaGlsZChwb2ludCkpKSByZXR1cm4gMzsKCWlmIChtX3BPcHRpb25zLT5XbmRIaXRUZXN0KG1fcE9wdGlvbnMtPlBhcmVudFRvQ2hpbGQocG9pbnQpKSkgcmV0dXJuIDU7CgoJcmV0dXJuIDE7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpDcmVhdGVDaGlsZFduZChjb25zdCBQV0xfQ1JFQVRFUEFSQU0gJiBjcCkKewoJQ1BXTF9Ob3RlSXRlbTo6Q3JlYXRlQ2hpbGRXbmQoY3ApOwoKCUNQV0xfQ29sb3Igc1RleHRDb2xvcjsKCglpZiAoQ1BXTF9VdGlsczo6SXNCbGFja09yV2hpdGUoR2V0QmFja2dyb3VuZENvbG9yKCkpKQoJCXNUZXh0Q29sb3IgPSBQV0xfREVGQVVMVF9XSElURUNPTE9SOwoJZWxzZQoJCXNUZXh0Q29sb3IgPSBQV0xfREVGQVVMVF9CTEFDS0NPTE9SOwoKCW1fcEF1dGhvciA9IG5ldyBDUFdMX0xhYmVsOwoJUFdMX0NSRUFURVBBUkFNIGFjcCA9IGNwOwoJYWNwLnBQYXJlbnRXbmQgPSB0aGlzOwoJYWNwLmR3RmxhZ3MgPSBQV1NfVklTSUJMRSB8IFBXU19DSElMRCB8IFBFU19MRUZUIHwgUEVTX1RPUDsKCWFjcC5zVGV4dENvbG9yID0gc1RleHRDb2xvcjsKCW1fcEF1dGhvci0+Q3JlYXRlKGFjcCk7CgoJbV9wQ2xvc2VCb3ggPSBuZXcgQ1BXTF9Ob3RlX0Nsb3NlQm94OwoJUFdMX0NSRUFURVBBUkFNIGNjcCA9IGNwOwoJY2NwLnBQYXJlbnRXbmQgPSB0aGlzOwoJY2NwLmR3Qm9yZGVyV2lkdGggPSAyOwoJY2NwLm5Cb3JkZXJTdHlsZSA9IFBCU19CRVZFTEVEOwoJY2NwLmR3RmxhZ3MgPSBQV1NfVklTSUJMRSB8IFBXU19DSElMRCB8IFBXU19CT1JERVI7CgljY3Auc1RleHRDb2xvciA9IHNUZXh0Q29sb3I7CgltX3BDbG9zZUJveC0+Q3JlYXRlKGNjcCk7CgoJbV9wSWNvbiA9IG5ldyBDUFdMX05vdGVfSWNvbjsKCVBXTF9DUkVBVEVQQVJBTSBpY3AgPSBjcDsKCWljcC5wUGFyZW50V25kID0gdGhpczsKCWljcC5kd0ZsYWdzID0gUFdTX1ZJU0lCTEUgfCBQV1NfQ0hJTEQ7CgltX3BJY29uLT5DcmVhdGUoaWNwKTsKCgltX3BPcHRpb25zID0gbmV3IENQV0xfTm90ZV9PcHRpb25zOwoJUFdMX0NSRUFURVBBUkFNIG9jcCA9IGNwOwoJb2NwLnBQYXJlbnRXbmQgPSB0aGlzOwoJb2NwLmR3RmxhZ3MgPSBQV1NfQ0hJTEQgfCBQV1NfVklTSUJMRTsKCW9jcC5zVGV4dENvbG9yID0gc1RleHRDb2xvcjsKCW1fcE9wdGlvbnMtPkNyZWF0ZShvY3ApOwoKCW1fcExCQm94ID0gbmV3IENQV0xfTm90ZV9MQkJveDsKCVBXTF9DUkVBVEVQQVJBTSBsY3AgPSBjcDsKCWxjcC5wUGFyZW50V25kID0gdGhpczsKCWxjcC5kd0ZsYWdzID0gUFdTX1ZJU0lCTEUgfCBQV1NfQ0hJTEQ7CglsY3AuZUN1cnNvclR5cGUgPSBGWENUX05FU1c7CglsY3Auc1RleHRDb2xvciA9IHNUZXh0Q29sb3I7CgltX3BMQkJveC0+Q3JlYXRlKGxjcCk7CgoJbV9wUkJCb3ggPSBuZXcgQ1BXTF9Ob3RlX1JCQm94OwoJUFdMX0NSRUFURVBBUkFNIHJjcCA9IGNwOwoJcmNwLnBQYXJlbnRXbmQgPSB0aGlzOwoJcmNwLmR3RmxhZ3MgPSBQV1NfVklTSUJMRSB8IFBXU19DSElMRDsKCXJjcC5lQ3Vyc29yVHlwZSA9IEZYQ1RfTldTRTsKCXJjcC5zVGV4dENvbG9yID0gc1RleHRDb2xvcjsKCW1fcFJCQm94LT5DcmVhdGUocmNwKTsKCgltX3BDb250ZW50c0JhciA9IG5ldyBDUFdMX1Njcm9sbEJhcihTQlRfVlNDUk9MTCk7CglQV0xfQ1JFQVRFUEFSQU0gc2NwID0gY3A7CglzY3AucFBhcmVudFduZCA9IHRoaXM7CglzY3Auc0JhY2tncm91bmRDb2xvciA9IENQV0xfQ29sb3IoQ09MT1JUWVBFX1JHQiwgMjQwLzI1NS4wZiwgMjQwLzI1NS4wZiwgMjQwLzI1NS4wZik7CglzY3AuZHdGbGFncyA9IFBXU19DSElMRCB8IFBXU19WSVNJQkxFIHwgUFdTX0JBQ0tHUk9VTkQ7CgltX3BDb250ZW50c0Jhci0+Q3JlYXRlKHNjcCk7CgltX3BDb250ZW50c0Jhci0+U2V0Tm90aWZ5Rm9yZXZlcih0cnVlKTsKfQoKdm9pZCBDUFdMX05vdGU6OlNldFN1YmplY3ROYW1lKGNvbnN0IENGWF9XaWRlU3RyaW5nJiBzTmFtZSkKewoJQ1BXTF9Ob3RlSXRlbTo6U2V0U3ViamVjdE5hbWUoc05hbWUpOwoJUmVQb3NDaGlsZFduZCgpOwp9Cgp2b2lkIENQV0xfTm90ZTo6U2V0QXV0aG9yTmFtZShjb25zdCBDRlhfV2lkZVN0cmluZyYgc05hbWUpCnsKCWlmIChtX3BBdXRob3IpCgl7CgkJbV9wQXV0aG9yLT5TZXRUZXh0KHNOYW1lLmNfc3RyKCkpOwoJCVJlUG9zQ2hpbGRXbmQoKTsKCX0KCglpZiAoSVBXTF9Ob3RlTm90aWZ5KiBwTm90aWZ5ID0gR2V0Tm90ZU5vdGlmeSgpKQoJewoJCXBOb3RpZnktPk9uU2V0QXV0aG9yTmFtZSh0aGlzKTsKCX0KfQoKQ0ZYX1dpZGVTdHJpbmcgQ1BXTF9Ob3RlOjpHZXRBdXRob3JOYW1lKCkgY29uc3QKewoJaWYgKG1fcEF1dGhvcikKCQlyZXR1cm4gbV9wQXV0aG9yLT5HZXRUZXh0KCk7CgoJcmV0dXJuIEwiIjsKfQoKYm9vbCBDUFdMX05vdGU6Ok9uTW91c2VXaGVlbChzaG9ydCB6RGVsdGEsIGNvbnN0IENQREZfUG9pbnQgJiBwb2ludCwgRlhfRFdPUkQgbkZsYWcpCnsKCUNQREZfUG9pbnQgcHRTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsUG9zKCk7CglDUERGX1JlY3QgcmNTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsQXJlYSgpOwoJQ1BERl9SZWN0IHJjQ29udGVudHMgPSBtX3BDb250ZW50cy0+R2V0Q2xpZW50UmVjdCgpOwoKCWlmIChyY1Njcm9sbC50b3AgLSByY1Njcm9sbC5ib3R0b20gPiByY0NvbnRlbnRzLkhlaWdodCgpKQoJewoJCUNQREZfUG9pbnQgcHROZXcgPSBwdFNjcm9sbDsKCgkJaWYgKHpEZWx0YSA+IDApCgkJCXB0TmV3LnkgKz0gMzA7CgkJZWxzZQoJCQlwdE5ldy55IC09IDMwOwoKCQlpZiAocHROZXcueSA+IHJjU2Nyb2xsLnRvcCkKCQkJcHROZXcueSA9IHJjU2Nyb2xsLnRvcDsKCQlpZiAocHROZXcueSA8IHJjU2Nyb2xsLmJvdHRvbSArIHJjQ29udGVudHMuSGVpZ2h0KCkpCgkJCXB0TmV3LnkgPSByY1Njcm9sbC5ib3R0b20gKyByY0NvbnRlbnRzLkhlaWdodCgpOwoJCWlmIChwdE5ldy55IDwgcmNTY3JvbGwuYm90dG9tKQoJCQlwdE5ldy55ID0gcmNTY3JvbGwuYm90dG9tOwoKCQlpZiAocHROZXcueSAhPSBwdFNjcm9sbC55KQoJCXsKCQkJbV9wQ29udGVudHMtPk9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFUkVTRVQsIDAsIDApOwoJCQltX3BDb250ZW50cy0+T25Ob3RpZnkodGhpcywgUE5NX1NDUk9MTFdJTkRPVywgU0JUX1ZTQ1JPTEwsIChpbnRwdHJfdCkmcHROZXcueSk7CgkJCW1fcENvbnRlbnRzQmFyLT5Pbk5vdGlmeSh0aGlzLCBQTk1fU0VUU0NST0xMUE9TLCBTQlRfVlNDUk9MTCwgKGludHB0cl90KSZwdE5ldy55KTsKCgkJCXJldHVybiB0cnVlOwoJCX0KCX0KCglyZXR1cm4gZmFsc2U7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpPbk5vdGlmeShDUFdMX1duZCogcFduZCwgRlhfRFdPUkQgbXNnLCBpbnRwdHJfdCB3UGFyYW0sIGludHB0cl90IGxQYXJhbSkKewoJc3dpdGNoIChtc2cpCgl7CgljYXNlIFBOTV9OT1RFRURJVENIQU5HRUQ6CgkJewoJCQlDUERGX1JlY3QgcmNTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsQXJlYSgpOwoKCgkJCVBXTF9TQ1JPTExfSU5GTyBzSW5mbzsKCQkJc0luZm8uZkNvbnRlbnRNaW4gPSByY1Njcm9sbC5ib3R0b207CgkJCXNJbmZvLmZDb250ZW50TWF4ID0gcmNTY3JvbGwudG9wOwoJCQlzSW5mby5mUGxhdGVXaWR0aCA9IG1fcENvbnRlbnRzLT5HZXRDbGllbnRSZWN0KCkuSGVpZ2h0KCk7CgkJCXNJbmZvLmZTbWFsbFN0ZXAgPSAxMy4wZjsKCQkJc0luZm8uZkJpZ1N0ZXAgPSBzSW5mby5mUGxhdGVXaWR0aDsKCgkJCWlmIChGWFNZU19tZW1jbXAoJm1fT2xkU2Nyb2xsSW5mbywgJnNJbmZvLCBzaXplb2YoUFdMX1NDUk9MTF9JTkZPKSkgIT0gMCkKCQkJewoJCQkJYm9vbCBiU2Nyb2xsQ2hhbmdlZCA9IGZhbHNlOwoKCQkJCWlmIChsUGFyYW0gPCAzKSAvL7fA1rnLwNGtu7cgbWFudGlzOjE1NzU5CgkJCQl7CgkJCQkJYlNjcm9sbENoYW5nZWQgPSBSZXNldFNjcm9sbEJhcigpOwoJCQkJCWlmIChiU2Nyb2xsQ2hhbmdlZCkKCQkJCQl7CgkJCQkJCWxQYXJhbSsrOwoJCQkJCQltX3BDb250ZW50cy0+T25Ob3RpZnkodGhpcywgUE5NX05PVEVSRVNFVCwgMCwgMCk7CgkJCQkJCU9uTm90aWZ5KHRoaXMsIFBOTV9OT1RFRURJVENIQU5HRUQsIDAsIGxQYXJhbSk7CgkJCQkJfQoJCQkJfQoKCQkJCWlmICghYlNjcm9sbENoYW5nZWQpCgkJCQl7CgkJCQkJaWYgKG1fcENvbnRlbnRzQmFyLT5Jc1Zpc2libGUoKSkKCQkJCQl7CgkJCQkJCW1fcENvbnRlbnRzQmFyLT5Pbk5vdGlmeShwV25kLCBQTk1fU0VUU0NST0xMSU5GTywgU0JUX1ZTQ1JPTEwsIChpbnRwdHJfdCkmc0luZm8pOwoJCQkJCQltX09sZFNjcm9sbEluZm8gPSBzSW5mbzsKCgkJCQkJCUNQREZfUG9pbnQgcHRTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsUG9zKCk7CgkJCQkJCUNQREZfUG9pbnQgcHRPbGQgPSBwdFNjcm9sbDsKCgkJCQkJCWlmIChwdFNjcm9sbC55ID4gc0luZm8uZkNvbnRlbnRNYXgpCgkJCQkJCQlwdFNjcm9sbC55ID0gc0luZm8uZkNvbnRlbnRNYXg7CgkJCQkJCWlmIChwdFNjcm9sbC55IDwgc0luZm8uZkNvbnRlbnRNaW4gKyBzSW5mby5mUGxhdGVXaWR0aCkKCQkJCQkJCXB0U2Nyb2xsLnkgPSBzSW5mby5mQ29udGVudE1pbiArIHNJbmZvLmZQbGF0ZVdpZHRoOwoJCQkJCQlpZiAocHRTY3JvbGwueSA8IHNJbmZvLmZDb250ZW50TWluKQoJCQkJCQkJcHRTY3JvbGwueSA9IHNJbmZvLmZDb250ZW50TWluOwoKCQkJCQkJaWYgKHB0T2xkLnkgIT0gcHRTY3JvbGwueSkKCQkJCQkJewoJCQkJCQkJbV9wQ29udGVudHNCYXItPk9uTm90aWZ5KHRoaXMsIFBOTV9TRVRTQ1JPTExQT1MsIFNCVF9WU0NST0xMLCAoaW50cHRyX3QpJnB0U2Nyb2xsLnkpOwoJCQkJCQkJbV9wQ29udGVudHNCYXItPkludmFsaWRhdGVSZWN0KE5VTEwpOwoJCQkJCQkJbV9wQ29udGVudHMtPk9uTm90aWZ5KHRoaXMsIFBOTV9TQ1JPTExXSU5ET1csIFNCVF9WU0NST0xMLCAoaW50cHRyX3QpJnB0U2Nyb2xsLnkpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoKCQltX3BDb250ZW50cy0+SW52YWxpZGF0ZVJlY3QoTlVMTCk7CgoJCXJldHVybjsKCWNhc2UgUE5NX1NDUk9MTFdJTkRPVzoKCQlpZiAobV9wQ29udGVudHMpCgkJCW1fcENvbnRlbnRzLT5Pbk5vdGlmeShwV25kLCBtc2csIHdQYXJhbSwgbFBhcmFtKTsKCQlyZXR1cm47CgljYXNlIFBOTV9TRVRTQ1JPTExQT1M6CgkJaWYgKG1fcENvbnRlbnRzQmFyKQoJCQltX3BDb250ZW50c0Jhci0+T25Ob3RpZnkocFduZCxQTk1fU0VUU0NST0xMUE9TLHdQYXJhbSxsUGFyYW0pOwoJCXJldHVybjsKCX0KCglpZiAobXNnID09IFBOTV9TRVRDQVJFVElORk8gJiYgSXNWYWxpZCgpKQoJewoJCWlmIChQV0xfQ0FSRVRfSU5GTyAqIHBJbmZvID0gKFBXTF9DQVJFVF9JTkZPKil3UGFyYW0pCgkJewoJCQlpZiAobV9wQ29udGVudHMpCgkJCXsKCQkJCUNQREZfUmVjdCByY0NsaWVudCA9IG1fcENvbnRlbnRzLT5HZXRDbGllbnRSZWN0KCk7CgkJCQlpZiAocEluZm8tPnB0SGVhZC55ID4gcmNDbGllbnQudG9wKQoJCQkJewoJCQkJCUNQREZfUG9pbnQgcHQgPSBtX3BDb250ZW50cy0+T3V0VG9JbihwSW5mby0+cHRIZWFkKTsKCQkJCQltX3BDb250ZW50cy0+T25Ob3RpZnkodGhpcywgUE5NX1NDUk9MTFdJTkRPVywgU0JUX1ZTQ1JPTEwsIChpbnRwdHJfdCkmcHQueSk7CgoJCQkJCUNQREZfUG9pbnQgcHRTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsUG9zKCk7CgkJCQkJbV9wQ29udGVudHNCYXItPk9uTm90aWZ5KHRoaXMsIFBOTV9TRVRTQ1JPTExQT1MsIFNCVF9WU0NST0xMLCAoaW50cHRyX3QpJnB0U2Nyb2xsLnkpOwoKCQkJCQlyZXR1cm47CgkJCQl9CgoJCQkJaWYgKHBJbmZvLT5wdEZvb3QueSA8IHJjQ2xpZW50LmJvdHRvbSkKCQkJCXsKCQkJCQlDUERGX1BvaW50IHB0ID0gbV9wQ29udGVudHMtPk91dFRvSW4ocEluZm8tPnB0Rm9vdCk7CgkJCQkJcHQueSArPSByY0NsaWVudC5IZWlnaHQoKTsKCQkJCQltX3BDb250ZW50cy0+T25Ob3RpZnkodGhpcywgUE5NX1NDUk9MTFdJTkRPVywgU0JUX1ZTQ1JPTEwsIChpbnRwdHJfdCkmcHQueSk7CgoJCQkJCUNQREZfUG9pbnQgcHRTY3JvbGwgPSBtX3BDb250ZW50cy0+R2V0U2Nyb2xsUG9zKCk7CgkJCQkJbV9wQ29udGVudHNCYXItPk9uTm90aWZ5KHRoaXMsIFBOTV9TRVRTQ1JPTExQT1MsIFNCVF9WU0NST0xMLCAoaW50cHRyX3QpJnB0U2Nyb2xsLnkpOwoKCQkJCQlyZXR1cm47CgkJCQl9CgkJCX0KCQl9Cgl9CgoJQ1BXTF9Ob3RlSXRlbTo6T25Ob3RpZnkocFduZCwgbXNnLCB3UGFyYW0sIGxQYXJhbSk7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpTZXRCa0NvbG9yKGNvbnN0IENQV0xfQ29sb3ImIGNvbG9yKQp7CglDUFdMX05vdGVJdGVtOjpTZXRCa0NvbG9yKGNvbG9yKTsKCglDUFdMX0NvbG9yIHNCSyA9IGNvbG9yOwoJQ1BXTF9Db2xvciBzVGV4dENvbG9yOwoJaWYgKENQV0xfVXRpbHM6OklzQmxhY2tPcldoaXRlKHNCSykpCgkJc1RleHRDb2xvciA9IFBXTF9ERUZBVUxUX1dISVRFQ09MT1I7CgllbHNlCgkJc1RleHRDb2xvciA9IFBXTF9ERUZBVUxUX0JMQUNLQ09MT1I7CgoJaWYgKG1fcENsb3NlQm94KQoJCW1fcENsb3NlQm94LT5TZXRUZXh0Q29sb3Ioc1RleHRDb2xvcik7CglpZiAobV9wQXV0aG9yKQoJCW1fcEF1dGhvci0+U2V0VGV4dENvbG9yKHNUZXh0Q29sb3IpOwoJaWYgKG1fcE9wdGlvbnMpCgkJbV9wT3B0aW9ucy0+U2V0VGV4dENvbG9yKHNUZXh0Q29sb3IpOwoJaWYgKG1fcExCQm94KQoJCW1fcExCQm94LT5TZXRUZXh0Q29sb3Ioc1RleHRDb2xvcik7CglpZiAobV9wUkJCb3gpCgkJbV9wUkJCb3gtPlNldFRleHRDb2xvcihzVGV4dENvbG9yKTsKfQoKYm9vbAlDUFdMX05vdGU6Ok9uTEJ1dHRvbkRvd24oY29uc3QgQ1BERl9Qb2ludCYgcG9pbnQsIEZYX0RXT1JEIG5GbGFnKQp7CglpZiAobV9wT3B0aW9ucy0+V25kSGl0VGVzdChtX3BPcHRpb25zLT5QYXJlbnRUb0NoaWxkKHBvaW50KSkpCgl7CgkJaWYgKElQV0xfTm90ZU5vdGlmeSogcE5vdGlmeSA9IEdldE5vdGVOb3RpZnkoKSkKCQl7CgkJCWludDMyX3QgeCwgeTsKCQkJUFdMdG9XbmQocG9pbnQsIHgsIHkpOwoJCQlpZiAoSUZYX1N5c3RlbUhhbmRsZXIqIHBTSCA9IEdldFN5c3RlbUhhbmRsZXIoKSkKCQkJCXBTSC0+Q2xpZW50VG9TY3JlZW4oR2V0QXR0YWNoZWRIV25kKCksIHgsIHkpOwoJCQlLaWxsRm9jdXMoKTsKCQkJcE5vdGlmeS0+T25Qb3B1cE1lbnUoeCwgeSk7CgoJCQlyZXR1cm4gdHJ1ZTsKCQl9Cgl9CgoJcmV0dXJuIENQV0xfV25kOjpPbkxCdXR0b25Eb3duKHBvaW50LG5GbGFnKTsKfQoKYm9vbAlDUFdMX05vdGU6Ok9uUkJ1dHRvblVwKGNvbnN0IENQREZfUG9pbnQgJiBwb2ludCwgRlhfRFdPUkQgbkZsYWcpCnsKCXJldHVybiBDUFdMX1duZDo6T25SQnV0dG9uVXAocG9pbnQsbkZsYWcpOwp9Cgpjb25zdCBDUFdMX05vdGUqIENQV0xfTm90ZTo6R2V0Tm90ZSgpIGNvbnN0CnsKCXJldHVybiB0aGlzOwp9CgpJUFdMX05vdGVOb3RpZnkqIENQV0xfTm90ZTo6R2V0Tm90ZU5vdGlmeSgpIGNvbnN0CnsKCWlmIChtX2JFbmFsYmxlTm90aWZ5KQoJCXJldHVybiBtX3BOb3RlTm90aWZ5OwoKCXJldHVybiBOVUxMOwp9Cgp2b2lkIENQV0xfTm90ZTo6U2V0SWNvblR5cGUoaW50MzJfdCBuVHlwZSkKewoJaWYgKG1fcEljb24pCgkJbV9wSWNvbi0+U2V0SWNvblR5cGUoblR5cGUpOwp9Cgp2b2lkIENQV0xfTm90ZTo6RW5hYmxlTW9kaWZ5KGJvb2wgYkVuYWJsZWQpCnsKCW1fcENvbnRlbnRzLT5FbmFibGVNb2RpZnkoYkVuYWJsZWQpOwp9Cgp2b2lkIENQV0xfTm90ZTo6RW5hYmxlUmVhZChib29sIGJFbmFibGVkKQp7CgltX3BDb250ZW50cy0+RW5hYmxlUmVhZChiRW5hYmxlZCk7Cn0KCkNGWF9XaWRlU3RyaW5nIENQV0xfTm90ZTo6R2V0UmVwbHlTdHJpbmcoKSBjb25zdAp7CglyZXR1cm4gbV9zUmVwbHlTdHJpbmc7Cn0KCnZvaWQgQ1BXTF9Ob3RlOjpTZXRSZXBseVN0cmluZyhjb25zdCBDRlhfV2lkZVN0cmluZyYgc3RyaW5nKQp7CgltX3NSZXBseVN0cmluZyA9IHN0cmluZzsKfQoK