Leaked source code of windows server 2003
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.

1035 lines
30 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 = pdpLobbyObject->m_HandleTable.Create(pdplConnection, &handle)) != DPN_OK)
  73. {
  74. DPFERR("Could not create Connection handle");
  75. DisplayDNError(0,hResultCode);
  76. DNFree(pdplConnection);
  77. return(hResultCode);
  78. }
  79. // Create connect event
  80. pdplConnection->hConnectEvent = DNCreateEvent(NULL,TRUE,FALSE,NULL);
  81. if (pdplConnection->hConnectEvent == NULL)
  82. {
  83. DPFERR("Could not create connection connect event");
  84. pdpLobbyObject->m_HandleTable.Destroy(handle, NULL);
  85. DNFree(pdplConnection);
  86. return(DPNERR_OUTOFMEMORY);
  87. }
  88. // Initialize entry
  89. pdplConnection->hConnect = handle;
  90. pdplConnection->dwTargetProcessIdentity = 0;
  91. pdplConnection->hTargetProcess=NULL;
  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. DNCloseHandle(pdplConnection->hConnectEvent);
  100. pdpLobbyObject->m_HandleTable.Destroy(handle, NULL);
  101. DNFree(pdplConnection);
  102. return(DPNERR_OUTOFMEMORY);
  103. }
  104. pdplConnection->m_blLobbyObjectLinkage.Initialize(); // TODO: MASONB: Pool these
  105. // TODO: MASONB: Set recursion count to 0 on m_cs and above
  106. DNEnterCriticalSection(&pdpLobbyObject->m_cs);
  107. pdplConnection->m_blLobbyObjectLinkage.InsertBefore(&pdpLobbyObject->m_blConnections);
  108. pdpLobbyObject->m_dwConnectionCount++;
  109. DNLeaveCriticalSection(&pdpLobbyObject->m_cs);
  110. *phConnect = handle;
  111. if (ppdplConnection != NULL)
  112. *ppdplConnection = pdplConnection;
  113. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  114. return(hResultCode);
  115. }
  116. #undef DPF_MODNAME
  117. #define DPF_MODNAME "DPLConnectionFind"
  118. HRESULT DPLConnectionFind(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  119. const DPNHANDLE hConnect,
  120. DPL_CONNECTION **const ppdplConnection,
  121. const BOOL fAddRef)
  122. {
  123. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx], ppdplConnection [0x%p], fAddRef [%ld]",
  124. hConnect, ppdplConnection, fAddRef);
  125. DNASSERT(pdpLobbyObject != NULL);
  126. DNASSERT(hConnect != NULL);
  127. DNASSERT(ppdplConnection != NULL);
  128. pdpLobbyObject->m_HandleTable.Lock();
  129. if (FAILED(pdpLobbyObject->m_HandleTable.Find(hConnect, (PVOID*)ppdplConnection)))
  130. {
  131. pdpLobbyObject->m_HandleTable.Unlock();
  132. DPFERR("Could not retrieve handle");
  133. return DPNERR_INVALIDHANDLE;
  134. }
  135. if (fAddRef)
  136. {
  137. DNInterlockedIncrement(&(*ppdplConnection)->lRefCount);
  138. }
  139. pdpLobbyObject->m_HandleTable.Unlock();
  140. return DPN_OK;
  141. }
  142. // DPLConnectionGetConnectSettings
  143. //
  144. // This function gets the connection settings attached to the specified connection.
  145. //
  146. #undef DPF_MODNAME
  147. #define DPF_MODNAME "DPLConnectionGetConnectSettings"
  148. HRESULT DPLConnectionGetConnectSettings( DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  149. DPNHANDLE const hConnect,
  150. DPL_CONNECTION_SETTINGS * const pdplConnectSettings,
  151. DWORD * const pdwDataSize )
  152. {
  153. HRESULT hResultCode;
  154. DPL_CONNECTION *pdplConnection;
  155. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnect, &pdplConnection, TRUE );
  156. if( FAILED( hResultCode ) )
  157. {
  158. DPFERR( "Unable to find specified connection" );
  159. return hResultCode;
  160. }
  161. // Grab lock to keep people from interfering.
  162. DNEnterCriticalSection( &pdplConnection->csLock );
  163. if( !pdplConnection->pConnectionSettings )
  164. {
  165. *pdwDataSize = 0;
  166. hResultCode = DPNERR_DOESNOTEXIST;
  167. goto GETCONNECTIONSETTINGS_EXIT;
  168. }
  169. hResultCode = pdplConnection->pConnectionSettings->CopyToBuffer( (BYTE *) pdplConnectSettings, pdwDataSize );
  170. GETCONNECTIONSETTINGS_EXIT:
  171. DNLeaveCriticalSection( &pdplConnection->csLock );
  172. // Release this function's reference
  173. DPLConnectionRelease( pdpLobbyObject, hConnect );
  174. return hResultCode;
  175. }
  176. // DPLConnectionSetConnectSettings
  177. //
  178. // This function sets the connection settings attached to the specified connection.
  179. //
  180. #undef DPF_MODNAME
  181. #define DPF_MODNAME "DPLConnectionSetConnectSettings"
  182. HRESULT DPLConnectionSetConnectSettings(
  183. DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  184. const DPNHANDLE hConnect,
  185. CConnectionSettings * pConnectionSettings )
  186. {
  187. HRESULT hResultCode;
  188. DPL_CONNECTION *pdplConnection;
  189. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnect, &pdplConnection, TRUE );
  190. if( FAILED( hResultCode ) )
  191. {
  192. DPFERR( "Unable to find specified connection" );
  193. return hResultCode;
  194. }
  195. // Grab lock to prevent other people from interfering
  196. DNEnterCriticalSection( &pdplConnection->csLock );
  197. // Free old one if there is one
  198. if( pdplConnection->pConnectionSettings )
  199. {
  200. delete pdplConnection->pConnectionSettings;
  201. pdplConnection->pConnectionSettings = NULL;
  202. }
  203. pdplConnection->pConnectionSettings = pConnectionSettings;
  204. hResultCode = DPN_OK;
  205. DNLeaveCriticalSection( &pdplConnection->csLock );
  206. DPLConnectionRelease( pdpLobbyObject, hConnect );
  207. return DPN_OK;
  208. }
  209. #undef DPF_MODNAME
  210. #define DPF_MODNAME "DPLConnectionGetContext"
  211. HRESULT DPLConnectionGetContext(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  212. const DPNHANDLE hConnection,
  213. PVOID *ppvConnectContext )
  214. {
  215. HRESULT hResultCode;
  216. DPL_CONNECTION *pdplConnection;
  217. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnection, &pdplConnection, TRUE );
  218. if( FAILED( hResultCode ) )
  219. {
  220. *ppvConnectContext = NULL;
  221. DPFERR( "Unable to find specified connection" );
  222. return hResultCode;
  223. }
  224. // Set connection context for the found handle
  225. DNEnterCriticalSection( &pdplConnection->csLock );
  226. *ppvConnectContext = pdplConnection->pvConnectContext;
  227. DNLeaveCriticalSection( &pdplConnection->csLock );
  228. // Release our reference to the connection
  229. DPLConnectionRelease( pdpLobbyObject, hConnection );
  230. return DPN_OK;
  231. }
  232. #undef DPF_MODNAME
  233. #define DPF_MODNAME "DPLConnectionSetContext"
  234. HRESULT DPLConnectionSetContext(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  235. const DPNHANDLE hConnection,
  236. PVOID pvConnectContext )
  237. {
  238. HRESULT hResultCode;
  239. DPL_CONNECTION *pdplConnection;
  240. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnection, &pdplConnection, TRUE );
  241. if( FAILED( hResultCode ) )
  242. {
  243. DPFERR( "Unable to find specified connection" );
  244. return hResultCode;
  245. }
  246. // Set connection context for the found handle
  247. DNEnterCriticalSection( &pdplConnection->csLock );
  248. pdplConnection->pvConnectContext = pvConnectContext;
  249. DNLeaveCriticalSection( &pdplConnection->csLock );
  250. // Release our reference to the connection
  251. DPLConnectionRelease( pdpLobbyObject, hConnection );
  252. return DPN_OK;
  253. }
  254. #undef DPF_MODNAME
  255. #define DPF_MODNAME "DPLConnectionRelease"
  256. HRESULT DPLConnectionRelease(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  257. const DPNHANDLE hConnect)
  258. {
  259. DPL_CONNECTION *pdplConnection;
  260. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]", hConnect);
  261. // TODO: MASONB: Thread safety issues
  262. if (FAILED(pdpLobbyObject->m_HandleTable.Find(hConnect, (PVOID*)&pdplConnection)))
  263. {
  264. DPFERR("Could not retrieve connection");
  265. return DPNERR_GENERIC;
  266. }
  267. if (DNInterlockedDecrement(&pdplConnection->lRefCount) == 0)
  268. {
  269. pdpLobbyObject->m_HandleTable.Destroy(hConnect, NULL);
  270. DNEnterCriticalSection(&pdpLobbyObject->m_cs);
  271. // This may already have been done by the timeout code
  272. if (!pdplConnection->m_blLobbyObjectLinkage.IsEmpty())
  273. {
  274. pdplConnection->m_blLobbyObjectLinkage.RemoveFromList();
  275. pdpLobbyObject->m_dwConnectionCount--;
  276. }
  277. DNLeaveCriticalSection(&pdpLobbyObject->m_cs);
  278. DPFX(DPFPREP, 5,"Freeing object");
  279. if (pdplConnection->pSendQueue)
  280. {
  281. pdplConnection->pSendQueue->Close();
  282. delete pdplConnection->pSendQueue;
  283. pdplConnection->pSendQueue = NULL;
  284. delete pdplConnection->pConnectionSettings;
  285. pdplConnection->pConnectionSettings = NULL;
  286. DNDeleteCriticalSection( &pdplConnection->csLock );
  287. }
  288. DNCloseHandle(pdplConnection->hConnectEvent);
  289. if (pdplConnection->hTargetProcess)
  290. DNCloseHandle(pdplConnection->hTargetProcess);
  291. DNFree(pdplConnection);
  292. }
  293. DPFX(DPFPREP, 3,"Returning: DPN_OK");
  294. return DPN_OK;
  295. }
  296. #undef DPF_MODNAME
  297. #define DPF_MODNAME "DPLConnectionConnect"
  298. HRESULT DPLConnectionConnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  299. const DPNHANDLE hConnect,
  300. const DWORD dwProcessId,
  301. const BOOL fApplication )
  302. {
  303. HRESULT hResultCode;
  304. DPL_CONNECTION *pdplConnection;
  305. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx], dwProcessId [0x%lx]",
  306. hConnect,dwProcessId);
  307. DNASSERT(pdpLobbyObject != NULL);
  308. DNASSERT(hConnect != NULL);
  309. DNASSERT(dwProcessId != 0);
  310. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
  311. {
  312. DPFERR("Could not find connection");
  313. DisplayDNError(0,hResultCode);
  314. return(hResultCode);
  315. }
  316. pdplConnection->pSendQueue = new CMessageQueue;
  317. if( !pdplConnection->pSendQueue )
  318. {
  319. DPFERR("Could not allocate queue out of memory");
  320. DPLConnectionRelease(pdpLobbyObject,hConnect);
  321. hResultCode = DPNERR_OUTOFMEMORY;
  322. return(hResultCode);
  323. }
  324. hResultCode = pdplConnection->pSendQueue->Open(dwProcessId,
  325. (fApplication) ? DPL_MSGQ_OBJECT_SUFFIX_APPLICATION : DPL_MSGQ_OBJECT_SUFFIX_CLIENT,
  326. DPL_MSGQ_SIZE,
  327. 0, INFINITE);
  328. if (hResultCode != DPN_OK)
  329. {
  330. DPFERR("Could not open message queue");
  331. DisplayDNError(0,hResultCode);
  332. delete pdplConnection->pSendQueue;
  333. pdplConnection->pSendQueue = NULL;
  334. DPLConnectionRelease(pdpLobbyObject,hConnect);
  335. return(hResultCode);
  336. }
  337. // Ensure other side is still connected to MsgQ
  338. if (!pdplConnection->pSendQueue->IsReceiving())
  339. {
  340. DPFERR("Application is not receiving");
  341. pdplConnection->pSendQueue->Close();
  342. delete pdplConnection->pSendQueue;
  343. pdplConnection->pSendQueue = NULL;
  344. DPLConnectionRelease(pdpLobbyObject,hConnect);
  345. return(DPNERR_DOESNOTEXIST);
  346. }
  347. DPLConnectionRelease(pdpLobbyObject,hConnect);
  348. return(hResultCode);
  349. }
  350. #undef DPF_MODNAME
  351. #define DPF_MODNAME "DPLConnectionDisconnect"
  352. HRESULT DPLConnectionDisconnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  353. const DPNHANDLE hConnect )
  354. {
  355. HRESULT hResultCode;
  356. DPL_CONNECTION *pdplConnection;
  357. DPL_INTERNAL_MESSAGE_DISCONNECT Msg;
  358. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
  359. DNASSERT(pdpLobbyObject != NULL);
  360. DNASSERT(hConnect != NULL);
  361. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
  362. {
  363. DPFERR("Could not find connection");
  364. DisplayDNError(0,hResultCode);
  365. return(hResultCode);
  366. }
  367. Msg.dwMsgId = DPL_MSGID_INTERNAL_DISCONNECT;
  368. Msg.dwPID = pdpLobbyObject->dwPID;
  369. hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(&Msg),
  370. sizeof(DPL_INTERNAL_MESSAGE_DISCONNECT),INFINITE,DPL_MSGQ_MSGFLAGS_USER1,0);
  371. // Release the reference for the Find above
  372. DPLConnectionRelease(pdpLobbyObject,hConnect);
  373. // Release the interface's reference
  374. DPLConnectionRelease(pdpLobbyObject,hConnect);
  375. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  376. return(hResultCode);
  377. }
  378. // DPLConnectionEnum
  379. //
  380. // Enumerate outstanding connections
  381. #undef DPF_MODNAME
  382. #define DPF_MODNAME "DPLConnectionEnum"
  383. HRESULT DPLConnectionEnum(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  384. DPNHANDLE *const prghConnect,
  385. DWORD *const pdwNum)
  386. {
  387. DPL_CONNECTION* pConnection;
  388. CBilink* pblTemp;
  389. DWORD dwCount;
  390. DPFX(DPFPREP, 3,"Parameters: prghConnect [0x%p], pdwNum [0x%p]",prghConnect,pdwNum);
  391. DNEnterCriticalSection(&pdpLobbyObject->m_cs);
  392. if (prghConnect == NULL || *pdwNum < pdpLobbyObject->m_dwConnectionCount)
  393. {
  394. *pdwNum = pdpLobbyObject->m_dwConnectionCount;
  395. DNLeaveCriticalSection(&pdpLobbyObject->m_cs);
  396. return DPNERR_BUFFERTOOSMALL;
  397. }
  398. *pdwNum = pdpLobbyObject->m_dwConnectionCount;
  399. pblTemp = pdpLobbyObject->m_blConnections.GetNext();
  400. for (dwCount = 0; dwCount < pdpLobbyObject->m_dwConnectionCount; dwCount++)
  401. {
  402. DNASSERT(pblTemp != &pdpLobbyObject->m_blConnections);
  403. pConnection = CONTAINING_OBJECT(pblTemp, DPL_CONNECTION, m_blLobbyObjectLinkage);
  404. prghConnect[dwCount] = pConnection->hConnect;
  405. pblTemp = pblTemp->GetNext();
  406. }
  407. DNASSERT(pblTemp == &pdpLobbyObject->m_blConnections);
  408. DNLeaveCriticalSection(&pdpLobbyObject->m_cs);
  409. DPFX(DPFPREP, 3,"Returning: DPN_OK");
  410. return DPN_OK;
  411. }
  412. // DPLConnectionSendREQ
  413. //
  414. // Send a request to connect to another process.
  415. // We will provide the handle of the current Connection to the other side
  416. // to send back as the SenderContext with messages to the local process
  417. // so that we can easily lookup info.
  418. // We will also provide the local PID so the other side can connect to us
  419. #undef DPF_MODNAME
  420. #define DPF_MODNAME "DPLConnectionSendREQ"
  421. HRESULT DPLConnectionSendREQ(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  422. const DPNHANDLE hConnect,
  423. const DWORD dwPID,
  424. DPL_CONNECT_INFO *const pInfo)
  425. {
  426. HRESULT hResultCode;
  427. DPL_CONNECTION *pdplConnection;
  428. DPL_INTERNAL_MESSAGE_CONNECT_REQ *pMsg = NULL;
  429. CPackedBuffer PackedBuffer;
  430. CConnectionSettings *pConnectSettings = NULL;
  431. PBYTE pbTmpBuffer = NULL;
  432. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
  433. DNASSERT(pdpLobbyObject != NULL);
  434. DNASSERT(hConnect != NULL);
  435. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
  436. {
  437. DPFERR("Could not find connection");
  438. DisplayDNError(0,hResultCode);
  439. return(hResultCode);
  440. }
  441. if (!pdplConnection->pSendQueue->IsReceiving())
  442. {
  443. DPFERR("Other side is not receiving");
  444. DPLConnectionRelease(pdpLobbyObject,hConnect);
  445. return(DPNERR_DOESNOTEXIST);
  446. }
  447. DNEnterCriticalSection( &pdplConnection->csLock );
  448. if( pInfo->pdplConnectionSettings )
  449. {
  450. pConnectSettings = new CConnectionSettings();
  451. if( !pConnectSettings )
  452. {
  453. DPFERR("Error allocating memory");
  454. hResultCode = DPNERR_OUTOFMEMORY;
  455. goto CONNECTREQ_EXIT;
  456. }
  457. hResultCode = pConnectSettings->InitializeAndCopy( pInfo->pdplConnectionSettings );
  458. if( FAILED( hResultCode ) )
  459. {
  460. DPFX(DPFPREP, 0, "Error copying settings hr [0x%x]", hResultCode );
  461. goto CONNECTREQ_EXIT;
  462. }
  463. }
  464. PackedBuffer.Initialize( NULL, 0 );
  465. // Determine size of message to send.
  466. PackedBuffer.AddToFront(NULL,sizeof(DPL_INTERNAL_MESSAGE_CONNECT_REQ_HEADER));
  467. // Add connect settings if they exist
  468. if( pInfo->pdplConnectionSettings )
  469. pConnectSettings->BuildWireStruct(&PackedBuffer);
  470. // Add lobby connect data
  471. PackedBuffer.AddToBack(NULL,pInfo->dwLobbyConnectDataSize);
  472. pbTmpBuffer = new BYTE[PackedBuffer.GetSizeRequired()];
  473. if( !pbTmpBuffer )
  474. {
  475. DPFERR("Error allocating memory" );
  476. hResultCode = DPNERR_OUTOFMEMORY;
  477. goto CONNECTREQ_EXIT;
  478. }
  479. pMsg = (DPL_INTERNAL_MESSAGE_CONNECT_REQ *) pbTmpBuffer;
  480. PackedBuffer.Initialize( pMsg, PackedBuffer.GetSizeRequired() );
  481. hResultCode = PackedBuffer.AddToFront( pMsg, sizeof( DPL_INTERNAL_MESSAGE_CONNECT_REQ_HEADER ) );
  482. if( FAILED( hResultCode ) )
  483. {
  484. DPFX( DPFPREP, 0, "Internal error! hr [0x%x]", hResultCode );
  485. goto CONNECTREQ_EXIT;
  486. }
  487. pMsg->dwMsgId = DPL_MSGID_INTERNAL_CONNECT_REQ;
  488. pMsg->hSender = hConnect;
  489. pMsg->dwSenderPID = dwPID;
  490. if( pInfo->pdplConnectionSettings )
  491. {
  492. hResultCode = pConnectSettings->BuildWireStruct(&PackedBuffer);
  493. if( FAILED( hResultCode ) )
  494. {
  495. DPFX( DPFPREP, 0, "Error building wire struct for settings hr [0x%x]", hResultCode );
  496. goto CONNECTREQ_EXIT;
  497. }
  498. pMsg->dwConnectionSettingsSize = 1;
  499. }
  500. else
  501. {
  502. pMsg->dwConnectionSettingsSize = 0;
  503. }
  504. hResultCode = PackedBuffer.AddToBack(pInfo->pvLobbyConnectData, pInfo->dwLobbyConnectDataSize, FALSE);
  505. if( FAILED( hResultCode ) )
  506. {
  507. DPFX( DPFPREP, 0, "Error adding connect data hr [0x%x]", hResultCode );
  508. goto CONNECTREQ_EXIT;
  509. }
  510. pMsg->dwLobbyConnectDataOffset = PackedBuffer.GetTailOffset();
  511. pMsg->dwLobbyConnectDataSize = pInfo->dwLobbyConnectDataSize;
  512. hResultCode = DPLConnectionSetConnectSettings( pdpLobbyObject, hConnect,pConnectSettings );
  513. if( FAILED( hResultCode ) )
  514. {
  515. DPFERR( "Could not set local copy of connection settings" );
  516. goto CONNECTREQ_EXIT;
  517. }
  518. hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(pMsg),
  519. PackedBuffer.GetSizeRequired(),
  520. INFINITE,
  521. DPL_MSGQ_MSGFLAGS_USER1,
  522. 0);
  523. if (hResultCode != DPN_OK)
  524. {
  525. DPFERR("Could not send connect info");
  526. goto CONNECTREQ_EXIT;
  527. }
  528. CONNECTREQ_EXIT:
  529. DNLeaveCriticalSection( &pdplConnection->csLock );
  530. if( pbTmpBuffer )
  531. delete [] pbTmpBuffer;
  532. DPLConnectionRelease(pdpLobbyObject,hConnect);
  533. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  534. if( FAILED( hResultCode ) )
  535. {
  536. if( pConnectSettings )
  537. delete pConnectSettings;
  538. }
  539. return(hResultCode);
  540. }
  541. // DPLConnectionReceiveREQ
  542. //
  543. // Receive a request to connect.
  544. // Attempt to connect to the requesting process using the PID supplied.
  545. // Keep the supplied SenderContext for future sends directed at that process.
  546. // Send a connect acknowledge
  547. #undef DPF_MODNAME
  548. #define DPF_MODNAME "DPLConnectionReceiveREQ"
  549. HRESULT DPLConnectionReceiveREQ(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  550. BYTE *const pBuffer)
  551. {
  552. HRESULT hResultCode;
  553. DPNHANDLE handle;
  554. DPL_CONNECTION *pdplConnection;
  555. DPL_INTERNAL_MESSAGE_CONNECT_REQ *pMsg;
  556. DPL_MESSAGE_CONNECT MsgConnect;
  557. DWORD dwSettingsBufferSize = 0;
  558. BOOL fLobbyLaunching = FALSE;
  559. CConnectionSettings *pConnectSettings = NULL;
  560. BYTE *pbTmpBuffer = NULL;
  561. DPFX(DPFPREP, 3,"Parameters: pBuffer [0x%p]",pBuffer);
  562. DNASSERT(pdpLobbyObject != NULL);
  563. DNASSERT(pBuffer != NULL);
  564. pMsg = reinterpret_cast<DPL_INTERNAL_MESSAGE_CONNECT_REQ*>(pBuffer);
  565. if ((hResultCode = DPLConnectionNew(pdpLobbyObject,&handle,&pdplConnection)) != DPN_OK)
  566. {
  567. DPFERR("Could not create new connection");
  568. DisplayDNError(0,hResultCode);
  569. return(hResultCode);
  570. }
  571. if ((hResultCode = DPLConnectionConnect(pdpLobbyObject,handle,pMsg->dwSenderPID,FALSE)) != DPN_OK)
  572. {
  573. DPFERR("Could not perform requested connection");
  574. goto CONNECTRECVREQ_ERROR;
  575. }
  576. pdplConnection->pSendQueue->SetSenderHandle(pMsg->hSender);
  577. pdplConnection->dwTargetProcessIdentity = pMsg->dwSenderPID;
  578. pdplConnection->hTargetProcess=DNOpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pMsg->dwSenderPID);
  579. if (pdplConnection->hTargetProcess==NULL)
  580. {
  581. DPFX(DPFPREP, 0, "Could not get open process PID %u", pMsg->dwSenderPID);
  582. DisplayDNError(0,GetLastError());
  583. hResultCode=DPNERR_DOESNOTEXIST;
  584. goto CONNECTRECVREQ_ERROR;
  585. }
  586. DPFX(DPFPREP, 0, "PID %u hProcess %u", pMsg->dwSenderPID,
  587. HANDLE_FROM_DNHANDLE(pdplConnection->hTargetProcess));
  588. if ((hResultCode = DPLConnectionSendACK(pdpLobbyObject,handle)) != DPN_OK)
  589. {
  590. DPFERR("Could not send connection acknowledge");
  591. goto CONNECTRECVREQ_ERROR;
  592. }
  593. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_MULTICONNECT)
  594. {
  595. DPFX(DPFPREP, 1, "Multiconnect flag specified, returning app to available status" );
  596. pdpLobbyObject->pReceiveQueue->MakeAvailable();
  597. }
  598. if( pMsg->dwConnectionSettingsSize )
  599. {
  600. pConnectSettings = new CConnectionSettings();
  601. if( !pConnectSettings )
  602. {
  603. DPFERR("Error allocating structure");
  604. hResultCode = DPNERR_OUTOFMEMORY;
  605. goto CONNECTRECVREQ_ERROR;
  606. }
  607. hResultCode = pConnectSettings->Initialize( &pMsg->dplConnectionSettings, (UNALIGNED BYTE *) pMsg );
  608. if( FAILED( hResultCode ) )
  609. {
  610. DPFX( DPFPREP, 0, "Error copying connection settings from wire hr=[0x%x]", hResultCode );
  611. goto CONNECTRECVREQ_ERROR;
  612. }
  613. }
  614. // Update the local connection settings
  615. hResultCode = DPLConnectionSetConnectSettings( pdpLobbyObject, handle, pConnectSettings );
  616. if( FAILED( hResultCode ) )
  617. {
  618. DPFX( DPFPREP, 0, "Error setting connection settings from wire hr=[0x%x]", hResultCode );
  619. goto CONNECTRECVREQ_ERROR;
  620. }
  621. // Indicate connection to application
  622. MsgConnect.dwSize = sizeof(DPL_MESSAGE_CONNECT);
  623. MsgConnect.hConnectId = handle;
  624. if( pMsg->dwLobbyConnectDataSize )
  625. {
  626. // Got to copy the connect data locally to an aligned buffer to ensure alignment -- ack
  627. pbTmpBuffer = new BYTE[pMsg->dwLobbyConnectDataSize];
  628. if( !pbTmpBuffer )
  629. {
  630. DPFERR("Error allocating structure");
  631. hResultCode = DPNERR_OUTOFMEMORY;
  632. goto CONNECTRECVREQ_ERROR;
  633. }
  634. memcpy( pbTmpBuffer, pBuffer + pMsg->dwLobbyConnectDataOffset, pMsg->dwLobbyConnectDataSize );
  635. MsgConnect.pvLobbyConnectData = pbTmpBuffer;
  636. MsgConnect.dwLobbyConnectDataSize = pMsg->dwLobbyConnectDataSize;
  637. }
  638. else
  639. {
  640. MsgConnect.pvLobbyConnectData = NULL;
  641. MsgConnect.dwLobbyConnectDataSize = 0;
  642. }
  643. MsgConnect.pvConnectionContext = NULL;
  644. if( pConnectSettings )
  645. {
  646. MsgConnect.pdplConnectionSettings = pConnectSettings->GetConnectionSettings();
  647. }
  648. else
  649. {
  650. MsgConnect.pdplConnectionSettings = NULL;
  651. }
  652. // If we're lobby launching set the connect event before calling the message handler
  653. // otherwise we may encounter deadlock then timeout if user blocks in callback
  654. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOOKINGFORLOBBYLAUNCH )
  655. {
  656. fLobbyLaunching = TRUE;
  657. pdpLobbyObject->dpnhLaunchedConnection = handle;
  658. }
  659. hResultCode = (pdpLobbyObject->pfnMessageHandler)(pdpLobbyObject->pvUserContext,
  660. DPL_MSGID_CONNECT,
  661. reinterpret_cast<BYTE*>(&MsgConnect));
  662. if( FAILED( hResultCode ) )
  663. {
  664. DPFX( DPFPREP, 0, "Error returned from user's callback -- ignoring hr [0x%x]", hResultCode );
  665. }
  666. // Set the context for this connection
  667. DPLConnectionSetContext( pdpLobbyObject, handle, MsgConnect.pvConnectionContext );
  668. if( pbTmpBuffer )
  669. delete [] pbTmpBuffer;
  670. // If we're looking for a lobby launch, set the dpnhLaunchedConnection to cache the connection handle
  671. DNSetEvent(pdpLobbyObject->hConnectEvent);
  672. DPFX(DPFPREP, 3,"Returning: [0x%lx]",DPN_OK);
  673. return(DPN_OK);
  674. CONNECTRECVREQ_ERROR:
  675. if( pbTmpBuffer )
  676. delete [] pbTmpBuffer;
  677. if( pConnectSettings )
  678. delete pConnectSettings;
  679. DPLConnectionDisconnect(pdpLobbyObject,handle);
  680. DPLConnectionRelease(pdpLobbyObject,handle);
  681. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  682. return(hResultCode);
  683. }
  684. // DPLConnectionSendACK
  685. //
  686. // Send a connect acknowledge.
  687. // Provide the local handle for the connection to the other side for future
  688. // sends to the local process
  689. #undef DPF_MODNAME
  690. #define DPF_MODNAME "DPLConnectionSendACK"
  691. HRESULT DPLConnectionSendACK(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  692. const DPNHANDLE hConnect)
  693. {
  694. HRESULT hResultCode;
  695. DPL_CONNECTION *pdplConnection;
  696. DPL_INTERNAL_MESSAGE_CONNECT_ACK Msg;
  697. DPFX(DPFPREP, 3,"Parameters: hConnect [0x%lx]",hConnect);
  698. DNASSERT(pdpLobbyObject != NULL);
  699. DNASSERT(hConnect != NULL);
  700. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hConnect,&pdplConnection,TRUE)) != DPN_OK)
  701. {
  702. DPFERR("Could not find connection");
  703. DisplayDNError(0,hResultCode);
  704. return(hResultCode);
  705. }
  706. Msg.dwMsgId = DPL_MSGID_INTERNAL_CONNECT_ACK;
  707. Msg.hSender = hConnect;
  708. hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(&Msg),
  709. sizeof(DPL_INTERNAL_MESSAGE_CONNECT_ACK),
  710. INFINITE,
  711. DPL_MSGQ_MSGFLAGS_USER1,
  712. 0);
  713. if (hResultCode != DPN_OK)
  714. {
  715. DPFERR("Could not send connection acknowledge");
  716. DisplayDNError(0,hResultCode);
  717. DPLConnectionRelease(pdpLobbyObject,hConnect);
  718. return(hResultCode);
  719. }
  720. DPLConnectionRelease(pdpLobbyObject,hConnect);
  721. hResultCode = DPN_OK;
  722. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  723. return(hResultCode);
  724. }
  725. // DPLConnectionReceiveACK
  726. //
  727. // Receive a connect acknowledge
  728. // Keep the supplied SenderContext for future sends directed at that process.
  729. #undef DPF_MODNAME
  730. #define DPF_MODNAME "DPLConnectionReceiveACK"
  731. HRESULT DPLConnectionReceiveACK(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  732. const DPNHANDLE hSender,
  733. BYTE *const pBuffer)
  734. {
  735. HRESULT hResultCode;
  736. DPL_CONNECTION *pdplConnection;
  737. DPL_INTERNAL_MESSAGE_CONNECT_ACK *pMsg;
  738. DPFX(DPFPREP, 3,"Parameters: hSender [0x%lx], pBuffer [0x%p]",hSender,pBuffer);
  739. DNASSERT(pdpLobbyObject != NULL);
  740. DNASSERT(pBuffer != NULL);
  741. pMsg = reinterpret_cast<DPL_INTERNAL_MESSAGE_CONNECT_ACK*>(pBuffer);
  742. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hSender,&pdplConnection,TRUE)) != DPN_OK)
  743. {
  744. DPFERR("Could not find sender's connection");
  745. DisplayDNError(0,hResultCode);
  746. return(hResultCode);
  747. }
  748. pdplConnection->pSendQueue->SetSenderHandle(pMsg->hSender);
  749. DNSetEvent(pdplConnection->hConnectEvent);
  750. DPLConnectionRelease(pdpLobbyObject,hSender);
  751. // Indicate that a connection was made by setting event
  752. DNSetEvent(pdpLobbyObject->hConnectEvent);
  753. hResultCode = DPN_OK;
  754. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  755. return(hResultCode);
  756. }
  757. // DPLConnectionReceiveDisconnect
  758. //
  759. // Receive a disconnect
  760. // Terminate the connection
  761. #undef DPF_MODNAME
  762. #define DPF_MODNAME "DPLConnectionReceiveDisconnect"
  763. HRESULT DPLConnectionReceiveDisconnect(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  764. const DPNHANDLE hSender,
  765. BYTE *const pBuffer,
  766. const HRESULT hrDisconnectReason )
  767. {
  768. HRESULT hResultCode;
  769. DPL_CONNECTION *pdplConnection;
  770. DPL_MESSAGE_DISCONNECT MsgDisconnect;
  771. DPFX(DPFPREP, 3,"Parameters: hSender [0x%lx]",hSender);
  772. DNASSERT(pdpLobbyObject != NULL);
  773. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hSender,&pdplConnection,TRUE)) != DPN_OK)
  774. {
  775. DPFERR("Could not find sender's connection");
  776. DisplayDNError(0,hResultCode);
  777. return(hResultCode);
  778. }
  779. // Indicate disconnect to user
  780. MsgDisconnect.dwSize = sizeof(DPL_MESSAGE_DISCONNECT);
  781. MsgDisconnect.hDisconnectId = hSender;
  782. MsgDisconnect.hrReason = hrDisconnectReason;
  783. // Return code is irrelevant, at this point we're going to indicate regardless
  784. hResultCode = DPLConnectionGetContext( pdpLobbyObject, hSender, &MsgDisconnect.pvConnectionContext );
  785. if( FAILED( hResultCode ) )
  786. {
  787. DPFX(DPFPREP, 0, "Error getting connection context for 0x%x hr=0x%x", hSender, hResultCode );
  788. }
  789. hResultCode = (pdpLobbyObject->pfnMessageHandler)(pdpLobbyObject->pvUserContext,
  790. DPL_MSGID_DISCONNECT,
  791. reinterpret_cast<BYTE*>(&MsgDisconnect));
  792. // Fixed memory leak, DPLConnectionRelease will free the send queue
  793. // pdplConnection->pSendQueue->Close();
  794. // pdplConnection->pSendQueue = NULL;
  795. DPLConnectionRelease(pdpLobbyObject,hSender);
  796. DPLConnectionRelease(pdpLobbyObject,hSender);
  797. hResultCode = DPN_OK;
  798. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  799. return(hResultCode);
  800. }