Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

987 lines
30 KiB

#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 <stdio.h>
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