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.

315 lines
7.2 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1998 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: classfac.c
  6. * Content: a generic class factory
  7. *
  8. *
  9. * This is a generic C class factory. All you need to do is implement
  10. * a function called DoCreateInstance that will create an instace of
  11. * your object.
  12. *
  13. * GP_ stands for "General Purpose"
  14. *
  15. * History:
  16. * Date By Reason
  17. * ==== == ======
  18. * 10/13/98 jwo Created it.
  19. * 04/11/00 rodtoll Added code for redirection for custom builds if registry bit is set
  20. * 08/23/2000 rodtoll DllCanUnloadNow always returning TRUE!
  21. * 10/05/2000 rodtoll Bug #46541 - DPVOICE: A/V linking to dpvoice.lib could cause application to fail init and crash
  22. ***************************************************************************/
  23. #include "dxvoicepch.h"
  24. HRESULT DVT_Create(LPDIRECTVOICESETUPOBJECT *piDVT);
  25. HRESULT DVS_Create(LPDIRECTVOICESERVEROBJECT *piDVS);
  26. HRESULT DVC_Create(LPDIRECTVOICECLIENTOBJECT *piDVC);
  27. #define EXP __declspec(dllexport)
  28. class CClassFactory : IClassFactory
  29. {
  30. public:
  31. CClassFactory(CLSID* pclsid) : m_lRefCnt(0), m_clsid(*pclsid) {}
  32. STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
  33. STDMETHOD_(ULONG, AddRef)()
  34. {
  35. return InterlockedIncrement(&m_lRefCnt);
  36. }
  37. STDMETHOD_(ULONG, Release)()
  38. {
  39. ULONG l = InterlockedDecrement(&m_lRefCnt);
  40. if (l == 0)
  41. {
  42. delete this;
  43. DecrementObjectCount();
  44. }
  45. return l;
  46. }
  47. STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj);
  48. STDMETHOD(LockServer)(BOOL fLock)
  49. {
  50. if( fLock )
  51. {
  52. InterlockedIncrement( &g_lNumLocks );
  53. }
  54. else
  55. {
  56. InterlockedDecrement( &g_lNumLocks );
  57. }
  58. return S_OK;
  59. }
  60. private:
  61. LONG m_lRefCnt;
  62. CLSID m_clsid;
  63. };
  64. STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, LPVOID* ppvObj)
  65. {
  66. *ppvObj = NULL;
  67. if( IsEqualIID(riid, IID_IClassFactory) ||
  68. IsEqualIID(riid, IID_IUnknown))
  69. {
  70. InterlockedIncrement( &m_lRefCnt );
  71. *ppvObj = this;
  72. return S_OK;
  73. }
  74. else
  75. {
  76. return E_NOINTERFACE;
  77. }
  78. }
  79. #undef DPF_MODNAME
  80. #define DPF_MODNAME "CClassFactory::CreateInstance"
  81. STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj)
  82. {
  83. HRESULT hr = DV_OK;
  84. if( ppvObj == NULL ||
  85. !DNVALID_WRITEPTR( ppvObj, sizeof(LPVOID) ) )
  86. {
  87. DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer passed for object" );
  88. return DVERR_INVALIDPOINTER;
  89. }
  90. if( pUnkOuter != NULL )
  91. {
  92. DPFX(DPFPREP, DVF_ERRORLEVEL, "Object does not support aggregation" );
  93. return CLASS_E_NOAGGREGATION;
  94. }
  95. if( IsEqualGUID(riid,IID_IDirectPlayVoiceClient) )
  96. {
  97. hr = DVC_Create((LPDIRECTVOICECLIENTOBJECT *) ppvObj);
  98. if (FAILED(hr))
  99. {
  100. DPFX(DPFPREP, DVF_ERRORLEVEL, "DVC_Create Failed hr=0x%x", hr );
  101. return hr;
  102. }
  103. // get the right interface and bump the refcount
  104. hr = DVC_QueryInterface((LPDIRECTVOICECLIENTOBJECT) *ppvObj, riid, ppvObj);
  105. }
  106. else if( IsEqualGUID(riid,IID_IDirectPlayVoiceServer) )
  107. {
  108. hr = DVS_Create((LPDIRECTVOICESERVEROBJECT *) ppvObj);
  109. if (FAILED(hr))
  110. {
  111. DPFX(DPFPREP, DVF_ERRORLEVEL, "DVS_Create Failed hr=0x%x", hr );
  112. return hr;
  113. }
  114. // get the right interface and bump the refcount
  115. hr = DVS_QueryInterface((LPDIRECTVOICESERVEROBJECT) *ppvObj, riid, ppvObj);
  116. }
  117. else if( IsEqualGUID(riid,IID_IDirectPlayVoiceTest) )
  118. {
  119. hr = DVT_Create((LPDIRECTVOICESETUPOBJECT *) ppvObj);
  120. if (FAILED(hr))
  121. {
  122. DPFX(DPFPREP, DVF_ERRORLEVEL, "DVT_Create Failed hr=0x%x", hr );
  123. return hr;
  124. }
  125. // get the right interface and bump the refcount
  126. hr = DVT_QueryInterface((LPDIRECTVOICESETUPOBJECT) *ppvObj, riid, ppvObj);
  127. }
  128. else if( IsEqualGUID(riid,IID_IUnknown) )
  129. {
  130. if( m_clsid == CLSID_DirectPlayVoice )
  131. {
  132. DPFX(DPFPREP, 0, "Requesting IUnknown through generic CLSID" );
  133. return E_NOINTERFACE;
  134. }
  135. else if( m_clsid == CLSID_DirectPlayVoiceClient )
  136. {
  137. hr = DVC_Create((LPDIRECTVOICECLIENTOBJECT *) ppvObj);
  138. if (FAILED(hr))
  139. {
  140. DPFX(DPFPREP, DVF_ERRORLEVEL, "DVC_Create Failed hr=0x%x", hr );
  141. return hr;
  142. }
  143. // get the right interface and bump the refcount
  144. hr = DVC_QueryInterface((LPDIRECTVOICECLIENTOBJECT) *ppvObj, riid, ppvObj);
  145. }
  146. else if( m_clsid == CLSID_DirectPlayVoiceServer )
  147. {
  148. hr = DVS_Create((LPDIRECTVOICESERVEROBJECT *) ppvObj);
  149. if (FAILED(hr))
  150. {
  151. DPFX(DPFPREP, DVF_ERRORLEVEL, "DVS_Create Failed hr=0x%x", hr );
  152. return hr;
  153. }
  154. // get the right interface and bump the refcount
  155. hr = DVS_QueryInterface((LPDIRECTVOICESERVEROBJECT) *ppvObj, riid, ppvObj);
  156. }
  157. else if( m_clsid == CLSID_DirectPlayVoiceTest )
  158. {
  159. hr = DVT_Create((LPDIRECTVOICESETUPOBJECT *) ppvObj);
  160. if (FAILED(hr))
  161. {
  162. DPFX(DPFPREP, DVF_ERRORLEVEL, "DVT_Create Failed hr=0x%x", hr );
  163. return hr;
  164. }
  165. // get the right interface and bump the refcount
  166. hr = DVT_QueryInterface((LPDIRECTVOICESETUPOBJECT) *ppvObj, riid, ppvObj);
  167. }
  168. else
  169. {
  170. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unknown interface" );
  171. return E_NOINTERFACE;
  172. }
  173. }
  174. else
  175. {
  176. return E_NOINTERFACE;
  177. }
  178. IncrementObjectCount();
  179. return hr;
  180. }
  181. #ifdef DPLAY_LOADANDCHECKTRUE
  182. typedef HRESULT (WINAPI *PFN_DLLGETCLASSOBJECT)(REFCLSID rclsid,REFIID riid,LPVOID *ppvObj );
  183. typedef HRESULT (WINAPI *PFN_DLLCANUNLOADNOW)(void);
  184. extern HMODULE ghRedirect;
  185. extern PFN_DLLGETCLASSOBJECT pfnGetClassObject;
  186. extern PFN_DLLCANUNLOADNOW pfnDllCanUnLoadNow;
  187. #endif
  188. /*
  189. * DllGetClassObject
  190. *
  191. * Entry point called by COM to get a ClassFactory pointer
  192. */
  193. STDAPI DllGetClassObject(
  194. REFCLSID rclsid,
  195. REFIID riid,
  196. LPVOID *ppvObj )
  197. {
  198. CClassFactory* pcf;
  199. HRESULT hr;
  200. #ifdef DPLAY_LOADANDCHECKTRUE
  201. if( ghRedirect != NULL )
  202. {
  203. GUID guidCLSID;
  204. if( IsEqualCLSID( rclsid, DPVOICE_CLSID_DPVOICE ) )
  205. {
  206. memcpy( &guidCLSID, &CLSID_DirectPlayVoice, sizeof(GUID) );
  207. }
  208. else
  209. {
  210. memcpy( &guidCLSID, rclsid, sizeof(GUID) );
  211. }
  212. return (*pfnGetClassObject)(&guidCLSID,riid,ppvObj);
  213. }
  214. #endif
  215. *ppvObj = NULL;
  216. /*
  217. * is this our class id?
  218. */
  219. if( !IsEqualCLSID(rclsid, DPVOICE_CLSID_DPVOICE) &&
  220. !IsEqualCLSID(rclsid, CLSID_DirectPlayVoiceClient) &&
  221. !IsEqualCLSID(rclsid, CLSID_DirectPlayVoiceServer) &&
  222. !IsEqualCLSID(rclsid, CLSID_DirectPlayVoiceTest) )
  223. {
  224. return CLASS_E_CLASSNOTAVAILABLE;
  225. }
  226. /*
  227. * only allow IUnknown and IClassFactory
  228. */
  229. if( !IsEqualIID( riid, IID_IUnknown ) &&
  230. !IsEqualIID( riid, IID_IClassFactory ) )
  231. {
  232. return E_NOINTERFACE;
  233. }
  234. /*
  235. * create a class factory object
  236. */
  237. pcf = new CClassFactory((CLSID*)&rclsid);
  238. if( NULL == pcf)
  239. {
  240. return E_OUTOFMEMORY;
  241. }
  242. hr = pcf->QueryInterface( riid, ppvObj );
  243. if( FAILED( hr ) )
  244. {
  245. delete ( pcf );
  246. *ppvObj = NULL;
  247. }
  248. else
  249. {
  250. IncrementObjectCount();
  251. }
  252. return hr;
  253. } /* DllGetClassObject */
  254. /*
  255. * DllCanUnloadNow
  256. *
  257. * Entry point called by COM to see if it is OK to free our DLL
  258. */
  259. STDAPI DllCanUnloadNow( void )
  260. {
  261. HRESULT hr = S_FALSE;
  262. #ifdef DPLAY_LOADANDCHECKTRUE
  263. if( ghRedirect != NULL )
  264. {
  265. return (*pfnDllCanUnLoadNow)();
  266. }
  267. #endif
  268. if ( (0 == g_lNumObjects) && (0 == g_lNumLocks) )
  269. {
  270. hr = S_OK;
  271. }
  272. return hr;
  273. } /* DllCanUnloadNow */