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.

273 lines
5.8 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. DLLMAIN.CPP
  5. Abstract:
  6. DLL/COM helpers.
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include "commain.cpp"
  11. #include <statsync.h>
  12. void EmptyList();
  13. class CDllLifeControl : public CLifeControl
  14. {
  15. protected:
  16. long m_lCount;
  17. public:
  18. CDllLifeControl() : m_lCount(0) {}
  19. virtual BOOL ObjectCreated(IUnknown* pv)
  20. {
  21. InterlockedIncrement(&m_lCount);
  22. return TRUE;
  23. }
  24. virtual void ObjectDestroyed(IUnknown* pv)
  25. {
  26. InterlockedDecrement(&m_lCount);
  27. }
  28. virtual void AddRef(IUnknown* pv){}
  29. virtual void Release(IUnknown* pv){}
  30. HRESULT CanUnloadNow()
  31. {
  32. HRESULT hRes = (m_lCount == 0)?S_OK:S_FALSE;
  33. return hRes;
  34. }
  35. };
  36. CStaticCritSec g_CS;
  37. static BOOL g_bInit = FALSE;
  38. static BOOL g_fAttached = FALSE;
  39. CDllLifeControl g_LifeControl;
  40. CLifeControl* g_pLifeControl = &g_LifeControl;
  41. //
  42. // these 2 functions assume that g_CS is held.
  43. //
  44. HRESULT EnsureInitialized()
  45. {
  46. HRESULT hr;
  47. if ( g_bInit )
  48. {
  49. return S_OK;
  50. }
  51. hr = GlobalInitialize();
  52. if ( FAILED(hr) )
  53. {
  54. return hr;
  55. }
  56. g_bInit = TRUE;
  57. return S_OK;
  58. }
  59. void EnsureUninitialized()
  60. {
  61. if ( g_bInit )
  62. {
  63. GlobalUninitialize();
  64. g_bInit = FALSE;
  65. }
  66. }
  67. //***************************************************************************
  68. //
  69. // DllGetClassObject
  70. //
  71. // Purpose: Called by Ole when some client wants a a class factory. Return
  72. // one only if it is the sort of class this DLL supports.
  73. //
  74. //***************************************************************************
  75. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
  76. {
  77. HRESULT hr;
  78. if ( !g_fAttached ) return E_UNEXPECTED;
  79. CMyInCritSec ics( &g_CS );
  80. if ( !g_fAttached ) return E_UNEXPECTED;
  81. hr = EnsureInitialized();
  82. if ( FAILED(hr) )
  83. {
  84. return hr;
  85. }
  86. for(LIST_ENTRY * pEntry = g_ClassInfoHead.Flink;
  87. pEntry != &g_ClassInfoHead ;
  88. pEntry = pEntry->Flink)
  89. {
  90. CClassInfo* pInfo = CONTAINING_RECORD(pEntry,CClassInfo,m_Entry);
  91. if(*pInfo->m_pClsid == rclsid)
  92. {
  93. return pInfo->m_pFactory->QueryInterface(riid, ppv);
  94. }
  95. }
  96. return E_FAIL;
  97. }
  98. //***************************************************************************
  99. //
  100. // DllCanUnloadNow
  101. //
  102. // Purpose: Called periodically by Ole in order to determine if the
  103. // DLL can be freed.//
  104. // Return: TRUE if there are no objects in use and the class factory
  105. // isn't locked.
  106. //***************************************************************************
  107. STDAPI DllCanUnloadNow(void)
  108. {
  109. if ( !g_fAttached ) return S_FALSE;
  110. CMyInCritSec ics( &g_CS );
  111. if ( !g_fAttached ) return S_FALSE;
  112. if ( !g_bInit )
  113. {
  114. return S_OK;
  115. }
  116. HRESULT hres = g_LifeControl.CanUnloadNow();
  117. if( hres == S_OK )
  118. {
  119. if ( GlobalCanShutdown() )
  120. {
  121. EnsureUninitialized();
  122. return S_OK;
  123. }
  124. }
  125. return S_FALSE;
  126. }
  127. //***************************************************************************
  128. //
  129. // DllRegisterServer
  130. //
  131. // Purpose: Called during initialization or by regsvr32.
  132. //
  133. // Return: NOERROR if registration successful, error otherwise.
  134. //***************************************************************************
  135. STDAPI DllRegisterServer(void)
  136. {
  137. HRESULT hr;
  138. if ( !g_fAttached ) return E_UNEXPECTED;
  139. CMyInCritSec ics( &g_CS );
  140. if ( !g_fAttached ) return E_UNEXPECTED;
  141. hr = EnsureInitialized();
  142. if ( FAILED(hr) ) return hr;
  143. GlobalRegister();
  144. for(LIST_ENTRY * pEntry = g_ClassInfoHead.Flink;
  145. pEntry != &g_ClassInfoHead;
  146. pEntry = pEntry->Flink)
  147. {
  148. CClassInfo* pInfo = CONTAINING_RECORD(pEntry,CClassInfo,m_Entry);
  149. HRESULT hres = RegisterServer(pInfo, FALSE);
  150. if(FAILED(hres)) return hres;
  151. }
  152. return S_OK;
  153. }
  154. //***************************************************************************
  155. //
  156. // DllUnregisterServer
  157. //
  158. // Purpose: Called when it is time to remove the registry entries.
  159. //
  160. // Return: NOERROR if registration successful, error otherwise.
  161. //***************************************************************************
  162. STDAPI DllUnregisterServer(void)
  163. {
  164. HRESULT hr;
  165. if ( !g_fAttached ) return E_UNEXPECTED;
  166. CMyInCritSec ics( &g_CS );
  167. if ( !g_fAttached ) return E_UNEXPECTED;
  168. hr = EnsureInitialized();
  169. if ( FAILED(hr) )
  170. {
  171. return hr;
  172. }
  173. GlobalUnregister();
  174. for(LIST_ENTRY * pEntry = g_ClassInfoHead.Flink;
  175. pEntry != &g_ClassInfoHead;
  176. pEntry = pEntry->Flink)
  177. {
  178. CClassInfo* pInfo = CONTAINING_RECORD(pEntry,CClassInfo,m_Entry);
  179. HRESULT hres = UnregisterServer(pInfo, FALSE);
  180. if(FAILED(hres)) return hres;
  181. }
  182. return S_OK;
  183. }
  184. BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
  185. {
  186. if (DLL_PROCESS_ATTACH==ulReason)
  187. {
  188. SetModuleHandle(hInstance);
  189. g_fAttached = TRUE;
  190. DisableThreadLibraryCalls ( hInstance ) ;
  191. if (CStaticCritSec::anyFailure())
  192. return FALSE;
  193. }
  194. else if(DLL_PROCESS_DETACH==ulReason)
  195. {
  196. if ( g_fAttached )
  197. {
  198. GlobalPostUninitialize();
  199. CMyInCritSec ics( &g_CS );
  200. EmptyList();
  201. }
  202. // This will prevent us from performing any other logic
  203. // until we are attached to again.
  204. g_fAttached = FALSE;
  205. }
  206. return TRUE;
  207. }