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. 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 ## 22000.318.35
Tested on build 22000.318. Tested on build 22000.318.

View File

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

View File

@ -3,83 +3,113 @@
DWORD WINAPI MonitorSettings(SettingsChangeParameters* params) DWORD WINAPI MonitorSettings(SettingsChangeParameters* params)
{ {
BOOL bShouldExit = FALSE; BOOL bShouldExit = FALSE;
HANDLE* handles = NULL;
printf("[SettingsMonitor] Started %p\n", params->settings[0].hEvent);
while (TRUE) while (TRUE)
{ {
HANDLE* handles = malloc(sizeof(HANDLE) * (params->size + 1)); handles = calloc(sizeof(HANDLE), params->size);
if (!handles) if (handles)
{ {
return 0; for (unsigned int i = 0; i < params->size; ++i)
}
for (unsigned int i = 0; i < params->size; ++i)
{
params->settings[i].hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!params->settings[i].hEvent)
{ {
return 0; if (i == 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)
{ {
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); else
for (unsigned int i = 0; i < params->size; ++i)
{ {
CloseHandle(params->settings[i].hEvent); InterlockedExchange(&(params->size), 0);
RegCloseKey(params->settings[i].hKey); return 0;
}
if (bShouldExit)
{
break;
} }
} }
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 <Windows.h>
#include <Shlwapi.h> #include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib") #pragma comment(lib, "Shlwapi.lib")
#include <stdio.h>
typedef struct _Setting typedef struct _Setting
{ {
@ -17,7 +18,7 @@ typedef struct _SettingsChangeParameters
{ {
Setting* settings; Setting* settings;
DWORD size; DWORD size;
HANDLE hExitEvent; HANDLE hThread;
} SettingsChangeParameters; } SettingsChangeParameters;
DWORD WINAPI MonitorSettings(SettingsChangeParameters*); DWORD WINAPI MonitorSettings(SettingsChangeParameters*);
#endif #endif

View File

@ -70,11 +70,9 @@ DWORD bTaskbarMonitorOverride = 0;
DWORD dwIMEStyle = 0; DWORD dwIMEStyle = 0;
DWORD dwTaskbarAl = 0; DWORD dwTaskbarAl = 0;
HMODULE hModule = NULL; HMODULE hModule = NULL;
HANDLE hSettingsMonitorThread = NULL;
HANDLE hDelayedInjectionThread = NULL; HANDLE hDelayedInjectionThread = NULL;
HANDLE hIsWinXShown = NULL; HANDLE hIsWinXShown = NULL;
HANDLE hWinXThread = NULL; HANDLE hWinXThread = NULL;
HANDLE hExitSettingsMonitor = NULL;
HANDLE hSwsSettingsChanged = NULL; HANDLE hSwsSettingsChanged = NULL;
HANDLE hSwsOpacityMaybeChanged = NULL; HANDLE hSwsOpacityMaybeChanged = NULL;
BYTE* lpShouldDisplayCCButton = NULL; BYTE* lpShouldDisplayCCButton = NULL;
@ -3948,92 +3946,159 @@ __declspec(dllexport) DWORD WINAPI main(
hSwsOpacityMaybeChanged = CreateEventW(NULL, FALSE, FALSE, NULL); hSwsOpacityMaybeChanged = CreateEventW(NULL, FALSE, FALSE, NULL);
} }
settings = calloc(10, sizeof(Setting)); if (!settings && !settingsParams)
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)
{ {
hSettingsMonitorThread = CreateThread( unsigned int numSettings = bIsExplorer ? 11 : 2;
0, settings = calloc(numSettings, sizeof(Setting));
0, if (settings)
MonitorSettings, {
settingsParams, unsigned int cs = 0;
0,
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); InjectBasicFunctions(bIsExplorer, TRUE);
@ -4699,6 +4764,14 @@ HRESULT WINAPI _DllRegisterServer()
wszFilename, wszFilename,
(wcslen(wszFilename) + 1) * sizeof(wchar_t) (wcslen(wszFilename) + 1) * sizeof(wchar_t)
); );
dwLastError = RegSetValueExW(
hKey,
L"ThreadingModel",
0,
REG_SZ,
L"Apartment",
10 * sizeof(wchar_t)
);
RegCloseKey(hKey); RegCloseKey(hKey);
} }
} }
@ -4735,6 +4808,14 @@ HRESULT WINAPI _DllRegisterServer()
wszFilename, wszFilename,
(wcslen(wszFilename) + 1) * sizeof(wchar_t) (wcslen(wszFilename) + 1) * sizeof(wchar_t)
); );
dwLastError = RegSetValueExW(
hKey,
L"ThreadingModel",
0,
REG_SZ,
L"Apartment",
10 * sizeof(wchar_t)
);
RegCloseKey(hKey); RegCloseKey(hKey);
} }
} }
@ -5213,6 +5294,25 @@ BOOL WINAPI DllMain(
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
break; break;
case DLL_PROCESS_DETACH: 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; break;
} }
return TRUE; return TRUE;