#include "ep_weather_host.h" #include "ep_weather_provider_google_html.h" #include "ep_weather_provider_google_script.h" #include "ep_weather_error_html.h" RTL_OSVERSIONINFOW global_rovi; DWORD32 global_ubr; SYSTEMTIME stLastUpdate; HRESULT STDMETHODCALLTYPE epw_Weather_static_Stub(void* _this) { return S_OK; } ULONG STDMETHODCALLTYPE epw_Weather_static_AddRefRelease(void* _this) { return 1; } static DWORD epw_Weather_ReleaseBecauseClientDiedThread(EPWeather* _this) { Sleep(5000); while (_this->lpVtbl->Release(_this)); return 0; } static void epw_Weather_SetTextScaleFactorFromRegistry(EPWeather* _this, HKEY hKey, BOOL bRefresh) { DWORD dwTextScaleFactor = 100, dwSize = sizeof(DWORD); if (_this->SHRegGetValueFromHKCUHKLMFunc && _this->SHRegGetValueFromHKCUHKLMFunc(L"SOFTWARE\\Microsoft\\Accessibility", L"TextScaleFactor", SRRF_RT_REG_DWORD, NULL, &dwTextScaleFactor, (LPDWORD)(&dwSize)) != ERROR_SUCCESS) { dwTextScaleFactor = 100; } if (InterlockedExchange64(&_this->dwTextScaleFactor, dwTextScaleFactor) == dwTextScaleFactor) { bRefresh = FALSE; } if (hKey == HKEY_CURRENT_USER) { if (RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Accessibility", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WOW64_64KEY | KEY_WRITE, NULL, &_this->hKCUAccessibility, NULL) == ERROR_SUCCESS) { RegNotifyChangeKeyValue(_this->hKCUAccessibility, FALSE, REG_NOTIFY_CHANGE_LAST_SET, _this->hSignalOnAccessibilitySettingsChangedFromHKCU, TRUE); } } else if (hKey == HKEY_LOCAL_MACHINE) { if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Accessibility", 0, KEY_READ | KEY_WOW64_64KEY | KEY_WRITE, NULL, &_this->hKLMAccessibility)) { RegNotifyChangeKeyValue(_this->hKLMAccessibility, FALSE, REG_NOTIFY_CHANGE_LAST_SET, _this->hSignalOnAccessibilitySettingsChangedFromHKLM, TRUE); } } if (bRefresh) { _ep_Weather_StartResize(_this); } } HRESULT STDMETHODCALLTYPE INetworkListManagerEvents_QueryInterface(GenericObjectWithThis* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_INetworkListManagerEvents) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE INetworkListManagerEvents_ConnectivityChanged(GenericObjectWithThis* _this2, NLM_CONNECTIVITY newConnectivity) { EPWeather* _this = _this2->_this; // GetWindowLongPtrW(FindWindowW(_T(EPW_WEATHER_CLASSNAME), NULL), GWLP_USERDATA); if (_this) { if ((newConnectivity & (NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET)) != 0) { printf("[Network Events for 0x%p] Internet connection status is: Available.\n", _this); LONG64 dwUpdateSchedule = InterlockedAdd64(&_this->dwUpdateSchedule, 0); SetTimer(_this->hWnd, EP_WEATHER_TIMER_REQUEST_REFRESH, EP_WEATHER_TIMER_REQUEST_REFRESH_DELAY, NULL); //PostMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); SetTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH, dwUpdateSchedule, NULL); printf("[Network Events for 0x%p] Reinstalled refresh timer.\n", _this); } else { printf("[Network Events for 0x%p] Internet connection status is: Offline.\n", _this); KillTimer(_this->hWnd, EP_WEATHER_TIMER_REQUEST_REFRESH); KillTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH); printf("[Network Events for 0x%p] Killed refresh timer.\n", _this); } } return S_OK; } GenericObjectWithThis* GenericObjectWithThis_MakeAndInitialize(IUnknownVtbl* vtbl, EPWeather* _this, const LPWSTR pName) { GenericObjectWithThis* pObj = malloc(sizeof(GenericObjectWithThis)); if (pObj) { ULONG cnt = InterlockedIncrement64(&(_this->cbGenericObject)); pObj->lpVtbl = vtbl; pObj->cbCount = 1; pObj->pInstance = pObj; pObj->_this = _this; pObj->pName = pName; wprintf(L"[] {%d} Making object { name: \"%s\", _this: 0x%p }\n", cnt, pName, _this); return pObj; } return NULL; } ULONG STDMETHODCALLTYPE GenericObjectWithThis_AddRef(GenericObjectWithThis* _this) { ULONG cnt = InterlockedIncrement64(&(_this->_this->cbGenericObject)); ULONG value = InterlockedIncrement64(&(_this->cbCount)); wprintf(L"[] {%d} AddRef, new value = %d on { name: \"%s\", _this: 0x%p }\n", cnt, value, _this->pName, _this->_this); return value; } ULONG STDMETHODCALLTYPE GenericObjectWithThis_Release(GenericObjectWithThis* _this) { ULONG cnt = InterlockedDecrement64(&(_this->_this->cbGenericObject)); ULONG value = InterlockedDecrement64(&(_this->cbCount)); if (value == 0) { wprintf(L"[] {%d} Release with free, new value = %d on { name: \"%s\", _this: 0x%p }\n", cnt, value, _this->pName, _this->_this); free(_this->pInstance); return 0; } wprintf(L"[] {%d} Release, new value = %d on { name: \"%s\", _this: 0x%p }\n", cnt, value, _this->pName, _this->_this); return value; } HRESULT STDMETHODCALLTYPE ICoreWebView2EnvironmentOptions_QueryInterface(IUnknown* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_ICoreWebView2EnvironmentOptions) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface(GenericObjectWithThis* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_QueryInterface(GenericObjectWithThis* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE ICoreWebView2NavigationStartingEventHandler_QueryInterface(GenericObjectWithThis* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_ICoreWebView2NavigationStartingEventHandler) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE ICoreWebView2NavigationCompletedEventHandler_QueryInterface(GenericObjectWithThis* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_ICoreWebView2NavigationCompletedEventHandler) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE ICoreWebView2PermissionRequestedEventHandler_QueryInterface(GenericObjectWithThis* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_ICoreWebView2PermissionRequestedEventHandler) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_QueryInterface(GenericObjectWithThis* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_ICoreWebView2CallDevToolsProtocolMethodCompletedHandler) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE ICoreWebView2ExecuteScriptCompletedHandler_QueryInterface(GenericObjectWithThis* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_ICoreWebView2ExecuteScriptCompletedHandler) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE ICoreWebView2_get_AdditionalBrowserArguments(ICoreWebView2EnvironmentOptions* _this, LPWSTR* value) { *value = CoTaskMemAlloc(82 * sizeof(WCHAR)); if (*value) { wcscpy_s(*value, 82, L"--disable-site-isolation-trials --disable-web-security --allow-insecure-localhost"); } return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_get_Language(ICoreWebView2EnvironmentOptions* _this, LPWSTR* value) { *value = CoTaskMemAlloc(6 * sizeof(WCHAR)); if (*value) { wcscpy_s(*value, 6, L"en-US"); } return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_get_TargetCompatibleBrowserVersion(ICoreWebView2EnvironmentOptions* _this, LPWSTR* value) { *value = CoTaskMemAlloc(13 * sizeof(WCHAR)); if (*value) { wcscpy_s(*value, 13, L"97.0.1072.69"); } return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_get_AllowSingleSignOnUsingOSPrimaryAccount(ICoreWebView2EnvironmentOptions* _this, BOOL* allow) { *allow = TRUE; return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_CreateCoreWebView2EnvironmentCompleted(GenericObjectWithThis* _this, HRESULT hr, ICoreWebView2Environment* pCoreWebView2Environemnt) { GenericObjectWithThis* pCoreWebView2CreateCoreWebView2ControllerCompletedHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl, _this->_this, L"pCoreWebView2CreateCoreWebView2ControllerCompletedHandler"); if (!pCoreWebView2CreateCoreWebView2ControllerCompletedHandler) return E_FAIL; HRESULT _hr = pCoreWebView2Environemnt->lpVtbl->CreateCoreWebView2Controller(pCoreWebView2Environemnt, _this->_this->hWnd, pCoreWebView2CreateCoreWebView2ControllerCompletedHandler); pCoreWebView2CreateCoreWebView2ControllerCompletedHandler->lpVtbl->Release(pCoreWebView2CreateCoreWebView2ControllerCompletedHandler); return _hr; } HRESULT STDMETHODCALLTYPE _epw_Weather_NavigateToError(EPWeather* _this) { _ep_Weather_ReboundBrowser(_this, TRUE); InterlockedExchange64(&_this->bIsNavigatingToError, TRUE); UINT dpi = GetDpiForWindow(_this->hWnd); DWORD dwTextScaleFactor = epw_Weather_GetTextScaleFactor(_this); DWORD dwZoomFactor = epw_Weather_GetZoomFactor(_this); int ch = MulDiv(MulDiv(MulDiv(EP_WEATHER_HEIGHT_ERROR, dpi, 96), dwTextScaleFactor, 100), dwZoomFactor, 100); RECT rc; GetClientRect(_this->hWnd, &rc); int w = MulDiv(MulDiv(MulDiv(EP_WEATHER_WIDTH, GetDpiForWindow(_this->hWnd), 96), dwTextScaleFactor, 100), dwZoomFactor, 100); if ((rc.bottom - rc.top != ch) || (rc.right - rc.left != w)) { RECT rcAdj; SetRect(&rcAdj, 0, 0, w, ch); AdjustWindowRectExForDpi(&rcAdj, epw_Weather_GetStyle(_this) & ~WS_OVERLAPPED, epw_Weather_HasMenuBar(_this), epw_Weather_GetExtendedStyle(_this), dpi); SetWindowPos(_this->hWnd, NULL, 0, 0, rcAdj.right - rcAdj.left, rcAdj.bottom - rcAdj.top, SWP_NOMOVE | SWP_NOSENDCHANGING); HWND hNotifyWnd = InterlockedAdd64(&_this->hNotifyWnd, 0); if (hNotifyWnd) { InvalidateRect(hNotifyWnd, NULL, TRUE); } } if (_this->pCoreWebView2) { LPWSTR wszPageTitle = NULL; if (SUCCEEDED(_this->pCoreWebView2->lpVtbl->get_DocumentTitle(_this->pCoreWebView2, &wszPageTitle))) { BOOL bIsOnErrorPage = !_wcsicmp(wszPageTitle, _T(CLSID_EPWeather_TEXT) L"_ErrorPage"); CoTaskMemFree(wszPageTitle); if (!bIsOnErrorPage) return _this->pCoreWebView2->lpVtbl->NavigateToString(_this->pCoreWebView2, ep_weather_error_html); else { printf("[Browser] Already on the error page.\n"); return S_OK; } } } return E_FAIL; } HRESULT STDMETHODCALLTYPE _epw_Weather_NavigateToProvider(EPWeather* _this) { _ep_Weather_ReboundBrowser(_this, FALSE); HRESULT hr = S_OK; LONG64 dwProvider = InterlockedAdd64(&_this->dwProvider, 0); if (dwProvider == EP_WEATHER_PROVIDER_TEST) { } else if (dwProvider == EP_WEATHER_PROVIDER_GOOGLE) { //hr = _this->pCoreWebView2->lpVtbl->Navigate(_this->pCoreWebView2, L"https://google.com"); LPWSTR wszScriptData = malloc(sizeof(WCHAR) * EP_WEATHER_PROVIDER_GOOGLE_HTML_LEN); if (wszScriptData) { swprintf_s(wszScriptData, EP_WEATHER_PROVIDER_GOOGLE_HTML_LEN, L"https://www.google.com/search?hl=%s&q=weather%s%s", _this->wszLanguage, _this->wszTerm[0] ? L" " : L"", _this->wszTerm); if (_this->pCoreWebView2) { hr = _this->pCoreWebView2->lpVtbl->Navigate(_this->pCoreWebView2, wszScriptData); } else { hr = E_FAIL; } if (FAILED(hr)) { InterlockedExchange64(&_this->bBrowserBusy, FALSE); } free(wszScriptData); } else { hr = E_OUTOFMEMORY; } } return hr; } HRESULT STDMETHODCALLTYPE _epw_Weather_ExecuteDataScript(EPWeather* _this) { HRESULT hr = S_OK; LONG64 dwProvider = InterlockedAdd64(&_this->dwProvider, 0); if (dwProvider == EP_WEATHER_PROVIDER_TEST) { } else if (dwProvider == EP_WEATHER_PROVIDER_GOOGLE) { LPWSTR wszScriptData = malloc(sizeof(WCHAR) * EP_WEATHER_PROVIDER_GOOGLE_SCRIPT_LEN); if (wszScriptData) { LONG64 dwIconPack = InterlockedAdd(&_this->dwIconPack, 0); if (dwIconPack == EP_WEATHER_ICONPACK_MICROSOFT) { swprintf_s(wszScriptData, EP_WEATHER_PROVIDER_GOOGLE_SCRIPT_LEN, L"%s%s%s%s%s%s", ep_weather_provider_google_script00, ep_weather_provider_google_script010, ep_weather_provider_google_script011, ep_weather_provider_google_script020, ep_weather_provider_google_script021, ep_weather_provider_google_script03); } else if (dwIconPack == EP_WEATHER_ICONPACK_GOOGLE) { swprintf_s(wszScriptData, EP_WEATHER_PROVIDER_GOOGLE_SCRIPT_LEN, ep_weather_provider_google_script10); } //wprintf(L"%s\n", _this->wszScriptData); if (_this->pCoreWebView2) { GenericObjectWithThis* pCoreWebView2ExecuteScriptCompletedHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2ExecuteScriptCompletedHandlerVtbl, _this, L"pCoreWebView2ExecuteScriptCompletedHandler"); if (!pCoreWebView2ExecuteScriptCompletedHandler) hr = E_FAIL; else hr = _this->pCoreWebView2->lpVtbl->ExecuteScript(_this->pCoreWebView2, wszScriptData, pCoreWebView2ExecuteScriptCompletedHandler); } else { hr = E_FAIL; } if (FAILED(hr)) { InterlockedExchange64(&_this->bBrowserBusy, FALSE); } free(wszScriptData); } else { hr = E_OUTOFMEMORY; } } return hr; } HRESULT STDMETHODCALLTYPE _ep_Weather_StartResize(EPWeather* _this) { _this->cntResizeWindow = 0; SetTimer(_this->hWnd, EP_WEATHER_TIMER_RESIZE_WINDOW, EP_WEATHER_TIMER_RESIZE_WINDOW_DELAY, NULL); return S_OK; } HRESULT STDMETHODCALLTYPE _ep_Weather_ReboundBrowser(EPWeather* _this, LONG64 dwType) { UINT dpi = GetDpiForWindow(_this->hWnd); RECT bounds; DWORD dwDevMode = InterlockedAdd64(&_this->dwDevMode, 0); if (dwType || dwDevMode) { GetClientRect(_this->hWnd, &bounds); } else { DWORD dwTextScaleFactor = epw_Weather_GetTextScaleFactor(_this); DWORD dwZoomFactor = epw_Weather_GetZoomFactor(_this); bounds.left = 0 - MulDiv(MulDiv(MulDiv(181, dpi, 96), dwTextScaleFactor, 100), dwZoomFactor, 100); bounds.top = 0 - MulDiv(MulDiv(MulDiv(178, dpi, 96), dwTextScaleFactor, 100), dwZoomFactor, 100); bounds.right = MulDiv(MulDiv(MulDiv((!InterlockedAdd64(&_this->dwTextDir, 0) ? 1333 : 705), dpi, 96), dwTextScaleFactor, 100), dwZoomFactor, 100);// 5560; bounds.bottom = MulDiv(MulDiv(MulDiv(600, dpi, 96), dwTextScaleFactor, 100), dwZoomFactor, 100);// 15600; } if (_this->pCoreWebView2Controller) { _this->pCoreWebView2Controller->lpVtbl->put_Bounds(_this->pCoreWebView2Controller, bounds); } return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_CreateCoreWebView2ControllerCompleted(GenericObjectWithThis* _this2, HRESULT hr, ICoreWebView2Controller* pCoreWebView2Controller) { EPWeather* _this = _this2->_this; // GetWindowLongPtrW(FindWindowW(_T(EPW_WEATHER_CLASSNAME), NULL), GWLP_USERDATA); if (!_this->pCoreWebView2Controller) { _this->pCoreWebView2Controller = pCoreWebView2Controller; _this->pCoreWebView2Controller->lpVtbl->get_CoreWebView2(_this->pCoreWebView2Controller, &_this->pCoreWebView2); _this->pCoreWebView2Controller->lpVtbl->AddRef(_this->pCoreWebView2Controller); _this->pCoreWebView2Controller->lpVtbl->put_ZoomFactor(_this->pCoreWebView2Controller, InterlockedAdd64(&_this->dwZoomFactor, 0) / 100.0); } _ep_Weather_ReboundBrowser(_this, FALSE); ICoreWebView2Controller2* pCoreWebView2Controller2 = NULL; _this->pCoreWebView2Controller->lpVtbl->QueryInterface(_this->pCoreWebView2Controller, &IID_ICoreWebView2Controller2, &pCoreWebView2Controller2); if (pCoreWebView2Controller2) { COREWEBVIEW2_COLOR transparent; transparent.A = 0; transparent.R = 0; transparent.G = 0; transparent.B = 0; pCoreWebView2Controller2->lpVtbl->put_DefaultBackgroundColor(pCoreWebView2Controller2, transparent); pCoreWebView2Controller2->lpVtbl->Release(pCoreWebView2Controller2); } ICoreWebView2Settings* pCoreWebView2Settings = NULL; _this->pCoreWebView2->lpVtbl->get_Settings(_this->pCoreWebView2, &pCoreWebView2Settings); if (pCoreWebView2Settings) { ICoreWebView2Settings6* pCoreWebView2Settings6 = NULL; pCoreWebView2Settings->lpVtbl->QueryInterface(pCoreWebView2Settings, &IID_ICoreWebView2Settings6, &pCoreWebView2Settings6); if (pCoreWebView2Settings6) { DWORD dwDevMode = InterlockedAdd64(&_this->dwDevMode, 0); pCoreWebView2Settings6->lpVtbl->put_AreDevToolsEnabled(pCoreWebView2Settings6, dwDevMode); pCoreWebView2Settings6->lpVtbl->put_AreDefaultContextMenusEnabled(pCoreWebView2Settings6, dwDevMode); pCoreWebView2Settings6->lpVtbl->put_IsStatusBarEnabled(pCoreWebView2Settings6, FALSE); pCoreWebView2Settings6->lpVtbl->put_IsZoomControlEnabled(pCoreWebView2Settings6, FALSE); pCoreWebView2Settings6->lpVtbl->put_IsGeneralAutofillEnabled(pCoreWebView2Settings6, FALSE); pCoreWebView2Settings6->lpVtbl->put_IsPasswordAutosaveEnabled(pCoreWebView2Settings6, FALSE); pCoreWebView2Settings6->lpVtbl->put_IsPinchZoomEnabled(pCoreWebView2Settings6, FALSE); pCoreWebView2Settings6->lpVtbl->put_IsSwipeNavigationEnabled(pCoreWebView2Settings6, FALSE); pCoreWebView2Settings6->lpVtbl->put_AreBrowserAcceleratorKeysEnabled(pCoreWebView2Settings6, dwDevMode); pCoreWebView2Settings6->lpVtbl->put_AreDefaultScriptDialogsEnabled(pCoreWebView2Settings6, dwDevMode); pCoreWebView2Settings6->lpVtbl->Release(pCoreWebView2Settings6); } pCoreWebView2Settings->lpVtbl->Release(pCoreWebView2Settings); } LONG64 dwDarkMode = InterlockedAdd64(&_this->g_darkModeEnabled, 0); epw_Weather_SetDarkMode(_this, dwDarkMode, FALSE); _this->pCoreWebView2NavigationStartingEventHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2NavigationStartingEventHandlerVtbl, _this, L"pCoreWebView2NavigationStartingEventHandler"); if (_this->pCoreWebView2NavigationStartingEventHandler) _this->pCoreWebView2->lpVtbl->add_NavigationStarting(_this->pCoreWebView2, _this->pCoreWebView2NavigationStartingEventHandler, &_this->tkOnNavigationStarting); _this->pCoreWebView2NavigationCompletedEventHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2NavigationCompletedEventHandlerVtbl, _this, L"pCoreWebView2NavigationCompletedEventHandler"); if (_this->pCoreWebView2NavigationCompletedEventHandler) _this->pCoreWebView2->lpVtbl->add_NavigationCompleted(_this->pCoreWebView2, _this->pCoreWebView2NavigationCompletedEventHandler, &_this->tkOnNavigationCompleted); _this->pCoreWebView2PermissionRequestedEventHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2PermissionRequestedEventHandlerVtbl, _this, L"pCoreWebView2PermissionRequestedEventHandler"); if (_this->pCoreWebView2PermissionRequestedEventHandler) _this->pCoreWebView2->lpVtbl->add_PermissionRequested(_this->pCoreWebView2, _this->pCoreWebView2PermissionRequestedEventHandler, &_this->tkOnPermissionRequested); _epw_Weather_NavigateToProvider(_this); return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_CallDevToolsProtocolMethodCompleted(GenericObjectWithThis* _this, HRESULT errorCode, LPCWSTR returnObjectAsJson) { EPWeather* EPWeather_Instance = _this->_this; if (EPWeather_Instance && !wcscmp(_this->pName, L"pCoreWebView2CallDevToolsProtocolMethodCompletedHandler_WithRefresh")) { wprintf(L"[CallDevToolsProtocolMethodCompleted] 0x%x [[ %s ]]\n", errorCode, returnObjectAsJson); PostMessageW(EPWeather_Instance->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); LPWSTR uri = NULL; if (EPWeather_Instance->pCoreWebView2) { if (SUCCEEDED(EPWeather_Instance->pCoreWebView2->lpVtbl->get_Source(EPWeather_Instance->pCoreWebView2, &uri))) { if (wcscmp(L"about:blank", uri ? uri : L"")) { SetTimer(EPWeather_Instance->hWnd, EP_WEATHER_TIMER_REQUEST_REFRESH, EP_WEATHER_TIMER_REQUEST_REFRESH_DELAY, NULL); } CoTaskMemFree(uri); } } } _this->lpVtbl->Release(_this); return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_NavigationStarting(GenericObjectWithThis* _this2, ICoreWebView2* pCoreWebView2, ICoreWebView2NavigationStartingEventArgs* pCoreWebView2NavigationStartingEventArgs) { EPWeather* _this = _this2->_this; // GetWindowLongPtrW(FindWindowW(_T(EPW_WEATHER_CLASSNAME), NULL), GWLP_USERDATA); LPWSTR wszUri = NULL; pCoreWebView2NavigationStartingEventArgs->lpVtbl->get_Uri(pCoreWebView2NavigationStartingEventArgs, &wszUri); if (wszUri) { if (!_wcsicmp(wszUri, L"epweather://refresh")) { pCoreWebView2NavigationStartingEventArgs->lpVtbl->put_Cancel(pCoreWebView2NavigationStartingEventArgs, TRUE); PostMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); } CoTaskMemFree(wszUri); } return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_NavigationCompleted(GenericObjectWithThis* _this2, ICoreWebView2* pCoreWebView2, ICoreWebView2NavigationCompletedEventArgs* pCoreWebView2NavigationCompletedEventArgs) { COREWEBVIEW2_WEB_ERROR_STATUS dwStatus = COREWEBVIEW2_WEB_ERROR_STATUS_UNKNOWN; pCoreWebView2NavigationCompletedEventArgs->lpVtbl->get_WebErrorStatus(pCoreWebView2NavigationCompletedEventArgs, &dwStatus); if (dwStatus == COREWEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED) return S_OK; EPWeather* _this = _this2->_this; // GetWindowLongPtrW(FindWindowW(_T(EPW_WEATHER_CLASSNAME), NULL), GWLP_USERDATA); BOOL bIsSuccess = FALSE; pCoreWebView2NavigationCompletedEventArgs->lpVtbl->get_IsSuccess(pCoreWebView2NavigationCompletedEventArgs, &bIsSuccess); if (bIsSuccess) { BOOL bIsNavigatingToError = InterlockedAdd64(&_this->bIsNavigatingToError, 0); if (bIsNavigatingToError) { InterlockedExchange64(&_this->bIsNavigatingToError, FALSE); InterlockedExchange64(&_this->bBrowserBusy, FALSE); } else { //_epw_Weather_ExecuteDataScript(_this); SetTimer(_this->hWnd, EP_WEATHER_TIMER_EXECUTEDATASCRIPT, EP_WEATHER_TIMER_EXECUTEDATASCRIPT_DELAY, NULL); } } else { printf("[Browser] Navigation completed with error, showing error page.\n"); _epw_Weather_NavigateToError(_this); } _this->pCoreWebView2Controller->lpVtbl->put_IsVisible(_this->pCoreWebView2Controller, FALSE); _this->pCoreWebView2Controller->lpVtbl->put_IsVisible(_this->pCoreWebView2Controller, TRUE); return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_ExecuteScriptCompleted(GenericObjectWithThis* _this2, HRESULT hr, LPCWSTR pResultObjectAsJson) { EPWeather* _this = _this2->_this; // GetWindowLongPtrW(FindWindowW(_T(EPW_WEATHER_CLASSNAME), NULL), GWLP_USERDATA); if (_this) { BOOL bOk = FALSE; LONG64 dwProvider = InterlockedAdd64(&_this->dwProvider, 0); if (dwProvider == EP_WEATHER_PROVIDER_GOOGLE) { if (!_wcsicmp(pResultObjectAsJson, L"\"run_part_2\"")) { //_this->pCoreWebView2->lpVtbl->OpenDevToolsWindow(_this->pCoreWebView2); //printf("running part 2\n"); //LONG64 bEnabled, dwDarkMode; //dwDarkMode = InterlockedAdd64(&_this->g_darkModeEnabled, 0); //epw_Weather_IsDarkMode(_this, dwDarkMode, &bEnabled); //swprintf_s(_this->wszScriptData, EP_WEATHER_PROVIDER_GOOGLE_SCRIPT_LEN, ep_weather_provider_google_script2, bEnabled ? 1 : 0); GenericObjectWithThis* pCoreWebView2ExecuteScriptCompletedHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2ExecuteScriptCompletedHandlerVtbl, _this, L"pCoreWebView2ExecuteScriptCompletedHandler"); if (pCoreWebView2ExecuteScriptCompletedHandler) _this->pCoreWebView2->lpVtbl->ExecuteScript(_this->pCoreWebView2, ep_weather_provider_google_script2, pCoreWebView2ExecuteScriptCompletedHandler); bOk = TRUE; } else if (!_wcsicmp(pResultObjectAsJson, L"\"run_part_0\"")) { LONG64 dwTemperatureUnit = InterlockedAdd64(&_this->dwTemperatureUnit, 0); LONG64 cbx = InterlockedAdd64(&_this->cbx, 0); LPWSTR wszScriptData = malloc(sizeof(WCHAR) * EP_WEATHER_PROVIDER_GOOGLE_SCRIPT_LEN); if (wszScriptData) { swprintf_s(wszScriptData, EP_WEATHER_PROVIDER_GOOGLE_SCRIPT_LEN, ep_weather_provider_google_script, dwTemperatureUnit == EP_WEATHER_TUNIT_FAHRENHEIT ? L'F' : L'C', cbx, cbx); GenericObjectWithThis* pCoreWebView2ExecuteScriptCompletedHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2ExecuteScriptCompletedHandlerVtbl, _this, L"pCoreWebView2ExecuteScriptCompletedHandler"); if (pCoreWebView2ExecuteScriptCompletedHandler) _this->pCoreWebView2->lpVtbl->ExecuteScript(_this->pCoreWebView2, wszScriptData, pCoreWebView2ExecuteScriptCompletedHandler); free(wszScriptData); } bOk = TRUE; } else if (!_wcsicmp(pResultObjectAsJson, L"\"run_part_1\"")) { printf("consent granted\n"); PostMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); SetTimer(_this->hWnd, EP_WEATHER_TIMER_REQUEST_REFRESH, EP_WEATHER_TIMER_REQUEST_REFRESH_DELAY * 5, NULL); _this2->lpVtbl->Release(_this2); return S_OK; } else { //wprintf(L"%s\n", pResultObjectAsJson); epw_Weather_LockData(_this); WCHAR* wszTextDir = pResultObjectAsJson + 1; if (wszTextDir) { WCHAR* wszHeight = wcschr(wszTextDir, L'#'); if (wszHeight) { wszHeight[0] = 0; wszHeight++; InterlockedExchange64(&_this->dwTextDir, wcsstr(wszTextDir, L"rtl")); WCHAR* wszTemperature = wcschr(wszHeight, L'#'); if (wszTemperature) { wszTemperature[0] = 0; wszTemperature++; WCHAR* wszUnit = wcschr(wszTemperature, L'#'); if (wszUnit) { wszUnit[0] = 0; wszUnit++; WCHAR* wszCondition = wcschr(wszUnit, L'#'); if (wszCondition) { wszCondition[0] = 0; wszCondition++; WCHAR* wszLocation = wcschr(wszCondition, L'#'); if (wszLocation) { wszLocation[0] = 0; wszLocation++; WCHAR* pImage = wcschr(wszLocation, L'#'); if (pImage) { pImage[0] = 0; pImage++; WCHAR* pTerm = wcschr(pImage, L'"'); if (pTerm) { pTerm[0] = 0; if (_this->wszTemperature) { free(_this->wszTemperature); } if (_this->wszUnit) { free(_this->wszUnit); } if (_this->wszCondition) { free(_this->wszCondition); } if (_this->pImage) { free(_this->pImage); } if (_this->wszLocation) { free(_this->wszLocation); } _this->cbTemperature = (wcslen(wszTemperature) + 1) * sizeof(WCHAR); _this->wszTemperature = malloc(_this->cbTemperature); _this->cbUnit = (wcslen(wszUnit) + 1) * sizeof(WCHAR); _this->wszUnit = malloc(_this->cbUnit); _this->cbCondition = (wcslen(wszCondition) + 1) * sizeof(WCHAR); _this->wszCondition = malloc(_this->cbCondition); _this->cbImage = wcslen(pImage) / 2; _this->pImage = malloc(_this->cbImage); _this->cbLocation = (wcslen(wszLocation) + 1) * sizeof(WCHAR); _this->wszLocation = malloc(_this->cbLocation); if (_this->wszTemperature && _this->wszUnit && _this->wszCondition && _this->pImage && _this->wszLocation) { wcscpy_s(_this->wszTemperature, _this->cbTemperature / 2, wszTemperature); wcscpy_s(_this->wszUnit, _this->cbUnit / 2, wszUnit); wcscpy_s(_this->wszCondition, _this->cbCondition / 2, wszCondition); wcscpy_s(_this->wszLocation, _this->cbLocation / 2, wszLocation); for (unsigned int i = 0; i < _this->cbImage * 2; i = i + 2) { WCHAR tmp[3]; tmp[0] = pImage[i]; tmp[1] = pImage[i + 1]; tmp[2] = 0; _this->pImage[i / 2] = wcstol(tmp, NULL, 16); } bOk = TRUE; } int h = _wtoi(wszHeight); int ch = MulDiv(h, EP_WEATHER_HEIGHT, 367); UINT dpi = GetDpiForWindow(_this->hWnd); DWORD dwTextScaleFactor = epw_Weather_GetTextScaleFactor(_this); DWORD dwZoomFactor = epw_Weather_GetZoomFactor(_this); ch = MulDiv(MulDiv(MulDiv(ch, dpi, 96), dwTextScaleFactor, 100), dwZoomFactor, 100); RECT rc; GetClientRect(_this->hWnd, &rc); int w = MulDiv(MulDiv(MulDiv(EP_WEATHER_WIDTH, GetDpiForWindow(_this->hWnd), 96), dwTextScaleFactor, 100), dwZoomFactor, 100); if ((rc.bottom - rc.top != ch) || (rc.right - rc.left != w)) { RECT rcAdj; SetRect(&rcAdj, 0, 0, w, ch); AdjustWindowRectExForDpi(&rcAdj, epw_Weather_GetStyle(_this) & ~WS_OVERLAPPED, epw_Weather_HasMenuBar(_this), epw_Weather_GetExtendedStyle(_this), dpi); SetWindowPos(_this->hWnd, NULL, 0, 0, rcAdj.right - rcAdj.left, rcAdj.bottom - rcAdj.top, SWP_NOMOVE | SWP_NOSENDCHANGING); _ep_Weather_ReboundBrowser(_this, FALSE); HWND hNotifyWnd = InterlockedAdd64(&_this->hNotifyWnd, 0); if (hNotifyWnd) { InvalidateRect(hNotifyWnd, NULL, TRUE); } } } } } } } } } } epw_Weather_UnlockData(_this); } } if (!bOk) { printf("[General] Navigating to error page.\n"); _epw_Weather_NavigateToError(_this); } else { GetLocalTime(&stLastUpdate); HWND hGUI = FindWindowW(L"ExplorerPatcher_GUI_" _T(EP_CLSID), NULL); if (hGUI) InvalidateRect(hGUI, NULL, TRUE); InterlockedExchange64(&_this->bBrowserBusy, FALSE); printf("[General] Fetched data, requesting redraw.\n"); SetTimer(_this->hWnd, EP_WEATHER_TIMER_REQUEST_REPAINT, EP_WEATHER_TIMER_REQUEST_REPAINT_DELAY, NULL); } } _this2->lpVtbl->Release(_this2); return S_OK; } HRESULT STDMETHODCALLTYPE ICoreWebView2_PermissionRequested(GenericObjectWithThis* _this2, ICoreWebView2* pCoreWebView2, ICoreWebView2PermissionRequestedEventArgs* pCoreWebView2PermissionRequestedEventArgs) { COREWEBVIEW2_PERMISSION_KIND kind; pCoreWebView2PermissionRequestedEventArgs->lpVtbl->get_PermissionKind(pCoreWebView2PermissionRequestedEventArgs, &kind); if (kind == COREWEBVIEW2_PERMISSION_KIND_GEOLOCATION) { DWORD r = InterlockedAdd64(&_this2->_this->dwGeolocationMode, 0); printf("[Permissions] Geolocation permission request: %d\n", r); pCoreWebView2PermissionRequestedEventArgs->lpVtbl->put_State(pCoreWebView2PermissionRequestedEventArgs, r ? COREWEBVIEW2_PERMISSION_STATE_ALLOW : COREWEBVIEW2_PERMISSION_STATE_DENY); } return S_OK; } ULONG STDMETHODCALLTYPE epw_Weather_AddRef(EPWeather* _this) { ULONG value = InterlockedIncrement64(&(_this->cbCount)); printf("[General] AddRef: %d\n", value); return value; } ULONG STDMETHODCALLTYPE epw_Weather_Release(EPWeather* _this) { ULONG value = InterlockedDecrement64(&(_this->cbCount)); printf("[General] Release: %d\n", value); if (value == 0) { if (_this->hMainThread) { if (_this->hSignalExitMainThread) { SetEvent(_this->hSignalExitMainThread); printf("[General] Waiting for main thread to exit.\n"); WaitForSingleObject(_this->hMainThread, INFINITE); } CloseHandle(_this->hMainThread); if (_this->hSignalExitMainThread) { CloseHandle(_this->hSignalExitMainThread); } } if (_this->hInitializeEvent) { CloseHandle(_this->hInitializeEvent); } if (_this->hMutexData) { CloseHandle(_this->hMutexData); } if (_this->hUxtheme) { FreeLibrary(_this->hUxtheme); } if (_this->hShlwapi) { FreeLibrary(_this->hShlwapi); } if (_this->hKCUAccessibility) { RegCloseKey(_this->hKCUAccessibility); } if (_this->hKLMAccessibility) { RegCloseKey(_this->hKLMAccessibility); } if (_this->hSignalOnAccessibilitySettingsChangedFromHKCU) { CloseHandle(_this->hSignalOnAccessibilitySettingsChangedFromHKCU); } if (_this->hSignalOnAccessibilitySettingsChangedFromHKLM) { CloseHandle(_this->hSignalOnAccessibilitySettingsChangedFromHKLM); } if (_this->hSignalKillSwitch) { CloseHandle(_this->hSignalKillSwitch); } FREE(_this); LONG dwOutstandingObjects = InterlockedDecrement(&epw_OutstandingObjects); LONG dwOutstandingLocks = InterlockedAdd(&epw_LockCount, 0); if (!dwOutstandingObjects && !dwOutstandingLocks) { } printf("[General] Outstanding objects: %d, outstanding locks: %d\n", dwOutstandingObjects, dwOutstandingLocks); #if defined(DEBUG) | defined(_DEBUG) printf("\nDumping memory leaks:\n"); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); _CrtDumpMemoryLeaks(); printf("Memory dump complete.\n\n"); #endif //TerminateProcess(GetCurrentProcess(), 0); return(0); } return value; } HRESULT STDMETHODCALLTYPE epw_Weather_QueryInterface(EPWeather* _this, REFIID riid, void** ppv) { if (!IsEqualIID(riid, &IID_IEPWeather) && !IsEqualIID(riid, &IID_IUnknown)) { *ppv = 0; return(E_NOINTERFACE); } *ppv = _this; _this->lpVtbl->AddRef(_this); return(NOERROR); } HRESULT STDMETHODCALLTYPE epw_Weather_About(EPWeather* _this, HWND hWnd) { HRESULT hr = NOERROR; if (SUCCEEDED(hr)) { hr = !_this ? (E_NOINTERFACE) : hr; } if (SUCCEEDED(hr)) { wchar_t text[MAX_PATH]; DWORD dwLeftMost = 0; DWORD dwSecondLeft = 0; DWORD dwSecondRight = 0; DWORD dwRightMost = 0; QueryVersionInfo(epw_hModule, VS_VERSION_INFO, &dwLeftMost, &dwSecondLeft, &dwSecondRight, &dwRightMost); swprintf_s(text, MAX_PATH, L"ExplorerPatcher Weather Host\r\n\r\nVersion %d.%d.%d.%d", dwLeftMost, dwSecondLeft, dwSecondRight, dwRightMost); MessageBoxW(hWnd, text, _T("ExplorerPatcher Weather Host"), MB_ICONINFORMATION); } return hr; } LRESULT CALLBACK epw_Weather_WindowProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) { EPWeather* _this = NULL; if (uMsg == WM_CREATE) { CREATESTRUCT* pCreate = (CREATESTRUCT*)(lParam); _this = (int*)(pCreate->lpCreateParams); SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)_this); } else { LONG_PTR ptr = GetWindowLongPtrW(hWnd, GWLP_USERDATA); _this = (EPWeather*)(ptr); } if (!_this) { return DefWindowProcW(hWnd, uMsg, wParam, lParam); } if (uMsg == WM_TIMER && wParam == EP_WEATHER_TIMER_REQUEST_REPAINT) { HWND hNotifyWnd = InterlockedAdd64(&_this->hNotifyWnd, 0); printf("[Timer Repaint] Request posted to window %x.\n", hNotifyWnd); if (hNotifyWnd) { InvalidateRect(hNotifyWnd, NULL, TRUE); //Sleep(100); //InvalidateRect(hNotifyWnd, NULL, TRUE); } KillTimer(_this->hWnd, EP_WEATHER_TIMER_REQUEST_REPAINT); return 0; } else if (uMsg == WM_TIMER && wParam == EP_WEATHER_TIMER_REQUEST_REFRESH) { KillTimer(_this->hWnd, EP_WEATHER_TIMER_REQUEST_REFRESH); return SendMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); } else if (uMsg == WM_TIMER && wParam == EP_WEATHER_TIMER_SCHEDULE_REFRESH) { if (SendMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0)) { printf("[Timer Scheduled Refresh] Browser is busy, waiting a minute and retrying...\n"); KillTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH); SetTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH, 1000 * 60, NULL); } else { KillTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH); LONG64 dwUpdateSchedule = InterlockedAdd64(&_this->dwUpdateSchedule, 0); printf("[Timer Scheduled Refresh] Fetching data, sleeping for %lld more ms.\n", dwUpdateSchedule); SetTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH, dwUpdateSchedule, NULL); } return 0; } else if (uMsg == WM_TIMER && wParam == EP_WEATHER_TIMER_RESIZE_WINDOW) { LPWSTR uri = NULL; if (_this->pCoreWebView2) { _this->pCoreWebView2->lpVtbl->get_Source(_this->pCoreWebView2, &uri); } DWORD dwTextScaleFactor = epw_Weather_GetTextScaleFactor(_this); DWORD dwZoomFactor = epw_Weather_GetZoomFactor(_this); UINT dpi = GetDpiForWindow(_this->hWnd); RECT rcAdj; SetRect(&rcAdj, 0, 0, MulDiv(MulDiv(MulDiv(EP_WEATHER_WIDTH, dpi, 96), dwTextScaleFactor, 100), dwZoomFactor, 100), MulDiv(MulDiv(MulDiv((!wcscmp(L"about:blank", uri ? uri : L"") ? EP_WEATHER_HEIGHT_ERROR : EP_WEATHER_HEIGHT), dpi, 96), dwTextScaleFactor, 100), dwZoomFactor, 100)); AdjustWindowRectExForDpi(&rcAdj, epw_Weather_GetStyle(_this) & ~WS_OVERLAPPED, epw_Weather_HasMenuBar(_this), epw_Weather_GetExtendedStyle(_this), dpi); SetWindowPos(_this->hWnd, NULL, 0, 0, rcAdj.right - rcAdj.left, rcAdj.bottom - rcAdj.top, SWP_NOMOVE | SWP_NOSENDCHANGING); CoTaskMemFree(uri); if (_this->cntResizeWindow == 7) { _this->cntResizeWindow = 0; KillTimer(_this->hWnd, EP_WEATHER_TIMER_RESIZE_WINDOW); } else { _this->cntResizeWindow++; } return 0; } else if (uMsg == WM_TIMER && wParam == EP_WEATHER_TIMER_EXECUTEDATASCRIPT) { _epw_Weather_ExecuteDataScript(_this); KillTimer(_this->hWnd, EP_WEATHER_TIMER_EXECUTEDATASCRIPT); return 0; } else if (uMsg == EP_WEATHER_WM_REBOUND_BROWSER) { LPWSTR uri = NULL; if (_this->pCoreWebView2) { _this->pCoreWebView2->lpVtbl->get_Source(_this->pCoreWebView2, &uri); } _ep_Weather_ReboundBrowser(_this, !wcscmp(L"about:blank", uri ? uri : L"")); CoTaskMemFree(uri); return 0; } else if (uMsg == EP_WEATHER_WM_FETCH_DATA) { INT64 bWasBrowserBusy = InterlockedCompareExchange64(&_this->bBrowserBusy, TRUE, FALSE); if (!bWasBrowserBusy) { return _epw_Weather_NavigateToProvider(_this); } return HRESULT_FROM_WIN32(ERROR_BUSY); } else if (uMsg == EP_WEATHER_WM_SET_BROWSER_THEME) { if (_this->pCoreWebView2) { GenericObjectWithThis* pCoreWebView2CallDevToolsProtocolMethodCompletedHandler = NULL; if (lParam) { pCoreWebView2CallDevToolsProtocolMethodCompletedHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerVtbl, _this, L"pCoreWebView2CallDevToolsProtocolMethodCompletedHandler_WithRefresh"); } else { pCoreWebView2CallDevToolsProtocolMethodCompletedHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerVtbl, _this, L"pCoreWebView2CallDevToolsProtocolMethodCompletedHandler"); } if (wParam) { printf("[SetDarkMode] 1\n"); _this->pCoreWebView2->lpVtbl->CallDevToolsProtocolMethod(_this->pCoreWebView2, L"Emulation.setEmulatedMedia", L"{\"features\": [ { \"name\": \"prefers-color-scheme\", \"value\": \"dark\" }]}", pCoreWebView2CallDevToolsProtocolMethodCompletedHandler); //_this->pCoreWebView2->lpVtbl->CallDevToolsProtocolMethod(_this->pCoreWebView2, L"Emulation.setAutoDarkModeOverride", L"{\"enabled\": true}", &EPWeather_ICoreWebView2CallDevToolsProtocolMethodCompletedHandler); } else { printf("[SetDarkMode] 0\n"); _this->pCoreWebView2->lpVtbl->CallDevToolsProtocolMethod(_this->pCoreWebView2, L"Emulation.setEmulatedMedia", L"{\"features\": [ { \"name\": \"prefers-color-scheme\", \"value\": \"light\" }]}", pCoreWebView2CallDevToolsProtocolMethodCompletedHandler); //_this->pCoreWebView2->lpVtbl->CallDevToolsProtocolMethod(_this->pCoreWebView2, L"Emulation.setAutoDarkModeOverride", L"{\"enabled\": false}", &EPWeather_ICoreWebView2CallDevToolsProtocolMethodCompletedHandler); } return S_OK; } } else if (uMsg == EP_WEATHER_WM_SETDEVMODE) { if (_this->pCoreWebView2) { ICoreWebView2Settings* pCoreWebView2Settings = NULL; _this->pCoreWebView2->lpVtbl->get_Settings(_this->pCoreWebView2, &pCoreWebView2Settings); if (pCoreWebView2Settings) { ICoreWebView2Settings6* pCoreWebView2Settings6 = NULL; pCoreWebView2Settings->lpVtbl->QueryInterface(pCoreWebView2Settings, &IID_ICoreWebView2Settings6, &pCoreWebView2Settings6); if (pCoreWebView2Settings6) { pCoreWebView2Settings6->lpVtbl->put_AreDevToolsEnabled(pCoreWebView2Settings6, wParam); pCoreWebView2Settings6->lpVtbl->put_AreDefaultContextMenusEnabled(pCoreWebView2Settings6, wParam); pCoreWebView2Settings6->lpVtbl->put_AreBrowserAcceleratorKeysEnabled(pCoreWebView2Settings6, wParam); pCoreWebView2Settings6->lpVtbl->put_AreDefaultScriptDialogsEnabled(pCoreWebView2Settings6, wParam); pCoreWebView2Settings6->lpVtbl->Release(pCoreWebView2Settings6); LONG dwStyle = epw_Weather_GetStyle(_this); if (!GetLastError()) { if (wParam) dwStyle |= WS_SIZEBOX; else dwStyle &= ~WS_SIZEBOX; SetWindowLongW(_this->hWnd, GWL_STYLE, dwStyle); } PostMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); } pCoreWebView2Settings->lpVtbl->Release(pCoreWebView2Settings); } } } else if (uMsg == EP_WEATHER_WM_SETZOOMFACTOR) { if (_this->pCoreWebView2Controller) { _this->pCoreWebView2Controller->lpVtbl->put_ZoomFactor(_this->pCoreWebView2Controller, wParam / 100.0); _ep_Weather_StartResize(_this); } } else if (uMsg == WM_CLOSE || (uMsg == WM_KEYUP && wParam == VK_ESCAPE) || (uMsg == WM_ACTIVATEAPP && wParam == FALSE && GetAncestor(GetForegroundWindow(), GA_ROOT) != _this->hWnd)) { epw_Weather_Hide(_this); return 0; } else if (uMsg == WM_WINDOWPOSCHANGING) { if (IsWindowVisible(hWnd)) { LONG64 dwDevMode = InterlockedAdd64(&_this->dwDevMode, 0); WINDOWPOS* pwp = (WINDOWPOS*)lParam; pwp->flags |= (!dwDevMode ? (SWP_NOMOVE | SWP_NOSIZE) : 0); if (dwDevMode) { _ep_Weather_ReboundBrowser(_this, TRUE); } } return 0; } else if (uMsg == WM_SETTINGCHANGE) { if (IsColorSchemeChangeMessage(lParam)) { MARGINS marGlassInset; if (!IsHighContrast()) { marGlassInset.cxLeftWidth = -1; // -1 means the whole window marGlassInset.cxRightWidth = -1; marGlassInset.cyBottomHeight = -1; marGlassInset.cyTopHeight = -1; } else { marGlassInset.cxLeftWidth = 0; marGlassInset.cxRightWidth = 0; marGlassInset.cyBottomHeight = 0; marGlassInset.cyTopHeight = 0; } LONG64 dwDarkMode = InterlockedAdd64(&_this->g_darkModeEnabled, 0); if (IsWindows11()) { if (!IsDwmExtendFrameIntoClientAreaBrokenInThisBuild()) { DwmExtendFrameIntoClientArea(_this->hWnd, &marGlassInset); } BOOL value = (IsThemeActive() && !IsHighContrast()) ? 1 : 0; SetMicaMaterialForThisWindow(_this->hWnd, value); } else { int s = 0; if (global_rovi.dwBuildNumber < 18985) { s = -1; } DwmSetWindowAttribute(_this->hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE + s, &dwDarkMode, sizeof(LONG64)); } if (!dwDarkMode) { epw_Weather_SetDarkMode(_this, dwDarkMode, TRUE); } return 0; } } else if (uMsg == WM_DPICHANGED) { //UINT dpiX = LOWORD(wParam); //UINT dpiY = HIWORD(wParam); //DWORD dwTextScaleFactor = epw_Weather_GetTextScaleFactor(_this); //DWORD dwZoomFactor = epw_Weather_GetZoomFactor(_this); //RECT rcAdj; //SetRect(&rcAdj, 0, 0, MulDiv(MulDiv(MulDiv(EP_WEATHER_WIDTH, dpiX, 96), dwTextScaleFactor, 100), dwZoomFactor, 100), MulDiv(MulDiv(MulDiv(EP_WEATHER_HEIGHT, dpiY, 96), dwTextScaleFactor, 100), dwZoomFactor, 100)); //AdjustWindowRectExForDpi(&rcAdj, epw_Weather_GetStyle(_this) & ~WS_OVERLAPPED, epw_Weather_HasMenuBar(_this), epw_Weather_GetExtendedStyle(_this), dpiX); RECT* rc = lParam; SetWindowPos(_this->hWnd, NULL, rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, 0); return 0; } else if (uMsg == WM_PAINT && !IsWindows11()) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); if (ps.fErase) { LONG64 bEnabled, dwDarkMode; dwDarkMode = InterlockedAdd64(&_this->g_darkModeEnabled, 0); epw_Weather_IsDarkMode(_this, dwDarkMode, &bEnabled); COLORREF oldcr = SetBkColor(hdc, bEnabled ? RGB(0, 0, 0) : RGB(255, 255, 255)); ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &ps.rcPaint, L"", 0, 0); SetBkColor(hdc, oldcr); } EndPaint(hWnd, &ps); return 0; } /*BOOL bIsRunningWithoutVisualStyle = !IsThemeActive() || IsHighContrast(); if (uMsg == WM_CREATE) { if (bIsRunningWithoutVisualStyle) { SetRectEmpty(&_this->rcBorderThickness); if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_THICKFRAME) { AdjustWindowRectEx(&_this->rcBorderThickness, GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL); _this->rcBorderThickness.left *= -1; _this->rcBorderThickness.top *= -1; } else if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_BORDER) { SetRect(&_this->rcBorderThickness, 1, 1, 1, 1); } SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); } } else if (uMsg == WM_NCCALCSIZE) { if (bIsRunningWithoutVisualStyle) { if (lParam) { NCCALCSIZE_PARAMS* sz = (NCCALCSIZE_PARAMS*)lParam; sz->rgrc[0].left += _this->rcBorderThickness.left; sz->rgrc[0].right -= _this->rcBorderThickness.right; sz->rgrc[0].bottom -= _this->rcBorderThickness.bottom; return 0; } } } else if (uMsg == WM_NCHITTEST) { if (bIsRunningWithoutVisualStyle) { LRESULT lRes = DefWindowProcW(hWnd, uMsg, wParam, lParam); if (lRes == HTCLIENT) { POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; ScreenToClient(hWnd, &pt); if (pt.y < _this->rcBorderThickness.top) { return HTTOP; } else { return HTCAPTION; } } else { return lRes; } } } else if (uMsg == WM_NCACTIVATE) { if (bIsRunningWithoutVisualStyle) { return 0; } }*/ return DefWindowProcW(hWnd, uMsg, wParam, lParam); } HRESULT STDMETHODCALLTYPE epw_Weather_IsDarkMode(EPWeather* _this, LONG64 dwDarkMode, LONG64* bEnabled) { BOOL bIsCompositionEnabled = TRUE; DwmIsCompositionEnabled(&bIsCompositionEnabled); if (!dwDarkMode) { RTL_OSVERSIONINFOW rovi; *bEnabled = bIsCompositionEnabled && ((global_rovi.dwBuildNumber < 18985) ? TRUE : (ShouldSystemUseDarkMode ? ShouldSystemUseDarkMode() : FALSE)) && !IsHighContrast(); } else { *bEnabled = dwDarkMode - 1; } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetDarkMode(EPWeather* _this, LONG64 dwDarkMode, LONG64 bRefresh) { LONG64 bEnabled; epw_Weather_IsDarkMode(_this, dwDarkMode, &bEnabled); InterlockedExchange64(&_this->g_darkModeEnabled, dwDarkMode); if ((dwDarkMode == 2 && bEnabled) || (dwDarkMode == 1 && !bEnabled) || !dwDarkMode) { RefreshImmersiveColorPolicyState(); if (_this->hWnd) { AllowDarkModeForWindow(_this->hWnd, bEnabled); int s = 0; if (global_rovi.dwBuildNumber < 18985) { s = -1; } DwmSetWindowAttribute(_this->hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE + s, &bEnabled, sizeof(BOOL)); //InvalidateRect(_this->hWnd, NULL, FALSE); PostMessageW(_this->hWnd, EP_WEATHER_WM_SET_BROWSER_THEME, bEnabled, bRefresh); } return S_OK; } return E_FAIL; } HRESULT STDMETHODCALLTYPE epw_Weather_SetGeolocationMode(EPWeather* _this, LONG64 dwGeolocationMode) { InterlockedExchange64(&_this->dwGeolocationMode, dwGeolocationMode); PostMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetWindowCornerPreference(EPWeather* _this, LONG64 dwWindowCornerPreference) { InterlockedExchange64(&_this->dwWindowCornerPreference, dwWindowCornerPreference); INT preference = dwWindowCornerPreference; if (_this->hWnd) { DwmSetWindowAttribute(_this->hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &preference, sizeof(preference)); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetDevMode(EPWeather* _this, LONG64 dwDevMode, LONG64 bRefresh) { InterlockedExchange64(&_this->dwDevMode, dwDevMode); if (bRefresh) { PostMessageW(_this->hWnd, EP_WEATHER_WM_SETDEVMODE, dwDevMode, 0); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetIconPack(EPWeather* _this, LONG64 dwIconPack, LONG64 bRefresh) { InterlockedExchange64(&_this->dwIconPack, dwIconPack); if (bRefresh) { PostMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetZoomFactor(EPWeather* _this, LONG64 dwZoomFactor) { InterlockedExchange64(&_this->dwZoomFactor, dwZoomFactor); PostMessageW(_this->hWnd, EP_WEATHER_WM_SETZOOMFACTOR, dwZoomFactor, 0); return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_GetLastUpdateTime(EPWeather* _this, LPSYSTEMTIME lpLastUpdateTime) { *lpLastUpdateTime = stLastUpdate; return S_OK; } DWORD WINAPI epw_Weather_MainThread(EPWeather* _this) { HRESULT hr = S_OK; BOOL bShouldReleaseBecauseClientDied = FALSE; SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); _this->hrLastError = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(_this->hrLastError)) { goto cleanup; } _this->hrLastError = CoCreateInstance( &CLSID_TaskbarList, NULL, CLSCTX_INPROC, &IID_ITaskbarList, (LPVOID*)&_this->pTaskList ); if (FAILED(_this->hrLastError)) { goto cleanup; } WNDCLASSW wc; ZeroMemory(&wc, sizeof(WNDCLASSW)); wc.style = CS_DBLCLKS; wc.lpfnWndProc = epw_Weather_WindowProc; wc.hInstance = epw_hModule; wc.hbrBackground = IsWindows11() ? (HBRUSH)GetStockObject(BLACK_BRUSH) : NULL; wc.lpszClassName = _T(EPW_WEATHER_CLASSNAME); wc.hCursor = LoadCursorW(NULL, IDC_ARROW); if (!RegisterClassW(&wc)) { //_this->hrLastError = HRESULT_FROM_WIN32(GetLastError()); //goto cleanup; } DWORD dwDevMode = InterlockedAdd64(&_this->dwDevMode, 0); DWORD dwStyle = WS_CAPTION | (dwDevMode ? WS_SIZEBOX : 0); DWORD dwExStyle = 0; RECT rc = _this->rc; AdjustWindowRectExForDpi(&rc, dwStyle, FALSE, dwExStyle, _this->dpiXInitial); _this->hWnd = CreateWindowExW(dwExStyle, _T(EPW_WEATHER_CLASSNAME), L"", WS_OVERLAPPED | dwStyle, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, epw_hModule, _this); // 1030, 630 if (!_this->hWnd) { _this->hrLastError = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; } SetPropW(_this->hWnd, L"valinet.ExplorerPatcher.ShellManagedWindow", TRUE); _this->hrLastError = _this->pTaskList->lpVtbl->DeleteTab(_this->pTaskList, _this->hWnd); if (FAILED(_this->hrLastError)) { goto cleanup; } WCHAR wszWorkFolder[MAX_PATH]; ZeroMemory(wszWorkFolder, MAX_PATH * sizeof(WCHAR)); SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wszWorkFolder); wcscat_s(wszWorkFolder, MAX_PATH, L"\\ExplorerPatcher\\ep_weather_host"); BOOL bRet = CreateDirectoryW(wszWorkFolder, NULL); if (!(bRet || (!bRet && GetLastError() == ERROR_ALREADY_EXISTS))) { _this->hrLastError = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); goto cleanup; } LONG64 dwDarkMode = InterlockedAdd64(&_this->g_darkModeEnabled, 0); if (IsWindows11()) { if (!IsHighContrast()) { if (!IsDwmExtendFrameIntoClientAreaBrokenInThisBuild()) { MARGINS marGlassInset = { -1, -1, -1, -1 }; // -1 means the whole window DwmExtendFrameIntoClientArea(_this->hWnd, &marGlassInset); } BOOL value = 1; SetMicaMaterialForThisWindow(_this->hWnd, TRUE); } } else { int s = 0; if (global_rovi.dwBuildNumber < 18985) { s = -1; } DwmSetWindowAttribute(_this->hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE + s, &dwDarkMode, sizeof(LONG64)); } epw_Weather_SetDarkMode(_this, dwDarkMode, FALSE); InterlockedExchange64(&_this->bBrowserBusy, TRUE); GenericObjectWithThis* pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = GenericObjectWithThis_MakeAndInitialize(&EPWeather_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl, _this, L"pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler"); if (!pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) goto cleanup; _this->hrLastError = CreateCoreWebView2EnvironmentWithOptions(NULL, wszWorkFolder, &EPWeather_ICoreWebView2EnvironmentOptions, pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler); pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler->lpVtbl->Release(pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler); if (FAILED(_this->hrLastError)) goto cleanup; INetworkListManager* spManager = NULL; IConnectionPointContainer* spConnectionPoints = NULL; IConnectionPoint* spConnectionPoint = NULL; IUnknown* spSink = NULL; DWORD dwCookie = 0; GenericObjectWithThis* pNetworkListManager = GenericObjectWithThis_MakeAndInitialize(&INetworkListManagerEvents_Vtbl, _this, L"pNetworkListManager"); if (pNetworkListManager) { if (SUCCEEDED(hr = CoCreateInstance(&CLSID_NetworkListManager, NULL, CLSCTX_ALL, &IID_INetworkListManager, &spManager) && spManager)) { if (SUCCEEDED(hr = spManager->lpVtbl->QueryInterface(spManager, &IID_IConnectionPointContainer, &spConnectionPoints))) { if (SUCCEEDED(hr = spConnectionPoints->lpVtbl->FindConnectionPoint(spConnectionPoints, &IID_INetworkListManagerEvents, &spConnectionPoint))) { if (SUCCEEDED(hr = pNetworkListManager->lpVtbl->QueryInterface(pNetworkListManager, &IID_IUnknown, &spSink))) { if (SUCCEEDED(hr = spConnectionPoint->lpVtbl->Advise(spConnectionPoint, spSink, &dwCookie))) { } } } } } } LONG64 dwUpdateSchedule = InterlockedAdd64(&_this->dwUpdateSchedule, 0); SetTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH, dwUpdateSchedule, NULL); SetEvent(_this->hInitializeEvent); MSG msg; while (TRUE) { DWORD dwRes = MsgWaitForMultipleObjects(EP_WEATHER_NUM_SIGNALS, &_this->hSignalExitMainThread, FALSE, INFINITE, QS_ALLINPUT); if (dwRes == WAIT_OBJECT_0 || dwRes == WAIT_ABANDONED_0 + 1) { if (dwRes == WAIT_ABANDONED_0 + 1) { printf("[General] Client has died.\n"); if (OpenEventW(READ_CONTROL, FALSE, _T(EP_SETUP_EVENTNAME))) { printf("[General] Servicing is in progress, terminating...\n"); TerminateProcess(GetCurrentProcess(), 0); } bShouldReleaseBecauseClientDied = TRUE; } PostQuitMessage(0); } else if (dwRes == WAIT_OBJECT_0 + EP_WEATHER_NUM_SIGNALS) { BOOL bRet = 0, bQuit = FALSE; while (bRet = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { bQuit = TRUE; break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } if (bQuit) { _this->pCoreWebView2Controller->lpVtbl->Close(_this->pCoreWebView2Controller); break; } } else if (dwRes == WAIT_OBJECT_0 + 2) { epw_Weather_SetTextScaleFactorFromRegistry(_this, HKEY_CURRENT_USER, TRUE); } else if (dwRes == WAIT_OBJECT_0 + 3) { epw_Weather_SetTextScaleFactorFromRegistry(_this, HKEY_LOCAL_MACHINE, TRUE); } } if (SUCCEEDED(hr)) { spConnectionPoint->lpVtbl->Unadvise(spConnectionPoint, dwCookie); } if (spSink) { spSink->lpVtbl->Release(spSink); } if (spConnectionPoint) { spConnectionPoint->lpVtbl->Release(spConnectionPoint); } if (spConnectionPoints) { spConnectionPoints->lpVtbl->Release(spConnectionPoints); } if (spManager) { spManager->lpVtbl->Release(spManager); } if (pNetworkListManager) { pNetworkListManager->lpVtbl->Release(pNetworkListManager); } cleanup: if (_this->tkOnNavigationStarting.value) { _this->pCoreWebView2->lpVtbl->remove_NavigationStarting(_this->pCoreWebView2, _this->tkOnNavigationStarting); } if (_this->pCoreWebView2NavigationStartingEventHandler) { _this->pCoreWebView2NavigationStartingEventHandler->lpVtbl->Release(_this->pCoreWebView2NavigationStartingEventHandler); } if (_this->tkOnNavigationCompleted.value) { _this->pCoreWebView2->lpVtbl->remove_NavigationCompleted(_this->pCoreWebView2, _this->tkOnNavigationCompleted); } if (_this->pCoreWebView2NavigationCompletedEventHandler) { _this->pCoreWebView2NavigationCompletedEventHandler->lpVtbl->Release(_this->pCoreWebView2NavigationCompletedEventHandler); } if (_this->tkOnPermissionRequested.value) { _this->pCoreWebView2->lpVtbl->remove_PermissionRequested(_this->pCoreWebView2, _this->tkOnPermissionRequested); } if (_this->pCoreWebView2PermissionRequestedEventHandler) { _this->pCoreWebView2PermissionRequestedEventHandler->lpVtbl->Release(_this->pCoreWebView2PermissionRequestedEventHandler); } if (_this->pCoreWebView2) { _this->pCoreWebView2->lpVtbl->Release(_this->pCoreWebView2); } if (_this->pCoreWebView2Controller) { _this->pCoreWebView2Controller->lpVtbl->Release(_this->pCoreWebView2Controller); } if (_this->wszTemperature) { free(_this->wszTemperature); } if (_this->wszUnit) { free(_this->wszUnit); } if (_this->wszCondition) { free(_this->wszCondition); } if (_this->pImage) { free(_this->pImage); } if (_this->wszLocation) { free(_this->wszLocation); } if (_this->hWnd) { DestroyWindow(_this->hWnd); } if (_this->pTaskList) { _this->pTaskList->lpVtbl->Release(_this->pTaskList); } CoUninitialize(); SetEvent(_this->hInitializeEvent); if (bShouldReleaseBecauseClientDied) { SHCreateThread(epw_Weather_ReleaseBecauseClientDiedThread, _this, CTF_NOADDREFLIB, NULL); } printf("[General] Exiting main thread.\n"); return 0; } HRESULT STDMETHODCALLTYPE epw_Weather_Initialize(EPWeather* _this, WCHAR wszName[MAX_PATH], BOOL bAllocConsole, LONG64 dwProvider, LONG64 cbx, LONG64 cby, LONG64 dwTemperatureUnit, LONG64 dwUpdateSchedule, RECT rc, LONG64 dwDarkMode, LONG64 dwGeolocationMode, HWND* hWnd, LONG64 dwZoomFactor, LONG64 dpiXInitial, LONG64 dpiYInitial) { InitializeGlobalVersionAndUBR(); if (bAllocConsole) { FILE* conout; AllocConsole(); freopen_s( &conout, "CONOUT$", "w", stdout ); } if (dwUpdateSchedule < 0) { return E_INVALIDARG; } InterlockedExchange64(&_this->dwUpdateSchedule, dwUpdateSchedule); if (dwTemperatureUnit < 0 || dwTemperatureUnit > EP_WEATHER_NUM_TUNITS) { return E_INVALIDARG; } InterlockedExchange64(&_this->dwTemperatureUnit, dwTemperatureUnit); if (dwProvider < 0 || dwProvider > EP_WEATHER_NUM_PROVIDERS) { return E_INVALIDARG; } InterlockedExchange64(&_this->dwProvider, dwProvider); if (!cbx || !cby) { return E_INVALIDARG; } InterlockedExchange64(&_this->cbx, cbx); InterlockedExchange64(&_this->cby, cby); _this->hSignalKillSwitch = CreateMutexW(NULL, FALSE, wszName); if (!_this->hSignalKillSwitch || GetLastError() != ERROR_ALREADY_EXISTS) { return E_INVALIDARG; } InterlockedExchange64(&_this->dwGeolocationMode, dwGeolocationMode); InterlockedExchange64(&_this->dwZoomFactor, dwZoomFactor); _this->dpiXInitial = dpiXInitial; _this->dpiYInitial = dpiYInitial; _this->hUxtheme = LoadLibraryW(L"uxtheme.dll"); if (_this->hUxtheme) { RefreshImmersiveColorPolicyState = GetProcAddress(_this->hUxtheme, (LPCSTR)104); SetPreferredAppMode = GetProcAddress(_this->hUxtheme, (LPCSTR)135); AllowDarkModeForWindow = GetProcAddress(_this->hUxtheme, (LPCSTR)133); ShouldAppsUseDarkMode = GetProcAddress(_this->hUxtheme, (LPCSTR)132); ShouldSystemUseDarkMode = GetProcAddress(_this->hUxtheme, (LPCSTR)138); if (ShouldAppsUseDarkMode && ShouldSystemUseDarkMode && SetPreferredAppMode && AllowDarkModeForWindow && RefreshImmersiveColorPolicyState ) { SetPreferredAppMode(TRUE); epw_Weather_SetDarkMode(_this, dwDarkMode, FALSE); } } _this->hShlwapi = LoadLibraryW(L"Shlwapi.dll"); if (_this->hShlwapi) { _this->SHRegGetValueFromHKCUHKLMFunc = GetProcAddress(_this->hShlwapi, "SHRegGetValueFromHKCUHKLM"); } _this->hMutexData = CreateMutexW(NULL, FALSE, NULL); if (!_this->hMutexData) { return HRESULT_FROM_WIN32(GetLastError()); } _this->hInitializeEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (!_this->hInitializeEvent) { return HRESULT_FROM_WIN32(GetLastError()); } _this->hSignalExitMainThread = CreateEventW(NULL, FALSE, FALSE, NULL); if (!_this->hSignalExitMainThread) { return HRESULT_FROM_WIN32(GetLastError()); } _this->hSignalOnAccessibilitySettingsChangedFromHKCU = CreateEventW(NULL, FALSE, FALSE, NULL); if (!_this->hSignalOnAccessibilitySettingsChangedFromHKCU) { return HRESULT_FROM_WIN32(GetLastError()); } _this->hSignalOnAccessibilitySettingsChangedFromHKLM = CreateEventW(NULL, FALSE, FALSE, NULL); if (!_this->hSignalOnAccessibilitySettingsChangedFromHKLM) { return HRESULT_FROM_WIN32(GetLastError()); } epw_Weather_SetTextScaleFactorFromRegistry(_this, HKEY_CURRENT_USER, FALSE); epw_Weather_SetTextScaleFactorFromRegistry(_this, HKEY_LOCAL_MACHINE, FALSE); _this->rc = rc; _this->hMainThread = CreateThread(NULL, 0, epw_Weather_MainThread, _this, 0, NULL); if (!_this->hMainThread) { return HRESULT_FROM_WIN32(GetLastError()); } WaitForSingleObject(_this->hInitializeEvent, INFINITE); if (FAILED(_this->hrLastError)) { return _this->hrLastError; } *hWnd = _this->hWnd; return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_Show(EPWeather* _this) { SetLastError(0); LONG_PTR dwExStyle = GetWindowLongPtrW(_this->hWnd, GWL_EXSTYLE); if (!GetLastError()) { SetWindowLongPtrW(_this->hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW | dwExStyle); } INT preference = InterlockedAdd64(&_this->dwWindowCornerPreference, 0); DwmSetWindowAttribute(_this->hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &preference, sizeof(preference)); PostMessageW(_this->hWnd, EP_WEATHER_WM_REBOUND_BROWSER, 0, 0); ShowWindow(_this->hWnd, SW_SHOW); _this->pTaskList->lpVtbl->DeleteTab(_this->pTaskList, _this->hWnd); return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_Hide(EPWeather* _this) { SetLastError(0); LONG_PTR dwExStyle = GetWindowLongPtrW(_this->hWnd, GWL_EXSTYLE); if (!GetLastError()) { SetWindowLongPtrW(_this->hWnd, GWL_EXSTYLE, ~WS_EX_TOOLWINDOW & dwExStyle); } ShowWindow(_this->hWnd, SW_HIDE); return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_GetWindowHandle(EPWeather* _this, HWND* phWnd) { *phWnd = _this->hWnd; return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_LockData(EPWeather* _this) { DWORD dwRes = WaitForSingleObject(_this->hMutexData, INFINITE); if (dwRes == WAIT_ABANDONED) { return HRESULT_FROM_WIN32(ERROR_ABANDONED_WAIT_0); } else if (dwRes == WAIT_FAILED) { return HRESULT_FROM_WIN32(GetLastError()); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_GetDataSizes(EPWeather* _this, LPDWORD pcbTemperature, LPDWORD pcbUnit, LPDWORD pcbCondition, LPDWORD pcbImage) { *pcbTemperature = _this->cbTemperature; *pcbUnit = _this->cbUnit; *pcbCondition = _this->cbCondition; *pcbImage = _this->cbImage; return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_GetData(EPWeather* _this, DWORD cbTemperature, LPCWSTR wszTemperature, DWORD cbUnit, LPCWSTR wszUnit, DWORD cbCondition, LPCWSTR wszCondition, DWORD cbImage, char* pImage) { if (cbTemperature) { memcpy_s(wszTemperature, cbTemperature, _this->wszTemperature, _this->cbTemperature); } if (cbUnit) { memcpy_s(wszUnit, cbUnit, _this->wszUnit, _this->cbUnit); } if (cbCondition) { memcpy_s(wszCondition, cbCondition, _this->wszCondition, _this->cbCondition); } if (cbImage) { memcpy_s(pImage, cbImage, _this->pImage, _this->cbImage); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_GetTitle(EPWeather* _this, DWORD cbTitle, LPCWSTR wszTitle, DWORD dwType) { WCHAR wszBuffer[MAX_PATH]; ZeroMemory(wszBuffer, MAX_PATH * sizeof(WCHAR)); if (cbTitle) { switch (dwType) { case EP_WEATHER_VIEW_ICONTEXT: case EP_WEATHER_VIEW_TEXTONLY: swprintf_s(wszBuffer, MAX_PATH, L"%s", _this->wszLocation); break; case EP_WEATHER_VIEW_ICONTEMP: case EP_WEATHER_VIEW_TEMPONLY: swprintf_s(wszBuffer, MAX_PATH, L"%s - %s", _this->wszLocation, _this->wszCondition); break; case EP_WEATHER_VIEW_ICONONLY: swprintf_s(wszBuffer, MAX_PATH, L"%s %s | %s - %s", _this->wszTemperature, _this->wszUnit, _this->wszLocation, _this->wszCondition); break; } memcpy_s(wszTitle, cbTitle, wszBuffer, MAX_PATH); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_UnlockData(EPWeather* _this) { if (!ReleaseMutex(_this->hMutexData)) { return HRESULT_FROM_WIN32(GetLastError()); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_IsInitialized(EPWeather* _this, BOOL* bIsInitialized) { *bIsInitialized = _this->hInitializeEvent; return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetNotifyWindow(EPWeather* _this, HWND hWndNotify) { InterlockedExchange64(&_this->hNotifyWnd, hWndNotify); } HRESULT STDMETHODCALLTYPE epw_Weather_SetTemperatureUnit(EPWeather* _this, LONG64 dwTemperatureUnit) { if (dwTemperatureUnit < 0 || dwTemperatureUnit > EP_WEATHER_NUM_TUNITS) { return E_INVALIDARG; } InterlockedExchange64(&_this->dwTemperatureUnit, dwTemperatureUnit); return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetUpdateSchedule(EPWeather* _this, LONG64 dwUpdateSchedule) { if (dwUpdateSchedule < 0) { return E_INVALIDARG; } LONG64 dwOldUpdateSchedule = InterlockedExchange64(&_this->dwUpdateSchedule, dwUpdateSchedule); if (dwOldUpdateSchedule != dwUpdateSchedule) { KillTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH); SetTimer(_this->hWnd, EP_WEATHER_TIMER_SCHEDULE_REFRESH, dwUpdateSchedule, NULL); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetTerm(EPWeather* _this, DWORD cbTerm, LPCWSTR wszTerm) { if (cbTerm) { memcpy_s(_this->wszTerm, sizeof(WCHAR) * MAX_PATH, wszTerm, cbTerm); } else { ZeroMemory(&_this->wszTerm, sizeof(WCHAR) * MAX_PATH); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetLanguage(EPWeather* _this, DWORD cbLanguage, LPCWSTR wszLanguage) { if (cbLanguage) { memcpy_s(_this->wszLanguage, sizeof(WCHAR) * MAX_PATH, wszLanguage, cbLanguage); } else { ZeroMemory(&_this->wszLanguage, sizeof(WCHAR) * MAX_PATH); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_SetIconSize(EPWeather* _this, LONG64 cbx, LONG64 cby) { DWORD dwOldX = InterlockedAdd64(&_this->cbx, 0); DWORD dwOldY = InterlockedAdd64(&_this->cby, 0); if (dwOldX != cbx) { InterlockedExchange64(&_this->cbx, cbx); InterlockedExchange64(&_this->cby, cby); PostMessageW(_this->hWnd, EP_WEATHER_WM_FETCH_DATA, 0, 0); } return S_OK; } HRESULT STDMETHODCALLTYPE epw_Weather_GetIconSize(EPWeather* _this, LONG64* cbx, LONG64* cby) { if (cbx) *cbx = InterlockedAdd64(&_this->cbx, 0); if (cby) *cby = InterlockedAdd64(&_this->cby, 0); return S_OK; }