mirror of https://github.com/lianthony/NT4.0
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.
168 lines
5.0 KiB
168 lines
5.0 KiB
//
|
|
// This file contains the DllGetClassObject for the shell objects
|
|
//
|
|
|
|
#include "shellprv.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Initialize GUIDs (should be done only and at-least once per DLL/EXE)
|
|
//
|
|
#define NO_CLSID_ShellFolder
|
|
#define INITGUID
|
|
#pragma data_seg(DATASEG_READONLY)
|
|
#include <initguid.h>
|
|
#include <shguidp.h>
|
|
#include "idlcomm.h"
|
|
#include "iid.h"
|
|
#pragma data_seg()
|
|
|
|
|
|
//=========================================================================
|
|
// DllGetClassObject
|
|
//=========================================================================
|
|
|
|
#pragma data_seg(DATASEG_READONLY)
|
|
//
|
|
// ClassID->lpfnCreateInstance function mapping table for all the shell
|
|
// classes.
|
|
//
|
|
struct {
|
|
REFCLSID rclsid;
|
|
LPFNCREATEINSTANCE lpfnCreateInstance;
|
|
} c_clsmap[] = {
|
|
{ &CLSID_ShellDesktop, CDesktop_CreateInstance },
|
|
{ &CLSID_ShellDrives, CDrives_CreateInstance },
|
|
{ &CLSID_ShellNetwork, CNetwork_CreateInstance },
|
|
{ &CLSID_ShellFileDefExt, CShellFileDefExt_CreateInstance },
|
|
{ &CLSID_ShellDrvDefExt, CShellDrvDefExt_CreateInstance },
|
|
{ &CLSID_ShellNetDefExt, CShellNetDefExt_CreateInstance },
|
|
{ &CLSID_ShellCopyHook, CShellCopyHook_CreateInstance },
|
|
{ &CLSID_ShellLink, CShellLink_CreateInstance },
|
|
{ &CLSID_CControls, CControls_CreateInstance },
|
|
{ &CLSID_CPrinters, CPrinters_CreateInstance },
|
|
{ &CLSID_ShellViewerExt, CShellViewerExt_CreateInstance },
|
|
{ &CLSID_ShellBitBucket, CShellBitBucket_CreateInstance },
|
|
{ &CLSID_ShellFindExt, CShellFindExt_CreateInstance },
|
|
{ &CLSID_PifProperties, CProxyPage_CreateInstance },
|
|
{ &CLSID_ShellFSFolder, CFSFolder_CreateInstance },
|
|
{ &CLSID_FileTypes, CFileTypes_CreateInstance },
|
|
};
|
|
#pragma data_seg()
|
|
|
|
|
|
#pragma data_seg(DATASEG_PERINSTANCE)
|
|
|
|
// REVIEW: is this worth doing?
|
|
//
|
|
// Cached class objects per process
|
|
//
|
|
// Notes: We can not share objects among multiple processes, because they
|
|
// contains a ponter to VTable. The address of VTable could be mapped
|
|
// into different address from process to process. (SatoNa)
|
|
//
|
|
STATIC LPUNKNOWN g_apunkCachedClasses[ARRAYSIZE(c_clsmap)] = { NULL, };
|
|
STATIC DWORD g_dwRegister[ARRAYSIZE(c_clsmap)] = { 0 };
|
|
STATIC BOOL fClassesRegistered = FALSE;
|
|
#pragma data_seg()
|
|
|
|
//
|
|
// OLE 2.0 compatible entry for COMPOBJ
|
|
//
|
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv)
|
|
{
|
|
HRESULT hres = ResultFromScode(CLASS_E_CLASSNOTAVAILABLE);
|
|
UINT icls;
|
|
|
|
if (!fClassesRegistered)
|
|
{
|
|
ClassCache_Initialize();
|
|
fClassesRegistered = TRUE;
|
|
}
|
|
|
|
for (icls = 0; icls < ARRAYSIZE(c_clsmap); icls++)
|
|
{
|
|
if (IsEqualIID(rclsid, c_clsmap[icls].rclsid))
|
|
{
|
|
// Don't enter the critical section, if we already have a cached class.
|
|
if (!g_apunkCachedClasses[icls])
|
|
{
|
|
// Enter critical section
|
|
ENTERCRITICAL;
|
|
if (!g_apunkCachedClasses[icls])
|
|
{
|
|
//
|
|
// Create a class factory object, and put it in the cache.
|
|
//
|
|
LPUNKNOWN punk;
|
|
hres = SHCreateDefClassObject(riid, &punk, c_clsmap[icls].lpfnCreateInstance,
|
|
NULL, NULL);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
g_apunkCachedClasses[icls]=punk;
|
|
}
|
|
}
|
|
LEAVECRITICAL;
|
|
}
|
|
|
|
//
|
|
// We need to check it again to make it sure that we have it.
|
|
//
|
|
if (g_apunkCachedClasses[icls])
|
|
{
|
|
hres = g_apunkCachedClasses[icls]->lpVtbl->QueryInterface(g_apunkCachedClasses[icls], riid, ppv);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
void ClassCache_Initialize()
|
|
{
|
|
UINT icls;
|
|
HRESULT hres;
|
|
LPUNKNOWN punk;
|
|
|
|
ENTERCRITICAL;
|
|
|
|
for (icls = 0; icls < ARRAYSIZE(c_clsmap); icls++)
|
|
{
|
|
hres = SHCreateDefClassObject(&IID_IClassFactory, &punk, c_clsmap[icls].lpfnCreateInstance,
|
|
NULL, NULL);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
g_apunkCachedClasses[icls]=punk;
|
|
SHCoRegisterClassObject(c_clsmap[icls].rclsid, punk,
|
|
CLSCTX_INPROC_SERVER,
|
|
REGCLS_MULTIPLEUSE,
|
|
&g_dwRegister[icls]);
|
|
}
|
|
}
|
|
LEAVECRITICAL;
|
|
}
|
|
|
|
|
|
//
|
|
// Releases all the cached class factory objects.
|
|
//
|
|
// This function must be called when a process is detached.
|
|
//
|
|
void ClassCache_Terminate()
|
|
{
|
|
UINT icls;
|
|
|
|
for (icls = 0; icls < ARRAYSIZE(c_clsmap); icls++)
|
|
{
|
|
if (g_apunkCachedClasses[icls])
|
|
{
|
|
int iRef;
|
|
|
|
SHCoRevokeClassObject(g_dwRegister[icls]);
|
|
|
|
iRef = g_apunkCachedClasses[icls]->lpVtbl->Release(g_apunkCachedClasses[icls]);
|
|
Assert(iRef==0);
|
|
}
|
|
}
|
|
}
|