|
|
/*****************************************************************************
* * DIOleDup.c * * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Functions that sort-of duplicate what OLE does. * * Contents: * * DICoCreateInstance * *****************************************************************************/
#include "dinputpr.h"
/*****************************************************************************
* * The sqiffle for this file. * *****************************************************************************/
#define sqfl sqflOleDup
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | _CreateInstance | * * Worker function for <f DICoCreateInstance>. * * @parm REFCLSID | rclsid | * * The <t CLSID> to create. * * @parm LPCTSTR | ptszDll | * * The name of the DLL to load. * * @parm LPUNKNOWN | punkOuter | * * Controlling unknown for aggregation. * * @parm RIID | riid | * * Interface to obtain. * * @parm PPV | ppvOut | * * Receives a pointer to the created object if successful. * * @parm HINSTANCE * | phinst | * * Receives the instance handle of the in-proc DLL that was * loaded. <f FreeLibrary> this DLL when you are finished * with the object. * * Note that since we don't implement a binder, this means * that you cannot give the returned pointer away to anybody * you don't control; otherwise, you won't know when to * free the DLL. * * @returns * * Standard OLE status code. * *****************************************************************************/
HRESULT INTERNAL _CreateInstance(REFCLSID rclsid, LPCTSTR ptszDll, LPUNKNOWN punkOuter, RIID riid, PPV ppvOut, HINSTANCE *phinst) { HRESULT hres; HINSTANCE hinst;
hinst = LoadLibrary(ptszDll); if (hinst) { LPFNGETCLASSOBJECT DllGetClassObject;
DllGetClassObject = (LPFNGETCLASSOBJECT) GetProcAddress(hinst, "DllGetClassObject");
if (DllGetClassObject) { IClassFactory *pcf;
hres = DllGetClassObject(rclsid, &IID_IClassFactory, &pcf); if (SUCCEEDED(hres)) { hres = pcf->lpVtbl->CreateInstance(pcf, punkOuter, riid, ppvOut); pcf->lpVtbl->Release(pcf);
/*
* Some people forget to adhere to * the OLE spec, which requires that *ppvOut be * set to zero on failure. */ if (FAILED(hres)) { if (*ppvOut) { RPF("ERROR! CoCreateInstance: %s forgot to zero " "out *ppvOut on failure path", ptszDll); } *ppvOut = 0; }
} } else { /*
* DLL does not export GetClassObject. */ hres = REGDB_E_CLASSNOTREG; }
if (SUCCEEDED(hres)) { *phinst = hinst; } else { FreeLibrary(hinst); } } else { /*
* DLL does not exist. */ hres = REGDB_E_CLASSNOTREG; }
return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | DICoCreateInstance | * * Private version of CoCreateInstance that doesn't use OLE. * * @parm LPTSTR | ptszClsid | * * The string version of the <t CLSID> to create. * * @parm LPUNKNOWN | punkOuter | * * Controlling unknown for aggregation. * * @parm RIID | riid | * * Interface to obtain. * * @parm PPV | ppvOut | * * Receives a pointer to the created object if successful. * * @parm HINSTANCE * | phinst | * * Receives the instance handle of the in-proc DLL that was * loaded. <f FreeLibrary> this DLL when you are finished * with the object. * * Note that since we don't implement a binder, this means * that you cannot give the returned pointer away to anybody * you don't control; otherwise, you won't know when to * free the DLL. * * @returns * * Standard OLE status code. * *****************************************************************************/
STDMETHODIMP DICoCreateInstance(LPTSTR ptszClsid, LPUNKNOWN punkOuter, RIID riid, PPV ppvOut, HINSTANCE *phinst) { HRESULT hres; CLSID clsid; EnterProcI(DICoCreateInstance, (_ "spG", ptszClsid, punkOuter, riid));
*ppvOut = 0; *phinst = 0;
if (ParseGUID(&clsid, ptszClsid)) { HKEY hk; LONG lRc; TCHAR tszKey[ctchGuid + 40]; /* 40 is more than enough */
/*
* Look up the CLSID in HKEY_CLASSES_ROOT. */ wsprintf(tszKey, TEXT("CLSID\\%s\\InProcServer32"), ptszClsid);
lRc = RegOpenKeyEx(HKEY_CLASSES_ROOT, tszKey, 0, KEY_QUERY_VALUE, &hk); if (lRc == ERROR_SUCCESS) { TCHAR tszDll[MAX_PATH]; DWORD cb;
cb = cbX(tszDll); lRc = RegQueryValue(hk, 0, tszDll, &cb);
if (lRc == ERROR_SUCCESS) { TCHAR tszModel[20]; /* more than enough */
lRc = RegQueryString(hk, TEXT("ThreadingModel"), tszModel, cA(tszModel)); if (lRc == ERROR_SUCCESS && ((lstrcmpi(tszModel, TEXT("Both"))==0x0) || (lstrcmpi(tszModel, TEXT("Free"))==0x0))) {
hres = _CreateInstance(&clsid, tszDll, punkOuter, riid, ppvOut, phinst);
} else { /*
* No threading model or bad threading model. */ hres = REGDB_E_CLASSNOTREG; } } else { /*
* No InprocServer32. */ hres = REGDB_E_CLASSNOTREG; }
RegCloseKey(hk);
} else { /*
* CLSID not registered. */ hres = REGDB_E_CLASSNOTREG; } } else { /*
* Invalid CLSID string. */ hres = REGDB_E_CLASSNOTREG; }
ExitOleProcPpv(ppvOut); return hres; }
|