LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqIAogKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lCiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZQogKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvbgogKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlCiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUKICogIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZQogKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqIAogKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKiAKICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLAogKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbgogKiAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkKICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlCiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnMKICogdW5kZXIgdGhlIExpY2Vuc2UuCiAqIAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCgoKLy8gTUFSS0VSKHVwZGF0ZV9wcmVjb21wLnB5KTogYXV0b2dlbiBpbmNsdWRlIHN0YXRlbWVudCwgZG8gbm90IHJlbW92ZQojaW5jbHVkZSAicHJlY29tcGlsZWRfc2QuaHh4IgoKI2luY2x1ZGUgIkVkaXRXaW5kb3cuaHh4IgoKI2luY2x1ZGUgInNkbW9kLmh4eCIKI2luY2x1ZGUgPGkxOG5wb29sL21zbGFuZ2lkLmh4eD4KI2luY2x1ZGUgPGNvbS9zdW4vc3Rhci9pMThuL1NjcmlwdFR5cGUuaHBwPgojaW5jbHVkZSA8ZWRpdGVuZy9lZGl0ZW5nLmh4eD4KI2luY2x1ZGUgPGVkaXRlbmcvZWRpdHZpZXcuaHh4PgojaW5jbHVkZSA8dmNsL3NjcmJhci5oeHg+CiNpbmNsdWRlIDxlZGl0ZW5nL2VlaXRlbS5oeHg+CiNpbmNsdWRlICJzZHJlc2lkLmh4eCIKI2luY2x1ZGUgPHN2bC9pdGVtcG9vbC5oeHg+CiNpbmNsdWRlIDxlZGl0ZW5nL2ZoZ3RpdGVtLmh4eD4KI2luY2x1ZGUgPHZvcy9tdXRleC5oeHg+CiNpbmNsdWRlIDx2Y2wvc3ZhcHAuaHh4PgojaW5jbHVkZSA8dW5vdG9vbHMvbGluZ3Vwcm9wcy5oeHg+CiNpbmNsdWRlIDx1bm90b29scy9saW5ndWNmZy5oeHg+CiNpbmNsdWRlIDxlZGl0ZW5nL2ZvbnRpdGVtLmh4eD4KI2luY2x1ZGUgPGVkaXRlbmcvZWRpdHN0YXQuaHh4PgoKI2RlZmluZSBTQ1JPTExfTElORSAJCTI0Cgp1c2luZyBuYW1lc3BhY2UgY29tOjpzdW46OnN0YXI6OmFjY2Vzc2liaWxpdHk7CnVzaW5nIG5hbWVzcGFjZSBjb206OnN1bjo6c3RhcjsKdXNpbmcgbmFtZXNwYWNlIGNvbTo6c3VuOjpzdGFyOjp1bm87CgpuYW1lc3BhY2Ugc2QgeyBuYW1lc3BhY2Ugbm90ZXMgewoKRWRpdFdpbmRvdzo6RWRpdFdpbmRvdyAoV2luZG93KiBwUGFyZW50V2luZG93LCBTZnhJdGVtUG9vbCogcEl0ZW1Qb29sKQogICAgOiBXaW5kb3cgKHBQYXJlbnRXaW5kb3csIFdpbkJpdHMoKSksCiAgICAgIERyb3BUYXJnZXRIZWxwZXIodGhpcyksCiAgICAgIG1wRWRpdFZpZXcoTlVMTCksCiAgICAgIG1wRWRpdEVuZ2luZShOVUxMKSwKICAgICAgbXBIb3Jpem9udGFsU2Nyb2xsQmFyKE5VTEwpLAogICAgICBtcFZlcnRpY2FsU2Nyb2xsQmFyKE5VTEwpLAogICAgICBtcFNjcm9sbEJveChOVUxMKQp7CglTZXRNYXBNb2RlKE1BUF9QSVhFTCk7CgogICAgLy8gY29tcGFyZSBEYXRhQ2hhbmdlZAoJU2V0QmFja2dyb3VuZCAoR2V0U2V0dGluZ3MoKS5HZXRTdHlsZVNldHRpbmdzKCkuR2V0V2luZG93Q29sb3IoKSk7CgoJbWFNb2RpZnlUaW1lci5TZXRUaW1lb3V0KDIwMDApOwoJbWFNb2RpZnlUaW1lci5TdGFydCgpOwoKCW1hQ3Vyc29yTW92ZVRpbWVyLlNldFRpbWVvdXQoNTAwKTsKCiAgICBDcmVhdGVFZGl0VmlldygpOwoKICAgIFN2eEZvbnRIZWlnaHRJdGVtIGFJdGVtIChHZXRGb250KCkuR2V0U2l6ZSgpLkhlaWdodCgpLCAxMDAsCiAgICAgICAgRUVfQ0hBUl9GT05USEVJR0hUKTsKICAgIHBJdGVtUG9vbC0+U2V0UG9vbERlZmF1bHRJdGVtIChhSXRlbSk7CiAgICBhSXRlbS5TZXRXaGljaChFRV9DSEFSX0ZPTlRIRUlHSFRfQ0pLKTsKICAgIHBJdGVtUG9vbC0+U2V0UG9vbERlZmF1bHRJdGVtIChhSXRlbSk7CiAgICBhSXRlbS5TZXRXaGljaChFRV9DSEFSX0ZPTlRIRUlHSFRfQ1RMKTsKICAgIHBJdGVtUG9vbC0+U2V0UG9vbERlZmF1bHRJdGVtIChhSXRlbSk7CgogICAgSW5zZXJ0VGV4dCAoVW5pU3RyaW5nOjpDcmVhdGVGcm9tQXNjaWkoIkVkaXRXaW5kb3cgY3JlYXRlZCBhbmQgcmVhZHkuXG4iKSk7Cn0KCgpFZGl0V2luZG93Ojp+RWRpdFdpbmRvdyAodm9pZCkKewoJbWFDdXJzb3JNb3ZlVGltZXIuU3RvcCgpOwoJbWFNb2RpZnlUaW1lci5TdG9wKCk7CgogICAgaWYgKG1wRWRpdFZpZXcgIT0gTlVMTCkKICAgIHsKICAgICAgICBFZGl0RW5naW5lICpwRWRpdEVuZ2luZSA9IG1wRWRpdFZpZXctPkdldEVkaXRFbmdpbmUoKTsKICAgICAgICBpZiAocEVkaXRFbmdpbmUpCiAgICAgICAgewogICAgICAgICAgICBwRWRpdEVuZ2luZS0+U2V0U3RhdHVzRXZlbnRIZGwoTGluaygpKTsKICAgICAgICAgICAgcEVkaXRFbmdpbmUtPlJlbW92ZVZpZXcgKG1wRWRpdFZpZXcpOwogICAgICAgIH0KICAgIH0KCWRlbGV0ZSBtcEVkaXRWaWV3OwoJZGVsZXRlIG1wSG9yaXpvbnRhbFNjcm9sbEJhcjsKCWRlbGV0ZSBtcFZlcnRpY2FsU2Nyb2xsQmFyOwoJZGVsZXRlIG1wU2Nyb2xsQm94OwoKfQoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKCnZvaWQgU21HZXRMZWZ0U2VsZWN0aW9uUGFydChjb25zdCBFU2VsZWN0aW9uIGFTZWwsCgkJCQkJCQlzYWxfdUludDE2ICZuUGFyYSwgc2FsX3VJbnQxNiAmblBvcykKCS8vIHJldHVybnMgcGFyYWdyYXBoIG51bWJlciBhbmQgcG9zaXRpb24gb2YgdGhlIHNlbGVjdGlvbnMgbGVmdCBwYXJ0CnsKCS8vIGNvbXBhcmUgc3RhcnQgYW5kIGVuZCBvZiBzZWxlY3Rpb24gYW5kIHVzZSB0aGUgb25lIHRoYXQgY29tZXMgZmlyc3QKCWlmICgKICAgICAgICAoYVNlbC5uU3RhcnRQYXJhIDwgIGFTZWwubkVuZFBhcmEpIHx8CiAgICAgICAgKGFTZWwublN0YXJ0UGFyYSA9PSBhU2VsLm5FbmRQYXJhICYmIGFTZWwublN0YXJ0UG9zIDwgYVNlbC5uRW5kUG9zKQogICAgICAgKQoJewluUGFyYSA9IGFTZWwublN0YXJ0UGFyYTsKCQluUG9zICA9IGFTZWwublN0YXJ0UG9zOwoJfQoJZWxzZQoJewluUGFyYSA9IGFTZWwubkVuZFBhcmE7CgkJblBvcyAgPSBhU2VsLm5FbmRQb3M7Cgl9Cn0KCgoKCkVkaXRFbmdpbmUgKiBFZGl0V2luZG93OjpHZXRFZGl0RW5naW5lICh2b2lkKQp7CiAgICBpZiAobXBFZGl0RW5naW5lID09IE5VTEwpCiAgICAgICAgbXBFZGl0RW5naW5lID0gQ3JlYXRlRWRpdEVuZ2luZSAoKTsKICAgIHJldHVybiBtcEVkaXRFbmdpbmU7Cn0KCgoKCkVkaXRFbmdpbmUqIEVkaXRXaW5kb3c6OkNyZWF0ZUVkaXRFbmdpbmUgKHZvaWQpCnsKICAgIEVkaXRFbmdpbmUqIHBFZGl0RW5naW5lID0gbXBFZGl0RW5naW5lOwoJaWYgKHBFZGl0RW5naW5lID09IE5VTEwpCgl7CgkJbXBFZGl0RW5naW5lSXRlbVBvb2wgPSBFZGl0RW5naW5lOjpDcmVhdGVQb29sKCk7CgogICAgICAgIC8vCiAgICAgICAgLy8gc2V0IGZvbnRzIHRvIGJlIHVzZWQKICAgICAgICAvLwogICAgICAgIFN2dExpbmd1T3B0aW9ucyBhT3B0OwogICAgICAgIFN2dExpbmd1Q29uZmlnKCkuR2V0T3B0aW9ucyggYU9wdCApOwogICAgICAgIC8vCiAgICAgICAgc3RydWN0IEZvbnREdGEgewogICAgICAgICAgICBzYWxfSW50MTYgICAgICAgbkZhbGxiYWNrTGFuZzsKICAgICAgICAgICAgc2FsX0ludDE2ICAgICAgIG5MYW5nOwogICAgICAgICAgICBzYWxfdUludDE2ICAgICAgbkZvbnRUeXBlOwogICAgICAgICAgICBzYWxfdUludDE2ICAgICAgbkZvbnRJbmZvSWQ7CiAgICAgICAgICAgIH0gYVRhYmxlWzNdID0KICAgICAgICB7CiAgICAgICAgICAgIC8vIGluZm8gdG8gZ2V0IHdlc3Rlcm4gZm9udCB0byBiZSB1c2VkCiAgICAgICAgICAgIHsgICBMQU5HVUFHRV9FTkdMSVNIX1VTLCAgICBMQU5HVUFHRV9OT05FLAogICAgICAgICAgICAgICAgREVGQVVMVEZPTlRfU0VSSUYsICAgICAgRUVfQ0hBUl9GT05USU5GTyB9LAogICAgICAgICAgICAvLyBpbmZvIHRvIGdldCBDSksgZm9udCB0byBiZSB1c2VkCiAgICAgICAgICAgIHsgICBMQU5HVUFHRV9KQVBBTkVTRSwgICAgICBMQU5HVUFHRV9OT05FLAogICAgICAgICAgICAgICAgREVGQVVMVEZPTlRfQ0pLX1RFWFQsICAgRUVfQ0hBUl9GT05USU5GT19DSksgfSwKICAgICAgICAgICAgLy8gaW5mbyB0byBnZXQgQ1RMIGZvbnQgdG8gYmUgdXNlZAogICAgICAgICAgICB7ICAgTEFOR1VBR0VfQVJBQklDX1NBVURJX0FSQUJJQSwgIExBTkdVQUdFX05PTkUsCiAgICAgICAgICAgICAgICBERUZBVUxURk9OVF9DVExfVEVYVCwgICBFRV9DSEFSX0ZPTlRJTkZPX0NUTCB9CiAgICAgICAgfTsKICAgICAgICBhVGFibGVbMF0ubkxhbmcgPSBNc0xhbmdJZDo6cmVzb2x2ZVN5c3RlbUxhbmd1YWdlQnlTY3JpcHRUeXBlKGFPcHQubkRlZmF1bHRMYW5ndWFnZSwgOjpjb206OnN1bjo6c3Rhcjo6aTE4bjo6U2NyaXB0VHlwZTo6TEFUSU4pOwogICAgICAgIGFUYWJsZVsxXS5uTGFuZyA9IE1zTGFuZ0lkOjpyZXNvbHZlU3lzdGVtTGFuZ3VhZ2VCeVNjcmlwdFR5cGUoYU9wdC5uRGVmYXVsdExhbmd1YWdlX0NKSywgOjpjb206OnN1bjo6c3Rhcjo6aTE4bjo6U2NyaXB0VHlwZTo6QVNJQU4pOwogICAgICAgIGFUYWJsZVsyXS5uTGFuZyA9IE1zTGFuZ0lkOjpyZXNvbHZlU3lzdGVtTGFuZ3VhZ2VCeVNjcmlwdFR5cGUoYU9wdC5uRGVmYXVsdExhbmd1YWdlX0NUTCwgOjpjb206OnN1bjo6c3Rhcjo6aTE4bjo6U2NyaXB0VHlwZTo6Q09NUExFWCk7CiAgICAgICAgLy8KICAgICAgICBmb3IgKGludCBpID0gMDsgIGkgPCAzOyAgKytpKQogICAgICAgIHsKICAgICAgICAgICAgY29uc3QgRm9udER0YSAmckZudER0YSA9IGFUYWJsZVtpXTsKICAgICAgICAgICAgTGFuZ3VhZ2VUeXBlIG5MYW5nID0gKExBTkdVQUdFX05PTkUgPT0gckZudER0YS5uTGFuZykgPwogICAgICAgICAgICAgICAgckZudER0YS5uRmFsbGJhY2tMYW5nIDogckZudER0YS5uTGFuZzsKICAgICAgICAgICAgRm9udCBhRm9udCA9IEFwcGxpY2F0aW9uOjpHZXREZWZhdWx0RGV2aWNlKCktPkdldERlZmF1bHRGb250KAogICAgICAgICAgICAgICAgckZudER0YS5uRm9udFR5cGUsIG5MYW5nLCBERUZBVUxURk9OVF9GTEFHU19PTkxZT05FKTsKICAgICAgICAgICAgbXBFZGl0RW5naW5lSXRlbVBvb2wtPlNldFBvb2xEZWZhdWx0SXRlbSgKICAgICAgICAgICAgICAgIFN2eEZvbnRJdGVtKAogICAgICAgICAgICAgICAgICAgIGFGb250LkdldEZhbWlseSgpLAogICAgICAgICAgICAgICAgICAgIGFGb250LkdldE5hbWUoKSwKICAgICAgICAgICAgICAgICAgICBhRm9udC5HZXRTdHlsZU5hbWUoKSwKICAgICAgICAgICAgICAgICAgICBhRm9udC5HZXRQaXRjaCgpLAogICAgICAgICAgICAgICAgICAgIGFGb250LkdldENoYXJTZXQoKSwKICAgICAgICAgICAgICAgICAgICByRm50RHRhLm5Gb250SW5mb0lkKSk7CiAgICAgICAgfQoKICAgICAgICAvLyBzZXQgZm9udCBoZWlnaHRzCgkJU3Z4Rm9udEhlaWdodEl0ZW0gYUZvbnRIZWlndCgKICAgICAgICAgICAgQXBwbGljYXRpb246OkdldERlZmF1bHREZXZpY2UoKS0+TG9naWNUb1BpeGVsKAogICAgICAgICAgICAgICAgU2l6ZSAoMCwgMTApLCBNYXBNb2RlIChNQVBfUE9JTlQpKS5IZWlnaHQoKSwgMTAwLAogICAgICAgICAgICBFRV9DSEFSX0ZPTlRIRUlHSFQgKTsKCQltcEVkaXRFbmdpbmVJdGVtUG9vbC0+U2V0UG9vbERlZmF1bHRJdGVtKCBhRm9udEhlaWd0KTsKCQlhRm9udEhlaWd0LlNldFdoaWNoIChFRV9DSEFSX0ZPTlRIRUlHSFRfQ0pLKTsKCQltcEVkaXRFbmdpbmVJdGVtUG9vbC0+U2V0UG9vbERlZmF1bHRJdGVtKCBhRm9udEhlaWd0KTsKCQlhRm9udEhlaWd0LlNldFdoaWNoIChFRV9DSEFSX0ZPTlRIRUlHSFRfQ1RMKTsKCQltcEVkaXRFbmdpbmVJdGVtUG9vbC0+U2V0UG9vbERlZmF1bHRJdGVtKCBhRm9udEhlaWd0KTsKCgkJcEVkaXRFbmdpbmUgPSBuZXcgRWRpdEVuZ2luZSAobXBFZGl0RW5naW5lSXRlbVBvb2wpOwoKCQlwRWRpdEVuZ2luZS0+RW5hYmxlVW5kbyAodHJ1ZSk7CgkJcEVkaXRFbmdpbmUtPlNldERlZlRhYiAoc2FsX3VJbnQxNigKCQkJQXBwbGljYXRpb246OkdldERlZmF1bHREZXZpY2UoKS0+R2V0VGV4dFdpZHRoKAogICAgICAgICAgICAgICAgVW5pU3RyaW5nOjpDcmVhdGVGcm9tQXNjaWkoIlhYWFgiKSkpKTsKCgkJcEVkaXRFbmdpbmUtPlNldENvbnRyb2xXb3JkKAoJCQkJKHBFZGl0RW5naW5lLT5HZXRDb250cm9sV29yZCgpCiAgICAgICAgICAgICAgICAgICAgfCBFRV9DTlRSTF9BVVRPSU5ERU5USU5HKSAmCgkJCQkofkVFX0NOVFJMX1VORE9BVFRSSUJTKSAmCgkJCQkofkVFX0NOVFJMX1BBU1RFU1BFQ0lBTCkpOwoKCQlwRWRpdEVuZ2luZS0+U2V0V29yZERlbGltaXRlcnMgKAogICAgICAgICAgICBVbmlTdHJpbmc6OkNyZWF0ZUZyb21Bc2NpaSgiIC49Ky0qLygpe31bXTtcIiIpKTsKCQlwRWRpdEVuZ2luZS0+U2V0UmVmTWFwTW9kZSAoTUFQX1BJWEVMKTsKCQlwRWRpdEVuZ2luZS0+U2V0UGFwZXJTaXplIChTaXplKDgwMCwgMCkpOwoJCXBFZGl0RW5naW5lLT5FcmFzZVZpcnR1YWxEZXZpY2UoKTsKCQlwRWRpdEVuZ2luZS0+Q2xlYXJNb2RpZnlGbGFnKCk7Cgl9CgoJcmV0dXJuIHBFZGl0RW5naW5lOwp9CgoKCgp2b2lkIEVkaXRXaW5kb3c6OkRhdGFDaGFuZ2VkIChjb25zdCBEYXRhQ2hhbmdlZEV2ZW50JikKewogICAgY29uc3QgU3R5bGVTZXR0aW5ncyBhU2V0dGluZ3MgKEdldFNldHRpbmdzKCkuR2V0U3R5bGVTZXR0aW5ncygpKTsKCiAgICBTZXRCYWNrZ3JvdW5kKCBhU2V0dGluZ3MuR2V0V2luZG93Q29sb3IoKSApOwoKICAgIC8vIGVkaXQgZmllbGRzIGluIG90aGVyIEFwcGxpY2F0aW9ucyB1c2UgdGhpcyBmb250IGluc3RlYWQgb2YKICAgIC8vIHRoZSBhcHBsaWNhdGlvbiBmb250IHRodXMgd2UgdXNlIHRoaXMgb25lIHRvbwogICAgU2V0UG9pbnRGb250KCBhU2V0dGluZ3MuR2V0RmllbGRGb250KCkgKTsKICAgIEVkaXRFbmdpbmUqIHBFZGl0RW5naW5lID0gR2V0RWRpdEVuZ2luZSgpOwoKCWlmIChwRWRpdEVuZ2luZSE9TlVMTCAmJiBtcEVkaXRFbmdpbmVJdGVtUG9vbCE9TlVMTCkKCXsKICAgICAgICAvLyEKICAgICAgICAvLyEgc2VlIGFsc28gU21Eb2NTaGVsbDo6R2V0RWRpdEVuZ2luZSgpICEKICAgICAgICAvLyEKCiAgICAgICAgLy8JCXBFZGl0RW5naW5lLT5TZXREZWZUYWIoIHNhbF91SW50MTYoIEdldFRleHRXaWR0aCggQzJTKCJYWFhYIikgKSApICk7CgogICAgICAgIHNhbF91SW50MTYgYUZudEluZm9JZFszXSA9IHsKICAgICAgICAgICAgICAgIEVFX0NIQVJfRk9OVElORk8sIEVFX0NIQVJfRk9OVElORk9fQ0pLLCBFRV9DSEFSX0ZPTlRJTkZPX0NUTCB9OwogICAgICAgIGZvciAoaW50IGkgPSAwOyAgaSA8IDM7ICArK2kpCiAgICAgICAgewogICAgICAgICAgICBjb25zdCBTZnhQb29sSXRlbSAqcEl0ZW0gPSBtcEVkaXRFbmdpbmVJdGVtUG9vbC0+R2V0UG9vbERlZmF1bHRJdGVtKCAgYUZudEluZm9JZFtpXSApOwogICAgICAgICAgICBpZiggcEl0ZW0gKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBjb25zdCBTdnhGb250SXRlbSAqcEZudEl0ZW0gPSAoKGNvbnN0IFN2eEZvbnRJdGVtICopIHBJdGVtKTsKICAgICAgICAgICAgICAgIGNvbnN0IEZvbnQgJnJGbnQgPSBhU2V0dGluZ3MuR2V0RmllbGRGb250KCk7CiAgICAgICAgICAgICAgICBTdnhGb250SXRlbSBhRm50SXRlbSggckZudC5HZXRGYW1pbHkoKSwgckZudC5HZXROYW1lKCksCiAgICAgICAgICAgICAgICAgICAgICAgIHJGbnQuR2V0U3R5bGVOYW1lKCksIHJGbnQuR2V0UGl0Y2goKSwKICAgICAgICAgICAgICAgICAgICAgICAgcEZudEl0ZW0tPkdldENoYXJTZXQoKSwKICAgICAgICAgICAgICAgICAgICAgICAgYUZudEluZm9JZFtpXSApOwogICAgICAgICAgICAgICAgbXBFZGl0RW5naW5lSXRlbVBvb2wtPlNldFBvb2xEZWZhdWx0SXRlbSggYUZudEl0ZW0gKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgU3Z4Rm9udEhlaWdodEl0ZW0gYUl0ZW0oIEdldEZvbnQoKS5HZXRTaXplKCkuSGVpZ2h0KCksIDEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRUVfQ0hBUl9GT05USEVJR0hUICk7CiAgICAgICAgbXBFZGl0RW5naW5lSXRlbVBvb2wtPlNldFBvb2xEZWZhdWx0SXRlbSggYUl0ZW0gKTsKICAgICAgICBhSXRlbS5TZXRXaGljaCggRUVfQ0hBUl9GT05USEVJR0hUX0NKSyApOwogICAgICAgIG1wRWRpdEVuZ2luZUl0ZW1Qb29sLT5TZXRQb29sRGVmYXVsdEl0ZW0oIGFJdGVtICk7CiAgICAgICAgYUl0ZW0uU2V0V2hpY2goIEVFX0NIQVJfRk9OVEhFSUdIVF9DVEwgKTsKICAgICAgICBtcEVkaXRFbmdpbmVJdGVtUG9vbC0+U2V0UG9vbERlZmF1bHRJdGVtKCBhSXRlbSApOwoKCQkvLyBmb3JjZXMgbmV3IHNldHRpbmdzIHRvIGJlIHVzZWQKICAgICAgICAvLyB1bmZvcnR1bmF0ZWx5IHRoaXMgcmVzZXRzIHRoZSB3aG9sZSBlZGl0IGVuZ2luZQogICAgICAgIC8vIHRodXMgd2UgbmVlZCB0byBzYXZlIGF0IGxlYXN0IHRoZSB0ZXh0CiAgICAgICAgU3RyaW5nIGFUeHQoIHBFZGl0RW5naW5lLT5HZXRUZXh0KCBMSU5FRU5EX0xGICkgKTsKCQlwRWRpdEVuZ2luZS0+Q2xlYXIoKTsJLy8jNzc5NTcgaW5jb3JyZWN0IGZvbnQgc2l6ZQogICAgICAgIHBFZGl0RW5naW5lLT5TZXRUZXh0KCBhVHh0ICk7Cgl9CgogICAgU3RyaW5nIGFUZXh0IChtcEVkaXRFbmdpbmUtPkdldFRleHQgKExJTkVFTkRfTEYpKTsKICAgIG1wRWRpdEVuZ2luZS0+Q2xlYXIoKTsKICAgIG1wRWRpdEVuZ2luZS0+U2V0VGV4dCAoYVRleHQpOwoKCUFkanVzdFNjcm9sbEJhcnMoKTsKCVJlc2l6ZSgpOwp9CgoKCgp2b2lkIEVkaXRXaW5kb3c6OlJlc2l6ZSAodm9pZCkKewoJaWYgKCFtcEVkaXRWaWV3KQoJCUNyZWF0ZUVkaXRWaWV3KCk7CgoJaWYgKG1wRWRpdFZpZXcgIT0gTlVMTCkKCXsKCQltcEVkaXRWaWV3LT5TZXRPdXRwdXRBcmVhKEFkanVzdFNjcm9sbEJhcnMoKSk7CgkJbXBFZGl0Vmlldy0+U2hvd0N1cnNvcigpOwoKICAgICAgICBEQkdfQVNTRVJUKCBtcEVkaXRWaWV3LT5HZXRFZGl0RW5naW5lKCksICJFZGl0RW5naW5lIG1pc3NpbmciICk7CgkJY29uc3QgbG9uZyBuTWF4VmlzQXJlYVN0YXJ0ID0gbXBFZGl0Vmlldy0+R2V0RWRpdEVuZ2luZSgpLT5HZXRUZXh0SGVpZ2h0KCkgLQoJCQkJCQkJCQkgIG1wRWRpdFZpZXctPkdldE91dHB1dEFyZWEoKS5HZXRIZWlnaHQoKTsKCQlpZiAobXBFZGl0Vmlldy0+R2V0VmlzQXJlYSgpLlRvcCgpID4gbk1heFZpc0FyZWFTdGFydCkKCQl7CgkJCVJlY3RhbmdsZSBhVmlzQXJlYShtcEVkaXRWaWV3LT5HZXRWaXNBcmVhKCkgKTsKCQkJYVZpc0FyZWEuVG9wKCkgPSAobk1heFZpc0FyZWFTdGFydCA+IDAgKSA/IG5NYXhWaXNBcmVhU3RhcnQgOiAwOwoJCQlhVmlzQXJlYS5TZXRTaXplKG1wRWRpdFZpZXctPkdldE91dHB1dEFyZWEoKS5HZXRTaXplKCkpOwoJCQltcEVkaXRWaWV3LT5TZXRWaXNBcmVhKGFWaXNBcmVhKTsKCQkJbXBFZGl0Vmlldy0+U2hvd0N1cnNvcigpOwoJCX0KCQlJbml0U2Nyb2xsQmFycygpOwoJfQoJSW52YWxpZGF0ZSgpOwp9CgoKCgp2b2lkIEVkaXRXaW5kb3c6Ok1vdXNlQnV0dG9uVXAoY29uc3QgTW91c2VFdmVudCAmckV2dCkKewoJaWYgKG1wRWRpdFZpZXcgIT0gTlVMTCkKCQltcEVkaXRWaWV3LT5Nb3VzZUJ1dHRvblVwKHJFdnQpOwoJZWxzZQoJCVdpbmRvdzo6TW91c2VCdXR0b25VcCAockV2dCk7CgoJLy8gZ2dmIEZvcm11bGFDdXJzb3IgbmV1IHBvc2l0aW9uaWVyZW4KICAgIC8vCUN1cnNvck1vdmVUaW1lckhkbCgmYUN1cnNvck1vdmVUaW1lcik7Cn0KCgoKCnZvaWQgRWRpdFdpbmRvdzo6TW91c2VCdXR0b25Eb3duKGNvbnN0IE1vdXNlRXZlbnQgJnJFdnQpCnsKCWlmIChtcEVkaXRWaWV3ICE9IE5VTEwpCgkJbXBFZGl0Vmlldy0+TW91c2VCdXR0b25Eb3duKHJFdnQpOwoJZWxzZQoJCVdpbmRvdzo6TW91c2VCdXR0b25Eb3duIChyRXZ0KTsKCglHcmFiRm9jdXMoKTsKfQoKCgoKdm9pZCBFZGl0V2luZG93OjpDb21tYW5kKGNvbnN0IENvbW1hbmRFdmVudCYgckNFdnQpCnsKICAgIC8qCWlmIChyQ0V2dC5HZXRDb21tYW5kKCkgPT0gQ09NTUFORF9DT05URVhUTUVOVSkKCXsKCQlHZXRQYXJlbnQoKS0+VG9Ub3AoKTsKCiAgICAgICAgUG9pbnQgYVBvaW50ID0gckNFdnQuR2V0TW91c2VQb3NQaXhlbCgpOwoJCVBvcHVwTWVudSogcFBvcHVwTWVudSA9IG5ldyBQb3B1cE1lbnUoU21SZXNJZChSSURfQ09NTUFORE1FTlUpKTsKCiAgICAgICAgLy8gYWRkZWQgZm9yIHJlcGxhY2VhYmlsaXR5IG9mIGNvbnRleHQgbWVudXMgIzk2MDg1LCAjOTM3ODIKICAgICAgICBNZW51KiBwTWVudSA9IE5VTEw7CiAgICAgICAgOjpjb206OnN1bjo6c3Rhcjo6dWk6OkNvbnRleHRNZW51RXhlY3V0ZUV2ZW50IGFFdmVudDsKICAgICAgICBhRXZlbnQuU291cmNlV2luZG93ID0gVkNMVW5vSGVscGVyOjpHZXRJbnRlcmZhY2UoIHRoaXMgKTsKICAgICAgICBhRXZlbnQuRXhlY3V0ZVBvc2l0aW9uLlggPSBhUG9pbnQuWCgpOwogICAgICAgIGFFdmVudC5FeGVjdXRlUG9zaXRpb24uWSA9IGFQb2ludC5ZKCk7CiAgICAgICAgaWYgKCBHZXRWaWV3KCktPlRyeUNvbnRleHRNZW51SW50ZXJjZXB0aW9uKCAqcFBvcHVwTWVudSwgcE1lbnUsIGFFdmVudCApICkKICAgICAgICB7CiAgICAgICAgICAgIGlmICggcE1lbnUgKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBkZWxldGUgcFBvcHVwTWVudTsKICAgICAgICAgICAgICAgIHBQb3B1cE1lbnUgPSAoUG9wdXBNZW51KikgcE1lbnU7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHBQb3B1cE1lbnUtPlNldFNlbGVjdEhkbChMSU5LKHRoaXMsIEVkaXRXaW5kb3csIE1lbnVTZWxlY3RIZGwpKTsKCiAgICAgICAgcFBvcHVwTWVudS0+RXhlY3V0ZSggdGhpcywgYVBvaW50ICk7CgkJZGVsZXRlIHBQb3B1cE1lbnU7Cgl9CgllbHNlKi8gaWYgKG1wRWRpdFZpZXcpCgkJbXBFZGl0Vmlldy0+Q29tbWFuZCggckNFdnQgKTsKCWVsc2UKCQlXaW5kb3c6OkNvbW1hbmQgKHJDRXZ0KTsKCn0KSU1QTF9MSU5LX0lOTElORV9TVEFSVCggRWRpdFdpbmRvdywgTWVudVNlbGVjdEhkbCwgTWVudSAqLCBFTVBUWUFSRyApCnsKICAgIC8qICAgIFNtVmlld1NoZWxsICpwVmlld1NoID0gckNtZEJveC5HZXRWaWV3KCk7CglpZiAocFZpZXdTaCkKCQlwVmlld1NoLT5HZXRWaWV3RnJhbWUoKS0+R2V0RGlzcGF0Y2hlcigpLT5FeGVjdXRlKAoJCQkJU0lEX0lOU0VSVENPTU1BTkQsIFNGWF9DQUxMTU9ERV9TVEFOREFSRCwKCQkJCW5ldyBTZnhJbnQxNkl0ZW0oU0lEX0lOU0VSVENPTU1BTkQsIHBNZW51LT5HZXRDdXJJdGVtSWQoKSksIDBMKTsKKi8KCXJldHVybiAwOwp9CklNUExfTElOS19JTkxJTkVfRU5EKCBFZGl0V2luZG93LCBNZW51U2VsZWN0SGRsLCBNZW51ICosIEVNUFRZQVJHICkKCnZvaWQgRWRpdFdpbmRvdzo6S2V5SW5wdXQoY29uc3QgS2V5RXZlbnQmICkKewp9CgoKCgp2b2lkIEVkaXRXaW5kb3c6OlBhaW50KGNvbnN0IFJlY3RhbmdsZSYgclJlY3QpCnsKCWlmICghbXBFZGl0VmlldykKCQlDcmVhdGVFZGl0VmlldygpOwoJbXBFZGl0Vmlldy0+UGFpbnQoclJlY3QpOwp9CgoKCgp2b2lkIEVkaXRXaW5kb3c6OkNyZWF0ZUVkaXRWaWV3ICh2b2lkKQp7CiAgICBFZGl0RW5naW5lKiBwRWRpdEVuZ2luZSA9IEdldEVkaXRFbmdpbmUoKTsKCiAgICAvLyEgcEVkaXRFbmdpbmUgYW5kIG1wRWRpdFZpZXcgbWF5IGJlIDAuCiAgICAvLyEgRm9yIGV4YW1wbGUgd2hlbiB0aGUgcHJvZ3JhbSBpcyB1c2VkIGJ5IHRoZSBkb2N1bWVudC1jb252ZXJ0ZXIKCWlmIChtcEVkaXRWaWV3PT1OVUxMICYmIHBFZGl0RW5naW5lIT1OVUxMKQoJewoJCW1wRWRpdFZpZXcgPSBuZXcgRWRpdFZpZXcgKHBFZGl0RW5naW5lLCB0aGlzKTsKCQlwRWRpdEVuZ2luZS0+SW5zZXJ0VmlldyAobXBFZGl0Vmlldyk7CgogICAgICAgIGlmIChtcFZlcnRpY2FsU2Nyb2xsQmFyID09IE5VTEwpCiAgICAgICAgICAgIG1wVmVydGljYWxTY3JvbGxCYXIgPSBuZXcgU2Nyb2xsQmFyICgKICAgICAgICAgICAgICAgIHRoaXMsIFdpbkJpdHMoV0JfVlNDUk9MTCB8IFdCX0RSQUcpKTsKICAgICAgICBpZiAobXBIb3Jpem9udGFsU2Nyb2xsQmFyID09IE5VTEwpCiAgICAgICAgICAgIG1wSG9yaXpvbnRhbFNjcm9sbEJhciA9IG5ldyBTY3JvbGxCYXIgKAogICAgICAgICAgICAgICAgdGhpcywgV2luQml0cyhXQl9IU0NST0xMIHwgV0JfRFJBRykpOwogICAgICAgIGlmIChtcFNjcm9sbEJveCA9PSBOVUxMKQogICAgICAgICAgICBtcFNjcm9sbEJveCAgPSBuZXcgU2Nyb2xsQmFyQm94ICh0aGlzKTsKCQltcFZlcnRpY2FsU2Nyb2xsQmFyLT5TZXRTY3JvbGxIZGwoTElOSyh0aGlzLCBFZGl0V2luZG93LCBTY3JvbGxIZGwpKTsKCQltcEhvcml6b250YWxTY3JvbGxCYXItPlNldFNjcm9sbEhkbChMSU5LKHRoaXMsIEVkaXRXaW5kb3csIFNjcm9sbEhkbCkpOwoKCQltcEVkaXRWaWV3LT5TZXRPdXRwdXRBcmVhKEFkanVzdFNjcm9sbEJhcnMoKSk7CgoJCUVTZWxlY3Rpb24gZVNlbGVjdGlvbjsKCgkJbXBFZGl0Vmlldy0+U2V0U2VsZWN0aW9uKGVTZWxlY3Rpb24pOwoJCVVwZGF0ZSgpOwoJCW1wRWRpdFZpZXctPlNob3dDdXJzb3IodHJ1ZSwgdHJ1ZSk7CgoJCXBFZGl0RW5naW5lLT5TZXRTdGF0dXNFdmVudEhkbCgKICAgICAgICAgICAgTElOSyh0aGlzLCBFZGl0V2luZG93LCBFZGl0U3RhdHVzSGRsKSk7CgkJU2V0UG9pbnRlcihtcEVkaXRWaWV3LT5HZXRQb2ludGVyKCkpOwoKCQlTZXRTY3JvbGxCYXJSYW5nZXMoKTsKCX0KfQoKCgoKSU1QTF9MSU5LKCBFZGl0V2luZG93LCBFZGl0U3RhdHVzSGRsLCBFZGl0U3RhdHVzICosIEVNUFRZQVJHICkKewogICAgaWYgKCFtcEVkaXRWaWV3KQoJCXJldHVybiAxOwoJZWxzZQoJewoJCVNldFNjcm9sbEJhclJhbmdlcygpOwoJCXJldHVybiAwOwoJfQp9CgpJTVBMX0xJTktfSU5MSU5FX1NUQVJUKCBFZGl0V2luZG93LCBTY3JvbGxIZGwsIFNjcm9sbEJhciAqLCBFTVBUWUFSRyApCnsKICAgIERCR19BU1NFUlQobXBFZGl0VmlldywgIkVkaXRWaWV3IG1pc3NpbmciKTsKICAgIGlmIChtcEVkaXRWaWV3KQogICAgewogICAgICAgIG1wRWRpdFZpZXctPlNldFZpc0FyZWEoUmVjdGFuZ2xlKFBvaW50KG1wSG9yaXpvbnRhbFNjcm9sbEJhci0+R2V0VGh1bWJQb3MoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtcFZlcnRpY2FsU2Nyb2xsQmFyLT5HZXRUaHVtYlBvcygpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1wRWRpdFZpZXctPkdldFZpc0FyZWEoKS5HZXRTaXplKCkpKTsKICAgICAgICBtcEVkaXRWaWV3LT5JbnZhbGlkYXRlKCk7CiAgICB9CglyZXR1cm4gMDsKfQpJTVBMX0xJTktfSU5MSU5FX0VORCggRWRpdFdpbmRvdywgU2Nyb2xsSGRsLCBTY3JvbGxCYXIgKiwgRU1QVFlBUkcgKQoKUmVjdGFuZ2xlIEVkaXRXaW5kb3c6OkFkanVzdFNjcm9sbEJhcnMoKQp7Cgljb25zdCBTaXplIGFPdXQoIEdldE91dHB1dFNpemVQaXhlbCgpICk7CglQb2ludCBhUG9pbnQ7CglSZWN0YW5nbGUgYVJlY3QoIGFQb2ludCwgYU91dCApOwoKCWlmIChtcFZlcnRpY2FsU2Nyb2xsQmFyICYmIG1wSG9yaXpvbnRhbFNjcm9sbEJhciAmJiBtcFNjcm9sbEJveCkKCXsKCQljb25zdCBsb25nIG5UbXAgPSBHZXRTZXR0aW5ncygpLkdldFN0eWxlU2V0dGluZ3MoKS5HZXRTY3JvbGxCYXJTaXplKCk7CgkJUG9pbnQgYVB0KCBhUmVjdC5Ub3BSaWdodCgpICk7IGFQdC5YKCkgLT0gblRtcCAtMUw7CgkJbXBWZXJ0aWNhbFNjcm9sbEJhci0+U2V0UG9zU2l6ZVBpeGVsKCBhUHQsIFNpemUoblRtcCwgYU91dC5IZWlnaHQoKSAtIG5UbXApKTsKCgkJYVB0ID0gYVJlY3QuQm90dG9tTGVmdCgpOyBhUHQuWSgpIC09IG5UbXAgLSAxTDsKCQltcEhvcml6b250YWxTY3JvbGxCYXItPlNldFBvc1NpemVQaXhlbCggYVB0LCBTaXplKGFPdXQuV2lkdGgoKSAtIG5UbXAsIG5UbXApKTsKCgkJYVB0LlgoKSA9IG1wSG9yaXpvbnRhbFNjcm9sbEJhci0+R2V0U2l6ZVBpeGVsKCkuV2lkdGgoKTsKCQlhUHQuWSgpID0gbXBWZXJ0aWNhbFNjcm9sbEJhci0+R2V0U2l6ZVBpeGVsKCkuSGVpZ2h0KCk7CgkJbXBTY3JvbGxCb3gtPlNldFBvc1NpemVQaXhlbChhUHQsIFNpemUoblRtcCwgblRtcCApKTsKCgkJYVJlY3QuUmlnaHQoKSAgPSBhUHQuWCgpIC0gMjsKCQlhUmVjdC5Cb3R0b20oKSA9IGFQdC5ZKCkgLSAyOwoJfQoJcmV0dXJuIGFSZWN0Owp9Cgp2b2lkIEVkaXRXaW5kb3c6OlNldFNjcm9sbEJhclJhbmdlcygpCnsKICAgIEVkaXRFbmdpbmUqIHBFZGl0RW5naW5lID0gR2V0RWRpdEVuZ2luZSgpOwogICAgaWYgKG1wRWRpdFZpZXcgIT0gTlVMTCAmJiBwRWRpdEVuZ2luZSAhPSBOVUxMKQogICAgewogICAgICAgIGlmIChtcFZlcnRpY2FsU2Nyb2xsQmFyICE9IE5VTEwpCiAgICAgICAgewogICAgICAgICAgICBsb25nIG5UbXAgPSBwRWRpdEVuZ2luZS0+R2V0VGV4dEhlaWdodCgpOwogICAgICAgICAgICBtcFZlcnRpY2FsU2Nyb2xsQmFyLT5TZXRSYW5nZShSYW5nZSgwLCBuVG1wKSk7CiAgICAgICAgICAgIG1wVmVydGljYWxTY3JvbGxCYXItPlNldFRodW1iUG9zKG1wRWRpdFZpZXctPkdldFZpc0FyZWEoKS5Ub3AoKSk7CiAgICAgICAgfQogICAgICAgIGlmIChtcEhvcml6b250YWxTY3JvbGxCYXIgIT0gTlVMTCkKICAgICAgICB7CiAgICAgICAgICAgIGxvbmcgblRtcCA9IHBFZGl0RW5naW5lLT5HZXRQYXBlclNpemUoKS5XaWR0aCgpOwogICAgICAgICAgICBtcEhvcml6b250YWxTY3JvbGxCYXItPlNldFJhbmdlKFJhbmdlKDAsblRtcCkpOwogICAgICAgICAgICBtcEhvcml6b250YWxTY3JvbGxCYXItPlNldFRodW1iUG9zKG1wRWRpdFZpZXctPkdldFZpc0FyZWEoKS5MZWZ0KCkpOwogICAgICAgIH0KCX0KfQoKdm9pZCBFZGl0V2luZG93OjpJbml0U2Nyb2xsQmFycygpCnsKICAgIGlmIChtcEVkaXRWaWV3ICE9IE5VTEwpCgl7CgkJY29uc3QgU2l6ZSBhT3V0KCBtcEVkaXRWaWV3LT5HZXRPdXRwdXRBcmVhKCkuR2V0U2l6ZSgpICk7CiAgICAgICAgaWYgKG1wVmVydGljYWxTY3JvbGxCYXIgIT0gTlVMTCkKICAgICAgICB7CiAgICAgICAgICAgIG1wVmVydGljYWxTY3JvbGxCYXItPlNldFZpc2libGVTaXplKGFPdXQuSGVpZ2h0KCkpOwogICAgICAgICAgICBtcFZlcnRpY2FsU2Nyb2xsQmFyLT5TZXRQYWdlU2l6ZShhT3V0LkhlaWdodCgpICogOCAvIDEwKTsKICAgICAgICAgICAgbXBWZXJ0aWNhbFNjcm9sbEJhci0+U2V0TGluZVNpemUoYU91dC5IZWlnaHQoKSAqIDIgLyAxMCk7CiAgICAgICAgfQoKICAgICAgICBpZiAobXBIb3Jpem9udGFsU2Nyb2xsQmFyICE9IE5VTEwpCiAgICAgICAgewogICAgICAgICAgICBtcEhvcml6b250YWxTY3JvbGxCYXItPlNldFZpc2libGVTaXplKGFPdXQuV2lkdGgoKSk7CiAgICAgICAgICAgIG1wSG9yaXpvbnRhbFNjcm9sbEJhci0+U2V0UGFnZVNpemUoYU91dC5XaWR0aCgpICogOCAvIDEwKTsKICAgICAgICAgICAgbXBIb3Jpem9udGFsU2Nyb2xsQmFyLT5TZXRMaW5lU2l6ZShTQ1JPTExfTElORSApOwogICAgICAgIH0KCgkJU2V0U2Nyb2xsQmFyUmFuZ2VzKCk7CgogICAgICAgIGlmIChtcFZlcnRpY2FsU2Nyb2xsQmFyICE9IE5VTEwpCiAgICAgICAgICAgIG1wVmVydGljYWxTY3JvbGxCYXItPlNob3coKTsKICAgICAgICBpZiAobXBIb3Jpem9udGFsU2Nyb2xsQmFyICE9IE5VTEwpCiAgICAgICAgICAgIG1wSG9yaXpvbnRhbFNjcm9sbEJhci0+U2hvdygpOwogICAgICAgIGlmIChtcFNjcm9sbEJveCAhPSBOVUxMKQogICAgICAgICAgICBtcFNjcm9sbEJveC0+U2hvdygpOwoJfQp9CgoKWHViU3RyaW5nIEVkaXRXaW5kb3c6OkdldFRleHQoKQp7CglTdHJpbmcgYVRleHQ7CiAgICBFZGl0RW5naW5lICpwRWRpdEVuZ2luZSA9IEdldEVkaXRFbmdpbmUoKTsKCURCR19BU1NFUlQoIHBFZGl0RW5naW5lLCAiRWRpdEVuZ2luZSBtaXNzaW5nIiApOwoJaWYgKHBFZGl0RW5naW5lKQoJCWFUZXh0ID0gcEVkaXRFbmdpbmUtPkdldFRleHQoIExJTkVFTkRfTEYgKTsKCXJldHVybiBhVGV4dDsKfQoKCnZvaWQgRWRpdFdpbmRvdzo6U2V0VGV4dChjb25zdCBYdWJTdHJpbmcmIHJUZXh0KQp7CiAgICBFZGl0RW5naW5lICpwRWRpdEVuZ2luZSA9IEdldEVkaXRFbmdpbmUoKTsKCURCR19BU1NFUlQoIHBFZGl0RW5naW5lLCAiRWRpdEVuZ2luZSBtaXNzaW5nIiApOwoJaWYgKHBFZGl0RW5naW5lICAmJiAgIXBFZGl0RW5naW5lLT5Jc01vZGlmaWVkKCkpCgl7CgkJaWYgKCFtcEVkaXRWaWV3KQoJCQlDcmVhdGVFZGl0VmlldygpOwoKCQlFU2VsZWN0aW9uIGVTZWxlY3Rpb24gPSBtcEVkaXRWaWV3LT5HZXRTZWxlY3Rpb24oKTsKCgkJcEVkaXRFbmdpbmUtPlNldFRleHQoclRleHQpOwoJCXBFZGl0RW5naW5lLT5DbGVhck1vZGlmeUZsYWcoKTsKCgkJLy8hIEhpZXIgZGllIFRpbWVyIG5ldSB6dSBzdGFydGVuIHZlcmhpbmRlcnQsIGRhc3MgZGllIEhhbmRsZXIgZvxyIGFuZGVyZQoJCS8vISAoaW0gQXVnZW5ibGljayBuaWNodCBtZWhyIGFrdGl2ZSkgTWF0aCBUYXNrcyBhdWZnZXJ1ZmVuIHdlcmRlbi4KCQltYU1vZGlmeVRpbWVyLlN0YXJ0KCk7CgkJbWFDdXJzb3JNb3ZlVGltZXIuU3RhcnQoKTsKCgkJbXBFZGl0Vmlldy0+U2V0U2VsZWN0aW9uKGVTZWxlY3Rpb24pOwoJfQp9CgoKdm9pZCBFZGl0V2luZG93OjpHZXRGb2N1cygpCnsKCVdpbmRvdzo6R2V0Rm9jdXMoKTsKCiAgICBpZiAoIW1wRWRpdFZpZXcpCiAgICAgICAgIENyZWF0ZUVkaXRWaWV3KCk7CglpZiAobXBFZGl0RW5naW5lICE9IE5VTEwpCgkJbXBFZGl0RW5naW5lLT5TZXRTdGF0dXNFdmVudEhkbCgKICAgICAgICAgICAgTElOSyh0aGlzLCBFZGl0V2luZG93LCBFZGl0U3RhdHVzSGRsKSk7Cn0KCgp2b2lkIEVkaXRXaW5kb3c6Okxvc2VGb2N1cygpCnsKCWlmIChtcEVkaXRFbmdpbmUgIT0gTlVMTCkKCQltcEVkaXRFbmdpbmUtPlNldFN0YXR1c0V2ZW50SGRsIChMaW5rKCkpOwoKCVdpbmRvdzo6TG9zZUZvY3VzKCk7Cn0KCgpib29sIEVkaXRXaW5kb3c6OklzQWxsU2VsZWN0ZWQoKSBjb25zdAp7CiAgICBib29sIGJSZXMgPSBmYWxzZTsKICAgIEVkaXRFbmdpbmUgKnBFZGl0RW5naW5lID0gKChFZGl0V2luZG93ICopIHRoaXMpLT5HZXRFZGl0RW5naW5lKCk7CglEQkdfQVNTRVJUKCBtcEVkaXRWaWV3LCAiTlVMTCBwb2ludGVyIiApOwogICAgREJHX0FTU0VSVCggcEVkaXRFbmdpbmUsICJOVUxMIHBvaW50ZXIiICk7CiAgICBpZiAocEVkaXRFbmdpbmUgICYmICBtcEVkaXRWaWV3KQogICAgewogICAgICAgIEVTZWxlY3Rpb24gZVNlbGVjdGlvbiggbXBFZGl0Vmlldy0+R2V0U2VsZWN0aW9uKCkgKTsKICAgICAgICBzYWxfSW50MzIgblBhcmFDbnQgPSBwRWRpdEVuZ2luZS0+R2V0UGFyYWdyYXBoQ291bnQoKTsKICAgICAgICBpZiAoIShuUGFyYUNudCAtIDEpKQogICAgICAgIHsKICAgICAgICAgICAgU3RyaW5nIFRleHQoIHBFZGl0RW5naW5lLT5HZXRUZXh0KCBMSU5FRU5EX0xGICkgKTsKICAgICAgICAgICAgYlJlcyA9ICFlU2VsZWN0aW9uLm5TdGFydFBvcyAmJiAoZVNlbGVjdGlvbi5uRW5kUG9zID09IFRleHQuTGVuICgpIC0gMSk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGJSZXMgPSAhZVNlbGVjdGlvbi5uU3RhcnRQYXJhICYmIChlU2VsZWN0aW9uLm5FbmRQYXJhID09IG5QYXJhQ250IC0gMSk7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIGJSZXM7Cn0KCnZvaWQgRWRpdFdpbmRvdzo6U2VsZWN0QWxsKCkKewoJREJHX0FTU0VSVCggbXBFZGl0VmlldywgIk5VTEwgcG9pbnRlciIgKTsKCWlmIChtcEVkaXRWaWV3KQoJewoJCS8vIDB4RkZGRiBhcyBsYXN0IHR3byBwYXJhbWV0ZXJzIHJlZmVycyB0byB0aGUgZW5kIG9mIHRoZSB0ZXh0CgkJbXBFZGl0Vmlldy0+U2V0U2VsZWN0aW9uKCBFU2VsZWN0aW9uKCAwLCAwLCAweEZGRkYsIDB4RkZGRiApICk7Cgl9Cn0KCgp2b2lkIEVkaXRXaW5kb3c6Ok1hcmtFcnJvcihjb25zdCBQb2ludCAmclBvcykKewogICAgREJHX0FTU0VSVCggbXBFZGl0VmlldywgIkVkaXRWaWV3IG1pc3NpbmciICk7CiAgICBpZiAobXBFZGl0VmlldykKICAgIHsKICAgICAgICBjb25zdCBpbnQgQ29sID0gclBvcy5YKCk7CiAgICAgICAgY29uc3QgaW50IFJvdyA9IHJQb3MuWSgpIC0gMTsKCiAgICAgICAgbXBFZGl0Vmlldy0+U2V0U2VsZWN0aW9uKEVTZWxlY3Rpb24gKCAoc2FsX3VJbnQxNilSb3csIChzYWxfdUludDE2KShDb2wgLSAxKSwgKHNhbF91SW50MTYpUm93LCAoc2FsX3VJbnQxNilDb2wpKTsKICAgICAgICBHcmFiRm9jdXMoKTsKICAgIH0KfQoKdm9pZCBFZGl0V2luZG93OjpTZWxOZXh0TWFyaygpCnsKICAgIEVkaXRFbmdpbmUgKnBFZGl0RW5naW5lID0gR2V0RWRpdEVuZ2luZSgpOwoJREJHX0FTU0VSVCggbXBFZGl0VmlldywgIk5VTEwgcG9pbnRlciIgKTsKCURCR19BU1NFUlQoIHBFZGl0RW5naW5lLCAiTlVMTCBwb2ludGVyIiApOwogICAgaWYgKHBFZGl0RW5naW5lICAmJiAgbXBFZGl0VmlldykKICAgIHsKICAgICAgICBFU2VsZWN0aW9uIGVTZWxlY3Rpb24gPSBtcEVkaXRWaWV3LT5HZXRTZWxlY3Rpb24oKTsKICAgICAgICBzYWxfdUludDE2ICAgICBQb3MgICAgICAgID0gZVNlbGVjdGlvbi5uRW5kUG9zOwogICAgICAgIFN0cmluZyAgICAgYU1hcmsgKFVuaVN0cmluZzo6Q3JlYXRlRnJvbUFzY2lpKCI8Pz4iKSk7CiAgICAgICAgU3RyaW5nICAgICBhVGV4dDsKICAgICAgICBzYWxfdUludDE2ICAgICBuQ291bnRzICAgID0gcEVkaXRFbmdpbmUtPkdldFBhcmFncmFwaENvdW50KCk7CgogICAgICAgIHdoaWxlIChlU2VsZWN0aW9uLm5FbmRQYXJhIDwgbkNvdW50cykKICAgICAgICB7CiAgICAgICAgICAgIGFUZXh0ID0gcEVkaXRFbmdpbmUtPkdldFRleHQoIGVTZWxlY3Rpb24ubkVuZFBhcmEgKTsKICAgICAgICAgICAgUG9zICAgPSBhVGV4dC5TZWFyY2goYU1hcmssIFBvcyk7CgogICAgICAgICAgICBpZiAoUG9zICE9IFNUUklOR19OT1RGT1VORCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgbXBFZGl0Vmlldy0+U2V0U2VsZWN0aW9uKEVTZWxlY3Rpb24gKGVTZWxlY3Rpb24ubkVuZFBhcmEsIFBvcywgZVNlbGVjdGlvbi5uRW5kUGFyYSwgUG9zICsgMykpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIFBvcyA9IDA7CiAgICAgICAgICAgIGVTZWxlY3Rpb24ubkVuZFBhcmErKzsKICAgICAgICB9CiAgICB9Cn0KCnZvaWQgRWRpdFdpbmRvdzo6U2VsUHJldk1hcmsoKQp7CiAgICBFZGl0RW5naW5lICpwRWRpdEVuZ2luZSA9IEdldEVkaXRFbmdpbmUoKTsKCURCR19BU1NFUlQoIHBFZGl0RW5naW5lLCAiTlVMTCBwb2ludGVyIiApOwoJREJHX0FTU0VSVCggbXBFZGl0VmlldywgIk5VTEwgcG9pbnRlciIgKTsKICAgIGlmIChwRWRpdEVuZ2luZSAgJiYgIG1wRWRpdFZpZXcpCiAgICB7CiAgICAgICAgRVNlbGVjdGlvbiBlU2VsZWN0aW9uID0gbXBFZGl0Vmlldy0+R2V0U2VsZWN0aW9uKCk7CiAgICAgICAgc2FsX3VJbnQxNiAgICAgUG9zICAgICAgICA9IFNUUklOR19OT1RGT1VORDsKICAgICAgICB4dWJfU3RyTGVuIE1heCAgICAgICAgPSBlU2VsZWN0aW9uLm5TdGFydFBvczsKICAgICAgICBTdHJpbmcgICAgIFRleHQoIHBFZGl0RW5naW5lLT5HZXRUZXh0KCBlU2VsZWN0aW9uLm5TdGFydFBhcmEgKSApOwogICAgICAgIFN0cmluZyAgICAgYU1hcmsgKFVuaVN0cmluZzo6Q3JlYXRlRnJvbUFzY2lpKCI8Pz4iKSk7CiAgICAgICAgc2FsX3VJbnQxNiAgICAgbkNvdW50cyAgICA9IHBFZGl0RW5naW5lLT5HZXRQYXJhZ3JhcGhDb3VudCgpOwoKICAgICAgICBkbwogICAgICAgIHsKICAgICAgICAgICAgc2FsX3VJbnQxNiBGbmQgPSBUZXh0LlNlYXJjaChhTWFyaywgMCk7CgogICAgICAgICAgICB3aGlsZSAoKEZuZCA8IE1heCkgJiYgKEZuZCAhPSBTVFJJTkdfTk9URk9VTkQpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBQb3MgPSBGbmQ7CiAgICAgICAgICAgICAgICBGbmQgPSBUZXh0LlNlYXJjaChhTWFyaywgRm5kICsgMSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChQb3MgPT0gU1RSSU5HX05PVEZPVU5EKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBlU2VsZWN0aW9uLm5TdGFydFBhcmEtLTsKICAgICAgICAgICAgICAgIFRleHQgPSBwRWRpdEVuZ2luZS0+R2V0VGV4dCggZVNlbGVjdGlvbi5uU3RhcnRQYXJhICk7CiAgICAgICAgICAgICAgICBNYXggPSBUZXh0LkxlbigpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHdoaWxlICgoZVNlbGVjdGlvbi5uU3RhcnRQYXJhIDwgbkNvdW50cykgJiYKICAgICAgICAgICAgKFBvcyA9PSBTVFJJTkdfTk9URk9VTkQpKTsKCiAgICAgICAgaWYgKFBvcyAhPSBTVFJJTkdfTk9URk9VTkQpCiAgICAgICAgewogICAgICAgICAgICBtcEVkaXRWaWV3LT5TZXRTZWxlY3Rpb24oRVNlbGVjdGlvbiAoZVNlbGVjdGlvbi5uU3RhcnRQYXJhLCBQb3MsIGVTZWxlY3Rpb24ublN0YXJ0UGFyYSwgUG9zICsgMykpOwogICAgICAgIH0KICAgIH0KfQoKYm9vbCBFZGl0V2luZG93OjpIYXNNYXJrKGNvbnN0IFN0cmluZyYgclRleHQpIGNvbnN0CgkvLyByZXR1cm5zIHRydWUgaWZmICdyVGV4dCcgY29udGFpbnMgYSBtYXJrCnsKCXJldHVybiByVGV4dC5TZWFyY2hBc2NpaSgiPD8+IiwgMCkgIT0gU1RSSU5HX05PVEZPVU5EOwp9Cgp2b2lkIEVkaXRXaW5kb3c6Ok1vdXNlTW92ZShjb25zdCBNb3VzZUV2ZW50ICZyRXZ0KQp7CglpZiAobXBFZGl0VmlldykKCQltcEVkaXRWaWV3LT5Nb3VzZU1vdmUockV2dCk7Cn0KCnNhbF9JbnQ4IEVkaXRXaW5kb3c6OkFjY2VwdERyb3AoIGNvbnN0IEFjY2VwdERyb3BFdmVudCYgKQp7CglyZXR1cm4gbXBFZGl0VmlldyA/IC8qbXBFZGl0Vmlldy0+UXVlcnlEcm9wKCByRXZ0ICkqL0RORF9BQ1RJT05fTk9ORTogRE5EX0FDVElPTl9OT05FOwp9CgpzYWxfSW50OCBFZGl0V2luZG93OjpFeGVjdXRlRHJvcCggY29uc3QgRXhlY3V0ZURyb3BFdmVudCYgKQp7CglyZXR1cm4gbXBFZGl0VmlldyA/IC8qbXBFZGl0Vmlldy0+RHJvcCggckV2dCApKi9ETkRfQUNUSU9OX05PTkUgOiBETkRfQUNUSU9OX05PTkU7Cn0KCkVTZWxlY3Rpb24gRWRpdFdpbmRvdzo6R2V0U2VsZWN0aW9uKCkgY29uc3QKewogICAgLy8gcG9pbnRlciBtYXkgYmUgMCB3aGVuIHJlbG9hZGluZyBhIGRvY3VtZW50IGFuZCB0aGUgb2xkIHZpZXcKICAgIC8vIHdhcyBhbHJlYWR5IGRlc3Ryb3llZAogICAgLy8oREJHX0FTU0VSVCggbXBFZGl0VmlldywgIk5VTEwgcG9pbnRlciIgKTsKCUVTZWxlY3Rpb24gZVNlbDsKCWlmIChtcEVkaXRWaWV3KQoJCWVTZWwgPSBtcEVkaXRWaWV3LT5HZXRTZWxlY3Rpb24oKTsKCXJldHVybiBlU2VsOwp9Cgp2b2lkIEVkaXRXaW5kb3c6OlNldFNlbGVjdGlvbihjb25zdCBFU2VsZWN0aW9uICZyU2VsKQp7CglEQkdfQVNTRVJUKCBtcEVkaXRWaWV3LCAiTlVMTCBwb2ludGVyIiApOwogICAgaWYgKG1wRWRpdFZpZXcpCiAgICAgICAgbXBFZGl0Vmlldy0+U2V0U2VsZWN0aW9uKHJTZWwpOwp9Cgpib29sIEVkaXRXaW5kb3c6OklzRW1wdHkoKSBjb25zdAp7CiAgICBFZGl0RW5naW5lICpwRWRpdEVuZ2luZSA9ICgoRWRpdFdpbmRvdyAqKSB0aGlzKS0+R2V0RWRpdEVuZ2luZSgpOwogICAgcmV0dXJuIChwRWRpdEVuZ2luZSAmJiAocEVkaXRFbmdpbmUtPkdldFRleHRMZW4oKSA9PSAwKSkgPyB0cnVlIDogZmFsc2U7Cn0KCmJvb2wgRWRpdFdpbmRvdzo6SXNTZWxlY3RlZCgpIGNvbnN0CnsKICAgIHJldHVybiBtcEVkaXRWaWV3ID8gbXBFZGl0Vmlldy0+SGFzU2VsZWN0aW9uKCkgOiBmYWxzZTsKfQoKdm9pZCBFZGl0V2luZG93OjpDdXQoKQp7CiAgICBEQkdfQVNTRVJUKCBtcEVkaXRWaWV3LCAiRWRpdFZpZXcgbWlzc2luZyIgKTsKICAgIGlmIChtcEVkaXRWaWV3KQogICAgICAgIG1wRWRpdFZpZXctPkN1dCgpOwp9Cgp2b2lkIEVkaXRXaW5kb3c6OkNvcHkoKQp7CiAgICBEQkdfQVNTRVJUKCBtcEVkaXRWaWV3LCAiRWRpdFZpZXcgbWlzc2luZyIgKTsKICAgIGlmIChtcEVkaXRWaWV3KQogICAgICAgIG1wRWRpdFZpZXctPkNvcHkoKTsKfQoKdm9pZCBFZGl0V2luZG93OjpQYXN0ZSgpCnsKICAgIERCR19BU1NFUlQoIG1wRWRpdFZpZXcsICJFZGl0VmlldyBtaXNzaW5nIiApOwogICAgaWYgKG1wRWRpdFZpZXcpCiAgICAgICAgbXBFZGl0Vmlldy0+UGFzdGUoKTsKfQoKdm9pZCBFZGl0V2luZG93OjpEZWxldGUoKQp7CiAgICBEQkdfQVNTRVJUKCBtcEVkaXRWaWV3LCAiRWRpdFZpZXcgbWlzc2luZyIgKTsKICAgIGlmIChtcEVkaXRWaWV3KQogICAgICAgIG1wRWRpdFZpZXctPkRlbGV0ZVNlbGVjdGVkKCk7Cn0KCnZvaWQgRWRpdFdpbmRvdzo6SW5zZXJ0VGV4dChjb25zdCBTdHJpbmcmIFRleHQpCnsKICAgIERCR19BU1NFUlQoIG1wRWRpdFZpZXcsICJFZGl0VmlldyBtaXNzaW5nIiApOwogICAgOjp2b3M6Ok9HdWFyZCBhR3VhcmQgKDo6QXBwbGljYXRpb246OkdldFNvbGFyTXV0ZXgoKSk7CiAgICBpZiAobXBFZGl0VmlldykKICAgICAgICBtcEVkaXRWaWV3LT5JbnNlcnRUZXh0KFRleHQpOwp9CgoKCn0gfSAvLyBlbmQgb2YgbmFtZXNwYWNlIDo6c2Q6Om5vdGVzCg==