250 lines
6.6 KiB
C
250 lines
6.6 KiB
C
/*****************************************************************************
|
|
*
|
|
* 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
|
|
|
|
#ifdef IDirectInputDevice2Vtbl
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @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;
|
|
}
|
|
|
|
#endif
|