Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

251 lines
6.3 KiB

#include <windows.h>
#include "comdll.h"
#include "ddraw.h"
#include "ddrawex.h"
UINT g_cRefDll = 0; // reference count for this DLL
HANDLE g_hinst = NULL; // HMODULE for this DLL
typedef struct {
const IClassFactoryVtbl *cf;
const CLSID *pclsid;
HRESULT (STDMETHODCALLTYPE *pfnCreate)(IUnknown *, REFIID, void **);
HRESULT (STDMETHODCALLTYPE *pfnRegUnReg)(BOOL bReg, HKEY hkCLSID, LPCSTR pszCLSID, LPCSTR pszModule);
} OBJ_ENTRY;
extern const IClassFactoryVtbl c_CFVtbl; // forward
//
// we always do a linear search here so put your most often used things first
//
const OBJ_ENTRY c_clsmap[] = {
{&c_CFVtbl, &CLSID_DirectDrawFactory, DirectDrawFactory_CreateInstance, NULL},
// add more entries here
{ NULL, NULL, NULL, NULL }
};
// static class factory (no allocs!)
STDMETHODIMP CClassFactory_QueryInterface(IClassFactory *pcf, REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
{
*ppvObj = (void *)pcf;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
DllAddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG) CClassFactory_AddRef(IClassFactory *pcf)
{
DllAddRef();
return 2;
}
STDMETHODIMP_(ULONG) CClassFactory_Release(IClassFactory *pcf)
{
DllRelease();
return 1;
}
STDMETHODIMP CClassFactory_CreateInstance(IClassFactory *pcf, IUnknown *punkOuter, REFIID riid, void **ppvObject)
{
OBJ_ENTRY *this = IToClass(OBJ_ENTRY, cf, pcf);
return this->pfnCreate(punkOuter, riid, ppvObject);
}
STDMETHODIMP CClassFactory_LockServer(IClassFactory *pcf, BOOL fLock)
{
if (fLock)
DllAddRef();
else
DllRelease();
return S_OK;
}
const IClassFactoryVtbl c_CFVtbl = {
CClassFactory_QueryInterface, CClassFactory_AddRef, CClassFactory_Release,
CClassFactory_CreateInstance,
CClassFactory_LockServer
};
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{
if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
{
const OBJ_ENTRY *pcls;
for (pcls = c_clsmap; pcls->pclsid; pcls++)
{
if (IsEqualIID(rclsid, pcls->pclsid))
{
*ppv = (void *)&(pcls->cf);
DllAddRef(); // Class Factory keeps dll in memory
return NOERROR;
}
}
}
// failure
*ppv = NULL;
return CLASS_E_CLASSNOTAVAILABLE;;
}
STDAPI_(void) DllAddRef()
{
InterlockedIncrement(&g_cRefDll);
}
STDAPI_(void) DllRelease()
{
InterlockedDecrement(&g_cRefDll);
}
STDAPI DllCanUnloadNow(void)
{
return g_cRefDll == 0 ? S_OK : S_FALSE;
}
STDAPI_(BOOL) DllEntryPoint(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hinst = hDll;
DisableThreadLibraryCalls(hDll);
}
return TRUE;
}
STDAPI_(void) TStringFromGUID(const GUID* pguid, LPTSTR pszBuf)
{
wsprintf(pszBuf, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), pguid->Data1,
pguid->Data2, pguid->Data3, pguid->Data4[0], pguid->Data4[1], pguid->Data4[2],
pguid->Data4[3], pguid->Data4[4], pguid->Data4[5], pguid->Data4[6], pguid->Data4[7]);
}
#ifndef UNICODE
STDAPI_(void) WStringFromGUID(const GUID* pguid, LPWSTR pszBuf)
{
char szAnsi[40];
TStringFromGUID(pguid, szAnsi);
MultiByteToWideChar(CP_ACP, 0, szAnsi, -1, pszBuf, sizeof(szAnsi));
}
#endif
BOOL DeleteKeyAndSubKeys(HKEY hkIn, LPCTSTR pszSubKey)
{
HKEY hk;
TCHAR szTmp[MAX_PATH];
DWORD dwTmpSize;
long l;
BOOL f;
l = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_ALL_ACCESS, &hk);
if (l != ERROR_SUCCESS)
return FALSE;
// loop through all subkeys, blowing them away.
//
f = TRUE;
while (f) {
dwTmpSize = MAX_PATH;
l = RegEnumKeyEx(hk, 0, szTmp, &dwTmpSize, 0, NULL, NULL, NULL);
if (l != ERROR_SUCCESS)
break;
f = DeleteKeyAndSubKeys(hk, szTmp);
}
// there are no subkeys left, [or we'll just generate an error and return FALSE].
// let's go blow this dude away.
//
RegCloseKey(hk);
l = RegDeleteKey(hkIn, pszSubKey);
return (l == ERROR_SUCCESS) ? TRUE : FALSE;
}
#define INPROCSERVER32 TEXT("InProcServer32")
#define CLSID TEXT("CLSID")
#define THREADINGMODEL TEXT("ThreadingModel")
#define TMBOTH TEXT("Both")
STDAPI DllRegisterServer(void)
{
const OBJ_ENTRY *pcls;
TCHAR szPath[MAX_PATH];
GetModuleFileName(g_hinst, szPath, ARRAYSIZE(szPath)); // get path to this DLL
for (pcls = c_clsmap; pcls->pclsid; pcls++)
{
HKEY hkCLSID;
if (RegOpenKey(HKEY_CLASSES_ROOT, CLSID, &hkCLSID) == ERROR_SUCCESS)
{
HKEY hkOurs;
LONG err;
TCHAR szGUID[80];
TStringFromGUID(pcls->pclsid, szGUID);
err = RegCreateKey(hkCLSID, szGUID, &hkOurs);
if (err == ERROR_SUCCESS)
{
HKEY hkInproc;
err = RegCreateKey(hkOurs, INPROCSERVER32, &hkInproc);
if (err == ERROR_SUCCESS)
{
err = RegSetValueEx(hkInproc, NULL, 0, REG_SZ, (LPBYTE)szPath, (lstrlen(szPath) + 1) * sizeof(TCHAR));
if (err == ERROR_SUCCESS)
{
err = RegSetValueEx(hkInproc, THREADINGMODEL, 0, REG_SZ, (LPBYTE)TMBOTH, sizeof(TMBOTH));
}
RegCloseKey(hkInproc);
}
if (pcls->pfnRegUnReg)
pcls->pfnRegUnReg(TRUE, hkOurs, szGUID, szPath);
RegCloseKey(hkOurs);
}
RegCloseKey(hkCLSID);
if (err != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(err);
}
}
return S_OK;
}
STDAPI DllUnregisterServer(void)
{
const OBJ_ENTRY *pcls;
for (pcls = c_clsmap; pcls->pclsid; pcls++)
{
HKEY hkCLSID;
if (RegOpenKey(HKEY_CLASSES_ROOT, CLSID, &hkCLSID) == ERROR_SUCCESS)
{
TCHAR szGUID[80];
TStringFromGUID(pcls->pclsid, szGUID);
DeleteKeyAndSubKeys(hkCLSID, szGUID);
RegCloseKey(hkCLSID);
if (pcls->pfnRegUnReg)
pcls->pfnRegUnReg(FALSE, NULL, szGUID, NULL);
}
}
return S_OK;
}