#include "shellprv.h" #pragma hdrstop #include "copy.h" void PSCache_Term(); void DAD_ThreadDetach(void); void DAD_ProcessDetach(void); void DragDrop_Term(BOOL fProcessDetach); void TaskMem_Term(void); // // Per-instance Global data (16-bit/32-bit common) // #pragma data_seg(DATASEG_PERINSTANCE) HINSTANCE g_hinst = NULL; #pragma data_seg() #ifdef DEBUG #ifdef WINNT #include extern UINT wDebugMask; #endif #endif // // NOTE these are the size of the icons in our ImageList, not the system // icon size. // int g_cxIcon = 0; int g_cyIcon = 0; int g_cxSmIcon = 0; int g_cySmIcon = 0; // // This is our process's heap, which the HeapAlloc functions will use // HANDLE g_hProcessHeap = NULL; COLORREF g_crAltColor = RGB(0,0,255); LPTSTR g_pszOutOfMemory = NULL; BOOL _GetOutOfMemoryString() { TCHAR szMessage[256]; BOOL fSuccess = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ERROR_OUTOFMEMORY, 0, szMessage, ARRAYSIZE(szMessage), NULL); if (fSuccess) { UINT cch = (lstrlen(szMessage)+1); g_pszOutOfMemory = Alloc(cch * SIZEOF(TCHAR)); if (g_pszOutOfMemory) { lstrcpyn(g_pszOutOfMemory, szMessage, cch); } else { Assert(0); fSuccess = FALSE; } } return fSuccess; } #ifdef WINNT // // Initializes the OpenIfJP EA // BOOL PASCAL SHInitializeOpenIfJpEA() { pOpenIfJPEa->NextEntryOffset = 0; pOpenIfJPEa->Flags = 0; pOpenIfJPEa->EaNameLength = lstrlenA(EA_NAME_OPENIFJP); pOpenIfJPEa->EaValueLength = 0; return (lstrcpyA(pOpenIfJPEa->EaName, EA_NAME_OPENIFJP) != NULL); } #endif // // Initializes global shared data in shell32.dll // make this as small as possible since it runs every time an app loads // BOOL _Initialize_SharedData(void) { if (!_GetOutOfMemoryString()) return FALSE; if (!SHChangeNotifyInit()) return FALSE; #ifdef WINNT // // Initialize the EA if (!SHInitializeOpenIfJpEA()) return FALSE; #endif return TRUE; } // // Clean up global shared data // BOOL _Terminate_SharedData(BOOL bLastTerm) { SHChangeNotifyTerminate(bLastTerm); // Only do the rest of this stuff on the last detach if (!bLastTerm) return(TRUE); FileIconTerm(); SpecialFolderIDTerminate(); BBTerminate(); return TRUE; } // // Per-instance Global data (32-bit only) // #pragma data_seg(DATASEG_PERINSTANCE) HINSTANCE s_hmodShare = NULL; BOOL s_fShareLoaded = FALSE; PFNISPATHSHARED g_pfnIsPathShared = NULL; HKEY g_hkcrCLSID = NULL; // HKEY_CLASSES_ROOT\CLSID HKEY g_hkcuExplorer = NULL; // caching for HKEY_CLASSES_ROOT\...\Explorer HKEY g_hklmExplorer = NULL; // caching for HKEY_LOCAL_MACHINE\...\Explorer #ifdef WINNT HKEY g_hklmApprovedExt = NULL; #endif // Version page stuff HINSTANCE s_hmodVersion = NULL; PFNVERQUERYVALUE g_pfnVerQueryValue = NULL; PFNVERQUERYVALUEINDEX g_pfnVerQueryValueIndex = NULL; PFNGETFILEVERSIONINFOSIZE g_pfnGetFileVersionInfoSize = NULL; PFNGETFILEVERSIONINFO g_pfnGetFileVersionInfo = NULL; #ifdef WINNT HINSTANCE s_hmodKernel32 = NULL; #endif PFNVERLANGUAGENAME g_pfnVerLanguageName = NULL; // Comdlg32 stuff HINSTANCE s_hmodComdlg32 = NULL; PFNGETOPENFILENAME g_pfnGetOpenFileName = NULL; // Winspool stuff HINSTANCE s_hmodWinspool = NULL; PFNADDPORT g_pfnAddPort = NULL; PFNCLOSEPRINTER g_pfnClosePrinter = NULL; PFNCONFIGUREPORT g_pfnConfigurePort = NULL; PFNDELETEPORT g_pfnDeletePort = NULL; PFNDELETEPRINTER g_pfnDeletePrinter = NULL; PFNDELETEPRINTERDRIVER g_pfnDeletePrinterDriver = NULL; PFNDEVICECAPABILITIES g_pfnDeviceCapabilities = NULL; PFNENUMJOBS g_pfnEnumJobs = NULL; PFNENUMMONITORS g_pfnEnumMonitors = NULL; PFNENUMPORTS g_pfnEnumPorts = NULL; PFNENUMPRINTPROCESSORDATATYPES g_pfnEnumPrintProcessorDataTypes = NULL; PFNENUMPRINTPROCESSORS g_pfnEnumPrintProcessors = NULL; PFNENUMPRINTERDRIVERS g_pfnEnumPrinterDrivers = NULL; PFNENUMPRINTERS g_pfnEnumPrinters = NULL; PFNENUMPRINTERPROPERTYSHEETS g_pfnEnumPrinterPropertySheets = NULL; PFNGETPRINTER g_pfnGetPrinter = NULL; PFNGETPRINTERDRIVER g_pfnGetPrinterDriver = NULL; PFNOPENPRINTER g_pfnOpenPrinter = NULL; PFNPRINTERPROPERTIES g_pfnPrinterProperties = NULL; PFNSETJOB g_pfnSetJob = NULL; PFNSETPRINTER g_pfnSetPrinter = NULL; #ifdef WINNT // PRINTQ // PrintUI stuff HINSTANCE s_hmodPrintUI = NULL; PFNQUEUECREATE g_pfnQueueCreate = NULL; PFNPRINTERPROPPAGES g_pfnPrinterPropPages = NULL; PFNSERVERPROPPAGES g_pfnServerPropPages = NULL; PFNPRINTERSETUP g_pfnPrinterSetup = NULL; PFNDOCUMENTDEFAULTS g_pfnDocumentDefaults = NULL; #endif #ifdef PRN_FOLDERDATA PFNFOLDERREGISTER g_pfnFolderRegister = NULL; PFNFOLDERUNREGISTER g_pfnFolderUnregister = NULL; PFNFOLDERENUMPRINTERS g_pfnFolderEnumPrinters = NULL; PFNFOLDERREFRESH g_pfnFolderRefresh = NULL; PFNFOLDERGETPRINTER g_pfnFolderGetPrinter = NULL; #endif // Linkinfo stuff HINSTANCE s_hmodLinkInfo = NULL; PFNCREATELINKINFO g_pfnCreateLinkInfo = NULL; PFNDESTROYLINKINFO g_pfnDestroyLinkInfo = NULL; PFNRESOLVELINKINFO g_pfnResolveLinkInfo = NULL; PFNGETLINKINFODATA g_pfnGetLinkInfoData = NULL; #ifdef DEBUG DWORD g_CriticalSectionOwner=0; int g_CriticalSectionCount=0; #endif #ifdef WINNT // Useful EA Buffer for opening Junction Points. (used in fstreex.c) CHAR EaBuffer[ SIZEOF(FILE_FULL_EA_INFORMATION) + SIZEOF(EA_NAME_OPENIFJP) ]; PFILE_FULL_EA_INFORMATION pOpenIfJPEa = (PFILE_FULL_EA_INFORMATION) EaBuffer; ULONG cbOpenIfJPEa = SIZEOF(EaBuffer); #endif #pragma data_seg() // // IsDllLoaded // // reload (iff needed) a DLL that should already be loaded // in our context. // // if we are coming up from a 16->32 thunk. it is possible that a module // will not be loaded in this context, so we will check for this and reload it. // // when will this happen: // // a 16bit app does not link to SHELL.DLL but just calls it. SHELL32.DLL // will not be loaded in the correct context and needs to be re-loaded. // // when a 16bit app exits Kernel32 may free a DLL we loaded, we still think // the module is loaded because we have a global variable in our INSTANCE // data that contains the HMODULE, because all Win16 apps share the same // instance data we get confused. // // ** all the above is total garbage in the new Win16 proccess model // ** Win16 apps now have their own address space, so things are happy // ** again. IsDllLoaded() is just mapped to a single compare (in shellprv.h) // ** but in DEBUG we still call this function to get extra debug output. // #ifdef DEBUG LPTSTR GetCurrentApp() { static TCHAR ach[128]; GetModuleFileName(GetModuleHandle(NULL), ach, ARRAYSIZE(ach)); return PathFindFileName(ach); } BOOL IsDllLoaded(HMODULE hDll, LPCTSTR pszDll) { // // if we never have loaded the module, load it for the first time. // this is normal. // if (hDll == NULL) { DebugMsg(DM_WARNING, TEXT("SHELL32: loading %s.dll for %s"), pszDll, GetCurrentApp()); return FALSE; } // // if we have loaded this DLL before, it may have been freed or we need // to reload it into this proccess context. This is a wierd case // that happens because all Win16 apps share the same address space // but are treated as different processes. // // *** with new Win16 proccess model, this should never never happen. // if (GetModuleHandle(pszDll) == NULL) { DebugMsg(DM_ERROR, TEXT("SHELL32: %s.dll is not loaded into process %08X (%s)"), pszDll, GetModuleHandle(NULL), GetCurrentApp()); Assert(FALSE); return FALSE; } return TRUE; } #else #define GetCurrentApp() NULL #endif // // Shared Global data (32-bit only) // BOOL g_cProcesses = 0; CRITICAL_SECTION g_csShell = {0}; CRITICAL_SECTION g_csPrinters = {0}; const TCHAR c_szNetworkSharingHandler[] = TEXT("Network\\SharingHandler"); #ifdef UNICODE const char c_szPathIsShared[] = "IsPathSharedW"; // Win NT UNICODE #else // UNICODE #ifdef WINNT const char c_szPathIsShared[] = "IsPathSharedA"; // Win NT Ansi #else // WINNT const char c_szPathIsShared[] = "IsPathShared"; // Win 95 #endif // WINNT #endif // UNICODE BOOL ShareDLL_Init(void) { TCHAR szPath[MAX_PATH]; LONG cb; //BUGBUG!!! what if share.dll is gone? // See if we have already tried to load this in this context if (s_fShareLoaded) return(TRUE); s_fShareLoaded = TRUE; szPath[0] = 0; cb = SIZEOF(szPath); RegQueryValue(HKEY_CLASSES_ROOT, c_szNetworkSharingHandler, szPath, &cb); if (szPath[0]) { s_hmodShare = LoadLibrary(szPath); if (ISVALIDHINSTANCE(s_hmodShare)) { g_pfnIsPathShared = (PFNISPATHSHARED)GetProcAddress(s_hmodShare, c_szPathIsShared); } } return TRUE; } void ShareDLL_Term() { if (ISVALIDHINSTANCE(s_hmodShare)) { FreeLibrary(s_hmodShare); s_hmodShare = NULL; g_pfnIsPathShared = NULL; } } const TCHAR c_szVersionDll[] = TEXT("version.dll"); #ifdef WINNT const TCHAR c_szKernel32Dll[] = TEXT("kernel32.dll"); #endif BOOL VersionDLL_Init(void) { #ifdef WINNT if ( IsDllLoaded(s_hmodVersion, TEXT("version")) && IsDllLoaded(s_hmodKernel32, TEXT("kernel32"))) #else if (IsDllLoaded(s_hmodVersion, TEXT("version"))) #endif return(TRUE); // already loaded. s_hmodVersion = LoadLibrary(c_szVersionDll); if (!ISVALIDHINSTANCE(s_hmodVersion)) { s_hmodVersion = NULL; // make sure it is NULL return(FALSE); } #ifdef WINNT s_hmodKernel32 = LoadLibrary(c_szKernel32Dll); if (!ISVALIDHINSTANCE(s_hmodKernel32)) { s_hmodKernel32 = NULL; // make sure it is NULL return(FALSE); } #endif #ifdef UNICODE g_pfnVerQueryValue = (PFNVERQUERYVALUE)GetProcAddress(s_hmodVersion, "VerQueryValueW"); g_pfnVerQueryValueIndex = (PFNVERQUERYVALUEINDEX)GetProcAddress(s_hmodVersion, "VerQueryValueIndexW"); g_pfnGetFileVersionInfoSize = (PFNGETFILEVERSIONINFOSIZE)GetProcAddress(s_hmodVersion, "GetFileVersionInfoSizeW"); g_pfnGetFileVersionInfo = (PFNGETFILEVERSIONINFO)GetProcAddress(s_hmodVersion, "GetFileVersionInfoW"); g_pfnVerLanguageName = (PFNVERLANGUAGENAME)GetProcAddress(s_hmodVersion, "VerLanguageNameW"); #else g_pfnVerQueryValue = (PFNVERQUERYVALUE)GetProcAddress(s_hmodVersion, "VerQueryValueA"); g_pfnVerQueryValueIndex = (PFNVERQUERYVALUEINDEX)GetProcAddress(s_hmodVersion, "VerQueryValueIndexA"); g_pfnGetFileVersionInfoSize = (PFNGETFILEVERSIONINFOSIZE)GetProcAddress(s_hmodVersion, "GetFileVersionInfoSizeA"); g_pfnGetFileVersionInfo = (PFNGETFILEVERSIONINFO)GetProcAddress(s_hmodVersion, "GetFileVersionInfoA"); g_pfnVerLanguageName = (PFNVERLANGUAGENAME)GetProcAddress(s_hmodVersion, "VerLanguageNameA"); #endif if (!g_pfnVerQueryValue || !g_pfnGetFileVersionInfoSize || !g_pfnGetFileVersionInfo || ! g_pfnVerLanguageName) { // BUGBUG: The next call to VersionDLL_Init will incorrectly return TRUE Assert(FALSE); return(FALSE); } return TRUE; } void VersionDLL_Term() { if (ISVALIDHINSTANCE(s_hmodVersion)) { FreeLibrary(s_hmodVersion); s_hmodVersion = NULL; g_pfnVerQueryValue = NULL; g_pfnGetFileVersionInfoSize = NULL; g_pfnGetFileVersionInfo = NULL; } } void Comdlg32DLL_Term() { if (ISVALIDHINSTANCE(s_hmodComdlg32)) { FreeLibrary(s_hmodComdlg32); s_hmodComdlg32 = NULL; g_pfnGetOpenFileName = NULL; } } BOOL Comdlg32DLL_Init(void) { if (IsDllLoaded(s_hmodComdlg32, TEXT("comdlg32"))) return(TRUE); // already loaded. s_hmodComdlg32 = LoadLibrary(TEXT("comdlg32.dll")); if (!ISVALIDHINSTANCE(s_hmodComdlg32)) { s_hmodComdlg32 = NULL; // make sure it is NULL return(FALSE); } #ifdef UNICODE g_pfnGetOpenFileName = (PFNGETOPENFILENAME)GetProcAddress(s_hmodComdlg32, "GetOpenFileNameW"); #else g_pfnGetOpenFileName = (PFNGETOPENFILENAME)GetProcAddress(s_hmodComdlg32, "GetOpenFileNameA"); #endif if (!g_pfnGetOpenFileName) { // BUGBUG: The next call to Comdlg32_Init will incorrectly return TRUE Assert(FALSE); Comdlg32DLL_Term(); // Free our usage of the DLL for now... return(FALSE); } return TRUE; } BOOL WinspoolDLL_Init(void) { if (s_hmodWinspool != NULL) return(TRUE); // already loaded. s_hmodWinspool = LoadLibrary(TEXT("winspool.drv")); if (!ISVALIDHINSTANCE(s_hmodWinspool)) { s_hmodWinspool = NULL; // make sure it is NULL return(FALSE); } #ifdef UNICODE g_pfnAddPort = (PFNADDPORT)GetProcAddress(s_hmodWinspool, "AddPortW"); g_pfnClosePrinter = (PFNCLOSEPRINTER)GetProcAddress(s_hmodWinspool, "ClosePrinter"); g_pfnConfigurePort = (PFNCONFIGUREPORT)GetProcAddress(s_hmodWinspool, "ConfigurePortW"); g_pfnDeletePort = (PFNADDPORT)GetProcAddress(s_hmodWinspool, "DeletePortW"); g_pfnDeletePrinter = (PFNDELETEPRINTER)GetProcAddress(s_hmodWinspool, "DeletePrinter"); g_pfnDeletePrinterDriver = (PFNDELETEPRINTERDRIVER)GetProcAddress(s_hmodWinspool, "DeletePrinterDriverW"); g_pfnDeviceCapabilities = (PFNDEVICECAPABILITIES)GetProcAddress(s_hmodWinspool, "DeviceCapabilitiesW"); g_pfnEnumJobs = (PFNENUMJOBS)GetProcAddress(s_hmodWinspool, "EnumJobsW"); g_pfnEnumMonitors = (PFNENUMPORTS)GetProcAddress(s_hmodWinspool, "EnumMonitorsW"); g_pfnEnumPorts = (PFNENUMPORTS)GetProcAddress(s_hmodWinspool, "EnumPortsW"); g_pfnEnumPrintProcessorDataTypes = (PFNENUMPRINTPROCESSORDATATYPES)GetProcAddress(s_hmodWinspool, "EnumPrintProcessorDatatypesW"); g_pfnEnumPrintProcessors = (PFNENUMPRINTPROCESSORS)GetProcAddress(s_hmodWinspool, "EnumPrintProcessorsW"); g_pfnEnumPrinterDrivers = (PFNENUMPRINTERDRIVERS)GetProcAddress(s_hmodWinspool, "EnumPrinterDriversW"); g_pfnEnumPrinters = (PFNENUMPRINTERS)GetProcAddress(s_hmodWinspool, "EnumPrintersW"); g_pfnEnumPrinterPropertySheets = (PFNENUMPRINTERPROPERTYSHEETS)GetProcAddress(s_hmodWinspool, (LPCSTR)MAKEINTRESOURCE(ENUMPRINTERPROPERTYSHEETS_ORD)); g_pfnGetPrinter = (PFNGETPRINTER)GetProcAddress(s_hmodWinspool, "GetPrinterW"); g_pfnGetPrinterDriver = (PFNGETPRINTERDRIVER)GetProcAddress(s_hmodWinspool, "GetPrinterDriverW"); g_pfnOpenPrinter = (PFNOPENPRINTER)GetProcAddress(s_hmodWinspool, "OpenPrinterW"); g_pfnPrinterProperties = (PFNPRINTERPROPERTIES)GetProcAddress(s_hmodWinspool, "PrinterProperties"); g_pfnSetJob = (PFNSETJOB)GetProcAddress(s_hmodWinspool, "SetJobW"); g_pfnSetPrinter = (PFNSETPRINTER)GetProcAddress(s_hmodWinspool, "SetPrinterW"); #else g_pfnAddPort = (PFNADDPORT)GetProcAddress(s_hmodWinspool, "AddPortA"); g_pfnClosePrinter = (PFNCLOSEPRINTER)GetProcAddress(s_hmodWinspool, "ClosePrinter"); g_pfnConfigurePort = (PFNCONFIGUREPORT)GetProcAddress(s_hmodWinspool, "ConfigurePortA"); g_pfnDeletePort = (PFNADDPORT)GetProcAddress(s_hmodWinspool, "DeletePortA"); g_pfnDeletePrinter = (PFNDELETEPRINTER)GetProcAddress(s_hmodWinspool, "DeletePrinter"); g_pfnDeletePrinterDriver = (PFNDELETEPRINTERDRIVER)GetProcAddress(s_hmodWinspool, "DeletePrinterDriverA"); g_pfnDeviceCapabilities = (PFNDEVICECAPABILITIES)GetProcAddress(s_hmodWinspool, "DeviceCapabilitiesA"); g_pfnEnumJobs = (PFNENUMJOBS)GetProcAddress(s_hmodWinspool, "EnumJobsA"); g_pfnEnumMonitors = (PFNENUMPORTS)GetProcAddress(s_hmodWinspool, "EnumMonitorsA"); g_pfnEnumPorts = (PFNENUMPORTS)GetProcAddress(s_hmodWinspool, "EnumPortsA"); g_pfnEnumPrintProcessorDataTypes = (PFNENUMPRINTPROCESSORDATATYPES)GetProcAddress(s_hmodWinspool, "EnumPrintProcessorDatatypesA"); g_pfnEnumPrintProcessors = (PFNENUMPRINTPROCESSORS)GetProcAddress(s_hmodWinspool, "EnumPrintProcessorsA"); g_pfnEnumPrinterDrivers = (PFNENUMPRINTERDRIVERS)GetProcAddress(s_hmodWinspool, "EnumPrinterDriversA"); g_pfnEnumPrinters = (PFNENUMPRINTERS)GetProcAddress(s_hmodWinspool, "EnumPrintersA"); g_pfnEnumPrinterPropertySheets = (PFNENUMPRINTERPROPERTYSHEETS)GetProcAddress(s_hmodWinspool, MAKEINTRESOURCE(ENUMPRINTERPROPERTYSHEETS_ORD)); g_pfnGetPrinter = (PFNGETPRINTER)GetProcAddress(s_hmodWinspool, "GetPrinterA"); g_pfnGetPrinterDriver = (PFNGETPRINTERDRIVER)GetProcAddress(s_hmodWinspool, "GetPrinterDriverA"); g_pfnOpenPrinter = (PFNOPENPRINTER)GetProcAddress(s_hmodWinspool, "OpenPrinterA"); g_pfnPrinterProperties = (PFNPRINTERPROPERTIES)GetProcAddress(s_hmodWinspool, "PrinterProperties"); g_pfnSetJob = (PFNSETJOB)GetProcAddress(s_hmodWinspool, "SetJobA"); g_pfnSetPrinter = (PFNSETPRINTER)GetProcAddress(s_hmodWinspool, "SetPrinterA"); #endif if (!g_pfnAddPort || !g_pfnClosePrinter || !g_pfnDeletePort || !g_pfnDeletePrinter || !g_pfnDeviceCapabilities || !g_pfnEnumJobs || !g_pfnDeletePrinterDriver || !g_pfnConfigurePort || !g_pfnEnumMonitors || !g_pfnEnumPorts || !g_pfnEnumPrintProcessorDataTypes || !g_pfnEnumPrintProcessors || !g_pfnEnumPrinterDrivers || !g_pfnEnumPrinters || !g_pfnEnumPrinterPropertySheets || !g_pfnGetPrinter || !g_pfnGetPrinterDriver || !g_pfnOpenPrinter || !g_pfnPrinterProperties || !g_pfnSetJob || !g_pfnSetPrinter) { // BUGBUG: The next call to WinspoolDLL_Init will incorrectly return TRUE Assert(FALSE); return(FALSE); } return(TRUE); } void WinspoolDLL_Term() { if (ISVALIDHINSTANCE(s_hmodWinspool)) { FreeLibrary(s_hmodWinspool); s_hmodWinspool = NULL; g_pfnAddPort = NULL; g_pfnClosePrinter = NULL; g_pfnConfigurePort = NULL; g_pfnDeletePort = NULL; g_pfnDeletePrinter = NULL; g_pfnDeletePrinterDriver = NULL; g_pfnDeviceCapabilities = NULL; g_pfnEnumJobs = NULL; g_pfnEnumMonitors = NULL; g_pfnEnumPorts = NULL; g_pfnEnumPrintProcessorDataTypes = NULL; g_pfnEnumPrintProcessors = NULL; g_pfnEnumPrinterDrivers = NULL; g_pfnEnumPrinters = NULL; g_pfnGetPrinter = NULL; g_pfnGetPrinterDriver = NULL; g_pfnOpenPrinter = NULL; g_pfnPrinterProperties = NULL; g_pfnSetJob = NULL; g_pfnSetPrinter = NULL; } } BOOL LinkInfoDLL_Init(void) { if (IsDllLoaded(s_hmodLinkInfo,TEXT("LinkInfo"))) return(TRUE); // already loaded. s_hmodLinkInfo = LoadLibrary(TEXT("LinkInfo.dll")); if (!ISVALIDHINSTANCE(s_hmodLinkInfo)) { s_hmodLinkInfo = NULL; // make sure it is NULL return(FALSE); } #ifdef UNICODE g_pfnCreateLinkInfo = (PFNCREATELINKINFO)GetProcAddress(s_hmodLinkInfo, "CreateLinkInfoW"); g_pfnDestroyLinkInfo = (PFNDESTROYLINKINFO)GetProcAddress(s_hmodLinkInfo, "DestroyLinkInfo"); g_pfnResolveLinkInfo = (PFNRESOLVELINKINFO)GetProcAddress(s_hmodLinkInfo, "ResolveLinkInfoW"); g_pfnGetLinkInfoData = (PFNGETLINKINFODATA)GetProcAddress(s_hmodLinkInfo, "GetLinkInfoData"); #else g_pfnCreateLinkInfo = (PFNCREATELINKINFO)GetProcAddress(s_hmodLinkInfo, "CreateLinkInfo"); g_pfnDestroyLinkInfo = (PFNDESTROYLINKINFO)GetProcAddress(s_hmodLinkInfo, "DestroyLinkInfo"); g_pfnResolveLinkInfo = (PFNRESOLVELINKINFO)GetProcAddress(s_hmodLinkInfo, "ResolveLinkInfo"); g_pfnGetLinkInfoData = (PFNGETLINKINFODATA)GetProcAddress(s_hmodLinkInfo, "GetLinkInfoData"); #endif if (!g_pfnCreateLinkInfo || !g_pfnDestroyLinkInfo || !g_pfnResolveLinkInfo || !g_pfnGetLinkInfoData) { // BUGBUG: The next call to LinkInfoDLL_Init will incorrectly return TRUE Assert(FALSE); return(FALSE); } return(TRUE); } void LinkInfoDLL_Term() { if (ISVALIDHINSTANCE(s_hmodLinkInfo)) { FreeLibrary(s_hmodLinkInfo); s_hmodLinkInfo = NULL; g_pfnCreateLinkInfo = NULL; g_pfnDestroyLinkInfo = NULL; g_pfnResolveLinkInfo = NULL; g_pfnGetLinkInfoData = NULL; } } #ifdef WINNT // PRINTQ void PrintUIDLL_Term() { if (ISVALIDHINSTANCE(s_hmodPrintUI)) { FreeLibrary(s_hmodPrintUI); s_hmodPrintUI = NULL; g_pfnQueueCreate = NULL; g_pfnPrinterPropPages = NULL; g_pfnServerPropPages = NULL; g_pfnPrinterSetup = NULL; g_pfnDocumentDefaults = NULL; #ifdef PRN_FOLDERDATA g_pfnFolderRegister = NULL; g_pfnFolderUnregister = NULL; g_pfnFolderEnumPrinters = NULL; g_pfnFolderRefresh = NULL; g_pfnFolderGetPrinter = NULL; #endif } } BOOL PrintUIDLL_Init(void) { if (IsDllLoaded(s_hmodPrintUI, TEXT("printui"))) return(TRUE); // already loaded. s_hmodPrintUI = LoadLibrary(TEXT("printui.dll")); if (!ISVALIDHINSTANCE(s_hmodPrintUI)) { s_hmodPrintUI = NULL; // make sure it is NULL return(FALSE); } g_pfnQueueCreate = (PFNQUEUECREATE)GetProcAddress(s_hmodPrintUI, "vQueueCreate"); g_pfnPrinterPropPages = (PFNPRINTERPROPPAGES)GetProcAddress(s_hmodPrintUI, "vPrinterPropPages"); g_pfnServerPropPages = (PFNSERVERPROPPAGES)GetProcAddress(s_hmodPrintUI, "vServerPropPages"); g_pfnPrinterSetup = (PFNPRINTERSETUP)GetProcAddress(s_hmodPrintUI, "bPrinterSetup"); g_pfnDocumentDefaults = (PFNDOCUMENTDEFAULTS)GetProcAddress(s_hmodPrintUI, "vDocumentDefaults"); #ifdef PRN_FOLDERDATA g_pfnFolderRegister = (PFNFOLDERREGISTER)GetProcAddress(s_hmodPrintUI, "hFolderRegister"); g_pfnFolderUnregister = (PFNFOLDERUNREGISTER)GetProcAddress(s_hmodPrintUI, "vFolderUnregister"); g_pfnFolderEnumPrinters = (PFNFOLDERENUMPRINTERS)GetProcAddress(s_hmodPrintUI, "bFolderEnumPrinters"); g_pfnFolderRefresh = (PFNFOLDERREFRESH)GetProcAddress(s_hmodPrintUI, "bFolderRefresh"); g_pfnFolderGetPrinter = (PFNFOLDERGETPRINTER)GetProcAddress(s_hmodPrintUI, "bFolderGetPrinter"); #endif #ifdef PRN_FOLDERDATA if (!g_pfnQueueCreate || !g_pfnPrinterPropPages || !g_pfnPrinterSetup || !g_pfnDocumentDefaults || !g_pfnServerPropPages || !g_pfnFolderRegister || !g_pfnFolderUnregister || !g_pfnFolderEnumPrinters || !g_pfnFolderGetPrinter || !g_pfnFolderRefresh) #else if (!g_pfnQueueCreate || !g_pfnPrinterPropPages || !g_pfnPrinterSetup || !g_pfnDocumentDefaults || !g_pfnServerPropPages) #endif { // BUGBUG: The next call to PrintUI_Init will incorrectly return TRUE Assert(FALSE); PrintUIDLL_Term(); // Free our usage of the DLL for now... return(FALSE); } return TRUE; } #endif void Shell_EnterCriticalSection(void) { EnterCriticalSection(&g_csShell); #ifdef DEBUG if (g_CriticalSectionCount++ == 0) g_CriticalSectionOwner = GetCurrentThreadId(); #endif } void Shell_LeaveCriticalSection(void) { #ifdef DEBUG if (--g_CriticalSectionCount == 0) g_CriticalSectionOwner = 0; #endif LeaveCriticalSection(&g_csShell); } TCHAR const c_szRegExplorer[] = REGSTR_PATH_EXPLORER; TCHAR const c_szApproved[] = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); BOOL _ProcessAttach(HINSTANCE hDll) // 32-bit { BOOL fSuccess = TRUE; // _asm int 3; g_hinst = hDll; g_hProcessHeap = GetProcessHeap(); #ifdef WINNT // // NT has no shared critical sections // InitializeCriticalSection(&g_csShell); InitializeCriticalSection(&g_csPrinters); #else // // This must be called for each attaching process otherwise // when the first process terminates the cs will be reclaimed. // ReinitializeCriticalSection(&g_csPrinters); ReinitializeCriticalSection(&g_csShell); #endif // // Open the useful registry keys // RegOpenKey(HKEY_CLASSES_ROOT, c_szCLSID, &g_hkcrCLSID); RegCreateKey(HKEY_CURRENT_USER, c_szRegExplorer, &g_hkcuExplorer); RegCreateKey(HKEY_LOCAL_MACHINE, c_szRegExplorer, &g_hklmExplorer); #ifdef WINNT if (0 != SHRestricted(REST_ENFORCESHELLEXTSECURITY)) RegOpenKey(HKEY_LOCAL_MACHINE, c_szApproved, &g_hklmApprovedExt); // Fetch the alternate color (for compression) if supplied. { DWORD cbData = sizeof(COLORREF); DWORD dwType; RegQueryValueEx(g_hkcuExplorer, c_szAltColor, NULL, &dwType, (LPBYTE)&g_crAltColor, &cbData); } #endif ENTERCRITICAL; if (g_cProcesses == 0) { fSuccess = _Initialize_SharedData(); } g_cProcesses++; LEAVECRITICAL; DebugMsg(DM_TRACE, TEXT("shell32: ProcessAttach: %s %d (%x)"), GetCurrentApp(), g_cProcesses, hDll); #ifdef DEBUG #define DEREFMACRO(x) x #define ValidateORD(_name) Assert( _name == (LPVOID)GetProcAddress(hDll, (LPSTR)MAKEINTRESOURCE(DEREFMACRO(_name##ORD))) ) if (g_cProcesses==1) // no need to be in critical section (just debug) { ValidateORD(SHValidateUNC); ValidateORD(SHChangeNotifyRegister); ValidateORD(SHChangeNotifyDeregister); ValidateORD(OleStrToStrN); ValidateORD(SHCloneSpecialIDList); Assert(DllGetClassObject==(LPVOID)GetProcAddress(hDll,(LPSTR)MAKEINTRESOURCE(SHDllGetClassObjectORD))); ValidateORD(SHLogILFromFSIL); ValidateORD(SHMapPIDLToSystemImageListIndex); ValidateORD(SHShellFolderView_Message); ValidateORD(Shell_GetImageLists); ValidateORD(SHGetSpecialFolderPath); ValidateORD(StrToOleStrN); ValidateORD(ILClone); ValidateORD(ILCloneFirst); ValidateORD(ILCombine); ValidateORD(ILCreateFromPath); ValidateORD(ILFindChild); ValidateORD(ILFree); ValidateORD(ILGetNext); ValidateORD(ILGetSize); ValidateORD(ILIsEqual); ValidateORD(ILRemoveLastID); ValidateORD(PathAddBackslash); ValidateORD(PathCombine); ValidateORD(PathIsExe); ValidateORD(PathMatchSpec); ValidateORD(SHGetSetSettings); ValidateORD(SHILCreateFromPath); ValidateORD(SHFree); ValidateORD(SHAddFromPropSheetExtArray); ValidateORD(SHCreatePropSheetExtArray); ValidateORD(SHDestroyPropSheetExtArray); ValidateORD(SHReplaceFromPropSheetExtArray); ValidateORD(SHCreateDefClassObject); ValidateORD(SHGetNetResource); } #ifdef WINNT /* * read wDebugMask entry from win.ini for SHELL32.DLL. * The default is 0x000E, which includes DM_WARNING, DM_ERROR, * and DM_ASSERT. The default has DM_TRACE and DM_ALLOC turned * off. */ { CHAR szDebugMask[ 80 ]; if (GetProfileStringA( "Shell32", "DebugMask", "0x000E", szDebugMask, ARRAYSIZE(szDebugMask)) > 0 ) { sscanf( szDebugMask, "%i", &wDebugMask ); } } #endif // WINNT #endif // // All the per-instance initialization code should come here. // // // This block must be placed at the end of this function. // #ifdef DEBUG { extern LPMALLOC g_pmemTask; if (g_pmemTask) { MessageBeep(0); DebugMsg(DM_ERROR, TEXT("sh TR - Somebody called SHAlloc in LibMain!")); Assert(0); } } #endif return fSuccess; } BOOL _ProcessDetach(HINSTANCE hDll, LPVOID lpReserved) { BOOL fSuccess = TRUE; // // We are not supposed to call any virtual calls while processing // PROCESS_DETACH signal. // TaskMem_Term(); // // All the per-instance terminate code should be done here. // ShareDLL_Term(); VersionDLL_Term(); Comdlg32DLL_Term(); WinspoolDLL_Term(); LinkInfoDLL_Term(); MprDLL_Term(); PSCache_Term(); RLTerminate(); // close our use of the Registry list... DragDrop_Term(TRUE); DAD_ProcessDetach(); ClassCache_Terminate(); Binder_Terminate(); // close this task with the binder CDrives_Terminate(); #ifdef WINNT PrintUIDLL_Term(); NetApi32DLL_Term(); #endif ENTERCRITICAL { DebugMsg(DM_TRACE, TEXT("shell32: ProcessDetach: %s %d (%x, %x)"), GetCurrentApp(), g_cProcesses, hDll, HINST_THISDLL); --g_cProcesses; fSuccess = _Terminate_SharedData(g_cProcesses == 0); // Flush the file class cache, some app may have changed associations // BUGBUG is this too often? FlushFileClass(); } LEAVECRITICAL CopyHooksTerminate(); if (g_hkcrCLSID) RegCloseKey(g_hkcrCLSID); if (g_hkcuExplorer) RegCloseKey(g_hkcuExplorer); if (g_hklmExplorer) RegCloseKey(g_hklmExplorer); #ifdef WINNT if (g_hklmApprovedExt); RegCloseKey(g_hklmApprovedExt); if (lpReserved == NULL) { FreeExtractIconInfo(-1); } #endif return fSuccess; } BOOL _ThreadDetach(HINSTANCE hDll) { typedef struct _DAD_DRAGCONTEXT * LPDAD_DRAGCONTEXT; extern LPDAD_DRAGCONTEXT s_pdadc; extern BOOL g_bAnyDropTarget; if (g_bAnyDropTarget) { DragDrop_Term(FALSE); } if (s_pdadc) { DAD_ThreadDetach(); } return TRUE; } #ifndef WINNT // created by the thunk scripts BOOL WINAPI Shl3216_ThunkConnect32(LPCTSTR pszDll16, LPCTSTR pszDll32, HANDLE hIinst, DWORD dwReason); BOOL WINAPI Shl1632_ThunkConnect32(LPCTSTR pszDll16, LPCTSTR pszDll32, HANDLE hIinst, DWORD dwReason); #endif BOOL APIENTRY LibMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) { #ifndef WINNT // // thunk connect // if (!Shl3216_ThunkConnect32(c_szShell16Dll, c_szShell32Dll, hDll, dwReason)) return FALSE; if (!Shl1632_ThunkConnect32(c_szShell16Dll, c_szShell32Dll, hDll, dwReason)) return FALSE; #endif switch(dwReason) { case DLL_PROCESS_ATTACH: _ProcessAttach(hDll); break; case DLL_PROCESS_DETACH: _ProcessDetach(hDll,lpReserved); break; case DLL_THREAD_DETACH: _ThreadDetach(hDll); break; case DLL_THREAD_ATTACH: DebugMsg(DM_TRACE, TEXT("shell32: ThreadAttach: %s %08x"), GetCurrentApp(), GetCurrentThreadId()); break; default: break; } return TRUE; } #ifdef DEBUG LRESULT WINAPI SendMessageD( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { ASSERTNONCRITICAL; #ifdef UNICODE return SendMessageW(hWnd, Msg, wParam, lParam); #else return SendMessageA(hWnd, Msg, wParam, lParam); #endif } #endif // DEBUG