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.

1001 lines
28 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: DPLConnect.cpp
  6. * Content: DirectPlay Lobby Connection Functions
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 02/21/00 mjn Created
  12. * 05/08/00 rmt Bug #33616 -- Does not run on Win9X
  13. * 05/30/00 rmt Bug #35700 - ConnectApp(h), Release(h), Release(h) returns OK
  14. * Added an additional release, handles were never getting destroyed
  15. * 06/15/00 rmt Bug #33617 - Must provide method for providing automatic launch of DirectPlay instances
  16. * 06/28/00 rmt Prefix Bug #38082
  17. * 07/08/2000 rmt Bug #38725 - Need to provide method to detect if app was lobby launched
  18. * rmt Bug #38757 - Callback messages for connections may return AFTER WaitForConnection returns
  19. * rmt Bug #38755 - No way to specify player name in Connection Settings
  20. * rmt Bug #38758 - DPLOBBY8.H has incorrect comments
  21. * rmt Bug #38783 - pvUserApplicationContext is only partially implemented
  22. * rmt Added DPLHANDLE_ALLCONNECTIONS and dwFlags (reserved field to couple of funcs).
  23. * 08/05/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  24. * 08/18/2000 rmt Bug #42751 - DPLOBBY8: Prohibit more than one lobby client or lobby app per process
  25. * 08/30/2000 rmt Bug #171827 - Prefix Bug
  26. * 01/04/2001 rodtoll WinBug #94200 - Remove BUGBUGs from Code.
  27. *@@END_MSINTERNAL
  28. *
  29. ***************************************************************************/
  30. #include "dnlobbyi.h"
  31. //**********************************************************************
  32. // Constant definitions
  33. //**********************************************************************
  34. //**********************************************************************
  35. // Macro definitions
  36. //**********************************************************************
  37. //**********************************************************************
  38. // Structure definitions
  39. //**********************************************************************
  40. //**********************************************************************
  41. // Variable definitions
  42. //**********************************************************************
  43. //**********************************************************************
  44. // Function prototypes
  45. //**********************************************************************
  46. //**********************************************************************
  47. // Function definitions
  48. //**********************************************************************
  49. #undef DPF_MODNAME
  50. #define DPF_MODNAME "DPLConnectionNew"
  51. HRESULT DPLConnectionNew(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  52. DPNHANDLE *const phConnect,
  53. DPL_CONNECTION **const ppdplConnection)
  54. {
  55. HRESULT hResultCode;
  56. DPL_CONNECTION *pdplConnection;
  57. DPNHANDLE handle;
  58. DPFX(DPFPREP, 3,"Parameters: phConnect [0x%p], ppdplConnection [0x%p]",phConnect,ppdplConnection);
  59. if( ppdplConnection == NULL )
  60. {
  61. DPFERR( "ppdplConnection param is NULL -- this should not happen" );
  62. DNASSERT( FALSE );
  63. return DPNERR_GENERIC;
  64. }
  65. // Create connection entry
  66. if ((pdplConnection = static_cast<DPL_CONNECTION*>(DNMalloc(sizeof(DPL_CONNECTION)))) == NULL)
  67. {
  68. DPFERR("Could not allocate Connection entry");
  69. return(DPNERR_OUTOFMEMORY);
  70. }
  71. // Create connection handle
  72. if ((hResultCode = H_Create(&pdpLobbyObject->hsHandles,
  73. static_cast<void*>(pdplConnection),&handle)) != DPN_OK)
  74. {
  75. DPFERR("Could not create Connection handle");
  76. DisplayDNError(0,hResultCode);
  77. DNFree(pdplConnection);
  78. return(hResultCode);
  79. }
  80. // Create connect event
  81. pdplConnection->hConnectEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  82. if (pdplConnection->hConnectEvent == NULL)
  83. {
  84. DPFERR("Could not create connection connect event");
  85. H_Destroy(&pdpLobbyObject->hsHandles,handle);
  86. DNFree(pdplConnection);
  87. return(DPNERR_OUTOFMEMORY);
  88. }
  89. // Initialize entry
  90. pdplConnection->hConnect = handle;
  91. pdplConnection->dwTargetPID = 0;
  92. pdplConnection->pSendQueue = NULL;
  93. pdplConnection->lRefCount = 1;
  94. pdplConnection->pConnectionSettings = NULL;
  95. pdplConnection->pvConnectContext = NULL;
  96. if (DNInitializeCriticalSection( &pdplConnection->csLock ) == FALSE)
  97. {
  98. DPFERR("Could not initialize connection CS");
  99. CloseHandle(pdplConnection->hConnectEvent);
  100. H_Destroy(&pdpLobbyObject->hsHandles,handle);
  101. DNFree(pdplConnection);
  102. return(DPNERR_OUTOFMEMORY);
  103. }
  104. *phConnect = handle;
  105. if (ppdplConnection != NULL)
  106. *ppdplConnection = pdplConnection;
  107. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  108. return(hResultCode);
  109. }
  110. #undef DPF_MODNAME
  111. #define DPF_MODNAME "DPLConnectionFind"
  112. HRESULT DPLConnectionFind(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  113. const DPNHANDLE hConnect,
  114. DPL_CONNECTION **const ppdplConnection,
  115. const BOOL bAddRef)
  116. {
  117. HRESULT hResultCode;
  118. DPL_CONNECTION *pdplConnection;
  119. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx], ppdplConnection [0x%p], bAddRef [%ld]",
  120. hConnect,ppdplConnection,bAddRef);
  121. DNASSERT(pdpLobbyObject != NULL);
  122. DNASSERT(hConnect != NULL);
  123. DNASSERT(ppdplConnection != NULL);
  124. if ((hResultCode = H_Retrieve(&pdpLobbyObject->hsHandles,hConnect,
  125. reinterpret_cast<void**>(&pdplConnection))) != DPN_OK)
  126. {
  127. DPFERR("Could not retrieve handle");
  128. return(hResultCode);
  129. }
  130. if (bAddRef)
  131. {
  132. InterlockedIncrement(&pdplConnection->lRefCount);
  133. }
  134. *ppdplConnection = pdplConnection;
  135. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  136. return(hResultCode);
  137. }
  138. // DPLConnectionGetConnectSettings
  139. //
  140. // This function gets the connection settings attached to the specified connection.
  141. //
  142. #undef DPF_MODNAME
  143. #define DPF_MODNAME "DPLConnectionGetConnectSettings"
  144. HRESULT DPLConnectionGetConnectSettings( DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  145. DPNHANDLE const hConnect,
  146. DPL_CONNECTION_SETTINGS * const pdplConnectSettings,
  147. DWORD * const pdwDataSize )
  148. {
  149. HRESULT hResultCode;
  150. DPL_CONNECTION *pdplConnection;
  151. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnect, &pdplConnection, TRUE );
  152. if( FAILED( hResultCode ) )
  153. {
  154. DPFERR( "Unable to find specified connection" );
  155. return hResultCode;
  156. }
  157. // Grab lock to keep people from interfering.
  158. DNEnterCriticalSection( &pdplConnection->csLock );
  159. if( !pdplConnection->pConnectionSettings )
  160. {
  161. *pdwDataSize = 0;
  162. hResultCode = DPNERR_DOESNOTEXIST;
  163. goto GETCONNECTIONSETTINGS_EXIT;
  164. }
  165. hResultCode = pdplConnection->pConnectionSettings->CopyToBuffer( (BYTE *) pdplConnectSettings, pdwDataSize );
  166. GETCONNECTIONSETTINGS_EXIT:
  167. DNLeaveCriticalSection( &pdplConnection->csLock );
  168. // Release this function's reference
  169. DPLConnectionRelease( pdpLobbyObject, hConnect );
  170. return hResultCode;
  171. }
  172. // DPLConnectionSetConnectSettings
  173. //
  174. // This function sets the connection settings attached to the specified connection.
  175. //
  176. #undef DPF_MODNAME
  177. #define DPF_MODNAME "DPLConnectionSetConnectSettings"
  178. HRESULT DPLConnectionSetConnectSettings(
  179. DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  180. const DPNHANDLE hConnect,
  181. CConnectionSettings * pConnectionSettings )
  182. {
  183. HRESULT hResultCode;
  184. DPL_CONNECTION *pdplConnection;
  185. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnect, &pdplConnection, TRUE );
  186. if( FAILED( hResultCode ) )
  187. {
  188. DPFERR( "Unable to find specified connection" );
  189. return hResultCode;
  190. }
  191. // Grab lock to prevent other people from interfering
  192. DNEnterCriticalSection( &pdplConnection->csLock );
  193. // Free old one if there is one
  194. if( pdplConnection->pConnectionSettings )
  195. {
  196. delete pdplConnection->pConnectionSettings;
  197. pdplConnection->pConnectionSettings = NULL;
  198. }
  199. pdplConnection->pConnectionSettings = pConnectionSettings;
  200. hResultCode = DPN_OK;
  201. DNLeaveCriticalSection( &pdplConnection->csLock );
  202. DPLConnectionRelease( pdpLobbyObject, hConnect );
  203. return DPN_OK;
  204. }
  205. #undef DPF_MODNAME
  206. #define DPF_MODNAME "DPLConnectionGetContext"
  207. HRESULT DPLConnectionGetContext(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  208. const DPNHANDLE hConnection,
  209. PVOID *ppvConnectContext )
  210. {
  211. HRESULT hResultCode;
  212. DPL_CONNECTION *pdplConnection;
  213. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnection, &pdplConnection, TRUE );
  214. if( FAILED( hResultCode ) )
  215. {
  216. *ppvConnectContext = NULL;
  217. DPFERR( "Unable to find specified connection" );
  218. return hResultCode;
  219. }
  220. // Set connection context for the found handle
  221. DNEnterCriticalSection( &pdplConnection->csLock );
  222. *ppvConnectContext = pdplConnection->pvConnectContext;
  223. DNLeaveCriticalSection( &pdplConnection->csLock );
  224. // Release our reference to the connection
  225. DPLConnectionRelease( pdpLobbyObject, hConnection );
  226. return DPN_OK;
  227. }
  228. #undef DPF_MODNAME
  229. #define DPF_MODNAME "DPLConnectionSetContext"
  230. HRESULT DPLConnectionSetContext(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  231. const DPNHANDLE hConnection,
  232. PVOID pvConnectContext )
  233. {
  234. HRESULT hResultCode;
  235. DPL_CONNECTION *pdplConnection;
  236. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnection, &pdplConnection, TRUE );
  237. if( FAILED( hResultCode ) )
  238. {
  239. DPFERR( "Unable to find specified connection" );
  240. return hResultCode;
  241. }
  242. // Set connection context for the found handle
  243. DNEnterCriticalSection( &pdplConnection->csLock );
  244. pdplConnection->pvConnectContext = pvConnectContext;
  245. DNLeaveCriticalSection( &pdplConnection->csLock );
  246. // Release our reference to the connection
  247. DPLConnectionRelease( pdpLobbyObject, hConnection );
  248. return DPN_OK;
  249. }
  250. #undef DPF_MODNAME
  251. #define DPF_MODNAME "DPLConnectionRelease"
  252. HRESULT DPLConnectionRelease(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  253. const DPNHANDLE hConnect)
  254. {
  255. HRESULT hResultCode;
  256. DPL_CONNECTION *pdplConnection;
  257. LONG lRefCount;
  258. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
  259. if ((hResultCode = H_Retrieve(&pdpLobbyObject->hsHandles,hConnect,
  260. reinterpret_cast<void**>(&pdplConnection))) != DPN_OK)
  261. {
  262. DPFERR("Could not retrieve connection");
  263. DisplayDNError(0,hResultCode);
  264. return(hResultCode);
  265. }
  266. if (InterlockedDecrement(&pdplConnection->lRefCount) == 0)
  267. {
  268. H_Destroy(&pdpLobbyObject->hsHandles,hConnect);
  269. DPFX(DPFPREP, 5,"Freeing object");
  270. if (pdplConnection->pSendQueue)
  271. {
  272. pdplConnection->pSendQueue->Close();
  273. delete pdplConnection->pSendQueue;
  274. pdplConnection->pSendQueue = NULL;
  275. delete pdplConnection->pConnectionSettings;
  276. pdplConnection->pConnectionSettings = NULL;
  277. DNDeleteCriticalSection( &pdplConnection->csLock );
  278. }
  279. CloseHandle(pdplConnection->hConnectEvent);
  280. DNFree(pdplConnection);
  281. }
  282. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  283. return(hResultCode);
  284. }
  285. #undef DPF_MODNAME
  286. #define DPF_MODNAME "DPLConnectionConnect"
  287. HRESULT DPLConnectionConnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  288. const DPNHANDLE hConnect,
  289. const DWORD dwProcessId,
  290. const BOOL fApplication )
  291. {
  292. HRESULT hResultCode;
  293. DPL_CONNECTION *pdplConnection;
  294. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx], dwProcessId [0x%lx]",
  295. hConnect,dwProcessId);
  296. DNASSERT(pdpLobbyObject != NULL);
  297. DNASSERT(hConnect != NULL);
  298. DNASSERT(dwProcessId != 0);
  299. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
  300. {
  301. DPFERR("Could not find connection");
  302. DisplayDNError(0,hResultCode);
  303. return(hResultCode);
  304. }
  305. pdplConnection->pSendQueue = new CMessageQueue;
  306. if( !pdplConnection->pSendQueue )
  307. {
  308. DPFERR("Could not allocate queue out of memory");
  309. DPLConnectionRelease(pdpLobbyObject,hConnect);
  310. hResultCode = DPNERR_OUTOFMEMORY;
  311. return(hResultCode);
  312. }
  313. hResultCode = pdplConnection->pSendQueue->Open(dwProcessId,
  314. (fApplication) ? DPL_MSGQ_OBJECT_SUFFIX_APPLICATION : DPL_MSGQ_OBJECT_SUFFIX_CLIENT,
  315. DPL_MSGQ_SIZE,
  316. 0, INFINITE);
  317. if (hResultCode != DPN_OK)
  318. {
  319. DPFERR("Could not open message queue");
  320. DisplayDNError(0,hResultCode);
  321. delete pdplConnection->pSendQueue;
  322. pdplConnection->pSendQueue = NULL;
  323. DPLConnectionRelease(pdpLobbyObject,hConnect);
  324. return(hResultCode);
  325. }
  326. // Ensure other side is still connected to MsgQ
  327. if (!pdplConnection->pSendQueue->IsReceiving())
  328. {
  329. DPFERR("Application is not receiving");
  330. pdplConnection->pSendQueue->Close();
  331. delete pdplConnection->pSendQueue;
  332. pdplConnection->pSendQueue = NULL;
  333. DPLConnectionRelease(pdpLobbyObject,hConnect);
  334. return(DPNERR_DOESNOTEXIST);
  335. }
  336. DPLConnectionRelease(pdpLobbyObject,hConnect);
  337. return(hResultCode);
  338. }
  339. #undef DPF_MODNAME
  340. #define DPF_MODNAME "DPLConnectionDisconnect"
  341. HRESULT DPLConnectionDisconnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  342. const DPNHANDLE hConnect )
  343. {
  344. HRESULT hResultCode;
  345. DPL_CONNECTION *pdplConnection;
  346. DPL_INTERNAL_MESSAGE_DISCONNECT Msg;
  347. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
  348. DNASSERT(pdpLobbyObject != NULL);
  349. DNASSERT(hConnect != NULL);
  350. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
  351. {
  352. DPFERR("Could not find connection");
  353. DisplayDNError(0,hResultCode);
  354. return(hResultCode);
  355. }
  356. Msg.dwMsgId = DPL_MSGID_INTERNAL_DISCONNECT;
  357. Msg.dwPID = pdpLobbyObject->dwPID;
  358. hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(&Msg),
  359. sizeof(DPL_INTERNAL_MESSAGE_DISCONNECT),INFINITE,DPL_MSGQ_MSGFLAGS_USER1,0);
  360. // Release the reference for the Find above
  361. DPLConnectionRelease(pdpLobbyObject,hConnect);
  362. // Release the interface's reference
  363. DPLConnectionRelease(pdpLobbyObject,hConnect);
  364. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  365. return(hResultCode);
  366. }
  367. // DPLConnectionEnum
  368. //
  369. // Enumerate outstanding connections
  370. #undef DPF_MODNAME
  371. #define DPF_MODNAME "DPLConnectionEnum"
  372. HRESULT DPLConnectionEnum(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  373. DPNHANDLE *const prghConnect,
  374. DWORD *const pdwNum)
  375. {
  376. HRESULT hResultCode;
  377. HRESULT hr;
  378. DPFX(DPFPREP, 3,"Parameters: prghConnect [0x%p], pdwNum [0x%p]",prghConnect,pdwNum);
  379. hr = H_Enum(&pdpLobbyObject->hsHandles,pdwNum,prghConnect);
  380. if (hr == S_OK)
  381. {
  382. hResultCode = DPN_OK;
  383. }
  384. else if (hr == E_POINTER)
  385. {
  386. hResultCode = DPNERR_BUFFERTOOSMALL;
  387. }
  388. else
  389. {
  390. hResultCode = DPNERR_GENERIC;
  391. }
  392. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  393. return(hResultCode);
  394. }
  395. // DPLConnectionSendREQ
  396. //
  397. // Send a request to connect to another process.
  398. // We will provide the handle of the current Connection to the other side
  399. // to send back as the SenderContext with messages to the local process
  400. // so that we can easily lookup info.
  401. // We will also provide the local PID so the other side can connect to us
  402. #undef DPF_MODNAME
  403. #define DPF_MODNAME "DPLConnectionSendREQ"
  404. HRESULT DPLConnectionSendREQ(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  405. const DPNHANDLE hConnect,
  406. const DWORD dwPID,
  407. DPL_CONNECT_INFO *const pInfo)
  408. {
  409. HRESULT hResultCode;
  410. DPL_CONNECTION *pdplConnection;
  411. DPL_INTERNAL_MESSAGE_CONNECT_REQ *pMsg = NULL;
  412. DWORD dwSize;
  413. CPackedBuffer PackedBuffer;
  414. DWORD dwConnectSettingsSize;
  415. CConnectionSettings *pConnectSettings = NULL;
  416. PBYTE pbTmpBuffer = NULL;
  417. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
  418. DNASSERT(pdpLobbyObject != NULL);
  419. DNASSERT(hConnect != NULL);
  420. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
  421. {
  422. DPFERR("Could not find connection");
  423. DisplayDNError(0,hResultCode);
  424. return(hResultCode);
  425. }
  426. if (!pdplConnection->pSendQueue->IsReceiving())
  427. {
  428. DPFERR("Other side is not receiving");
  429. DPLConnectionRelease(pdpLobbyObject,hConnect);
  430. return(DPNERR_DOESNOTEXIST);
  431. }
  432. DNEnterCriticalSection( &pdplConnection->csLock );
  433. if( pInfo->pdplConnectionSettings )
  434. {
  435. pConnectSettings = new CConnectionSettings();
  436. if( !pConnectSettings )
  437. {
  438. DPFERR("Error allocating memory");
  439. hResultCode = DPNERR_OUTOFMEMORY;
  440. goto CONNECTREQ_EXIT;
  441. }
  442. hResultCode = pConnectSettings->InitializeAndCopy( pInfo->pdplConnectionSettings );
  443. if( FAILED( hResultCode ) )
  444. {
  445. DPFX(DPFPREP, 0, "Error copying settings hr [0x%x]", hResultCode );
  446. goto CONNECTREQ_EXIT;
  447. }
  448. }
  449. PackedBuffer.Initialize( NULL, 0 );
  450. // Determine size of message to send.
  451. PackedBuffer.AddToFront(NULL,sizeof(DPL_INTERNAL_MESSAGE_CONNECT_REQ_HEADER));
  452. // Add connect settings if they exist
  453. if( pInfo->pdplConnectionSettings )
  454. pConnectSettings->BuildWireStruct(&PackedBuffer);
  455. // Add lobby connect data
  456. PackedBuffer.AddToBack(NULL,pInfo->dwLobbyConnectDataSize);
  457. pbTmpBuffer = new BYTE[PackedBuffer.GetSizeRequired()];
  458. if( !pbTmpBuffer )
  459. {
  460. DPFERR("Error allocating memory" );
  461. hResultCode = DPNERR_OUTOFMEMORY;
  462. goto CONNECTREQ_EXIT;
  463. }
  464. pMsg = (DPL_INTERNAL_MESSAGE_CONNECT_REQ *) pbTmpBuffer;
  465. PackedBuffer.Initialize( pMsg, PackedBuffer.GetSizeRequired() );
  466. hResultCode = PackedBuffer.AddToFront( pMsg, sizeof( DPL_INTERNAL_MESSAGE_CONNECT_REQ_HEADER ) );
  467. if( FAILED( hResultCode ) )
  468. {
  469. DPFX( DPFPREP, 0, "Internal error! hr [0x%x]", hResultCode );
  470. goto CONNECTREQ_EXIT;
  471. }
  472. pMsg->dwMsgId = DPL_MSGID_INTERNAL_CONNECT_REQ;
  473. pMsg->hSender = hConnect;
  474. pMsg->dwSenderPID = dwPID;
  475. if( pInfo->pdplConnectionSettings )
  476. {
  477. hResultCode = pConnectSettings->BuildWireStruct(&PackedBuffer);
  478. if( FAILED( hResultCode ) )
  479. {
  480. DPFX( DPFPREP, 0, "Error building wire struct for settings hr [0x%x]", hResultCode );
  481. goto CONNECTREQ_EXIT;
  482. }
  483. pMsg->dwConnectionSettingsSize = 1;
  484. }
  485. else
  486. {
  487. pMsg->dwConnectionSettingsSize = 0;
  488. }
  489. hResultCode = PackedBuffer.AddToBack(pInfo->pvLobbyConnectData, pInfo->dwLobbyConnectDataSize, FALSE);
  490. if( FAILED( hResultCode ) )
  491. {
  492. DPFX( DPFPREP, 0, "Error adding connect data hr [0x%x]", hResultCode );
  493. goto CONNECTREQ_EXIT;
  494. }
  495. pMsg->dwLobbyConnectDataOffset = PackedBuffer.GetTailOffset();
  496. pMsg->dwLobbyConnectDataSize = pInfo->dwLobbyConnectDataSize;
  497. hResultCode = DPLConnectionSetConnectSettings( pdpLobbyObject, hConnect,pConnectSettings );
  498. if( FAILED( hResultCode ) )
  499. {
  500. DPFERR( "Could not set local copy of connection settings" );
  501. goto CONNECTREQ_EXIT;
  502. }
  503. hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(pMsg),
  504. PackedBuffer.GetSizeRequired(),
  505. INFINITE,
  506. DPL_MSGQ_MSGFLAGS_USER1,
  507. 0);
  508. if (hResultCode != DPN_OK)
  509. {
  510. DPFERR("Could not send connect info");
  511. goto CONNECTREQ_EXIT;
  512. }
  513. CONNECTREQ_EXIT:
  514. DNLeaveCriticalSection( &pdplConnection->csLock );
  515. if( pbTmpBuffer )
  516. delete [] pbTmpBuffer;
  517. DPLConnectionRelease(pdpLobbyObject,hConnect);
  518. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  519. if( FAILED( hResultCode ) )
  520. {
  521. if( pConnectSettings )
  522. delete pConnectSettings;
  523. }
  524. return(hResultCode);
  525. }
  526. // DPLConnectionReceiveREQ
  527. //
  528. // Receive a request to connect.
  529. // Attempt to connect to the requesting process using the PID supplied.
  530. // Keep the supplied SenderContext for future sends directed at that process.
  531. // Send a connect acknowledge
  532. #undef DPF_MODNAME
  533. #define DPF_MODNAME "DPLConnectionReceiveREQ"
  534. HRESULT DPLConnectionReceiveREQ(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  535. BYTE *const pBuffer)
  536. {
  537. HRESULT hResultCode;
  538. DPNHANDLE handle;
  539. DPL_CONNECTION *pdplConnection;
  540. DPL_INTERNAL_MESSAGE_CONNECT_REQ *pMsg;
  541. DPL_MESSAGE_CONNECT MsgConnect;
  542. DPL_CONNECTION_SETTINGS *pSettingsBuffer = NULL;
  543. DWORD dwSettingsBufferSize = 0;
  544. BOOL fLobbyLaunching = FALSE;
  545. CConnectionSettings *pConnectSettings = NULL;
  546. BYTE *pbTmpBuffer = NULL;
  547. DPFX(DPFPREP, 3,"Parameters: pBuffer [0x%p]",pBuffer);
  548. DNASSERT(pdpLobbyObject != NULL);
  549. DNASSERT(pBuffer != NULL);
  550. pMsg = reinterpret_cast<DPL_INTERNAL_MESSAGE_CONNECT_REQ*>(pBuffer);
  551. if ((hResultCode = DPLConnectionNew(pdpLobbyObject,&handle,&pdplConnection)) != DPN_OK)
  552. {
  553. DPFERR("Could not create new connection");
  554. DisplayDNError(0,hResultCode);
  555. return(hResultCode);
  556. }
  557. if ((hResultCode = DPLConnectionConnect(pdpLobbyObject,handle,pMsg->dwSenderPID,FALSE)) != DPN_OK)
  558. {
  559. DPFERR("Could not perform requested connection");
  560. goto CONNECTRECVREQ_ERROR;
  561. }
  562. pdplConnection->pSendQueue->SetSenderHandle(pMsg->hSender);
  563. pdplConnection->dwTargetPID = pMsg->dwSenderPID;
  564. if ((hResultCode = DPLConnectionSendACK(pdpLobbyObject,handle)) != DPN_OK)
  565. {
  566. DPFERR("Could not send connection acknowledge");
  567. goto CONNECTRECVREQ_ERROR;
  568. }
  569. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_MULTICONNECT)
  570. {
  571. DPFX(DPFPREP, 1, "Multiconnect flag specified, returning app to available status" );
  572. pdpLobbyObject->pReceiveQueue->MakeAvailable();
  573. }
  574. if( pMsg->dwConnectionSettingsSize )
  575. {
  576. pConnectSettings = new CConnectionSettings();
  577. if( !pConnectSettings )
  578. {
  579. DPFERR("Error allocating structure");
  580. hResultCode = DPNERR_OUTOFMEMORY;
  581. goto CONNECTRECVREQ_ERROR;
  582. }
  583. hResultCode = pConnectSettings->Initialize( &pMsg->dplConnectionSettings, (UNALIGNED BYTE *) pMsg );
  584. if( FAILED( hResultCode ) )
  585. {
  586. DPFX( DPFPREP, 0, "Error copying connection settings from wire hr=[0x%x]", hResultCode );
  587. goto CONNECTRECVREQ_ERROR;
  588. }
  589. }
  590. // Update the local connection settings
  591. hResultCode = DPLConnectionSetConnectSettings( pdpLobbyObject, handle, pConnectSettings );
  592. if( FAILED( hResultCode ) )
  593. {
  594. DPFX( DPFPREP, 0, "Error setting connection settings from wire hr=[0x%x]", hResultCode );
  595. goto CONNECTRECVREQ_ERROR;
  596. }
  597. // Indicate connection to application
  598. MsgConnect.dwSize = sizeof(DPL_MESSAGE_CONNECT);
  599. MsgConnect.hConnectId = handle;
  600. if( pMsg->dwLobbyConnectDataSize )
  601. {
  602. // Got to copy the connect data locally to an aligned buffer to ensure alignment -- ack
  603. pbTmpBuffer = new BYTE[pMsg->dwLobbyConnectDataSize];
  604. if( !pbTmpBuffer )
  605. {
  606. DPFERR("Error allocating structure");
  607. hResultCode = DPNERR_OUTOFMEMORY;
  608. goto CONNECTRECVREQ_ERROR;
  609. }
  610. memcpy( pbTmpBuffer, pBuffer + pMsg->dwLobbyConnectDataOffset, pMsg->dwLobbyConnectDataSize );
  611. MsgConnect.pvLobbyConnectData = pbTmpBuffer;
  612. MsgConnect.dwLobbyConnectDataSize = pMsg->dwLobbyConnectDataSize;
  613. }
  614. else
  615. {
  616. MsgConnect.pvLobbyConnectData = NULL;
  617. MsgConnect.dwLobbyConnectDataSize = 0;
  618. }
  619. MsgConnect.pvConnectionContext = NULL;
  620. if( pConnectSettings )
  621. {
  622. MsgConnect.pdplConnectionSettings = pConnectSettings->GetConnectionSettings();
  623. }
  624. else
  625. {
  626. MsgConnect.pdplConnectionSettings = NULL;
  627. }
  628. // If we're lobby launching set the connect event before calling the message handler
  629. // otherwise we may encounter deadlock then timeout if user blocks in callback
  630. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOOKINGFORLOBBYLAUNCH )
  631. {
  632. fLobbyLaunching = TRUE;
  633. pdpLobbyObject->dpnhLaunchedConnection = handle;
  634. }
  635. hResultCode = (pdpLobbyObject->pfnMessageHandler)(pdpLobbyObject->pvUserContext,
  636. DPL_MSGID_CONNECT,
  637. reinterpret_cast<BYTE*>(&MsgConnect));
  638. if( FAILED( hResultCode ) )
  639. {
  640. DPFX( DPFPREP, 0, "Error returned from user's callback -- ignoring hr [0x%x]", hResultCode );
  641. }
  642. // Set the context for this connection
  643. DPLConnectionSetContext( pdpLobbyObject, handle, MsgConnect.pvConnectionContext );
  644. if( pbTmpBuffer )
  645. delete [] pbTmpBuffer;
  646. // If we're looking for a lobby launch, set the dpnhLaunchedConnection to cache the connection handle
  647. SetEvent(pdpLobbyObject->hConnectEvent);
  648. DPFX(DPFPREP, 3,"Returning: [0x%lx]",DPN_OK);
  649. return(DPN_OK);
  650. CONNECTRECVREQ_ERROR:
  651. if( pbTmpBuffer )
  652. delete [] pbTmpBuffer;
  653. if( pConnectSettings )
  654. delete pConnectSettings;
  655. DPLConnectionDisconnect(pdpLobbyObject,handle);
  656. DPLConnectionRelease(pdpLobbyObject,handle);
  657. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  658. return(hResultCode);
  659. }
  660. // DPLConnectionSendACK
  661. //
  662. // Send a connect acknowledge.
  663. // Provide the local handle for the connection to the other side for future
  664. // sends to the local process
  665. #undef DPF_MODNAME
  666. #define DPF_MODNAME "DPLConnectionSendACK"
  667. HRESULT DPLConnectionSendACK(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  668. const DPNHANDLE hConnect)
  669. {
  670. HRESULT hResultCode;
  671. DPL_CONNECTION *pdplConnection;
  672. DPL_INTERNAL_MESSAGE_CONNECT_ACK Msg;
  673. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
  674. DNASSERT(pdpLobbyObject != NULL);
  675. DNASSERT(hConnect != NULL);
  676. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
  677. {
  678. DPFERR("Could not find connection");
  679. DisplayDNError(0,hResultCode);
  680. return(hResultCode);
  681. }
  682. Msg.dwMsgId = DPL_MSGID_INTERNAL_CONNECT_ACK;
  683. Msg.hSender = hConnect;
  684. hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(&Msg),
  685. sizeof(DPL_INTERNAL_MESSAGE_CONNECT_ACK),
  686. INFINITE,
  687. DPL_MSGQ_MSGFLAGS_USER1,
  688. 0);
  689. if (hResultCode != DPN_OK)
  690. {
  691. DPFERR("Could not send connection acknowledge");
  692. DisplayDNError(0,hResultCode);
  693. DPLConnectionRelease(pdpLobbyObject,hConnect);
  694. return(hResultCode);
  695. }
  696. DPLConnectionRelease(pdpLobbyObject,hConnect);
  697. hResultCode = DPN_OK;
  698. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  699. return(hResultCode);
  700. }
  701. // DPLConnectionReceiveACK
  702. //
  703. // Receive a connect acknowledge
  704. // Keep the supplied SenderContext for future sends directed at that process.
  705. #undef DPF_MODNAME
  706. #define DPF_MODNAME "DPLConnectionReceiveACK"
  707. HRESULT DPLConnectionReceiveACK(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  708. const DPNHANDLE hSender,
  709. BYTE *const pBuffer)
  710. {
  711. HRESULT hResultCode;
  712. DPL_CONNECTION *pdplConnection;
  713. DPL_INTERNAL_MESSAGE_CONNECT_ACK *pMsg;
  714. DPFX(DPFPREP, 3,"Parameters: hSender [0x%lx], pBuffer [0x%p]",hSender,pBuffer);
  715. DNASSERT(pdpLobbyObject != NULL);
  716. DNASSERT(pBuffer != NULL);
  717. pMsg = reinterpret_cast<DPL_INTERNAL_MESSAGE_CONNECT_ACK*>(pBuffer);
  718. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hSender,&pdplConnection,TRUE)) != DPN_OK)
  719. {
  720. DPFERR("Could not find sender's connection");
  721. DisplayDNError(0,hResultCode);
  722. return(hResultCode);
  723. }
  724. pdplConnection->pSendQueue->SetSenderHandle(pMsg->hSender);
  725. SetEvent(pdplConnection->hConnectEvent);
  726. DPLConnectionRelease(pdpLobbyObject,hSender);
  727. // Indicate that a connection was made by setting event
  728. SetEvent(pdpLobbyObject->hConnectEvent);
  729. hResultCode = DPN_OK;
  730. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  731. return(hResultCode);
  732. }
  733. // DPLConnectionReceiveDisconnect
  734. //
  735. // Receive a disconnect
  736. // Terminate the connection
  737. #undef DPF_MODNAME
  738. #define DPF_MODNAME "DPLConnectionReceiveDisconnect"
  739. HRESULT DPLConnectionReceiveDisconnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  740. const DPNHANDLE hSender,
  741. BYTE *const pBuffer,
  742. const HRESULT hrDisconnectReason )
  743. {
  744. HRESULT hResultCode;
  745. DPL_CONNECTION *pdplConnection;
  746. DPL_MESSAGE_DISCONNECT MsgDisconnect;
  747. DPFX(DPFPREP, 3,"Parameters: hSender [0x%lx]",hSender);
  748. DNASSERT(pdpLobbyObject != NULL);
  749. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hSender,&pdplConnection,TRUE)) != DPN_OK)
  750. {
  751. DPFERR("Could not find sender's connection");
  752. DisplayDNError(0,hResultCode);
  753. return(hResultCode);
  754. }
  755. // Indicate disconnect to user
  756. MsgDisconnect.dwSize = sizeof(DPL_MESSAGE_DISCONNECT);
  757. MsgDisconnect.hDisconnectId = hSender;
  758. MsgDisconnect.hrReason = hrDisconnectReason;
  759. // Return code is irrelevant, at this point we're going to indicate regardless
  760. hResultCode = DPLConnectionGetContext( pdpLobbyObject, hSender, &MsgDisconnect.pvConnectionContext );
  761. if( FAILED( hResultCode ) )
  762. {
  763. DPFX(DPFPREP, 0, "Error getting connection context for 0x%x hr=0x%x", hSender, hResultCode );
  764. }
  765. hResultCode = (pdpLobbyObject->pfnMessageHandler)(pdpLobbyObject->pvUserContext,
  766. DPL_MSGID_DISCONNECT,
  767. reinterpret_cast<BYTE*>(&MsgDisconnect));
  768. // Fixed memory leak, DPLConnectionRelease will free the send queue
  769. // pdplConnection->pSendQueue->Close();
  770. // pdplConnection->pSendQueue = NULL;
  771. DPLConnectionRelease(pdpLobbyObject,hSender);
  772. DPLConnectionRelease(pdpLobbyObject,hSender);
  773. hResultCode = DPN_OK;
  774. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  775. return(hResultCode);
  776. }