1
0
mirror of https://github.com/valinet/ExplorerPatcher.git synced 2024-12-18 02:16:00 +01:00

Fixes for shell extension

* Properly implemented cleanup routines when injected into
applications other than Explorer
* Never EVER forget to specify a ThreadingModel for a COM object
in registry. That was the cause the DLL was making Microsoft Teams
crash on startup
* Do not free memory when the DLL is unloaded (DLL_PROCESS_DETACH)
and lpvReserved is non-NULL. It means the DLL is unloaded as the process
terminates, in which case all threads are dead, so it is not safe to call freeing
routines - let the operating system reclaim the memory on process exit
This commit is contained in:
Valentin Radu 2021-11-11 07:00:44 +02:00
parent e2af83e68b
commit 04616cee16
5 changed files with 297 additions and 158 deletions

View File

@ -2,6 +2,14 @@
This document includes the same release notes as in the [Releases](https://github.com/valinet/ExplorerPatcher/releases) section on GitHub.
## 22000.318.36
Tested on build 22000.318.
#### Fixes
* Lots of bug and issue fixes for shell extension failing to work under certain circumstances; fixed #259
## 22000.318.35
Tested on build 22000.318.

View File

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 22000,318,35,0
PRODUCTVERSION 22000,318,35,0
FILEVERSION 22000,318,36,0
PRODUCTVERSION 22000,318,36,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "VALINET Solutions SRL"
VALUE "FileDescription", "ExplorerPatcher"
VALUE "FileVersion", "22000.318.35.0"
VALUE "FileVersion", "22000.318.36.0"
VALUE "InternalName", "ExplorerPatcher.dll"
VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved."
VALUE "OriginalFilename", "ExplorerPatcher.dll"
VALUE "ProductName", "ExplorerPatcher"
VALUE "ProductVersion", "22000.318.35.0"
VALUE "ProductVersion", "22000.318.36.0"
END
END
BLOCK "VarFileInfo"

View File

@ -3,83 +3,113 @@
DWORD WINAPI MonitorSettings(SettingsChangeParameters* params)
{
BOOL bShouldExit = FALSE;
HANDLE* handles = NULL;
printf("[SettingsMonitor] Started %p\n", params->settings[0].hEvent);
while (TRUE)
{
HANDLE* handles = malloc(sizeof(HANDLE) * (params->size + 1));
if (!handles)
handles = calloc(sizeof(HANDLE), params->size);
if (handles)
{
return 0;
}
for (unsigned int i = 0; i < params->size; ++i)
{
params->settings[i].hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!params->settings[i].hEvent)
for (unsigned int i = 0; i < params->size; ++i)
{
return 0;
}
handles[i] = params->settings[i].hEvent;
if (RegCreateKeyExW(
params->settings[i].origin,
params->settings[i].name,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&(params->settings[i].hKey),
NULL
) != ERROR_SUCCESS)
{
return 0;
}
if (RegNotifyChangeKeyValue(
params->settings[i].hKey,
FALSE,
REG_NOTIFY_CHANGE_LAST_SET,
params->settings[i].hEvent,
TRUE
) != ERROR_SUCCESS)
{
return 0;
}
}
handles[params->size] = params->hExitEvent;
DWORD dwRes = WaitForMultipleObjects(
params->size + (params->hExitEvent ? 1 : 0),
handles,
FALSE,
INFINITE
);
if (dwRes != WAIT_FAILED)
{
unsigned int i = dwRes - WAIT_OBJECT_0;
if (i >= 0 && i < params->size)
{
params->settings[i].callback(params->settings[i].data);
}
else if (i == params->size && params->hExitEvent)
{
bShouldExit = TRUE;
}
for (unsigned int j = 0; j < params->size; ++j)
{
if (WaitForSingleObject(handles[j], 0) == WAIT_OBJECT_0)
if (i == 0)
{
params->settings[j].callback(params->settings[j].data);
if (params->settings[i].hEvent)
{
handles[i] = params->settings[i].hEvent;
continue;
}
else
{
InterlockedExchange(&(params->size), NULL);
return 0;
}
}
params->settings[i].hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!params->settings[i].hEvent)
{
InterlockedExchange(&(params->size), 0);
return 0;
}
handles[i] = params->settings[i].hEvent;
if (RegCreateKeyExW(
params->settings[i].origin,
params->settings[i].name,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&(params->settings[i].hKey),
NULL
) != ERROR_SUCCESS)
{
InterlockedExchange(&(params->size), 0);
return 0;
}
if (RegNotifyChangeKeyValue(
params->settings[i].hKey,
FALSE,
REG_NOTIFY_CHANGE_LAST_SET,
params->settings[i].hEvent,
TRUE
) != ERROR_SUCCESS)
{
InterlockedExchange(&(params->size), 0);
return 0;
}
}
DWORD dwRes = WaitForMultipleObjects(
params->size,
handles,
FALSE,
INFINITE
);
if (dwRes != WAIT_FAILED)
{
unsigned int i = dwRes - WAIT_OBJECT_0;
if (i >= 1 && i < params->size)
{
params->settings[i].callback(params->settings[i].data);
}
else if (i == 0)
{
bShouldExit = TRUE;
}
for (unsigned int j = 1; j < params->size; ++j)
{
if (WaitForSingleObject(handles[j], 0) == WAIT_OBJECT_0)
{
params->settings[j].callback(params->settings[j].data);
}
}
}
free(handles);
for (unsigned int i = 1; i < params->size; ++i)
{
if (params->settings[i].hEvent)
{
CloseHandle(params->settings[i].hEvent);
}
if (params->settings[i].hKey)
{
RegCloseKey(params->settings[i].hKey);
}
}
if (bShouldExit)
{
break;
}
}
free(handles);
for (unsigned int i = 0; i < params->size; ++i)
else
{
CloseHandle(params->settings[i].hEvent);
RegCloseKey(params->settings[i].hKey);
}
if (bShouldExit)
{
break;
InterlockedExchange(&(params->size), 0);
return 0;
}
}
printf("[SettingsMonitor] Ended %p\n", params->settings[0].hEvent);
InterlockedExchange(&(params->size), 0);
return 0;
}

View File

@ -3,6 +3,7 @@
#include <Windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <stdio.h>
typedef struct _Setting
{
@ -17,7 +18,7 @@ typedef struct _SettingsChangeParameters
{
Setting* settings;
DWORD size;
HANDLE hExitEvent;
HANDLE hThread;
} SettingsChangeParameters;
DWORD WINAPI MonitorSettings(SettingsChangeParameters*);
#endif

View File

@ -70,11 +70,9 @@ DWORD bTaskbarMonitorOverride = 0;
DWORD dwIMEStyle = 0;
DWORD dwTaskbarAl = 0;
HMODULE hModule = NULL;
HANDLE hSettingsMonitorThread = NULL;
HANDLE hDelayedInjectionThread = NULL;
HANDLE hIsWinXShown = NULL;
HANDLE hWinXThread = NULL;
HANDLE hExitSettingsMonitor = NULL;
HANDLE hSwsSettingsChanged = NULL;
HANDLE hSwsOpacityMaybeChanged = NULL;
BYTE* lpShouldDisplayCCButton = NULL;
@ -3948,92 +3946,159 @@ __declspec(dllexport) DWORD WINAPI main(
hSwsOpacityMaybeChanged = CreateEventW(NULL, FALSE, FALSE, NULL);
}
settings = calloc(10, sizeof(Setting));
settings[0].callback = LoadSettings;
settings[0].data = bIsExplorer;
settings[0].hEvent = NULL;
settings[0].hKey = NULL;
wcscpy_s(settings[0].name, MAX_PATH, TEXT(REGPATH));
settings[0].origin = HKEY_CURRENT_USER;
settings[1].callback = LoadSettings;
settings[1].data = bIsExplorer;
settings[1].hEvent = NULL;
settings[1].hKey = NULL;
wcscpy_s(settings[1].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage");
settings[1].origin = HKEY_CURRENT_USER;
settings[2].callback = SetEvent;
settings[2].data = hSwsSettingsChanged;
settings[2].hEvent = NULL;
settings[2].hKey = NULL;
wcscpy_s(settings[2].name, MAX_PATH, TEXT(REGPATH) L"\\sws");
settings[2].origin = HKEY_CURRENT_USER;
settings[3].callback = SetEvent;
settings[3].data = hSwsOpacityMaybeChanged;
settings[3].hEvent = NULL;
settings[3].hKey = NULL;
wcscpy_s(settings[3].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MultitaskingView\\AltTabViewHost");
settings[3].origin = HKEY_CURRENT_USER;
settings[4].callback = Explorer_RefreshUI;
settings[4].data = NULL;
settings[4].hEvent = NULL;
settings[4].hKey = NULL;
wcscpy_s(settings[4].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced");
settings[4].origin = HKEY_CURRENT_USER;
settings[5].callback = Explorer_RefreshUI;
settings[5].data = NULL;
settings[5].hEvent = NULL;
settings[5].hKey = NULL;
wcscpy_s(settings[5].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Search");
settings[5].origin = HKEY_CURRENT_USER;
settings[6].callback = Explorer_RefreshUI;
settings[6].data = NULL;
settings[6].hEvent = NULL;
settings[6].hKey = NULL;
wcscpy_s(settings[6].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\People");
settings[6].origin = HKEY_CURRENT_USER;
settings[7].callback = Explorer_RefreshUI;
settings[7].data = NULL;
settings[7].hEvent = NULL;
settings[7].hKey = NULL;
wcscpy_s(settings[7].name, MAX_PATH, L"SOFTWARE\\Microsoft\\TabletTip\\1.7");
settings[7].origin = HKEY_CURRENT_USER;
settings[8].callback = SetEvent;
settings[8].data = hSwsSettingsChanged;
settings[8].hEvent = NULL;
settings[8].hKey = NULL;
wcscpy_s(settings[8].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer");
settings[8].origin = HKEY_CURRENT_USER;
settings[9].callback = UpdateStartMenuPositioning;
settings[9].data = MAKELPARAM(FALSE, TRUE);
settings[9].hEvent = NULL;
settings[9].hKey = NULL;
wcscpy_s(settings[9].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced");
settings[9].origin = HKEY_CURRENT_USER;
settingsParams = calloc(1, sizeof(SettingsChangeParameters));
settingsParams->settings = settings;
settingsParams->size = bIsExplorer ? 10 : 1;
hExitSettingsMonitor = CreateEventW(NULL, FALSE, FALSE, NULL);
settingsParams->hExitEvent = hExitSettingsMonitor;
if (!hSettingsMonitorThread)
if (!settings && !settingsParams)
{
hSettingsMonitorThread = CreateThread(
0,
0,
MonitorSettings,
settingsParams,
0,
0
);
unsigned int numSettings = bIsExplorer ? 11 : 2;
settings = calloc(numSettings, sizeof(Setting));
if (settings)
{
unsigned int cs = 0;
if (cs < numSettings)
{
settings[cs].callback = NULL;
settings[cs].data = NULL;
settings[cs].hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
settings[cs].hKey = NULL;
ZeroMemory(settings[cs].name, MAX_PATH);
settings[cs].origin = NULL;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = LoadSettings;
settings[cs].data = bIsExplorer;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, TEXT(REGPATH));
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = LoadSettings;
settings[cs].data = bIsExplorer;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = SetEvent;
settings[cs].data = hSwsSettingsChanged;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, TEXT(REGPATH) L"\\sws");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = SetEvent;
settings[cs].data = hSwsOpacityMaybeChanged;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MultitaskingView\\AltTabViewHost");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = Explorer_RefreshUI;
settings[cs].data = NULL;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = Explorer_RefreshUI;
settings[cs].data = NULL;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Search");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = Explorer_RefreshUI;
settings[cs].data = NULL;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\People");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = Explorer_RefreshUI;
settings[cs].data = NULL;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\TabletTip\\1.7");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = SetEvent;
settings[cs].data = hSwsSettingsChanged;
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
if (cs < numSettings)
{
settings[cs].callback = UpdateStartMenuPositioning;
settings[cs].data = MAKELPARAM(FALSE, TRUE);
settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced");
settings[cs].origin = HKEY_CURRENT_USER;
cs++;
}
settingsParams = calloc(1, sizeof(SettingsChangeParameters));
if (settingsParams)
{
settingsParams->settings = settings;
InterlockedExchange(&(settingsParams->size), numSettings);
settingsParams->hThread = CreateThread(
0,
0,
MonitorSettings,
settingsParams,
0,
0
);
}
else
{
if (numSettings && settings[0].hEvent)
{
CloseHandle(settings[0].hEvent);
}
free(settings);
settings = NULL;
}
}
}
InjectBasicFunctions(bIsExplorer, TRUE);
@ -4699,6 +4764,14 @@ HRESULT WINAPI _DllRegisterServer()
wszFilename,
(wcslen(wszFilename) + 1) * sizeof(wchar_t)
);
dwLastError = RegSetValueExW(
hKey,
L"ThreadingModel",
0,
REG_SZ,
L"Apartment",
10 * sizeof(wchar_t)
);
RegCloseKey(hKey);
}
}
@ -4735,6 +4808,14 @@ HRESULT WINAPI _DllRegisterServer()
wszFilename,
(wcslen(wszFilename) + 1) * sizeof(wchar_t)
);
dwLastError = RegSetValueExW(
hKey,
L"ThreadingModel",
0,
REG_SZ,
L"Apartment",
10 * sizeof(wchar_t)
);
RegCloseKey(hKey);
}
}
@ -5213,6 +5294,25 @@ BOOL WINAPI DllMain(
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
if (!lpvReserved && bInstanced)
{
if (settings && settingsParams)
{
SetEvent(settings[0].hEvent);
if (WaitForSingleObject(settingsParams->hThread, 0) != WAIT_OBJECT_0)
{
while (InterlockedCompareExchange(&(settingsParams->size), 0, 0)) {};
}
CloseHandle(settings[0].hEvent);
CloseHandle(settingsParams->hThread);
free(settingsParams);
settingsParams = NULL;
free(settings);
settings = NULL;
}
InjectBasicFunctions(FALSE, FALSE);
bInstanced = FALSE;
}
break;
}
return TRUE;