windows-nt/Source/XPSP1/NT/printscan/wia/common/stirt/olesupp.c
2020-09-26 16:20:57 +08:00

499 lines
14 KiB
C

/*****************************************************************************
*
* olesupp.c
*
* Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
*
* Abstract:
*
* Implementation of CreateInstance for free-threaded components
* which allows us to not load OLE32.
*
* Contents:
*
* MyCoCreateInstance
*
*****************************************************************************/
/*
#include <windows.h>
#include <windowsx.h>
#include <objbase.h>
#include <regstr.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <devguid.h>
#include <stdio.h>
#include <stilog.h>
#include <stiregi.h>
#include <sti.h>
#include <stierr.h>
#include <stiusd.h>
#include "stipriv.h"
#include "stiapi.h"
#include "stirc.h"
#include "debug.h"
*/
#include "sticomm.h"
#include "coredbg.h"
#define DbgFl DbgFlSti
BOOL
ParseGUID(
LPGUID pguid,
LPCTSTR ptsz
);
BOOL
ParseGUIDA(
LPGUID pguid,
LPCSTR psz
);
/*****************************************************************************
*
* @doc INTERNAL
*
* @func HRESULT | MyCoCreateInstance |
*
* Private version of CoCreateInstance that doesn't use OLE32.
*
* @parm LPTSTR | ptszClsid |
*
*
* @parm LPUNKNOWN | punkOuter |
*
* Controlling unknown for aggregation.
*
* @parm RIID | riid |
*
* Interface ID
*
* @parm PPV | ppvOut |
*
* Receives a pointer to the created object if successful.
*
* @parm HINSTANCE * | phinst |
*
* As we don't have an infrastructure to unload objects , it becomes
* responsibility of the user to unload DLL when done with it.
*
* @returns
*
* OLE status code.
*
*****************************************************************************/
STDMETHODIMP
MyCoCreateInstanceW(
LPWSTR pwszClsid,
LPUNKNOWN punkOuter,
RIID riid,
PPV ppvOut,
HINSTANCE *phinst
)
{
HRESULT hres;
CLSID clsid;
HINSTANCE hinst;
EnterProcI(MyCoCreateInstanceW, (_ "spG", pwszClsid, punkOuter, riid));
#ifdef UNICODE
*ppvOut = 0;
*phinst = 0;
if (SUCCEEDED(CLSIDFromString(pwszClsid, &clsid))) {
HKEY hk;
LONG lRet;
WCHAR wszKey[ctchGuid + 40];
//
// Look up the CLSID in HKEY_CLASSES_ROOT.
//
swprintf(wszKey, L"CLSID\\%s\\InProcServer32", pwszClsid);
lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKey, 0, KEY_QUERY_VALUE, &hk);
if (lRet == ERROR_SUCCESS) {
WCHAR wszDll[MAX_PATH];
DWORD cb;
cb = cbX(wszDll);
lRet = RegQueryValueW(hk, 0, wszDll, &cb);
if (lRet == ERROR_SUCCESS) {
WCHAR wszModel[40];
DWORD dwType;
DWORD cbBuffer = sizeof(wszModel);
lRet = RegQueryValueExW( hk,
L"ThreadingModel",
NULL,
&dwType,
(PBYTE)wszModel,
&cbBuffer );
if (NOERROR ==lRet &&
(lstrcmpiW(wszModel, L"Both") ||
lstrcmpiW(wszModel, L"Free"))) {
hinst = LoadLibrary(wszDll);
if (hinst) {
LPFNGETCLASSOBJECT DllGetClassObject;
DllGetClassObject = (LPFNGETCLASSOBJECT)
GetProcAddress(hinst, "DllGetClassObject");
if (DllGetClassObject) {
IClassFactory *pcf;
hres = DllGetClassObject(&clsid, &IID_IClassFactory, &pcf);
if (SUCCEEDED(hres)) {
hres = pcf->lpVtbl->CreateInstance(pcf, punkOuter, riid, ppvOut);
pcf->lpVtbl->Release(pcf);
/*
* People forget to adhere to
* the OLE spec, which requires that *ppvOut be
* set to zero on failure.
*/
if (FAILED(hres)) {
*ppvOut = 0;
}
}
} else {
/*
* DLL does not export GetClassObject.
*/
DBG_TRC(("MyCoCreateInstanceW, DLL does not export GetClassObject"));
hres = REGDB_E_CLASSNOTREG;
}
if (SUCCEEDED(hres)) {
*phinst = hinst;
} else {
FreeLibrary(hinst);
}
} else {
/*
* DLL does not exist.
*/
DBG_TRC(("MyCoCreateInstanceW, DLL does not exist"));
hres = REGDB_E_CLASSNOTREG;
}
} else {
/*
* No threading model or bad threading model.
*/
DBG_TRC(("MyCoCreateInstanceW, No threading model or bad threading model"));
hres = REGDB_E_CLASSNOTREG;
}
} else {
/*
* No InprocServer32.
*/
DBG_TRC(("MyCoCreateInstanceW, No InprocServer32"));
hres = REGDB_E_CLASSNOTREG;
}
RegCloseKey(hk);
} else {
/*
* CLSID not registered.
*/
DBG_WRN(("MyCoCreateInstanceW, CLSID not registered"));
hres = REGDB_E_CLASSNOTREG;
}
} else {
/*
* Invalid CLSID string.
*/
DBG_WRN(("MyCoCreateInstanceW, Invalid CLSID string"));
hres = REGDB_E_CLASSNOTREG;
}
#else
hres = E_FAIL;
#endif // UNICODE
ExitOleProcPpv(ppvOut);
return hres;
}
STDMETHODIMP
MyCoCreateInstanceA(
LPSTR pszClsid,
LPUNKNOWN punkOuter,
RIID riid,
PPV ppvOut,
HINSTANCE *phinst
)
{
HRESULT hres;
CLSID clsid;
HINSTANCE hinst;
EnterProcI(MyCoCreateInstanceA, (_ "spG", TEXT("ANSI ClassId not converted to UNICODE"), punkOuter, riid));
*ppvOut = 0;
*phinst = 0;
if (ParseGUIDA(&clsid, pszClsid)) {
HKEY hk;
LONG lRet;
CHAR szKey[ctchGuid + 40];
//
// Look up the CLSID in HKEY_CLASSES_ROOT.
//
sprintf(szKey, "CLSID\\%s\\InProcServer32", pszClsid);
lRet = RegOpenKeyExA(HKEY_CLASSES_ROOT, szKey, 0,
KEY_QUERY_VALUE, &hk);
if (lRet == ERROR_SUCCESS) {
CHAR szDll[MAX_PATH];
DWORD cb;
cb = cbX(szDll);
lRet = RegQueryValueA(hk, 0, szDll, &cb);
if (lRet == ERROR_SUCCESS) {
CHAR szModel[40];
DWORD dwType;
DWORD cbBuffer = sizeof(szModel);
lRet = RegQueryValueExA( hk,
"ThreadingModel",
NULL,
&dwType,
szModel,
&cbBuffer );
if (NOERROR ==lRet &&
(lstrcmpiA(szModel, "Both") ||
lstrcmpiA(szModel, "Free"))) {
hinst = LoadLibraryA(szDll);
if (hinst) {
LPFNGETCLASSOBJECT DllGetClassObject;
DllGetClassObject = (LPFNGETCLASSOBJECT)
GetProcAddress(hinst, "DllGetClassObject");
if (DllGetClassObject) {
IClassFactory *pcf;
hres = DllGetClassObject(&clsid, &IID_IClassFactory, &pcf);
if (SUCCEEDED(hres)) {
hres = pcf->lpVtbl->CreateInstance(pcf, punkOuter,
riid, ppvOut);
pcf->lpVtbl->Release(pcf);
/*
* People forget to adhere to
* the OLE spec, which requires that *ppvOut be
* set to zero on failure.
*/
if (FAILED(hres)) {
*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;
}
} 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;
}
#define ctchGuid (1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
LPCTSTR
_ParseHex(
LPCTSTR ptsz,
LPBYTE *ppb,
int cb,
TCHAR tchDelim
)
{
if (ptsz) {
int i = cb * 2;
DWORD dwParse = 0;
do {
DWORD uch;
uch = (TBYTE)*ptsz - TEXT('0');
if (uch < 10) { /* a decimal digit */
} else {
uch = (*ptsz | 0x20) - TEXT('a');
if (uch < 6) { /* a hex digit */
uch += 10;
} else {
return 0; /* Parse error */
}
}
dwParse = (dwParse << 4) + uch;
ptsz++;
} while (--i);
if (tchDelim && *ptsz++ != tchDelim) return 0; /* Parse error */
for (i = 0; i < cb; i++) {
(*ppb)[i] = ((LPBYTE)&dwParse)[i];
}
*ppb += cb;
}
return ptsz;
} // _ParseHex
LPCSTR
_ParseHexA(
LPCSTR psz,
LPBYTE *ppb,
int cb,
CHAR chDelim
)
{
if (psz) {
int i = cb * 2;
DWORD dwParse = 0;
do {
DWORD uch;
uch = (BYTE)*psz - '0';
if (uch < 10) { /* a decimal digit */
} else {
uch = (*psz | 0x20) - 'a';
if (uch < 6) { /* a hex digit */
uch += 10;
} else {
return 0; /* Parse error */
}
}
dwParse = (dwParse << 4) + uch;
psz++;
} while (--i);
if (chDelim && *psz++ != chDelim) return 0; /* Parse error */
for (i = 0; i < cb; i++) {
(*ppb)[i] = ((LPBYTE)&dwParse)[i];
}
*ppb += cb;
}
return psz;
} // _ParseHexA
BOOL
ParseGUID(
LPGUID pguid,
LPCTSTR ptsz
)
{
if (lstrlen(ptsz) == ctchGuid - 1 && *ptsz == TEXT('{')) {
ptsz++;
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 4, TEXT('-'));
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 2, TEXT('-'));
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 2, TEXT('-'));
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, TEXT('-'));
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, TEXT('}'));
return (ptsz == NULL) ? FALSE : TRUE ;
} else {
return 0;
}
} // ParseGUID
BOOL
ParseGUIDA(
LPGUID pguid,
LPCSTR psz
)
{
if (lstrlenA(psz) == ctchGuid - 1 && *psz == '{') {
psz++;
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 4, '-');
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 2, '-');
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 2, '-');
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, '-');
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, '}');
return (psz == NULL) ? FALSE : TRUE ;
} else {
return 0;
}
} // ParseGUID