@echo off rem IE Opener helper - single-file installer (double-click). rem /silent no prompts (unattended / GPO) /legacy force the PowerShell launcher instead of the fast exe set "SELF=%~f0" set "SETUP_SILENT=0" set "SETUP_LEGACY=0" set "SETUP_COMPILE=0" taskkill /F /IM IEOpenerHost.exe /T >nul 2>nul taskkill /F /IM IEOpenerHost.exe /T >nul 2>nul for %%A in (%*) do ( if /i "%%~A"=="/silent" set "SETUP_SILENT=1" if /i "%%~A"=="/legacy" set "SETUP_LEGACY=1" if /i "%%~A"=="/compile" set "SETUP_COMPILE=1" ) powershell -NoProfile -ExecutionPolicy Bypass -Command "$s=[IO.File]::ReadAllText($env:SELF); $i=$s.IndexOf('#'+'#PS-BEGIN##'); Invoke-Expression $s.Substring($i)" exit /b %errorlevel% ##PS-BEGIN## $ErrorActionPreference = 'Stop' $silent = ($env:SETUP_SILENT -eq '1') Get-Process -Name 'IEOpenerHost', 'IEOpenerHost' -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Milliseconds 300 $code = 0 try { $dst = Join-Path $env:LOCALAPPDATA 'IEModeOpener' Write-Host "[1/5] Extracting helper to $dst" New-Item -ItemType Directory -Path $dst -Force | Out-Null $utf8 = New-Object Text.UTF8Encoding($false) $files = [ordered]@{} $files['host.ps1'] = @' # Chrome native messaging host: opens URL in Edge IE mode via Enterprise site list policy $stdin = [Console]::OpenStandardInput() $stdout = [Console]::OpenStandardOutput() function Send($obj) { $json = $obj | ConvertTo-Json -Compress $bytes = [Text.Encoding]::UTF8.GetBytes($json) $stdout.Write([BitConverter]::GetBytes([int]$bytes.Length), 0, 4) $stdout.Write($bytes, 0, $bytes.Length) $stdout.Flush() } function Convert-Pattern([string]$p) { $p = $p.Trim() $p = $p -replace '^[a-zA-Z][a-zA-Z0-9+.-]*://', '' $p = $p -replace '^\*\.', '' $p = $p -replace '/?\*+$', '' $p = $p.TrimEnd('/') if ($p -eq '' -or $p -match '\*') { return $null } return $p } function Get-ManagedListPath { # Device-level policy (HKLM) takes precedence over user-level policy $v = $null try { $v = (Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Edge' -ErrorAction Stop).InternetExplorerIntegrationSiteList } catch {} if (-not $v) { return $null } if ($v -match '^file:///(.+)$') { return ([Uri]::UnescapeDataString($Matches[1]) -replace '/', '\') } if ($v -match '^[A-Za-z]:\\' -or $v -match '^\\\\') { return $v } return "UNSUPPORTED|" + $v } function Update-ManagedList($path, $sites) { if ($path -like 'UNSUPPORTED|*') { throw $path } if (-not (Test-Path $path)) { throw ("NOT_FOUND|" + $path) } $xml = New-Object System.Xml.XmlDocument $xml.PreserveWhitespace = $true $xml.Load($path) $root = $xml.DocumentElement if ($root.Name -ne 'site-list') { throw ("BAD_XML|" + $path) } $existing = @{} foreach ($n in $root.SelectNodes('site')) { $u = ($n.GetAttribute('url')).ToLower().TrimEnd('/') -replace '^[a-z]+://', '' $existing[$u] = $true } $added = 0 foreach ($s in $sites) { if ($existing.ContainsKey($s.ToLower())) { continue } $site = $xml.CreateElement('site'); $site.SetAttribute('url', $s) $cm = $xml.CreateElement('compat-mode'); $cm.InnerText = 'Default' $oi = $xml.CreateElement('open-in'); $oi.InnerText = 'IE11' [void]$site.AppendChild($cm); [void]$site.AppendChild($oi) [void]$root.AppendChild($site) $added++ } if ($added -gt 0) { $ver = 0 [void][int]::TryParse($root.GetAttribute('version'), [ref]$ver) $root.SetAttribute('version', [string]($ver + 1)) # Edge reloads only when version increases try { $xml.Save($path) } catch { throw ("NOT_WRITABLE|" + $path + "|" + $env:USERNAME) } } # remove our own user-level policy values to avoid confusion $key = 'HKCU:\Software\Policies\Microsoft\Edge' foreach ($n in 'InternetExplorerIntegrationLevel','InternetExplorerIntegrationSiteList','InternetExplorerIntegrationReloadInIEModeAllowed') { Remove-ItemProperty -Path $key -Name $n -ErrorAction SilentlyContinue } } function Update-SiteList($patterns, $extraUrl) { $sites = New-Object System.Collections.Generic.List[string] foreach ($p in @($patterns)) { if (-not $p) { continue } $c = Convert-Pattern ([string]$p) if ($c -and -not $sites.Contains($c)) { $sites.Add($c) } } if ($extraUrl) { try { $h = ([Uri]$extraUrl).Host; if ($h -and -not $sites.Contains($h)) { $sites.Add($h) } } catch {} } $managedPath = Get-ManagedListPath if ($managedPath) { Update-ManagedList $managedPath $sites; return } $dir = Join-Path $env:LOCALAPPDATA "IEModeOpener" Get-ChildItem $dir -Filter "sitelist-*.xml" -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -Skip 3 | Remove-Item -Force -ErrorAction SilentlyContinue # new file name each time so Edge notices the policy value changed $file = Join-Path $dir ("sitelist-" + [DateTime]::UtcNow.Ticks + ".xml") $sb = New-Object System.Text.StringBuilder [void]$sb.AppendLine('') [void]$sb.AppendLine('') [void]$sb.AppendLine(' IEModeOpener1.0' + (Get-Date).ToString('yyyy-MM-ddTHH:mm:ss') + '') foreach ($s in $sites) { $e = [Security.SecurityElement]::Escape($s) [void]$sb.AppendLine(' DefaultIE11') } [void]$sb.AppendLine('') [IO.File]::WriteAllText($file, $sb.ToString(), (New-Object Text.UTF8Encoding($false))) $uri = 'file:///' + (($file -replace '\\', '/') -replace ' ', '%20') $key = 'HKCU:\Software\Policies\Microsoft\Edge' New-Item -Path $key -Force | Out-Null New-ItemProperty -Path $key -Name InternetExplorerIntegrationLevel -Value 1 -PropertyType DWord -Force | Out-Null New-ItemProperty -Path $key -Name InternetExplorerIntegrationSiteList -Value $uri -PropertyType String -Force | Out-Null New-ItemProperty -Path $key -Name InternetExplorerIntegrationReloadInIEModeAllowed -Value 1 -PropertyType DWord -Force | Out-Null } try { $lenBuf = New-Object byte[] 4 [void]$stdin.Read($lenBuf, 0, 4) $len = [BitConverter]::ToInt32($lenBuf, 0) $buf = New-Object byte[] $len $read = 0 while ($read -lt $len) { $read += $stdin.Read($buf, $read, $len - $read) } $msg = [Text.Encoding]::UTF8.GetString($buf) | ConvertFrom-Json function Test-PasswordPolicyDisabled { foreach ($r in @('HKLM:\SOFTWARE\Policies\IEModeOpener', 'HKCU:\Software\Policies\IEModeOpener')) { try { $v = (Get-ItemProperty $r -ErrorAction Stop).DisablePasswordManager if ([int]$v -eq 1) { return $true } } catch {} } return $false } $dpapiEntropy = [Text.Encoding]::UTF8.GetBytes('IEOpener_DPAPI_v1_Salt') function Protect-Dpapi([string]$plain) { if ([string]::IsNullOrEmpty($plain)) { return '' } if ($plain.StartsWith('dpapi:')) { return $plain } Add-Type -AssemblyName System.Security -ErrorAction SilentlyContinue $bytes = [Text.Encoding]::UTF8.GetBytes($plain) $enc = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $dpapiEntropy, [System.Security.Cryptography.DataProtectionScope]::CurrentUser) return 'dpapi:' + [Convert]::ToBase64String($enc) } function Unprotect-Dpapi([string]$token) { if ([string]::IsNullOrEmpty($token)) { return '' } if (-not $token.StartsWith('dpapi:')) { return $token } Add-Type -AssemblyName System.Security -ErrorAction SilentlyContinue $enc = [Convert]::FromBase64String($token.Substring(6)) $dec = [System.Security.Cryptography.ProtectedData]::Unprotect($enc, $dpapiEntropy, [System.Security.Cryptography.DataProtectionScope]::CurrentUser) return [Text.Encoding]::UTF8.GetString($dec) } if ($msg.type -eq 'dpapi_encrypt') { $disabled = Test-PasswordPolicyDisabled if ($disabled) { Send @{ ok = $false; disablePasswordManager = $true; error = 'Disabled by GPO' }; exit } $outList = New-Object System.Collections.Generic.List[string] foreach ($p in @($msg.passwords)) { $outList.Add((Protect-Dpapi ([string]$p))) } Send @{ ok = $true; disablePasswordManager = $false; encrypted = $outList } exit } if ($msg.type -eq 'dpapi_decrypt') { $disabled = Test-PasswordPolicyDisabled if ($disabled) { Send @{ ok = $false; disablePasswordManager = $true; error = 'Disabled by GPO' }; exit } $plain = Unprotect-Dpapi ([string]$msg.token) Send @{ ok = $true; plain = $plain } exit } if ($msg.type -eq 'diag') { $mp = Get-ManagedListPath $info = [ordered]@{ ok = $true; version = '7.1.1'; user = $env:USERNAME; disablePasswordManager = (Test-PasswordPolicyDisabled); managed = [string]$mp; exists = $false; writable = $false; listVersion = ''; hasSite = $false; siteCount = 0; edgeRunning = [bool](Get-Process msedge -ErrorAction SilentlyContinue) } if ($mp -and $mp -notlike 'UNSUPPORTED|*' -and (Test-Path $mp)) { $info.exists = $true try { $fs = [IO.File]::Open($mp, 'Open', 'ReadWrite', 'Read'); $fs.Close(); $info.writable = $true } catch {} try { $x = New-Object System.Xml.XmlDocument $x.Load($mp) $info.listVersion = $x.DocumentElement.GetAttribute('version') $nodes = $x.DocumentElement.SelectNodes('site') $info.siteCount = $nodes.Count $h = $null try { $h = ([Uri][string]$msg.url).Host.ToLower() } catch {} if ($h) { foreach ($n in $nodes) { $u = ($n.GetAttribute('url')).ToLower() -replace '^[a-z]+://', '' $u = ($u -split '/')[0] if ($u -eq $h) { $info.hasSite = $true } } } } catch {} } Send $info exit } if ($msg.type -eq 'sync') { Update-SiteList $msg.include ([string]$msg.url) Send @{ ok = $true } exit } $url = [string]$msg.url if ($url -notmatch '^https?://') { Send @{ ok = $false; error = "invalid url" }; exit } $edge = $null foreach ($p in @("${env:ProgramFiles(x86)}\Microsoft\Edge\Application\msedge.exe", "$env:ProgramFiles\Microsoft\Edge\Application\msedge.exe")) { if (Test-Path $p) { $edge = $p; break } } if (-not $edge) { Send @{ ok = $false; error = "msedge.exe not found" }; exit } Update-SiteList $msg.include $url Start-Process -FilePath $edge -ArgumentList @("--ie-mode-force", "--internet-explorer-integration=iemode", "`"$url`"") Send @{ ok = $true } } catch { Send @{ ok = $false; error = $_.Exception.Message } } '@ $files['host.bat'] = @' @echo off powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0host.ps1" '@ $files['ieopener.ps1'] = @' param([switch]$CompileOnly) # IE tab helper (PowerShell fallback launcher + compiler). Must not write anything else to stdout when run as a host. $ErrorActionPreference = "Stop" $WarningPreference = "SilentlyContinue" $ProgressPreference = "SilentlyContinue" $dir = Join-Path $env:LOCALAPPDATA "IEModeOpener" $src = Join-Path $dir "IEOpenerHost.cs" $dll = Join-Path $dir "IEOpenerHost.dll" $exe = Join-Path $dir "IEOpenerHost.exe" $log = Join-Path $dir "ieopener.log" $refs = @("System.Windows.Forms", "System.Drawing", "System.Web.Extensions", "System.Xml", "System.Security") try { if (-not (Test-Path $dll)) { Add-Type -TypeDefinition (Get-Content $src -Raw) -ReferencedAssemblies $refs -OutputAssembly $dll -OutputType Library | Out-Null } if ($CompileOnly) { Write-Host "Compile OK (dll): $dll" # Standalone 32-bit exe: Chrome can start it directly (no cmd.exe / PowerShell at runtime = much faster start) try { if (Test-Path $exe) { Remove-Item $exe -Force } # Windows PowerShell 5.1's Add-Type has no -CompilerOptions, so compile with CodeDom directly (also avoids loading the x86 exe) $cp = New-Object System.CodeDom.Compiler.CompilerParameters [void]$cp.ReferencedAssemblies.AddRange([string[]]@("System.dll", "System.Windows.Forms.dll", "System.Drawing.dll", "System.Web.Extensions.dll", "System.Xml.dll", "System.Security.dll")) $cp.OutputAssembly = $exe $cp.GenerateExecutable = $true $cp.GenerateInMemory = $false $cp.CompilerOptions = "/platform:x86 /target:winexe" $cr = (New-Object Microsoft.CSharp.CSharpCodeProvider).CompileAssemblyFromSource($cp, [IO.File]::ReadAllText($src)) $ce = @($cr.Errors | Where-Object { -not $_.IsWarning }) if ($ce.Count -gt 0) { throw (($ce | ForEach-Object { $_.ToString() }) -join "; ") } Write-Host "Compile OK (exe): $exe" } catch { Write-Host ("EXE compile failed, PowerShell fallback will be used: " + $_.Exception.Message) } exit 0 } Add-Type -Path $dll | Out-Null [IEOpenerHost]::Run() } catch { if ($CompileOnly) { Write-Host "COMPILE FAILED:"; Write-Host ($_ | Out-String); exit 1 } Add-Content -Path $log -Value ((Get-Date).ToString("HH:mm:ss.fff") + " " + ($_ | Out-String)) } '@ $files['ieopener.bat'] = @' @echo off rem Use 32-bit PowerShell when available (matches IE mode / 32-bit ActiveX) set "PSEXE=%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" if not exist "%PSEXE%" set "PSEXE=powershell" "%PSEXE%" -NoProfile -NonInteractive -STA -WindowStyle Hidden -ExecutionPolicy Bypass -File "%~dp0ieopener.ps1" '@ $files['IEOpenerHost.cs'] = @' using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Reflection; using System.Text; using System.Threading; using System.Web.Script.Serialization; using System.Windows.Forms; using System.Xml; using System.Security.Cryptography; using Microsoft.Win32; // Chrome native-messaging host: overlays an IE (MSHTML) WebBrowser control on the Chrome tab content area. public static class IEOpenerHost { [StructLayout(LayoutKind.Sequential)] struct RECT { public int Left, Top, Right, Bottom; } delegate bool EnumProc(IntPtr h, IntPtr l); [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr h, out RECT r); [DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr h); [DllImport("user32.dll")] static extern bool IsWindow(IntPtr h); [DllImport("user32.dll")] static extern bool IsIconic(IntPtr h); [DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern int GetClassName(IntPtr h, StringBuilder sb, int max); [DllImport("user32.dll")] static extern bool EnumChildWindows(IntPtr p, EnumProc cb, IntPtr l); [DllImport("user32.dll")] static extern bool SetProcessDPIAware(); [DllImport("user32.dll", EntryPoint = "SetWindowLongPtrW")] static extern IntPtr SetWindowLongPtr64(IntPtr h, int idx, IntPtr v); [DllImport("user32.dll", EntryPoint = "SetWindowLongW")] static extern int SetWindowLong32(IntPtr h, int idx, int v); [DllImport("user32.dll")] static extern uint GetDpiForWindow(IntPtr h); [DllImport("wininet.dll", CharSet = CharSet.Unicode, SetLastError = true)] static extern bool InternetSetCookieEx(string url, string name, string data, int flags, IntPtr reserved); [DllImport("wininet.dll", CharSet = CharSet.Unicode, SetLastError = true)] static extern bool InternetGetCookieEx(string url, string name, StringBuilder data, ref int size, int flags, IntPtr reserved); [DllImport("user32.dll")] static extern bool EnumWindows(EnumProc cb, IntPtr l); [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr h, out uint pid); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr h, int cmd); [DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr h, IntPtr after, int x, int y, int cx, int cy, uint flags); [DllImport("user32.dll", EntryPoint = "GetWindowLongPtrW")] static extern IntPtr GetWindowLongPtr64(IntPtr h, int idx); [DllImport("user32.dll", EntryPoint = "GetWindowLongW")] static extern int GetWindowLong32(IntPtr h, int idx); [DllImport("user32.dll", EntryPoint = "SetWindowLongPtrW")] static extern IntPtr SetStyle64(IntPtr h, int idx, IntPtr v); [DllImport("user32.dll", EntryPoint = "SetWindowLongW")] static extern int SetStyle32(IntPtr h, int idx, int v); [DllImport("user32.dll")] static extern bool PostMessage(IntPtr h, uint msg, IntPtr w, IntPtr l); const string HelperVersion = "7.1.1"; static Stopwatch clock = new Stopwatch(); static long bootMs = -1; static Dictionary marks = new Dictionary(); static void Mark(string name) { marks[name] = clock.ElapsedMilliseconds; Log("mark " + name + " +" + marks[name] + "ms"); } static void MarkOnce(string name) { if (!marks.ContainsKey(name)) Mark(name); } // Entry point for the standalone (no PowerShell) build [STAThread] public static void Main() { Run(); } static Control sync; static OverlayForm form; internal static WebBrowser MainBrowser { get { return form != null ? form.Wb : null; } } static Stream stdout; static readonly object outLock = new object(); static JavaScriptSerializer json = new JavaScriptSerializer(); static IntPtr owner = IntPtr.Zero; static IntPtr appliedOwner = IntPtr.Zero; static bool wantVisible = false; static int topOffset = 0; static System.Windows.Forms.Timer timer; static int currentEmulation = 0; static int zoomPercent = 0; // 0 = follow Windows display scaling static int appliedZoom = 100; static bool cookieReverse = true; static string printPreset = "standard"; // "dock" mode: real Edge IE-mode window placed over the Chrome tab static bool dockMode = false; static IntPtr dock = IntPtr.Zero; static List preWindows = new List(); static DateTime dockSearchUntil = DateTime.MinValue; static Rectangle lastDockRect = Rectangle.Empty; public static void Run() { clock.Start(); // Does not modify IE FormSuggest registry settings; password prompt is handled in Chrome extension UI. try { bootMs = (long)(DateTime.Now - Process.GetCurrentProcess().StartTime).TotalMilliseconds; } catch (Exception) { } Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); Application.ThreadException += delegate (object so, System.Threading.ThreadExceptionEventArgs ev) { Log("UI: " + ev.Exception); }; AppDomain.CurrentDomain.UnhandledException += delegate (object so, UnhandledExceptionEventArgs ev) { Log("FATAL: " + ev.ExceptionObject); }; Log("started (" + (IntPtr.Size * 8) + "bit) bootMs=" + bootMs); try { SetProcessDPIAware(); } catch (Exception) { } stdout = Console.OpenStandardOutput(); Dictionary hello = new Dictionary(); hello["evt"] = "hello"; hello["version"] = HelperVersion; hello["boot"] = bootMs; hello["disablePasswordManager"] = IsPasswordManagerDisabledByPolicy(); SendEvt(hello); sync = new Control(); IntPtr h = sync.Handle; Thread t = new Thread(ReadLoop); t.IsBackground = true; t.Start(); Application.Run(new ApplicationContext()); } static bool ReadFull(Stream s, byte[] buf, int count) { int read = 0; while (read < count) { int n = s.Read(buf, read, count - read); if (n <= 0) return false; read += n; } return true; } static void ReadLoop() { try { Stream stdin = Console.OpenStandardInput(); byte[] lenBuf = new byte[4]; while (true) { if (!ReadFull(stdin, lenBuf, 4)) break; int len = BitConverter.ToInt32(lenBuf, 0); if (len <= 0 || len > 1024 * 1024) break; byte[] buf = new byte[len]; if (!ReadFull(stdin, buf, len)) break; string s = Encoding.UTF8.GetString(buf); Dictionary msg = json.Deserialize>(s); sync.BeginInvoke(new MethodInvoker(delegate { Handle(msg); })); } } catch (Exception e) { Log(e.ToString()); } try { sync.BeginInvoke(new MethodInvoker(delegate { Quit(); })); } catch (Exception) { } } static string S(Dictionary m, string k) { object o; if (m.TryGetValue(k, out o) && o != null) return o.ToString(); return ""; } static int I(Dictionary m, string k, int def) { int v; if (int.TryParse(S(m, k), out v)) return v; return def; } static void Handle(Dictionary m) { try { string cmd = S(m, "cmd"); if (cmd != "layout") Log("cmd " + cmd + " " + S(m, "engine")); if (cmd == "open") { Mark("open"); if (S(m, "engine") == "edge") { topOffset = I(m, "top", 0); GrabOwner(); wantVisible = true; OpenEdge(S(m, "url")); EnsureTimer(); Sync(); return; } int fb = I(m, "fallback", 11001); string es = S(m, "emulation"); int emu; if (es == "" || es == "auto") emu = AutoEmulation(S(m, "url"), fb); else if (!int.TryParse(es, out emu)) emu = fb; currentEmulation = emu; zoomPercent = I(m, "zoom", 0); cookieReverse = S(m, "cookieReverse").ToLowerInvariant() != "false"; string pp = S(m, "printPreset"); if (pp.Length > 0) ApplyPrintPreset(pp); SetEmulation(emu); topOffset = I(m, "top", 0); GrabOwner(); EnsureForm(); Mark("form"); wantVisible = true; Navigate(S(m, "url")); Mark("navigate"); Sync(); } else if (cmd == "layout") { topOffset = I(m, "top", topOffset); Sync(); } else if (cmd == "show") { GrabOwner(); wantVisible = true; Sync(); } else if (cmd == "hide") { wantVisible = false; if (form != null) form.Hide(); SetPopupsVisible(false); if (dockMode && dock != IntPtr.Zero) ShowWindow(dock, 0); } else if (cmd == "cookies") { SetCookies(m); } else if (cmd == "devtools") { OpenDevTools(); } else if (cmd == "zoom") { zoomPercent = I(m, "percent", 0); ApplyZoom(); if (form != null) form.ReportDocMode(); } else if (cmd == "print_preset") { ApplyPrintPreset(S(m, "preset")); } else if (cmd == "screenshot") { CaptureScreenshot(); } else if (cmd == "compat_diag") { RunCompatDiag(); } else if (cmd == "autofill") { DoAutofill(S(m, "username"), S(m, "password")); } else if (cmd == "go") { Navigate(S(m, "url")); } else if (cmd == "back") { if (form != null && form.Wb.CanGoBack) form.Wb.GoBack(); } else if (cmd == "forward") { if (form != null && form.Wb.CanGoForward) form.Wb.GoForward(); } else if (cmd == "reload") { if (form != null) form.Wb.Refresh(); } else if (cmd == "stop") { if (form != null) form.Wb.Stop(); } else if (cmd == "print") { if (form != null) form.Wb.ShowPrintDialog(); } else if (cmd == "preview") { if (form != null) form.Wb.ShowPrintPreviewDialog(); } else if (cmd == "pagesetup") { if (form != null) form.Wb.ShowPageSetupDialog(); } else if (cmd == "close") { Quit(); } } catch (Exception e) { Log(e.ToString()); Dictionary d = new Dictionary(); d["evt"] = "error"; d["error"] = e.Message; SendEvt(d); } } // IE zooms pages by the Windows display scaling; the bare WebBrowser control does not, so do it here. static void ApplyZoom() { if (form == null) return; try { int pct = zoomPercent; if (pct <= 0) { int dpi = 0; try { dpi = (int)GetDpiForWindow(owner != IntPtr.Zero ? owner : form.Handle); } catch (Exception) { } if (dpi <= 0) { using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) { dpi = (int)g.DpiX; } } if (dpi < 96) dpi = 96; pct = (int)Math.Round(dpi * 100.0 / 96.0); } appliedZoom = pct; // The old code passed pvaIn by reference (VT_BYREF), which MSHTML rejects, so the zoom never changed. ZoomBrowser(form.Wb, pct); foreach (PopupForm p in popups.ToArray()) { if (!p.IsDisposed) ZoomBrowser(p.Wb, pct); } } catch (Exception e) { Log("zoom: " + e.Message); } } // Apply OLECMDID_OPTICAL_ZOOM (63): ExecWB by value first, then the document's IOleCommandTarget. internal static bool ZoomBrowser(WebBrowser wb, int pct) { if (wb == null || pct <= 0) return false; // IOleCommandTarget.Exec(OLECMDID_OPTICAL_ZOOM=63) directly on the ActiveX control: fast and works in all document modes try { object ax = wb.ActiveXInstance; IEOOleCommandTarget ct = ax as IEOOleCommandTarget; if (ct == null && wb.Document != null) ct = wb.Document.DomDocument as IEOOleCommandTarget; if (ct != null) { object vin = (int)pct, vout = null; int hr = ct.Exec(IntPtr.Zero, 63, 2, ref vin, ref vout); if (hr >= 0) return true; // S_OK (0) or S_FALSE (1) Log("zoom Exec hr=0x" + hr.ToString("X8")); } } catch (Exception e) { Log("zoom Exec: " + e.Message); } try { object ax2 = wb.ActiveXInstance; if (ax2 != null) { object vout = null; ax2.GetType().InvokeMember("ExecWB", BindingFlags.InvokeMethod, null, ax2, new object[] { 63, 2, (int)pct, vout }); return true; } } catch (Exception e) { Log("zoom ExecWB: " + (e.InnerException != null ? e.InnerException.Message : e.Message)); } return false; } // ---- Popups (window.open / target=_blank) open in an IE window inside THIS process ---- // Same process = session cookies (login state), window.opener and POST data are all preserved. static List popups = new List(); static PopupForm pendingPopup = null; static DateTime pendingAt = DateTime.MinValue; static int pendingKind = 0; internal static void OnNewWindow(ref object ppDisp, ref bool cancel, string url, int kind) { try { Log("OnNewWindow fired: kind=" + kind); if (pendingPopup != null && !pendingPopup.IsDisposed && (DateTime.UtcNow - pendingAt).TotalMilliseconds < 500 && pendingPopup.Wb.Url != null && pendingPopup.Wb.Url.ToString() == url) { cancel = true; return; } PopupForm p = new PopupForm(); int n = popups.Count % 8; int dpi = 96; try { dpi = (int)GetDpiForWindow(owner != IntPtr.Zero ? owner : (form != null ? form.Handle : IntPtr.Zero)); } catch (Exception) { } if (dpi < 96) dpi = 96; int w = 620 * dpi / 96, h = 460 * dpi / 96, step = 32 * dpi / 96; RECT orc; if (owner != IntPtr.Zero && GetWindowRect(owner, out orc)) p.Bounds = new Rectangle(orc.Left + 80 * dpi / 96 + n * step, orc.Top + 80 * dpi / 96 + n * step, w, h); else p.Bounds = new Rectangle(150 + n * step, 150 + n * step, w, h); popups.Add(p); p.FormClosed += delegate { Log("PopupForm FormClosed: remaining=" + (popups.Count - 1)); popups.Remove(p); if (pendingPopup == p) pendingPopup = null; }; p.Show(); cancel = true; pendingPopup = p; pendingAt = DateTime.UtcNow; pendingKind = kind; Log("popup navigating directly"); if (!string.IsNullOrEmpty(url)) { p.Wb.Navigate(url); } } catch (Exception e) { Log("newwindow exception: " + e); cancel = true; } } // window.close() in the main page closes the Chrome tab internal static void OnMainWindowClosing() { Dictionary d = new Dictionary(); d["evt"] = "closetab"; SendEvt(d); } internal static int CurrentZoom() { return appliedZoom; } static void SetPopupsVisible(bool visible) { // Never hide independent popup windows when parent tab is hidden/occluded. // Hiding popups causes infinite flicker and disappears from taskbar when maximized over Chrome. return; } // Copy Chrome cookies into the WinINet jar used by the IE engine (so existing logins carry over). static void SetCookies(Dictionary m) { object o; if (!m.TryGetValue("cookies", out o)) return; System.Collections.IEnumerable list = o as System.Collections.IEnumerable; if (list == null) return; int ok = 0, ng = 0; foreach (object it in list) { Dictionary c = it as Dictionary; if (c == null) continue; string name = S(c, "name"), val = S(c, "value"), domain = S(c, "domain"), path = S(c, "path"); bool secure = S(c, "secure").ToLowerInvariant() == "true"; bool httpOnly = S(c, "httpOnly").ToLowerInvariant() == "true"; bool hostOnly = S(c, "hostOnly").ToLowerInvariant() == "true"; if (path.Length == 0) path = "/"; StringBuilder sb = new StringBuilder(); sb.Append(name).Append('=').Append(val); if (!hostOnly && domain.Length > 0) sb.Append("; domain=").Append(domain); sb.Append("; path=").Append(path); double exp; if (double.TryParse(S(c, "expirationDate"), NumberStyles.Float, CultureInfo.InvariantCulture, out exp) || double.TryParse(S(c, "expirationDate"), out exp)) { if (exp > 0) sb.Append("; expires=").Append(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(exp).ToString("r", CultureInfo.InvariantCulture)); } if (secure) sb.Append("; secure"); if (httpOnly) sb.Append("; HttpOnly"); string host = domain.TrimStart('.'); string curl = (secure ? "https://" : "http://") + host + path; if (InternetSetCookieEx(curl, null, sb.ToString(), 0x2000, IntPtr.Zero)) ok++; else ng++; } Log("cookies set ok=" + ok + " failed=" + ng); Mark("cookies"); } // Reverse cookie sync (IE -> Chrome): reads WinINet cookies (including HttpOnly) after navigation/login in IE. internal static void SendReverseCookies(string url) { if (!cookieReverse || string.IsNullOrEmpty(url)) return; if (!(url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))) return; try { int size = 8192; StringBuilder sb = new StringBuilder(size); if (!InternetGetCookieEx(url, null, sb, ref size, 0x2000, IntPtr.Zero)) { if (size <= 0) return; sb = new StringBuilder(size + 64); if (!InternetGetCookieEx(url, null, sb, ref size, 0x2000, IntPtr.Zero)) return; } string raw = sb.ToString(); if (string.IsNullOrEmpty(raw)) return; List> list = new List>(); foreach (string part in raw.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { string kv = part.Trim(); int eq = kv.IndexOf('='); if (eq <= 0) continue; Dictionary c = new Dictionary(); c["name"] = kv.Substring(0, eq).Trim(); c["value"] = kv.Substring(eq + 1).Trim(); list.Add(c); } if (list.Count == 0) return; Dictionary d = new Dictionary(); d["evt"] = "cookies_back"; d["url"] = url; d["cookies"] = list; SendEvt(d); } catch (Exception e) { Log("reverse cookies: " + e.Message); } } // Apply legacy form-printing preset directly to HKCU IE PageSetup registry static void ApplyPrintPreset(string preset) { try { printPreset = string.IsNullOrEmpty(preset) ? "standard" : preset; if (printPreset == "standard") return; using (RegistryKey k = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Internet Explorer\PageSetup")) { if (k != null) { if (printPreset == "clean" || printPreset == "zero") { k.SetValue("header", "", RegistryValueKind.String); k.SetValue("footer", "", RegistryValueKind.String); k.SetValue("Print_Background", "yes", RegistryValueKind.String); } if (printPreset == "zero") { // 0.19685 inches = 5mm margin on all sides (prevents form clipping) k.SetValue("margin_top", "0.196850", RegistryValueKind.String); k.SetValue("margin_bottom", "0.196850", RegistryValueKind.String); k.SetValue("margin_left", "0.196850", RegistryValueKind.String); k.SetValue("margin_right", "0.196850", RegistryValueKind.String); k.SetValue("Shrink_To_Fit", "yes", RegistryValueKind.String); } } } using (RegistryKey m = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Internet Explorer\Main")) { if (m != null && (printPreset == "clean" || printPreset == "zero")) { m.SetValue("Print_Background", "yes", RegistryValueKind.String); } } Log("print preset applied: " + printPreset); } catch (Exception e) { Log("print preset: " + e.Message); } } // Capture the visible IE overlay area as PNG, copy to Windows Clipboard, and send Base64 to Chrome for saving static void CaptureScreenshot() { try { Rectangle r = Rectangle.Empty; if (form != null && form.Visible && form.Width > 0 && form.Height > 0) r = form.Bounds; else if (dockMode && dock != IntPtr.Zero && IsWindowVisible(dock)) { RECT dr; if (GetWindowRect(dock, out dr)) r = Rectangle.FromLTRB(dr.Left, dr.Top, dr.Right, dr.Bottom); } if (r.Width <= 0 || r.Height <= 0) { Dictionary err = new Dictionary(); err["evt"] = "error"; err["error"] = "Capture area is not visible"; SendEvt(err); return; } using (Bitmap bmp = new Bitmap(r.Width, r.Height)) { using (Graphics g = Graphics.FromImage(bmp)) { g.CopyFromScreen(r.Left, r.Top, 0, 0, r.Size, CopyPixelOperation.SourceCopy); } try { Clipboard.SetImage(bmp); } catch (Exception) { } using (MemoryStream ms = new MemoryStream()) { bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png); string b64 = Convert.ToBase64String(ms.ToArray()); Dictionary d = new Dictionary(); d["evt"] = "screenshot"; d["dataUrl"] = "data:image/png;base64," + b64; d["width"] = r.Width; d["height"] = r.Height; d["title"] = (form != null && form.Wb != null) ? (form.Wb.DocumentTitle ?? "") : ""; SendEvt(d); } } } catch (Exception e) { Log("screenshot: " + e.Message); Dictionary err = new Dictionary(); err["evt"] = "error"; err["error"] = "Screenshot failed: " + e.Message; SendEvt(err); } } // Inspect the live IE DOM for legacy IE dependencies (ActiveX, VBScript, documentMode, legacy JS APIs) static void RunCompatDiag() { try { if (form == null || form.Wb == null || form.Wb.Document == null) return; string jsCode = @"(function(){ try { var d = document, r = []; var dm = d.documentMode || 5; var cm = d.compatMode || ''; var xua = ''; var metas = d.getElementsByTagName('meta'); for (var i=0; i= 0 || lg.indexOf('vbs') >= 0) vbs++; if (scs[m].getAttribute('for') && scs[m].getAttribute('event')) evtFor++; if (scs[m].text) srcText += '\n' + scs[m].text; } var html = d.documentElement ? d.documentElement.innerHTML : ''; var bag = srcText + '\n' + html; var apis = []; if (bag.indexOf('ActiveXObject') >= 0) apis.push('new ActiveXObject()'); if (bag.indexOf('document.all') >= 0) apis.push('document.all'); if (bag.indexOf('attachEvent') >= 0) apis.push('attachEvent / detachEvent'); if (bag.indexOf('showModalDialog') >= 0) apis.push('window.showModalDialog'); if (bag.indexOf('createPopup') >= 0) apis.push('window.createPopup'); if (bag.indexOf('execScript') >= 0) apis.push('window.execScript'); if (bag.indexOf('clipboardData') >= 0) apis.push('window.clipboardData'); if (bag.indexOf('behavior:') >= 0 || bag.indexOf('expression(') >= 0) apis.push('CSS behavior / expression()'); var frames = d.getElementsByTagName('frame').length + d.getElementsByTagName('iframe').length; return [dm, cm, xua, axList.length, axList.join(' ; '), vbs, evtFor, apis.join(', '), frames].join('||'); } catch(e) { return 'ERR||' + e.message; } })()"; object res = form.Wb.Document.InvokeScript("eval", new object[] { jsCode }); string raw = res != null ? res.ToString() : ""; string[] p = raw.Split(new string[] { "||" }, StringSplitOptions.None); Dictionary d = new Dictionary(); d["evt"] = "compat_report"; d["url"] = form.Wb.Url != null ? form.Wb.Url.ToString() : ""; d["title"] = form.Wb.DocumentTitle ?? ""; if (p.Length >= 9) { d["docMode"] = p[0]; d["compatMode"] = p[1]; d["xua"] = p[2]; d["activeXCount"] = p[3]; d["activeXDetail"] = p[4]; d["vbscriptCount"] = p[5]; d["eventForCount"] = p[6]; d["legacyApis"] = p[7]; d["frameCount"] = p[8]; } else { d["docMode"] = "?"; d["legacyApis"] = raw; } SendEvt(d); } catch (Exception e) { Log("compat_diag: " + e.Message); Dictionary err = new Dictionary(); err["evt"] = "error"; err["error"] = "Compatibility check failed: " + e.Message; SendEvt(err); } } static void OpenDevTools() { string sr = Environment.GetEnvironmentVariable("SystemRoot") ?? @"C:\Windows"; string[] c = new string[] { sr + @"\System32\F12\IEChooser.exe", sr + @"\SysWOW64\F12\IEChooser.exe" }; foreach (string x in c) { if (File.Exists(x)) { ProcessStartInfo psi = new ProcessStartInfo(x); psi.UseShellExecute = true; Process.Start(psi); return; } } Dictionary d = new Dictionary(); d["evt"] = "error"; d["error"] = "IE developer tools (F12\\IEChooser.exe) not found on this PC"; SendEvt(d); } static readonly byte[] DpapiEntropy = Encoding.UTF8.GetBytes("IEOpener_DPAPI_v1_Salt"); static bool IsPasswordManagerDisabledByPolicy() { try { using (RegistryKey k = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Policies\IEModeOpener")) { if (k != null && Convert.ToInt32(k.GetValue("DisablePasswordManager", 0)) == 1) return true; } } catch (Exception) { } try { using (RegistryKey k = Registry.CurrentUser.OpenSubKey(@"Software\Policies\IEModeOpener")) { if (k != null && Convert.ToInt32(k.GetValue("DisablePasswordManager", 0)) == 1) return true; } } catch (Exception) { } return false; } static string EncryptDpapi(string plain) { if (string.IsNullOrEmpty(plain)) return ""; if (plain.StartsWith("dpapi:", StringComparison.Ordinal)) return plain; try { byte[] data = Encoding.UTF8.GetBytes(plain); byte[] enc = ProtectedData.Protect(data, DpapiEntropy, DataProtectionScope.CurrentUser); return "dpapi:" + Convert.ToBase64String(enc); } catch (Exception) { return ""; } } static string DecryptDpapi(string token) { if (string.IsNullOrEmpty(token)) return ""; if (!token.StartsWith("dpapi:", StringComparison.Ordinal)) return token; try { byte[] enc = Convert.FromBase64String(token.Substring(6)); byte[] dec = ProtectedData.Unprotect(enc, DpapiEntropy, DataProtectionScope.CurrentUser); return Encoding.UTF8.GetString(dec); } catch (Exception) { return ""; } } static void DoAutofill(string username, string password) { try { if (IsPasswordManagerDisabledByPolicy()) { Log("Autofill blocked by GPO DisablePasswordManager"); return; } password = DecryptDpapi(password); if (form == null || form.Wb == null) return; form.Invoke(new MethodInvoker(delegate { try { HtmlDocument doc = form.Wb.Document; if (doc == null) return; HtmlElement pwField = null; HtmlElement userField = null; // Search document and any child frames List docs = new List(); docs.Add(doc); try { if (doc.Window != null && doc.Window.Frames != null) { for (int i = 0; i < doc.Window.Frames.Count; i++) { try { HtmlDocument fdoc = doc.Window.Frames[i].Document; if (fdoc != null) docs.Add(fdoc); } catch (Exception) { } } } } catch (Exception) { } foreach (HtmlDocument d in docs) { HtmlElementCollection inputs = d.GetElementsByTagName("input"); foreach (HtmlElement el in inputs) { string t = (el.GetAttribute("type") ?? "").ToLower(); if (t == "password") { pwField = el; break; } } if (pwField != null) { foreach (HtmlElement el in inputs) { if (el == pwField) break; string t = (el.GetAttribute("type") ?? "").ToLower(); if (t == "text" || t == "email" || t == "") { userField = el; } } break; } } if (pwField != null) { if (userField != null && !string.IsNullOrEmpty(username)) { userField.Focus(); userField.SetAttribute("value", username); try { userField.InvokeMember("fireEvent", new object[] { "onchange" }); } catch (Exception) { } try { userField.InvokeMember("fireEvent", new object[] { "oninput" }); } catch (Exception) { } } if (!string.IsNullOrEmpty(password)) { pwField.Focus(); pwField.SetAttribute("value", password); try { pwField.InvokeMember("fireEvent", new object[] { "onchange" }); } catch (Exception) { } try { pwField.InvokeMember("fireEvent", new object[] { "oninput" }); } catch (Exception) { } } Log("Autofill executed"); Dictionary res = new Dictionary(); res["evt"] = "autofill_result"; res["status"] = "ok"; SendEvt(res); } else { Log("Autofill: password field not found in DOM"); Dictionary res = new Dictionary(); res["evt"] = "autofill_result"; res["status"] = "not_found"; SendEvt(res); } } catch (Exception ex) { Log("Autofill inner error: " + ex.Message); } })); } catch (Exception e) { Log("DoAutofill error: " + e.Message); } } static string lastReportedPwHash = null; static void CheckAndReportPassword(WebBrowser wb) { try { if (IsPasswordManagerDisabledByPolicy()) return; if (wb == null || wb.Document == null) return; HtmlDocument doc = wb.Document; List docs = new List(); docs.Add(doc); try { if (doc.Window != null && doc.Window.Frames != null) { for (int i = 0; i < doc.Window.Frames.Count; i++) { try { HtmlDocument fdoc = doc.Window.Frames[i].Document; if (fdoc != null) docs.Add(fdoc); } catch (Exception) { } } } } catch (Exception) { } foreach (HtmlDocument d in docs) { HtmlElementCollection inputs = d.GetElementsByTagName("input"); HtmlElement pwEl = null; HtmlElement userEl = null; foreach (HtmlElement el in inputs) { string t = (el.GetAttribute("type") ?? "").ToLower(); if (t == "password") { string pwVal = el.GetAttribute("value"); if (!string.IsNullOrEmpty(pwVal)) { pwEl = el; break; } } } if (pwEl != null) { string pw = pwEl.GetAttribute("value") ?? ""; if (string.IsNullOrEmpty(pw)) continue; foreach (HtmlElement el in inputs) { if (el == pwEl) break; string t = (el.GetAttribute("type") ?? "").ToLower(); if (t == "text" || t == "email" || t == "") { string val = el.GetAttribute("value"); if (!string.IsNullOrEmpty(val)) { userEl = el; } } } string user = userEl != null ? (userEl.GetAttribute("value") ?? "") : ""; string currentUrl = wb.Url != null ? wb.Url.ToString() : ""; if (string.IsNullOrEmpty(currentUrl) || currentUrl.StartsWith("about:", StringComparison.OrdinalIgnoreCase)) continue; string hash = currentUrl + "|" + user + "|" + pw; if (hash == lastReportedPwHash) return; lastReportedPwHash = hash; string encPw = EncryptDpapi(pw); if (string.IsNullOrEmpty(encPw)) continue; Log("Password submission event (DPAPI encrypted) sent to extension"); Dictionary evt = new Dictionary(); evt["evt"] = "password_submitted"; evt["url"] = currentUrl; evt["username"] = user; evt["password"] = encPw; evt["dpapi"] = true; evt["title"] = wb.DocumentTitle ?? ""; SendEvt(evt); break; } } } catch (Exception e) { Log("CheckAndReportPassword error: " + e.Message); } } static void HookFormSubmits(WebBrowser wb) { try { if (wb == null || wb.Document == null) return; HtmlElementCollection forms = wb.Document.Forms; if (forms != null) { foreach (HtmlElement f in forms) { try { f.AttachEventHandler("onsubmit", delegate { CheckAndReportPassword(wb); }); } catch (Exception) { } } } } catch (Exception) { } } static void Navigate(string url) { if (form == null) return; if (!(url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))) return; form.Wb.Navigate(url); } static void EnsureForm() { if (form != null) return; form = new OverlayForm(); IntPtr h = form.Handle; timer = new System.Windows.Forms.Timer(); timer.Interval = 80; timer.Tick += delegate { try { Sync(); } catch (Exception e) { Log("tick: " + e); } }; timer.Start(); } static string ManagedListPath() { try { using (RegistryKey k = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Policies\Microsoft\Edge")) { if (k == null) return null; object v = k.GetValue("InternetExplorerIntegrationSiteList"); if (v == null) return null; string s = v.ToString(); if (s.StartsWith("file:///", StringComparison.OrdinalIgnoreCase)) return Uri.UnescapeDataString(s.Substring(8)).Replace('/', '\\'); if (s.Length > 2 && s[1] == ':') return s; return null; } } catch (Exception) { return null; } } // Real IE shows intranet sites (single-label names / private IPs) in Compatibility View (IE7 mode) by default. static bool LooksIntranet(string host) { if (host.IndexOf('.') < 0) return true; System.Net.IPAddress ip; if (System.Net.IPAddress.TryParse(host, out ip) && ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { byte[] b = ip.GetAddressBytes(); if (b[0] == 10) return true; if (b[0] == 172 && b[1] >= 16 && b[1] <= 31) return true; if (b[0] == 192 && b[1] == 168) return true; } return false; } // Pick the document mode from the Enterprise Mode site list (compat-mode), like Edge IE mode does. static int AutoEmulation(string url, int fallback) { try { Uri u = new Uri(url); string host = u.Host.ToLowerInvariant(); int dflt = LooksIntranet(host) ? 7000 : fallback; string path = ManagedListPath(); if (path == null || !File.Exists(path)) return dflt; string target = (host + u.AbsolutePath).ToLowerInvariant().TrimEnd('/'); XmlDocument x = new XmlDocument(); x.Load(path); string bestMode = null; int bestLen = -1; foreach (XmlNode n in x.DocumentElement.SelectNodes("site")) { string su = n.Attributes["url"] == null ? "" : n.Attributes["url"].Value.ToLowerInvariant(); int i = su.IndexOf("://"); if (i >= 0) su = su.Substring(i + 3); su = su.TrimEnd('/'); if (su.Length == 0) continue; bool match = (target == su) || target.StartsWith(su + "/"); if (!match && su.IndexOf('/') < 0) match = (host == su) || host.EndsWith("." + su); if (match && su.Length > bestLen) { XmlNode cm = n.SelectSingleNode("compat-mode"); bestMode = (cm == null) ? "" : cm.InnerText.Trim(); bestLen = su.Length; } } if (bestMode == null) return dflt; switch (bestMode.ToLowerInvariant()) { case "ie8enterprise": return 8000; case "ie7enterprise": return 7000; case "ie11": return 11001; case "ie10": return 10001; case "ie9": return 9999; case "ie8": return 8888; case "ie7": return 7000; case "ie5": return 7000; default: return dflt; } } catch (Exception) { return fallback; } } static void SetEmulation(int v) { try { string exe = Process.GetCurrentProcess().ProcessName + ".exe"; using (RegistryKey k = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION")) { k.SetValue(exe, v, RegistryValueKind.DWord); } } catch (Exception) { } } static bool IsChrome(IntPtr h) { StringBuilder sb = new StringBuilder(256); GetClassName(h, sb, 256); return sb.ToString() == "Chrome_WidgetWin_1"; } static void GrabOwner() { IntPtr fg = GetForegroundWindow(); if (fg != IntPtr.Zero && fg != dock && IsChrome(fg) && ProcName(fg) != "msedge") owner = fg; } static void ApplyOwner() { if (form == null || owner == IntPtr.Zero) return; SetOwnerOf(form.Handle, owner); } static void SetOwnerOf(IntPtr w, IntPtr own) { if (IntPtr.Size == 8) SetWindowLongPtr64(w, -8, own); else SetWindowLong32(w, -8, own.ToInt32()); } static string ProcName(IntPtr h) { try { uint pid; GetWindowThreadProcessId(h, out pid); return Process.GetProcessById((int)pid).ProcessName.ToLowerInvariant(); } catch (Exception) { return ""; } } static List EdgeWindows() { List list = new List(); EnumWindows(delegate (IntPtr h, IntPtr l) { if (IsWindowVisible(h) && IsChrome(h) && ProcName(h) == "msedge") list.Add(h); return true; }, IntPtr.Zero); return list; } static string FindEdge() { string[] c = new string[] { Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)") ?? "", @"Microsoft\Edge\Application\msedge.exe"), Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles") ?? "", @"Microsoft\Edge\Application\msedge.exe") }; foreach (string x in c) if (File.Exists(x)) return x; return null; } static void OpenEdge(string url) { if (!(url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))) throw new Exception("invalid url"); string edge = FindEdge(); if (edge == null) throw new Exception("msedge.exe not found"); preWindows = EdgeWindows(); dockMode = true; dock = IntPtr.Zero; lastDockRect = Rectangle.Empty; dockSearchUntil = DateTime.UtcNow.AddSeconds(20); ProcessStartInfo psi = new ProcessStartInfo(edge, "--new-window \"" + url + "\""); psi.UseShellExecute = true; // do not inherit our stdin/stdout pipes Process.Start(psi); } static void StripFrame(IntPtr h) { const int GWL_STYLE = -16; long st = (IntPtr.Size == 8) ? GetWindowLongPtr64(h, GWL_STYLE).ToInt64() : (long)GetWindowLong32(h, GWL_STYLE); st &= ~(0x00C00000L | 0x00040000L | 0x00080000L | 0x00020000L | 0x00010000L); if (IntPtr.Size == 8) SetStyle64(h, GWL_STYLE, new IntPtr(st)); else SetStyle32(h, GWL_STYLE, unchecked((int)st)); } static void DockSync() { if (dock == IntPtr.Zero) { if (dockSearchUntil != DateTime.MinValue && DateTime.UtcNow > dockSearchUntil) { dockSearchUntil = DateTime.MinValue; Dictionary d0 = new Dictionary(); d0["evt"] = "error"; d0["error"] = "Edge window not found (20s timeout)"; SendEvt(d0); return; } if (dockSearchUntil == DateTime.MinValue) return; foreach (IntPtr h in EdgeWindows()) { if (!preWindows.Contains(h)) { dock = h; break; } } if (dock == IntPtr.Zero) return; ShowWindow(dock, 9); // SW_RESTORE (in case it opened maximized) StripFrame(dock); appliedOwner = IntPtr.Zero; lastDockRect = Rectangle.Empty; } if (!IsWindow(dock)) { dock = IntPtr.Zero; dockMode = false; Dictionary d = new Dictionary(); d["evt"] = "error"; d["error"] = "Edge window was closed"; SendEvt(d); return; } if (!wantVisible || owner == IntPtr.Zero || !IsWindow(owner) || IsIconic(owner) || !IsWindowVisible(owner)) { if (IsWindowVisible(dock)) ShowWindow(dock, 0); // SW_HIDE return; } if (appliedOwner != owner) { SetOwnerOf(dock, owner); appliedOwner = owner; lastDockRect = Rectangle.Empty; } Rectangle r = GetContentRect(owner); if (r.Width <= 0 || r.Height <= 0) return; r = new Rectangle(r.Left, r.Top + topOffset, r.Width, Math.Max(0, r.Height - topOffset)); bool shown = IsWindowVisible(dock); if (!shown) ShowWindow(dock, 8); // SW_SHOWNA if (!shown || r != lastDockRect) { // NOACTIVATE | NOZORDER | FRAMECHANGED SetWindowPos(dock, IntPtr.Zero, r.Left, r.Top, r.Width, r.Height, 0x0010 | 0x0004 | 0x0020); lastDockRect = r; } } static void EnsureTimer() { if (timer != null) return; timer = new System.Windows.Forms.Timer(); timer.Interval = 80; timer.Tick += delegate { try { Sync(); } catch (Exception e) { Log("tick: " + e); } }; timer.Start(); } static Rectangle GetContentRect(IntPtr win) { long bestArea = 0; Rectangle best = Rectangle.Empty; EnumChildWindows(win, delegate (IntPtr h, IntPtr l) { StringBuilder sb = new StringBuilder(128); GetClassName(h, sb, 128); if (sb.ToString() == "Chrome_RenderWidgetHostHWND" && IsWindowVisible(h)) { RECT r; GetWindowRect(h, out r); long area = (long)(r.Right - r.Left) * (r.Bottom - r.Top); if (area > bestArea) { bestArea = area; best = Rectangle.FromLTRB(r.Left, r.Top, r.Right, r.Bottom); } } return true; }, IntPtr.Zero); if (bestArea > 0) return best; // Fallback: estimate from the top-level window RECT w; GetWindowRect(win, out w); int dpi = 96; try { dpi = (int)GetDpiForWindow(win); } catch (Exception) { } int top = (int)(120 * dpi / 96.0); int border = (int)(8 * dpi / 96.0); return Rectangle.FromLTRB(w.Left + border, w.Top + top, w.Right - border, w.Bottom - border); } static void Sync() { if (dockMode) { DockSync(); return; } if (form == null) return; if (!wantVisible || owner == IntPtr.Zero || !IsWindow(owner) || IsIconic(owner) || !IsWindowVisible(owner)) { if (form.Visible) form.Hide(); SetPopupsVisible(false); return; } SetPopupsVisible(true); if (appliedOwner != owner) { ApplyOwner(); appliedOwner = owner; } Rectangle r = GetContentRect(owner); if (r.Width <= 0 || r.Height <= 0) return; r = new Rectangle(r.Left, r.Top + topOffset, r.Width, Math.Max(0, r.Height - topOffset)); if (!form.Visible) { form.Bounds = r; form.Show(); } else if (form.Bounds != r) { form.Bounds = r; } } static void Quit() { try { if (timer != null) timer.Stop(); if (dockMode && dock != IntPtr.Zero && IsWindow(dock)) PostMessage(dock, 0x0010, IntPtr.Zero, IntPtr.Zero); // WM_CLOSE if (form != null) { form.Hide(); form.Dispose(); } } catch (Exception) { } Environment.Exit(0); } static void SendEvt(Dictionary d) { try { byte[] b = Encoding.UTF8.GetBytes(json.Serialize(d)); lock (outLock) { stdout.Write(BitConverter.GetBytes(b.Length), 0, 4); stdout.Write(b, 0, b.Length); stdout.Flush(); } } catch (Exception) { } } internal static void Log(string s) { try { string dir = Path.Combine(Environment.GetEnvironmentVariable("LOCALAPPDATA"), "IEModeOpener"); string logPath = Path.Combine(dir, "ieopener.log"); FileInfo fi = new FileInfo(logPath); if (fi.Exists && fi.Length > 524288) { File.WriteAllText(logPath, DateTime.Now.ToString("HH:mm:ss.fff") + " [log rotated at 512KB]\r\n"); } File.AppendAllText(logPath, DateTime.Now.ToString("HH:mm:ss.fff") + " [" + System.Diagnostics.Process.GetCurrentProcess().Id + "] " + s + "\r\n"); } catch (Exception) { } } class OverlayForm : Form { public IEOBrowser Wb; public OverlayForm() { FormBorderStyle = FormBorderStyle.None; ShowInTaskbar = false; StartPosition = FormStartPosition.Manual; Wb = new IEOBrowser(); Wb.Dock = DockStyle.Fill; Wb.ScriptErrorsSuppressed = true; Controls.Add(Wb); Wb.Navigating += delegate { CheckAndReportPassword(Wb); }; Wb.Navigated += delegate { MarkOnce("navigated"); Report("nav"); }; Wb.DocumentTitleChanged += delegate { Report("title"); }; Wb.DocumentCompleted += delegate { if (Wb.ReadyState == WebBrowserReadyState.Complete) { MarkOnce("completed"); ApplyZoom(); ReportDocMode(); HookFormSubmits(Wb); if (Wb.Url != null) SendReverseCookies(Wb.Url.ToString()); } }; // Popups are now handled by IEOBrowser (NewWindow2/3 -> in-process PopupForm); OnNewWindow below is no longer used. Wb.PreviewKeyDown += delegate (object so, PreviewKeyDownEventArgs ev) { if (ev.KeyCode == Keys.F12) OpenDevTools(); }; } protected override bool ShowWithoutActivation { get { return true; } } void Report(string evt) { Dictionary d = new Dictionary(); d["evt"] = evt; d["url"] = Wb.Url != null ? Wb.Url.ToString() : ""; d["title"] = Wb.DocumentTitle ?? ""; SendEvt(d); } public void ReportDocMode() { string dm = ""; string ua = ""; try { object o = Wb.Document.InvokeScript("eval", new object[] { "document.documentMode" }); if (o != null) dm = o.ToString(); object u = Wb.Document.InvokeScript("eval", new object[] { "navigator.userAgent" }); if (u != null) ua = u.ToString(); } catch (Exception) { } Dictionary d = new Dictionary(); d["evt"] = "docmode"; d["docmode"] = dm; d["emulation"] = currentEmulation; d["bits"] = IntPtr.Size * 8; d["boot"] = bootMs; d["marks"] = new Dictionary(marks); d["zoom"] = appliedZoom; d["ua"] = ua; SendEvt(d); } void OnNewWindow(object sender, System.ComponentModel.CancelEventArgs e) { string u = Wb.StatusText; if (!string.IsNullOrEmpty(u) && (u.StartsWith("http://") || u.StartsWith("https://"))) { e.Cancel = true; Dictionary d = new Dictionary(); d["evt"] = "newwindow"; d["url"] = u; SendEvt(d); } } } [ComVisible(true)] public class PopupScriptBridge { Form form; public PopupScriptBridge(Form f) { form = f; } public object GetOpener() { try { if (IEOpenerHost.MainBrowser != null && IEOpenerHost.MainBrowser.Document != null) { return IEOpenerHost.MainBrowser.Document.Window.DomWindow; } } catch (Exception ex) { IEOpenerHost.Log("GetOpener err: " + ex.Message); } return null; } public void CloseWindow() { try { Log("PopupScriptBridge: CloseWindow called, posting WM_CLOSE"); if (form != null && !form.IsDisposed) { PostMessage(form.Handle, 0x0010, IntPtr.Zero, IntPtr.Zero); form.BeginInvoke(new MethodInvoker(delegate { try { form.Close(); form.Dispose(); } catch (Exception) { } })); } } catch (Exception ex) { Log("CloseWindow err: " + ex.Message); } } } // Separate IE window for popups, living in the same process as the tab (shares session/login). public class PopupForm : Form { public IEOBrowser Wb; protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x00040000; // WS_EX_APPWINDOW (force taskbar icon even when maximized) return cp; } } protected override void OnResize(EventArgs e) { base.OnResize(e); Log("popup OnResize: WindowState=" + WindowState + " Size=" + Size); } public PopupForm() { Text = "IE Popup"; StartPosition = FormStartPosition.Manual; ShowInTaskbar = true; FormBorderStyle = FormBorderStyle.Sizable; DoubleBuffered = true; Wb = new IEOBrowser(); Wb.Dock = DockStyle.Fill; Wb.ScriptErrorsSuppressed = true; Wb.ObjectForScripting = new PopupScriptBridge(this); Controls.Add(Wb); CreateControl(); Wb.CreateControl(); try { IntPtr h = Handle; IntPtr hw = Wb.Handle; } catch (Exception) { } Shown += delegate { PerformLayout(); try { Wb.Focus(); } catch (Exception) { } }; Resize += delegate { PerformLayout(); }; Wb.Navigating += delegate { if (pendingPopup == this) pendingPopup = null; CheckAndReportPassword(Wb); }; Wb.Navigated += delegate { string u = Wb.Url != null ? Wb.Url.ToString() : ""; if (!string.IsNullOrEmpty(u) && u != "about:blank") Text = u; }; Wb.DocumentTitleChanged += delegate { string t = Wb.DocumentTitle; if (!string.IsNullOrEmpty(t)) Text = t; }; Wb.DocumentCompleted += delegate { if (Wb.ReadyState == WebBrowserReadyState.Complete) { HookFormSubmits(Wb); try { if (Wb.Document != null) { Wb.Document.InvokeScript("eval", new object[] { "try { " + " window.close = function() { try { window.external.CloseWindow(); } catch(e){} }; " + " try { " + " var _op = window.external.GetOpener(); " + " if (_op) { " + " try { window.opener = _op; } catch(e1) { " + " try { Object.defineProperty(window, 'opener', { value: _op, writable: true, configurable: true }); } catch(e2){} " + " } " + " } " + " } catch(e3){} " + "} catch(e){}" }); } } catch (Exception) { } ZoomBrowser(Wb, appliedZoom); if (Wb.Url != null) SendReverseCookies(Wb.Url.ToString()); PerformLayout(); try { Wb.Invalidate(true); Wb.Update(); } catch (Exception) { } } }; Wb.PreviewKeyDown += delegate (object so, PreviewKeyDownEventArgs ev) { if (ev.KeyCode == Keys.F12) OpenDevTools(); }; } public void SetAddress(string u) { if (!string.IsNullOrEmpty(u)) Text = u; } public int ChromeHeight { get { return 0; } } } // Called from IEOBrowserEvents (window.moveTo/resizeTo, window.open features) internal static void OnWindowSet(IEOBrowser b, int kind, int v) { try { PopupForm p = b.FindForm() as PopupForm; if (p == null || p.IsDisposed) return; // never move/resize the overlay on the Chrome tab if (p.WindowState != FormWindowState.Normal) return; // ignore move/resize when maximized/minimized double z = appliedZoom > 0 ? appliedZoom / 100.0 : 1.0; int px = (int)Math.Round(v * z); if (kind == 0) p.Left = px; else if (kind == 1) p.Top = px; else if (kind == 2) p.ClientSize = new Size(Math.Max(px, 120), p.ClientSize.Height); else if (kind == 3) p.ClientSize = new Size(p.ClientSize.Width, Math.Max(px, 80) + p.ChromeHeight); p.PerformLayout(); try { if (p.Wb != null) { p.Wb.Invalidate(true); p.Wb.Update(); } } catch (Exception) { } } catch (Exception e) { Log("windowset: " + e.Message); } } internal static void OnWindowClosing(IEOBrowser b, ref bool cancel) { try { Log("windowclosing fired, allowing close (cancel=false)"); cancel = false; // Do not cancel MSHTML window closure! Form f = b != null ? b.FindForm() : null; PopupForm pf = f as PopupForm; if (pf != null) { Log("closing PopupForm safely via PostMessage WM_CLOSE"); PostMessage(pf.Handle, 0x0010, IntPtr.Zero, IntPtr.Zero); pf.BeginInvoke(new MethodInvoker(delegate { try { pf.Close(); pf.Dispose(); } catch (Exception) { } })); return; } foreach (PopupForm pf2 in new List(popups)) { if (pf2 != null && !pf2.IsDisposed && pf2.Wb == b) { Log("closing pf2 safely via BeginInvoke"); pf2.BeginInvoke(new MethodInvoker(delegate { try { pf2.Close(); pf2.Dispose(); } catch (Exception ex) { Log("pf2 close err: " + ex.Message); } })); return; } } OnMainWindowClosing(); } catch (Exception e) { Log("windowclosing: " + e.Message); } } } // ---- COM declarations used for popups and zoom ---- [ComImport, Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IEOOleCommandTarget { [PreserveSig] int QueryStatus(IntPtr pguidCmdGroup, uint cCmds, IntPtr prgCmds, IntPtr pCmdText); [PreserveSig] int Exec(IntPtr pguidCmdGroup, uint nCmdID, uint nCmdexecopt, ref object pvaIn, ref object pvaOut); } [ComImport, Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface IEODWebBrowserEvents2 { [DispId(251)] void NewWindow2([In, Out, MarshalAs(UnmanagedType.IDispatch)] ref object ppDisp, [In, Out] ref bool Cancel); [DispId(262)] void WindowSetResizable([In] bool Resizable); [DispId(263)] void WindowClosing([In] bool IsChildWindow, [In, Out] ref bool Cancel); [DispId(264)] void WindowSetLeft([In] int Left); [DispId(265)] void WindowSetTop([In] int Top); [DispId(266)] void WindowSetWidth([In] int Width); [DispId(267)] void WindowSetHeight([In] int Height); [DispId(273)] void NewWindow3([In, Out, MarshalAs(UnmanagedType.IDispatch)] ref object ppDisp, [In, Out] ref bool Cancel, [In] uint dwFlags, [In, MarshalAs(UnmanagedType.BStr)] string bstrUrlContext, [In, MarshalAs(UnmanagedType.BStr)] string bstrUrl); } [StructLayout(LayoutKind.Sequential)] public struct DOCHOSTUIINFO { public uint cbSize; public uint dwFlags; public uint dwDoubleClick; public IntPtr pchHostCss; public IntPtr pchHostNS; } [ComImport, Guid("bd3f23c0-d43e-11cf-893b-00aa00bdce1a"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IDocHostUIHandler { [PreserveSig] int ShowContextMenu(uint dwID, IntPtr ppt, IntPtr pcmdtReserved, IntPtr pdispReserved); [PreserveSig] int GetHostInfo(ref DOCHOSTUIINFO pInfo); [PreserveSig] int ShowUI(uint dwID, IntPtr pActiveObject, IntPtr pCommandTarget, IntPtr pFrame, IntPtr pDoc); [PreserveSig] int HideUI(); [PreserveSig] int UpdateUI(); [PreserveSig] int EnableModeless(bool fEnable); [PreserveSig] int OnDocWindowActivate(bool fActivate); [PreserveSig] int OnFrameWindowActivate(bool fActivate); [PreserveSig] int ResizeBorder(IntPtr prcBorder, IntPtr pUIWindow, bool fRSIObject); [PreserveSig] int TranslateAccelerator(IntPtr lpMsg, IntPtr pguidCmdGroup, uint nCmdID); [PreserveSig] int GetOptionKeyPath(out IntPtr pbstrKeyPath, uint dw); [PreserveSig] int GetDropTarget(IntPtr pDropTarget, out IntPtr ppDropTarget); [PreserveSig] int GetExternal(out IntPtr ppDispatch); [PreserveSig] int TranslateUrl(uint dwTranslate, IntPtr pchURL, out IntPtr ppchURL); [PreserveSig] int FilterDataObject(IntPtr pDataObject, out IntPtr ppDataObject); } [ComImport, Guid("3050f3f0-98b5-11cf-bb82-00aa00bdce0b"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ICustomDoc { void SetUIHandler(IDocHostUIHandler pUIHandler); } [ClassInterface(ClassInterfaceType.None), ComVisible(true)] public class IEOBrowserEvents : StandardOleMarshalObject, IEODWebBrowserEvents2 { IEOBrowser b; public IEOBrowserEvents(IEOBrowser browser) { b = browser; } public void NewWindow2(ref object ppDisp, ref bool Cancel) { IEOpenerHost.OnNewWindow(ref ppDisp, ref Cancel, "", 2); } public void NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl) { IEOpenerHost.OnNewWindow(ref ppDisp, ref Cancel, bstrUrl, 3); } public void WindowClosing(bool IsChildWindow, ref bool Cancel) { IEOpenerHost.OnWindowClosing(b, ref Cancel); } public void WindowSetResizable(bool Resizable) { } public void WindowSetLeft(int Left) { IEOpenerHost.OnWindowSet(b, 0, Left); } public void WindowSetTop(int Top) { IEOpenerHost.OnWindowSet(b, 1, Top); } public void WindowSetWidth(int Width) { IEOpenerHost.OnWindowSet(b, 2, Width); } public void WindowSetHeight(int Height) { IEOpenerHost.OnWindowSet(b, 3, Height); } } // WebBrowser that also listens to DWebBrowserEvents2 (NewWindow3 gives us ppDisp, which the stock control hides) public class IEOBrowser : WebBrowser, IDocHostUIHandler { const uint DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE = 0x00004000; const uint DOCHOSTUIFLAG_THEME = 0x00040000; AxHost.ConnectionPointCookie cookie; IEOBrowserEvents sink; public IEOBrowser() { } public void ApplyUIHandler() { try { if (Document != null && Document.DomDocument != null) { ICustomDoc cd = Document.DomDocument as ICustomDoc; if (cd != null) { cd.SetUIHandler(this); } } } catch (Exception ex) { IEOpenerHost.Log("SetUIHandler error: " + ex.Message); } } protected override void AttachInterfaces(object nativeWindow) { base.AttachInterfaces(nativeWindow); ApplyUIHandler(); } protected override void DetachInterfaces() { try { if (Document != null && Document.DomDocument != null) { ICustomDoc cd = Document.DomDocument as ICustomDoc; if (cd != null) cd.SetUIHandler(null); } } catch (Exception) { } base.DetachInterfaces(); } int IDocHostUIHandler.GetHostInfo(ref DOCHOSTUIINFO info) { info.cbSize = (uint)Marshal.SizeOf(typeof(DOCHOSTUIINFO)); info.dwFlags |= (DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE | DOCHOSTUIFLAG_THEME); return 0; } int IDocHostUIHandler.ShowContextMenu(uint dwID, IntPtr ppt, IntPtr pcmdtReserved, IntPtr pdispReserved) { return 1; } int IDocHostUIHandler.ShowUI(uint dwID, IntPtr pActiveObject, IntPtr pCommandTarget, IntPtr pFrame, IntPtr pDoc) { return 1; } int IDocHostUIHandler.HideUI() { return 0; } int IDocHostUIHandler.UpdateUI() { return 0; } int IDocHostUIHandler.EnableModeless(bool fEnable) { return 0; } int IDocHostUIHandler.OnDocWindowActivate(bool fActivate) { return 0; } int IDocHostUIHandler.OnFrameWindowActivate(bool fActivate) { return 0; } int IDocHostUIHandler.ResizeBorder(IntPtr prcBorder, IntPtr pUIWindow, bool fRSIObject) { return 0; } int IDocHostUIHandler.TranslateAccelerator(IntPtr lpMsg, IntPtr pguidCmdGroup, uint nCmdID) { return 1; } int IDocHostUIHandler.GetOptionKeyPath(out IntPtr pbstrKeyPath, uint dw) { pbstrKeyPath = IntPtr.Zero; return 1; } int IDocHostUIHandler.GetDropTarget(IntPtr pDropTarget, out IntPtr ppDropTarget) { ppDropTarget = IntPtr.Zero; return 1; } int IDocHostUIHandler.GetExternal(out IntPtr ppDispatch) { ppDispatch = IntPtr.Zero; return 1; } int IDocHostUIHandler.TranslateUrl(uint dwTranslate, IntPtr pchURL, out IntPtr ppchURL) { ppchURL = IntPtr.Zero; return 1; } int IDocHostUIHandler.FilterDataObject(IntPtr pDataObject, out IntPtr ppDataObject) { ppDataObject = IntPtr.Zero; return 1; } public object ApplicationDisp { get { try { object ax = ActiveXInstance; if (ax != null) { return ax.GetType().InvokeMember("Application", BindingFlags.GetProperty, null, ax, null); } } catch (Exception e) { IEOpenerHost.Log("GetApplication err: " + e.Message); } return null; } } protected override void CreateSink() { base.CreateSink(); try { sink = new IEOBrowserEvents(this); cookie = new AxHost.ConnectionPointCookie(ActiveXInstance, sink, typeof(IEODWebBrowserEvents2)); } catch (Exception e) { IEOpenerHost.Log("sink: " + e.Message); } try // RegisterAsBrowser: lets target="name" / window.open(url, "name") find this window { object ax = ActiveXInstance; if (ax != null) ax.GetType().InvokeMember("RegisterAsBrowser", BindingFlags.SetProperty, null, ax, new object[] { true }); } catch (Exception e) { IEOpenerHost.Log("registerAsBrowser: " + e.Message); } } protected override void DetachSink() { try { if (cookie != null) { cookie.Disconnect(); cookie = null; } } catch (Exception) { } base.DetachSink(); } } '@ foreach ($k in $files.Keys) { [IO.File]::WriteAllText((Join-Path $dst $k), $files[$k], $utf8) } Remove-Item (Join-Path $dst 'IEOpenerHost.dll') -Force -ErrorAction SilentlyContinue Remove-Item (Join-Path $dst 'IEOpenerHost.exe') -Force -ErrorAction SilentlyContinue Remove-Item (Join-Path $dst 'ietab.*') -Force -ErrorAction SilentlyContinue function Expand-GzipBase64([string]$b64, [string]$outPath) { $gzBytes = [Convert]::FromBase64String($b64) $msIn = New-Object IO.MemoryStream(,$gzBytes) $gz = New-Object IO.Compression.GZipStream($msIn, [IO.Compression.CompressionMode]::Decompress) $fsOut = [IO.File]::Create($outPath) $gz.CopyTo($fsOut) $fsOut.Close() $gz.Close() $msIn.Close() } $prebuiltExeB64 = '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' $prebuiltDllB64 = 'H4sIAKGU8WoC/8y9CXxcVfU4ft+bmTdbtjeTzEz2SdNlmq1N0n2hTZO0DXRPSwsU0kkySaedzBveTNqG2hJARRRQQFFQviyCoIACgoCKQhW+IqDgxtoqCgpfUFlcQBF+55x735s3k7RA5fP//Bty555zt3PPPdtdJqw99XPMxhizw+977zF2D+P/lrP3/zcOv0W13y1id7ofq7tHWvNY3ead8XQ4pWvDenQkPBBNJrVMuD8W1keT4Xgy3LW+NzyiDcZaCgs9U0UfG7oZWyPZ2FWff32X0e/vmFznlbyMPQ6AwnFH/gJJGHMSJiWUlzndjGU/2XKJ8PjPxpZ/Aqvif9lP84P+fQ76PYnxfu+RJ5lkWGIF7Dj+AX0uC+gCeLUFbsnE9mXg84WfiXk9zky6LV3saNHT+gDkOW0Sn+gvcuvBWi1v0WMJDSoWCJqpr99MqLcin8z7/8I/V9PwDjZ7Jwz6ScHl4/jnn21nWzml6kGg1S4fxFXSnIx5NGCIp/IiKJI8SkCHz9R1SlC+TgnphZQv5y00N9S7sBaqXadU6H4qingAFwEqlYZNohYIiKdZkSNBRFZEKnkZyIu9WS5toMz+CCQNp+rl0IdNK8Iuis1+TtXrCV2Si2asEuawk7NQ5dSrWOrDxI/zKMVcGSQFPjkSgM9d46BD9iO26UdYCOnxHKxFMtTSdxUQLiUdAtQ4oggfKcf2FVgtbFRbg9UqsRqiCK9VAVhB7Cp0B/R25IM7GKkGbM2pF7Yge9whfRWhyw8iAZxn7iyvIsBxZTrRFanBzmEZ7Gmo5fEoehRa6nFINBgN4FGEP5GFL4FstluB/DIgI83Q64WzTWRkFRJfh/07kHhMtCkAToeJVWMZMNqTBpX3eJ1BbRp8OrXpiJqBhMIaeRqkKpQeD5vawmwzSHx+wFwP8bx/toNUBGhRA57GgGxT7Mop2kzqLzBbDjQozm0exd72x2BDjRxpwP7a5P3zkdVhLhwr8aNyto3dx22FGmlEJlRcNBf696ZvgmK/Q3FWRIAMpanPGYg04fK6Aq29qLklbPZJLqpbqLhdvNIiZIPHrcFCePx21XEQpNau2jUgvfHAfIMPquNd5evIgtkoOK3IlMbPHSnxK6qitRnLdIRR3YN1hjSsNVqM1xl43paWsgH1q4rr29lnsxLOr8+yhnsNftkYiBJoM1Nlm49pIDqeJo/S5ORjNugPwyo2gK7KrJSbWKiHAqL4WGQOVpaVBjvwy8HeAGY5sVx/BFce64AU/BLzc7FiWH8e8or+CqSy/lejTmSeMTdF/w8igSGehduBTA6izlqq605J1GlaLOsqAIEICJ0yXohruAhywfECVHq9XDJGWI5JJybgQpTDa4BQWa+D4vDbwCBq7pX1dqN+gYtmTYM0F7r0VeaIpZZenYhSChsLXD4bcaJZdha6x4tp7I1ZukoIcZrRTFsAVfW9kuDKuI+KzzOK/SgXC6Eg0OpU7REQXMUdWUAsmGyuODBomiT4NHHq7Vh+g1FO81/gsiHyl8YUm2p53wep12z/VPc5GevebXKgzMJiXuO7VOMBs8aaABWSUW3y0Ie2CCcUAT1WDoIU2Rd+EtocLMNai3Hxl+CK6wYuEClBU7QgSh0/YnbslSMzcMAewj9r4j2ogMqCNkJvNNGzZP3PuasQqUMCkKCFDhyMSNuGbf8hYdv/ZGcp60HZYCGuwYJfUY1pcnbQBkTfR+jFFnQjor9G6F4THZb1mNGfrO81u56Nlceo8gWyZfDc9VuwlWp81qzRzieB8UvWd2lLkYtNubgT0BIsCFL7K/Lbs9y6y7D9qywHt5zaP4mar3/dbF/D29+fW7cDihbcQlXvzq/6hdyqK7DqOVT1AbNqiIvMiKUe6KyncbuiP5ZfabWlUhdWmq/oh/Mr1VsqdWMln6K/blZykKU/ssLvUB1Z+0oeD00u93n/kYWPAwTmoepKtM4cRd6MjGxHVTau+Zad/2IAhTa2EmznPxnFeCqPOaSGgyiPENnM3hvwHvTkKEJzARdM9IqNDiqMeNFCkUEHJ1bL664ir6MB0Z6494jH1aS4tB4AnnPW7phlq93hdSbqOUGnLD9V5LYtPy1yIjbwKOOqoaTEICUyBZXuYDkOfRLywBHwK411qkNVrix0a2vIFrr3N2brqkpwG3JKdVwcb3vySIXfrrttwCI7sSiyNuuyGpgUweFLWcMJ3O/IbAPznApOnEe87FfPsQrOKxdrA7F0ox9pstvIZcvaOgpDRoGDstfZXCtr6wFRGtmA66hySNsIiajR1G2joKegtNBJzKpdFvLJPpuWEhY20OYK+t2HwcozPQg0++z6fPiIbMolvMLv0JfazFW3TonThNNv2ljqd4KL7kW7vgVqh1GvSlWFx2N+j+oJ1C7jQZjqCYaMXMhm5MpVJ6TaZtQ1IOvI3COtfpc+gAO7tC3IeDdkkILGAoGZQE+gQXU3GL7ezc46j/OTsatY3zusFfNGvGMDn98tZFU/G0bhi34ylAVPIZqyIS4VyfsXYIWtSN/BChPRrpSOI4QxBvr/KTJGZUxNfwO5DJoNXTvy+8MGTbvog8vUGZFtGN1WophjnOx3+VwUKHORXX728jmLqTqJnnYKLfypuPBT89CkxHau3C5bcNPhz+POQknHYNwDSHB2njWne0BB8hWvgmsnF5lG9ZhqKHQsnIBJO0+t3XFaQfhRSWQLa8P06bfnjdB0EiF8jgj6qqalqkKM9Dn2Q8Brr91ArbYpqv3UbYCblo9zudOn4Ty3I0kzROPw5WhGsTibs1akSYu62ulktiivKu8qN6PBOwNr9mULtB2QB/YJkJaY1mgc18gxDhJm199EbcEFtUeiyDqfqE2rYdf6AXck5HfqM+wgxM7s+kO/3F7O4fIH8S6Ddux5HrOzGZbtpFvmvyGBx1gVtgjMizJm3Zj02o2NCBnkhoqDaNsa+P7Mxa6Saa+LcSm4VRHjgg1WRrswondCNlAQKHTintjjVxfgmKqqDfJg3T4KYCU6iYWvoTw59JjdiNXA9OmaCTkB2m9CLoAuMCE3QJfZc0LAa+3CE4GFcOg3H63QC4X3Ha2wQHVTsNjs1H8OSL8bhd3jL1QLwSANoeFbqg3j0joJmq4WNNeABeHxZalaqP8SWYdFgOU1CvU/mTi3wDn0fxoUhG+EFYjAzt/jK4rEcegyazEgd6Ggr1WL6o11nLccOi1ziE7Dd8AeIRgMBALB9G4k1ufzqUWRBGb9Pr/eCBWp/8gICiYnwNMEU9JnGX1MV72E6MgiXMGLTkIZKVVLA7UtV6mlWhJ7LFaRN1uhXqNDH4YPtVh1RzQsKlFLgANkNMK4Z+RqWoCKqbiC2woa7e7gtkIQBHAankWv/Oe9946UqeroIhylTC1rcqpl3N8KOx9QAwF9DIa4Tg0EXcK2B0L6FRxV7jZQ2T03D26D/CiBYgiZyzqrgkwn/JYJHlbOVtinYZhCjCFwy9DkkknzmqQGmeZXqZ2Jq1Es0zQFJDXQ1DxKWscdsFzq9DHLZKE3pbkFohDH4dkYItYu33aMio7DXrRwxLECFx/dcRgjm3Qa8oXGEpDDW3wV+DotQxIc8Bc0JlSvWnAl7W5GKbpQHSCbe4QPDbSuTO/FvFN1kn6pjgBI8D6UAKyujZEQk7JhRBLcpp2VU+YGCd+PdQogJilQC1QvxCQXurWP0b7syBYe1rlUF7cYNzuMsM5FsbZsALggbgHw6K7C79YfRMFxTxLWmHEf7O/ZCuAObukrzLjPzi4AuAhtDzeTNhnE8GXobdyPjgETAkVEevh0jMgPoI7/Gyk8SEZu4fcweKa6pyjGtlTliJhixvSKrgFAO9egdjadwBzIR3wGEbcqBiK/jy2KfhfWeETJNjmcj3g7H6E68xCNzpxRjnhAoxSuK3xyq5xichCqtb/vzGDd8+g+4nE2KU7eo/5l6IyaWJYmVKA/DGjXZEvGOtZwPQPJZj+C33fpNIn/Q3xI4j5pg5TFG/9SEv8NmWvsZLuhUTHq5TguF9968B2Wdg7SP4PnzyWjy2MM7TwCCjnwcWzXuJm2xk1r8/bFTUsIEcE9e9NsyvskHj9M8UkUOMDHNP4xnX/MwAafwF59LPJJGgpz52NudivpQoErb4Pjoqz+J6cBk/gfvgQmKzoRPaQ/hcrujlwg/COgP81LP4P9ByBzIdrUMHuUaRfhahWodrCWdr5e7sjFiMMgKv1ZsgTgGyOfQ0W+BNXOoV2KU7+MLANXWzQKROw0czfm1GtdgJgFCWzD1ppbMqd+ugt9PBFMBtfAxzn+/Hz8XsDzNSvI7obAZ6DaNIYsO8jPQ/1pzcp0KhGtuYkoUB0wPwef3xGPu0lxi/zJEMef56I4PlcS+cTcqjt/m+nmy3BVXiNRaG44Oz7GZfXv8AtrzyoklnP3MF3idwotUjauwvoLAD4En/+y1Ef8n9HHYBt5osyXyvz3ZFPmHaxMprsRdcJGuyloYRnfpX2B27YX8UTvQZiXJ6+GXloHis2dKCx1QLkOjPnlZB2MdVAMrxO8KIzVwJAH9Jo6dKyugPZFFEjOUZBHztGpdQZH7WThLWNmtxBG96V5pTSY0doUkKOJgfvieK17GagDg9rLYVx34Eqj8QYEgyY4hGDIBJMIlpvgpxCsMMHrEaw0wfsRrDLB5xCsNsE3EKzhYGONIER3TclyARu4BMDl6GTY3hZMmWR7+z6HIHokr9GE45Cc85AfSPz3ZDOOt1PcD0G6qvdDV5EvGTzdB5AnxNcYIoSAol+M5TjGdaojqOgPWUCv068E/M7GRlVRnVdCRHIFClrQlb6SDFRQ+zIuTuQrdBh+guqEyADES1UgMngsT1qyM7TzGb6bZRzfU1AMZmNgVsAcgtxfhYK7px5q/Q856aZqRb8TwAA3Llcja67BHXW7PVhwZLPVB5Lt447w90YH4AirncfowG91edRBoMGF+/05qL8lbEpbVm1PMM9YNrIpaQPfwU44m+NxHlvw/s2MS5oUfswv6+GpLFVBsWOTLDfQtYWsXUszPFhNZ7PXIbVUz0lGmlaj4IibK0TBEeaiOwe6OK1hTScytzHmxvcdsxnGlKsotIt81Tro9TgoUeOkS5SjjhdZycczzjrQVp1hw5MnYauyZsejmKZpGdbwlhakbyDJUbSvYRyj3UiG4iass51D2tcRWB/w2xvnWTDg276B+ZtFZCtOplzg2agrWjDVDgIIEmdpp90CSdt3qNit3UobFjqs9RVHvmmoYAuwR/uW8IPabbR1aVyqltAGNdMvzKG+CKvdnmOc7jB8zN7soafq8ja6oTFuapq/CzuaEr6jUVUVfJgqThBLI9/Gw+ALUUvFmL7GqOqzjAlRvjNyJ/aySfUcdXSv6tW7phqhXRVA60yoCCDznqXJpnoKYACi6/IjdaqP0+VX/UCXn9MFbLkLN2OH34XNWJGv+N0A7CUrc2muRi/G800Jef9CDIUo9u5zad+hOAc3EbxAu5sQp041/Q9uH/XkVHQspdo95jVaTh3Y/AX0capTZqkj71+UHctJYznFWIuMsZzWfmjDyMcKWPrJqRNUg8ZYQUsd/XNTxfkLN2Sw4+GG7M6pht0q0H8Fef33WQQZssZF+ku5bXEjnde2kLddMs1EGHuhIn0DINWiSfdCf+OWZr3YD30s70xnFvzCNp99meXGJI/A74nwWyZl97uIXwYwbOLZrXl40CjWALjH+d7K/BeEwjqMceTccRcL/PY8/HkCf30e/kaB/4k88Uyq08Z/s3s87hOAPrXUm76Fbg/lAyhcLtsBEgi8AW8q0A9OE1w/st3l4qIyCw8mF5l3Zdb4Uz4yjyBnc6HrXeVW447X69TuJSEIefTnoENlsnXgtjDAto6wkLEP/ZoNMUzl1DgOXwGw3FQk54Zo5yGWG0cyhV7nJKZws9UUrgoUNM62IFxZQ1joFmbQ6XRnrSCerLgmmMD7uORzE1i24EfAeV8ZN4Hoo7Mm0FHqV/C43cGNUqBxC+jO8RjCapUbAqqJxowrrqK6/AoYyAA3RNeBgQxwQwSaCIYoyI2NqghrU45nhUq2J3NMtHzU5aJ/0KkhpzfUeJYastCLJxUKt6IjoLFHIx1V1GpFC3OsaKHFilZCL9lpFalFfFp2tQCYFuJHWWe9R0dZIT6vcrUc5lUu5iWsqBEYl4kzl7y5FcuTBNFeORs74+Ean/1b6EJKdHm6cSa16I8YSvEQr0KtCKgl16kVQb1kOtq4ipBaDGm5AVaoXkgj36WDWVU9WINqI85K8MWSqo4jCljdgqesPtXHRz0XrzZKp+fYOfAk3M59brph1vy0NQBvKCC8o1WLDQiFBTySgL4DrYLZlyxY7sKDo0m2hX5uaQtAhMldtf6H3FWZ1V2BLS3VD0Gf4Gcms6Wf5/YG47SZePyTZ0vnwS+IEbsyz5bi0zCQLLpDs9rMcYA/jeccci7+Bnz6BZn9tlxbiv8+Y+O/hq2zvJdZjOvQasbFdvY/aH/RBhakv4mvItzyAazjpppNfv5pNTbykTMtSO17PIjepnA9sTe2QExl6onXqQMFKVdzoftd5Vu4ot/nl5/3ZYMrrrAPg2DbuWA7cnbl4jEMv4fcympGjRh5NVt8nsGSYvaZKzn+GeOi9piHq1mDLdOVRwPDu158TxNCW4vPI474PboPaFeydyB0HyoeFjqdzI/j4Z1cTPCdewOpIb0FHy4ohn/gz6TSP8CbmCJEFtH9kPZDPMgjxBTjTdA6g0XjUwy8dr9RTXuAKOX7mY/DZ7m5nwnPMPczzfbSwiO7Fb0fUYf4ZhxR24yduP6NGQYnmkKuGh60/wivHGbVbtd+jA7gSCO/agi1FruC2oNYtqjd7io84oeOirMboukAMje968K9zEA6u5c5cIA5+J5RJrmuwP1DbQsdHAdmycEG2cciDyENPYr2vzhW+3JF+wl/7nVJracdqkAmjM8S2kucwUtqS9rc+FE7W5TgI4b2AkCFb8IcYAPiXd/bePGD46UfJpZoP0VJXUB946Mlpdlma3SEt0GdAnzLA1IPIT/tQptdLn/h4XvxblDRHjG3ydhWHJKDaQ7UzroKIqlHSeDTj4m9g1v7GWqJXykjN/dzXJfv4yI8jj08wfcIGOSCoSIF2Skcn/YLrIoGTful8HB5KO1XBhGNDm7I0Sc+hJ3/WnjBQFuh6lY95fx8HcsFvWDQid4STq9bXDwtvIyOPVQ3d0ZlmKWrKD7h3+BYUhCdYXOz6q6dJRauzmm0KHXqP5uBp+u8wZPZBk2LxRiqs3U2eOtfIJ1PiWi3qUgt0J42rgCM6SiiBXCumPu6J98lX1c8ySZHVfgq+emWmNgyze9b+DaeCPsPLkFdGqlJP4No/f9m4EOiZymvRMARiPwUyIdEvgny5SI/D/IVIn8C5CtFfiXkq0R+HeSrKf+ufxyHE6OqPp8/8hyu4Jmqv9slDLWXnk8wugCdLoLpBbStZ6xxdXg5uDh/4ZETSRoh00Ev2yCzIKzOoMyscDHPTA/fM4Uy1UblUiPjBX4cUabbIGVqIZ3jzOHDXwq/eEV0yOJXjH+vyfxXsdx74PuCKrSB9Aj2MIrhyREhFR5+9rEjYl4CKDIdelRMONzPecMos2msZG7WNnR0ZN8wzuSsUentBd1heWSFgIiCb1X4a0bdOVMESg30/lgm9tUgnRK9VrQcuzcr/NydgLASWYiBc0iJLMV7u+aZxqNGRRnHK/2G73KrrVpu/I/w67ms8eaPCJag27yUv81t98q1b9kibiSxAbLFUuS32NRDCLLRMt0H1qIdAlNXTJOJ/M7gKjdHxmmIF2LorG+pqso9Czlk45cI0218MjU2y2QoqCqQ9wPGbtOeR0Nl8GgWf1+upm8jHqV/D4UHsJ7yrnI7epqN+LCDplxE5FEnDfS+G7QT91IqP9PDt8mLZ1oP/JBqvQ9Rf8BDPXdQv/mY5R7Fbw/4HY0hMDSOK8EO05mf3VlwpER1BLehAVXtF8fbfldKx2NEwzXwOYXu/y2uvDzHlXv1B2GM9AuQPyuyjKYJuMNZ3AnoimEDZQ+OlxoLPE4XNXjpMx4y3kgU+GRx7z1nOd1pjweRUTosS0rWp0FKl8/pF8UDZzyidPIjyga/OCOrR3kk8WgB8XgNVUjZ1ViCWR8+QPFJkT+SQwq/997s93b1eYQsYQ0l/Sdch1IhUK8pcXxUY8iSk10AejoV/X1ZjpjyZ39I6sGXEPcycnU1f5mD2Mj/IWI+FdKMct5fmKen4nh4ZkPuewxLx69wnSB+aq+Sy2us9jkif0Z+HEQGO7W/kAN1Ensb3VD4V0Q8AxG0492Ax4yg86aAmoaYWjd/Psq1t8MQzXFvzmLxUjs68aXZxQzQ4h7zfuzMhpz7sYaD+Na1aW6e2jdP5bpuJ6PB8w4crIDnUQ+byy0XewXWl68NB4lYj2l+6vlcTfNBufwZUWkXhiE+m3npZxOXflKDzwYAXdTZ6KKOXvtuM6qKioQ8JfIazgNfEGUpxH14M6eyhlOp2psK3QdJ8l9HIudkFyR3JDGGGKJ2TkTF5m6i2ji7ldlnWMNdfAvy38TQG4wYukjE0McIl+uNcHm9GS7XG/j8cNmwofj9gsv5nZsaxi81cV9jUwjI8TVXNxhmdZcwvP02cXM7PXtVi/e3p+wSd7biIveUXacWuOT9oCP21hbZdQAz8vve9R5Yhuapgb/Fu5mHCWr6DuPF4y7qRuUSQ3Vl1f6u8u1cA+7kK0tjB3a1uiCLVSnMJsprd3hlyzu42n3OUxPZx6XxgppcuNDHiGz3Nsgg4S7MIOnuUyAzgzJEvrGem5n7dMOvO9lMiWIKld+NK5EVpHPGI9rj171qy/38hDfqDUH+VD1PC4sji3N1z9S4ya7ZQeNY7tW40DhRVVScoHEmXc0Byiv8FZ9ivMxryL4ZULjieS31UJ+84PPSOXogJPkN7IgYOSf/kUF91iA2BbkdLaFiXidAFpUinNIst3juTWMPHoj8zbKOjMXjxn2Tnfa2EXH+6KGvv8ja3zF+obulgPcgxLn2aQWgH//ACvjdI+XieOSfyKkK7S0TFwBsFtTeNuJFV+Rfk8SLIbZ0SzZejEYNehzsQX6uoupPNohwQ3+9QUQZ4Ma8jSLvdab/zY8a3kE2zXZp/6H3YszFdrVOcdIXvcDe6tOwwbvYzbJGEeZG3kPfXsXP8VEDqbLf4XNka1+n2oN6uhHPuuwhHitDzOoRL8Xs5foYL6uQIanUz+YQf0AmSYLv2fsvxh54IMtzfK3VgHGPJkPVUWCY7FGaXAq9u21yHMav8ymaTSIAH2DSs8nAbK/Q39eWNZYQKvuO/DSvPeE8lT8hL7A1uxWXZof2jf22YDsCDgS22ELtUxVX7T6SakVTJNzg+uwRJ2TSLkg0N9ZrtpW3z1REObAl4oGMq3aDaDYM1G3LVlc0L6b0wLQpyD+DWoGJ0woNfhwJFeqfaMR3XJO8Q6d76UdZ3Z+N744x9sYb/JzcsPHGpxc2PMY1trx/OY5RBGOIrCn2DQbvQyGD9zJrFf5L3r8i226F2S7k0a9qPMrxPbP0Z57fL8GviuH5WmH6TrLo+n2N4nTTFtgkN9tKGxW+zh7VrtBaH1hO9p6obVqj1zeJ+gJFO5KJSi5K3c1F6B3uMi4eCt38S2WHv4Nygk+K08UwWKQE105pjJd609+huw/VfqADzbxPiahQdgDn7KKZN3XxT/7sez4HaOnk9pn6+QZ5HM/vPe623Hvw77Qtgn590G/zxRAOKu8GvGY4GJlqvNh/rGnSF/sNxl4W/fce+C2QJp551kn81zjztMFaPivK0n4YeBy/5FnGv8SZLkUEfsM0jQIzjjYsXYY4t7lHMH0TuQz+1agAfb8qQF8VC9A3k2oH6esYQfo2WPaBYCBvs0FbL9qGZCPxbASYDuDQuDb8XT6vU0n9VImbKI/+Z+AOWd3xaqqJ5+d4pBsxj3RP1SubYTFC9F2lWZjdiug2mU68OYB82WrqBt2ph2D0ivbV+nyjMX3dSsZNhCK6bzOz1nf8ZXLeyxv8mqfSsMKmlUOXtfvbHfQFL9ofgWlgTagHHryvLy2UIxWoWoFIJf+o4h/V+JG+FO/X6HSWBqjUakgNI2Q5ajEfCZsYrc7MKs2F8rvKqSh8UyQ6+as3y5xUdhqWTZVIMKeZZS4q2245n55ulrmp7HQsmyGRPkXMsoMzjUj0DCyfics408BrDQA24G4c97Ijk7x/t4m9Fz1kPdoTpxJ5sudNCr/EONrLJsXy9sVBetGMPhPLPfzAQZ78GRe+3dFPakZv5aCnXAWuJqeLxvUcpQm+Atb3UhOFmhS6m5xuasJDzbwnO1c3Z5/sYF4xAPwa50FULcszP7v+LZRKy/ehDfwk31wG7L1Qm746nm6Usi/B8LuF5BBzengQ6jrz3wpxG17AdmayZ1Rn4Hs88gnEgCYSLX4/16PQ2QSdlzYXKnQ0QUDTLBDVZvSbtWQG+dwfMebupEXnU+ePERsWce8l2w40mN/Nkdk6fmSo4lfJlaaZ9GH9ElUwi+F3s7NQuI9Uoaf6bfNknqq0wdmQ9VVtbdxX5frMhqzva3g/n2knmzyb7tH195qFN+ANm1aJDsh1LBLA5A6MF3I17Z/gP2A6Wssx781ldtrpfC7Gd6Nb6c3SbFquaVqrRPGfne3Q2jD4QL20sZXi7xjItki7ZHwVH/9ywWUt/C8XRDDOuvBM+kMFIf0xwpbLkTmI7SWs5c8WYAwv0RtjoijiJRZSlDNXMr/azelVWFEp52ENr9jAv10lG1/P4g3FbR2e5+Hfb2gjOWw8qq3I/VKVIaaliv5si3Hy6ZQVbZ5Ee2KZ1tzS5+ctjcx6aEO+Y/CJ1yOfsfx6EpbGrIdozF4WknROt6AsNgP5+yZxkgyG8QwHq5Ka8q8pTpgmOpzGiQ7HymYeWMp5gaX5/boqtnirET9ewcrv4PkJDkvcse2BWu0Wn1Xqt5f6HcJz6Y+3gi7Ps7itIHdiFdylBbX5WV/WaC6n4csas76Mh1LpPvqakMW5NZrOLbIwi6BshK4UBWZKloXcAe40HBms5CKszpUqbqC9zshis0Pu+3YZPhN8X71Zxn3fbsNngu+bZpap9uYiKEwYndI3RKZnix1UPGL4TfqybsQsPthkeM6k6TmbDDz3nIZeX8LKvmaskyGYNi6YngBazRUSWc02tJqLbHZShVCkHheyxWYvcpTz/Dx5P1ax4yZIaUB7S3DAFunh5pfAYC4YygXLBQga28lpRBuNZ79zyNZYRD/CIfp2a1OlBRgt4Ps5J8T9n6LvPHj137eiKzrWnmLBAm7bFoGh6iIRuIwkFcfH7yvPPY7xS/n4JDmRbivPaTzi+ddsj3vQkq3ETcMq3Bg040XDtP0t+BVGthzM6QHMBjDSwf8CE/4LNsyzkZ0/B5pKANlzoNwyx9Fr0nepOvkbCpgr/2pxU6X4Am9BG36BF6gvhXltpqemVcjaqW2TsZZuGYy5zphh7Ndc9MZtPvW/Grkspy9A/Z2HGsqHlPcj8LjbYEq6B5kyF/80DPiodW2T+Sje0utsmunkxG4nYsEblTqDxh9/4W9UrnPzrxPjN2HG2yb/Jgy3ZQqbNZfTzdhaNvdcw4/LdM3I/TiS1eTjn9qJOKFSTipf85Ny17yqSuhZ74mgU/zpHH7XYM+cltkt7bPbWxcy+osj+Bbw82B16g/yS49rYAdX35vR48lhOr66BuKZm0Bd6rf0stVn8b/FVL9qS08Xni0C7IJO61ck8OWF8Z5F2rrsulo3nvj8a1o7PnjD0S/mb1NIvu/Gv10lrlRPEt+NWCD+JtR88ekQv8WWq9eA+GtSsLHG7+CJWXnEp8J+y56C9I+UvgaphwUlWSpii6UqycM2Q15h90m3A+ZV+WlZYTU2m83DumyIT9mGbD72fdtXAPMeYbbbbTaFJe1PwbiX28+3K6zfiT1rkBaxZ50POqF/F9ac68KxVnlk6TS2Dm8N2Y8LqgBfUIRpiNJGSu8s/nyxwn5F6RvFiPlUCfZ5MaU3lWDPj5Z8r6SI/R1ShS1QsWaviqVjlP5QxTpvq0h/nQ/HXe+TYXan+ZCSa3xY55eU/oHSlym1+zEN+rHPekg9bLEfW33cj60eodLHKX3RfztgCktx1m+V4qz9ZYifUYZj9ZRhq0QZtrqc8HeVfbVMYYcg9bB3ypDbawJYcziAdb4duCYANFMqBV+FdEoQW82k/DzKr6T0DEr3UHoppb8IHgoq7FlKWehQMMBODp1vD7DTKT1I6XmQetgNIRzrntCQLcCeCz0YUtjfQ9hDYzmm68qHbEXs1PKn5Qr2m/J7yyvYC5B62LIKnMsWSBezUfzjTmycMDdXYG+llcjnOyu/XlnEnqj8QWUNa6mqr6phyyg9g9IhSg9Sej2kQHk1jrWs5kGnwrbVILf1miGQov2Qetj9NdjzV2tRru6pxdX/WS1K5tO1OK49jOliSkcovZTSX1P6NqWeOkyXUzoIaSO7FP+ME7udMM9TGpmCo4xNwVGunYKj/G89ps9Q+hKl71FaMhXTaZTOpXQtpTumIt8+Dnnz77cxtCHngHHhf6cIIS9AEfo7B1PBa9r4vhT0MoIQ2Il59O2SCNtC74lWULsG1kfQZiprZAPsWjAoZ4hvb2oE6QI6k7lhhE/RCM1sjMou5/scAd0koE8BNSXs2/QCuI1dQNCP6U1VO7sUKCthvX4cfT60QOjlMoQWsG8QVFmB0EJ2C0G/JWgx+yb1/ZcqhJaw26hsqBqhpQJy1iB0AruDoFm1CC1ndxJ0OkEdEGlvHO+DNVHZP+QvQfqO/BWct+1qSNfYboN0o+1OSPfa7oMdzkHbA5B/wvYYpL+xPQHpc5S+bPsVpH+3PQmpw/4MpF475qsojVA6x451VthxrHWU32rHtgP2I9i//UVIr7G/AekL9hmSyl6xz4L0LcLLjidh9BsdKwHzbwf2oKr/J6vsS+o/Ib3U/wmbylZWvuFU2W+r3wDJXuZ8EuSji9LVlK6j9DLnD6CHW8O/dEswr2ckA9NT/0u3wt50zQeb9S9KZTemJe4noFUlpBJze34gbRz3eubLG8fbIZXYoOeLkO72fBlq1hYeAGl+qmAW9Jks9ECrvZQuLPyB08/aq/tcCjur+gj2VvMVSKfWvAFpZy3WP7P2YzD6uZDnfwPxkvCIFBJSjdA54IKz0GelqeSPOHQ1QHYTugkghwk9Is0Uf+wQoaekVvx7KQJ6WVoovtmH0DvSUgtULHeRV+NQrXwSfpdJQLPkDfjtHAF1yqeI/SdCW+UYvpIR0ICc4H9ekaCPyWl8XSGg8+UxNtWEPi9/HE+tBXSj/GnSUw7dLS+llyUcOgSUtZnQY/LnIBLdEOZxe6vtRtCRbwtoHkCL2E8Iupwts90CGvNzgi5znWy7B6DSOl52qx3Lrp/C291u/wdArwrou1B2AvtVPYd+ZH8PoHcE9KDdIy1nVVM59L/2gNTJFszk0M+gXRcbbKDx2FP2sNTFqpo4VORol1ay8RYOVThuYSeyrwuoxbFUOpHd1sJ7WeToAOhOAZ3kCEgnsY+18ponO25ka9jsdl4WB2gtK53LobOgz3XMtYBDFxK0ehGHriSIvtQM0J2OhQD9REC/cZworWNLlnDoDwCtZ6UdHHrNsV7awO4RUJGyRdrEQis5NA2gXvaqgOYqN4L13L6KQycot4B9fVxAPcpp0hb2sdUcOkXpA+hVAQ0rg9LJLLKGQ6PKLmkb+5KAzlWmslPY4wL6DPR5Kqtey6EvELRGQNcomnQqywjoZmVU2s7+JqA7lbOk09nsdRy6H2g5nd0poIeB6tPZjvUc+oVyrnQGu19Ah2GEPnbNJg79kaCbejn0hnK+1MdSmzkkOW9hO9hNWzikELTgZA55nQFpB/vJyXz9/M4bWZTdspVDQedFUj/bdwqH6p1fkGLsBSHJL5b8Xh5m/xaQpv5VjrMXhXyO+m9hu9lUwd05la84d7Odgs5Hq19xjrC/nUpQ6PbaW8B78b9h+snQFud1kgE9JJ3mvEk604QOOL8ppU3oAuc90l42vh1hbHdI2sc+djpCP3Zd7nwIoHGCzmG3OX8K0DsEfZLdDTXH2JI+Xlbk+DlAz57GoX/Wftu9n70koLrw99wH2HsCagkfcp7NCrZzaEf4R+5zmLadz+gT4Ufc57Gv9Rm0HJE+we7hEJNcL0ifZNt3cMjrOgTQ1B28lx9NQei1HZzqqa6XAApFCWLLXH8GaM5Adn7ns58M8l5Wu34K0NMccvW63pQ+xRJR3udfphxyfopdI6B/A/RpdpOAXPXfdl/IfiygsvrvuS9moX4OTak/5PwcWy6gWfU/cl/KwgN8fkvqH3F/Xli3hxxnuph8uQkdcLnkK8UO5iHHuS6/fLUJXeSqlK81oWtcYfk6E/qma4Z8vQl9H6AbTOhhgL5mQk8BdKMJveRqkm8yR5/mXiTfakJz3Svk202ow90j32FCq91vSneb0PocaJt7k5yFhgG6x4T2A3SvCV3i3ip/14T+x32GfJ8Jfdsdk+83oR+7E/IhE/qFOy3/2ISOuMfkB03oFaj5E3N+77jPkX/Knhs01v18+RH2CkF/lJC7j7J/CQg58TOmxDiE3P0lKxUQcv7XLCAg5PVv2DQBIa+fZHMEhLx+inUKCHn9NNsUy0rdM2w7h1jKg9CjMS6fZ3uulp9hzwnoc1D2LFsyhNDz0rWeFfKzbEhAP/Qskp9jcQE97+mRf8cSAvqX503pRaYJyO9FSBdQi3eT/CIbFdB6gP7I9gloFKA/sf0Cusq7VX6JHRTQ971nyK+wcwT0B29M/gv7rICUgoT8GrtKQNML0vIb7GYBdRWMyW+yewU0ADX/wX4yxHXskwUvSG+xyDCf7ZUFhwB6VUA3EPT4lCzP3mJPcYgN+RG6v9Fa9hMOsZLAXvtb7JYl2bJ/sTs5xFoqEKJjebPMxSH2ZsUh57/YPWuzZe+w+znEzq6+CaB3NmXL3mX2Xl42s+YmgH63LVvGpNc4xFbWIvRSTlnkFF72SSrDfcz9BTLsQQ4V8PxkqcyeKED7/CvCPEWYZwhz2FLnt4T5wzEwEnuR8C8T/i9468zeLMCdwdtHKZULsRTrKKLOM1THGBcpdxZmR/Ra8sWF2E8Z3mqzIPVTjn8xiFUV4onJm3l0Hi1/7BnJEIkjpp5G4VS9bEmnFWKdGVSnkWhrJUx7Xt7G5poYCaJ4xC+h/HLKr6I6LxJP1hG+11L/RRrrNMr3U7qT0iS13Wv2aaS8/nhhluefoLx1peqp7cWFuWtn5C8l/OWFxhxxv4L11xVm+cMxq6j0r/Sa8o2S/PyUAOZnBvLzX6LRr7asplXSDtMqfI14/iWq8y1Kv0Ppd6ntA4XH6v9oeSttP6IeeD8PHldvH2SU/yVqf018e5Zm9IfCLP5Vwr9J+PdIhh1FtjBKhQ1KFxahCi+n9MSiLGaZE9MuSrcR5oy8VjbYd0phO4sVSWEHyxThiB8rwhHPKcIRP4FP89hlhL/WUnojld5FpT8uQnoeodLHKX3Kkv6e6r9K9f9BGKkYMf9LM3q1UAaMkzClxVgaLEZdri9G/GzCLKbSVYCxsXWEOZnq9FNeo/Ss4qyOLCzKzeMckc4Y0cnneGKRpSaly5yMeMWIV4x4hem51PNni4/Fmf+/8eRo8jaZBhXCjriINbEHGPqFhyl9AtKb5OchnSG/TJjXIf2p1MHOKLlDLmB7Su6D9OySB2VJ+kLJo5D/SsmTslvCmnWUqtLD6jtUKttmSk+qL0DbV1SMzV9XXbYOSfIVQur3+W1jrMEXsvVIC31TbBsl3TfdVi7hPmGjdKGv2RaVvuGbY2slTFT6vm+RLS4941sqjUmv+zpspURbKdGzkfIbWYF/re0Cqn8JpBttl0gN/kr5EglHv4Jo2yjdat9mO4Wt86dsbmo1Jt3r77DdLh32f9p2r/QX/yWQ/tP/RVuUSaVX2a7l9LADzluhfqD0Lhi3tvRh25lSY+lvbJI0p/R5G870T5CuoPw6qCNJfaVvQqtdpYekuKSVPsHiUPOvtlaWKX1IamXnUnoBpVdCupFdDzVb2S2U3k7pA5Q+BelC6VXo82FJKlPsD0ueskL7E1Jt2SHpaampTLVXsbayavtGtqjsIQkpqbc/L20rewHajpUtsr8M4y6H9JOAOVMKlJ5od7Mvl623vy49XLbFvlD6Tdk7chWbHXhTqmKLAk/KY6wj4AI6NwTOtqvynNJP2M8BLn0W+t8W+CKMNRC4yl4uI0/q2MHAVwF/UeAQjHtpoA9GnKv8VKqTHwk8aJ8pPx14QVpIHF7IXgw8Ysf0CXurXBh80r5Qbiw9TOn/2cegzuuQ9gbfhTRQandI0kCwwIFz8TlmyiNBnNf5wU7HQpLJqdSnJN0QPBnq3BxEbt8W3OFoEvh7ggnIo1RgXndMJZqn0hzPlP8UvNoBsWDwekh9oZsd57DK0BtsI6sL4So0h3DV5lO6InQ/lK4NPQgp4s8h/AUw9585HpYGQr8C/Ajh91D6jO8w4C8P/cHxdflbodcdt8tIz73yS6G3HJfIr4XeBUxbmVN5QP5PqEBpZQXld9leBpnB1akpX6DgjJYpD8vzy0+UnpB7y/ukp2XUu6fl3eWVcgfI8KBypnx2OdJ/YTnS/8Xyc6G3w/5PKfdK15R/UXlefqv8KsCwitshr1ZcpcwhnswhDrwsnVjxQ+V1WNMHId1V8XPlbfnskl9DHuXkbRn5M4c9EnhOWcKeDvxVeVm6vOJvituGq6na7q440S5JP664y6ba5pT+W1FtKyBdwnB1VNujENOqtl9UOJyq7eGyBcpGdprzNCeu4IjzZclT+bCz3IYyo9rqKn/ujBNVcZasnCHH2f7K/wCG7APMyO5S5Y9Xngjr+MVKt0uSrq4sdtXZGkurIf1t5XRIX690KipxRpWlKqBH9lShDFRWFThabdhzq21R1U8hPbFqjqvDplctcvXQLDpsX6jqcG203V61CvDfr+KSs86F0tUL6UNVvYD/edU2SH8HpV0kb13AvfsgRa3vkFZV3wVWaAXochwsxptSh7S1+quuNcThNTSvqO2L1fWgWXzttjgdzrh0dfUdchwwP3eNsRurX2RjbE7p05C/rRrTFZBfQ5zfTJxfw35Y/aS8mXj7tPST6pdc50D9v7jiZB/iNtT9h+Weml1SlK2rme4+07ajptF9O8hAm/sUNlSzANJEzSHpTFtPzXL3mA0pOcf26ZqHpDFbX+kdMmrZifYn5C/UrAf6r6t5E+Tt65DfyO6uOdVdxx6v6XNvZL+rmQF29WVI69jrNYcdV8go/1eQ/NcxVhtzXyFzfSmuRdtbXVsJ9SOQr2NXQVoF3Bh3V9G8ttO8ttOMOohLBZxXlFZRegXQeYu7lf1f+Cn3A7Z3w0eAEvIprKLuBci31FUCJZvqXgHaknVvQM29dTji9XVvu9+2DQTec0t2lLFW9os6h8ct8tKUAk8rK57yH6cqMBum+D0P27hVH5pS4UFKZkOd86fcZbuCXT4FRoGalfLr8l1TXoDR8ezmWvabKW9C+vspyA08v6kjfd/IHq1Au3Fm/U8hPau+Um5lF9VfjVTVI+V31P/HuZF9H9KZdpJMO67FQki/4+khzEY7ytgpkH7BO5Pm2ypS3IW30u77dUmfeof3TPuFU7/nbaUd6r3okb33ssumYk3cpRZB3FHI3OxRdpHsZo+zS+UWVs9+621hjewl749Y2r3NY5NecV8I6Zvu+zz1kH8I0jfdr3kGCDMAmA7veZQ/D/K7vV+VvJ6vQIpt/yDtZodlm4xpPaWdlA5Qeh6lX6X0R5T+gdKwbQDS522Yl+yY1lHaQWmUYxyYnkPpDjem45ReQ+n9lP6O0uVeqkPpOKXXUHo/pcsLMGWFNC6lyyndQek4pddQej+vU2TzvO1ZDqns3QGp1zsOaan3GkirvfdDOt37O0hneVmxzbPAu0z6prwRfrdKt8mnwO8v5D7bPtu9tl/YDtv+bptpH7B/w/59e7ljr+NOh0/pUUaUi5SvK15nvzPtfNL5T2epq8mVdF3mutJ1tesbrrtc33U95PqV6x+uYnfQXefudq9xJ9yXues8Sz3rPGd4Yp6kJ+3Z67nBe6v3kPeXXoz+HLjPhZiviO5b2p1Xwc79FedvIA26/gnpoOsdSG8ruF4GF8Awyj+Z2gxAK5kNg3TI7AbmxYhP+hukLdIbkM6W/gFpm/QWpHOkf0E6T3oH0gXSu5AugvC0iC2hFwMnSHZIl0sKpCskF6RdkgfSlVIBpKulIslR0lryHXmlLWA/yRFz3K38URl2fcv1vOszbibZ2IiERw0Odg59Otln6dPNrqZPL7sJPu1SIXuE4GL2FH2q7GX69LOSEvwsY1PoM8hqZYjZpXI2C+bbJVWyThnfWVSzrTKW17IB+qxjH6PPenY+fU5jS6n9DLaePmeKfhtFv83sMahnH8//f0JVWv//XHT3+/Pc/2cX4WRpIu6pCfV+zD5py8e9zM63T8R9vXxif/VV/KRcxrMRWmGFJENmxXSPLOPtJfPhDgJ+y+A3AL9B+O1j1/NrvCVrtcHRROwE1tO9PhVLxvTVWjrTMphI5CDYpu7Ozaw7OTqyQdcG2Po9MT0RHVup6SNsg5YaTfUO6PFUZoUeHxyOcQyVQRfrE7FObWQkmhzcHNWHYxnEdW2N9a/Qtb3pmN69J5bMpNtY1/rO1et7N2/p6Vm3cj3r6dIGcNgtPauhYSKms57O0XRGGwE8dpDT2IJgI+kBTU/E+1nvWDoTG2Hr+3fFBjLs5GhiNLZ5LBVja0cTmfhANJ3piiViw9FMTNRs2RpPDkIfLUh3mhH1omTTaDITH4m19CQzMV1L9cb0PfGBWJr1ZoC2qD4IM1wb1dM7owkxWnZ2bHUskYrpJ8f0dFxLslWxDHQcG9a10eQgHxBxPLcJm/akOXByPB3vT8RMGDI9A1oyPmAQtRn/d2v8HdKK0XhiEMaCnjoT0XR6XXQkRkvVuRMKxLxYbyyDSxdLp7s29HTsjeoxRPHSNVpyeENGnzcnF9Xehn12peJAtEEG8iAZy0C9Tk3bHY917zNxqyw4HN4Y2Zzh5p16LDooqOgZZL07tb2iX3PcDZqlQZauVXl0Qf3ezFgixkmmLGChcWYt9B0dNpe1Kx4dTgI6PoALpqX2RjMDO9lAQhvYzfo1LbM2bdTs1BIJWAJYp3TLKpR7YHZXnBBRfWxHGxuJ6rvTDJZ6NyXrkwMgTtF4knVqyYyuJVh6LDnAhlByQM77sMgQAzFEz3pcslh0hKUzg9pohsHvGqTEkMFYf0v3vkwsidKStmK5frWA7MWjifhZUaSKnRjdE+UFBh6G2pWGEm0v0M+iqVQiHhtcT8DeaDJjSBXwYf3QUBqUcTMIts4ylA6M6jroU/fIaIL3f5amjWyI6QOANPo6FVBsgFZ5UwyMQDqG/8+1JIhWDLsbhMmAPYlRhq2JpzM7WqFCzBCFLlA4HJLKe2NRfWDnFlCuhLlaenQvSDRDXYgmh4HUBKoqVCbtAE2EoujgylEwT5hZo2kp1st6GDcTrAOoHCMaMTG4n0J7lGZgzAahc7JOBtCRMXInAYlsfXJdzBDJ9UlcQQ50JrQ00tXJWUQjoEJRxwZXTZ1AZUsOCv4YKCJtg4VXndFUZlSPwQLGYMF3ajQ9MJWpaAaFlqHx7Yrt2axpCWBcKpqKd6OYpcbAFmwANd+r6YNro0mQdb0rno4CBYMrxjZoifjAGKjfgD6WylAr1hWzAlrHaEYbigMDkbWbYilNz8QGN+xdHU3vZJ07YwO7O5B2RBujsNUwB7SIvaP9I3EwuOuie+JkO7uTaZgCGUtOyiCu+YZoZieDpdmdBtOgR8E0MBw0K1jAqSzQk+7cqWsgE6v0aD+XVeIVz0JVyqwfYmg4uG0DJ2NI1Er4RJjYRRk0iqmVOlZEwelFpeR0cmEnMwUmK5khmaLyjaPxDC1a954MUA7MFwsPw5t5Qwisir0mNgRKBEK4KT68M8NWaBlwUqxlIKOBy0ru0XaDCe9Au7AplgbPwyjfGU0k+qOgICtiw/GkqNadHBS5rf1kP7h1zOwEG9EBVmgP5xZfGfEB8yNtMy3YSEpLwsQQmQABAwuVIB/ZoQ+n2eQdAju4m2c4P8FX1glWKhPbEAU2pomaHES2z/VJmBjYHVynjsFBkGxRnZZ0dYy4kgNsHI3pY+A6M6PQz77YADM1ro2ZPKdOUaRZLuvNCsR3E8IFMIGt8UEQPxMUw5qjtLOB/l6keHDvykQUpjC4t0sbhaE6QXN2s9TATgw8OmEeIruulzhHMrMP3EtyFHmGJT3JIY3KtoABig/G4GNLahDYBJnuJJJPC4E8WZ+EteIECN6DxCZJSvOwnJ8rQO1gSTaD9qRBT2IdA7CUMT2KckUrhmt3UmyMVA2dNBgGEV8BhD5ET0YT2fZb9ASoSgLQYIKjIk4B7mQDrP5sCLZyTceqvu51HSvWdPetXL9pbW9fx5bN6zvXr92wpntzd169zau713azjn0UJQKTktyHbtDA0nHbJ/wFgxXczVU7O2pHJhMd2EkRxFAUg6quWB5iQijYYuX+xNL8tZq8BqzQxAKxhhMLzFWdWJS3zhMrTLbyk9WaTBYm1suRjonFk8rLpBzMlaBJq1hkatJyU8qOQQfK3cTiCZKIJgMlAyJzJAv8WUqYoF4UGi4UvYb8WGvtZDpbDwYtA1a/fxR4lu6HQG0fS4GaswSLD+5je9goUJFEhwDLGGVDpPbohPU9sUFG5isVH2QDI4MsOgSEsX1sjA3sY+BIR9LDbC9Ls/7RIRBj2AiwEbabDcaG2N5+MBAQPaSIjAGytWw3BhF7RDyQ4n4+lcAYMQOWPclG08gxICRluNadqDZDhkOAuI1BAMQGmcYZMxIDew2kGRV07kZi4KbS4K6A1hgbYqMsNTwaH+wcGVwFWwugBnJgv/Rh/gkpbReSkOnpoo8YWF4tBcTtifYkMQUegsPKslHsaDrSWdSW5Aj38bSR4t6FZS01+nFzv8G4FRbGtz+d0UEShFoaIFheoCaFVADr0ebzBUkNAkezEOl5inQiJsQllbujFN4+hZvDIa6QbMhUopQ+IPQltaVHUDe0qbdH9JVIrYU1TiFNhjYM7oW+ssKfygOAOtpEDO41xRx9xZZNa6BUfFpkO5UDWAyuCCGSUZyZICxOLiV334luPQ4tzI0nR5AObIolovsoZ1ko0ZDHkvH+eCKeGcuWdiUSPSMYPWRRKJbtbbTpz98Tbs3FbEXxjENER5VXTai8Krcy6nV3IppKxwbXQsgZT4PUJUEkQS/6enB/PmxkwOLjXo42tOhGQMVpXwW6k4Z1Yb2bO/j2MUu1sRMmNDbjue59AzEybtkoZQlw5IT+vr7ZLK2B7kxa0ViWzt6pS05Y2NfXCRYnNtiR1JJjI9poei0ponFo0MaMRaGdImAGrXqyk/o6FiWtR6v1ochoZ2ZjzurJIcPdZ6I6N7XrQNLENpzCYb6rMTAUfGJd2qlh0puKwp4y1QfxP8TzA+YIm7VMNJGzsBbzPMkMebAKUcfkJdHBwb68pcEOu7QRtKAUVnJKBQbrT+wKRQlkkU8DbTvA7bhgybSW4PsE8+RmNJMaxagdCqJ8BLGR5GRwjvE8l9n0CrDC/PzGOlfDsuGelC05YaCvD61EIjpGBzLzYdnFZhXXfk4uOJfxReXR/wdc+Xk58+hJ0jTGQPhWxHF3AztP9GObNT532A5qpCE4wy2bVy7AVRe61oWGlh8eMPNMbLMmSjfrY1CVjs8wD/E/7PhBEnqSsTNHo2hYEOo28pu1NdremA5TiUKfSS5ta2LJYfQFEF2xU2O6xlcymlylITOZ+DCRsJvcC3Ni2dym2BD4vZ10fkPxNm2jYZOcgJ2aCcO2ek88tteKBmcF0jaaEjg6lRHHQ7DZTO3EQ6GVsDdZvReWE0u7UvFtEK/A2mm0o2Y8i+4QZrCJln2z1qHr0TFuutKiwqDl0G9FFBpQREM+a1tPMp1BZ8lWZ0YS4KNGR2KCM3nAiAmThwXG06fhDmJD4nwKFpmOLPj+BYGYsdtcGxvpj3HZ74FQXM9qxQSpjNIhJ236Bi0GynIEgtK5EEIV8K6z+UcrXyYKhDbFRrQ9fKJbMgNoUrbocQ6Cb0dtWYH8ApswOJg/lGHlUIOzRbRoEEesG00k1uvdIymQqImHc6wHDxfB6FLQIfJiX2SBLOYCNRWCJaOvVQmtP3uI1gnx1KgeoyiDs03IrihgfHfI1o0iZ+mkEUhAoqNoMffEkfnGuRYdIsF8e4U57NwZxU1cfIRbkrXAsHXZg1ty0HocD+yoPI27c1HWC7ZFBOmwc0eA+oFlhtht/RADU5zmKro2PqBraW0og0fYoOybYsNxKBozM+g+BSe2YMAhAuvRfiwwKpGKE/m9hr7zBUCeGCdcmOeBHZlKHtwNZ1cadWnN5k0r0AqNRFOsZwRVDbE8x63BUEY4D1BmtDqdWmpsQ3xfLAEmTReLAihsxg/HGGzNU/0amgIgjncFgq7hOQKdpuaeHrZgDeQM1eQrRSNuAFxvdA+OSBYSVBl1dd4cYeysKrk5nkHxIqXiZ6xgRffEdS1JCkqyZoIno8Qgg2BjA3zbBxxNGw6WVpakC1UCFqB3ZyyRwJMPjBXWaBDarwVLDzEVN+l8WUyjCxm06+ZhMEjWqB7PKoYBt3TiGZ82jGZtDMfOgLrEBjH0ROmMCgwwtxcC/5hRgxYnhwlbkilRNMFixNiS7PEhGocBMmkidOXCQdksNqu3VE6BeppZ1BSrdidiyEVLXWQvR6ZXjG2ODtOxn6UqVsgGXMLrgJEZGKWLjmzRhDm0trEleceZFI/N5vTR5U+OieInFDmoJdljT2o754P57Na5PIbAs409sG2mcAfPnLYkY+mBaCqG6yRWYVMMKB6IibM08LrGeq/D3fgG46gti2zp1QZ2xzJkbbFoZXQknuDam4tZZR7UcbkiTcZNKFXthxhpFM/5QMfR3nRnzea2kQTbZnFgazSIdbZll8SqPQYOitdhZCc+8XAY1gdXGcE04s21yhMVE59by9wxgA0k08RNFVgfbjyp89443h3QyKYnpB3wEogUcFMIGyBOIT9IiME2I5E+YX9H58q2jq7uzuY53Ss7mue0ds9tXtE6b05ze/fC1o7W9u72tq7OA2zqVL4rn71v3mz41z6/mbtFofAkq6vM27YVYz2ThISt81kCmbHEcpZNsjSPEe/BNfSjSaAIDjZGa+NJPlOItlaR/dY3Q+BrbpEgQNlnyCUdc1NnCz+gYEYnIXCA9cfSEBPEopRhS3LPzan/fmYeOaPVw7U1Qsm1WjKO+t2N0s62gokC65gYhSgObSTZQ8xw2TKdrzCdVL0jkaA1oxUcFD7cQOKxP107YCLOejPRTMxihTicNlxOWrgc0qhEHEgm55POBTfEdLzAWxMd0+hABPQ0jmd/4mB3Ip/a2lhqCKOmnINq4s7QJLXn8hVZ0NeXQMufbmuH5m2Ttm+bzU/krfHOjlbWMkCXC2AnRgcynM6scnCY3Hg2HhW3NdCtJcyjKwoaZv7EqjkBYbbmAiuw0NLMUHuUhkTsaM2jTITo4OC6tL3JSSv1T1bpw22KZ1sow43WWFYyLCD0z40fZDrRUqAk8YMiCvJIMibDYZDak9wcTe/uj+rUilz8Blg4Ml5pY/tsYugaymyPEK9EYUW3rmt6unc0hceFGASL2+Q8cyiw6aOvqzWmzhYddXEnqQ6DI5QTAoHzSQ7nbG8mX2xrdxNqEDZ3XXGXZblbF2cOmdE0qXeabwbxgBE6EeFnrg+A7ZKINpZYLq5QhtpbhS3J8tzIZwWtvd0KzLECc63APCsw3wpYtaH9A1raObO5HTLmyPcWK0aHhmJ6jB8x8MMaECsuHnQcRgbfeGWAvEQZ5Ocf4vqtE0Ps3EO9VaNxy6GUeaOCW8osGttZS9gGcS7eGx+2HBmCCeuxdEa2zGx3NDz1J84iMS+OVsS2lvbdHCPOmmk3AG4dRhvg90j4Psk7wqJMZ7vx2/yOMH5T3zGCfznavYX1sEWILV7JOthm+F3DYX+aZahNhsXYIGAijJX3szjAMwHqZxr8wGYMelnKmDPG9gDEvDuhdgJ+NOhxD+R1KI8DlISy+ayFtdIvcxvtWfMglKdhJLxoAM5BLg0/e6FUh3HXAgxrxIapL/wqxwAbwf8fViGsIRuDWqPYi5tjgW4b/BbGoM0w9JvEv0bt1liKIYa5cSbYE3NmGGKZcxR6TTCmDkFvSHc/fA4An5g/Bj2OMhwlY8zAHaXRYG7us4j+EcYqByi3G+rAOjHkA581jOLlvVI+mAIsUpSBOeKFA2KR8iGaKfSk4jz3QJ1hGhMpT7OdULoXcjsBP4i4Yut4sILqIOO8RyyOxYpTRMEAzRlGKM+O3MdS1rELc6CyNLRBGNvxkQEbHKB5poimPoarhavBVIMXQ4BJEA9HqSed1msEaVVTeavJHMPEPZPLxXz2e0nScFV1kh8N4EGav1gnb3YOOD+d5owcAN74U0I++DxGqf4A9cJXAWnSaRxWaKwbyXitAYVZN9sHdQcgh3dhS9lsgJljG/7FqODEWtS60IC24t+dqZxYC/FUs2MDzQIpWylWO2zmOk1KB6k2zg21FWcbJzkG/WpdD7l1NN+thB0kuQgT93Wz7W5RBi3aU+aYYZYrWbzXMK2lTpRmgIYxxhqTNMLenBFiMBuUpZSpBzQnNcvhDGkvc5vr7t1Dcj+K+cJB4gqfD3NzOdoJ+DSNPEoUMHcGPqm+uhPKMzAazpioUnfSOJksxjYLVn0xzSDbN8y5GHHGCABXI+0pmmVWi7sM7SpbLGaXEnwgS2YDKVGxJIc+qrs6n7Jig9ZFbBb9zVUDThuY2lxtDQt+hQm3lP4vRkNEf4LWEDDluS36shapXs+xLmGWW5OvCrfauHpCo07vJR3NCB2Lse1gU+Ok6chVXrYdvECSuKKTzcwIKU7RGuuE3062GfWsN0/PYjQi2sQY9coKdxJukNvswiFh6wmq22CxRivE3Iap3SjRzZxj3LKVcZ/F7XifYQnU2eRBFrJ5oJtz8a/IVubW66exMtw6B3PLEnTRizYxF6+TbuDqscpesgCI3w0lm6GfPtBV9Hus96Pj5VpDI5qzli2cY53DUCNFreKmfrPqo9Wm0vmd1CYjpDYsqIxCLk7SlyTehMkWoF/mPpcVD5JORNkW7g2bDXgR1BkRqz4Leka7sZgkEkedx+bgX+j27iXfxLUaV97kpTdDfKMxyifzLkT1jN5JSnL1gup9aW2EbumTZLC4MkcgGNnPCpmHhd/nBw3MGHx+sNrGzx5iYZhCi6XC4KBRGBHOtYkMNi87jZ0OzDm+3kfM/lsmjLEW4EFazo/BTxiE/vhGGcgZxerW80eYAT/HN8Y+oDsqRjn+XkaEU0lb6B0mXDcJhMGZNBiQMVBRFNB1wvlEYFSj/QyQjg9HAQ9HMNg1aIlTMLCYcksslLUQJagQKPi8vBF+Zn5oGcuf/U5aiaU5fDgNej/d5EIHGTidFHiUTA3O2nA+zQCfCfg49PjhOWD8xIEXyAdOzXT44ZS1kGldQ8EBmrJOYQwiNPOl9INrvw/oQFlozpE0w+TMoNpWaflwcx0g7c8IOeC9Ha/sHjguGY0C9WvIjGb+a/3XYG67jlvaeWsexn0UEr/LlPhdIPEGbRPlfddHJO8D5D743I3RToP0/WUgIbYX2P6/k4GJNPUT/OFp4pbUcJEfLVUZCuY/PFUZkJvUR0aNVfJbaIuBTjsCP8ZK8hE4tcZo+VKKhxBhaoOcXkZ1UIdmiBKObyT86YRdJKie+aFl/Hg1PEWh/PFppRG8xT4irdxtauVu0EqDtolaudvUyqOtUy5ti0yOR8xeT4NePqik58rULtpoRo9rlYyZ7oFxDK7PpgiLH3CsFDzJ4tN0zLGZNnGZ/zrqwAD1eFebB7dxCr4/itUeMVd7BFabUzZxrUc+IgucoOOApUQBH+s06Pv9JCBB275h8uHDeZLwwXs5mm2aecxI47+LaXC+LeKQA2VnPeCRFi55uSsZZicIiTOoO3br3DYzTXnGlfrvqP7gPOXyxCnhkdsHb8uPGIyoamae9n3Us8gI3Z05iTY3Cn3eDtQYNmry1v9feAOMrkdY4hj7tFxLwX3a+9fjkpQkCV8Ns18LEp/1dcdnyfpJIzmlE7maz1NjZouP20vGTbv54WNgQy44zZPpVYfY76NcbgNsfhxh1TWDmlx/x481w8foCW3Kh7fb7097/tq3iGuGD0r5sdp/1LRGyR7ggdxOkNE9OXur96d08tZhNou0IHaUnj/qORgXJvxEA3nVRRcWePQ2/IHnYj0Ab/kAfX7UsxgQx3YZuhAzjvGPj/qj9/VRUx0T1x69R/WgH5Tmo/X00fM5Qb3304UTHpd3iYPP4+X1sfr7qKnvB2inuNhB37zoKPHKsVfMOEROmyeqH3TunbA+vdR/Lh1c5yfv+3isrOFphugaZ0RcpBxPlJ7tgceX1nia+8IP22P8mH1+uHnq4loFrw3Qk+KpcJM4t20yT8uaJuzsrCNOLN0FnI+LdQ3TrgHpbDLj0vz9VVPOeltbN1naWtfi9Lx6KHUffJUP0AxRSwZIrmJiP5PPjxmwIpvgh/fOVwtPI0eEhPE9yOL3je8OQP8oh5I7xvg1JXNgn/wiP3vRrdOVp0YPIPCCBP2wcU7OyiY7PWdOvkKsPJoTZ3SKqy28XMot6RJ+Ea85WGX+7sPaLhuV81WylJXh+g+Tdx2DCIevHCvLrpClrm3ZhHkaF/p0xbKwM++sNk4WLUM3JwN0/jtAj0gmXM6U9UKdNHmZEVgl8bijrBNKt+dcWQNt87cza+121gZ1VrJW+uyBde4kj6uJ5wSGP8i22woWbCtdP32gdnuxjEche8TzAv5EImx5NoG29v37mmm5RBsyryzDZN3CpIE8Ft6A/9uxpb1A50qwGlthXTZBn9vJAyfoypBf2vKxDAlaLx6q0EVpc9eHeRizdOLV5IcYq3CQ1hxlZxFjXlytlHhYY+zPMcf3EPigYsSQWr/xACEb1zFVozu6neJ8AC8YNfGYQfRa35H3eCRs+vxR8eCI1eY/MOkT3gQf5WToAUGG5BQ9EnPgRTjrze93kXgQYOUcfzSBcjB4lNWM02p2AY/Wwgx5jT5LDdY8kf7sLi7Msg9OSDdOn1i7n6QQdYk/ruonDVsFa7aeRv4QKz+tC/CT8TOHhsIoRSWjdOLHbGDv9m+YwBfkbT+sbdzis8OWEwHUkS6gpwN+e6gkSfZqjOwVzmSmeOLAayNFYSE1/HJXPKSalr8mfZaxM4YEeLNSyZZ2mtang9Zgk8U+T5xJ3uxJIq0jsMIMacZu8UDng2jqZFf93caDslX5l/75V/5G+XDOY5ReoiZm+mt8iMbtKn9AMoseQfE6zCkeldha8p5lNUOOa7VUidQuECuA4/IHA/QQisrmT17mxrJWeprHc7NhPMwtFJ8LxOd88TkXapoWdvyGj/5lBJr2mFBwXbixJB1Y4cJgaTe9WNxCC4ZvSTaRW+ilQKGPTN0WYCzW6YGSdSB2nfS2QyO32EduaVCEe1vFSxBgQOGIeI1FC1u/gVoMC3e6UixPGlRhHzBlHog8O+lYorGdnHJKCFN26bcz6zgmK8uPNh4LIoU8ZOHXLOLt4szJ+pnMsLHqZhAVfhjSnPfKawqTbFNAjA2qw3nlk5nJCDjL2eTuMvROJCYMDHCk+Wj97BXX+gOWV2/4bsW6LptIRPnrIesarRbvwFYDdh0YIla+Bta1k96soknaADj+hpWVH9XVlceJziymRWzkWflq6HkR0ICvA9MU/g7RD2vHcJzXChOdGbGhHqRgOUOPMjB0OAmk8HQKP/GV7WmQnk4vbgkT3JsTBpmvdmpTMEZbDk8MA0blMWs7o47xhi/7/o8H7vzt7V6z3NpnhOQvSa/5ErCByr5OhRUbyO95sjeL6JSGqPWYeEUUFTXTFAhbQ/EwrNJaWM1OhquEWsm688cwZj55vyvIXGLdHpJ8jdwlqz06P4hfzbj21jXvszitPuinFdJemnuG3Hvuq1t8gcZxzG8YWX5VRmWNE4/kjvZgh83I7VsjaTNeyXYQl5KW7YVhxPF9bJw2ndl32xji0ObCP/GNJqtdRfRZ55wjQVp2La1HKisox7UL62Vfoua+MR0QcmVIWUqst7GKE9a5/mg9WWhaaH2fii8qN5H0xNlZghpry15T45aCfQ6T2zyLQ0FrYNMvLqUgFDz32eyLL77zm3hWYyjGUlKkiS/LeFtrPxPPqTLmk+cEYCafOL+xmnyvu5+wB6g8nDda/glIH7GM0/t+lEwUCYOK/BMm3uvMvDHDx5y5liNqS03aJp9l66S9549gPY9vIUUYEk/4uUvkezbcj0RyqGkS7wuyFPGziv2Cc/wh8iKTxiaajU4qZsTYiwQtWLNJPK1N0vjD5GYnq8fPEiafcZu5svlnHfn5iW3bLVIxubxIKt/RZtWazeSPcvHrHKvFA+DE5LuR4OThCJu5StwKTlaao7qFafE8lqD6TcJMp4UEdtBpmW66OXC6M/T3rUN9vXrrG7f8a92LHbcPnnDJtSe0Pcdcd5+1/eTyOb+7QFaKPNnvj9gYCzmZLIdK1AI7k2QAbK6Qr9oFn3LIVxKCCrLCbKGQK6RgkcsF1dwhF3PIRUVFrpCXKZDxVZe4sIIsQxP8/4WGStwO7NblYU4ZGsM/REAOUujFyexyyB0K2RRfnax4nEqZb5pc5IG+pSIYUgL8TPgttTPmK4dMs6xUuVp/uODkW+etmwtwq6yEZEWWFRcAcxVovlCCztSlrtuW9Z2t/tqzCIAOF0zC11ztACrkIhqhqsgLsxBZlxuG43kivdzlpI58VdBplZvZpZKqErnIBQThrCXZplQ7IFNUBJOgVJKAOsaKkHWIdBVRRZykFAphVWAoI+IQH4IWagfyWPItcAETZPgske0umKQjLEtVIUiBSe6w3dcdCvl6qhxhSfZ1AzkLbGHgSpjJ9jCwSMHKvrW2CAOafCrUknwqlFbZw8y3kcAtALrsEQChlssZtruQ356wAz7dMK8qJ/SB88MOZexQ5nkX1KECd1GRrLixJTQMKWHJVaJGXNABgiGo6oJmIBIh8eGGTlwl/CNUAlOBBiEnFLk5JPmaKF1gZ8vpL0fbGRB/OvzOwXGrgE6cr6SOSBWSH8j3CKlASv3MLwEJfsgAE4uqq+xOqZrY44d1ov/LOLJk/AK74hu/SABfQOAKCCB941fBkhRVVcGo6lIHCNX4tcAqdambyer4DepSdSmMV6jAGqnjt+IHdELVbleQ5PErUBCbOT1VUDXE0Q/yqo+VOO28yDf+MPRXXYXTBrlz2Z2yyyWkuwqpeQIkDUuo88NAf1G1Q5ktSTWsyOURwugMS75u3/jzME5RsdNJElztKPItgWm4QED8rMQv2ZwSSW1RiQuyKHGgh6BWRfiPdC9U4nQWgUQWQTNDyoHYF0PQLyp7YaGQdmBQNbIVNRrauFxQyQdTuar6/7V39bBxFFF4f3w3u+e7xbu2wYFZdJFsgSUu2vvLXQoDa18iguKEyI4JklHk849Acn4UKYULpJuTUlC4SIEExRUuKCiQKCmIRENBg0RBQYFEihQpAFG4sFCA773Z9V0OS4BEh+f2ZmZn37x58+Z7b/bm7nYC6bD29l2yj84+DgwV+FPhQaGYkZ7feRwoU4ZyXIzKoCglavck1bZCxpgMVIbolctMlIsDoDLJJ/BwxxSPG6xRVfCFS1ccPx+8CibQpiMSvTCXSVAHocexTVpUJ/JwJp6vTgZqZqygdVLIFwW3AEZqFsT+XAHCwFOpGVa6DW9GmpoVz0BA33Fk4hQQLIgZFoh2kpAR2kHnEfeFWinnSGlM7LlFKwQrX9XJGmw9zBANPsMhPTkviIIDYfs14DJ1JoVLL7RDOI1soOagAMSeU7RNT/oqHhU2zuno9AiscGcjiFhtFnWORzNQ56EXXy0WillT93fRV5cZmLhECnoboDGDEjJgE2bYfjIzIufHfj6RQ51lVm/15UoQU7QkjE13FL2vPytcKCkcpgslekHy7AXq+oRwQAH1XU8u4oxkljABw3Skm3bMwlAA2HDJYYZevrojBOfJtyIWDNDOPo/8jsbPDg4+f48VtuO4RWPSVwoQcjhlkBoMqEDd9XSt93GQ2jzvkpgiJHNJwt7R0AY1yjx6a8H7nUz4AhHAgo5DqV9oBiQPcuhUpwcDD1qsYO918RxqHNWCPjzP07E3gIYjG/LgIk9ol3+Fe36X7Aq1d8dFNmW5G7ymybPs+64QpHYzAsx62rJ2gUjJ4LRtZG34pRGMARDvsMkE6h4D6QMhoK97oTbaHmvxY7Z49QmffOoR2imyPC7Y8xIP5yTJtJiAkcPzQMaPPIcoHPDcc2BKapLtCbTCwuU5+HEYsjCn2Dntkcd0vYyeMnHpjVGRBZY8xpAjbEKVP0fzRQ6UOb55ISPNsuamaA7midUCuDHTJp53Sid+bGkyoCwI/XzOFRk/jwrBMtryY7JZyfobsxiAmDdtk/04zElmCZuWLIgsdew+PIMkUQyagKG4r0jPsL6nMCiyQG6QTXERo3c1V6Q7DfU1QCr0GEsIEfiEl1WKrh4OvtRsvk1853dJ+n2S/qDnNvWABvghN/yI4590vV91sq+TAx63xzzvzjIOuqZOMjpxNTgeegBDl4oJSV03z/J2CxbNuzSPYO48tHQYcHo7leFdOjGU5PQdTtAbGrjLGFNvgvC5yyz7vGdNY3q+UanMLyzMl2pnTzdL5ag8X4pRUIqiOI6iWlRrNCKDpwS/e9Ixkx3fqWa1FjfK9Tgqna43G6VyuRWVzlRqMWpWovjcQiNeqLVwv2YaFldB5rc0kzWTjEgzTppx00wuzYymGd9Mm25vVLcq1fWotFGrbqLp9a1S80y1jabX1qKovbFOjy7RQkb1aKu6BdGa7bqmbLeblQHKqJ12r6yFoFsY6C8iZw/1RexND/xuHXYBLB0AspKVDETS9HowihHDOU0hkrrCLJ4nVS1bT795e+3WxZs3Dp+3tvwOPS3BND7/ub9fxzeULxpHhi8P6a4t3Lzd2t7mnQV4O4vNTX7YJoU/ZlB/zDgO/zCYrKwp2oJ5qJwgEB1RToG2hL+K/KrVv7Jq1RCvGEv4KL7C6/RLydr8NaQXjXMGb9du3B/55feUz2B4JUlp/xZr6FqLW17hpZJ01fw8f4jXu6RPc61l/jBPXwY98c9+Dp+NfMF79y4lP4ul1a2/cvqQaaLDV81okw6MlwzaUyilb/FqVn+trd9OkXXmDNCuPPmcBL5+auBNffNBP/jtCS1rpD9EMYzhFc90pfwULwNo1L/I8l1Ifiywzd+n3DJ2Bv/7yrJd4LYuJeXvJm2lst74V23WuJ96+WbDuMNLO8O9He5rk+vEvJJMXzS3k1Xhv6t3HP7D8KNh5Cl5+VgV/8fwJ8qULVYA2AAA' if ($env:SETUP_COMPILE -eq '1') { Write-Host "[2/5] Compiling IE tab helper from source (/compile mode)..." $psexe = Join-Path $env:SystemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe' $old = $ErrorActionPreference $ErrorActionPreference = 'Continue' $out = & $psexe -NoProfile -ExecutionPolicy Bypass -File (Join-Path $dst 'ieopener.ps1') -CompileOnly 2>&1 $rc = $LASTEXITCODE $ErrorActionPreference = $old $out | ForEach-Object { Write-Host $_ } if ($rc -ne 0) { throw 'compile failed' } } else { Write-Host "[2/5] Deploying prebuilt IEOpenerHost.exe (fixed SHA-256: 27f553a285768dd5... / no compiler invoked)..." Expand-GzipBase64 $prebuiltExeB64 (Join-Path $dst 'IEOpenerHost.exe') Expand-GzipBase64 $prebuiltDllB64 (Join-Path $dst 'IEOpenerHost.dll') } Remove-Item (Join-Path $dst 'IEOpenerHost.cs') -Force -ErrorAction SilentlyContinue Write-Host "[3/5] Testing the standalone helper..." $exe = Join-Path $dst 'IEOpenerHost.exe' $useExe = $false if ((Test-Path $exe) -and ($env:SETUP_LEGACY -ne '1')) { try { $psi = New-Object Diagnostics.ProcessStartInfo $exe $psi.UseShellExecute = $false; $psi.RedirectStandardInput = $true; $psi.RedirectStandardOutput = $true $p = [Diagnostics.Process]::Start($psi) $p.StandardInput.Close() $buf = New-Object byte[] 4 $n = $p.StandardOutput.BaseStream.Read($buf, 0, 4) $exited = $p.WaitForExit(8000) if (-not $exited) { $p.Kill() } $useExe = ($n -eq 4 -and $exited -and $p.ExitCode -eq 0) } catch { $useExe = $false } } if ($useExe) { Write-Host " -> direct exe (fast start)" } else { Write-Host " -> PowerShell launcher (fallback)" } $tabTarget = 'ieopener.bat' if ($useExe) { $tabTarget = 'IEOpenerHost.exe' } Write-Host "[4/5] Registering with Chrome / Edge..." $originStore = 'chrome-extension://ingmhjfnoaobdppmhjdnmccbmnnibjbo/' $originDev = 'chrome-extension://bhkmlgbnhggnjjcpjgigdalhebjgfggi/' foreach ($pair in @(@('com.ie_mode_opener','host.bat'), @('com.ie_mode_opener.tab',$tabTarget))) { $name = $pair[0] $mf = Join-Path $dst ($name + '.json') $p = (Join-Path $dst $pair[1]).Replace('\','\\') $json = "{`r`n `"name`": `"$name`",`r`n `"description`": `"IE Opener helper`",`r`n `"path`": `"$p`",`r`n `"type`": `"stdio`",`r`n `"allowed_origins`": [`"$originStore`", `"$originDev`"]`r`n}" [IO.File]::WriteAllText($mf, $json, $utf8) foreach ($root in @('Google\Chrome','Microsoft\Edge','Chromium')) { New-Item -Path ("HKCU:\Software\$root\NativeMessagingHosts\$name") -Value $mf -Force | Out-Null } } Write-Host "[5/5] Verifying..." foreach ($name in @('com.ie_mode_opener','com.ie_mode_opener.tab')) { $v = (Get-Item ("HKCU:\Software\Google\Chrome\NativeMessagingHosts\$name")).GetValue('') if (-not (Test-Path $v)) { throw "manifest missing: $v" } Write-Host " $name -> $v" } Write-Host "" Write-Host "OK. Helper installed. Go back to the extension page and press the re-check button." } catch { Write-Host "" Write-Host ("FAILED: " + $_.Exception.Message) Write-Host "Please send a screenshot of this window." $code = 1 } if (-not $silent) { [void](Read-Host 'Press Enter to close') } exit $code