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.

247 lines
6.6 KiB

  1. /*****************************************************************************
  2. *
  3. * DIOleDup.c
  4. *
  5. * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * Functions that sort-of duplicate what OLE does.
  10. *
  11. * Contents:
  12. *
  13. * DICoCreateInstance
  14. *
  15. *****************************************************************************/
  16. #include "dinputpr.h"
  17. /*****************************************************************************
  18. *
  19. * The sqiffle for this file.
  20. *
  21. *****************************************************************************/
  22. #define sqfl sqflOleDup
  23. /*****************************************************************************
  24. *
  25. * @doc INTERNAL
  26. *
  27. * @func HRESULT | _CreateInstance |
  28. *
  29. * Worker function for <f DICoCreateInstance>.
  30. *
  31. * @parm REFCLSID | rclsid |
  32. *
  33. * The <t CLSID> to create.
  34. *
  35. * @parm LPCTSTR | ptszDll |
  36. *
  37. * The name of the DLL to load.
  38. *
  39. * @parm LPUNKNOWN | punkOuter |
  40. *
  41. * Controlling unknown for aggregation.
  42. *
  43. * @parm RIID | riid |
  44. *
  45. * Interface to obtain.
  46. *
  47. * @parm PPV | ppvOut |
  48. *
  49. * Receives a pointer to the created object if successful.
  50. *
  51. * @parm HINSTANCE * | phinst |
  52. *
  53. * Receives the instance handle of the in-proc DLL that was
  54. * loaded. <f FreeLibrary> this DLL when you are finished
  55. * with the object.
  56. *
  57. * Note that since we don't implement a binder, this means
  58. * that you cannot give the returned pointer away to anybody
  59. * you don't control; otherwise, you won't know when to
  60. * free the DLL.
  61. *
  62. * @returns
  63. *
  64. * Standard OLE status code.
  65. *
  66. *****************************************************************************/
  67. HRESULT INTERNAL
  68. _CreateInstance(REFCLSID rclsid, LPCTSTR ptszDll, LPUNKNOWN punkOuter,
  69. RIID riid, PPV ppvOut, HINSTANCE *phinst)
  70. {
  71. HRESULT hres;
  72. HINSTANCE hinst;
  73. hinst = LoadLibrary(ptszDll);
  74. if (hinst) {
  75. LPFNGETCLASSOBJECT DllGetClassObject;
  76. DllGetClassObject = (LPFNGETCLASSOBJECT)
  77. GetProcAddress(hinst, "DllGetClassObject");
  78. if (DllGetClassObject) {
  79. IClassFactory *pcf;
  80. hres = DllGetClassObject(rclsid, &IID_IClassFactory, &pcf);
  81. if (SUCCEEDED(hres)) {
  82. hres = pcf->lpVtbl->CreateInstance(pcf, punkOuter,
  83. riid, ppvOut);
  84. pcf->lpVtbl->Release(pcf);
  85. /*
  86. * Some people forget to adhere to
  87. * the OLE spec, which requires that *ppvOut be
  88. * set to zero on failure.
  89. */
  90. if (FAILED(hres)) {
  91. if (*ppvOut) {
  92. RPF("ERROR! CoCreateInstance: %s forgot to zero "
  93. "out *ppvOut on failure path", ptszDll);
  94. }
  95. *ppvOut = 0;
  96. }
  97. }
  98. } else {
  99. /*
  100. * DLL does not export GetClassObject.
  101. */
  102. hres = REGDB_E_CLASSNOTREG;
  103. }
  104. if (SUCCEEDED(hres)) {
  105. *phinst = hinst;
  106. } else {
  107. FreeLibrary(hinst);
  108. }
  109. } else {
  110. /*
  111. * DLL does not exist.
  112. */
  113. hres = REGDB_E_CLASSNOTREG;
  114. }
  115. return hres;
  116. }
  117. /*****************************************************************************
  118. *
  119. * @doc INTERNAL
  120. *
  121. * @func HRESULT | DICoCreateInstance |
  122. *
  123. * Private version of CoCreateInstance that doesn't use OLE.
  124. *
  125. * @parm LPTSTR | ptszClsid |
  126. *
  127. * The string version of the <t CLSID> to create.
  128. *
  129. * @parm LPUNKNOWN | punkOuter |
  130. *
  131. * Controlling unknown for aggregation.
  132. *
  133. * @parm RIID | riid |
  134. *
  135. * Interface to obtain.
  136. *
  137. * @parm PPV | ppvOut |
  138. *
  139. * Receives a pointer to the created object if successful.
  140. *
  141. * @parm HINSTANCE * | phinst |
  142. *
  143. * Receives the instance handle of the in-proc DLL that was
  144. * loaded. <f FreeLibrary> this DLL when you are finished
  145. * with the object.
  146. *
  147. * Note that since we don't implement a binder, this means
  148. * that you cannot give the returned pointer away to anybody
  149. * you don't control; otherwise, you won't know when to
  150. * free the DLL.
  151. *
  152. * @returns
  153. *
  154. * Standard OLE status code.
  155. *
  156. *****************************************************************************/
  157. STDMETHODIMP
  158. DICoCreateInstance(LPTSTR ptszClsid, LPUNKNOWN punkOuter,
  159. RIID riid, PPV ppvOut, HINSTANCE *phinst)
  160. {
  161. HRESULT hres;
  162. CLSID clsid;
  163. EnterProcI(DICoCreateInstance, (_ "spG", ptszClsid, punkOuter, riid));
  164. *ppvOut = 0;
  165. *phinst = 0;
  166. if (ParseGUID(&clsid, ptszClsid)) {
  167. HKEY hk;
  168. LONG lRc;
  169. TCHAR tszKey[ctchGuid + 40]; /* 40 is more than enough */
  170. /*
  171. * Look up the CLSID in HKEY_CLASSES_ROOT.
  172. */
  173. wsprintf(tszKey, TEXT("CLSID\\%s\\InProcServer32"), ptszClsid);
  174. lRc = RegOpenKeyEx(HKEY_CLASSES_ROOT, tszKey, 0,
  175. KEY_QUERY_VALUE, &hk);
  176. if (lRc == ERROR_SUCCESS) {
  177. TCHAR tszDll[MAX_PATH];
  178. DWORD cb;
  179. cb = cbX(tszDll);
  180. lRc = RegQueryValue(hk, 0, tszDll, &cb);
  181. if (lRc == ERROR_SUCCESS) {
  182. TCHAR tszModel[20]; /* more than enough */
  183. lRc = RegQueryString(hk, TEXT("ThreadingModel"),
  184. tszModel, cA(tszModel));
  185. if (lRc == ERROR_SUCCESS &&
  186. ((lstrcmpi(tszModel, TEXT("Both"))==0x0) ||
  187. (lstrcmpi(tszModel, TEXT("Free"))==0x0))) {
  188. hres = _CreateInstance(&clsid, tszDll, punkOuter,
  189. riid, ppvOut, phinst);
  190. } else {
  191. /*
  192. * No threading model or bad threading model.
  193. */
  194. hres = REGDB_E_CLASSNOTREG;
  195. }
  196. } else {
  197. /*
  198. * No InprocServer32.
  199. */
  200. hres = REGDB_E_CLASSNOTREG;
  201. }
  202. RegCloseKey(hk);
  203. } else {
  204. /*
  205. * CLSID not registered.
  206. */
  207. hres = REGDB_E_CLASSNOTREG;
  208. }
  209. } else {
  210. /*
  211. * Invalid CLSID string.
  212. */
  213. hres = REGDB_E_CLASSNOTREG;
  214. }
  215. ExitOleProcPpv(ppvOut);
  216. return hres;
  217. }