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.

720 lines
19 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ClassFac.cpp
  6. * Content: DirectPlay Lobby COM Class Factory
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 02/21/00 mjn Created
  12. * 03/22/2000 jtk Changed interface names
  13. * 04/18/2000 rmt Updated object create to set param validation flag
  14. * 05/09/2000 rmt Bug #34306 QueryInterface on lobbyclient for lobbiedapp works (and shouldn't).
  15. * 06/07/2000 rmt Bug #34383 Must provide CLSID for each IID to fix issues with Whistler
  16. * 06/20/2000 rmt Bugfix - QueryInterface had bug which was limiting interface list to 2 elements
  17. * 07/08/2000 rmt Added guard bytes
  18. * 08/05/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  19. * 08/08/2000 rmt Removed assert which wasn't needed
  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 "dnlobbyi.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 DN_UnknownVtbl =
  42. {
  43. (IUnknownQueryInterface*) DPL_QueryInterface,
  44. (IUnknownAddRef*) DPL_AddRef,
  45. (IUnknownRelease*) DPL_Release
  46. };
  47. //
  48. // VTable for Class Factory
  49. //
  50. IDirectPlayLobbyClassFactVtbl DPLCF_Vtbl =
  51. {
  52. DPLCF_QueryInterface,
  53. DPLCF_AddRef,
  54. DPLCF_Release,
  55. DPLCF_CreateInstance,
  56. DPLCF_LockServer
  57. };
  58. //**********************************************************************
  59. // Variable definitions
  60. //**********************************************************************
  61. //
  62. // Globals
  63. //
  64. extern DWORD GdwHLocks;
  65. extern DWORD GdwHObjects;
  66. //**********************************************************************
  67. // Function prototypes
  68. //**********************************************************************
  69. //**********************************************************************
  70. // Function definitions
  71. //**********************************************************************
  72. #undef DPF_MODNAME
  73. #define DPF_MODNAME "DPLCF_QueryInterface"
  74. STDMETHODIMP DPLCF_QueryInterface(IDirectPlayLobbyClassFact *pInterface,
  75. REFIID riid,
  76. LPVOID *ppv)
  77. {
  78. _PIDirectPlayLobbyClassFact lpcfObj;
  79. HRESULT hResultCode = S_OK;
  80. DPFX(DPFPREP, 3,"Parameters: pInterface [0x%p], riid [0x%p], ppv [0x%p]",pInterface,riid,ppv);
  81. lpcfObj = (_PIDirectPlayLobbyClassFact)pInterface;
  82. if (IsEqualIID(riid,IID_IUnknown))
  83. {
  84. DPFX(DPFPREP, 5,"riid = IID_IUnknown");
  85. *ppv = pInterface;
  86. lpcfObj->lpVtbl->AddRef( pInterface );
  87. }
  88. else if (IsEqualIID(riid,IID_IClassFactory))
  89. {
  90. DPFX(DPFPREP, 5,"riid = IID_IClassFactory");
  91. *ppv = pInterface;
  92. lpcfObj->lpVtbl->AddRef( pInterface );
  93. }
  94. else
  95. {
  96. DPFX(DPFPREP, 5,"riid not found !");
  97. *ppv = NULL;
  98. hResultCode = E_NOINTERFACE;
  99. }
  100. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx], *ppv = [%p]",hResultCode,*ppv);
  101. return(hResultCode);
  102. }
  103. #undef DPF_MODNAME
  104. #define DPF_MODNAME "DPLCF_AddRef"
  105. STDMETHODIMP_(ULONG) DPLCF_AddRef(IDirectPlayLobbyClassFact *pInterface)
  106. {
  107. _PIDirectPlayLobbyClassFact lpcfObj;
  108. DPFX(DPFPREP, 3,"Parameters: pInterface [%p]",pInterface);
  109. lpcfObj = (_PIDirectPlayLobbyClassFact)pInterface;
  110. InterlockedIncrement( &lpcfObj->lRefCount );
  111. DPFX(DPFPREP, 3,"Returning: lpcfObj->lRefCount = [%lx]",lpcfObj->lRefCount);
  112. return(lpcfObj->lRefCount);
  113. }
  114. #undef DPF_MODNAME
  115. #define DPF_MODNAME "DPLCF_Release"
  116. STDMETHODIMP_(ULONG) DPLCF_Release(IDirectPlayLobbyClassFact *pInterface)
  117. {
  118. _PIDirectPlayLobbyClassFact lpcfObj;
  119. DPFX(DPFPREP, 3,"Parameters: pInterface [%p]",pInterface);
  120. lpcfObj = (_PIDirectPlayLobbyClassFact)pInterface;
  121. DPFX(DPFPREP, 5,"Original : lpcfObj->lRefCount = %ld",lpcfObj->lRefCount);
  122. if( InterlockedDecrement( &lpcfObj->lRefCount ) == 0 )
  123. {
  124. DPFX(DPFPREP, 5,"Freeing class factory object: lpcfObj [%p]",lpcfObj);
  125. DNFree(lpcfObj);
  126. GdwHObjects--;
  127. return(0);
  128. }
  129. DPFX(DPFPREP, 3,"Returning: lpcfObj->lRefCount = [%lx]",lpcfObj->lRefCount);
  130. return(lpcfObj->lRefCount);
  131. }
  132. #undef DPF_MODNAME
  133. #define DPF_MODNAME "DPLCF_CreateObject"
  134. HRESULT DPLCF_CreateObject(IDirectPlayLobbyClassFact *pInterface,
  135. LPVOID *lplpv,
  136. REFIID riid)
  137. {
  138. HRESULT hResultCode = S_OK;
  139. OSVERSIONINFOA ver;
  140. PDIRECTPLAYLOBBYOBJECT pdpLobbyObject = NULL;
  141. _PIDirectPlayLobbyClassFact lpcfObj = (_PIDirectPlayLobbyClassFact)pInterface;
  142. DPFX(DPFPREP, 3,"Parameters: lplpv [%p]",lplpv);
  143. /*
  144. *
  145. * TIME BOMB
  146. *
  147. */
  148. #ifndef DX_FINAL_RELEASE
  149. {
  150. #pragma message("BETA EXPIRATION TIME BOMB! Remove for final build!")
  151. SYSTEMTIME st;
  152. GetSystemTime(&st);
  153. if ( st.wYear > DX_EXPIRE_YEAR || ((st.wYear == DX_EXPIRE_YEAR) && (MAKELONG(st.wDay, st.wMonth) > MAKELONG(DX_EXPIRE_DAY, DX_EXPIRE_MONTH))) )
  154. {
  155. MessageBox(0, DX_EXPIRE_TEXT,TEXT("Microsoft Direct Play"), MB_OK);
  156. // return E_FAIL;
  157. }
  158. }
  159. #endif
  160. if ((pdpLobbyObject = (PDIRECTPLAYLOBBYOBJECT)DNMalloc(sizeof(DIRECTPLAYLOBBYOBJECT))) == NULL)
  161. {
  162. return(E_OUTOFMEMORY);
  163. }
  164. DPFX(DPFPREP, 5,"pdpLobbyObject [%p]",pdpLobbyObject);
  165. // Set allocatable elements to NULL to simplify free'ing later on
  166. pdpLobbyObject->dwSignature = DPLSIGNATURE_LOBBYOBJECT;
  167. pdpLobbyObject->hReceiveThread = NULL;
  168. pdpLobbyObject->dwFlags = 0;
  169. pdpLobbyObject->hConnectEvent = NULL;
  170. pdpLobbyObject->pfnMessageHandler = NULL;
  171. pdpLobbyObject->pvUserContext = NULL;
  172. pdpLobbyObject->lLaunchCount = 0;
  173. pdpLobbyObject->dpnhLaunchedConnection = NULL;
  174. pdpLobbyObject->pReceiveQueue = NULL;
  175. pdpLobbyObject->dwPID = GetCurrentProcessId();
  176. if ((hResultCode = H_Initialize(&pdpLobbyObject->hsHandles,
  177. DPL_NUM_APP_HANDLES)) != DPN_OK)
  178. {
  179. DPLCF_FreeObject(pdpLobbyObject);
  180. return(hResultCode);
  181. }
  182. if ((pdpLobbyObject->hConnectEvent = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL)
  183. {
  184. DPLCF_FreeObject(pdpLobbyObject);
  185. hResultCode = DPNERR_OUTOFMEMORY;
  186. return(hResultCode);
  187. }
  188. if ((pdpLobbyObject->hLobbyLaunchConnectEvent = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL )
  189. {
  190. DPLCF_FreeObject(pdpLobbyObject);
  191. hResultCode = DPNERR_OUTOFMEMORY;
  192. return(hResultCode);
  193. }
  194. pdpLobbyObject->phHandleBuffer = NULL;
  195. pdpLobbyObject->dwHandleBufferSize = 0;
  196. DPFX(DPFPREP, 5,"InitializeHandles() succeeded");
  197. if (IsEqualIID(riid,IID_IDirectPlay8LobbyClient) ||
  198. (riid == IID_IUnknown && lpcfObj->clsid == CLSID_DirectPlay8LobbyClient ) )
  199. {
  200. DPFX(DPFPREP, 5,"DirectPlay Lobby Client");
  201. pdpLobbyObject->dwFlags |= DPL_OBJECT_FLAG_LOBBYCLIENT;
  202. }
  203. else if (IsEqualIID(riid,IID_IDirectPlay8LobbiedApplication) ||
  204. (riid == IID_IUnknown && lpcfObj->clsid == CLSID_DirectPlay8LobbiedApplication ) )
  205. {
  206. DPFX(DPFPREP, 5,"DirectPlay Lobbied Application");
  207. pdpLobbyObject->dwFlags |= DPL_OBJECT_FLAG_LOBBIEDAPPLICATION;
  208. }
  209. else
  210. {
  211. DPFX(DPFPREP, 5,"Invalid DirectPlay Lobby Interface");
  212. DPLCF_FreeObject(pdpLobbyObject);
  213. return(E_NOTIMPL);
  214. }
  215. pdpLobbyObject->dwFlags |= DPL_OBJECT_FLAG_PARAMVALIDATION;
  216. // Determine platform
  217. // Just always call the ANSI function
  218. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  219. if(!GetVersionExA(&ver))
  220. {
  221. DPFX(DPFPREP, 0, "Unable to determinte platform -- setting flag to ANSI");
  222. pdpLobbyObject->bIsUnicodePlatform = FALSE;
  223. }
  224. else
  225. {
  226. switch(ver.dwPlatformId)
  227. {
  228. case VER_PLATFORM_WIN32_WINDOWS:
  229. DPFX(DPFPREP, 1, "Platform detected as non-NT -- setting flag to ANSI");
  230. pdpLobbyObject->bIsUnicodePlatform = FALSE;
  231. break;
  232. case VER_PLATFORM_WIN32_NT:
  233. DPFX(DPFPREP, 1, "Platform detected as NT -- setting flag to Unicode");
  234. pdpLobbyObject->bIsUnicodePlatform = TRUE;
  235. break;
  236. default:
  237. DPFX(DPFPREP, 0, "Unable to determine platform -- setting flag to ANSI");
  238. pdpLobbyObject->bIsUnicodePlatform = FALSE;
  239. break;
  240. }
  241. }
  242. *lplpv = pdpLobbyObject;
  243. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx], *lplpv = [%p]",hResultCode,*lplpv);
  244. return(hResultCode);
  245. }
  246. #undef DPF_MODNAME
  247. #define DPF_MODNAME "DirectPlay8LobbyCreate"
  248. HRESULT WINAPI DirectPlay8LobbyCreate( const GUID * pcIID, void **ppvInterface, IUnknown *pUnknown)
  249. {
  250. GUID clsid;
  251. if( pcIID == NULL ||
  252. !DNVALID_READPTR( pcIID, sizeof( GUID ) ) )
  253. {
  254. DPFERR( "Invalid pointer specified for interface GUID" );
  255. return DPNERR_INVALIDPOINTER;
  256. }
  257. if( *pcIID != IID_IDirectPlay8LobbyClient &&
  258. *pcIID != IID_IDirectPlay8LobbiedApplication )
  259. {
  260. DPFERR("Interface ID is not recognized" );
  261. return DPNERR_INVALIDPARAM;
  262. }
  263. if( ppvInterface == NULL || !DNVALID_WRITEPTR( ppvInterface, sizeof( void * ) ) )
  264. {
  265. DPFERR( "Invalid pointer specified to receive interface" );
  266. return DPNERR_INVALIDPOINTER;
  267. }
  268. if( pUnknown != NULL )
  269. {
  270. DPFERR( "Aggregation is not supported by this object yet" );
  271. return DPNERR_INVALIDPARAM;
  272. }
  273. if( *pcIID == IID_IDirectPlay8LobbyClient )
  274. {
  275. clsid = CLSID_DirectPlay8LobbyClient;
  276. }
  277. else if( *pcIID == IID_IDirectPlay8LobbiedApplication )
  278. {
  279. clsid = CLSID_DirectPlay8LobbiedApplication;
  280. }
  281. else
  282. {
  283. DPFERR( "Invalid IID specified" );
  284. return DPNERR_INVALIDINTERFACE;
  285. }
  286. return COM_CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, *pcIID, ppvInterface, TRUE );
  287. }
  288. #undef DPF_MODNAME
  289. #define DPF_MODNAME "DPLCF_FreeObject"
  290. HRESULT DPLCF_FreeObject(LPVOID lpv)
  291. {
  292. HRESULT hResultCode = S_OK;
  293. PDIRECTPLAYLOBBYOBJECT pdpLobbyObject = NULL;
  294. if (lpv != NULL)
  295. {
  296. pdpLobbyObject = (PDIRECTPLAYLOBBYOBJECT)lpv;
  297. if( pdpLobbyObject->phHandleBuffer )
  298. delete [] pdpLobbyObject->phHandleBuffer;
  299. if (pdpLobbyObject->pReceiveQueue)
  300. delete pdpLobbyObject->pReceiveQueue;
  301. if (pdpLobbyObject->hLobbyLaunchConnectEvent)
  302. CloseHandle(pdpLobbyObject->hLobbyLaunchConnectEvent);
  303. if (pdpLobbyObject->hConnectEvent)
  304. CloseHandle(pdpLobbyObject->hConnectEvent);
  305. // Free application handles
  306. H_Terminate(&pdpLobbyObject->hsHandles);
  307. pdpLobbyObject->dwSignature = DPLSIGNATURE_LOBBYOBJECT_FREE;
  308. DPFX(DPFPREP, 5,"free pdpLobbyObject [%p]",pdpLobbyObject);
  309. DNFree(pdpLobbyObject);
  310. }
  311. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx]",hResultCode);
  312. return(hResultCode);
  313. }
  314. #undef DPF_MODNAME
  315. #define DPF_MODNAME "DPLCF_CreateInstance"
  316. STDMETHODIMP DPLCF_CreateInstance(IDirectPlayLobbyClassFact *pInterface,
  317. LPUNKNOWN lpUnkOuter,
  318. REFIID riid,
  319. LPVOID *ppv)
  320. {
  321. HRESULT hResultCode = S_OK;
  322. LPINTERFACE_LIST lpIntList = NULL;
  323. LPOBJECT_DATA lpObjectData = NULL;
  324. DPFX(DPFPREP, 3,"Parameters: pInterface [0x%p], lpUnkOuter [0x%p], riid [0x%p], ppv [0x%p]",pInterface,lpUnkOuter,riid,ppv);
  325. if (lpUnkOuter != NULL)
  326. return(CLASS_E_NOAGGREGATION);
  327. if ((lpObjectData = (LPOBJECT_DATA)DNMalloc(sizeof(OBJECT_DATA))) == NULL)
  328. {
  329. DPFERR("DNMalloc() failed");
  330. return(E_OUTOFMEMORY);
  331. }
  332. DPFX(DPFPREP, 5,"lpObjectData [%p]",lpObjectData);
  333. // Object creation and initialization
  334. if ((hResultCode = DPLCF_CreateObject(pInterface,&lpObjectData->lpvData,riid)) != S_OK)
  335. {
  336. DNFree(lpObjectData);
  337. return(hResultCode);
  338. }
  339. DPFX(DPFPREP, 5,"Created and initialized object");
  340. // Get requested interface
  341. if ((hResultCode = DPL_CreateInterface(lpObjectData,riid,&lpIntList)) != S_OK)
  342. {
  343. DPLCF_FreeObject(lpObjectData->lpvData);
  344. DNFree(lpObjectData);
  345. return(hResultCode);
  346. }
  347. DPFX(DPFPREP, 5,"Found interface");
  348. lpObjectData->lpIntList = lpIntList;
  349. lpObjectData->lRefCount = 1;
  350. InterlockedIncrement( &lpIntList->lRefCount );
  351. GdwHObjects++;
  352. *ppv = lpIntList;
  353. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx], *ppv = [%p]",hResultCode,*ppv);
  354. return(S_OK);
  355. }
  356. #undef DPF_MODNAME
  357. #define DPF_MODNAME "DPLCF_LockServer"
  358. STDMETHODIMP DPLCF_LockServer(IDirectPlayLobbyClassFact *pInterface,
  359. BOOL bLock)
  360. {
  361. DPFX(DPFPREP, 3,"Parameters: lpv [%p], bLock [%lx]",pInterface,bLock);
  362. if (bLock)
  363. {
  364. GdwHLocks++;
  365. }
  366. else
  367. {
  368. GdwHLocks--;
  369. }
  370. return(S_OK);
  371. }
  372. #undef DPF_MODNAME
  373. #define DPF_MODNAME "DPL_CreateInterface"
  374. static HRESULT DPL_CreateInterface(LPOBJECT_DATA lpObject,
  375. REFIID riid,
  376. LPINTERFACE_LIST *const ppv)
  377. {
  378. LPINTERFACE_LIST lpIntNew;
  379. LPVOID lpVtbl;
  380. DPFX(DPFPREP, 3,"Parameters: lpObject [%p], riid [%p], ppv [%p]",lpObject,riid,ppv);
  381. if (IsEqualIID(riid,IID_IUnknown))
  382. {
  383. DPFX(DPFPREP, 5,"riid = IID_IUnknown");
  384. lpVtbl = &DN_UnknownVtbl;
  385. }
  386. else if (IsEqualIID(riid,IID_IDirectPlay8LobbyClient))
  387. {
  388. DPFX(DPFPREP, 5,"riid = IID_IDirectPlay8LobbyClient");
  389. lpVtbl = &DPL_Lobby8ClientVtbl;
  390. }
  391. else if (IsEqualIID(riid,IID_IDirectPlay8LobbiedApplication))
  392. {
  393. DPFX(DPFPREP, 5,"riid = IID_IDirectPlay8LobbiedApplication");
  394. lpVtbl = &DPL_8LobbiedApplicationVtbl;
  395. }
  396. else
  397. {
  398. DPFX(DPFPREP, 5,"riid not found !");
  399. return(E_NOINTERFACE);
  400. }
  401. if ((lpIntNew = (LPINTERFACE_LIST)DNMalloc(sizeof(INTERFACE_LIST))) == NULL)
  402. {
  403. DPFERR("DNMalloc() failed");
  404. return(E_OUTOFMEMORY);
  405. }
  406. lpIntNew->lpVtbl = lpVtbl;
  407. lpIntNew->lRefCount = 0;
  408. lpIntNew->lpIntNext = NULL;
  409. DBG_CASSERT( sizeof( lpIntNew->iid ) == sizeof( riid ) );
  410. memcpy( &(lpIntNew->iid), &riid, sizeof( lpIntNew->iid ) );
  411. lpIntNew->lpObject = lpObject;
  412. *ppv = lpIntNew;
  413. DPFX(DPFPREP, 3,"Returning: hResultCode = [S_OK], *ppv = [%p]",*ppv);
  414. return(S_OK);
  415. }
  416. #undef DPF_MODNAME
  417. #define DPF_MODNAME "DPL_FindInterface"
  418. LPINTERFACE_LIST DPL_FindInterface(LPVOID lpv, REFIID riid)
  419. {
  420. LPINTERFACE_LIST lpIntList;
  421. DPFX(DPFPREP, 3,"Parameters: lpv [%p], riid [%p]",lpv,riid);
  422. lpIntList = ((LPINTERFACE_LIST)lpv)->lpObject->lpIntList; // Find first interface
  423. while (lpIntList != NULL)
  424. {
  425. if (IsEqualIID(riid,lpIntList->iid))
  426. break;
  427. lpIntList = lpIntList->lpIntNext;
  428. }
  429. DPFX(DPFPREP, 3,"Returning: lpIntList = [%p]",lpIntList);
  430. return(lpIntList);
  431. }
  432. #undef DPF_MODNAME
  433. #define DPF_MODNAME "DPL_QueryInterface"
  434. STDMETHODIMP DPL_QueryInterface(LPVOID lpv,REFIID riid,LPVOID *ppv)
  435. {
  436. LPINTERFACE_LIST lpIntList;
  437. LPINTERFACE_LIST lpIntNew;
  438. HRESULT hResultCode;
  439. PDIRECTPLAYLOBBYOBJECT pdpLobbyObject;
  440. DPFX(DPFPREP, 3,"Parameters: lpv [0x%p], riid [0x%p], ppv [0x%p]",lpv,riid,ppv);
  441. TRY
  442. {
  443. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(GET_OBJECT_FROM_INTERFACE(lpv));
  444. lpIntList = (LPINTERFACE_LIST)lpv;
  445. if( FAILED( hResultCode = DPL_ValidateQueryInterface( lpv,riid,ppv ) ) )
  446. {
  447. DPFX(DPFPREP, 0, "Error validating QueryInterface params hr=[0x%lx]", hResultCode );
  448. DPF_RETURN(hResultCode);
  449. }
  450. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBIEDAPPLICATION &&
  451. riid == IID_IDirectPlay8LobbyClient )
  452. {
  453. DPFERR( "Cannot request lobbyclient interface from lobbyapp object" );
  454. return DPNERR_NOINTERFACE;
  455. }
  456. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBYCLIENT &&
  457. riid == IID_IDirectPlay8LobbiedApplication )
  458. {
  459. DPFERR( "Cannot request lobbied application interface from lobbyclient object" );
  460. return DPNERR_NOINTERFACE;
  461. }
  462. }
  463. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  464. {
  465. DPFERR("Invalid object" );
  466. DPF_RETURN(DPNERR_INVALIDOBJECT);
  467. }
  468. if ((lpIntList = DPL_FindInterface(lpv,riid)) == NULL)
  469. { // Interface must be created
  470. lpIntList = ((LPINTERFACE_LIST)lpv)->lpObject->lpIntList;
  471. if ((hResultCode = DPL_CreateInterface(lpIntList->lpObject,riid,&lpIntNew)) != S_OK)
  472. {
  473. DPF_RETURN(hResultCode);
  474. }
  475. lpIntNew->lpIntNext = lpIntList;
  476. ((LPINTERFACE_LIST)lpv)->lpObject->lpIntList = lpIntNew;
  477. lpIntList = lpIntNew;
  478. }
  479. if (lpIntList->lRefCount == 0) // New interface exposed
  480. {
  481. InterlockedIncrement( &lpIntList->lpObject->lRefCount );
  482. }
  483. InterlockedIncrement( &lpIntList->lRefCount );
  484. *ppv = lpIntList;
  485. DPF_RETURN(S_OK);
  486. }
  487. #undef DPF_MODNAME
  488. #define DPF_MODNAME "DPL_AddRef"
  489. STDMETHODIMP_(ULONG) DPL_AddRef(LPVOID lpv)
  490. {
  491. LPINTERFACE_LIST lpIntList;
  492. PDIRECTPLAYLOBBYOBJECT pdpLobbyObject;
  493. HRESULT hResultCode;
  494. DPFX(DPFPREP, 3,"Parameters: lpv [%p]",lpv);
  495. TRY
  496. {
  497. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(GET_OBJECT_FROM_INTERFACE(lpv));
  498. lpIntList = (LPINTERFACE_LIST)lpv;
  499. if( FAILED( hResultCode = DPL_ValidateAddRef( lpv ) ) )
  500. {
  501. DPFX(DPFPREP, 0, "Error validating AddRef params hr=[0x%lx]", hResultCode );
  502. DPF_RETURN(0);
  503. }
  504. }
  505. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  506. {
  507. DPFERR("Invalid object" );
  508. DPF_RETURN(0);
  509. }
  510. InterlockedIncrement( &lpIntList->lRefCount );
  511. DPF_RETURN(lpIntList->lRefCount);
  512. }
  513. #undef DPF_MODNAME
  514. #define DPF_MODNAME "DPL_Release"
  515. STDMETHODIMP_(ULONG) DPL_Release(LPVOID lpv)
  516. {
  517. LPINTERFACE_LIST lpIntList;
  518. LPINTERFACE_LIST lpIntCurrent;
  519. PDIRECTPLAYLOBBYOBJECT pdpLobbyObject;
  520. HRESULT hResultCode;
  521. DPFX(DPFPREP, 3,"Parameters: lpv [%p]",lpv);
  522. TRY
  523. {
  524. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(GET_OBJECT_FROM_INTERFACE(lpv));
  525. lpIntList = (LPINTERFACE_LIST)lpv;
  526. if( FAILED( hResultCode = DPL_ValidateRelease( lpv ) ) )
  527. {
  528. DPFX(DPFPREP, 0, "Error validating release params hr=[0x%lx]", hResultCode );
  529. DPF_RETURN(0);
  530. }
  531. }
  532. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  533. {
  534. DPFERR("Invalid object" );
  535. DPF_RETURN(0);
  536. }
  537. DPFX(DPFPREP, 5,"Original : lpIntList->lRefCount = %ld",lpIntList->lRefCount);
  538. DPFX(DPFPREP, 5,"Original : lpIntList->lpObject->lRefCount = %ld",lpIntList->lpObject->lRefCount);
  539. if( InterlockedDecrement( &lpIntList->lRefCount ) == 0 )
  540. { // Decrease interface count
  541. if( InterlockedDecrement( &lpIntList->lpObject->lRefCount ) == 0 )
  542. { // Free object and all interfaces
  543. DPFX(DPFPREP, 5,"Free object");
  544. if( pdpLobbyObject->pReceiveQueue )
  545. {
  546. DPFX(DPFPREP, 0, "*******************************************************************" );
  547. DPFX(DPFPREP, 0, "ERROR: Releasing object without calling close!" );
  548. DPFX(DPFPREP, 0, "You MUST call Close before destroying the object" );
  549. DPFX(DPFPREP, 0, "*******************************************************************" );
  550. DPL_Close( lpv, 0 );
  551. }
  552. // Free object here
  553. DPLCF_FreeObject(lpIntList->lpObject->lpvData);
  554. lpIntList = lpIntList->lpObject->lpIntList; // Get head of interface list
  555. DPFX(DPFPREP, 5,"lpIntList->lpObject [%p]",lpIntList->lpObject);
  556. DNFree(lpIntList->lpObject);
  557. // Free Interfaces
  558. DPFX(DPFPREP, 5,"Free interfaces");
  559. while(lpIntList != NULL)
  560. {
  561. lpIntCurrent = lpIntList;
  562. lpIntList = lpIntList->lpIntNext;
  563. DPFX(DPFPREP, 5,"\tinterface [%p]",lpIntCurrent);
  564. DNFree(lpIntCurrent);
  565. }
  566. GdwHObjects--;
  567. DPFX(DPFPREP, 3,"Returning: 0");
  568. return(0);
  569. }
  570. }
  571. DPFX(DPFPREP, 3,"Returning: lpIntList->lRefCount = [%lx]",lpIntList->lRefCount);
  572. DPF_RETURN(lpIntList->lRefCount);
  573. }