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.

492 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1998 - 1999
  3. Module Name:
  4. noncom
  5. Abstract:
  6. This module provides a means to bypass COM, such that typical in-process
  7. COM objects can be called directly in any operating system.
  8. Author:
  9. Doug Barlow (dbarlow) 1/4/1999
  10. Notes:
  11. ?Notes?
  12. --*/
  13. #ifndef WIN32_LEAN_AND_MEAN
  14. #define WIN32_LEAN_AND_MEAN
  15. #endif
  16. #include <windows.h>
  17. #include <scardlib.h>
  18. #include <ole2.h>
  19. #include <unknwn.h>
  20. #include <noncom.h>
  21. typedef HRESULT
  22. (STDAPICALLTYPE *GetClassObjectFunc)(
  23. REFCLSID rclsid,
  24. REFIID riid,
  25. LPVOID * ppv);
  26. #ifdef UNDER_TEST
  27. typedef struct {
  28. IID iid;
  29. HINSTANCE hDll;
  30. GetClassObjectFunc pgco;
  31. } NonComModuleStruct;
  32. class NonComControlStruct
  33. {
  34. public:
  35. DWORD dwInitializeCount;
  36. CRITICAL_SECTION csLock;
  37. CDynamicArray<NonComModuleStruct> rgModules;
  38. };
  39. static NonComControlStruct *l_pControl = NULL;
  40. /*++
  41. NoCoInitialize:
  42. This function initializes the NonCOM subsystem.
  43. Arguments:
  44. pvReserved - [in] Reserved; must be NULL.
  45. Return Value:
  46. S_OK - The NonCOM subsystem was initialized correctly.
  47. S_FALSE - The NonCOM library is already initialized.
  48. Remarks:
  49. ?Remarks?
  50. Author:
  51. Doug Barlow (dbarlow) 1/4/1999
  52. --*/
  53. STDAPI
  54. NoCoInitialize(
  55. LPVOID pvReserved)
  56. {
  57. HRESULT hReturn = E_UNEXPECTED;
  58. //
  59. // Validate parameters.
  60. //
  61. if (NULL != pvReserved)
  62. {
  63. hReturn = E_INVALIDARG;
  64. goto ErrorExit;
  65. }
  66. //
  67. // Create the Control structure, if necessary.
  68. //
  69. if (NULL == l_pControl)
  70. {
  71. l_pControl = new NonComControlStruct;
  72. if (NULL == l_pControl)
  73. {
  74. hReturn = E_OUTOFMEMORY;
  75. goto ErrorExit;
  76. }
  77. InitializeCriticalSection(&l_pControl->csLock);
  78. CCritSect csLock(&l_pControl->csLock);
  79. // ?code? Database initialization
  80. l_pControl->dwInitializeCount = 1;
  81. }
  82. else
  83. {
  84. CCritSect csLock(&l_pControl->csLock);
  85. ASSERT(0 < l_pControl->dwInitializeCount);
  86. l_pControl->dwInitializeCount += 1;
  87. }
  88. return S_OK;
  89. ErrorExit:
  90. return hReturn;
  91. }
  92. /*++
  93. NoCoUninitialize:
  94. Closes the NonCOM library on the current apartment, unloads all DLLs
  95. loaded by the apartment, frees any other resources that the apartment
  96. maintains, and forces all RPC connections on the apartment to close.
  97. Arguments:
  98. None
  99. Return Value:
  100. None
  101. Remarks:
  102. ?Remarks?
  103. Author:
  104. Doug Barlow (dbarlow) 1/4/1999
  105. --*/
  106. STDAPI_(void)
  107. NoCoUninitialize(
  108. void)
  109. {
  110. DWORD dwI;
  111. NonComModuleStruct *pMod;
  112. if (NULL != l_pControl)
  113. {
  114. {
  115. CCritSect csLock(&l_pControl->csLock);
  116. ASSERT(0 < l_pControl->dwInitializeCount);
  117. l_pControl->dwInitializeCount -= 1;
  118. if (0 == l_pControl->dwInitializeCount)
  119. {
  120. for (dwI = l_pControl->rgModules.Count(); 0 < dwI;)
  121. {
  122. pMod = l_pControl->rgModules[--dwI];
  123. FreeLibrary(pMod->hDll);
  124. delete pMod;
  125. }
  126. l_pControl->rgModules.Clear();
  127. }
  128. }
  129. DeleteCriticalSection(&l_pControl->csLock);
  130. delete l_pControl;
  131. l_pControl = NULL;
  132. }
  133. }
  134. #endif
  135. /*++
  136. NoCoGetClassObject:
  137. Provides a pointer to an interface on a class object associated with a
  138. specified CLSID. CoGetClassObject locates, and if necessary, dynamically
  139. loads the executable code required to do this.
  140. Arguments:
  141. rclsid - [in] CLSID associated with the data and code that you will use to
  142. create the objects.
  143. riid - [in] Reference to the identifier of the interface, which will be
  144. supplied in ppv on successful return. This interface will be used to
  145. communicate with the class object.
  146. ppv - [out] Address of pointer variable that receives the interface
  147. pointer requested in riid. Upon successful return, *ppv contains the
  148. requested interface pointer.
  149. Return Value:
  150. S_OK - Location and connection to the specified class object was successful.
  151. REGDB_E_CLASSNOTREG - CLSID is not properly registered. Can also indicate
  152. that the value you specified in dwClsContext is not in the registry.
  153. E_NOINTERFACE - Either the object pointed to by ppv does not support the
  154. interface identified by riid, or the QueryInterface operation on the
  155. class object returned E_NOINTERFACE.
  156. REGDB_E_READREGDB - Error reading the registration database.
  157. CO_E_DLLNOTFOUND - In-process DLL not found.
  158. E_ACCESSDENIED - General access failure.
  159. Remarks:
  160. ?Remarks?
  161. Author:
  162. Doug Barlow (dbarlow) 1/4/1999
  163. --*/
  164. STDAPI
  165. NoCoGetClassObject(
  166. REFCLSID rclsid,
  167. REFIID riid,
  168. LPVOID * ppv)
  169. {
  170. DWORD dwStatus;
  171. HRESULT hReturn = E_UNEXPECTED;
  172. TCHAR szGuid[40];
  173. CBuffer szDll;
  174. HINSTANCE hDll = NULL;
  175. GetClassObjectFunc pfGetObject;
  176. #ifdef UNDER_TEST
  177. if (NULL == l_pControl)
  178. {
  179. hReturn = NoCoInitialize(NULL);
  180. if (S_OK != hReturn)
  181. goto ErrorExit;
  182. }
  183. {
  184. DWORD dwI;
  185. CCritSect(&l_pControl->csLock);
  186. for (dwI = l_pControl->rgModules.Count(); 0 < dwI;)
  187. {
  188. dwI -= 1;
  189. if (IsEqualGUID(l_pControl->rgModules[dwI]->iid, rclsid))
  190. {
  191. try
  192. {
  193. hReturn = (*l_pControl->rgModules[dwI]->pgco)(rclsid, riid, ppv);
  194. }
  195. catch (...)
  196. {
  197. hReturn = E_UNEXPECTED;
  198. }
  199. goto ErrorExit;
  200. }
  201. }
  202. }
  203. #endif
  204. StringFromGuid(&rclsid, szGuid);
  205. try
  206. {
  207. //
  208. // Open the Class Registry Database.
  209. //
  210. CRegistry regClsId(
  211. HKEY_CLASSES_ROOT,
  212. TEXT("ClsID"),
  213. KEY_READ);
  214. dwStatus = regClsId.Status(TRUE);
  215. if (ERROR_SUCCESS != dwStatus)
  216. {
  217. hReturn = REGDB_E_READREGDB;
  218. goto ErrorExit;
  219. }
  220. //
  221. // Look up the specified Class.
  222. //
  223. CRegistry regClass(
  224. regClsId,
  225. szGuid,
  226. KEY_READ);
  227. dwStatus = regClass.Status(TRUE);
  228. if (ERROR_SUCCESS != dwStatus)
  229. {
  230. hReturn = REGDB_E_CLASSNOTREG;
  231. goto ErrorExit;
  232. }
  233. //
  234. // Get the registered InProcess Server.
  235. //
  236. CRegistry regServer(
  237. regClass,
  238. TEXT("InprocServer32"),
  239. KEY_READ);
  240. dwStatus = regServer.Status(TRUE);
  241. if (ERROR_SUCCESS != dwStatus)
  242. {
  243. hReturn = REGDB_E_CLASSNOTREG;
  244. goto ErrorExit;
  245. }
  246. //
  247. // Get the handler DLL name.
  248. //
  249. regServer.GetValue(TEXT(""), szDll);
  250. }
  251. catch (DWORD dwError)
  252. {
  253. switch (dwError)
  254. {
  255. case ERROR_OUTOFMEMORY:
  256. hReturn = E_OUTOFMEMORY;
  257. break;
  258. default:
  259. hReturn = HRESULT_FROM_WIN32(dwError);
  260. }
  261. goto ErrorExit;
  262. }
  263. //
  264. // We've got the target DLL. Load it and look for the entrypoint.
  265. //
  266. hDll = LoadLibrary((LPCTSTR)szDll.Access());
  267. if (NULL == hDll)
  268. {
  269. hReturn = CO_E_DLLNOTFOUND;
  270. goto ErrorExit;
  271. }
  272. pfGetObject = (GetClassObjectFunc)GetProcAddress(
  273. hDll,
  274. "DllGetClassObject");
  275. if (NULL == pfGetObject)
  276. {
  277. hReturn = E_NOINTERFACE;
  278. goto ErrorExit;
  279. }
  280. #ifdef UNDER_TEST
  281. {
  282. NonComModuleStruct *pMod = new NonComModuleStruct;
  283. if (NULL == pMod)
  284. {
  285. hReturn = E_OUTOFMEMORY;
  286. goto ErrorExit;
  287. }
  288. pMod->hDll = hDll;
  289. CopyMemory(&pMod->iid, &rclsid, sizeof(IID));
  290. pMod->pgco = pfGetObject;
  291. try
  292. {
  293. l_pControl->rgModules.Add(pMod);
  294. }
  295. catch (...)
  296. {
  297. delete pMod;
  298. }
  299. }
  300. #endif
  301. try
  302. {
  303. hReturn = (*pfGetObject)(rclsid, riid, ppv);
  304. }
  305. catch (...)
  306. {
  307. hReturn = E_UNEXPECTED;
  308. }
  309. if (S_OK != hReturn)
  310. goto ErrorExit;
  311. //
  312. // Add the Handler to our database.
  313. //
  314. // ?code? -- No database yet.
  315. hDll = NULL;
  316. ASSERT(NULL == hDll);
  317. return S_OK;
  318. ErrorExit:
  319. if (NULL != hDll)
  320. FreeLibrary(hDll);
  321. return hReturn;
  322. }
  323. /*++
  324. NoCoCreateInstance:
  325. Creates a single uninitialized object of the class associated with a
  326. specified CLSID. Call CoCreateInstance when you want to create only one
  327. object on the local system.
  328. Arguments:
  329. rclsid - [in] CLSID associated with the data and code that will be used to
  330. create the object.
  331. pUnkOuter - [in] If NULL, indicates that the object is not being created as
  332. part of an aggregate. If non-NULL, pointer to the aggregate object's
  333. IUnknown interface (the controlling IUnknown).
  334. riid - [in] Reference to the identifier of the interface to be used to
  335. communicate with the object.
  336. ppv - [out] Address of pointer variable that receives the interface
  337. pointer requested in riid. Upon successful return, *ppv contains the
  338. requested interface pointer.
  339. Return Value:
  340. S_OK - An instance of the specified object class was successfully created.
  341. REGDB_E_CLASSNOTREG - A specified class is not registered in the
  342. registration database. Also can indicate that the type of server you
  343. requested in the CLSCTX enumeration is not registered or the values
  344. for the server types in the registry are corrupt.
  345. Author:
  346. Doug Barlow (dbarlow) 1/15/1999
  347. --*/
  348. STDAPI
  349. NoCoCreateInstance(
  350. REFCLSID rclsid,
  351. LPUNKNOWN pUnkOuter,
  352. REFIID riid,
  353. LPVOID * ppv)
  354. {
  355. HRESULT hReturn = E_UNEXPECTED;
  356. IClassFactory *pCF = NULL;
  357. hReturn = NoCoGetClassObject(rclsid, IID_IClassFactory, (LPVOID*)&pCF);
  358. if (S_OK != hReturn)
  359. goto ErrorExit;
  360. hReturn = pCF->CreateInstance(pUnkOuter, riid, ppv);
  361. if (S_OK != hReturn)
  362. goto ErrorExit;
  363. pCF->Release();
  364. pCF = NULL;
  365. return S_OK;
  366. ErrorExit:
  367. if (NULL != pCF)
  368. pCF->Release();
  369. return hReturn;
  370. }