Leaked source code of windows server 2003
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.

385 lines
10 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: comutil.cpp
  6. * Content: Contains implementation of COM helper functions for DPLAY8 project.
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 06/07/00 rmt Created
  12. * 06/15/2000 rmt Fixed small bug in COM_CoCreateInstance which was causing AV
  13. * 06/27/00 rmt Added abstraction for COM_Co(Un)Initialize
  14. * 07/06/00 rmt Modified to match updated creg usage
  15. * 08/08/2000 rmt Bug #41736 - AV in call to lstrcpy by COM_GetDllName
  16. * 01/11/2001 rmt MANBUG #48487 - DPLAY: Crashes if CoCreate() isn't called.
  17. * 03/14/2001 rmt WINBUG #342420 - Restore COM emulation layer to operation.
  18. *@@END_MSINTERNAL
  19. *
  20. ***************************************************************************/
  21. #include "dncmni.h"
  22. #include "comutil.h"
  23. #ifndef DPNBUILD_NOCOMEMULATION
  24. #undef DPF_SUBCOMP
  25. #define DPF_SUBCOMP DN_SUBCOMP_COMMON
  26. HRESULT COM_GetDLLName( const GUID* pguidCLSID, TCHAR *szPath, DWORD *pdwSizeInBytes );
  27. typedef HRESULT (WINAPI *PFNDLLGETCLASSOBJECT)(REFCLSID rclsid,REFIID riid,LPVOID *ppvObj );
  28. typedef HRESULT (WINAPI *PFNDLLCANUNLOADNOW)(void);
  29. CBilink g_blComEntriesGlobal;
  30. DNCRITICAL_SECTION csComEntriesLock;
  31. typedef struct _COMDLL_ENTRY
  32. {
  33. HMODULE hDLL;
  34. TCHAR szFileName[_MAX_PATH];
  35. GUID clsid;
  36. PFNDLLGETCLASSOBJECT pfnGetClassObject;
  37. PFNDLLCANUNLOADNOW pfnCanUnloadNow;
  38. CBilink blComEntries;
  39. } COMDLL_ENTRY, *PCOMDLL_ENTRY;
  40. #undef DPF_MODNAME
  41. #define DPF_MODNAME "COM_Init"
  42. HRESULT COM_Init()
  43. {
  44. g_blComEntriesGlobal.Initialize();
  45. if (DNInitializeCriticalSection( &csComEntriesLock ) == FALSE)
  46. {
  47. return DPNERR_OUTOFMEMORY;
  48. }
  49. return DPN_OK;
  50. }
  51. #undef DPF_MODNAME
  52. #define DPF_MODNAME "COM_Free"
  53. void COM_Free()
  54. {
  55. CBilink *pblSearch;
  56. PCOMDLL_ENTRY pEntry;
  57. pblSearch = g_blComEntriesGlobal.GetNext();
  58. while( pblSearch != &g_blComEntriesGlobal )
  59. {
  60. pEntry = CONTAINING_OBJECT( pblSearch, COMDLL_ENTRY, blComEntries );
  61. pblSearch = pblSearch->GetNext();
  62. FreeLibrary( pEntry->hDLL );
  63. DNFree(pEntry);
  64. }
  65. DNDeleteCriticalSection( &csComEntriesLock );
  66. }
  67. #undef DPF_MODNAME
  68. #define DPF_MODNAME "COM_CoInitialize"
  69. HRESULT COM_CoInitialize( void * pvParam )
  70. {
  71. return CoInitializeEx( pvParam, COINIT_MULTITHREADED );
  72. }
  73. #undef DPF_MODNAME
  74. #define DPF_MODNAME "COM_CoUninitialize"
  75. void COM_CoUninitialize()
  76. {
  77. CoUninitialize();
  78. }
  79. #undef DPF_MODNAME
  80. #define DPF_MODNAME "COM_GetEntry"
  81. HRESULT COM_GetEntry( const GUID* pclsid, PCOMDLL_ENTRY *ppEntry )
  82. {
  83. CBilink *pblSearch;
  84. PCOMDLL_ENTRY pEntry;
  85. HRESULT hr;
  86. DWORD dwSize;
  87. DNEnterCriticalSection( &csComEntriesLock );
  88. pblSearch = g_blComEntriesGlobal.GetNext();
  89. while( pblSearch != &g_blComEntriesGlobal )
  90. {
  91. pEntry = CONTAINING_OBJECT( pblSearch, COMDLL_ENTRY, blComEntries );
  92. // This should never happen, but makes prefix happy
  93. if( !pEntry )
  94. {
  95. DNASSERT( FALSE );
  96. DNLeaveCriticalSection( &csComEntriesLock );
  97. return DPNERR_GENERIC;
  98. }
  99. if( pEntry->clsid == *pclsid )
  100. {
  101. *ppEntry = pEntry;
  102. DNLeaveCriticalSection( &csComEntriesLock );
  103. return DPN_OK;
  104. }
  105. pblSearch = pblSearch->GetNext();
  106. }
  107. pEntry = (COMDLL_ENTRY*) DNMalloc(sizeof(COMDLL_ENTRY));
  108. if (pEntry == NULL)
  109. {
  110. DPFERR( "Error allocating COM entry" );
  111. hr = DPNERR_OUTOFMEMORY;
  112. goto LOAD_FAILED;
  113. }
  114. memset( pEntry, 0x00, sizeof( COMDLL_ENTRY ) );
  115. pEntry->clsid = *pclsid;
  116. pEntry->blComEntries.Initialize();
  117. dwSize = _MAX_PATH * sizeof(TCHAR);
  118. hr = COM_GetDLLName( pclsid, pEntry->szFileName, &dwSize );
  119. if( FAILED( hr ) )
  120. {
  121. DPFERR( "Unable to find DLL name for COM object" );
  122. goto LOAD_FAILED;
  123. }
  124. pEntry->hDLL = LoadLibrary( pEntry->szFileName );
  125. if( !pEntry->hDLL )
  126. {
  127. #ifdef DBG
  128. hr = GetLastError();
  129. DPFX(DPFPREP, 0, "Unable to load libary err=0x%x", hr );
  130. #endif // DBG
  131. hr = DPNERR_GENERIC;
  132. goto LOAD_FAILED;
  133. }
  134. pEntry->pfnGetClassObject = (PFNDLLGETCLASSOBJECT) GetProcAddress( pEntry->hDLL, _TWINCE("DllGetClassObject") );
  135. if (pEntry->pfnGetClassObject == NULL)
  136. {
  137. #ifdef DBG
  138. hr = GetLastError();
  139. DPFX(DPFPREP, 0, "Unable to get \"DllGetClassObject\" function pointer err=0x%x", hr );
  140. #endif // DBG
  141. hr = DPNERR_GENERIC;
  142. goto LOAD_FAILED;
  143. }
  144. pEntry->pfnCanUnloadNow = (PFNDLLCANUNLOADNOW) GetProcAddress( pEntry->hDLL, _TWINCE("DllCanUnloadNow") );
  145. if (pEntry->pfnCanUnloadNow == NULL)
  146. {
  147. #ifdef DBG
  148. hr = GetLastError();
  149. DPFX(DPFPREP, 0, "Unable to get \"DllCanUnloadNow\" function pointer err=0x%x", hr );
  150. #endif // DBG
  151. hr = DPNERR_GENERIC;
  152. goto LOAD_FAILED;
  153. }
  154. pEntry->blComEntries.InsertBefore( &g_blComEntriesGlobal );
  155. DNLeaveCriticalSection( &csComEntriesLock );
  156. *ppEntry = pEntry;
  157. return DPN_OK;
  158. LOAD_FAILED:
  159. if( pEntry != NULL )
  160. {
  161. if( pEntry->hDLL != NULL )
  162. {
  163. FreeLibrary( pEntry->hDLL );
  164. }
  165. DNFree(pEntry);
  166. }
  167. DNLeaveCriticalSection( &csComEntriesLock );
  168. return hr;
  169. }
  170. #undef DPF_MODNAME
  171. #define DPF_MODNAME "COM_GetDLLName"
  172. HRESULT COM_GetDLLName( const GUID* pguidCLSID, TCHAR *szPath, DWORD *pdwSizeInBytes )
  173. {
  174. CRegistry cregRoot;
  175. CRegistry cregCLSID;
  176. CRegistry cregInProc;
  177. HRESULT hr = DPN_OK;
  178. BOOL fSuccess;
  179. WCHAR *wszTmpPath = NULL;
  180. DWORD dwTmpSize = 0;
  181. fSuccess = cregRoot.Open( HKEY_CLASSES_ROOT, L"CLSID", TRUE, FALSE );
  182. if( !fSuccess )
  183. {
  184. DPFX(DPFPREP, 0, "Error opening HKEY_CLASSES_ROOT\\CLSID" );
  185. hr = E_FAIL;
  186. goto COM_GETDLLNAME_ERROR;
  187. }
  188. fSuccess = cregCLSID.Open( cregRoot, pguidCLSID, TRUE, FALSE );
  189. if( !fSuccess )
  190. {
  191. DPFX(DPFPREP, 0, "Error opening specified CLSID" );
  192. hr = E_FAIL;
  193. goto COM_GETDLLNAME_ERROR;
  194. }
  195. fSuccess = cregInProc.Open( cregCLSID, L"InprocServer32", TRUE, FALSE );
  196. if( !fSuccess )
  197. {
  198. DPFX(DPFPREP, 0, "Error opening inprocserver key" );
  199. hr = E_FAIL;
  200. goto COM_GETDLLNAME_ERROR;
  201. }
  202. cregCLSID.Close();
  203. cregRoot.Close();
  204. fSuccess = cregInProc.ReadString( L"", wszTmpPath, &dwTmpSize );
  205. if( !dwTmpSize )
  206. {
  207. DPFX(DPFPREP, 0, "Error opening default key" );
  208. hr = E_FAIL;
  209. goto COM_GETDLLNAME_ERROR;
  210. }
  211. if( dwTmpSize > *pdwSizeInBytes )
  212. {
  213. DPFX(DPFPREP, 0, "Buffer too small" );
  214. hr = DPNERR_BUFFERTOOSMALL;
  215. *pdwSizeInBytes = dwTmpSize;
  216. goto COM_GETDLLNAME_ERROR;
  217. }
  218. *pdwSizeInBytes = dwTmpSize;
  219. if (!szPath)
  220. {
  221. DPFX(DPFPREP, 0, "Invalid param - NULL szPath" );
  222. hr = DPNERR_INVALIDPARAM;
  223. goto COM_GETDLLNAME_ERROR;
  224. }
  225. #ifdef UNICODE
  226. wszTmpPath = szPath;
  227. #else
  228. wszTmpPath = (WCHAR*) DNMalloc(dwTmpSize * sizeof(WCHAR));
  229. if( !wszTmpPath )
  230. {
  231. DPFX(DPFPREP, 0, "Error allocating memory" );
  232. hr = DPNERR_OUTOFMEMORY;
  233. goto COM_GETDLLNAME_ERROR;
  234. }
  235. #endif // UNICODE
  236. fSuccess = cregInProc.ReadString( L"", wszTmpPath, &dwTmpSize );
  237. if( !fSuccess )
  238. {
  239. DPFX(DPFPREP, 0, "Error opening default key" );
  240. hr = E_FAIL;
  241. goto COM_GETDLLNAME_ERROR;
  242. }
  243. #ifndef UNICODE
  244. if( FAILED( hr = STR_jkWideToAnsi(szPath,wszTmpPath, *pdwSizeInBytes ) ) )
  245. {
  246. DPFX(DPFPREP, 0, "Error converting path to DLL to ANSI hr=0x%x", hr );
  247. hr = E_FAIL;
  248. }
  249. DNFree(wszTmpPath);
  250. #endif // !UNICODE
  251. return hr;
  252. COM_GETDLLNAME_ERROR:
  253. #ifndef UNICODE
  254. if( wszTmpPath )
  255. {
  256. DNFree(wszTmpPath);
  257. }
  258. #endif // !UNICODE
  259. return hr;
  260. }
  261. // DP_CoCreateInstance
  262. //
  263. // This CoCreateInstance can be used instead of CoCreateInstance and will manually perform the
  264. // steps neccessary to do a CoCreateInstance if COM has not been initialized.
  265. //
  266. #undef DPF_MODNAME
  267. #define DPF_MODNAME "COM_CoCreateInstance"
  268. STDAPI COM_CoCreateInstance( REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv, BOOL fWarnUser )
  269. {
  270. HRESULT hr;
  271. PCOMDLL_ENTRY pEntry;
  272. IClassFactory *pClassFactory;
  273. hr = CoCreateInstance( rclsid, pUnkOuter, dwClsContext, riid, ppv );
  274. if( hr == CO_E_NOTINITIALIZED )
  275. {
  276. if( fWarnUser )
  277. {
  278. DPFX(DPFPREP, 0, "=====================================================================================" );
  279. DPFX(DPFPREP, 0, "" );
  280. DPFX(DPFPREP, 0, "The DirectPlay8/Voice create functions are no longer supported. It is recommended" );
  281. DPFX(DPFPREP, 0, "that your application be updated to use CoCreateInstance instead." );
  282. DPFX(DPFPREP, 0, "" );
  283. DPFX(DPFPREP, 0, "=====================================================================================" );
  284. }
  285. hr = COM_GetEntry( &rclsid, &pEntry );
  286. if( FAILED( hr ) )
  287. return hr;
  288. hr = (*pEntry->pfnGetClassObject)( rclsid, IID_IClassFactory, (void **) &pClassFactory );
  289. if( FAILED( hr ) )
  290. {
  291. DPFX(DPFPREP, 0, "Failed getting class object on dynamic entry hr=0x%x", hr );
  292. return hr;
  293. }
  294. hr = pClassFactory->lpVtbl->CreateInstance( pClassFactory, pUnkOuter, riid, ppv );
  295. if( FAILED( hr ) )
  296. {
  297. DPFX(DPFPREP, 0, "Class factory returned an error hr=0x%x", hr );
  298. }
  299. pClassFactory->lpVtbl->Release(pClassFactory);
  300. return hr;
  301. }
  302. return hr;
  303. }
  304. #endif // !DPNBUILD_NOCOMEMULATION