Counter Strike : Global Offensive Source Code
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.

224 lines
5.8 KiB

  1. //=========== (C) Copyright 2015 Valve, L.L.C. All rights reserved. ===========
  2. //
  3. // The copyright to the contents herein is the property of Valve, L.L.C.
  4. // The contents may be used and/or copied only with the written permission of
  5. // Valve, L.L.C., or in accordance with the terms and conditions stipulated in
  6. // the agreement/contract under which the contents have been supplied.
  7. //
  8. // Shares dynamic loading of COM/ole32/oleaut32 out of tier0.
  9. //=============================================================================
  10. #include "tier0/platform_com.h"
  11. #include "tier0/threadtools.h"
  12. #ifdef PLATFORM_WINDOWS
  13. typedef int32 ThreadInitOnce_t;
  14. typedef class CSysModule* PlatModule_t;
  15. #define PLAT_MODULE_INVALID ( (PlatModule_t)0 )
  16. static PlatCOMFunctions_t g_COMFunctions;
  17. static PlatModule_t g_hCOM;
  18. static ThreadInitOnce_t g_COMFunctionsInit;
  19. static const char *g_COMFunctionNames[] =
  20. {
  21. "CoInitializeEx",
  22. "CoUninitialize",
  23. "CoCreateInstance",
  24. "CoTaskMemAlloc",
  25. "CoTaskMemRealloc",
  26. "CoTaskMemFree",
  27. };
  28. enum PlatGetProcAddressesFlags_t
  29. {
  30. k_nPlatGetProcAddresses_Default = 0x00000000,
  31. k_nPlatGetProcAddresses_Optional = 0x00000001,
  32. };
  33. // Plat_GetProcAddresses copied from Source2 platform.cpp
  34. // Added here to avoid changing platform.h...
  35. void *Plat_GetProcAddresses( const char *pModuleName,
  36. int nNames,
  37. const char **pNames,
  38. size_t nTotalPointerBytes,
  39. void *pPointers,
  40. size_t nTotalFlagsBytes,
  41. uint32 *pFlags,
  42. bool bFailFatal )
  43. {
  44. if ( (nTotalPointerBytes & (sizeof( void* ) - 1)) != 0 )
  45. {
  46. Plat_FatalError( "%s: invalid pointer byte count\n", __FUNCTION__ );
  47. }
  48. if ( (size_t)nNames != nTotalPointerBytes / sizeof( void* ) )
  49. {
  50. Plat_FatalError( "%s: different number of names and pointers\n", __FUNCTION__ );
  51. }
  52. if ( (nTotalFlagsBytes & (sizeof( *pFlags ) - 1)) != 0 )
  53. {
  54. Plat_FatalError( "%s: invalid flag byte count\n", __FUNCTION__ );
  55. }
  56. if ( pFlags )
  57. {
  58. if ( (size_t)nNames != nTotalFlagsBytes / sizeof( *pFlags ) )
  59. {
  60. Plat_FatalError( "%s: different number of names and flags\n", __FUNCTION__ );
  61. }
  62. }
  63. HMODULE hModule = ::LoadLibrary( pModuleName );
  64. if ( hModule == 0 )
  65. {
  66. if ( bFailFatal )
  67. {
  68. int nErr = GetLastError();
  69. Plat_FatalError( "%s: unable to load '%s', error %d\n", __FUNCTION__, pModuleName, nErr );
  70. }
  71. return NULL;
  72. }
  73. void** pFunc = (void**)pPointers;
  74. for ( int i = 0; i < nNames; i++ )
  75. {
  76. uint32 nFlags = pFlags ? pFlags[i] : 0;
  77. *pFunc = ::GetProcAddress( hModule, pNames[i] );
  78. if ( !*pFunc &&
  79. (nFlags & k_nPlatGetProcAddresses_Optional) == 0 )
  80. {
  81. if ( bFailFatal )
  82. {
  83. Plat_FatalError( "%s: unable to find %s in '%s'\n", __FUNCTION__, pNames[i], pModuleName );
  84. }
  85. ::FreeLibrary( hModule );
  86. memset( pPointers, 0, nTotalPointerBytes );
  87. return NULL;
  88. }
  89. pFunc++;
  90. }
  91. return hModule;
  92. }
  93. static bool Plat_LoadCOM_Once( ThreadInitOnce_t *pMarker )
  94. {
  95. const char *pCOMName = "ole32.dll";
  96. g_hCOM = (PlatModule_t)Plat_GetProcAddresses( pCOMName,
  97. ARRAYSIZE( g_COMFunctionNames ),
  98. g_COMFunctionNames,
  99. sizeof( g_COMFunctions ),
  100. &g_COMFunctions,
  101. 0,
  102. NULL,
  103. false );
  104. // We always succeed in this routine as we
  105. // handle failure at a higher level.
  106. return true;
  107. }
  108. PlatCOMFunctions_t *Plat_LoadCOM()
  109. {
  110. ThreadInitOnceCall( &g_COMFunctionsInit, Plat_LoadCOM_Once );
  111. return &g_COMFunctions;
  112. }
  113. PlatCOMFunctions_t *Plat_CheckCOM()
  114. {
  115. if ( g_hCOM == PLAT_MODULE_INVALID )
  116. {
  117. return NULL;
  118. }
  119. return &g_COMFunctions;
  120. }
  121. PlatCOMFunctions_t *Plat_RequireCOM()
  122. {
  123. if ( g_hCOM == PLAT_MODULE_INVALID )
  124. {
  125. Plat_FatalError( "Unable to load COM\n" );
  126. }
  127. return &g_COMFunctions;
  128. }
  129. void Plat_UnloadCOM()
  130. {
  131. // We do not unload COM currently but we have a stub
  132. // that callers should use so that we can drop in unloading
  133. // if we need it in the future.
  134. }
  135. static PlatOleAutFunctions_t g_OleAutFunctions;
  136. static PlatModule_t g_hOleAut;
  137. static ThreadInitOnce_t g_OleAutFunctionsInit;
  138. static const char *g_OleAutFunctionNames[] =
  139. {
  140. "VariantInit",
  141. "VariantClear",
  142. "VariantCopy",
  143. "SysAllocString",
  144. "SysAllocStringByteLen",
  145. "SysAllocStringLen",
  146. "SysFreeString",
  147. "SysReAllocString",
  148. "SysReAllocStringLen",
  149. "SysStringByteLen",
  150. "SysStringLen",
  151. };
  152. static bool Plat_LoadOleAut_Once( ThreadInitOnce_t *pMarker )
  153. {
  154. const char *pOleAutName = "oleaut32.dll";
  155. g_hOleAut = (PlatModule_t)Plat_GetProcAddresses( pOleAutName,
  156. ARRAYSIZE( g_OleAutFunctionNames ),
  157. g_OleAutFunctionNames,
  158. sizeof( g_OleAutFunctions ),
  159. &g_OleAutFunctions,
  160. 0,
  161. NULL,
  162. false );
  163. // We always succeed in this routine as we
  164. // handle failure at a higher level.
  165. return true;
  166. }
  167. PlatOleAutFunctions_t *Plat_LoadOleAut()
  168. {
  169. ThreadInitOnceCall( &g_OleAutFunctionsInit, Plat_LoadOleAut_Once );
  170. return &g_OleAutFunctions;
  171. }
  172. PlatOleAutFunctions_t *Plat_CheckOleAut()
  173. {
  174. if ( g_hOleAut == PLAT_MODULE_INVALID )
  175. {
  176. return NULL;
  177. }
  178. return &g_OleAutFunctions;
  179. }
  180. PlatOleAutFunctions_t *Plat_RequireOleAut()
  181. {
  182. if ( g_hOleAut == PLAT_MODULE_INVALID )
  183. {
  184. Plat_FatalError( "Unable to load oleaut32\n" );
  185. }
  186. return &g_OleAutFunctions;
  187. }
  188. void Plat_UnloadOleAut()
  189. {
  190. // We do not unload oleaut32 currently but we have a stub
  191. // that callers should use so that we can drop in unloading
  192. // if we need it in the future.
  193. }
  194. #endif // #ifdef PLATFORM_WINDOWS