Browse Source

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
pull/400/head 22000.318.36.0_04616ce
Valentin Radu 4 years ago
parent
commit
04616cee16
  1. 8
      CHANGELOG.md
  2. 8
      ExplorerPatcher/ExplorerPatcher.rc
  3. 152
      ExplorerPatcher/SettingsMonitor.c
  4. 3
      ExplorerPatcher/SettingsMonitor.h
  5. 276
      ExplorerPatcher/dllmain.c

8
CHANGELOG.md

@ -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.

8
ExplorerPatcher/ExplorerPatcher.rc

@ -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"

152
ExplorerPatcher/SettingsMonitor.c

@ -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;
}
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 (i == 0)
{
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;
}
} }
if (RegNotifyChangeKeyValue( DWORD dwRes = WaitForMultipleObjects(
params->settings[i].hKey, params->size,
handles,
FALSE, FALSE,
REG_NOTIFY_CHANGE_LAST_SET, INFINITE
params->settings[i].hEvent, );
TRUE if (dwRes != WAIT_FAILED)
) != 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; 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);
}
}
} }
for (unsigned int j = 0; j < params->size; ++j) free(handles);
for (unsigned int i = 1; i < params->size; ++i)
{ {
if (WaitForSingleObject(handles[j], 0) == WAIT_OBJECT_0) if (params->settings[i].hEvent)
{
CloseHandle(params->settings[i].hEvent);
}
if (params->settings[i].hKey)
{ {
params->settings[j].callback(params->settings[j].data); 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);
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;
} }

3
ExplorerPatcher/SettingsMonitor.h

@ -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

276
ExplorerPatcher/dllmain.c

@ -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; unsigned int numSettings = bIsExplorer ? 11 : 2;
settings[0].hEvent = NULL; settings = calloc(numSettings, sizeof(Setting));
settings[0].hKey = NULL; if (settings)
wcscpy_s(settings[0].name, MAX_PATH, TEXT(REGPATH)); {
settings[0].origin = HKEY_CURRENT_USER; unsigned int cs = 0;
settings[1].callback = LoadSettings; if (cs < numSettings)
settings[1].data = bIsExplorer; {
settings[1].hEvent = NULL; settings[cs].callback = NULL;
settings[1].hKey = NULL; settings[cs].data = NULL;
wcscpy_s(settings[1].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage"); settings[cs].hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
settings[1].origin = HKEY_CURRENT_USER; settings[cs].hKey = NULL;
ZeroMemory(settings[cs].name, MAX_PATH);
settings[2].callback = SetEvent; settings[cs].origin = NULL;
settings[2].data = hSwsSettingsChanged; cs++;
settings[2].hEvent = NULL; }
settings[2].hKey = NULL;
wcscpy_s(settings[2].name, MAX_PATH, TEXT(REGPATH) L"\\sws"); if (cs < numSettings)
settings[2].origin = HKEY_CURRENT_USER; {
settings[cs].callback = LoadSettings;
settings[3].callback = SetEvent; settings[cs].data = bIsExplorer;
settings[3].data = hSwsOpacityMaybeChanged; settings[cs].hEvent = NULL;
settings[3].hEvent = NULL; settings[cs].hKey = NULL;
settings[3].hKey = NULL; wcscpy_s(settings[cs].name, MAX_PATH, TEXT(REGPATH));
wcscpy_s(settings[3].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MultitaskingView\\AltTabViewHost"); settings[cs].origin = HKEY_CURRENT_USER;
settings[3].origin = HKEY_CURRENT_USER; cs++;
}
settings[4].callback = Explorer_RefreshUI;
settings[4].data = NULL; if (cs < numSettings)
settings[4].hEvent = NULL; {
settings[4].hKey = NULL; settings[cs].callback = LoadSettings;
wcscpy_s(settings[4].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"); settings[cs].data = bIsExplorer;
settings[4].origin = HKEY_CURRENT_USER; settings[cs].hEvent = NULL;
settings[cs].hKey = NULL;
settings[5].callback = Explorer_RefreshUI; wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage");
settings[5].data = NULL; settings[cs].origin = HKEY_CURRENT_USER;
settings[5].hEvent = NULL; cs++;
settings[5].hKey = NULL; }
wcscpy_s(settings[5].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Search");
settings[5].origin = HKEY_CURRENT_USER; if (cs < numSettings)
{
settings[6].callback = Explorer_RefreshUI; settings[cs].callback = SetEvent;
settings[6].data = NULL; settings[cs].data = hSwsSettingsChanged;
settings[6].hEvent = NULL; settings[cs].hEvent = NULL;
settings[6].hKey = NULL; settings[cs].hKey = NULL;
wcscpy_s(settings[6].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\People"); wcscpy_s(settings[cs].name, MAX_PATH, TEXT(REGPATH) L"\\sws");
settings[6].origin = HKEY_CURRENT_USER; settings[cs].origin = HKEY_CURRENT_USER;
cs++;
settings[7].callback = Explorer_RefreshUI; }
settings[7].data = NULL;
settings[7].hEvent = NULL; if (cs < numSettings)
settings[7].hKey = NULL; {
wcscpy_s(settings[7].name, MAX_PATH, L"SOFTWARE\\Microsoft\\TabletTip\\1.7"); settings[cs].callback = SetEvent;
settings[7].origin = HKEY_CURRENT_USER; settings[cs].data = hSwsOpacityMaybeChanged;
settings[cs].hEvent = NULL;
settings[8].callback = SetEvent; settings[cs].hKey = NULL;
settings[8].data = hSwsSettingsChanged; wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MultitaskingView\\AltTabViewHost");
settings[8].hEvent = NULL; settings[cs].origin = HKEY_CURRENT_USER;
settings[8].hKey = NULL; cs++;
wcscpy_s(settings[8].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer"); }
settings[8].origin = HKEY_CURRENT_USER;
if (cs < numSettings)
settings[9].callback = UpdateStartMenuPositioning; {
settings[9].data = MAKELPARAM(FALSE, TRUE); settings[cs].callback = Explorer_RefreshUI;
settings[9].hEvent = NULL; settings[cs].data = NULL;
settings[9].hKey = NULL; settings[cs].hEvent = NULL;
wcscpy_s(settings[9].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"); settings[cs].hKey = NULL;
settings[9].origin = HKEY_CURRENT_USER; wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced");
settings[cs].origin = HKEY_CURRENT_USER;
settingsParams = calloc(1, sizeof(SettingsChangeParameters)); cs++;
settingsParams->settings = settings; }
settingsParams->size = bIsExplorer ? 10 : 1;
hExitSettingsMonitor = CreateEventW(NULL, FALSE, FALSE, NULL); if (cs < numSettings)
settingsParams->hExitEvent = hExitSettingsMonitor; {
if (!hSettingsMonitorThread) settings[cs].callback = Explorer_RefreshUI;
{ settings[cs].data = NULL;
hSettingsMonitorThread = CreateThread( settings[cs].hEvent = NULL;
0, settings[cs].hKey = NULL;
0, wcscpy_s(settings[cs].name, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Search");
MonitorSettings, settings[cs].origin = HKEY_CURRENT_USER;
settingsParams, cs++;
0, }
0
); 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;

Loading…
Cancel
Save