212 lines
5.3 KiB
C
212 lines
5.3 KiB
C
/***************************************************************************
|
|
* dll.c
|
|
*
|
|
* Standard DLL entry-point functions
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "priv.h"
|
|
#include <ntverp.h>
|
|
|
|
//
|
|
// Downlevel delay load support (need to link to dload.lib)
|
|
//
|
|
#include <delayimp.h>
|
|
|
|
EXTERN_C
|
|
FARPROC
|
|
WINAPI
|
|
Downlevel_DelayLoadFailureHook(
|
|
UINT unReason,
|
|
PDelayLoadInfo pDelayInfo
|
|
);
|
|
|
|
PfnDliHook __pfnDliFailureHook = Downlevel_DelayLoadFailureHook;
|
|
HANDLE BaseDllHandle;
|
|
|
|
#define MLUI_INIT
|
|
#include <mluisupp.h>
|
|
|
|
BOOL g_bRunningOnNT = FALSE;
|
|
BOOL g_bRunningOnNT5OrHigher = FALSE;
|
|
BOOL g_bRunningOnMemphis = FALSE;
|
|
HINSTANCE g_hinst = NULL;
|
|
CRITICAL_SECTION g_csDll = {0};
|
|
DWORD g_TpsTls = (UINT)-1;
|
|
DWORD g_tlsThreadRef = (UINT)-1;
|
|
DWORD g_tlsOtherThreadsRef = (UINT)-1;
|
|
BOOL g_bDllTerminating = FALSE;
|
|
|
|
#ifdef DEBUG
|
|
//#define PROOFREAD_PARSES
|
|
#endif
|
|
|
|
#ifdef PROOFREAD_PARSES
|
|
enum
|
|
{
|
|
PP_COMPARE,
|
|
PP_ORIGINAL_ONLY,
|
|
PP_NEW_ONLY
|
|
};
|
|
|
|
|
|
DWORD g_dwProofMode = PP_COMPARE;
|
|
|
|
#endif // PROOFREAD_PARSES
|
|
|
|
void TermPalette();
|
|
void DeinitPUI();
|
|
void FreeViewStatePropertyBagCache();
|
|
void FreeDynamicLibraries();
|
|
STDAPI_(void) FreeGlobalSecurityAttributes();
|
|
STDAPI_(void) InitTimerQueue();
|
|
|
|
//
|
|
// Table of all window classes we register so we can unregister them
|
|
// at DLL unload.
|
|
//
|
|
// Since we are single-binary, we have to play it safe and do
|
|
// this cleanup (needed only on NT, but harmless on Win95).
|
|
//
|
|
const LPCTSTR c_rgszClasses[] = {
|
|
TEXT("WorkerA"), // util.cpp
|
|
TEXT("WorkerW"), // util.cpp
|
|
TEXT("WorkerW"), // util.cpp
|
|
};
|
|
|
|
//
|
|
// Global DCs used during mirroring an Icon.
|
|
//
|
|
HDC g_hdc = NULL, g_hdcMask = NULL;
|
|
BOOL g_bMirroredOS = FALSE;
|
|
|
|
STDAPI_(void) InitShellKeys(BOOL fInit);
|
|
#ifndef NO_ETW_TRACING
|
|
ULONG UnRegisterTracing();
|
|
#endif
|
|
|
|
BOOL APIENTRY DllMain(IN HANDLE hDll, IN DWORD dwReason, IN LPVOID lpReserved)
|
|
{
|
|
switch(dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
DisableThreadLibraryCalls(hDll);
|
|
|
|
#ifdef DEBUG
|
|
CcshellGetDebugFlags();
|
|
#endif
|
|
InitializeCriticalSection(&g_csDll); // for later use
|
|
|
|
BaseDllHandle = hDll; // for delayload
|
|
g_hinst = hDll;
|
|
MLLoadResources(g_hinst, TEXT("shlwaplc.dll"));
|
|
g_bRunningOnNT = IsOS(OS_NT);
|
|
g_bRunningOnNT5OrHigher = IsOS(OS_WIN2000ORGREATER);
|
|
g_bRunningOnMemphis = IsOS(OS_WIN98ORGREATER);
|
|
|
|
InitStopWatchMode(); // See if perf mode is enabled
|
|
InitTimerQueue();
|
|
|
|
// Check if we are running on a system that supports the mirroring APIs
|
|
// i.e. (NT5 or Memphis/BiDi)
|
|
//
|
|
g_bMirroredOS = IS_MIRRORING_ENABLED();
|
|
g_TpsTls = TlsAlloc();
|
|
g_tlsThreadRef = TlsAlloc();
|
|
g_tlsOtherThreadsRef = TlsAlloc();
|
|
|
|
InitShellKeys(TRUE);
|
|
|
|
#ifdef PROOFREAD_PARSES
|
|
{
|
|
DWORD dwSize = sizeof(g_dwProofMode);
|
|
if (ERROR_SUCCESS != SHGetValue( HKEY_CURRENT_USER,
|
|
TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
|
|
TEXT("Verify URLCombine"), NULL, &g_dwProofMode, &dwSize) ||
|
|
(g_dwProofMode > PP_NEW_ONLY))
|
|
{
|
|
g_dwProofMode = PP_COMPARE;
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
g_bDllTerminating = TRUE;
|
|
MLFreeResources(g_hinst);
|
|
if (lpReserved == NULL)
|
|
{
|
|
DeinitPUI(); // free up plug ui resource hinstance dpa table
|
|
FreeViewStatePropertyBagCache();
|
|
}
|
|
|
|
//
|
|
// Icon mirroring stuff (see mirror.c)
|
|
// Cleanup cached DCs. No need to synchronize the following section of
|
|
// code since it is only called in DLL_PROCESS_DETACH which is
|
|
// synchronized by the OS Loader.
|
|
//
|
|
if (g_bMirroredOS)
|
|
{
|
|
if (g_hdc)
|
|
DeleteDC(g_hdc);
|
|
|
|
if (g_hdcMask)
|
|
DeleteDC(g_hdcMask);
|
|
|
|
g_hdc = g_hdcMask = NULL;
|
|
}
|
|
|
|
FreeGlobalSecurityAttributes();
|
|
TermPalette();
|
|
if (StopWatchMode()) {
|
|
StopWatchFlush(); // Flush the performance timing data to disk
|
|
#ifndef NO_ETW_TRACING
|
|
// If any event tracing controls are enabled, this cleans them up.
|
|
UnRegisterTracing();
|
|
#endif
|
|
}
|
|
DeleteCriticalSection(&g_csDll);
|
|
|
|
if (lpReserved == NULL)
|
|
{
|
|
SHTerminateThreadPool();
|
|
SHUnregisterClasses(HINST_THISDLL, c_rgszClasses, ARRAYSIZE(c_rgszClasses));
|
|
#ifdef I_WANT_WIN95_TO_CRASH
|
|
// If you call FreeLibrary during PROCESS_ATTACH, Win95 will crash
|
|
FreeDynamicLibraries();
|
|
#endif
|
|
}
|
|
|
|
if (g_TpsTls != (UINT)-1)
|
|
TlsFree(g_TpsTls);
|
|
|
|
if (g_tlsThreadRef != (UINT)-1)
|
|
TlsFree(g_tlsThreadRef);
|
|
|
|
if (g_tlsOtherThreadsRef != (UINT)-1)
|
|
TlsFree(g_tlsOtherThreadsRef);
|
|
|
|
InitShellKeys(FALSE);
|
|
|
|
break;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
ASSERT(0); // We shouldn't get these because we called DisableThreadLibraryCalls().
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// DllGetVersion
|
|
//
|
|
// All we have to do is declare this puppy and CCDllGetVersion does the rest
|
|
//
|
|
DLLVER_SINGLEBINARY(VER_PRODUCTVERSION_DW, VER_PRODUCTBUILD_QFE);
|