From d101cb52479c69a673114d59f6455be0a69d66a0 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 3 Nov 2016 12:00:39 +0100 Subject: [PATCH] Windows tray app (#3103) * Check if already running in ui command * Windows tray app * Upadted CI scripts --- .gitlab-ci.yml | 2 + appveyor.yml | 2 + nsis/installer.nsi | 54 ++++++- nsis/logo.ico | Bin 99678 -> 67646 bytes parity/run.rs | 10 ++ windows/ptray/ptray.cpp | 274 ++++++++++++++++++++++++++++++++++++ windows/ptray/ptray.ico | Bin 0 -> 67646 bytes windows/ptray/ptray.rc | Bin 0 -> 4364 bytes windows/ptray/ptray.vcxproj | 155 ++++++++++++++++++++ windows/ptray/resource.h | Bin 0 -> 1788 bytes windows/ptray/targetver.h | 8 ++ 11 files changed, 500 insertions(+), 5 deletions(-) create mode 100644 windows/ptray/ptray.cpp create mode 100644 windows/ptray/ptray.ico create mode 100644 windows/ptray/ptray.rc create mode 100644 windows/ptray/ptray.vcxproj create mode 100644 windows/ptray/resource.h create mode 100644 windows/ptray/targetver.h diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c1fdabd12..b50ca7b22 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -322,6 +322,8 @@ windows: - curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll - curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe - signtool sign /f %keyfile% /p %certpass% target\release\parity.exe + - msbuild windows\ptray\ptray.vcxproj /p:Platform=x86 /p:Configuration=Release + - signtool sign /f %keyfile% /p %certpass% windows\ptray\release\ptray.exe - cd nsis - makensis.exe installer.nsi - copy installer.exe InstallParity.exe diff --git a/appveyor.yml b/appveyor.yml index 75a2da7cb..e04caf233 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -38,6 +38,8 @@ after_test: - cargo build --verbose --release - ps: if($env:cert) { Start-FileDownload $env:cert -FileName $env:keyfile } - ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass target\release\parity.exe } + - msbuild windows\ptray\ptray.vcxproj /p:Platform=x86 /p:Configuration=Release + - ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass windows\ptray\release\ptray.exe } - makensis.exe nsis\installer.nsi - ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass nsis\installer.exe } diff --git a/nsis/installer.nsi b/nsis/installer.nsi index 2c7c37428..448618bbf 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -1,10 +1,17 @@ +!include WinMessages.nsh +!define WND_CLASS "Parity" +!define WND_TITLE "Parity" +!define WAIT_MS 5000 +!define SYNC_TERM 0x00100001 + !define APPNAME "Parity" !define COMPANYNAME "Ethcore" !define DESCRIPTION "Fast, light, robust Ethereum implementation" !define VERSIONMAJOR 1 !define VERSIONMINOR 4 !define VERSIONBUILD 0 +!define ARGS "--warp --mode=passive" !addplugindir .\ @@ -13,6 +20,10 @@ !define ABOUTURL "https://github.com/ethcore/parity" # "Publisher" link !define INSTALLSIZE 26120 +!define termMsg "Installer cannot stop running ${WND_TITLE}.$\nDo you want to terminate process?" +!define stopMsg "Stopping ${WND_TITLE} Application" + + RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on) InstallDir "$PROGRAMFILES64\${COMPANYNAME}\${APPNAME}" @@ -26,7 +37,7 @@ outFile "installer.exe" page license page directory -Page instfiles +page instfiles !macro VerifyUserIsAdmin UserInfo::GetAccountType @@ -38,6 +49,31 @@ ${If} $0 != "admin" ;Require admin rights on NT4+ ${EndIf} !macroend +!macro TerminateApp + Push $0 ; window handle + Push $1 + Push $2 ; process handle + DetailPrint "$(stopMsg)" + FindWindow $0 '${WND_CLASS}' '' + IntCmp $0 0 done + System::Call 'user32.dll::GetWindowThreadProcessId(i r0, *i .r1) i .r2' + System::Call 'kernel32.dll::OpenProcess(i ${SYNC_TERM}, i 0, i r1) i .r2' + SendMessage $0 ${WM_CLOSE} 0 0 /TIMEOUT=${TO_MS} + System::Call 'kernel32.dll::WaitForSingleObject(i r2, i ${WAIT_MS}) i .r1' + IntCmp $1 0 close + MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION "$(termMsg)" /SD IDYES IDYES terminate IDNO close + System::Call 'kernel32.dll::CloseHandle(i r2) i .r1' + Quit + terminate: + System::Call 'kernel32.dll::TerminateProcess(i r2, i 0) i .r1' + close: + System::Call 'kernel32.dll::CloseHandle(i r2) i .r1' + done: + Pop $2 + Pop $1 + Pop $0 +!macroend + function .onInit setShellVarContext all !insertmacro VerifyUserIsAdmin @@ -48,10 +84,13 @@ section "install" setOutPath $INSTDIR # Files added here should be removed by the uninstaller (see section "uninstall") file /oname=parity.exe ..\target\release\parity.exe + file /oname=ptray.exe ..\windows\ptray\Release\ptray.exe + file "logo.ico" file vc_redist.x64.exe ExecWait '"$INSTDIR\vc_redist.x64.exe" /passive /norestart' + delete $INSTDIR\vc_redist.x64.exe # Add any other files for the install directory (license files, app data, etc) here # Uninstaller - See function un.onInit and section "uninstall" for configuration @@ -79,11 +118,11 @@ section "install" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "InstallLocation" "$\"$INSTDIR$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\"" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "Publisher" "$\"${COMPANYNAME}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "Publisher" "${COMPANYNAME}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "HelpLink" "$\"${HELPURL}$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLUpdateInfo" "$\"${UPDATEURL}$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLInfoAbout" "$\"${ABOUTURL}$\"" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayVersion" "$\"${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayVersion" "${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}" WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMajor" ${VERSIONMAJOR} WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMinor" ${VERSIONMINOR} # There is no option for modifying or repairing the install @@ -91,6 +130,9 @@ section "install" WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "NoRepair" 1 # Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "EstimatedSize" ${INSTALLSIZE} + + WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Run" ${APPNAME} "$INSTDIR\ptray.exe ${ARGS}" + ExecShell "" "$INSTDIR\ptray.exe" "${ARGS}" sectionEnd # Uninstaller @@ -107,7 +149,7 @@ function un.onInit functionEnd section "uninstall" - + !insertmacro TerminateApp # Remove Start Menu launcher delete "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" # Try to remove the Start Menu folder - this will only happen if it is empty @@ -115,6 +157,7 @@ section "uninstall" # Remove files delete $INSTDIR\parity.exe + delete $INSTDIR\ptray.exe delete $INSTDIR\logo.ico # Always delete uninstaller as the last action @@ -131,5 +174,6 @@ section "uninstall" # Remove uninstaller information from the registry DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" - + DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "${APPNAME}" sectionEnd + diff --git a/nsis/logo.ico b/nsis/logo.ico index 4fbaa4d39cff498e1cba9deda57b3fd031e98ae4..61e68b90b86ccb69f7c13a0595bba8ffd1943c4c 100644 GIT binary patch literal 67646 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. use std::sync::{Arc, Mutex, Condvar}; +use std::net::{TcpListener}; use ctrlc::CtrlC; use fdlimit::raise_fd_limit; use ethcore_rpc::{NetworkSettings, is_major_importing}; @@ -94,6 +95,15 @@ pub struct RunCmd { } pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { + if cmd.ui && cmd.dapps_conf.enabled { + // Check if Parity is already running + let addr = format!("{}:{}", cmd.dapps_conf.interface, cmd.dapps_conf.port); + if !TcpListener::bind(&addr as &str).is_ok() { + url::open(&format!("http://{}:{}/", cmd.dapps_conf.interface, cmd.dapps_conf.port)); + return Ok(()); + } + } + // set up panic handler let panic_handler = PanicHandler::new_in_arc(); diff --git a/windows/ptray/ptray.cpp b/windows/ptray/ptray.cpp new file mode 100644 index 000000000..ac2f197a7 --- /dev/null +++ b/windows/ptray/ptray.cpp @@ -0,0 +1,274 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "resource.h" + +#pragma comment(lib, "shlwapi.lib") + +#define MAX_LOADSTRING 100 +#define IDM_EXIT 100 +#define IDM_OPEN 101 +#define WM_USER_SHELLICON WM_USER + 1 + +HANDLE parityHandle = INVALID_HANDLE_VALUE; +DWORD parityProcId = 0; +NOTIFYICONDATA nidApp; +WCHAR szTitle[MAX_LOADSTRING]; +WCHAR szWindowClass[MAX_LOADSTRING]; + +LPCWSTR cParityExe = _T("parity.exe"); + +ATOM MyRegisterClass(HINSTANCE hInstance); +bool InitInstance(HINSTANCE, int, LPWSTR cmdLine); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +void KillParity(); +void OpenUI(); +bool ParityIsRunning(); + +bool GetParityExePath(TCHAR* dest, size_t destSize) +{ + if (!dest || MAX_PATH > destSize) + return false; + GetModuleFileName(NULL, dest, destSize); + if (!PathRemoveFileSpec(dest)) + return false; + return PathAppend(dest, _T("parity.exe")) == TRUE; +} + +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + CreateMutex(0, FALSE, _T("Local\\ParityTray")); + if (GetLastError() == ERROR_ALREADY_EXISTS) + return -1; + + LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadStringW(hInstance, IDC_PTRAY, szWindowClass, MAX_LOADSTRING); + MyRegisterClass(hInstance); + + if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) + return FALSE; + + HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PTRAY)); + MSG msg; + // Main message loop: + while (GetMessage(&msg, nullptr, 0, 0)) + { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (int)msg.wParam; +} + +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEXW wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PTRAY)); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PTRAY); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + return RegisterClassExW(&wcex); +} + + +bool InitInstance(HINSTANCE hInstance, int nCmdShow, LPWSTR cmdLine) +{ + // Check if already running + PROCESSENTRY32 entry; + entry.dwSize = sizeof(PROCESSENTRY32); + + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + if (Process32First(snapshot, &entry) == TRUE) + { + while (Process32Next(snapshot, &entry) == TRUE) + { + if (lstrcmp(entry.szExeFile, cParityExe) == 0) + { + parityHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); + parityProcId = entry.th32ProcessID; + break; + } + } + } + + CloseHandle(snapshot); + + if (parityHandle == INVALID_HANDLE_VALUE) + { + // Launch parity + TCHAR path[MAX_PATH] = { 0 }; + if (!GetParityExePath(path, MAX_PATH)) + return false; + + PROCESS_INFORMATION procInfo = { 0 }; + STARTUPINFO startupInfo = { sizeof(STARTUPINFO) }; + + LPWSTR cmd = new WCHAR[lstrlen(cmdLine) + lstrlen(path) + 2]; + lstrcpy(cmd, path); + lstrcat(cmd, _T(" ")); + lstrcat(cmd, cmdLine); + if (!CreateProcess(nullptr, cmd, nullptr, nullptr, false, CREATE_NO_WINDOW, nullptr, nullptr, &startupInfo, &procInfo)) + return false; + delete[] cmd; + parityHandle = procInfo.hProcess; + parityProcId = procInfo.dwProcessId; + } + + HWND hWnd = CreateWindowW(szWindowClass, szTitle, 0, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); + + if (!hWnd) + return false; + + HICON hMainIcon = LoadIcon(hInstance, (LPCTSTR)MAKEINTRESOURCE(IDI_PTRAY)); + + nidApp.cbSize = sizeof(NOTIFYICONDATA); // sizeof the struct in bytes + nidApp.hWnd = (HWND)hWnd; //handle of the window which will process this app. messages + nidApp.uID = IDI_PTRAY; //ID of the icon that willl appear in the system tray + nidApp.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; //ORing of all the flags + nidApp.hIcon = hMainIcon; // handle of the Icon to be displayed, obtained from LoadIcon + nidApp.uCallbackMessage = WM_USER_SHELLICON; + LoadString(hInstance, IDS_CONTROL_PARITY, nidApp.szTip, MAX_LOADSTRING); + Shell_NotifyIcon(NIM_ADD, &nidApp); + return TRUE; + +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_USER_SHELLICON: + // systray msg callback + POINT lpClickPoint; + switch (LOWORD(lParam)) + { + case WM_LBUTTONDOWN: + OpenUI(); + break; + case WM_RBUTTONDOWN: + UINT uFlag = MF_BYPOSITION | MF_STRING; + GetCursorPos(&lpClickPoint); + HMENU hPopMenu = CreatePopupMenu(); + InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, IDM_EXIT, _T("Open")); + InsertMenu(hPopMenu, 0xFFFFFFFF, MF_SEPARATOR | MF_BYPOSITION, 0, nullptr); + InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, IDM_EXIT, _T("Exit")); + + SetForegroundWindow(hWnd); + TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, lpClickPoint.x, lpClickPoint.y, 0, hWnd, NULL); + return TRUE; + + } + break; + case WM_COMMAND: + { + int wmId = LOWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDM_EXIT: + DestroyWindow(hWnd); + break; + case IDM_OPEN: + OpenUI(); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + } + break; + case WM_DESTROY: + Shell_NotifyIcon(NIM_DELETE, &nidApp); + KillParity(); + PostQuitMessage(0); + break; + case WM_TIMER: + if (!ParityIsRunning()) + DestroyWindow(hWnd); + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +void KillParity() +{ + DWORD procId = parityProcId; + //This does not require the console window to be visible. + if (AttachConsole(procId)) + { + // Disable Ctrl-C handling for our program + SetConsoleCtrlHandler(nullptr, true); + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + FreeConsole(); + + //Re-enable Ctrl-C handling or any subsequently started + //programs will inherit the disabled state. + SetConsoleCtrlHandler(nullptr, false); + } + WaitForSingleObject(parityHandle, INFINITE); +} + +bool ParityIsRunning() +{ + return WaitForSingleObject(parityHandle, 0) == WAIT_TIMEOUT; +} + +void OpenUI() +{ + // Launch parity + TCHAR path[MAX_PATH] = { 0 }; + if (!GetParityExePath(path, MAX_PATH)) + return; + + PROCESS_INFORMATION procInfo = { 0 }; + STARTUPINFO startupInfo = { sizeof(STARTUPINFO) }; + + LPWSTR cmd = _T("parity.exe ui"); + CreateProcess(path, cmd, nullptr, nullptr, false, CREATE_NO_WINDOW, nullptr, nullptr, &startupInfo, &procInfo); +} \ No newline at end of file diff --git a/windows/ptray/ptray.ico b/windows/ptray/ptray.ico new file mode 100644 index 0000000000000000000000000000000000000000..61e68b90b86ccb69f7c13a0595bba8ffd1943c4c GIT binary patch literal 67646 zcmeI52izT1nZ^SwgpPugB!mzk2?->S-be*PAdp5#frOHTo&-oJp$8X4kR~WiB`%1d zV8@2L8Vl&!*1GFj*6gl`WnEpxUd}%M_dV~ld%pk*igG8vlQT1S?wy(QJm-1KIWu3k zZky@fx^><3|K8p9-+HrdyLIca8SZXdscfh65|v$5Myo7QS*NmI z7rm|7x*DB8yu7B+Ba1C4w*Tl7P zja+MI`O{mVr+(rh74#Twe#Urjw%KNB^UXIe3fs@7G{38JKU02ija)0&%(Zh5o#mOe zKzALsiwgF3gUT~%^T4`^uYG^BZfVP{wo2W*ZId-cp zw@jON+q^h;^LJzWnO>ic+n~Zdac|sXXQ{UU?J`Z}E|n)$ingz=N4qy`j@e?1&C+%| zZl7Md^Gnknd+d>V_wJqg_U)VY?bk027%(91zyJPe|A7P3z=6~QRI6zJ0PW}VDEs&C zpZe=N`|Y={eZTjfz0)2&dZb-;*(Gha-FC*4xTfZH#CCk%rsm$bNA8t-ez7n3OsiEs zt@4yg3+~aTQO7Z00VchA^-O*D*<1MaPX``wU>Y*ypmfmCgVV6#!_tURBhtvxBh#o+ zlu>EaXcg)xBS)o?BS(4}p<`KBJz}KF@Zo9r(4pyI{np@v4oU|ec%V2lF!d8R_U^NH z>e-{GxVCfJZrg2Z*BsXwbzE#n<{ zz4qEm7z{`U2#D05L(+kR4m91^XP>^Q*PeT(U3Pw1 z+IH)$i+gF_L!0~L-f08c;>EDQ_2nv0tMNJ}ZNL5Ysi*okeGa^b4WmzwN~6aLYheer z6DLkknW!?!>q)GaWr9ARFoA8=wyxtRu+R4&a)@}43!EtUGuC-A7Ea~$G2#b2gA=25 z9q0v|7^>?UB8}i0`$>oT?A0w*=HZqT>2YrK3;tm%qC3|&XXsn$&;s~DN|ImK1J)cZTt1v6#snE;&GK~+t60D8EyC1yj-P=ZyU37@A@olzuoq!PoF;KyP>7DAN_o? z`Z8D^dg!4lWj$5fUVNW(LHi0GRCtm3Fh#geg&+K;X#`wCBgBc|g6zknup8oo*@}w2 zKr;@}{;(CLZviJL!XAwnOL5!b+AvnSFj{`Yh;)#AQ{s@lbieqH+&?ASBDO0vZATma zwJm$22g_H&X40REzD|EXO!!g`JuG8?SUSu&5Zip_96$$*16dzz8x9yB+H+xw;SV1& zC(sCSVe;gub{&&h&)N_+Vq)e($p`lxjT5F7?n6}d!MI@dLfSCy5aWWy8peY$@*78* z-#AD-K>v2izTzgdfHtLVY2z2-vXd_AL6w@`2kzQ$@%sM#2k731TYpD?>CcBBCXCw@ zI1u|C^FuQif&*}({tRDux(gU`mJ}m14y1=^Y zL*|5i=IiJ{@WwR3bOE~&wxhj96gEWIqZ1Zqzy+ryqTAi!1N$1jh&CS0XHtb-FrD-er zqTvqKhfm8KVBL%9fvpQeG{E#BbD*jTHOz%+-j2Rr)db@Lno!XNI}Q!d^?16&X6bFbuod?8}<19~&k4WCD z>L04DYke%YJsA8YmXmeTAFCAC6nekIjytCQ8b?9X&_3)i7*Crvtx~kjzKs3h)0_ir zn-=8#v2OOkKFj?*I8fOaegu4Q9jF{z(FE5AjuGaYDDF>IxS(Urr^q}hITFW+5BW24 zQl6J0zQDh9UbN@~IuZ7PTCs%d0lvWq#R&(>FX&Zk<7%5{3{F=4=Uh(I$$qa=yDsqG zd6%6{?}>Z3XSBYKyK}(#Ak2*uU@tv@11i(BUhpFGfaBqU^8x!2Hbmc%@8F*Y-dQt( zBVjwR2j(w0KT7PK3#Hv?@}krV*Ncod+-b)JizzrJ#~9{A5MKljqzP)9NwOuA6n7S! z$o@m*qlk$avl=45X)ndfj7>)$tG0c{0!;oK3%SVx_v-qtFWc4fo@f|05{#xzJ0eXx z0?bv{`hV5}u+AI+cee|f3%2ciDC`A%$asT!)qe=T!Z;%ALl4+baXTT*SkIg&_Jt1E zXB?AD?9YAQIfL(j76{{-tq5M^I=Er6M8p~51lz=$Y9rGHd}iE<-M{V2>jg)&9rl4X^4QXA_8SMXop5_We$sPK^eM(d`e|MQ@l-nuGB#lJ zd@Kj+M}MGFoICu|J%s&1(kOfw+7E1x5bn)lTws4_LZJ&4o>aL}UC(?d?1OQo=sS{DbxhTjz&!qt$P4 zy(qYW9$+)zg8WMI4&5mjWXwygC^f;k zP-=q35~d4iKXZqlp08j8O%uay4#S`>tu&;B%xl;8V;E4Bsc;G%H z+hH@?HrV|s z%W!@9rz*wogZ=9pvB>{+wY?Af!^+_`g$ zGH1?Q+duP|nL6$m=Ly`&7?-@jhLrp$c_CfE#$=3-Fh8P>b!dk3z_B)8GI(INf$x;| z!s5@Y4^?|%_y;FUH=HAG8>;IiC&F$xKY|MteK6jX`Vcn5a}MlR-#2cAZ<&2cY=;UQ zKzE19CnQ%0Ms0inumi(CcKNuzSi_!e;t=NKnC1%~`uU6*U_K+woH;9j@BI14rG*O@ zr6o(2q*G2lIW1qdEG=KYJe_*lsaBtI$|>o@6Hl~b=FOXzX3m}$^rSr}f(OQttO@2Tm>+=_cnMo#+hHFHet2AAx`C~L7xZh^ zt#0Ll#}*~#g$9^bl>6&kfCp|fERKK|rWM2sQ;Y+Qt1#!eidAJD4F8zr9DS+fH+yQ1 z4n8RUDVR9!M_V61?zrR9@y9PpC!KVn@LrzII_u1I?s?~>OD?@6U3=}d>DF6sO}F2E zdwR`lUX!l5=9+ZLC6}ag&pkJte){Rgg$45$q&c(aq@$%9*b9E&eMw(kA4%$zyX z^aFk2{BCzR#{Efjf#Y2Ra^02-!rAm7+XB-Q^dQ>`)nOxo6U`c|%~yaI#)HfYI8d<> zbxxFeVEYR@q3>inVezPV5nPDc{Rrm+egt!)$PX}|;3Ye~qy?{xAy__}WiK7vlGkTG z=HMZNHSRenO`kSB&5+Kc?epdxn@%|Xgmkj{`I%>)nXbI@O2hgiANff7!4H0ro_gx% z>E}QHdHTgKeo>UCo_Z=h@x*u2+uru}blYvWrOPkBJe_^^*$G{kKYxCjCA)#2fVP-V zDLjwVHke;2_k7F*~$W*gvwt-D6J-GCR)jdDBm0zQ=M z#*yF&ILEqbvqSto{U5xoMn5XNFdo1U?Th2GMwGroVDGj04#hDg4+_o5{sX=N`9t)$ zfB*in0j+&DV+p3ubh$$Zwr~l5lbj@NgMFVfXHHtUU}0J!9S8SYZoWDF<3Ijm`t`4W zoqqb$pQa!E=tt>?Km1|($xnWge*4?srgqEkfB*aR%U}L7ec=mVNcY@xkMZCv{nldH z4SWXhHa}84fDdeAH`cFTpDvbuELyZM%{_K*T{8mfY7N$TJ8JhETw6+i(s2*pB91i< z$|jlbD$SW8TgSB=GgC!1?SU5I`*6MSdxm#K7Yh3TKa3;7JLBwi)rZWV32WC0bi>yp z=0q3Z0As7t2^0dG90XOJDku=>V9wTj0T` zKmF-+i@v*h&1(DYs@E!0C zEEnMzV-s2nw!%wjM)dt7Gv3DtTl5INA2$!bW??$vgcHoSf%_*eInmY^Em~ySHFxf@ zcAfaPpMi!2hizu7-}EbKHYM! z4ruxQz(E70GZW3$qWSY>tI_*6yx|S$pa1!v(?9&fKcuU!x++H02=`v~JlC(hAh&COg zI0x=>-lqRhaw4$LoB(698-abJ#%Itm#W)2qf$RX!B@h#~!%+Lcc2mo~`mkl5cF#R~ z+WZZ!o&I;M?&;L!%hP@L-k08V|NUl*PnHhQ59k*QrOEhm*zx037OG#Ie3JVH7hHHj zy79&v(j$*NVp`A@3Gf%*^rkmiKgTB^MsS^-p}sgfEf6NBoqAgO+Sk5j9E59&7cVw# zI2xZ&xdr;3#Sp^Uxxl{A1U`coUQZ`aA?!KFEaUflyBA`YRp*?Ou3C4MuKPy$uXm*P zyyrdXi(mX=`tEnXo8T(tzy9mLtRJ9#x7>0|y87y?jVGrpUF!NojH9;0KA=e!Yv%kz zaDu)ce6V%l>!0CEgY)7L2=EZqx_0?`@{s z!T|>!ps~tHX5a9)PLST-bkj{LH<~TR2G3tGKOHMS5RK$MX-5j{?1Kx~ZTy6bFTOb4 zEMMXM?|=W(a^QaP>wIZES`+>NzljcmH*v)u{_qF$Ax{+t;2-Csox#*NkaH8ZE>6%7 zog2;%a#S<$Eo95Nhee88mnmMwC&kbB@P|JvU-b#|Q{XGwg-?TT`~B~K-wM7C_A8d} zeeZkeeeZi;dhKgpYr4Siacy&@C#F&29X>)k9t0n%wetaO2rf|LQ@USic0+oB9l#gd zw`&am<95sD+W8Ze8vZ@@=&3R2F@?_u&X-<#X*y4F9ok60q{cpa|IB`n`XF}G^8t=O z7!vQ%hd%nzkD48z?`&%MzyJF`!{A)?!6nj{IdkXOdFHC7J^9TI8#b7~dBY7iq~)?b z#GvGzz_iFq33u#yaG#n~pec%HhNMHWamkswXeDMqEV;}pN?R&>N z-eJ0Q*Ijp7Kfn3rn~ckM-Fa7f;DHB>(;WLB|M4GoTj&@*&E0q3ozBrc;4je^W~y%# zexmxl=N~*b`E;BJop2w*b;0~Yaf95@gb5RE&Opp5ZeR+=VBK66Yex-xwt422xeC}t zt{H!4#n~&;EcHQb8(Lh&9Uqti$BE14NK3(rTmW(22S4z^^uZ5)Fn#!+{waM-9Qe0? z`!~amKHSwp-=iO$z2fY2eD2@yihRQ-Udr1?m20Itzz;Ai9@ zWBkIm6^B?J!u`Y+EeKm-b|G_secC23#4|`dU(gOy?E~xP@;>dT9nbUC%+ZHiwBs?t zoW71<#I=Xc6ANK;t!Ul0)utT7@%Zw@0JJN11O1>ccspIEc;Wu^xzByBrk_+!tuu&9{1jRuYKhcpZJ8ZSYx`txxv=4*I0zwI@YJNo_PUJmdL*& zr@%EWmCw0YJVOi6m!-1d=(m@p>6E3X*glS1e(G}PgM8570>5*SIEkIZ4|x6SUzZ+x z>@nlO6Hk1{bYsclCB^}C2Q6ymDywLIPM7w(`kJfLg%@6E?T2Pl zu-)Vd$^Bv9Z;)^Gna_MS{qA?at3qF_|K>NpNnjhlgWZ`e?LkZNw}}V8`qi%(hu(bu zn@uY?2mT6r6u38Qbd9_-KErI~9^n+aLVQ6y$8S(rk8NxpIm~yw{T*q;M>nL$Kl!-f z`(fp~9(w2@)49toyUebM8s1`?@Mp0F=)qlg-DSTwPx0*x#TxF5dOj-hQW1xmE`U3D zTkY8Ue)OSkH|Vd75AZx4b2FN_W~{64pE$mG3}Xq5?J@?9F9qi0WxaO1vG0bvbiRha z_M;8pOe{$I5ev;zyW+PIzY!zjYk?nnh#t^J-~RTu3(T7v5YHVf546N(Dz>V z`q$f6@XOKi(@r~Gal!&!v&I(00sQ;Gzg%}s;B)L1zQ1um*9phK96#`rpZsL{*MI$2 zv+oZ+_+UbB!1LjUA2vVlvBw@y8#ivWJQw*de8X>j>s#sb(lxXXKNXumY=CcpO}qZO z>%}$YI@MNOm*IXyCI6Jy3m#ZGK<04fq=el-KZea2F?pH*Lpy@W6a@;Z0kby})Lupc~i`jsurjvg7oDlccrh ztv=6e1UbX57We^Au))|+k1dXqwk%KdHS$m_pZUyZYKjqZRQK8ox#4u-#NiO za!uH**|TSfJEtXL4+?$@c7b!UKWxEr#lYwnz5qS|8U$C!eSPRdA2Pk?TF8A8ClEK@ zbkofiN8&4fM0$a(ppA~w`E9O*VgkpPnw(`NKV|sG=gyNl7u+_mkGueLh7M96=6y#^ ze6n*x>~8QLx)w6S_r#Yt-l!`_VB9+vGdYI5^BboN>nK7W;$k zefQm$o>VLtcFi>Gt#37s+;PX9mODaYXah9Ba#P|!vksf!W1QlIFphb2MXtJ{5BLJa zg4lrF^xl*vzS;(J7M?5pgG%j~L4yvkd8(Fk6K*w}t2|)6QA`JHAAKCHaQoo)qSS~g z59oKa@0n+unXXV??dxCvy2bVFIPl{i|Jd3UJAn41(+d=rVr$69;Y+f7>s#L}v|`bs z<9&=7J5XRAT=1IwA=kn6qsiDQ_MuvVJ*0P!UeRRp^&PAT8r z#s<5H1Hc^Yk7;7xz5CYot`#^0M%I6&)n)A(UT=%ckvtyK1$v68q2Xndo_6g#;kQtquh5R*j&P#C+V`X<=3nSH-BvR1#dF8RC*&l~QO@|fSH3cR z{_~$Nv<)qI_q*R^A2_g%)dt$@bj(cn4({VUPN8hh|q-K0`@}spzqS> zz;T&06kCc74c%p*zY*-g9PF9TmN{TNsH_uP@;jVomf8-#7jEJ|Fc;#{M<3Og_)~U$*g5i7 zjGY7r=sS!-M2?btG3!2-6=NAuXMLdmV-xTnupincH^|&!-c7Vk<-JrDyup5bW!ret zd(YmAAIIzdG~R}fX84zO+_$TofCpaSK*^PIfAGX~p^ZkEUkL}Kv)IG4&pt~&{0)}V zv4(2%A2~MsY5cF_)z2c9IRE@LHa1Ai$U<%&pK*nbGh1sKuQ>z4$os8ypsEL%59AN4 zyr4b8U*Nm7Z9ao9wc7OodxExcjbO~Ymv_DEotF2C+xo;~pD1*I`=FiRRgtG;oI)Ik z;=W?&1Keov!TiX>ZEP4H;3Y39-$hly8|*()**5&K7n3xWMBC7}@lDK+Q@a`V;zO~m z&#HLW*X!EgI-z~Kx0-#Z@PY4>w_&{KeEHmr@dl33R#9Uc-t(SEET4qmh5uk}EdPrf zZfF3tw-^Tg5zgm$d;O}4;oEPGUae)1Ko$YD?bF{#UDmhViACYe3G0v1fcS#%Ae{W(RbStqfi~bn%+`7FSy!!+KcM*$jGf2a82C(13ErQ0;z^dfA}+K%WeX2V zEpSb6%!3QzLo!!jjB>#}diH3CKiL1UiT{56`dRG27`S8azAs}cB^SW3&H+9%>@&6gSLj&N>E9GyIgNfze|NY<1 zH#qamv&63j7UzR)fj_zHwp_qYc)vG37~ZZ4?R-e@|9*UMfEo>f_vjS(-=-WQzR7?8 z_kYJFT5gazk}FrPw0og_uqkyNC^exvmSI|8x&SxC2iX8}fs6Dd>wr-PQVA&3vCEKwASuN;0MgonDPSi=g6Oa_OqWY z+NimLk4Qe%$B9o8{)=oL;Tmy=G1y;K#%0O9VSlj~#P6JsehJqZw?L<@*f>UBw|#YP z&@a&dvkTPl28=U*?6d4gm~P}_LfgnEaV^YWfxi*2aBswh`__IwPB4>jyxMYcP_L`%>JVIi`Z&z~4%uBrW z)>m7MiM_xMm@fbaggKn2_A#ueogcP8_>plAys4cN@F4pTW;>(<_L=9=h(8#|zEX2! zKlQ0k**us#l?Nba9Si=>yWaJ#bdK^_$DeS#+E)2t{E5IHztDU`?Nfh`aV_GGvN$Ik z|8e%ttv3B1>|61V{;$}4j>bP=|_@ucfQ<^gu34F@vLe%YrVLCKUTNZ7Ylm zfjKpH!g%5}zfBH;e89~&-(qtF@c9@QB_<3ThaZ5?gYGR`w$%E8X@GvO9HWm4voRg|@pOzm z4Im#B3mU*!7kb8AOZNkWYvus)23)A-AWCldXJ`a-L`?tpY&$O)>|6Xl!(Zb^j=yrB z(n#Y0TrfUVI8oS!QXhg7p%2tnz&_T|j7`}Kjx~mz8w{Rum2JX>(P{rz&`z!jq^gw)|EsO(QaRa>VJJi7u=L!Ayc;`3U-9?@%-y%NnA6sMA2z~$Pk7?oV2*(Gf4y_D zjsAmuOZ?Yg_Mdq~hCkRh3NcJ*0iS_4`EkeHw}S&-gSCH-?-2e1Ia23^`F0mg&r|Gj#(#UJcH(&WXy8Z+kk zE@BnhWUk?_F?*|9`A}dF7s5tFUGT!~L-4_TNIuJUqvS#rfBZ`44*6aB4n98ZL_FVa z!FDoEPrDHVo}}C`{sVbp`dn2z&;aK1U8p(9v@!7j=Q9q#1LH!q|A#i91(_$pyDcAt zeeeO@!0*E*oiBfcIn%K)E=+t&&KizZ$33xUJTrIdspNx>HC`H@;6RQo!q=>F!TY}F zAeawE{MSYN5BBSu`0u@UU(5e+|MYeGAJ`Z8>t1-q(@M4nt_fKS414EEO)F|#$bG-D z4}OG=Fir>$(*T{H+%5eFpB|kLt&Fye8aoQERqhUG6qBcje)fF76)(RPe! zp)bq_eCt~us+}MG=ealR&@H#zTpJUB3uxVn6)P-f#JR(lY}VwVA~)ss!E?vV0~$7L zMA~78^1bsF{K39u{Fmp4;0*j};?F!;+Q;?4H6Ye&8lhv11GzRGF+K=e^g#sBo z)}TR=i?TZFK^doJ`(XQZbX872IPT?Ay-&;GM+NrX6AJK)d^#J=cNi zdgubYz{Xk0T444f^uTK8j^SSL!#QAl$ozm4&JWjwDi_cI?C81Yo}1pF`F{9&)&5+? z72le+rR`&`7J0RY9(t&Hn5{FGh#lZ}$(^J2fyp6joFmCYL?2B_+P;7_i2k>W@7Mo zSLZ4?pxE8l5^t!v_5@EaK0#n$jV(6#dQKdiBx zYThZ%$3A#L-)B6En1&o>mB(ll&m)~7|AqODoGX0Gf&<{+-~f6+?r+MJ$@X`3nteNO zSLc7Xeg1=I$q!flID9~!v3DM*Ry-OyP~`#723Jd9?sg(HB69&d05>S&fv=+t;O+a| zhs^kA8xnd%Tc3UQ3iYv<*XDXe8&_-Q0?^0MQuLiZ$K3Af{EIlAoGf#=u@(3l=#A?@ z&STBNchz;$2lN?SJVEo1;p57ct4z!BCGbz1njhyNw?n*#&j|t0SbhYq&?i&Z~_-lP@JvYERMHoxQALssQ2XayH-r6MB#s${l zM&^mNSLg)$!%whv$KG_oI3R7%{@_E^uPnG=9Lf5ibvU?i;UeYwnNM}O>}Ng4-)w*0 zF+=`^oc~#8on>6WzQT>>f<7}of2n+dvov3XcN>s{UaaxxrOGKWhlFt^_ym5~ad4+! zch%=P2fVmf=e*>SOU=gMYcS5!^heR9haP^|o;_s@7`<^nGshc|b0}(f;GYq~`L;)1r_hp1{o@PW@b zrdjkp7Ck$JFSt^=j#f5ftSYY7ri%TD8?XZ_SFKFfTz!q6?RvcCcg1(W1mBV4@#XNt zR}TTqk|EI=4T*->mUN$o27i>h zHn>KF7L>k2g9pKh!hZ}N_;Kh#p#=?F0UzKGemY}4jPs$ZVA0irkLAyEoo^h#cHFJG zC0&gxV}tJ%X2fT_vjR<~kALSo-)ZTyU7Zs@o;lv+_tE?{Yu4Dh$&OGqIgT@>3vCPfr>e%=mb2;D+xYOs! zK@d|gCvEN8i%qNe>=!@x=Tzc*)Yu5PLGECY=CaZ6BG&Y{v*Z9=2)jTmh~G!w-)pb7 zF+bz|n|l8Xyx<){H4WfB62yYo6>Kr>jSqzOdM&(76R4dJ#*3Oh`2Nra=S-;?!3}JB z)weA7XFaIc4fDTkTQRrJf1>QbDrq{;*?#tOUC$T94uIojmtAf#A^q&yYhP)$qbu7@ zo)M1lo{xLpaF2~Ik<(!;hj@VkFBq31kA!WYzca3L@x^PcFJEx}1?KDDtUN#Se!Jq( z!?OEug*l4MRWIjKfji@2UWX1C2V@6`)tR?R-`_I-9k~XUVEc4S+xNdQCzNNwIX`_f zaIe;dZ3r&F6ZFBh!9VoDxlnLGzh|0Iu_55@#WlfsQQ8i}UdMQ>=~@wXV2%3q?TQD` z>2?b-HhA*<9kKUn<%i7{D`sQNwX21E9WmVl!j>EXxn<%GVnuAjtMrTs?+amU0>2U8 z5Ss*+_<4*mVQbKnb~ypgOFr}JzyJFp2T8sQ-34>%LI-TUviYczuyX~&BXE%5k4Y*T?-N-p`4tTX-gn=DO%rq5<+`~GM6 z#h5bZrjK%+g*aXYwQc)^9%Z@~{cUd_b@PVH*^b#lqP_luk^F(LlIrgGBN z-y#37{*CKRhsYh01rNlD;6@7%_zdjPguEX5P;jBN8wD?n1N47* z5_ZGiD?_e^`9j$C^~%qXcWZ|U^8(2QU!goK&yHSv@g?&0Z!O;8R>kVMT<2PNXH4WJ z8FTV+N3dt?+sD7n1{fFeJPFpt1;!kS%O~p@-+_Y$wZol#VED%_!}Z0MzyH9yfO)2j zc!06tdGplw7q|}4_uxZtqFm2*0dBP8fbDnO&0bXb0mjA)d9@a`XS zw2YtNhutkb#s)WYZD2}n20sqJVfA^dZLSdh9s8fD4m=xf;QMne_yzbL^m}4GbPn8$ zIS=x+Tn9=nuuUF-JU{;a!3P~|^Lyx@!mC>T)W81#Z`%I-mp*;^+W5jzNBO*FaJF~8 zDpwVlJ0~jJ@Ip9ZC!7N%SA4&J7N4Ub^X%AC8;l3R4bz8;R%n0KPQW7{n^|o0!Ov4% zfVLA~q0h}c5pyxf1u!Kyf$oom)G&Y}H zug!^2Z5qIM6Ma7K#}1JDXKapla__$T?(P2e2R!&w|Naa3xBdH1aE+L7lAaUC|G-xb z4$$W4K)eH(=lGlxQJ4B~oY{!XgU|*1NA?@eaE0w$+rE+yRjqJtWQ`Cvf(x9R+&%F$ zIThlun{K+%d_!V&o)eET0NyJ?UWjLOcs_`}NiK%D!+uoj^OwoiFb2Wg z)J2OHTKrpJ56)c_Y(CE;Ft4A#7rkfudHrC|-|TuW{{9mjU}^dLZ*YKji%gz8MSRq| zbAtomFMD7-$m{dxJ0}Wl5GG+WVqf7i7!QOu#~AK`J^LK{qOS14^HG66zN3!Kwu5uw zS232yoM74>Y_HUF!{m$5`ZunBquv?yfcBqnV{Xg?<9z|ER`LGlb(Y5?{;$r_emdOA z8KCp;)O=)cM_ z_z2YGec8|4)BE3azr}Re9O6rIle{mKbMxEiJ$=TomhKn*9~)52feCxy@6O|yZm^Gc zytlFW&)467ga>W^{_EyjY+>_Em~VnliVp^_xyQCVFipsMkojQz$eeILLRf1X-Ea-S ze`LEXp%(=&j0<&*sQL?GAL2Lo+aPYS`=R-~o26a*=Y3%F=U7hEN!tGXck)Bw6QXPMBhv!if0YByjm!h_gLj|R zI01(GP89bi+^)oLQrC*v2e7Z&ir5Z+((wk1x-G$P$e3r&fW5_=R{LjmJv#3q@fx4< z1ljNt^*$L2`37t{e+$br#4z`3!56h0MS;EgdSx9R(C1wboFDl6_|`nb$1_~a|Hh|Nt0w6DP3c;K7}ji9})?^~^P z_+iOdPmYj8Z}DexqZ6A9t^h{lh(!wv~Abfr%xYy ze=u{<@mt}4D+j~}^?NH>0}4(Q{D3#k33R03O7MXiAE8o5AFcDk{RqPfti=bzJlCcL z*a+LM)H#l{*aBN2j=&4);+fMfjA}ep|O0ZY%hl>vcPk z`I0rF>Q@FQ&;&1;BNgmT2R5;d{?ku*riA%h`1k`ATW`Ppj_vfGwx-Q#`xnB}TNm*a zl|QHyJP3QRU;q8mSlth?3v=h;x??3C$TteiYc;x1*o%xgwj#6uKCoVFYrVn+Uzhf? z&#?D(!yI4IIHKA(LhZ$TzgU+}xP5RQ*k@)Z-~t-qdJvj#nvgYs^+F>8clO14u4xNm zfA90k<;#B_K72&#t-t9T?N@En+{UyuZT>=9cGAT>sPb!-f&;8`AG_|lYvS+JPE@{- zyfyhv+B`5O2Zm3@`%&0u+R#Q9+*Y6s)snG?A1xfH+6LhX?p9dO1-x0$xHoIl0Jy;C zh3#&&;~O{?LY~!`3s0hIyMj zqsx2x8N=z(t4CLT9xl+Pv@LD?LSJ~Ubc0F@hvC4^JMWwZ4H{@R4qHcjOWZ?y8CKvd z>?zm>(*>~38c}G4`43&#kKhNKFfLHT8Tb-9i;gSu!ZPo;i zsriwi4Hf*0xHIdM*$C4N$KF2IXIyLegy4>C^D&zlmcuz@!UUT;v!C9t)P3vjo6>sP ziZ-L|{uY*PbrZ8x9#g4tfbHPHHrs5IXq(|fho=eh6Pe4-ctU7GXf)V^Ti6JztK0Yr z!4vk|XKlEk{q8sTXW>^^O?;6#;J!olE2_L;T|5Zw$KNN9V||?%UOZ;59CNb{95N*J z>9cp*LSrRyzwO#0w-IecoBgdVFVPJxS9wyUg$L}TZ8qP0^VC!0+JlE2VDp)oniwk zT#NPdY}a`=AHMtqy*pv#@R4cYfPs4Vy3fzx-nzQ)+$OXQZS-PTF40XsrSe;qmUamq zY^}dr(OdJ52dn>#(%&QFeI|#iPw}2x#+k4aJ_k)>b@IC-o)5eXTjPRor4FAlbHKF3 z_))<>bIJQZnhw^UqqDJkVNJZw`N`8w(|A13TaxqUnOkgGk3IHCTVyV80(b76HlQtD zj0;>}t@3FV+Mz8EHj^IEhLk7sa&P{kFi`o~xJt#yi#U;mFaA7&$`R9GrMgc9)m!Qe0euwsKP7OTlj2-{VwldZ_v}T0Tb4)D0UpO!@2~X~2L1 zsjtR2cH3>Y7QDGG-9uM}d*dFt*XH{dwChE`bXN<|E=yE4sC3niwf(^b_(0*E2fcdr zG+z=eK6uE%;>K{pZ`iP*#*?AKa+vr6XQ*SHZOY)mLoENk@4kIg&mKL~PCM>sza8gz z8k}p_m+ysp;@-H&&hpG!pr;PINac$vKT~O&OVIvidt1K@teQ30wJXizV*6QQ%{6kZ zTr=0sJ#>~oy#@BuPb^cpM};_YqslYpgN|+C$aA!hYuKp5HF0fRBiGtlp1&5rXBw~E0yh3z+hLE(JI*6bt>ys z9#uh)zoUXS2bRs6&p3u-`3~P*r^0XXoBTHC;9Q)Ob9a_b3v^nb(*m6q=(Iqm1v)Lz zX@O1)bXuU(0-YA4Qy{wZ1YgMmMde&M%(PxJ+{~R_GWoIA6|Uncm8p= zZj=0gjj^47U|nqIABfF-iN(+5AGC}0WBTxe8_VPE2RD@4b_?suZ974^X(y=syq%!9 zT8^8PQss2kMn9>3f2Z2%H8nA%4b{(e0nP2|$6P>TyLLIcpyqb%@^pc<%hLrmw`-TH z=boF}8|&xq-rU|$|9p$5+g?{cezRx0UH^J#tJwn2wmqB2Z>ay^)8e_Yeth@lc9T!d z?Is_a+f6<<`QF@a_Lr9J4b=;7)BkEWp#ECBVD;zP1xjFQ7brcbUC@=O-hs85)|D4v zdb6S2Ha*%{Zkt|JPS}U;&nNmrYjIZ`uz_ytG!GgVFE+5Q?K0ZnxnpfRW~9gezU?s5<~i;!8>-i$b+LEW#4mS!JjP3x zcES1Qct?KdbLy}Bw>Wj3bIKpPjDO&FHzKPs7_)=?KSp}hqtbbV_dcVsQ5d&57?^oP z%`X)Dn@wb7nsZLz9>E4eS5`N zR1Yn(NY>TJpRx!(BqyqWN}bk$!6_)45bG3tIeQJ(r@Y1b)8i>rqtrHX(4Tsb1+NK@ z&R*TBDI+v)+b6Oq)RG>^KcuSE*?9mW+cfF@O>>1S`{?MBy8~8rSij+SZ8O?o^pL*E zj6+u#335%|ThypMd&^u8xt&6Z0kff+J&(vmD;*~slA}}ak%-{cSw|Kts*3T%=d^f5 zT%^k2s4?QAg|8o1Je_*B5d(=GW=q*QE1j=CVlP!fhvXGa2pW2%oO^4Wf6v+#D(3|< zs#7T|gWW0bvP5-R_Gpc?PH1Ag>*eePeWm{PCbd;D3%lbYWlBb&sj^eBFJrcc>U|Wx>O4Y%vF(Q&x+~_1z%8S5}?cH!AGe z3UBEC-}QOhmLi|4NL$ UthP^z@jit)bXR-G*R9U_4@oN!P5=M^ literal 0 HcmV?d00001 diff --git a/windows/ptray/ptray.vcxproj b/windows/ptray/ptray.vcxproj new file mode 100644 index 000000000..efe1d2e48 --- /dev/null +++ b/windows/ptray/ptray.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {37C89E90-8C9E-4FFC-AAE7-B3695D5EB6F4} + Win32Proj + ptray + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + + + + + Use + Level3 + Disabled + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/windows/ptray/resource.h b/windows/ptray/resource.h new file mode 100644 index 0000000000000000000000000000000000000000..1f4b023431b96fb9c6edaf617bd5e9ac940c75c7 GIT binary patch literal 1788 zcmb7_QEw7K6ot>TiT_~}AB|Gbr24o58X`*xONo6VmV&`F#XwOT<6pOaXQreS*ab3K zX6EjlbI;zn=W_qAqKf`7Iy%!(4K>x}>4a5Bb+y>#`pbB(XZTi>DAQCU%{9}4XQEqd z18fT|^;OsG>UzmY^i5;k@XWE_GGAevVj1DJWH)9%!E(*&^;(2;u%h>+?(q4+X=B{s zHRtq-i{}>s$0&}Jz_>yDAuKOg*ZHmv*270FpzlI$fZA1GJ*8kfTP;>?B7EA5U)70< zk#o>eu)EBCQ2U@Z_hQCxGV+^3&RIbI0LODs56^-l`oslybJ3A?B^S>yK zRgT;WNUJ;_&-t{FvypQu!?)HhWw;&HoZl59yW$>eWBYWO#mMgqk$WJUaf>?s7-}y& zqBd%KIOp6|%44OJaol|Oit4cXR!U4@H`eda3#{u2YF(mh_lBRWt@kmiw%%uGI0s)CAqto;U@Hxnob#q^WN+P#jImrIicqFWqOs9ct5`3a@MZVYUo-K+5bIP M{4Y!%B0b&z2Q6jVQ2+n{ literal 0 HcmV?d00001 diff --git a/windows/ptray/targetver.h b/windows/ptray/targetver.h new file mode 100644 index 000000000..87c0086de --- /dev/null +++ b/windows/ptray/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include