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.

351 lines
8.2 KiB

  1. // File: clclsfct.cpp
  2. //
  3. // IClassFactory and related routines
  4. //
  5. // ULONG DLLAddRef(void);
  6. // ULONG DLLRelease(void);
  7. //
  8. // STDAPI DllCanUnloadNow(void);
  9. // VOID DllLock(void);
  10. // VOID DllRelease(void);
  11. //
  12. //////////////////////////////////////////////////////////////////////////
  13. #include "precomp.h"
  14. #include "clclsfct.h"
  15. // from imanager.cpp
  16. PIUnknown NewNmManager(OBJECTDESTROYEDPROC ObjectDestroyed);
  17. CCLASSCONSTRUCTOR s_cclscnstr[] =
  18. {
  19. {&CLSID_NmManager2, &NewNmManager},
  20. };
  21. // DLL reference count == number of class factories +
  22. // number of URLs +
  23. // LockServer() count
  24. ULONG s_ulcDLLRef = 0;
  25. ///////////////////////////////////////////////////////////////////////////
  26. /* G E T C L A S S C O N S T R U C T O R */
  27. /*-------------------------------------------------------------------------
  28. %%Function: GetClassConstructor
  29. -------------------------------------------------------------------------*/
  30. HRESULT GetClassConstructor(REFCLSID rclsid, PNEWOBJECTPROC pNewObject)
  31. {
  32. HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  33. UINT u;
  34. ASSERT(IsValidREFCLSID(rclsid));
  35. ASSERT(IS_VALID_WRITE_PTR(pNewObject, NEWOBJECTPROC));
  36. *pNewObject = NULL;
  37. for (u = 0; u < ARRAY_ELEMENTS(s_cclscnstr); u++)
  38. {
  39. if (rclsid == *(s_cclscnstr[u].pcclsid))
  40. {
  41. *pNewObject = s_cclscnstr[u].NewObject;
  42. hr = S_OK;
  43. }
  44. }
  45. ASSERT((hr == S_OK &&
  46. IS_VALID_CODE_PTR(*pNewObject, NEWOBJECTPROC)) ||
  47. (hr == CLASS_E_CLASSNOTAVAILABLE &&
  48. ! *pNewObject));
  49. return hr;
  50. }
  51. VOID STDMETHODCALLTYPE DLLObjectDestroyed(void)
  52. {
  53. TRACE_OUT(("DLLObjectDestroyed(): Object destroyed."));
  54. DllRelease();
  55. }
  56. /****************************** Public Functions *****************************/
  57. ULONG DLLAddRef(void)
  58. {
  59. ASSERT(s_ulcDLLRef < ULONG_MAX);
  60. ULONG ulcRef = ++s_ulcDLLRef;
  61. DbgMsgRefCount("DLLAddRef(): DLL reference count is now %lu.", ulcRef);
  62. return ulcRef;
  63. }
  64. ULONG DLLRelease(void)
  65. {
  66. ULONG ulcRef;
  67. if (s_ulcDLLRef > 0)
  68. {
  69. s_ulcDLLRef--;
  70. }
  71. ulcRef = s_ulcDLLRef;
  72. DbgMsgRefCount("DLLRelease(): DLL reference count is now %lu.", ulcRef);
  73. return ulcRef;
  74. }
  75. PULONG GetDLLRefCountPtr(void)
  76. {
  77. return(&s_ulcDLLRef);
  78. }
  79. /********************************** Methods **********************************/
  80. CCLClassFactory::CCLClassFactory(NEWOBJECTPROC NewObject,
  81. OBJECTDESTROYEDPROC ObjectDestroyed) :
  82. RefCount(ObjectDestroyed)
  83. {
  84. // Don't validate this until after construction.
  85. ASSERT(IS_VALID_CODE_PTR(NewObject, NEWOBJECTPROC));
  86. m_NewObject = NewObject;
  87. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  88. }
  89. CCLClassFactory::~CCLClassFactory(void)
  90. {
  91. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  92. m_NewObject = NULL;
  93. }
  94. ULONG STDMETHODCALLTYPE CCLClassFactory::AddRef(void)
  95. {
  96. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  97. ULONG ulcRef = RefCount::AddRef();
  98. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  99. return ulcRef;
  100. }
  101. ULONG STDMETHODCALLTYPE CCLClassFactory::Release(void)
  102. {
  103. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  104. ULONG ulcRef = RefCount::Release();
  105. return ulcRef;
  106. }
  107. HRESULT STDMETHODCALLTYPE CCLClassFactory::QueryInterface(REFIID riid, PVOID *ppvObject)
  108. {
  109. HRESULT hr = S_OK;
  110. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  111. ASSERT(IsValidREFIID(riid));
  112. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  113. if (riid == IID_IClassFactory)
  114. {
  115. *ppvObject = (PIClassFactory)this;
  116. ASSERT(IS_VALID_INTERFACE_PTR((PIClassFactory)*ppvObject, IClassFactory));
  117. TRACE_OUT(("CCLClassFactory::QueryInterface(): Returning IClassFactory."));
  118. }
  119. else if (riid == IID_IUnknown)
  120. {
  121. *ppvObject = (PIUnknown)this;
  122. ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
  123. TRACE_OUT(("CCLClassFactory::QueryInterface(): Returning IUnknown."));
  124. }
  125. else
  126. {
  127. *ppvObject = NULL;
  128. hr = E_NOINTERFACE;
  129. TRACE_OUT(("CCLClassFactory::QueryInterface(): Called on unknown interface."));
  130. }
  131. if (hr == S_OK)
  132. {
  133. AddRef();
  134. }
  135. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  136. return hr;
  137. }
  138. HRESULT STDMETHODCALLTYPE CCLClassFactory::CreateInstance(PIUnknown piunkOuter,
  139. REFIID riid, PVOID *ppvObject)
  140. {
  141. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  142. ASSERT(! piunkOuter || IS_VALID_INTERFACE_PTR(piunkOuter, IUnknown));
  143. ASSERT(IsValidREFIID(riid));
  144. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  145. *ppvObject = NULL;
  146. if (NULL != piunkOuter)
  147. {
  148. WARNING_OUT(("CCLClassFactory::CreateInstance(): Aggregation not supported."));
  149. return CLASS_E_NOAGGREGATION;
  150. }
  151. PIUnknown piunk = (*m_NewObject)( (void(__stdcall *)(void)) &DLLObjectDestroyed);
  152. if (NULL == piunk)
  153. {
  154. return E_OUTOFMEMORY;
  155. }
  156. DllLock();
  157. HRESULT hr = piunk->QueryInterface(riid, ppvObject);
  158. // N.b., the Release() method will destroy the object if the
  159. // QueryInterface() method failed.
  160. piunk->Release();
  161. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  162. return hr;
  163. }
  164. HRESULT STDMETHODCALLTYPE CCLClassFactory::LockServer(BOOL fLock)
  165. {
  166. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  167. if (fLock)
  168. {
  169. DllLock();
  170. }
  171. else
  172. {
  173. DllRelease();
  174. }
  175. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  176. return S_OK;
  177. }
  178. /***************************** Exported Functions ****************************/
  179. /* D L L G E T C L A S S O B J E C T */
  180. /*-------------------------------------------------------------------------
  181. %%Function: DllGetClassObject
  182. -------------------------------------------------------------------------*/
  183. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PVOID *ppvObject)
  184. {
  185. ASSERT(IsValidREFCLSID(rclsid));
  186. ASSERT(IsValidREFIID(riid));
  187. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  188. *ppvObject = NULL;
  189. NEWOBJECTPROC NewObject;
  190. HRESULT hr = GetClassConstructor(rclsid, &NewObject);
  191. if (S_OK != hr)
  192. {
  193. WARNING_OUT(("DllGetClassObject(): Called on unknown class."));
  194. return hr;
  195. }
  196. if ((riid != IID_IUnknown) && (riid != IID_IClassFactory))
  197. {
  198. WARNING_OUT(("DllGetClassObject(): Called on unknown interface."));
  199. return E_NOINTERFACE;
  200. }
  201. PCCLClassFactory pcf = new CCLClassFactory(NewObject,
  202. (void(__stdcall *)(void)) &DLLObjectDestroyed);
  203. if (NULL == pcf)
  204. {
  205. return E_OUTOFMEMORY;
  206. }
  207. if (riid == IID_IClassFactory)
  208. {
  209. *ppvObject = (PIClassFactory)pcf;
  210. ASSERT(IS_VALID_INTERFACE_PTR((PIClassFactory)*ppvObject, IClassFactory));
  211. TRACE_OUT(("DllGetClassObject(): Returning IClassFactory."));
  212. }
  213. else
  214. {
  215. ASSERT(riid == IID_IUnknown);
  216. *ppvObject = (PIUnknown)pcf;
  217. ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
  218. TRACE_OUT(("DllGetClassObject(): Returning IUnknown."));
  219. }
  220. DllLock();
  221. TRACE_OUT(("DllGetClassObject(): Created a new class factory."));
  222. return S_OK;
  223. }
  224. /* D L L C A N U N L O A D N O W */
  225. /*-------------------------------------------------------------------------
  226. %%Function: DllCanUnloadNow
  227. -------------------------------------------------------------------------*/
  228. STDAPI DllCanUnloadNow(void)
  229. {
  230. HRESULT hr = (s_ulcDLLRef > 0) ? S_FALSE : S_OK;
  231. TRACE_OUT(("DllCanUnloadNow(): DLL reference count is %lu.", s_ulcDLLRef));
  232. return hr;
  233. }
  234. /* D L L L O C K */
  235. /*-------------------------------------------------------------------------
  236. %%Function: DllLock
  237. -------------------------------------------------------------------------*/
  238. VOID DllLock(void)
  239. {
  240. InterlockedIncrement((LPLONG) &s_ulcDLLRef);
  241. DbgMsgRefCount("Ref: DllLock count=%d", s_ulcDLLRef);
  242. }
  243. /* D L L R E L E A S E */
  244. /*-------------------------------------------------------------------------
  245. %%Function: DllRelease
  246. -------------------------------------------------------------------------*/
  247. VOID DllRelease(void)
  248. {
  249. LONG cRef = InterlockedDecrement((LPLONG) &s_ulcDLLRef);
  250. #ifdef DEBUG
  251. DbgMsgRefCount("Ref: DllLock count=%d", s_ulcDLLRef);
  252. if (0 == cRef)
  253. {
  254. WARNING_OUT(("NMCOM.DLL Can now be unloaded"));
  255. }
  256. #endif
  257. }