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.

1222 lines
36 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: DPLCommon.cpp
  6. * Content: DirectPlay Lobby Common Functions
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 02/21/00 mjn Created
  12. * 04/13/00 rmt First pass param validation
  13. * 04/26/00 mjn Removed dwTimeOut from Send() API call
  14. * 05/01/00 rmt Bug #33108 -- Initialize returns DPNERR_NORESPONSE when not lobbied
  15. * 05/03/00 rmt Updated initialize so if lobby launched automatically establishes a
  16. * connection and makes self unavailable. (Also waits for connection).
  17. * 05/16/00 rmt Bug #34734 -- Init Client, Init App, Close App hangs --
  18. * both client and app were using 'C' prefix, should have been 'C' for
  19. * client and 'A' for app.
  20. * 06/14/00 rmt Fixed build break with new compiler (added ')''s).
  21. * 06/15/00 rmt Bug #33617 - Must provide method for providing automatic launch of DirectPlay instances
  22. * 06/28/00 rmt Prefix Bug #38082
  23. * 07/06/00 rmt Bug #38717 ASSERTION when sending data
  24. * 07/08/2000 rmt Bug #38725 - Need to provide method to detect if app was lobby launched
  25. * rmt Bug #38757 - Callback messages for connections may return AFTER WaitForConnection returns
  26. * rmt Bug #38755 - No way to specify player name in Connection Settings
  27. * rmt Bug #38758 - DPLOBBY8.H has incorrect comments
  28. * rmt Bug #38783 - pvUserApplicationContext is only partially implemented
  29. * rmt Added DPLHANDLE_ALLCONNECTIONS and dwFlags (reserved field to couple of funcs).
  30. * 07/13/2000 rmt Fixed memory leak
  31. * 07/14/2000 rmt Bug #39257 - LobbyClient::ReleaseApp returns E_OUTOFMEMORY when called when no one connected
  32. * 07/21/2000 rmt Removed assert which wasn't needed
  33. * 08/03/2000 rmt Removed assert which wasn't needed
  34. * 08/05/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  35. * 08/18/2000 rmt Bug #42751 - DPLOBBY8: Prohibit more than one lobby client or lobby app per process
  36. * 08/24/2000 rmt Bug #43317 - DP8LOBBY: Occasionally when closing Lobby App right after releasing handles, causes assertion.
  37. * 02/06/2001 rodtoll WINBUG #293871: DPLOBBY8: [IA64] Lobby launching a 64-bit
  38. * app from 64-bit lobby launcher crashes with unaligned memory error.
  39. *
  40. *@@END_MSINTERNAL
  41. *
  42. ***************************************************************************/
  43. #include "dnlobbyi.h"
  44. //**********************************************************************
  45. // Constant definitions
  46. //**********************************************************************
  47. //**********************************************************************
  48. // Macro definitions
  49. //**********************************************************************
  50. //**********************************************************************
  51. // Structure definitions
  52. //**********************************************************************
  53. //**********************************************************************
  54. // Variable definitions
  55. //**********************************************************************
  56. LONG volatile g_lLobbyAppCount = 0;
  57. LONG volatile g_lLobbyClientCount = 0;
  58. //**********************************************************************
  59. // Function prototypes
  60. //**********************************************************************
  61. //**********************************************************************
  62. // Function definitions
  63. //**********************************************************************
  64. // DPL_GetConnectionSettings
  65. //
  66. // Retrieves the pdplSessionInfo (if any) associated with the specified connection. This method
  67. // is shared between the client and app interfaces.
  68. //
  69. #undef DPF_MODNAME
  70. #define DPF_MODNAME "DPL_GetConnectionSettings"
  71. STDMETHODIMP DPL_GetConnectionSettings(LPVOID lpv,const DPNHANDLE hLobbyClient, DPL_CONNECTION_SETTINGS * const pdplSessionInfo, DWORD *pdwInfoSize, const DWORD dwFlags )
  72. {
  73. HRESULT hResultCode;
  74. DIRECTPLAYLOBBYOBJECT *pdpLobbyObject;
  75. DPFX(DPFPREP, 3,"Parameters: hTarget [0x%lx], pdplSessionInfo [0x%p], pdwInfoSize [%p], dwFlags [0x%lx]",
  76. hLobbyClient,pdplSessionInfo,pdwInfoSize,dwFlags);
  77. #ifndef DPNBUILD_NOPARAMVAL
  78. TRY
  79. {
  80. #endif // !DPNBUILD_NOPARAMVAL
  81. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(GET_OBJECT_FROM_INTERFACE(lpv));
  82. #ifndef DPNBUILD_NOPARAMVAL
  83. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_PARAMVALIDATION )
  84. {
  85. if( FAILED( hResultCode = DPL_ValidateGetConnectionSettings( lpv, hLobbyClient, pdplSessionInfo, pdwInfoSize, dwFlags ) ) )
  86. {
  87. DPFX(DPFPREP, 0, "Error validating getconnectsettings params hr=[0x%lx]", hResultCode );
  88. DPF_RETURN( hResultCode );
  89. }
  90. }
  91. // Ensure we've been initialized
  92. if (pdpLobbyObject->pReceiveQueue == NULL)
  93. {
  94. DPFERR("Not initialized");
  95. DPF_RETURN(DPNERR_UNINITIALIZED);
  96. }
  97. }
  98. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  99. {
  100. DPFERR("Invalid object" );
  101. DPF_RETURN(DPNERR_INVALIDOBJECT);
  102. }
  103. #endif // !DPNBUILD_NOPARAMVAL
  104. // Attempt to retrieve connection settings.
  105. hResultCode = DPLConnectionGetConnectSettings( pdpLobbyObject, hLobbyClient, pdplSessionInfo, pdwInfoSize );
  106. DPF_RETURN( hResultCode );
  107. }
  108. // DPL_SetConnectionSettings
  109. //
  110. // Sets the pdplSessionInfo structure associated with the specified connection. This method
  111. // is shared between the client and app interfaces.
  112. //
  113. // This function will generate a DPL_MSGID_CONNECTION_SETTINGS message to be sent to the specified
  114. // connection.
  115. //
  116. #undef DPF_MODNAME
  117. #define DPF_MODNAME "DPL_SetConnectionSettings"
  118. STDMETHODIMP DPL_SetConnectionSettings(LPVOID lpv,const DPNHANDLE hLobbyClient, const DPL_CONNECTION_SETTINGS * const pdplSessionInfo, const DWORD dwFlags )
  119. {
  120. HRESULT hResultCode;
  121. DPL_CONNECTION *pdplConnection;
  122. DIRECTPLAYLOBBYOBJECT *pdpLobbyObject;
  123. DPNHANDLE *hTargets = NULL;
  124. DWORD dwNumTargets = 0;
  125. DWORD dwTargetIndex = 0;
  126. CConnectionSettings *pConnectionSettings = NULL;
  127. DPFX(DPFPREP, 3,"Parameters: hLobbyClient [0x%lx], pBuffer [0x%p], dwFlags [0x%lx]",
  128. hLobbyClient,pdplSessionInfo,dwFlags);
  129. #ifndef DPNBUILD_NOPARAMVAL
  130. TRY
  131. {
  132. #endif // !DPNBUILD_NOPARAMVAL
  133. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(GET_OBJECT_FROM_INTERFACE(lpv));
  134. #ifndef DPNBUILD_NOPARAMVAL
  135. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_PARAMVALIDATION )
  136. {
  137. if( FAILED( hResultCode = DPL_ValidateSetConnectionSettings( lpv, hLobbyClient, pdplSessionInfo, dwFlags ) ) )
  138. {
  139. DPFX(DPFPREP, 0, "Error validating setconnectsettings params hr=[0x%lx]", hResultCode );
  140. DPF_RETURN( hResultCode );
  141. }
  142. }
  143. // Ensure we've been initialized
  144. if (pdpLobbyObject->pReceiveQueue == NULL)
  145. {
  146. DPFERR("Not initialized");
  147. DPF_RETURN(DPNERR_UNINITIALIZED);
  148. }
  149. }
  150. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  151. {
  152. DPFERR("Invalid object" );
  153. DPF_RETURN(DPNERR_INVALIDOBJECT);
  154. }
  155. #endif // !DPNBUILD_NOPARAMVAL
  156. if( hLobbyClient == DPLHANDLE_ALLCONNECTIONS )
  157. {
  158. dwNumTargets = 0;
  159. // We need loop so if someone adds a connection during our run
  160. // it gets added to our list
  161. //
  162. while( 1 )
  163. {
  164. hResultCode = DPLConnectionEnum( pdpLobbyObject, hTargets, &dwNumTargets );
  165. if( hResultCode == DPNERR_BUFFERTOOSMALL )
  166. {
  167. if( hTargets )
  168. {
  169. delete [] hTargets;
  170. }
  171. hTargets = new DPNHANDLE[dwNumTargets];
  172. if( hTargets == NULL )
  173. {
  174. DPFERR("Error allocating memory" );
  175. dwNumTargets = 0;
  176. hResultCode = DPNERR_OUTOFMEMORY;
  177. goto SETCONNECT_EXIT;
  178. }
  179. continue;
  180. }
  181. else if( FAILED( hResultCode ) )
  182. {
  183. DPFX(DPFPREP, 0, "Error getting list of connections hr=0x%x", hResultCode );
  184. break;
  185. }
  186. else
  187. {
  188. break;
  189. }
  190. }
  191. // Failed getting connection information
  192. if( FAILED( hResultCode ) )
  193. {
  194. if( hTargets )
  195. {
  196. delete [] hTargets;
  197. hTargets = NULL;
  198. }
  199. dwNumTargets = 0;
  200. goto SETCONNECT_EXIT;
  201. }
  202. }
  203. else
  204. {
  205. hTargets = new DPNHANDLE[1]; // We use array delete below so we need array new
  206. if( hTargets == NULL )
  207. {
  208. DPFERR("Error allocating memory" );
  209. dwNumTargets = 0;
  210. hResultCode = DPNERR_OUTOFMEMORY;
  211. goto SETCONNECT_EXIT;
  212. }
  213. dwNumTargets = 1;
  214. hTargets[0] = hLobbyClient;
  215. }
  216. for( dwTargetIndex = 0; dwTargetIndex < dwNumTargets; dwTargetIndex++ )
  217. {
  218. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hTargets[dwTargetIndex],&pdplConnection,TRUE)) != DPN_OK)
  219. {
  220. DPFERR("Invalid send target");
  221. DisplayDNError(0,hResultCode);
  222. continue;
  223. }
  224. if( pdplSessionInfo )
  225. {
  226. pConnectionSettings = new CConnectionSettings();
  227. if( !pConnectionSettings )
  228. {
  229. DPFERR("Error allocating memory" );
  230. hResultCode = DPNERR_OUTOFMEMORY;
  231. goto SETCONNECT_EXIT;
  232. }
  233. hResultCode = pConnectionSettings->InitializeAndCopy( pdplSessionInfo );
  234. if( FAILED( hResultCode ) )
  235. {
  236. DPFX( DPFPREP, 0, "Error setting up connection settings hr [0x%x]", hResultCode );
  237. goto SETCONNECT_EXIT;
  238. }
  239. }
  240. // Attempt to set connection settings.
  241. hResultCode = DPLConnectionSetConnectSettings( pdpLobbyObject, hTargets[dwTargetIndex], pConnectionSettings );
  242. if( FAILED( hResultCode ) )
  243. {
  244. DPFX(DPFPREP, 0, "Error setting connct settings for 0x%x hr=0x%x", hTargets[dwTargetIndex], hResultCode );
  245. delete pConnectionSettings;
  246. }
  247. hResultCode = DPLSendConnectionSettings( pdpLobbyObject, hTargets[dwTargetIndex] );
  248. if( FAILED( hResultCode ) )
  249. {
  250. DPFX(DPFPREP, 0, "Error sending connection settings to client 0x%x hr=0x%x", hTargets[dwTargetIndex], hResultCode );
  251. }
  252. pConnectionSettings = NULL;
  253. }
  254. SETCONNECT_EXIT:
  255. for( dwTargetIndex = 0; dwTargetIndex < dwNumTargets; dwTargetIndex++ )
  256. {
  257. if( hTargets[dwTargetIndex] )
  258. DPLConnectionRelease(pdpLobbyObject,hTargets[dwTargetIndex]);
  259. }
  260. if( hTargets )
  261. delete [] hTargets;
  262. DPF_RETURN(hResultCode);
  263. }
  264. #undef DPF_MODNAME
  265. #define DPF_MODNAME "DPL_RegisterMessageHandlerClient"
  266. STDMETHODIMP DPL_RegisterMessageHandlerClient(PVOID pv,
  267. const PVOID pvUserContext,
  268. const PFNDPNMESSAGEHANDLER pfn,
  269. const DWORD dwFlags)
  270. {
  271. return DPL_RegisterMessageHandler( pv, pvUserContext, pfn, NULL, dwFlags );
  272. }
  273. // HRESULT DPL_RegisterMessageHandler
  274. // PVOID pv Interface pointer
  275. // PVOID pvUserContext User context
  276. // PFNDPNMESSAGEHANDLER pfn User supplied message handler
  277. // DWORD dwFlags Not Used
  278. //
  279. // Returns
  280. // DPN_OK If the message handler was registered without incident
  281. // DPNERR_INVALIDPARAM If there was an invalid parameter
  282. // DPNERR_GENERIC If there were any problems
  283. //
  284. // Notes
  285. // This function registers a user supplied message handler function. This function should
  286. // only be called once, even in cases where a game is being re-connected (i.e. after ending)
  287. //
  288. // This will set up the required message queues, handshake the lobby client's PID (if supplied on the
  289. // command line) and spawn the application's receive message queue thread.
  290. #undef DPF_MODNAME
  291. #define DPF_MODNAME "DPL_RegisterMessageHandler"
  292. STDMETHODIMP DPL_RegisterMessageHandler(PVOID pv,
  293. const PVOID pvUserContext,
  294. const PFNDPNMESSAGEHANDLER pfn,
  295. DPNHANDLE * const pdpnhConnection,
  296. const DWORD dwFlags)
  297. {
  298. HRESULT hResultCode = DPN_OK;
  299. DWORD dwCurrentPid;
  300. DWORD dwThreadId;
  301. PDIRECTPLAYLOBBYOBJECT pdpLobbyObject;
  302. char cSuffix;
  303. DPFX(DPFPREP, 3,"Parameters: pv [0x%p], pfn [0x%p], dwFlags [%lx]",pv,pfn,dwFlags);
  304. #ifndef DPNBUILD_NOPARAMVAL
  305. TRY
  306. {
  307. #endif // !DPNBUILD_NOPARAMVAL
  308. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(GET_OBJECT_FROM_INTERFACE(pv));
  309. #ifndef DPNBUILD_NOPARAMVAL
  310. // TODO: MASONB: Why no paramval flag wrapping this?
  311. if( FAILED( hResultCode = DPL_ValidateRegisterMessageHandler( pv, pvUserContext, pfn, pdpnhConnection, dwFlags ) ) )
  312. {
  313. DPFX(DPFPREP, 0, "Error validating register message handler params hr=[0x%lx]", hResultCode );
  314. DPF_RETURN( hResultCode );
  315. }
  316. // Ensure we've been initialized
  317. if (pdpLobbyObject->pReceiveQueue != NULL)
  318. {
  319. DPFERR("Already initialized");
  320. DPF_RETURN(DPNERR_ALREADYINITIALIZED);
  321. }
  322. }
  323. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  324. {
  325. DPFERR("Invalid object" );
  326. DPF_RETURN(DPNERR_INVALIDOBJECT);
  327. }
  328. #endif // !DPNBUILD_NOPARAMVAL
  329. if (pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBIEDAPPLICATION )
  330. {
  331. // If we weren't at zero complain, otherwise put us at 1
  332. if( DNInterlockedCompareExchange((LONG*)&g_lLobbyAppCount, 1, 0) != 0 )
  333. {
  334. DPFERR( "You can only start one lobbied application per process!" );
  335. DPF_RETURN( DPNERR_NOTALLOWED );
  336. }
  337. }
  338. else
  339. {
  340. DNASSERT(pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBYCLIENT);
  341. // If we weren't at zero complain, otherwise put us at 1
  342. if( DNInterlockedCompareExchange((LONG*)&g_lLobbyClientCount, 1, 0) != 0 )
  343. {
  344. DPFERR( "You can only start one lobby client per process!" );
  345. DPF_RETURN( DPNERR_NOTALLOWED );
  346. }
  347. }
  348. #ifndef DPNBUILD_NOPARAMVAL
  349. // Disable parameter validation flag if DPNINITIALIZE_DISABLEPARAMVAL
  350. // is specified
  351. if( dwFlags & DPLINITIALIZE_DISABLEPARAMVAL )
  352. {
  353. pdpLobbyObject->dwFlags &= ~(DPL_OBJECT_FLAG_PARAMVALIDATION);
  354. }
  355. #endif // !DPNBUILD_NOPARAMVAL
  356. pdpLobbyObject->pfnMessageHandler = pfn;
  357. pdpLobbyObject->pvUserContext = pvUserContext;
  358. pdpLobbyObject->pReceiveQueue = new CMessageQueue;
  359. if( pdpLobbyObject->pReceiveQueue == NULL )
  360. {
  361. DPFX(DPFPREP, 0, "Error allocating receive queue" );
  362. hResultCode = DPNERR_OUTOFMEMORY;
  363. goto ERROR_DPL_RegisterMessageHandler;
  364. }
  365. pdpLobbyObject->pReceiveQueue->SetMessageHandler(static_cast<PVOID>(pdpLobbyObject),DPLMessageHandler);
  366. if (pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBIEDAPPLICATION)
  367. {
  368. cSuffix = DPL_MSGQ_OBJECT_SUFFIX_APPLICATION;
  369. }
  370. else
  371. {
  372. cSuffix = DPL_MSGQ_OBJECT_SUFFIX_CLIENT;
  373. }
  374. // Open application receive message queue
  375. dwCurrentPid = GetCurrentProcessId();
  376. if ((hResultCode = pdpLobbyObject->pReceiveQueue->Open(dwCurrentPid,
  377. cSuffix,DPL_MSGQ_SIZE,DPL_MSGQ_TIMEOUT_IDLE,0)) != DPN_OK)
  378. {
  379. DPFERR("Could not open App Rec Q");
  380. goto ERROR_DPL_RegisterMessageHandler;
  381. }
  382. if ((pdpLobbyObject->hReceiveThread =
  383. DNCreateThread(NULL,(DWORD)NULL,(LPTHREAD_START_ROUTINE)DPLProcessMessageQueue,
  384. static_cast<void*>(pdpLobbyObject->pReceiveQueue),(DWORD)NULL,&dwThreadId)) == NULL)
  385. {
  386. DPFERR("CreateThread() failed");
  387. hResultCode = DPNERR_GENERIC;
  388. pdpLobbyObject->pReceiveQueue->Close();
  389. goto ERROR_DPL_RegisterMessageHandler;
  390. }
  391. pdpLobbyObject->pReceiveQueue->WaitForReceiveThread(INFINITE);
  392. if (pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBIEDAPPLICATION)
  393. {
  394. DPFX(DPFPREP, 5,"Attempt lobby connection");
  395. hResultCode = DPLAttemptLobbyConnection(pdpLobbyObject);
  396. if ( hResultCode == DPN_OK)
  397. {
  398. if( pdpnhConnection )
  399. *pdpnhConnection = pdpLobbyObject->dpnhLaunchedConnection;
  400. DPFX(DPFPREP, 5,"Application was lobby launched");
  401. DPFX(DPFPREP, 5,"Waiting for true connect notification" );
  402. DWORD dwReturnValue = DNWaitForSingleObject( pdpLobbyObject->hConnectEvent, DPL_LOBBYLAUNCHED_CONNECT_TIMEOUT );
  403. DNASSERT( dwReturnValue == WAIT_OBJECT_0 );
  404. }
  405. else if( hResultCode != DPNERR_TIMEDOUT )
  406. {
  407. DPFX(DPFPREP, 5,"Application was not lobby launched");
  408. if( pdpnhConnection )
  409. *pdpnhConnection = NULL;
  410. // Need to reset return code to OK.. this is not an error
  411. hResultCode = DPN_OK;
  412. }
  413. else
  414. {
  415. DPFERR( "App was lobby launched but timed out establishing a connection" );
  416. if( pdpnhConnection )
  417. *pdpnhConnection = NULL;
  418. }
  419. }
  420. EXIT_DPL_RegisterMessageHandler:
  421. DPF_RETURN(hResultCode);
  422. ERROR_DPL_RegisterMessageHandler:
  423. if (pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBIEDAPPLICATION )
  424. {
  425. DNInterlockedExchange((LONG*)&g_lLobbyAppCount, 0);
  426. }
  427. else
  428. {
  429. DNASSERT(pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBYCLIENT);
  430. DNInterlockedExchange((LONG*)&g_lLobbyClientCount, 0);
  431. }
  432. goto EXIT_DPL_RegisterMessageHandler;
  433. }
  434. #undef DPF_MODNAME
  435. #define DPF_MODNAME "DPL_Close"
  436. STDMETHODIMP DPL_Close(PVOID pv, const DWORD dwFlags )
  437. {
  438. HRESULT hResultCode;
  439. DWORD dwNumHandles;
  440. DPNHANDLE *prgHandles;
  441. DWORD dw;
  442. DIRECTPLAYLOBBYOBJECT *pdpLobbyObject;
  443. DPL_CONNECTION *pConnection;
  444. DPFX(DPFPREP, 3,"Parameters: (none)");
  445. #ifndef DPNBUILD_NOPARAMVAL
  446. TRY
  447. {
  448. #endif // !DPNBUILD_NOPARAMVAL
  449. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(GET_OBJECT_FROM_INTERFACE(pv));
  450. #ifndef DPNBUILD_NOPARAMVAL
  451. // TODO: MASONB: Why no paramval flag wrapping this?
  452. if( FAILED( hResultCode = DPL_ValidateClose( pv, dwFlags ) ) )
  453. {
  454. DPFX(DPFPREP, 0, "Error validating close params hr=[0x%lx]", hResultCode );
  455. return hResultCode;
  456. }
  457. // Ensure we've been initialized
  458. if (pdpLobbyObject->pReceiveQueue == NULL)
  459. {
  460. DPFERR("Already closed");
  461. return DPNERR_UNINITIALIZED;
  462. }
  463. }
  464. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  465. {
  466. DPFERR("Invalid object" );
  467. return DPNERR_INVALIDOBJECT;
  468. }
  469. #endif // !DPNBUILD_NOPARAMVAL
  470. // Shutdown the queue first to ensure that we don't end up shutting down a connection
  471. // twice! (E.g. disconnect comes in as we are disconnecting it).
  472. if (pdpLobbyObject->pReceiveQueue)
  473. {
  474. if (pdpLobbyObject->pReceiveQueue->IsOpen())
  475. {
  476. // Ask receive thread to terminate
  477. DPFX(DPFPREP, 5,"Terminate Receive Msg Thread");
  478. pdpLobbyObject->pReceiveQueue->Terminate();
  479. // Wait for termination to occur
  480. if (DNWaitForSingleObject(pdpLobbyObject->hReceiveThread,INFINITE) != WAIT_OBJECT_0)
  481. {
  482. hResultCode = DPNERR_GENERIC;
  483. DPFERR("WaitForSingleObject failed");
  484. }
  485. pdpLobbyObject->pReceiveQueue->Close();
  486. if (pdpLobbyObject->pReceiveQueue)
  487. {
  488. delete pdpLobbyObject->pReceiveQueue;
  489. pdpLobbyObject->pReceiveQueue = NULL;
  490. }
  491. if (pdpLobbyObject->hReceiveThread)
  492. {
  493. DNCloseHandle(pdpLobbyObject->hReceiveThread);
  494. pdpLobbyObject->hReceiveThread = NULL;
  495. }
  496. if (pdpLobbyObject->hConnectEvent)
  497. {
  498. DNCloseHandle(pdpLobbyObject->hConnectEvent);
  499. pdpLobbyObject->hConnectEvent = NULL;
  500. }
  501. if (pdpLobbyObject->hLobbyLaunchConnectEvent)
  502. {
  503. DNCloseHandle(pdpLobbyObject->hLobbyLaunchConnectEvent);
  504. pdpLobbyObject->hLobbyLaunchConnectEvent = NULL;
  505. }
  506. }
  507. }
  508. // Enumerate handles outstanding
  509. dwNumHandles = 0;
  510. prgHandles = NULL;
  511. hResultCode = DPLConnectionEnum(pdpLobbyObject,prgHandles,&dwNumHandles);
  512. while (hResultCode == DPNERR_BUFFERTOOSMALL)
  513. {
  514. if (prgHandles)
  515. DNFree(prgHandles);
  516. if ((prgHandles = static_cast<DPNHANDLE*>(DNMalloc(dwNumHandles*sizeof(DPNHANDLE)))) != NULL)
  517. {
  518. hResultCode = DPLConnectionEnum(pdpLobbyObject,prgHandles,&dwNumHandles);
  519. }
  520. else
  521. {
  522. DPFERR("Could not allocate space for handle array");
  523. hResultCode = DPNERR_OUTOFMEMORY;
  524. break;
  525. }
  526. }
  527. // Send DISCONNECTs to all attached msg queues, for which there are handles
  528. if (hResultCode == DPN_OK)
  529. {
  530. for (dw = 0 ; dw < dwNumHandles ; dw++)
  531. {
  532. hResultCode = DPLConnectionFind(pdpLobbyObject,prgHandles[dw],&pConnection,TRUE );
  533. if( SUCCEEDED( hResultCode ) )
  534. {
  535. hResultCode = DPLConnectionDisconnect(pdpLobbyObject,prgHandles[dw]);
  536. if( FAILED( hResultCode ) )
  537. {
  538. DPFX(DPFPREP, 0, "Error disconnecting connection 0x%x", hResultCode );
  539. }
  540. DPLConnectionRelease( pdpLobbyObject,prgHandles[dw]);
  541. }
  542. }
  543. // Errors above are irrelevant, it's quite possible after building the list of outstanding
  544. // connections that before we attempt to close the list one has gone away.
  545. //
  546. hResultCode = DPN_OK;
  547. }
  548. if (prgHandles)
  549. {
  550. DNFree(prgHandles);
  551. prgHandles = NULL;
  552. }
  553. if (pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBIEDAPPLICATION )
  554. {
  555. DNInterlockedExchange((LONG*)&g_lLobbyAppCount, 0);
  556. }
  557. else
  558. {
  559. DNASSERT(pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_LOBBYCLIENT);
  560. DNInterlockedExchange((LONG*)&g_lLobbyClientCount, 0);
  561. }
  562. DPF_RETURN( hResultCode );
  563. }
  564. #undef DPF_MODNAME
  565. #define DPF_MODNAME "DPL_Send"
  566. STDMETHODIMP DPL_Send(PVOID pv,
  567. const DPNHANDLE hTarget,
  568. BYTE *const pBuffer,
  569. const DWORD dwBufferSize,
  570. const DWORD dwFlags)
  571. {
  572. HRESULT hResultCode;
  573. DPL_CONNECTION *pdplConnection;
  574. DIRECTPLAYLOBBYOBJECT *pdpLobbyObject;
  575. DPNHANDLE *hTargets = NULL;
  576. DWORD dwNumTargets = 0;
  577. DWORD dwTargetIndex = 0;
  578. DPFX(DPFPREP, 3,"Parameters: hTarget [0x%lx], pBuffer [0x%p], dwBufferSize [%ld], dwFlags [0x%lx]",
  579. hTarget,pBuffer,dwBufferSize,dwFlags);
  580. #ifndef DPNBUILD_NOPARAMVAL
  581. TRY
  582. {
  583. #endif // !DPNBUILD_NOPARAMVAL
  584. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(GET_OBJECT_FROM_INTERFACE(pv));
  585. #ifndef DPNBUILD_NOPARAMVAL
  586. if( pdpLobbyObject->dwFlags & DPL_OBJECT_FLAG_PARAMVALIDATION )
  587. {
  588. if( FAILED( hResultCode = DPL_ValidateSend( pv, hTarget, pBuffer, dwBufferSize, dwFlags ) ) )
  589. {
  590. DPFX(DPFPREP, 0, "Error validating send params hr=[0x%lx]", hResultCode );
  591. DPF_RETURN( hResultCode );
  592. }
  593. }
  594. // Ensure we've been initialized
  595. if (pdpLobbyObject->pReceiveQueue == NULL)
  596. {
  597. DPFERR("Not initialized");
  598. DPF_RETURN(DPNERR_UNINITIALIZED);
  599. }
  600. }
  601. EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  602. {
  603. DPFERR("Invalid object" );
  604. DPF_RETURN(DPNERR_INVALIDOBJECT);
  605. }
  606. #endif // !DPNBUILD_NOPARAMVAL
  607. if( hTarget == DPLHANDLE_ALLCONNECTIONS )
  608. {
  609. dwNumTargets = 0;
  610. // We need loop so if someone adds a connection during our run
  611. // it gets added to our list
  612. //
  613. while( 1 )
  614. {
  615. hResultCode = DPLConnectionEnum( pdpLobbyObject, hTargets, &dwNumTargets );
  616. if( hResultCode == DPNERR_BUFFERTOOSMALL )
  617. {
  618. if( hTargets )
  619. {
  620. delete [] hTargets;
  621. }
  622. hTargets = new DPNHANDLE[dwNumTargets];
  623. if( hTargets == NULL )
  624. {
  625. DPFERR("Error allocating memory" );
  626. dwNumTargets = 0;
  627. hResultCode = DPNERR_OUTOFMEMORY;
  628. goto EXIT_AND_CLEANUP;
  629. }
  630. memset( hTargets, 0x00, sizeof(DPNHANDLE)*dwNumTargets);
  631. continue;
  632. }
  633. else if( FAILED( hResultCode ) )
  634. {
  635. DPFX(DPFPREP, 0, "Error getting list of connections hr=0x%x", hResultCode );
  636. break;
  637. }
  638. else
  639. {
  640. break;
  641. }
  642. }
  643. // Failed getting connection information
  644. if( FAILED( hResultCode ) )
  645. {
  646. if( hTargets )
  647. {
  648. delete [] hTargets;
  649. hTargets = NULL;
  650. }
  651. dwNumTargets = 0;
  652. goto EXIT_AND_CLEANUP;
  653. }
  654. }
  655. else
  656. {
  657. hTargets = new DPNHANDLE[1]; // We use array delete below so we need array new
  658. if( hTargets == NULL )
  659. {
  660. DPFERR("Error allocating memory" );
  661. dwNumTargets = 0;
  662. hResultCode = DPNERR_OUTOFMEMORY;
  663. goto EXIT_AND_CLEANUP;
  664. }
  665. dwNumTargets = 1;
  666. hTargets[0] = hTarget;
  667. }
  668. for( dwTargetIndex = 0; dwTargetIndex < dwNumTargets; dwTargetIndex++ )
  669. {
  670. if ((hResultCode = DPLConnectionFind(pdpLobbyObject,hTargets[dwTargetIndex],&pdplConnection,TRUE)) != DPN_OK)
  671. {
  672. DPFERR("Invalid send target");
  673. DisplayDNError(0,hResultCode);
  674. hResultCode = DPNERR_INVALIDHANDLE;
  675. goto EXIT_AND_CLEANUP;
  676. }
  677. DNASSERT(pdplConnection->pSendQueue != NULL);
  678. if (!pdplConnection->pSendQueue->IsReceiving())
  679. {
  680. DPFERR("Other side is not listening");
  681. DPLConnectionRelease(pdpLobbyObject,hTarget);
  682. hResultCode = DPNERR_INVALIDHANDLE;
  683. goto EXIT_AND_CLEANUP;
  684. }
  685. hResultCode = pdplConnection->pSendQueue->Send(pBuffer,dwBufferSize,INFINITE,DPL_MSGQ_MSGFLAGS_USER2,0);
  686. if( FAILED( hResultCode ) )
  687. {
  688. DPFX(DPFPREP, 0, "Error sending to connection 0x%x hr=0x%x", hTargets[dwTargetIndex], hResultCode );
  689. }
  690. }
  691. EXIT_AND_CLEANUP:
  692. for( dwTargetIndex = 0; dwTargetIndex < dwNumTargets; dwTargetIndex++ )
  693. {
  694. if( hTargets[dwTargetIndex] )
  695. DPLConnectionRelease(pdpLobbyObject,hTargets[dwTargetIndex]);
  696. }
  697. if( hTargets )
  698. delete [] hTargets;
  699. DPF_RETURN(hResultCode);
  700. }
  701. #undef DPF_MODNAME
  702. #define DPF_MODNAME "DPLReceiveIdleTimeout"
  703. HRESULT DPLReceiveIdleTimeout(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  704. const DPNHANDLE hSender)
  705. {
  706. DPL_CONNECTION *pConnection;
  707. CBilink* pblTemp;
  708. CBilink blRemove;
  709. blRemove.Initialize();
  710. DPFX(DPFPREP, 6, "(%p) Enumerating processes, checking for exit", pdpLobbyObject );
  711. DNEnterCriticalSection(&pdpLobbyObject->m_cs);
  712. // Go through the list of all connections and build up a list of the ones that
  713. // need to be removed.
  714. pblTemp = pdpLobbyObject->m_blConnections.GetNext();
  715. while (pblTemp != &pdpLobbyObject->m_blConnections)
  716. {
  717. pConnection = CONTAINING_OBJECT(pblTemp, DPL_CONNECTION, m_blLobbyObjectLinkage);
  718. pblTemp = pblTemp->GetNext();
  719. DWORD dwExitCode=0;
  720. if (DNGetExitCodeProcess(pConnection->hTargetProcess, &dwExitCode)==FALSE || dwExitCode!=STILL_ACTIVE)
  721. {
  722. DPFX(DPFPREP, 5, "(%p) Process exit detected hTargetProcess %u dwExitCode %u GetLastError %u",
  723. pdpLobbyObject, HANDLE_FROM_DNHANDLE(pConnection->hTargetProcess), dwExitCode, GetLastError());
  724. // Take the connection off of the Lobby Object's list and on a temporary list
  725. pConnection->m_blLobbyObjectLinkage.RemoveFromList();
  726. pdpLobbyObject->m_dwConnectionCount--;
  727. pConnection->m_blLobbyObjectLinkage.InsertBefore(&blRemove);
  728. }
  729. }
  730. DNLeaveCriticalSection(&pdpLobbyObject->m_cs);
  731. // Go through the list of removed connections and signal the user
  732. pblTemp = blRemove.GetNext();
  733. while (pblTemp != &blRemove)
  734. {
  735. pConnection = CONTAINING_OBJECT(pblTemp, DPL_CONNECTION, m_blLobbyObjectLinkage);
  736. pblTemp = pblTemp->GetNext();
  737. pConnection->m_blLobbyObjectLinkage.RemoveFromList();
  738. // Process has exited..
  739. DPFX(DPFPREP, 6, "(%p) Process has exited PID %u hProcess", pdpLobbyObject,
  740. pConnection->dwTargetProcessIdentity, HANDLE_FROM_DNHANDLE(pConnection->hTargetProcess ));
  741. DPLConnectionReceiveDisconnect( pdpLobbyObject, pConnection->hConnect, NULL, DPNERR_CONNECTIONLOST );
  742. }
  743. return DPN_OK;
  744. }
  745. #undef DPF_MODNAME
  746. #define DPF_MODNAME "DPLReceiveUserMessage"
  747. HRESULT DPLReceiveUserMessage(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  748. const DPNHANDLE hSender,
  749. BYTE *const pBuffer,
  750. const DWORD dwBufferSize)
  751. {
  752. HRESULT hResultCode;
  753. DPL_MESSAGE_RECEIVE Msg;
  754. Msg.dwSize = sizeof(DPL_MESSAGE_RECEIVE);
  755. Msg.pBuffer = pBuffer;
  756. Msg.dwBufferSize = dwBufferSize;
  757. Msg.hSender = hSender;
  758. hResultCode = DPLConnectionGetContext( pdpLobbyObject, hSender, &Msg.pvConnectionContext );
  759. // Failed to get the connection's context -- strange, but we're going to indicate anyhow.
  760. //
  761. if( FAILED( hResultCode ) )
  762. {
  763. DPFX(DPFPREP, 0, "Failed getting connection context hResultCode = 0x%x", hResultCode );
  764. }
  765. hResultCode = (pdpLobbyObject->pfnMessageHandler)(pdpLobbyObject->pvUserContext,
  766. DPL_MSGID_RECEIVE,
  767. reinterpret_cast<BYTE*>(&Msg));
  768. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  769. return(hResultCode);
  770. }
  771. #undef DPF_MODNAME
  772. #define DPF_MODNAME "DPLMessageHandler"
  773. HRESULT DPLMessageHandler(PVOID pvContext,
  774. const DPNHANDLE hSender,
  775. DWORD dwMessageFlags,
  776. BYTE *const pBuffer,
  777. const DWORD dwBufferSize)
  778. {
  779. DIRECTPLAYLOBBYOBJECT *pdpLobbyObject;
  780. HRESULT hResultCode;
  781. DWORD *pdwMsgId;
  782. DPFX(DPFPREP, 3,"Parameters: hSender [0x%x], pBuffer [0x%p], dwBufferSize [%ld]",
  783. hSender,pBuffer,dwBufferSize);
  784. DNASSERT(pBuffer != NULL);
  785. /*if (dwBufferSize < sizeof(DWORD))
  786. {
  787. DPFERR("Invalid message");
  788. return(DPNERR_GENERIC);
  789. }*/
  790. pdpLobbyObject = static_cast<DIRECTPLAYLOBBYOBJECT*>(pvContext);
  791. pdwMsgId = reinterpret_cast<DWORD*>(pBuffer);
  792. if( dwMessageFlags & DPL_MSGQ_MSGFLAGS_USER1 )
  793. {
  794. DPFX(DPFPREP, 5,"Received INTERNAL message");
  795. switch(*pdwMsgId)
  796. {
  797. case DPL_MSGID_INTERNAL_IDLE_TIMEOUT:
  798. {
  799. DPFX(DPFPREP, 5,"Received: DPL_MSGID_INTERNAL_IDLE_TIMEOUT" );
  800. DPLReceiveIdleTimeout(pdpLobbyObject,hSender);
  801. break;
  802. }
  803. case DPL_MSGID_INTERNAL_DISCONNECT:
  804. {
  805. DPFX(DPFPREP, 5,"Received: DPL_MSGID_INTERNAL_DISCONNECT");
  806. DPLConnectionReceiveDisconnect(pdpLobbyObject,hSender,pBuffer,DPN_OK);
  807. break;
  808. }
  809. case DPL_MSGID_INTERNAL_CONNECT_REQ:
  810. {
  811. DPFX(DPFPREP, 5,"Received: DPL_MSGID_INTERNAL_CONNECT_REQ");
  812. DPLConnectionReceiveREQ(pdpLobbyObject,pBuffer);
  813. break;
  814. }
  815. case DPL_MSGID_INTERNAL_CONNECT_ACK:
  816. {
  817. DPFX(DPFPREP, 5,"Received: DPL_MSGID_INTERNAL_CONNECT_ACK");
  818. DPLConnectionReceiveACK(pdpLobbyObject,hSender,pBuffer);
  819. break;
  820. }
  821. case DPL_MSGID_INTERNAL_UPDATE_STATUS:
  822. {
  823. DPFX(DPFPREP, 5,"Received: DPL_MSGID_INTERNAL_UPDATE_STATUS");
  824. DPLUpdateAppStatus(pdpLobbyObject,hSender,pBuffer);
  825. break;
  826. }
  827. case DPL_MSGID_INTERNAL_CONNECTION_SETTINGS:
  828. {
  829. DPFX(DPFPREP, 5,"Received: DPL_MSGID_INTERNAL_CONNECTION_SETTINGS");
  830. DPLUpdateConnectionSettings(pdpLobbyObject,hSender,pBuffer);
  831. break;
  832. }
  833. default:
  834. {
  835. DPFX(DPFPREP, 5,"Received: Unknown message [0x%lx]",*pdwMsgId);
  836. DNASSERT(FALSE);
  837. break;
  838. }
  839. }
  840. }
  841. else if( dwMessageFlags & DPL_MSGQ_MSGFLAGS_USER2 )
  842. {
  843. DNASSERT( !(dwMessageFlags & DPL_MSGQ_MSGFLAGS_QUEUESYSTEM) );
  844. DPFX(DPFPREP, 5,"Received USER message");
  845. DPLReceiveUserMessage(pdpLobbyObject,hSender,pBuffer,dwBufferSize);
  846. }
  847. hResultCode = DPN_OK;
  848. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  849. return(hResultCode);
  850. }
  851. // DPLSendConnectionSettings
  852. //
  853. // This function is used to send a connection settings update message
  854. #undef DPF_MODNAME
  855. #define DPF_MODNAME "DPLSendConnectionSettings"
  856. HRESULT DPLSendConnectionSettings( DIRECTPLAYLOBBYOBJECT * const pdpLobbyObject,
  857. const DPNHANDLE hConnection )
  858. {
  859. BYTE *pbTransmitBuffer = NULL;
  860. DWORD dwTransmitBufferSize = 0;
  861. DPL_INTERNAL_CONNECTION_SETTINGS_UPDATE *pdplMsgSettings = NULL;
  862. DPL_CONNECTION *pdplConnection = NULL;
  863. CPackedBuffer PackBuffer;
  864. HRESULT hResultCode = DPN_OK;
  865. hResultCode = DPLConnectionFind(pdpLobbyObject, hConnection, &pdplConnection, TRUE );
  866. if( FAILED( hResultCode ) )
  867. {
  868. DPFERR( "Unable to find specified connection" );
  869. return hResultCode;
  870. }
  871. // Grab lock to prevent other people from interfering
  872. DNEnterCriticalSection( &pdplConnection->csLock );
  873. PackBuffer.Initialize( NULL, 0 );
  874. PackBuffer.AddToFront( NULL, sizeof( DPL_INTERNAL_CONNECTION_SETTINGS_UPDATE_HEADER ) );
  875. if( pdplConnection->pConnectionSettings )
  876. {
  877. pdplConnection->pConnectionSettings->BuildWireStruct( &PackBuffer );
  878. }
  879. dwTransmitBufferSize = PackBuffer.GetSizeRequired();
  880. pbTransmitBuffer = new BYTE[ dwTransmitBufferSize ];
  881. if( !pbTransmitBuffer )
  882. {
  883. DPFX( DPFPREP, 0, "Error allocating memory" );
  884. hResultCode = DPNERR_OUTOFMEMORY;
  885. goto DPLSENDCONNECTSETTINGS_DONE;
  886. }
  887. pdplMsgSettings = (DPL_INTERNAL_CONNECTION_SETTINGS_UPDATE *) pbTransmitBuffer;
  888. PackBuffer.Initialize( pbTransmitBuffer, dwTransmitBufferSize );
  889. DNASSERT( pdplMsgSettings );
  890. hResultCode = PackBuffer.AddToFront( NULL, sizeof( DPL_INTERNAL_CONNECTION_SETTINGS_UPDATE_HEADER ) );
  891. if( FAILED( hResultCode ) )
  892. {
  893. DPFX( DPFPREP, 0, "Error adding main struct hr [0x%x]", hResultCode );
  894. goto DPLSENDCONNECTSETTINGS_DONE;
  895. }
  896. if( pdplConnection->pConnectionSettings )
  897. {
  898. hResultCode = pdplConnection->pConnectionSettings->BuildWireStruct( &PackBuffer );
  899. if( FAILED( hResultCode ) )
  900. {
  901. DPFX( DPFPREP, 0, "Error adding connect struct hr [0x%x]", hResultCode );
  902. goto DPLSENDCONNECTSETTINGS_DONE;
  903. }
  904. pdplMsgSettings->dwConnectionSettingsSize = 1;
  905. }
  906. else
  907. {
  908. pdplMsgSettings->dwConnectionSettingsSize = 0;
  909. }
  910. pdplMsgSettings->dwMsgId = DPL_MSGID_INTERNAL_CONNECTION_SETTINGS;
  911. if (!pdplConnection->pSendQueue->IsReceiving())
  912. {
  913. DPFERR("Other side is not receiving");
  914. goto DPLSENDCONNECTSETTINGS_DONE;
  915. }
  916. hResultCode = pdplConnection->pSendQueue->Send(reinterpret_cast<BYTE*>(pdplMsgSettings),
  917. PackBuffer.GetSizeRequired(),
  918. INFINITE,
  919. DPL_MSGQ_MSGFLAGS_USER1,
  920. 0);
  921. if ( FAILED( hResultCode ) )
  922. {
  923. DPFX(DPFPREP, 0, "Could not send connect settings hr [0x%x]", hResultCode );
  924. goto DPLSENDCONNECTSETTINGS_DONE;
  925. }
  926. hResultCode = DPN_OK;
  927. DPLSENDCONNECTSETTINGS_DONE:
  928. if( pbTransmitBuffer )
  929. delete [] pbTransmitBuffer;
  930. DNLeaveCriticalSection( &pdplConnection->csLock );
  931. DPLConnectionRelease(pdpLobbyObject,hConnection);
  932. return hResultCode;
  933. }
  934. // DPLUpdateConnectionSettings
  935. //
  936. // This function is called when a connection settings update message has been received.
  937. //
  938. #undef DPF_MODNAME
  939. #define DPF_MODNAME "DPLUpdateConnectionSettings"
  940. HRESULT DPLUpdateConnectionSettings(DIRECTPLAYLOBBYOBJECT *const pdpLobbyObject,
  941. const DPNHANDLE hSender,
  942. BYTE *const pBuffer )
  943. {
  944. HRESULT hr;
  945. DPL_MESSAGE_CONNECTION_SETTINGS MsgConnectionSettings;
  946. DWORD dwSettingsBufferSize = 0;
  947. BOOL fAddressReferences = FALSE;
  948. CConnectionSettings *pConnectionSettings = NULL;
  949. DPL_INTERNAL_CONNECTION_SETTINGS_UPDATE *pConnectionSettingsMsg = NULL;
  950. DPFX(DPFPREP, 3,"Parameters: pBuffer [0x%p]",pBuffer);
  951. DNASSERT(pdpLobbyObject != NULL);
  952. DNASSERT(pBuffer != NULL);
  953. pConnectionSettingsMsg = (DPL_INTERNAL_CONNECTION_SETTINGS_UPDATE *) pBuffer;
  954. if( pConnectionSettingsMsg->dwConnectionSettingsSize )
  955. {
  956. pConnectionSettings = new CConnectionSettings();
  957. if( !pConnectionSettings )
  958. {
  959. DPFX( DPFPREP, 0, "Error allocating connection settings" );
  960. hr = DPNERR_OUTOFMEMORY;
  961. goto UPDATESETTINGS_FAILURE;
  962. }
  963. hr = pConnectionSettings->Initialize( &pConnectionSettingsMsg->dplConnectionSettings, (UNALIGNED BYTE *) pConnectionSettingsMsg );
  964. if( FAILED( hr ) )
  965. {
  966. DPFX( DPFPREP, 0, "Error building structure from wire struct hr [0x%x]", hr );
  967. goto UPDATESETTINGS_FAILURE;
  968. }
  969. }
  970. // Set the connection settings on the object
  971. hr = DPLConnectionSetConnectSettings( pdpLobbyObject, hSender, pConnectionSettings );
  972. if( FAILED( hr ) )
  973. {
  974. DPFX(DPFPREP, 0, "Error setting connection settings hr = 0x%x", hr );
  975. goto UPDATESETTINGS_FAILURE;
  976. }
  977. // Setup message to indicate to user
  978. MsgConnectionSettings.dwSize = sizeof(DPL_MESSAGE_CONNECTION_SETTINGS);
  979. MsgConnectionSettings.hSender = hSender;
  980. if( pConnectionSettings )
  981. MsgConnectionSettings.pdplConnectionSettings = pConnectionSettings->GetConnectionSettings();
  982. else
  983. MsgConnectionSettings.pdplConnectionSettings = NULL;
  984. hr = DPLConnectionGetContext( pdpLobbyObject, hSender, &MsgConnectionSettings.pvConnectionContext );
  985. if( FAILED( hr ) )
  986. {
  987. DPFX(DPFPREP, 0, "Error getting connection's context value" );
  988. goto UPDATESETTINGS_FAILURE;
  989. }
  990. hr = (pdpLobbyObject->pfnMessageHandler)(pdpLobbyObject->pvUserContext,
  991. DPL_MSGID_CONNECTION_SETTINGS,
  992. reinterpret_cast<BYTE*>(&MsgConnectionSettings));
  993. if( FAILED( hr ) )
  994. {
  995. DPFX(DPFPREP, 1, "Error returned from user callback -- ignored hr [0x%x]", hr );
  996. }
  997. return DPN_OK;
  998. UPDATESETTINGS_FAILURE:
  999. if( pConnectionSettings )
  1000. delete pConnectionSettings;
  1001. return hr;
  1002. }