1
0
mirror of https://github.com/valinet/ExplorerPatcher.git synced 2024-11-27 17:00:59 +01:00
ExplorerPatcher/ep_weather_host/ep_weather_host.c
Valentin Radu 9ec44832dd Weather: Fixed a bug that could hang the host process and explorer
A nasty bug was sometime occurring where both explorer and the widget
host process could hang; this often happened when explorer was
restarted. The reason this happened was because the widget host
process could hang waiting for the "Lock_EPWeather_Instance" lock. This
was a global lock that made sure only one instance of the widget could
be created.

The idea of the global "Lock_EPWeather_Instance" lock was, of course,
pretty bad, but I chose it because I couldn't figure out/didn't want to
deal with passing an EPWeather "this" instance to WebView2 or
NetworkListManagerEvents functions. Bad decision.

This patch addresses this bug, by providing a generic object
which holds a reference to EPWeather "this" on which I build event
handlers for WebView2 and so on. Since these now contain this
reference, they cannot be static anymore, thus I switched to dynamically
allocating them and managing them throughout their lifetime using,
of course, reference counting. This is the proper solution.

Thus, this bug and any similar ones should now be fixed.
2022-08-05 15:31:36 +03:00

1951 lines
77 KiB
C

#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", ep_weather_provider_google_script00, ep_weather_provider_google_script01, ep_weather_provider_google_script02, 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(167, 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);
}
}
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 == 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;
}