Source code of Windows XP (NT5)
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.

490 lines
11 KiB

  1. /*
  2. * clsfact.cpp - IClassFactory implementation.
  3. *
  4. * Taken from URL code - essentially identical to DavidDi's original code
  5. *
  6. * Created: ChrisPi 9-11-95
  7. *
  8. */
  9. /* Headers
  10. **********/
  11. #include "precomp.h"
  12. #include "CLinkID.h"
  13. #include "clrefcnt.hpp"
  14. #include "clenumft.hpp"
  15. #include "clCnfLnk.hpp"
  16. #include "clclsfct.h"
  17. #define INITGUID
  18. #include <initguid.h>
  19. #include <olectlid.h>
  20. #include <confguid.h>
  21. // from niMgr.cpp
  22. PIUnknown NewNmManager(OBJECTDESTROYEDPROC ObjectDestroyed);
  23. // from imconfmg.cpp
  24. PIUnknown NewConfMgr(OBJECTDESTROYEDPROC ObjectDestroyed);
  25. /* Module Constants
  26. *******************/
  27. #pragma data_seg(DATA_SEG_READ_ONLY)
  28. CCLASSCONSTRUCTOR s_cclscnstr[] =
  29. {
  30. // { &CLSID_ConferenceManager, &NewNmManager },
  31. { &CLSID_ConfLink, &NewConfLink },
  32. // { &CLSID_NmManager, &NewNmManager },
  33. // { &CLSID_MIMEFileTypesPropSheetHook, &NewMIMEHook },
  34. // { &CLSID_Internet, &NewInternet },
  35. };
  36. #pragma data_seg()
  37. /* Module Variables
  38. *******************/
  39. #pragma data_seg(DATA_SEG_PER_INSTANCE)
  40. // DLL reference count == number of class factories +
  41. // number of URLs +
  42. // LockServer() count
  43. ULONG s_ulcDLLRef = 0;
  44. #pragma data_seg()
  45. /***************************** Private Functions *****************************/
  46. HRESULT GetClassConstructor(REFCLSID rclsid,
  47. PNEWOBJECTPROC pNewObject)
  48. {
  49. HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  50. UINT u;
  51. ASSERT(IsValidREFCLSID(rclsid));
  52. ASSERT(IS_VALID_WRITE_PTR(pNewObject, NEWOBJECTPROC));
  53. *pNewObject = NULL;
  54. for (u = 0; u < ARRAY_ELEMENTS(s_cclscnstr); u++)
  55. {
  56. if (rclsid == *(s_cclscnstr[u].pcclsid))
  57. {
  58. *pNewObject = s_cclscnstr[u].NewObject;
  59. hr = S_OK;
  60. }
  61. }
  62. ASSERT((hr == S_OK &&
  63. IS_VALID_CODE_PTR(*pNewObject, NEWOBJECTPROC)) ||
  64. (hr == CLASS_E_CLASSNOTAVAILABLE &&
  65. ! *pNewObject));
  66. return(hr);
  67. }
  68. VOID STDMETHODCALLTYPE DLLObjectDestroyed(void)
  69. {
  70. TRACE_OUT(("DLLObjectDestroyed(): Object destroyed."));
  71. DllRelease();
  72. }
  73. PIUnknown NewConfLink(OBJECTDESTROYEDPROC ObjectDestroyed)
  74. {
  75. ASSERT(! ObjectDestroyed ||
  76. IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
  77. TRACE_OUT(("NewConfLink(): Creating a new ConfLink."));
  78. return((PIUnknown) (PIConferenceLink) new CConfLink(ObjectDestroyed));
  79. }
  80. #if 0
  81. PIUnknown NewMIMEHook(OBJECTDESTROYEDPROC ObjectDestroyed)
  82. {
  83. ASSERT(! ObjectDestroyed ||
  84. IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
  85. TRACE_OUT(("NewMIMEHook(): Creating a new MIMEHook."));
  86. return((PIUnknown)(PIShellPropSheetExt)new(MIMEHook(ObjectDestroyed)));
  87. }
  88. PIUnknown NewInternet(OBJECTDESTROYEDPROC ObjectDestroyed)
  89. {
  90. ASSERT(! ObjectDestroyed ||
  91. IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
  92. TRACE_OUT(("NewInternet(): Creating a new Internet."));
  93. return((PIUnknown)(PIShellPropSheetExt)new(Internet(ObjectDestroyed)));
  94. }
  95. #endif // 0
  96. #ifdef DEBUG
  97. BOOL IsValidPCCCLClassFactory(PCCCLClassFactory pccf)
  98. {
  99. return(IS_VALID_READ_PTR(pccf, CCCLClassFactory) &&
  100. IS_VALID_CODE_PTR(pccf->m_NewObject, NEWOBJECTPROC) &&
  101. IS_VALID_STRUCT_PTR((PCRefCount)pccf, CRefCount) &&
  102. IS_VALID_INTERFACE_PTR((PCIClassFactory)pccf, IClassFactory));
  103. }
  104. #endif
  105. /****************************** Public Functions *****************************/
  106. ULONG DLLAddRef(void)
  107. {
  108. ULONG ulcRef;
  109. ASSERT(s_ulcDLLRef < ULONG_MAX);
  110. ulcRef = ++s_ulcDLLRef;
  111. TRACE_OUT(("DLLAddRef(): DLL reference count is now %lu.",
  112. ulcRef));
  113. return(ulcRef);
  114. }
  115. ULONG DLLRelease(void)
  116. {
  117. ULONG ulcRef;
  118. if (EVAL(s_ulcDLLRef > 0))
  119. s_ulcDLLRef--;
  120. ulcRef = s_ulcDLLRef;
  121. TRACE_OUT(("DLLRelease(): DLL reference count is now %lu.",
  122. ulcRef));
  123. return(ulcRef);
  124. }
  125. PULONG GetDLLRefCountPtr(void)
  126. {
  127. return(&s_ulcDLLRef);
  128. }
  129. /********************************** Methods **********************************/
  130. CCLClassFactory::CCLClassFactory(NEWOBJECTPROC NewObject,
  131. OBJECTDESTROYEDPROC ObjectDestroyed) :
  132. RefCount(ObjectDestroyed)
  133. {
  134. DebugEntry(CCLClassFactory::CCLClassFactory);
  135. // Don't validate this until after construction.
  136. ASSERT(IS_VALID_CODE_PTR(NewObject, NEWOBJECTPROC));
  137. m_NewObject = NewObject;
  138. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  139. DebugExitVOID(CCLClassFactory::CCLClassFactory);
  140. return;
  141. }
  142. CCLClassFactory::~CCLClassFactory(void)
  143. {
  144. DebugEntry(CCLClassFactory::~CCLClassFactory);
  145. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  146. m_NewObject = NULL;
  147. // Don't validate this after destruction.
  148. DebugExitVOID(CCLClassFactory::~CCLClassFactory);
  149. return;
  150. }
  151. ULONG STDMETHODCALLTYPE CCLClassFactory::AddRef(void)
  152. {
  153. ULONG ulcRef;
  154. DebugEntry(CCLClassFactory::AddRef);
  155. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  156. ulcRef = RefCount::AddRef();
  157. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  158. DebugExitULONG(CCLClassFactory::AddRef, ulcRef);
  159. return(ulcRef);
  160. }
  161. ULONG STDMETHODCALLTYPE CCLClassFactory::Release(void)
  162. {
  163. ULONG ulcRef;
  164. DebugEntry(CCLClassFactory::Release);
  165. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  166. ulcRef = RefCount::Release();
  167. DebugExitULONG(CCLClassFactory::Release, ulcRef);
  168. return(ulcRef);
  169. }
  170. HRESULT STDMETHODCALLTYPE CCLClassFactory::QueryInterface(REFIID riid,
  171. PVOID *ppvObject)
  172. {
  173. HRESULT hr = S_OK;
  174. DebugEntry(CCLClassFactory::QueryInterface);
  175. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  176. ASSERT(IsValidREFIID(riid));
  177. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  178. if (riid == IID_IClassFactory)
  179. {
  180. *ppvObject = (PIClassFactory)this;
  181. ASSERT(IS_VALID_INTERFACE_PTR((PIClassFactory)*ppvObject, IClassFactory));
  182. TRACE_OUT(("CCLClassFactory::QueryInterface(): Returning IClassFactory."));
  183. }
  184. else if (riid == IID_IUnknown)
  185. {
  186. *ppvObject = (PIUnknown)this;
  187. ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
  188. TRACE_OUT(("CCLClassFactory::QueryInterface(): Returning IUnknown."));
  189. }
  190. else
  191. {
  192. *ppvObject = NULL;
  193. hr = E_NOINTERFACE;
  194. TRACE_OUT(("CCLClassFactory::QueryInterface(): Called on unknown interface."));
  195. }
  196. if (hr == S_OK)
  197. AddRef();
  198. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  199. // removed by ChrisPi CINTERFACE undeclared identifier
  200. // ASSERT(FAILED(hr) ||
  201. // IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
  202. DebugExitHRESULT(CCLClassFactory::QueryInterface, hr);
  203. return(hr);
  204. }
  205. HRESULT STDMETHODCALLTYPE CCLClassFactory::CreateInstance(PIUnknown piunkOuter,
  206. REFIID riid,
  207. PVOID *ppvObject)
  208. {
  209. HRESULT hr;
  210. DebugEntry(CCLClassFactory::CreateInstance);
  211. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  212. ASSERT(! piunkOuter ||
  213. IS_VALID_INTERFACE_PTR(piunkOuter, IUnknown));
  214. ASSERT(IsValidREFIID(riid));
  215. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  216. *ppvObject = NULL;
  217. if (! piunkOuter)
  218. {
  219. PIUnknown piunk;
  220. piunk = (*m_NewObject)( (void(__stdcall *)(void)) &DLLObjectDestroyed);
  221. if (piunk)
  222. {
  223. DllLock();
  224. hr = piunk->QueryInterface(riid, ppvObject);
  225. // N.b., the Release() method will destroy the object if the
  226. // QueryInterface() method failed.
  227. piunk->Release();
  228. }
  229. else
  230. hr = E_OUTOFMEMORY;
  231. }
  232. else
  233. {
  234. hr = CLASS_E_NOAGGREGATION;
  235. WARNING_OUT(("CCLClassFactory::CreateInstance(): Aggregation not supported."));
  236. }
  237. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  238. // removed by ChrisPi - see above
  239. // ASSERT(FAILED(hr) ||
  240. // IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
  241. DebugExitHRESULT(CCLClassFactory::CreateInstance, hr);
  242. return(hr);
  243. }
  244. HRESULT STDMETHODCALLTYPE CCLClassFactory::LockServer(BOOL bLock)
  245. {
  246. HRESULT hr;
  247. DebugEntry(CCLClassFactory::LockServer);
  248. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  249. // bLock may be any value.
  250. if (bLock)
  251. DllLock();
  252. else
  253. DllRelease();
  254. hr = S_OK;
  255. ASSERT(IS_VALID_STRUCT_PTR(this, CCCLClassFactory));
  256. DebugExitHRESULT(CCLClassFactory::LockServer, hr);
  257. return(hr);
  258. }
  259. /***************************** Exported Functions ****************************/
  260. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PVOID *ppvObject)
  261. {
  262. HRESULT hr = S_OK;
  263. NEWOBJECTPROC NewObject;
  264. DebugEntry(DllGetClassObject);
  265. ASSERT(IsValidREFCLSID(rclsid));
  266. ASSERT(IsValidREFIID(riid));
  267. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  268. *ppvObject = NULL;
  269. hr = GetClassConstructor(rclsid, &NewObject);
  270. if (hr == S_OK)
  271. {
  272. if (riid == IID_IUnknown ||
  273. riid == IID_IClassFactory)
  274. {
  275. PCCLClassFactory pcf;
  276. pcf = new CCLClassFactory(NewObject, (void(__stdcall *)(void)) &DLLObjectDestroyed);
  277. if (pcf)
  278. {
  279. if (riid == IID_IClassFactory)
  280. {
  281. *ppvObject = (PIClassFactory)pcf;
  282. ASSERT(IS_VALID_INTERFACE_PTR((PIClassFactory)*ppvObject, IClassFactory));
  283. TRACE_OUT(("DllGetClassObject(): Returning IClassFactory."));
  284. }
  285. else
  286. {
  287. ASSERT(riid == IID_IUnknown);
  288. *ppvObject = (PIUnknown)pcf;
  289. ASSERT(IS_VALID_INTERFACE_PTR((PIUnknown)*ppvObject, IUnknown));
  290. TRACE_OUT(("DllGetClassObject(): Returning IUnknown."));
  291. }
  292. DllLock();
  293. hr = S_OK;
  294. TRACE_OUT(("DllGetClassObject(): Created a new class factory."));
  295. }
  296. else
  297. hr = E_OUTOFMEMORY;
  298. }
  299. else
  300. {
  301. WARNING_OUT(("DllGetClassObject(): Called on unknown interface."));
  302. hr = E_NOINTERFACE;
  303. }
  304. }
  305. else
  306. WARNING_OUT(("DllGetClassObject(): Called on unknown class."));
  307. // removed by ChrisPi - see above
  308. // ASSERT(FAILED(hr) ||
  309. // IS_VALID_INTERFACE_PTR(*ppvObject, INTERFACE));
  310. DebugExitHRESULT(DllGetClassObject, hr);
  311. return(hr);
  312. }
  313. STDAPI DllCanUnloadNow(void)
  314. {
  315. HRESULT hr;
  316. DebugEntry(DllCanUnloadNow);
  317. hr = (s_ulcDLLRef > 0) ? S_FALSE : S_OK;
  318. TRACE_OUT(("DllCanUnloadNow(): DLL reference count is %lu.", s_ulcDLLRef));
  319. DebugExitHRESULT(DllCanUnloadNow, hr);
  320. return(hr);
  321. }
  322. void DllLock(void)
  323. {
  324. InterlockedIncrement((LPLONG) &s_ulcDLLRef);
  325. DBGAPI_TRACE("Ref: DllLock count=%d", s_ulcDLLRef);
  326. }
  327. void DllRelease(void)
  328. {
  329. LONG cRef = InterlockedDecrement((LPLONG) &s_ulcDLLRef);
  330. #ifdef DEBUG
  331. DBGAPI_TRACE("Ref: DllLock count=%d", s_ulcDLLRef);
  332. if (0 == cRef)
  333. WARNING_OUT(("MSCONF.DLL Can now be unloaded"));
  334. #endif
  335. }