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.

560 lines
15 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ClassFac.cpp
  6. * Content: DNET COM class factory
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 07/21/99 mjn Created
  12. * 02/04/2000 rmt Adjusted for use in DPAddress
  13. * 02/17/2000 rmt Parameter validation work
  14. * 02/20/2000 rmt Added parameter validation for IUnknown funcs
  15. * 03/21/2000 rmt Renamed all DirectPlayAddress8's to DirectPlay8Addresses
  16. * 06/20/2000 rmt Bugfix - QueryInterface had bug which was limiting interface list to 2 elements
  17. * 07/09/2000 rmt Added signature bytes to start of address objects
  18. * 07/13/2000 rmt Added critical sections to protect FPMs
  19. * 08/05/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  20. * 01/11/2001 rmt MANBUG #48487 - DPLAY: Crashes if CoCreate() isn't called.
  21. * 03/14/2001 rmt WINBUG #342420 - Restore COM emulation layer to operation.
  22. *@@END_MSINTERNAL
  23. *
  24. ***************************************************************************/
  25. #include "dnaddri.h"
  26. //**********************************************************************
  27. // Constant definitions
  28. //**********************************************************************
  29. //**********************************************************************
  30. // Macro definitions
  31. //**********************************************************************
  32. //**********************************************************************
  33. // Structure definitions
  34. //**********************************************************************
  35. typedef STDMETHODIMP IUnknownQueryInterface( IUnknown *pInterface, REFIID riid, LPVOID *ppvObj );
  36. typedef STDMETHODIMP_(ULONG) IUnknownAddRef( IUnknown *pInterface );
  37. typedef STDMETHODIMP_(ULONG) IUnknownRelease( IUnknown *pInterface );
  38. //
  39. // VTable for IUnknown interface
  40. //
  41. IUnknownVtbl DP8A_UnknownVtbl =
  42. {
  43. (IUnknownQueryInterface*) DP8A_QueryInterface,
  44. (IUnknownAddRef*) DP8A_AddRef,
  45. (IUnknownRelease*) DP8A_Release
  46. };
  47. //
  48. // VTable for Class Factory
  49. //
  50. IDirectPlay8AddressClassFactVtbl DP8ACF_Vtbl =
  51. {
  52. DP8ACF_QueryInterface,
  53. DP8ACF_AddRef,
  54. DP8ACF_Release,
  55. DP8ACF_CreateInstance,
  56. DP8ACF_LockServer
  57. };
  58. //**********************************************************************
  59. // Variable definitions
  60. //**********************************************************************
  61. //**********************************************************************
  62. // Function prototypes
  63. //**********************************************************************
  64. static HRESULT DP8A_CreateInterface(LPOBJECT_DATA lpObject,REFIID riid, LPINTERFACE_LIST *const ppv);
  65. //**********************************************************************
  66. // Function definitions
  67. //**********************************************************************
  68. extern IDirectPlay8AddressClassFactVtbl DP8ACF_Vtbl;
  69. extern IUnknownVtbl DP8A_UnknownVtbl;
  70. // Globals
  71. extern DWORD GdwHLocks;
  72. extern DWORD GdwHObjects;
  73. #undef DPF_MODNAME
  74. #define DPF_MODNAME "DP8ACF_QueryInterface"
  75. STDMETHODIMP DP8ACF_QueryInterface(IDirectPlay8AddressClassFact *pInterface, REFIID riid,LPVOID *ppv)
  76. {
  77. _LPIDirectPlay8AddressClassFact lpcfObj;
  78. HRESULT hResultCode = S_OK;
  79. DPFX(DPFPREP, 3,"Parameters: pInterface [%p], riid [%p], ppv [%p]",pInterface,riid,ppv);
  80. lpcfObj = (_LPIDirectPlay8AddressClassFact)pInterface;
  81. if (IsEqualIID(riid,IID_IUnknown))
  82. {
  83. DPFX(DPFPREP, 5,"riid = IID_IUnknown");
  84. *ppv = pInterface;
  85. lpcfObj->lpVtbl->AddRef( pInterface );
  86. }
  87. else if (IsEqualIID(riid,IID_IClassFactory))
  88. {
  89. DPFX(DPFPREP, 5,"riid = IID_IClassFactory");
  90. *ppv = pInterface;
  91. lpcfObj->lpVtbl->AddRef( pInterface );
  92. }
  93. else
  94. {
  95. DPFX(DPFPREP, 5,"riid not found !");
  96. *ppv = NULL;
  97. hResultCode = E_NOINTERFACE;
  98. }
  99. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx], *ppv = [%p]",hResultCode,*ppv);
  100. return(hResultCode);
  101. }
  102. #undef DPF_MODNAME
  103. #define DPF_MODNAME "DP8ACF_AddRef"
  104. STDMETHODIMP_(ULONG) DP8ACF_AddRef(IDirectPlay8AddressClassFact *pInterface)
  105. {
  106. _LPIDirectPlay8AddressClassFact lpcfObj;
  107. DPFX(DPFPREP, 3,"Parameters: pInterface [%p]",pInterface);
  108. lpcfObj = (_LPIDirectPlay8AddressClassFact)pInterface;
  109. InterlockedIncrement( &lpcfObj->lRefCount );
  110. DPFX(DPFPREP, 3,"Returning: lpcfObj->lRefCount = [%lx]",lpcfObj->lRefCount);
  111. return(lpcfObj->lRefCount);
  112. }
  113. #undef DPF_MODNAME
  114. #define DPF_MODNAME "DP8ACF_Release"
  115. STDMETHODIMP_(ULONG) DP8ACF_Release(IDirectPlay8AddressClassFact *pInterface)
  116. {
  117. _LPIDirectPlay8AddressClassFact lpcfObj;
  118. DPFX(DPFPREP, 3,"Parameters: pInterface [%p]",pInterface);
  119. lpcfObj = (_LPIDirectPlay8AddressClassFact)pInterface;
  120. DPFX(DPFPREP, 5,"Original : lpcfObj->lRefCount = %ld",lpcfObj->lRefCount);
  121. if( InterlockedDecrement( &lpcfObj->lRefCount )== 0 )
  122. {
  123. DPFX(DPFPREP, 5,"Freeing class factory object: lpcfObj [%p]",lpcfObj);
  124. fpmAddressClassFacs->Release(fpmAddressClassFacs, lpcfObj);
  125. GdwHObjects--;
  126. return(0);
  127. }
  128. DPFX(DPFPREP, 3,"Returning: lpcfObj->lRefCount = [%lx]",lpcfObj->lRefCount);
  129. return(lpcfObj->lRefCount);
  130. }
  131. #undef DPF_MODNAME
  132. #define DPF_MODNAME "DP8ACF_CreateObject"
  133. HRESULT DP8ACF_CreateObject(LPVOID *lplpv,REFIID riid)
  134. {
  135. HRESULT hr = S_OK;
  136. DP8ADDRESSOBJECT *pdnObject = NULL;
  137. DPFX(DPFPREP, 3,"Parameters: lplpv [%p]",lplpv);
  138. pdnObject = (DP8ADDRESSOBJECT *) fpmAddressObjects->Get(fpmAddressObjects);
  139. if (pdnObject == NULL)
  140. {
  141. DPFERR("FPM_Get() failed");
  142. return(E_OUTOFMEMORY);
  143. }
  144. DPFX(DPFPREP, 5,"pdnObject [%p]",pdnObject);
  145. hr = pdnObject->Init( );
  146. if( FAILED( hr ) )
  147. {
  148. fpmAddressObjects->Release( fpmAddressObjects, pdnObject );
  149. DPFX(DPFPREP, 0,"Failed to init hr=0x%x", hr );
  150. return hr;
  151. }
  152. *lplpv = pdnObject;
  153. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx], *lplpv = [%p]",hr,*lplpv);
  154. return(hr);
  155. }
  156. #undef DPF_MODNAME
  157. #define DPF_MODNAME "DirectPlay8AddressCreate"
  158. HRESULT WINAPI DirectPlay8AddressCreate( const GUID * pcIID, void **ppvInterface, IUnknown *pUnknown)
  159. {
  160. if( pcIID == NULL ||
  161. !DNVALID_READPTR( pcIID, sizeof( GUID ) ) )
  162. {
  163. DPFERR( "Invalid pointer specified for interface GUID" );
  164. return DPNERR_INVALIDPOINTER;
  165. }
  166. if( *pcIID != IID_IDirectPlay8Address &&
  167. *pcIID != IID_IDirectPlay8AddressIP )
  168. {
  169. DPFERR("Interface ID is not recognized" );
  170. return DPNERR_INVALIDPARAM;
  171. }
  172. if( ppvInterface == NULL || !DNVALID_WRITEPTR( ppvInterface, sizeof( void * ) ) )
  173. {
  174. DPFERR( "Invalid pointer specified to receive interface" );
  175. return DPNERR_INVALIDPOINTER;
  176. }
  177. if( pUnknown != NULL )
  178. {
  179. DPFERR( "Aggregation is not supported by this object yet" );
  180. return DPNERR_INVALIDPARAM;
  181. }
  182. return COM_CoCreateInstance( CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER, *pcIID, ppvInterface, TRUE );
  183. }
  184. #undef DPF_MODNAME
  185. #define DPF_MODNAME "DP8ACF_FreeObject"
  186. HRESULT DP8ACF_FreeObject(LPVOID lpv)
  187. {
  188. HRESULT hResultCode = S_OK;
  189. DP8ADDRESSOBJECT *pdnObject = (DP8ADDRESSOBJECT *) lpv;
  190. DNASSERT(pdnObject != NULL);
  191. pdnObject->Cleanup();
  192. DPFX(DPFPREP, 5,"free pdnObject [%p]",pdnObject);
  193. // Release the object
  194. fpmAddressObjects->Release( fpmAddressObjects, pdnObject );
  195. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx]",hResultCode);
  196. return(hResultCode);
  197. }
  198. #undef DPF_MODNAME
  199. #define DPF_MODNAME "DP8ACF_CreateInstance"
  200. STDMETHODIMP DP8ACF_CreateInstance(IDirectPlay8AddressClassFact *pInterface,LPUNKNOWN lpUnkOuter,REFIID riid,LPVOID *ppv)
  201. {
  202. HRESULT hResultCode = S_OK;
  203. LPINTERFACE_LIST lpIntList = NULL;
  204. LPOBJECT_DATA lpObjectData = NULL;
  205. DPFX(DPFPREP, 3,"Parameters: pInterface [%p], lpUnkOuter [%p], riid [%p], ppv [%p]",pInterface,lpUnkOuter,riid,ppv);
  206. if( ppv == NULL || !DNVALID_WRITEPTR( ppv, sizeof(LPVOID) ) )
  207. {
  208. DPFX(DPFPREP, 0, "Cannot pass NULL for new object param" );
  209. return E_INVALIDARG;
  210. }
  211. if (lpUnkOuter != NULL)
  212. {
  213. DPFX(DPFPREP, 0, "Aggregation is not supported, pUnkOuter must be NULL" );
  214. return(CLASS_E_NOAGGREGATION);
  215. }
  216. lpObjectData = (LPOBJECT_DATA) fpmAddressObjectDatas->Get(fpmAddressObjectDatas);
  217. if (lpObjectData == NULL)
  218. {
  219. DPFERR("FPM_Get() failed");
  220. return(E_OUTOFMEMORY);
  221. }
  222. DPFX(DPFPREP, 5,"lpObjectData [%p]",lpObjectData);
  223. lpObjectData->dwSignature = DPASIGNATURE_OD;
  224. // Object creation and initialization
  225. if ((hResultCode = DP8ACF_CreateObject(&lpObjectData->lpvData,riid)) != S_OK)
  226. {
  227. fpmAddressObjectDatas->Release(fpmAddressObjectDatas, lpObjectData);
  228. return(hResultCode);
  229. }
  230. DPFX(DPFPREP, 5,"Created and initialized object");
  231. // Get requested interface
  232. if ((hResultCode = DP8A_CreateInterface(lpObjectData,riid,&lpIntList)) != S_OK)
  233. {
  234. DP8ACF_FreeObject(lpObjectData->lpvData);
  235. fpmAddressObjectDatas->Release(fpmAddressObjectDatas, lpObjectData);
  236. return(hResultCode);
  237. }
  238. DPFX(DPFPREP, 5,"Found interface");
  239. lpObjectData->lpIntList = lpIntList;
  240. lpObjectData->lRefCount = 1;
  241. InterlockedIncrement( &lpIntList->lRefCount );
  242. GdwHObjects++;
  243. *ppv = lpIntList;
  244. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx], *ppv = [%p]",hResultCode,*ppv);
  245. return(S_OK);
  246. }
  247. #undef DPF_MODNAME
  248. #define DPF_MODNAME "DP8ACF_LockServer"
  249. STDMETHODIMP DP8ACF_LockServer(IDirectPlay8AddressClassFact *pInterface,BOOL bLock)
  250. {
  251. DPFX(DPFPREP, 3,"Parameters: lpv [%p], bLock [%lx]",pInterface,bLock);
  252. if (bLock)
  253. {
  254. GdwHLocks++;
  255. }
  256. else
  257. {
  258. GdwHLocks--;
  259. }
  260. return(S_OK);
  261. }
  262. #undef DPF_MODNAME
  263. #define DPF_MODNAME "DP8A_CreateInterface"
  264. static HRESULT DP8A_CreateInterface(LPOBJECT_DATA lpObject, REFIID riid, LPINTERFACE_LIST *const ppv)
  265. {
  266. LPINTERFACE_LIST lpIntNew;
  267. LPVOID lpVtbl;
  268. DPFX(DPFPREP, 3,"Parameters: lpObject [%p], riid [%p], ppv [%p]",lpObject,riid,ppv);
  269. if (IsEqualIID(riid,IID_IUnknown))
  270. {
  271. DPFX(DPFPREP, 5,"riid = IID_IUnknown");
  272. lpVtbl = &DP8A_UnknownVtbl;
  273. }
  274. else if (IsEqualIID(riid,IID_IDirectPlay8Address))
  275. {
  276. DPFX(DPFPREP, 5,"riid = IID_IDirectPlay8Address");
  277. lpVtbl = &DP8A_BaseVtbl;
  278. }
  279. else if (IsEqualIID(riid,IID_IDirectPlay8AddressIP))
  280. {
  281. DPFX(DPFPREP, 5,"riid = IID_IDirectPlay8AddressIP");
  282. lpVtbl = &DP8A_IPVtbl;
  283. }
  284. else if (IsEqualIID(riid,IID_IDirectPlay8AddressInternal))
  285. {
  286. DPFX(DPFPREP, 5,"riid = IID_IDirectPlay8AddressInternal");
  287. lpVtbl = &DP8A_InternalVtbl;
  288. }
  289. else
  290. {
  291. DPFX(DPFPREP, 5,"riid not found !");
  292. return(E_NOINTERFACE);
  293. }
  294. lpIntNew = (LPINTERFACE_LIST) fpmAddressInterfaceLists->Get(fpmAddressInterfaceLists);
  295. if (lpIntNew == NULL)
  296. {
  297. DPFERR("FPM_Get() failed");
  298. return(E_OUTOFMEMORY);
  299. }
  300. lpIntNew->dwSignature = DPASIGNATURE_IL;
  301. lpIntNew->lpVtbl = lpVtbl;
  302. lpIntNew->lRefCount = 0;
  303. lpIntNew->lpIntNext = NULL;
  304. DBG_CASSERT( sizeof( lpIntNew->iid ) == sizeof( riid ) );
  305. memcpy( &(lpIntNew->iid), &riid, sizeof( lpIntNew->iid ) );
  306. lpIntNew->lpObject = lpObject;
  307. *ppv = lpIntNew;
  308. DPFX(DPFPREP, 3,"Returning: hResultCode = [S_OK], *ppv = [%p]",*ppv);
  309. return(S_OK);
  310. }
  311. #undef DPF_MODNAME
  312. #define DPF_MODNAME "DP8A_FindInterface"
  313. LPINTERFACE_LIST DP8A_FindInterface(LPVOID lpv, REFIID riid)
  314. {
  315. LPINTERFACE_LIST lpIntList;
  316. DPFX(DPFPREP, 3,"Parameters: lpv [%p], riid [%p]",lpv,riid);
  317. lpIntList = ((LPINTERFACE_LIST)lpv)->lpObject->lpIntList; // Find first interface
  318. while (lpIntList != NULL)
  319. {
  320. if (IsEqualIID(riid,lpIntList->iid))
  321. break;
  322. lpIntList = lpIntList->lpIntNext;
  323. }
  324. DPFX(DPFPREP, 3,"Returning: lpIntList = [%p]",lpIntList);
  325. return(lpIntList);
  326. }
  327. #undef DPF_MODNAME
  328. #define DPF_MODNAME "DP8A_QueryInterface"
  329. STDMETHODIMP DP8A_QueryInterface(LPVOID lpv,REFIID riid,LPVOID *ppv)
  330. {
  331. LPINTERFACE_LIST lpIntList;
  332. LPINTERFACE_LIST lpIntNew;
  333. HRESULT hResultCode;
  334. DPFX(DPFPREP, 3,"Parameters: lpv [%p], riid [%p], ppv [%p]",lpv,riid,ppv);
  335. if( lpv == NULL || !DP8A_VALID(lpv) )
  336. {
  337. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid object" );
  338. return DPNERR_INVALIDOBJECT;
  339. }
  340. if( ppv == NULL ||
  341. !DNVALID_WRITEPTR(ppv, sizeof(LPVOID) ) )
  342. {
  343. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid pointer for interface" );
  344. return DPNERR_INVALIDPOINTER;
  345. }
  346. if ((lpIntList = DP8A_FindInterface(lpv,riid)) == NULL)
  347. { // Interface must be created
  348. lpIntList = ((LPINTERFACE_LIST)lpv)->lpObject->lpIntList;
  349. if ((hResultCode = DP8A_CreateInterface(lpIntList->lpObject,riid,&lpIntNew)) != S_OK)
  350. {
  351. return(hResultCode);
  352. }
  353. lpIntNew->lpIntNext = lpIntList;
  354. ((LPINTERFACE_LIST)lpv)->lpObject->lpIntList = lpIntNew;
  355. lpIntList = lpIntNew;
  356. }
  357. // Interface is being created or was cached
  358. // Increment object count
  359. if( lpIntList->lRefCount == 0 )
  360. {
  361. InterlockedIncrement( &lpIntList->lpObject->lRefCount );
  362. }
  363. InterlockedIncrement( &lpIntList->lRefCount );
  364. *ppv = lpIntList;
  365. DPFX(DPFPREP, 3,"Returning: hResultCode = [S_OK], *ppv = [%p]",*ppv);
  366. return(S_OK);
  367. }
  368. #undef DPF_MODNAME
  369. #define DPF_MODNAME "DP8A_AddRef"
  370. STDMETHODIMP_(ULONG) DP8A_AddRef(LPVOID lpv)
  371. {
  372. LPINTERFACE_LIST lpIntList;
  373. DPFX(DPFPREP, 3,"Parameters: lpv [%p]",lpv);
  374. if( lpv == NULL || !DP8A_VALID(lpv) )
  375. {
  376. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid object" );
  377. return DPNERR_INVALIDOBJECT;
  378. }
  379. lpIntList = (LPINTERFACE_LIST)lpv;
  380. InterlockedIncrement( &lpIntList->lRefCount );
  381. DPFX(DPFPREP, 3,"Returning: lpIntList->lRefCount = [%lx]",lpIntList->lRefCount);
  382. return(lpIntList->lRefCount);
  383. }
  384. #undef DPF_MODNAME
  385. #define DPF_MODNAME "DP8A_Release"
  386. STDMETHODIMP_(ULONG) DP8A_Release(LPVOID lpv)
  387. {
  388. LPINTERFACE_LIST lpIntList;
  389. LPINTERFACE_LIST lpIntCurrent;
  390. DPFX(DPFPREP, 3,"Parameters: lpv [%p]",lpv);
  391. if( lpv == NULL || !DP8A_VALID(lpv) )
  392. {
  393. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid object" );
  394. return DPNERR_INVALIDOBJECT;
  395. }
  396. lpIntList = (LPINTERFACE_LIST)lpv;
  397. DPFX(DPFPREP, 5,"Original : lpIntList->lRefCount = %ld",lpIntList->lRefCount);
  398. DPFX(DPFPREP, 5,"Original : lpIntList->lpObject->lRefCount = %ld",lpIntList->lpObject->lRefCount);
  399. if( InterlockedDecrement( &lpIntList->lRefCount ) == 0 )
  400. { // Decrease interface count
  401. if( InterlockedDecrement( &lpIntList->lpObject->lRefCount ) == 0 )
  402. { // Free object and all interfaces
  403. DPFX(DPFPREP, 5,"Free object");
  404. // Free object here
  405. DP8ACF_FreeObject(lpIntList->lpObject->lpvData);
  406. lpIntList = lpIntList->lpObject->lpIntList; // Get head of interface list
  407. DPFX(DPFPREP, 5,"lpIntList->lpObject [%p]",lpIntList->lpObject);
  408. lpIntList->lpObject->dwSignature = DPASIGNATURE_OD_FREE;
  409. fpmAddressObjectDatas->Release(fpmAddressObjectDatas, lpIntList->lpObject);
  410. // Free Interfaces
  411. DPFX(DPFPREP, 5,"Free interfaces");
  412. while(lpIntList != NULL)
  413. {
  414. lpIntCurrent = lpIntList;
  415. lpIntList = lpIntList->lpIntNext;
  416. DPFX(DPFPREP, 5,"\tinterface [%p]",lpIntCurrent);
  417. lpIntCurrent->dwSignature = DPASIGNATURE_IL_FREE;
  418. fpmAddressInterfaceLists->Release(fpmAddressInterfaceLists, lpIntCurrent);
  419. }
  420. GdwHObjects--;
  421. DPFX(DPFPREP, 3,"Returning: 0");
  422. return(0);
  423. }
  424. }
  425. DPFX(DPFPREP, 3,"Returning: lpIntList->lRefCount = [%lx]",lpIntList->lRefCount);
  426. return(lpIntList->lRefCount);
  427. }