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.

317 lines
8.4 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // File: combase.cpp
  4. //
  5. // Contents: COM server functionality.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "private.h"
  9. #include "combase.h"
  10. #include "regsvr.h"
  11. extern CClassFactory *g_ObjectInfo[];
  12. LONG g_cRefDll = -1; // -1 /w no refs, for win95 InterlockedIncrement/Decrement compat
  13. void FreeGlobalObjects(void);
  14. //+---------------------------------------------------------------------------
  15. //
  16. // DllAddRef
  17. //
  18. //----------------------------------------------------------------------------
  19. void DllAddRef(void)
  20. {
  21. if (InterlockedIncrement(&g_cRefDll) == 0) // g_cRefDll == -1 with zero refs
  22. {
  23. DllInit();
  24. }
  25. }
  26. //+---------------------------------------------------------------------------
  27. //
  28. // DllRelease
  29. //
  30. //----------------------------------------------------------------------------
  31. void DllRelease(void)
  32. {
  33. if (InterlockedDecrement(&g_cRefDll) < 0) // g_cRefDll == -1 with zero refs
  34. {
  35. EnterCriticalSection(GetServerCritSec());
  36. // need to check ref again after grabbing mutex
  37. if (g_ObjectInfo[0] != NULL)
  38. {
  39. FreeGlobalObjects();
  40. }
  41. Assert(g_cRefDll == -1);
  42. LeaveCriticalSection(GetServerCritSec());
  43. DllUninit();
  44. }
  45. }
  46. //+---------------------------------------------------------------------------
  47. //
  48. // CClassFactory declaration with IClassFactory Interface
  49. //
  50. //----------------------------------------------------------------------------
  51. class CClassFactory : public IClassFactory
  52. {
  53. public:
  54. // IUnknown methods
  55. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj);
  56. STDMETHODIMP_(ULONG) AddRef(void);
  57. STDMETHODIMP_(ULONG) Release(void);
  58. // IClassFactory methods
  59. STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj);
  60. STDMETHODIMP LockServer(BOOL fLock);
  61. // Constructor
  62. CClassFactory(const CLSID *pclsid, HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj))
  63. : _pclsid(pclsid)
  64. {
  65. _pfnCreateInstance = pfnCreateInstance;
  66. }
  67. public:
  68. const CLSID *_pclsid;
  69. HRESULT (*_pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj);
  70. };
  71. //+---------------------------------------------------------------------------
  72. //
  73. // CClassFactory::QueryInterface
  74. //
  75. //----------------------------------------------------------------------------
  76. STDAPI CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
  77. {
  78. if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  79. {
  80. *ppvObj = this;
  81. DllAddRef();
  82. return NOERROR;
  83. }
  84. *ppvObj = NULL;
  85. return E_NOINTERFACE;
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // CClassFactory::AddRef
  90. //
  91. //----------------------------------------------------------------------------
  92. STDAPI_(ULONG) CClassFactory::AddRef()
  93. {
  94. DllAddRef();
  95. return g_cRefDll+1; // -1 w/ no refs
  96. }
  97. //+---------------------------------------------------------------------------
  98. //
  99. // CClassFactory::Release
  100. //
  101. //----------------------------------------------------------------------------
  102. STDAPI_(ULONG) CClassFactory::Release()
  103. {
  104. DllRelease();
  105. return g_cRefDll+1; // -1 w/ no refs
  106. }
  107. //+---------------------------------------------------------------------------
  108. //
  109. // CClassFactory::CreateInstance
  110. //
  111. //----------------------------------------------------------------------------
  112. STDAPI CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
  113. {
  114. return _pfnCreateInstance(pUnkOuter, riid, ppvObj);
  115. }
  116. //+---------------------------------------------------------------------------
  117. //
  118. // CClassFactory::LockServer
  119. //
  120. //----------------------------------------------------------------------------
  121. STDAPI CClassFactory::LockServer(BOOL fLock)
  122. {
  123. if (fLock)
  124. {
  125. DllAddRef();
  126. }
  127. else
  128. {
  129. DllRelease();
  130. }
  131. return S_OK;
  132. }
  133. //+---------------------------------------------------------------------------
  134. //
  135. // BuildGlobalObjects
  136. //
  137. //----------------------------------------------------------------------------
  138. void BuildGlobalObjects(void)
  139. {
  140. const OBJECT_ENTRY *pEntry;
  141. int i;
  142. // Build CClassFactory Objects
  143. i = 0;
  144. for (pEntry = &c_rgCoClassFactoryTable[0]; pEntry->pfnCreateInstance != NULL; pEntry++)
  145. {
  146. g_ObjectInfo[i++] = new CClassFactory(pEntry->pclsid, pEntry->pfnCreateInstance);
  147. }
  148. // You can add more object info here.
  149. // Don't forget to increase number of item for g_ObjectInfo[],
  150. }
  151. //+---------------------------------------------------------------------------
  152. //
  153. // FreeGlobalObjects
  154. //
  155. //----------------------------------------------------------------------------
  156. void FreeGlobalObjects(void)
  157. {
  158. const OBJECT_ENTRY *pEntry;
  159. pEntry = &c_rgCoClassFactoryTable[0];
  160. // Free CClassFactory Objects
  161. // we know the size of g_ObjectInfo must match c_rgCoClassFactoryTable, which is null terminated
  162. for (int i = 0; pEntry->pfnCreateInstance != NULL; i++, pEntry++)
  163. {
  164. if (NULL != g_ObjectInfo[i])
  165. {
  166. delete g_ObjectInfo[i];
  167. g_ObjectInfo[i] = NULL;
  168. }
  169. }
  170. }
  171. //+---------------------------------------------------------------------------
  172. //
  173. // DllGetClassObject
  174. //
  175. //----------------------------------------------------------------------------
  176. HRESULT COMBase_DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppvObj)
  177. {
  178. const OBJECT_ENTRY *pEntry;
  179. if (ppvObj == NULL)
  180. return E_INVALIDARG;
  181. if (g_ObjectInfo[0] == NULL)
  182. {
  183. EnterCriticalSection(GetServerCritSec());
  184. // need to check ref again after grabbing mutex
  185. if (g_ObjectInfo[0] == NULL)
  186. {
  187. BuildGlobalObjects();
  188. }
  189. LeaveCriticalSection(GetServerCritSec());
  190. }
  191. if (IsEqualIID(riid, IID_IClassFactory) ||
  192. IsEqualIID(riid, IID_IUnknown))
  193. {
  194. // we know the size of g_ObjectInfo must match c_rgCoClassFactoryTable, which is null terminated
  195. pEntry = &c_rgCoClassFactoryTable[0];
  196. for (int i = 0; pEntry->pfnCreateInstance != NULL; i++, pEntry++)
  197. {
  198. if (NULL != g_ObjectInfo[i] &&
  199. IsEqualGUID(rclsid, *g_ObjectInfo[i]->_pclsid))
  200. {
  201. *ppvObj = (void *)g_ObjectInfo[i];
  202. DllAddRef(); // class factory holds DLL ref count
  203. return NOERROR;
  204. }
  205. }
  206. }
  207. *ppvObj = NULL;
  208. return CLASS_E_CLASSNOTAVAILABLE;
  209. }
  210. //+---------------------------------------------------------------------------
  211. //
  212. // DllCanUnloadNow
  213. //
  214. //----------------------------------------------------------------------------
  215. HRESULT COMBase_DllCanUnloadNow(void)
  216. {
  217. if (g_cRefDll >= 0) // -1 with no refs
  218. return S_FALSE;
  219. return S_OK;
  220. }
  221. //+---------------------------------------------------------------------------
  222. //
  223. // DllRegisterServer
  224. //
  225. //----------------------------------------------------------------------------
  226. HRESULT COMBase_DllRegisterServer(void)
  227. {
  228. const OBJECT_ENTRY *pEntry;
  229. TCHAR achPath[MAX_PATH+1];
  230. HRESULT hr = E_FAIL;
  231. if (GetModuleFileName(GetServerHINSTANCE(), achPath, ARRAYSIZE(achPath)) == 0)
  232. goto Exit;
  233. achPath[ARRAYSIZE(achPath)-1] = 0;
  234. for (pEntry = &c_rgCoClassFactoryTable[0]; pEntry->pfnCreateInstance != NULL; pEntry++)
  235. {
  236. if (!RegisterServer(*pEntry->pclsid, pEntry->pszDesc, achPath, TEXT("Apartment"), NULL))
  237. goto Exit;
  238. }
  239. hr = S_OK;
  240. Exit:
  241. return hr;
  242. }
  243. //+---------------------------------------------------------------------------
  244. //
  245. // DllUnregisterServer
  246. //
  247. //----------------------------------------------------------------------------
  248. HRESULT COMBase_DllUnregisterServer(void)
  249. {
  250. const OBJECT_ENTRY *pEntry;
  251. HRESULT hr = E_FAIL;
  252. for (pEntry = &c_rgCoClassFactoryTable[0]; pEntry->pfnCreateInstance != NULL; pEntry++)
  253. {
  254. if (FAILED(hr = RegisterServer(*pEntry->pclsid, NULL, NULL, NULL, NULL) ? S_OK : E_FAIL))
  255. goto Exit;
  256. }
  257. hr = S_OK;
  258. Exit:
  259. return hr;
  260. }