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.

498 lines
14 KiB

  1. /*****************************************************************************
  2. *
  3. * olesupp.c
  4. *
  5. * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * Implementation of CreateInstance for free-threaded components
  10. * which allows us to not load OLE32.
  11. *
  12. * Contents:
  13. *
  14. * MyCoCreateInstance
  15. *
  16. *****************************************************************************/
  17. /*
  18. #include <windows.h>
  19. #include <windowsx.h>
  20. #include <objbase.h>
  21. #include <regstr.h>
  22. #include <setupapi.h>
  23. #include <cfgmgr32.h>
  24. #include <devguid.h>
  25. #include <stdio.h>
  26. #include <stilog.h>
  27. #include <stiregi.h>
  28. #include <sti.h>
  29. #include <stierr.h>
  30. #include <stiusd.h>
  31. #include "stipriv.h"
  32. #include "stiapi.h"
  33. #include "stirc.h"
  34. #include "debug.h"
  35. */
  36. #include "sticomm.h"
  37. #include "coredbg.h"
  38. #define DbgFl DbgFlSti
  39. BOOL
  40. ParseGUID(
  41. LPGUID pguid,
  42. LPCTSTR ptsz
  43. );
  44. BOOL
  45. ParseGUIDA(
  46. LPGUID pguid,
  47. LPCSTR psz
  48. );
  49. /*****************************************************************************
  50. *
  51. * @doc INTERNAL
  52. *
  53. * @func HRESULT | MyCoCreateInstance |
  54. *
  55. * Private version of CoCreateInstance that doesn't use OLE32.
  56. *
  57. * @parm LPTSTR | ptszClsid |
  58. *
  59. *
  60. * @parm LPUNKNOWN | punkOuter |
  61. *
  62. * Controlling unknown for aggregation.
  63. *
  64. * @parm RIID | riid |
  65. *
  66. * Interface ID
  67. *
  68. * @parm PPV | ppvOut |
  69. *
  70. * Receives a pointer to the created object if successful.
  71. *
  72. * @parm HINSTANCE * | phinst |
  73. *
  74. * As we don't have an infrastructure to unload objects , it becomes
  75. * responsibility of the user to unload DLL when done with it.
  76. *
  77. * @returns
  78. *
  79. * OLE status code.
  80. *
  81. *****************************************************************************/
  82. STDMETHODIMP
  83. MyCoCreateInstanceW(
  84. LPWSTR pwszClsid,
  85. LPUNKNOWN punkOuter,
  86. RIID riid,
  87. PPV ppvOut,
  88. HINSTANCE *phinst
  89. )
  90. {
  91. HRESULT hres;
  92. CLSID clsid;
  93. HINSTANCE hinst;
  94. EnterProcI(MyCoCreateInstanceW, (_ "spG", pwszClsid, punkOuter, riid));
  95. #ifdef UNICODE
  96. *ppvOut = 0;
  97. *phinst = 0;
  98. if (SUCCEEDED(CLSIDFromString(pwszClsid, &clsid))) {
  99. HKEY hk;
  100. LONG lRet;
  101. WCHAR wszKey[ctchGuid + 40];
  102. //
  103. // Look up the CLSID in HKEY_CLASSES_ROOT.
  104. //
  105. swprintf(wszKey, L"CLSID\\%s\\InProcServer32", pwszClsid);
  106. lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKey, 0, KEY_QUERY_VALUE, &hk);
  107. if (lRet == ERROR_SUCCESS) {
  108. WCHAR wszDll[MAX_PATH];
  109. DWORD cb;
  110. cb = cbX(wszDll);
  111. lRet = RegQueryValueW(hk, 0, wszDll, &cb);
  112. if (lRet == ERROR_SUCCESS) {
  113. WCHAR wszModel[40];
  114. DWORD dwType;
  115. DWORD cbBuffer = sizeof(wszModel);
  116. lRet = RegQueryValueExW( hk,
  117. L"ThreadingModel",
  118. NULL,
  119. &dwType,
  120. (PBYTE)wszModel,
  121. &cbBuffer );
  122. if (NOERROR ==lRet &&
  123. (lstrcmpiW(wszModel, L"Both") ||
  124. lstrcmpiW(wszModel, L"Free"))) {
  125. hinst = LoadLibrary(wszDll);
  126. if (hinst) {
  127. LPFNGETCLASSOBJECT DllGetClassObject;
  128. DllGetClassObject = (LPFNGETCLASSOBJECT)
  129. GetProcAddress(hinst, "DllGetClassObject");
  130. if (DllGetClassObject) {
  131. IClassFactory *pcf;
  132. hres = DllGetClassObject(&clsid, &IID_IClassFactory, &pcf);
  133. if (SUCCEEDED(hres)) {
  134. hres = pcf->lpVtbl->CreateInstance(pcf, punkOuter, riid, ppvOut);
  135. pcf->lpVtbl->Release(pcf);
  136. /*
  137. * People forget to adhere to
  138. * the OLE spec, which requires that *ppvOut be
  139. * set to zero on failure.
  140. */
  141. if (FAILED(hres)) {
  142. *ppvOut = 0;
  143. }
  144. }
  145. } else {
  146. /*
  147. * DLL does not export GetClassObject.
  148. */
  149. DBG_TRC(("MyCoCreateInstanceW, DLL does not export GetClassObject"));
  150. hres = REGDB_E_CLASSNOTREG;
  151. }
  152. if (SUCCEEDED(hres)) {
  153. *phinst = hinst;
  154. } else {
  155. FreeLibrary(hinst);
  156. }
  157. } else {
  158. /*
  159. * DLL does not exist.
  160. */
  161. DBG_TRC(("MyCoCreateInstanceW, DLL does not exist"));
  162. hres = REGDB_E_CLASSNOTREG;
  163. }
  164. } else {
  165. /*
  166. * No threading model or bad threading model.
  167. */
  168. DBG_TRC(("MyCoCreateInstanceW, No threading model or bad threading model"));
  169. hres = REGDB_E_CLASSNOTREG;
  170. }
  171. } else {
  172. /*
  173. * No InprocServer32.
  174. */
  175. DBG_TRC(("MyCoCreateInstanceW, No InprocServer32"));
  176. hres = REGDB_E_CLASSNOTREG;
  177. }
  178. RegCloseKey(hk);
  179. } else {
  180. /*
  181. * CLSID not registered.
  182. */
  183. DBG_WRN(("MyCoCreateInstanceW, CLSID not registered"));
  184. hres = REGDB_E_CLASSNOTREG;
  185. }
  186. } else {
  187. /*
  188. * Invalid CLSID string.
  189. */
  190. DBG_WRN(("MyCoCreateInstanceW, Invalid CLSID string"));
  191. hres = REGDB_E_CLASSNOTREG;
  192. }
  193. #else
  194. hres = E_FAIL;
  195. #endif // UNICODE
  196. ExitOleProcPpv(ppvOut);
  197. return hres;
  198. }
  199. STDMETHODIMP
  200. MyCoCreateInstanceA(
  201. LPSTR pszClsid,
  202. LPUNKNOWN punkOuter,
  203. RIID riid,
  204. PPV ppvOut,
  205. HINSTANCE *phinst
  206. )
  207. {
  208. HRESULT hres;
  209. CLSID clsid;
  210. HINSTANCE hinst;
  211. EnterProcI(MyCoCreateInstanceA, (_ "spG", TEXT("ANSI ClassId not converted to UNICODE"), punkOuter, riid));
  212. *ppvOut = 0;
  213. *phinst = 0;
  214. if (ParseGUIDA(&clsid, pszClsid)) {
  215. HKEY hk;
  216. LONG lRet;
  217. CHAR szKey[ctchGuid + 40];
  218. //
  219. // Look up the CLSID in HKEY_CLASSES_ROOT.
  220. //
  221. sprintf(szKey, "CLSID\\%s\\InProcServer32", pszClsid);
  222. lRet = RegOpenKeyExA(HKEY_CLASSES_ROOT, szKey, 0,
  223. KEY_QUERY_VALUE, &hk);
  224. if (lRet == ERROR_SUCCESS) {
  225. CHAR szDll[MAX_PATH];
  226. DWORD cb;
  227. cb = cbX(szDll);
  228. lRet = RegQueryValueA(hk, 0, szDll, &cb);
  229. if (lRet == ERROR_SUCCESS) {
  230. CHAR szModel[40];
  231. DWORD dwType;
  232. DWORD cbBuffer = sizeof(szModel);
  233. lRet = RegQueryValueExA( hk,
  234. "ThreadingModel",
  235. NULL,
  236. &dwType,
  237. szModel,
  238. &cbBuffer );
  239. if (NOERROR ==lRet &&
  240. (lstrcmpiA(szModel, "Both") ||
  241. lstrcmpiA(szModel, "Free"))) {
  242. hinst = LoadLibraryA(szDll);
  243. if (hinst) {
  244. LPFNGETCLASSOBJECT DllGetClassObject;
  245. DllGetClassObject = (LPFNGETCLASSOBJECT)
  246. GetProcAddress(hinst, "DllGetClassObject");
  247. if (DllGetClassObject) {
  248. IClassFactory *pcf;
  249. hres = DllGetClassObject(&clsid, &IID_IClassFactory, &pcf);
  250. if (SUCCEEDED(hres)) {
  251. hres = pcf->lpVtbl->CreateInstance(pcf, punkOuter,
  252. riid, ppvOut);
  253. pcf->lpVtbl->Release(pcf);
  254. /*
  255. * People forget to adhere to
  256. * the OLE spec, which requires that *ppvOut be
  257. * set to zero on failure.
  258. */
  259. if (FAILED(hres)) {
  260. *ppvOut = 0;
  261. }
  262. }
  263. } else {
  264. /*
  265. * DLL does not export GetClassObject.
  266. */
  267. hres = REGDB_E_CLASSNOTREG;
  268. }
  269. if (SUCCEEDED(hres)) {
  270. *phinst = hinst;
  271. } else {
  272. FreeLibrary(hinst);
  273. }
  274. } else {
  275. /*
  276. * DLL does not exist.
  277. */
  278. hres = REGDB_E_CLASSNOTREG;
  279. }
  280. } else {
  281. /*
  282. * No threading model or bad threading model.
  283. */
  284. hres = REGDB_E_CLASSNOTREG;
  285. }
  286. } else {
  287. /*
  288. * No InprocServer32.
  289. */
  290. hres = REGDB_E_CLASSNOTREG;
  291. }
  292. RegCloseKey(hk);
  293. } else {
  294. /*
  295. * CLSID not registered.
  296. */
  297. hres = REGDB_E_CLASSNOTREG;
  298. }
  299. } else {
  300. /*
  301. * Invalid CLSID string.
  302. */
  303. hres = REGDB_E_CLASSNOTREG;
  304. }
  305. ExitOleProcPpv(ppvOut);
  306. return hres;
  307. }
  308. #define ctchGuid (1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  309. LPCTSTR
  310. _ParseHex(
  311. LPCTSTR ptsz,
  312. LPBYTE *ppb,
  313. int cb,
  314. TCHAR tchDelim
  315. )
  316. {
  317. if (ptsz) {
  318. int i = cb * 2;
  319. DWORD dwParse = 0;
  320. do {
  321. DWORD uch;
  322. uch = (TBYTE)*ptsz - TEXT('0');
  323. if (uch < 10) { /* a decimal digit */
  324. } else {
  325. uch = (*ptsz | 0x20) - TEXT('a');
  326. if (uch < 6) { /* a hex digit */
  327. uch += 10;
  328. } else {
  329. return 0; /* Parse error */
  330. }
  331. }
  332. dwParse = (dwParse << 4) + uch;
  333. ptsz++;
  334. } while (--i);
  335. if (tchDelim && *ptsz++ != tchDelim) return 0; /* Parse error */
  336. for (i = 0; i < cb; i++) {
  337. (*ppb)[i] = ((LPBYTE)&dwParse)[i];
  338. }
  339. *ppb += cb;
  340. }
  341. return ptsz;
  342. } // _ParseHex
  343. LPCSTR
  344. _ParseHexA(
  345. LPCSTR psz,
  346. LPBYTE *ppb,
  347. int cb,
  348. CHAR chDelim
  349. )
  350. {
  351. if (psz) {
  352. int i = cb * 2;
  353. DWORD dwParse = 0;
  354. do {
  355. DWORD uch;
  356. uch = (BYTE)*psz - '0';
  357. if (uch < 10) { /* a decimal digit */
  358. } else {
  359. uch = (*psz | 0x20) - 'a';
  360. if (uch < 6) { /* a hex digit */
  361. uch += 10;
  362. } else {
  363. return 0; /* Parse error */
  364. }
  365. }
  366. dwParse = (dwParse << 4) + uch;
  367. psz++;
  368. } while (--i);
  369. if (chDelim && *psz++ != chDelim) return 0; /* Parse error */
  370. for (i = 0; i < cb; i++) {
  371. (*ppb)[i] = ((LPBYTE)&dwParse)[i];
  372. }
  373. *ppb += cb;
  374. }
  375. return psz;
  376. } // _ParseHexA
  377. BOOL
  378. ParseGUID(
  379. LPGUID pguid,
  380. LPCTSTR ptsz
  381. )
  382. {
  383. if (lstrlen(ptsz) == ctchGuid - 1 && *ptsz == TEXT('{')) {
  384. ptsz++;
  385. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 4, TEXT('-'));
  386. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 2, TEXT('-'));
  387. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 2, TEXT('-'));
  388. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  389. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, TEXT('-'));
  390. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  391. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  392. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  393. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  394. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, 0 );
  395. ptsz = _ParseHex(ptsz, (LPBYTE *)&pguid, 1, TEXT('}'));
  396. return (ptsz == NULL) ? FALSE : TRUE ;
  397. } else {
  398. return 0;
  399. }
  400. } // ParseGUID
  401. BOOL
  402. ParseGUIDA(
  403. LPGUID pguid,
  404. LPCSTR psz
  405. )
  406. {
  407. if (lstrlenA(psz) == ctchGuid - 1 && *psz == '{') {
  408. psz++;
  409. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 4, '-');
  410. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 2, '-');
  411. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 2, '-');
  412. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
  413. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, '-');
  414. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
  415. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
  416. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
  417. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
  418. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, 0 );
  419. psz = _ParseHexA(psz, (LPBYTE *)&pguid, 1, '}');
  420. return (psz == NULL) ? FALSE : TRUE ;
  421. } else {
  422. return 0;
  423. }
  424. } // ParseGUID