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.

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