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.

2006 lines
52 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: MsgHandler.cpp
  6. * Content: DirectPlay Core/Protocol Interface
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 01/15/00 mjn Created
  12. * 01/27/00 mjn Added support for retention of receive buffers
  13. * 04/08/00 mjn Save SP with connections
  14. * 04/11/00 mjn Use CAsyncOp for ENUMs
  15. * 04/13/00 mjn Use Protocol Interface VTBL
  16. * 04/14/00 mjn DNPICompleteListen sets status and SyncEvent
  17. * 04/17/00 mjn DNPICompleteEnumQuery just sets return value of AsyncOp
  18. * 04/18/00 mjn CConnection tracks connection status better
  19. * 04/21/00 mjn Ensure that RECEIVEs are from a valid connection before passing up notifications
  20. * mjn Disconnect CONNECTing end points on errors
  21. * 04/22/00 mjn Consume notifications when closing or disconnecting.
  22. * 04/26/00 mjn Removed DN_ASYNC_OP and related functions
  23. * 05/23/00 mjn Call DNConnectToPeerFailed if ExistingPlayer connect to NewPlayer fails
  24. * 06/14/00 mjn Allow only one connection to Host in DNPICompleteConnect()
  25. * 06/21/00 mjn Modified DNSendMessage() and DNCreateSendParent() to use protocol voice bit
  26. * 06/22/00 mjn Fixed DNPIIndicateReceive() to properly handle voice messages
  27. * mjn Cleaned up DNPIIndicateConnectionTerminated()
  28. * 06/24/00 mjn Fixed DNPICompleteConnect()
  29. * 07/08/00 mjn Only signal protocol shutdown event if it exists
  30. * 07/11/00 mjn Fixed DNPIAddressInfoXXX() routines to ENUM,LISTEN,CONNECT multiple adapters with address info
  31. * 07/20/00 mjn Modified CONNECT process, cleaned up refcount problems
  32. * 07/24/00 mjn Decline EnumQueries if not host or if host is migrating
  33. * 07/28/00 mjn Added code to validate return value from DPNICompleteSend()
  34. * 07/29/00 mjn Fix calls to DNUserConnectionTerminated()
  35. * 07/30/00 mjn Use DNUserTerminateSession() rather than DNUserConnectionTerminated()
  36. * 07/31/00 mjn Added hrReason to DNTerminateSession()
  37. * mjn Added dwDestroyReason to DNHostDisconnect()
  38. * 08/02/00 mjn Pass received voice messages through DNReceiveUserData()
  39. * 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  40. * 08/05/00 mjn Added m_bilinkActiveList to CAsyncOp
  41. * 08/15/00 mjn Call DNConnectToHostFailed() when connecting player's connection to host drops
  42. * 08/16/00 mjn Modified IndicateConnect() and CompleteConnect() to determine SP directly from AsyncOps
  43. * 08/23/00 mjn Unregister with DPNSVR when LISTENs terminate
  44. * 09/04/00 mjn Added CApplicationDesc
  45. * 09/06/00 mjn Fixed DNPIIndicateConnectionTerminated() to better handle disconnects from partially connected players
  46. * 09/14/00 mjn Release Protocol refcounts in completions
  47. * 09/21/00 mjn Disconnect duplicate connections to Host player in DNPICompleteConnect()
  48. * 09/29/00 mjn AddRef/Release locks in DNPIIndicateReceive()
  49. * 09/30/00 mjn AddRef/Release locks in DNPIIndicateEnumQuery(),DNPIIndicateEnumResponse()
  50. * 10/11/00 mjn Cancel outstanding CONNECTs if one succeeds
  51. * 10/17/00 mjn Fixed clean up for unreachable players
  52. * 02/08/01 mjn Wait for cancels in DNPICompleteXXX()
  53. * mjn Wait for endpoint users in DNPIIndicateConnectionTerminated()
  54. * 03/30/01 mjn Changes to prevent multiple loading/unloading of SP's
  55. * 04/05/01 mjn Set destroy reason to DPNDESTROYPLAYERREASON_CONNECTIONLOST in DNPIIndicateConnectionTerminated()
  56. * 05/23/01 mjn Cancel LISTEN's that have been flagged as cancelled in DNPICompleteListen()
  57. * 06/03/01 mjn Orphan completed CONNECT's and DISCONNECT's
  58. * 06/25/01 mjn Don't unregister with DPNSVR in DNPICompleteListenTerminate()
  59. * 07/24/01 mjn Added DPNBUILD_NOSERVER compile flag
  60. *@@END_MSINTERNAL
  61. *
  62. ***************************************************************************/
  63. #include "dncorei.h"
  64. #undef DPF_MODNAME
  65. #define DPF_MODNAME "DNPIIndicateEnumQuery"
  66. HRESULT DNPIIndicateEnumQuery(void *const pvUserContext,
  67. void *const pvEndPtContext,
  68. const HANDLE hCommand,
  69. void *const pvEnumQueryData,
  70. const DWORD dwEnumQueryDataSize)
  71. {
  72. HRESULT hResultCode;
  73. CAsyncOp *pAsyncOp;
  74. DIRECTNETOBJECT *pdnObject;
  75. CNameTableEntry *pLocalPlayer;
  76. BOOL fReleaseLock;
  77. DPFX(DPFPREP, 6,"Parameters: pvEndPtContext [0x%p], hCommand [0x%p], pvEnumQueryData [0x%p], dwEnumQueryDataSize [%ld]",
  78. pvEndPtContext,hCommand,pvEnumQueryData,dwEnumQueryDataSize);
  79. DNASSERT(pvUserContext != NULL);
  80. DNASSERT(pvEndPtContext != NULL);
  81. pLocalPlayer = NULL;
  82. fReleaseLock = FALSE;
  83. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  84. pAsyncOp = static_cast<CAsyncOp*>(pvEndPtContext);
  85. //
  86. // Prevent close while in this call-back
  87. //
  88. if ((hResultCode = DNAddRefLock(pdnObject)) != DPN_OK)
  89. {
  90. hResultCode = DPN_OK;
  91. goto Failure;
  92. }
  93. fReleaseLock = TRUE;
  94. //
  95. // Don't perform this if host migrating
  96. //
  97. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  98. if (pdnObject->dwFlags & DN_OBJECT_FLAG_HOST_MIGRATING)
  99. {
  100. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  101. hResultCode = DPN_OK;
  102. goto Failure;
  103. }
  104. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  105. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) == DPN_OK)
  106. {
  107. if (pLocalPlayer->IsHost())
  108. {
  109. #pragma TODO(minara,"The protocol should ensure that the LISTEN does not complete until this call-back returns")
  110. #pragma TODO(minara,"As the context value (AsyncOp) needs to be valid !")
  111. DNProcessEnumQuery( pdnObject, pAsyncOp, reinterpret_cast<const PROTOCOL_ENUM_DATA*>( pvEnumQueryData ) );
  112. }
  113. pLocalPlayer->Release();
  114. pLocalPlayer = NULL;
  115. }
  116. hResultCode = DPN_OK;
  117. Exit:
  118. if (fReleaseLock)
  119. {
  120. DNDecRefLock(pdnObject);
  121. fReleaseLock = FALSE;
  122. }
  123. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  124. return(hResultCode);
  125. Failure:
  126. if (pLocalPlayer)
  127. {
  128. pLocalPlayer->Release();
  129. pLocalPlayer = NULL;
  130. }
  131. goto Exit;
  132. }
  133. #undef DPF_MODNAME
  134. #define DPF_MODNAME "DNPIIndicateEnumResponse"
  135. HRESULT DNPIIndicateEnumResponse(void *const pvUserContext,
  136. const HANDLE hCommand,
  137. void *const pvCommandContext,
  138. void *const pvEnumResponseData,
  139. const DWORD dwEnumResponseDataSize)
  140. {
  141. HRESULT hResultCode;
  142. CAsyncOp *pAsyncOp;
  143. DIRECTNETOBJECT *pdnObject;
  144. BOOL fReleaseLock;
  145. DPFX(DPFPREP, 6,"Parameters: hCommand [0x%p], pvCommandContext [0x%p], pvEnumResponseData [0x%p], dwEnumResponseDataSize [%ld]",
  146. hCommand,pvCommandContext,pvEnumResponseData,dwEnumResponseDataSize);
  147. DNASSERT(pvUserContext != NULL);
  148. DNASSERT(pvCommandContext != NULL);
  149. fReleaseLock = FALSE;
  150. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  151. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  152. //
  153. // Prevent close while in this call-back
  154. //
  155. if ((hResultCode = DNAddRefLock(pdnObject)) != DPN_OK)
  156. {
  157. hResultCode = DPN_OK;
  158. goto Failure;
  159. }
  160. fReleaseLock = TRUE;
  161. #pragma TODO(minara,"The protocol should ensure that the ENUM does not complete until this call-back returns")
  162. #pragma TODO(minara,"As the context value (AsyncOp) needs to be valid !")
  163. DNProcessEnumResponse( pdnObject,
  164. pAsyncOp,
  165. reinterpret_cast<const PROTOCOL_ENUM_RESPONSE_DATA*>( pvEnumResponseData ));
  166. hResultCode = DPN_OK;
  167. Exit:
  168. if (fReleaseLock)
  169. {
  170. DNDecRefLock(pdnObject);
  171. fReleaseLock = FALSE;
  172. }
  173. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  174. return(hResultCode);
  175. Failure:
  176. goto Exit;
  177. }
  178. //
  179. // When a new connection is indicated by the Protocol layer, we will perform some basic validation,
  180. // and then create a CConnection object for it
  181. //
  182. #undef DPF_MODNAME
  183. #define DPF_MODNAME "DNPIIndicateConnect"
  184. HRESULT DNPIIndicateConnect(void *const pvUserContext,
  185. void *const pvListenContext,
  186. const HANDLE hEndPt,
  187. void **const ppvEndPtContext)
  188. {
  189. HRESULT hResultCode;
  190. CConnection *pConnection;
  191. DIRECTNETOBJECT *pdnObject;
  192. #pragma TODO( minara, "Decline connections to non-hosting players and peers who are not expecting them")
  193. DPFX(DPFPREP, 6,"Parameters: pvListenContext [0x%p], hEndPt [0x%p], ppvEndPtContext [0x%p]",
  194. pvListenContext,hEndPt,ppvEndPtContext);
  195. DNASSERT(pvUserContext != NULL);
  196. DNASSERT(pvListenContext != NULL);
  197. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  198. pConnection = NULL;
  199. //
  200. // Allocate and set up a CConnection object and hand a reference to the Protocol
  201. //
  202. if ((hResultCode = ConnectionNew(pdnObject,&pConnection)) != DPN_OK)
  203. {
  204. DPFERR("Could not get new connection");
  205. DisplayDNError(0,hResultCode);
  206. DNASSERT(FALSE);
  207. goto Failure;
  208. }
  209. pConnection->SetStatus( CONNECTING );
  210. pConnection->SetEndPt(hEndPt);
  211. DNASSERT( (static_cast<CAsyncOp*>(pvListenContext))->GetParent() != NULL);
  212. DNASSERT( (static_cast<CAsyncOp*>(pvListenContext))->GetParent()->GetSP() != NULL);
  213. pConnection->SetSP((static_cast<CAsyncOp*>(pvListenContext))->GetParent()->GetSP());
  214. pConnection->AddRef();
  215. *ppvEndPtContext = pConnection;
  216. if (pdnObject->dwFlags & (DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING))
  217. {
  218. DPFERR("CONNECT indicated while closing or disconnecting");
  219. DNPerformDisconnect(pdnObject,pConnection,hEndPt,FALSE);
  220. goto Failure;
  221. }
  222. DNASSERT(pdnObject->NameTable.GetLocalPlayer() != NULL);
  223. if (pdnObject->NameTable.GetLocalPlayer()->IsHost())
  224. {
  225. // This connect was detected by a host player
  226. DPFX(DPFPREP, 7,"Host received connection attempt");
  227. //
  228. // Ensure we're not connecting (still in Host()) or drop the connection
  229. //
  230. if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING)
  231. {
  232. pConnection->Disconnect();
  233. goto Failure;
  234. }
  235. }
  236. else
  237. {
  238. // This connect was detected by a peer player (should be expecting a connection)
  239. DPFX(DPFPREP, 7,"Non-Host player received connection attempt");
  240. }
  241. //
  242. // Add this entry to the bilink of indicated connections. When we receive more info,
  243. // or this connection is terminated, we will remove this entry from the bilink.
  244. // This will enable us to clean up properly.
  245. //
  246. DNEnterCriticalSection(&pdnObject->csConnectionList);
  247. pConnection->AddRef();
  248. pConnection->m_bilinkIndicated.InsertBefore(&pdnObject->m_bilinkIndicated);
  249. DNLeaveCriticalSection(&pdnObject->csConnectionList);
  250. pConnection->Release();
  251. pConnection = NULL;
  252. hResultCode = DPN_OK;
  253. Exit:
  254. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  255. return(hResultCode);
  256. Failure:
  257. if (pConnection)
  258. {
  259. pConnection->Release();
  260. pConnection = NULL;
  261. }
  262. goto Exit;
  263. }
  264. #undef DPF_MODNAME
  265. #define DPF_MODNAME "DNPIIndicateDisconnect"
  266. HRESULT DNPIIndicateDisconnect(void *const pvUserContext,
  267. void *const pvEndPtContext)
  268. {
  269. HRESULT hResultCode;
  270. CConnection *pConnection;
  271. DIRECTNETOBJECT *pdnObject;
  272. CNameTableEntry *pNTEntry;
  273. DPFX(DPFPREP, 6,"Parameters: pvEndPtContext [0x%p]",
  274. pvEndPtContext);
  275. DNASSERT(pvUserContext != NULL);
  276. DNASSERT(pvEndPtContext != NULL);
  277. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  278. pConnection = static_cast<CConnection*>(pvEndPtContext);
  279. //
  280. // Mark the connection as DISCONNECTing so that we don't use it any more
  281. //
  282. pConnection->Lock();
  283. pConnection->SetStatus( DISCONNECTING );
  284. pConnection->Unlock();
  285. if (pConnection->GetDPNID() == 0)
  286. {
  287. if (pdnObject->NameTable.GetLocalPlayer() && pdnObject->NameTable.GetLocalPlayer()->IsHost())
  288. {
  289. DPFX(DPFPREP, 7,"Joining player has issued a disconnect to Host (local) player");
  290. }
  291. else
  292. {
  293. DPFX(DPFPREP, 7,"Host has issued a disconnect to Joining (local) player");
  294. }
  295. }
  296. else
  297. {
  298. DNASSERT(!(pdnObject->dwFlags & DN_OBJECT_FLAG_CLIENT));
  299. if (pdnObject->NameTable.GetLocalPlayer() && pdnObject->NameTable.GetLocalPlayer()->IsHost())
  300. {
  301. DPFX(DPFPREP, 7,"Connected player has issued a disconnect to Host (local) player");
  302. }
  303. else
  304. {
  305. DPFX(DPFPREP, 7,"Connected player has issued a disconnect to local player");
  306. }
  307. //
  308. // Mark this player for normal destruction since they disconnected and are playing nice
  309. //
  310. if ((hResultCode = pdnObject->NameTable.FindEntry(pConnection->GetDPNID(),&pNTEntry)) == DPN_OK)
  311. {
  312. pNTEntry->Lock();
  313. if (pNTEntry->GetDestroyReason() == 0)
  314. {
  315. pNTEntry->SetDestroyReason( DPNDESTROYPLAYERREASON_NORMAL );
  316. }
  317. pNTEntry->Unlock();
  318. pNTEntry->Release();
  319. pNTEntry = NULL;
  320. }
  321. }
  322. hResultCode = DPN_OK;
  323. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  324. return(hResultCode);
  325. }
  326. #undef DPF_MODNAME
  327. #define DPF_MODNAME "DNPIIndicateConnectionTerminated"
  328. HRESULT DNPIIndicateConnectionTerminated(void *const pvUserContext,
  329. void *const pvEndPtContext,
  330. const HRESULT hr)
  331. {
  332. HRESULT hResultCode;
  333. CConnection *pConnection;
  334. DIRECTNETOBJECT *pdnObject;
  335. BOOL fWasConnecting;
  336. CBilink *pBilink;
  337. DWORD dwCount;
  338. CSyncEvent *pSyncEvent;
  339. DPFX(DPFPREP, 6,"Parameters: pvEndPtContext [0x%p], hr [0x%lx]",pvEndPtContext,hr);
  340. DNASSERT(pvUserContext != NULL);
  341. DNASSERT(pvEndPtContext != NULL);
  342. pSyncEvent = NULL;
  343. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  344. pConnection = static_cast<CConnection*>(pvEndPtContext);
  345. //
  346. // pConnection should still have at least 1 reference on it at this stage since
  347. // INDICATE_CONNECTION_TERMINATED is supposed to be the final release for it.
  348. // All outstanding SENDs and RECEIVEs should have already been processed.
  349. //
  350. // If there are any users of the endpoint, then we will need to wait for them
  351. // to be done with it. To do this, we will count the number of threads using
  352. // the endpoint (not including any occurances of THIS thread), and set the count
  353. // and an event on the Connection
  354. //
  355. fWasConnecting = FALSE;
  356. pConnection->Lock();
  357. if (pConnection->IsConnecting())
  358. {
  359. fWasConnecting = TRUE;
  360. }
  361. pConnection->SetStatus( INVALID );
  362. dwCount = 0;
  363. pBilink = pConnection->m_bilinkCallbackThreads.GetNext();
  364. while (pBilink != &pConnection->m_bilinkCallbackThreads)
  365. {
  366. if (!(CONTAINING_CALLBACKTHREAD(pBilink))->IsCurrentThread())
  367. {
  368. dwCount++;
  369. }
  370. pBilink = pBilink->GetNext();
  371. }
  372. if (dwCount != 0)
  373. {
  374. if ((hResultCode = SyncEventNew(pdnObject,&pSyncEvent)) != DPN_OK)
  375. {
  376. DPFERR("Could not get sync event - ignore and continue (we will not wait!)");
  377. dwCount = 0;
  378. }
  379. else
  380. {
  381. pConnection->SetThreadCount( dwCount );
  382. pConnection->SetThreadEvent( pSyncEvent );
  383. }
  384. }
  385. pConnection->Unlock();
  386. if (dwCount)
  387. {
  388. DNASSERT(pSyncEvent != NULL);
  389. pSyncEvent->WaitForEvent();
  390. pConnection->Lock();
  391. pConnection->SetThreadEvent( NULL );
  392. pConnection->Unlock();
  393. pSyncEvent->ReturnSelfToPool();
  394. pSyncEvent = NULL;
  395. }
  396. //
  397. // Remove this connection from the indicated connection list
  398. //
  399. DNEnterCriticalSection(&pdnObject->csConnectionList);
  400. if (!pConnection->m_bilinkIndicated.IsEmpty())
  401. {
  402. pConnection->Release();
  403. }
  404. pConnection->m_bilinkIndicated.RemoveFromList();
  405. DNLeaveCriticalSection(&pdnObject->csConnectionList);
  406. //
  407. // If we are a client (in client server), and the server has disconnected from us, we have to shut down
  408. //
  409. if (pdnObject->dwFlags & DN_OBJECT_FLAG_CLIENT)
  410. {
  411. if (fWasConnecting)
  412. {
  413. DPFX(DPFPREP, 7,"Server disconnected from local connecting client - failing connect");
  414. }
  415. else
  416. {
  417. DPFX(DPFPREP, 7,"Server disconnected from local client - shutting down");
  418. //
  419. // Only inform the user if they are IN the session
  420. //
  421. if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTED)
  422. {
  423. DNUserTerminateSession(pdnObject,DPNERR_CONNECTIONLOST,NULL,0);
  424. }
  425. DNTerminateSession(pdnObject,DPNERR_CONNECTIONLOST);
  426. }
  427. }
  428. #ifndef DPNBUILD_NOSERVER
  429. else if (pdnObject->dwFlags & DN_OBJECT_FLAG_SERVER)
  430. {
  431. if (fWasConnecting || (pConnection->GetDPNID() == 0))
  432. {
  433. DPFX(DPFPREP, 7,"Unconnected client has disconnected from server");
  434. }
  435. else
  436. {
  437. CNameTableEntry *pNTEntry;
  438. DWORD dwReason;
  439. pNTEntry = NULL;
  440. //
  441. // If the destruction code has not been set, mark as CONNECTIONLOST
  442. //
  443. if ((hResultCode = pdnObject->NameTable.FindEntry(pConnection->GetDPNID(),&pNTEntry)) == DPN_OK)
  444. {
  445. pNTEntry->Lock();
  446. if (pNTEntry->GetDestroyReason() == 0)
  447. {
  448. pNTEntry->SetDestroyReason( DPNDESTROYPLAYERREASON_CONNECTIONLOST );
  449. }
  450. dwReason = pNTEntry->GetDestroyReason();
  451. pNTEntry->Unlock();
  452. pNTEntry->Release();
  453. pNTEntry = NULL;
  454. }
  455. else
  456. {
  457. dwReason = DPNDESTROYPLAYERREASON_CONNECTIONLOST;
  458. }
  459. DNHostDisconnect(pdnObject,pConnection->GetDPNID(),dwReason);
  460. }
  461. }
  462. #endif // DPNBUILD_NOSERVER
  463. else // DN_OBJECT_FLAG_PEER
  464. {
  465. DNASSERT( pdnObject->dwFlags & DN_OBJECT_FLAG_PEER );
  466. if (fWasConnecting || (pConnection->GetDPNID() == 0))
  467. {
  468. DPFX(DPFPREP, 7,"Unconnected peer has disconnected from local peer");
  469. CAsyncOp *pConnectParent;
  470. pConnectParent = NULL;
  471. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  472. if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING)
  473. {
  474. pdnObject->dwFlags &= (~(DN_OBJECT_FLAG_CONNECTED
  475. | DN_OBJECT_FLAG_CONNECTING
  476. | DN_OBJECT_FLAG_HOST_CONNECTED));
  477. if (pdnObject->pConnectParent)
  478. {
  479. pConnectParent = pdnObject->pConnectParent;
  480. pdnObject->pConnectParent = NULL;
  481. }
  482. if( pdnObject->pIDP8ADevice )
  483. {
  484. IDirectPlay8Address_Release( pdnObject->pIDP8ADevice );
  485. pdnObject->pIDP8ADevice = NULL;
  486. }
  487. if( pdnObject->pConnectAddress )
  488. {
  489. IDirectPlay8Address_Release( pdnObject->pConnectAddress );
  490. pdnObject->pConnectAddress = NULL;
  491. }
  492. }
  493. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  494. if (pConnectParent)
  495. {
  496. pConnectParent->Release();
  497. pConnectParent = NULL;
  498. }
  499. DNASSERT(pConnectParent == NULL);
  500. }
  501. else
  502. {
  503. CNameTableEntry *pNTEntry;
  504. CNameTableEntry *pLocalPlayer;
  505. DWORD dwReason;
  506. pNTEntry = NULL;
  507. pLocalPlayer = NULL;
  508. //
  509. // If the destruction code has not been set, mark as CONNECTIONLOST
  510. //
  511. if ((hResultCode = pdnObject->NameTable.FindEntry(pConnection->GetDPNID(),&pNTEntry)) == DPN_OK)
  512. {
  513. pNTEntry->Lock();
  514. if (pNTEntry->GetDestroyReason() == 0)
  515. {
  516. pNTEntry->SetDestroyReason( DPNDESTROYPLAYERREASON_CONNECTIONLOST );
  517. }
  518. dwReason = pNTEntry->GetDestroyReason();
  519. pNTEntry->Unlock();
  520. pNTEntry->Release();
  521. pNTEntry = NULL;
  522. }
  523. else
  524. {
  525. dwReason = DPNDESTROYPLAYERREASON_CONNECTIONLOST;
  526. }
  527. //
  528. // Based on who we are, and who's disconnecting, we will have different behaviour
  529. //
  530. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef(&pLocalPlayer)) == DPN_OK)
  531. {
  532. if (pLocalPlayer->IsHost())
  533. {
  534. DPFX(DPFPREP, 7,"Connected peer has disconnected from Host");
  535. DNHostDisconnect(pdnObject,pConnection->GetDPNID(),dwReason);
  536. }
  537. else
  538. {
  539. DPFX(DPFPREP, 7,"Peer has disconnected from non-Host peer");
  540. DNPlayerDisconnectNew(pdnObject,pConnection->GetDPNID());
  541. }
  542. pLocalPlayer->Release();
  543. pLocalPlayer = NULL;
  544. }
  545. }
  546. }
  547. pConnection->Release();
  548. pConnection = NULL;
  549. hResultCode = DPN_OK;
  550. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  551. return(hResultCode);
  552. }
  553. #undef DPF_MODNAME
  554. #define DPF_MODNAME "DNPIIndicateReceive"
  555. HRESULT DNPIIndicateReceive(void *const pvUserContext,
  556. void *const pvEndPtContext,
  557. void *const pvData,
  558. const DWORD dwDataSize,
  559. const HANDLE hBuffer,
  560. const DWORD dwFlags)
  561. {
  562. HRESULT hResultCode;
  563. DIRECTNETOBJECT *pdnObject;
  564. void *pvInternalData;
  565. DWORD dwInternalDataSize;
  566. CConnection *pConnection;
  567. DWORD *pdwMsgId;
  568. BOOL fReleaseLock;
  569. DPFX(DPFPREP, 6,"Parameters: pvEndPtContext [0x%p], pvData [0x%p], dwDataSize [%ld], hBuffer [0x%p], dwFlags [0x%lx]",
  570. pvEndPtContext,pvData,dwDataSize,hBuffer,dwFlags);
  571. DNASSERT(pvUserContext != NULL);
  572. DNASSERT(pvEndPtContext != NULL);
  573. DNASSERT(pvData != NULL);
  574. DNASSERT(((DWORD_PTR) pvData & 3) == 0); // data should be DWORD aligned
  575. DNASSERT(dwDataSize != 0);
  576. DNASSERT(hBuffer != NULL);
  577. fReleaseLock = FALSE;
  578. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  579. pConnection = static_cast<CConnection*>(pvEndPtContext);
  580. //
  581. // Prevent close while in this call-back
  582. //
  583. if ((hResultCode = DNAddRefLock(pdnObject)) != DPN_OK)
  584. {
  585. hResultCode = DPN_OK;
  586. goto Failure;
  587. }
  588. fReleaseLock = TRUE;
  589. //
  590. // Ensure that this is a valid connection
  591. //
  592. if (!pConnection->IsConnected() && !pConnection->IsConnecting())
  593. {
  594. hResultCode = DPN_OK;
  595. goto Failure;
  596. }
  597. pConnection->AddRef();
  598. if ((dwFlags & DN_SENDFLAGS_SET_USER_FLAG) && !(dwFlags & DN_SENDFLAGS_SET_USER_FLAG_TWO))
  599. {
  600. //
  601. // Internal message
  602. //
  603. DPFX(DPFPREP, 7,"Received INTERNAL message");
  604. DNASSERT(dwDataSize >= sizeof(DWORD));
  605. pdwMsgId = static_cast<DWORD*>(pvData);
  606. dwInternalDataSize = dwDataSize - sizeof(DWORD);
  607. if (dwInternalDataSize > 0)
  608. {
  609. pvInternalData = static_cast<void*>(static_cast<BYTE*>(pvData) + sizeof(DWORD));
  610. }
  611. else
  612. {
  613. pvInternalData = NULL;
  614. }
  615. hResultCode = DNProcessInternalOperation( pdnObject,
  616. *pdwMsgId,
  617. pvInternalData,
  618. dwInternalDataSize,
  619. pConnection,
  620. hBuffer,
  621. NULL );
  622. }
  623. else
  624. {
  625. //
  626. // User or voice message
  627. //
  628. DPFX(DPFPREP, 7,"Received USER or Voice message");
  629. hResultCode = DNReceiveUserData(pdnObject,
  630. pConnection,
  631. static_cast<BYTE*>(pvData),
  632. dwDataSize,
  633. hBuffer,
  634. NULL,
  635. 0,
  636. dwFlags);
  637. }
  638. //
  639. // Only allow DPNERR_PENDING or DPN_OK
  640. //
  641. if (hResultCode != DPNERR_PENDING)
  642. {
  643. hResultCode = DPN_OK;
  644. }
  645. pConnection->Release();
  646. pConnection = NULL;
  647. Exit:
  648. if (fReleaseLock)
  649. {
  650. DNDecRefLock(pdnObject);
  651. fReleaseLock = FALSE;
  652. }
  653. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  654. return(hResultCode);
  655. Failure:
  656. goto Exit;
  657. }
  658. #undef DPF_MODNAME
  659. #define DPF_MODNAME "DNPICompleteListen"
  660. HRESULT DNPICompleteListen(void *const pvUserContext,
  661. void **const ppvCommandContext,
  662. const HRESULT hr,
  663. const HANDLE hCommand)
  664. {
  665. HRESULT hResultCode;
  666. CAsyncOp *pAsyncOp;
  667. CAsyncOp *pParent;
  668. DIRECTNETOBJECT *pdnObject;
  669. DPFX(DPFPREP, 6,"Parameters: ppvCommandContext [0x%p], hr [0x%lx], hCommand [0x%p]",
  670. ppvCommandContext,hr,hCommand);
  671. DNASSERT(pvUserContext != NULL);
  672. DNASSERT(ppvCommandContext != NULL);
  673. DNASSERT(*ppvCommandContext != NULL);
  674. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  675. pAsyncOp = static_cast<CAsyncOp*>(*ppvCommandContext);
  676. pParent = NULL;
  677. //
  678. // AddRef pAsyncOp to keep it around in case a CompleteListenTerminated is posted
  679. //
  680. pAsyncOp->AddRef();
  681. pAsyncOp->Lock();
  682. if (pAsyncOp->GetParent())
  683. {
  684. pAsyncOp->GetParent()->AddRef();
  685. pParent = pAsyncOp->GetParent();
  686. }
  687. pAsyncOp->Unlock();
  688. //
  689. // If the LISTEN was cancelled and has been started successfully, we will need to shut it down.
  690. // Otherwise, we will keep the result of the LISTEN attempt
  691. //
  692. DNASSERT(pAsyncOp->GetResultPointer() != NULL);
  693. if (hr == DPN_OK)
  694. {
  695. if (pAsyncOp->IsCancelled())
  696. {
  697. HRESULT hrCancel;
  698. if ((hrCancel = DNPCancelCommand(pdnObject->pdnProtocolData,hCommand)) == DPN_OK)
  699. {
  700. *(pAsyncOp->GetResultPointer()) = DPNERR_USERCANCEL;
  701. }
  702. else
  703. {
  704. *(pAsyncOp->GetResultPointer()) = DPNERR_GENERIC;
  705. }
  706. }
  707. else
  708. {
  709. //
  710. // We probably don't have to lock pAsyncOp to clear the CANNOT_CANCEL, but better safe than sorry
  711. //
  712. pAsyncOp->Lock();
  713. pAsyncOp->ClearCannotCancel();
  714. pAsyncOp->SetResult( hr );
  715. pAsyncOp->Unlock();
  716. *(pAsyncOp->GetResultPointer()) = hr;
  717. }
  718. }
  719. else
  720. {
  721. *(pAsyncOp->GetResultPointer()) = hr;
  722. }
  723. //
  724. // Set SyncEvent
  725. //
  726. DNASSERT(pAsyncOp->GetSyncEvent() != NULL);
  727. pAsyncOp->GetSyncEvent()->Set();
  728. //
  729. // If there was an SP parent, we will check to see if this is the last completion and then set the
  730. // parent's SP listen event (if it exists)
  731. //
  732. if (pParent)
  733. {
  734. #ifndef DPNBUILD_ONLYONEADAPTER
  735. DN_LISTEN_OP_DATA *pListenOpData;
  736. pListenOpData = pParent->GetLocalListenOpData();
  737. if (pListenOpData->dwCompleteAdapters < pListenOpData->dwNumAdapters)
  738. {
  739. pListenOpData->dwCompleteAdapters++;
  740. if (pListenOpData->dwCompleteAdapters == pListenOpData->dwNumAdapters)
  741. {
  742. if (pListenOpData->pSyncEvent)
  743. {
  744. pListenOpData->pSyncEvent->Set();
  745. pListenOpData->pSyncEvent = NULL;
  746. }
  747. }
  748. }
  749. #endif // ! DPNBUILD_ONLYONEADAPTER
  750. pParent->Release();
  751. pParent = NULL;
  752. }
  753. //
  754. // Done with pAsyncOp - release reference taken earlier
  755. //
  756. pAsyncOp->Release();
  757. hResultCode = DPN_OK;
  758. DNASSERT( pParent == NULL);
  759. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  760. return(hResultCode);
  761. }
  762. #undef DPF_MODNAME
  763. #define DPF_MODNAME "DNPICompleteListenTerminate"
  764. HRESULT DNPICompleteListenTerminate(void *const pvUserContext,
  765. void *const pvCommandContext,
  766. const HRESULT hr)
  767. {
  768. HRESULT hResultCode;
  769. CAsyncOp *pAsyncOp;
  770. DIRECTNETOBJECT *pdnObject;
  771. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hr [0x%lx]",
  772. pvCommandContext,hr);
  773. DNASSERT(pvUserContext != NULL);
  774. DNASSERT(pvCommandContext != NULL);
  775. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  776. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  777. //
  778. // Indicate complete and remove from active list
  779. //
  780. pAsyncOp->Lock();
  781. DNASSERT(!pAsyncOp->IsComplete());
  782. pAsyncOp->SetComplete();
  783. pAsyncOp->Unlock();
  784. DNEnterCriticalSection(&pdnObject->csActiveList);
  785. pAsyncOp->m_bilinkActiveList.RemoveFromList();
  786. DNLeaveCriticalSection(&pdnObject->csActiveList);
  787. DNASSERT(pAsyncOp->IsChild());
  788. pAsyncOp->Orphan();
  789. //
  790. // Ensure there are no cancels outstanding
  791. //
  792. DNWaitForCancel(pAsyncOp);
  793. pAsyncOp->Release();
  794. pAsyncOp = NULL;
  795. hResultCode = DPN_OK;
  796. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  797. return(hResultCode);
  798. }
  799. #undef DPF_MODNAME
  800. #define DPF_MODNAME "DNPICompleteEnumQuery"
  801. HRESULT DNPICompleteEnumQuery(void *const pvUserContext,
  802. void *const pvCommandContext,
  803. const HRESULT hr)
  804. {
  805. HRESULT hResultCode;
  806. CAsyncOp *pAsyncOp;
  807. DIRECTNETOBJECT *pdnObject;
  808. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hr [0x%lx]",
  809. pvCommandContext,hr);
  810. DNASSERT(pvUserContext != NULL);
  811. DNASSERT(pvCommandContext != NULL);
  812. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  813. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  814. DNASSERT( pAsyncOp->GetOpType() == ASYNC_OP_ENUM_QUERY );
  815. //
  816. // Indicate complete and remove from active list
  817. //
  818. pAsyncOp->Lock();
  819. DNASSERT(!pAsyncOp->IsComplete());
  820. pAsyncOp->SetComplete();
  821. pAsyncOp->Unlock();
  822. DNEnterCriticalSection(&pdnObject->csActiveList);
  823. pAsyncOp->m_bilinkActiveList.RemoveFromList();
  824. DNLeaveCriticalSection(&pdnObject->csActiveList);
  825. pAsyncOp->SetResult( hr );
  826. pAsyncOp->Orphan();
  827. //
  828. // Ensure there are no cancels outstanding
  829. //
  830. DNWaitForCancel(pAsyncOp);
  831. pAsyncOp->Release();
  832. pAsyncOp = NULL;
  833. //
  834. // Release Protocol reference
  835. //
  836. DNProtocolRelease(pdnObject);
  837. hResultCode = DPN_OK;
  838. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  839. return(hResultCode);
  840. }
  841. #undef DPF_MODNAME
  842. #define DPF_MODNAME "DNPICompleteEnumResponse"
  843. HRESULT DNPICompleteEnumResponse(void *const pvUserContext,
  844. void *const pvCommandContext,
  845. const HRESULT hr)
  846. {
  847. HRESULT hResultCode;
  848. CAsyncOp *pAsyncOp;
  849. DIRECTNETOBJECT *pdnObject;
  850. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hr [0x%lx]",
  851. pvCommandContext,hr);
  852. DNASSERT(pvUserContext != NULL);
  853. DNASSERT(pvCommandContext != NULL);
  854. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  855. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  856. DNASSERT( pAsyncOp->GetOpType() == ASYNC_OP_ENUM_RESPONSE );
  857. pAsyncOp->Lock();
  858. DNASSERT(!pAsyncOp->IsComplete());
  859. pAsyncOp->SetComplete();
  860. pAsyncOp->Unlock();
  861. if (pAsyncOp->IsChild())
  862. {
  863. DNASSERT(FALSE);
  864. pAsyncOp->Orphan();
  865. }
  866. if (SUCCEEDED(pdnObject->HandleTable.Destroy( pAsyncOp->GetHandle(), NULL )))
  867. {
  868. // Release the HandleTable reference
  869. pAsyncOp->Release();
  870. }
  871. pAsyncOp->SetResult( hr );
  872. //
  873. // Ensure there are no cancels outstanding
  874. //
  875. DNWaitForCancel(pAsyncOp);
  876. pAsyncOp->Release();
  877. pAsyncOp = NULL;
  878. //
  879. // Release protocol reference
  880. //
  881. DNProtocolRelease(pdnObject);
  882. hResultCode = DPN_OK;
  883. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  884. return(hResultCode);
  885. }
  886. #undef DPF_MODNAME
  887. #define DPF_MODNAME "DNPICompleteConnect"
  888. HRESULT DNPICompleteConnect(void *const pvUserContext,
  889. void *const pvCommandContext,
  890. const HRESULT hrProt,
  891. const HANDLE hEndPt,
  892. void **const ppvEndPtContext)
  893. {
  894. HRESULT hResultCode;
  895. HRESULT hr;
  896. CAsyncOp *pAsyncOp;
  897. CConnection *pConnection;
  898. DIRECTNETOBJECT *pdnObject;
  899. IDirectPlay8Address *pIDevice;
  900. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hrProt [0x%lx], hEndPt [0x%p], ppvEndPtContext [0x%p]",
  901. pvCommandContext,hrProt,hEndPt,ppvEndPtContext);
  902. DNASSERT(pvUserContext != NULL);
  903. DNASSERT(pvCommandContext != NULL);
  904. DNASSERT( (hrProt != DPN_OK) || (ppvEndPtContext != NULL) );
  905. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  906. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  907. DNASSERT( pAsyncOp->GetOpType() == ASYNC_OP_CONNECT );
  908. pConnection = NULL;
  909. pIDevice = NULL;
  910. //
  911. // Re-map DPNERR_ABORTED (!)
  912. //
  913. if (hrProt == DPNERR_ABORTED)
  914. {
  915. hr = DPNERR_USERCANCEL;
  916. }
  917. else
  918. {
  919. hr = hrProt;
  920. }
  921. //
  922. // Indicate complete and remove from active list
  923. //
  924. pAsyncOp->Lock();
  925. DNASSERT(!pAsyncOp->IsComplete());
  926. pAsyncOp->SetComplete();
  927. pAsyncOp->Unlock();
  928. DNEnterCriticalSection(&pdnObject->csActiveList);
  929. pAsyncOp->m_bilinkActiveList.RemoveFromList();
  930. DNLeaveCriticalSection(&pdnObject->csActiveList);
  931. if (pAsyncOp->IsChild())
  932. {
  933. pAsyncOp->Orphan();
  934. }
  935. //
  936. // If there is a DPNID associated with this operation, then we are an ExistingPlayer
  937. // connecting with a NewPlayer. If there is no DPNID, then we are a NewPlayer connecting
  938. // to the Host.
  939. //
  940. if (pAsyncOp->GetDPNID())
  941. {
  942. DPFX(DPFPREP, 7,"CONNECT completed for existing player connecting to NewPlayer");
  943. //
  944. // We are an existing player attempting to CONNECT to a NewPlayer.
  945. // If this CONNECT failed, we must inform the Host
  946. //
  947. if (hr != DPN_OK)
  948. {
  949. DPFERR("Could not CONNECT to NewPlayer");
  950. DisplayDNError(0,hr);
  951. DNConnectToPeerFailed(pdnObject,pAsyncOp->GetDPNID());
  952. hResultCode = DPN_OK;
  953. goto Failure;
  954. }
  955. //
  956. // Allocate and set up a CConnection object and hand a reference to the Protocol
  957. //
  958. DNASSERT(pAsyncOp->GetSP() != NULL);
  959. if ((hResultCode = ConnectionNew(pdnObject,&pConnection)) != DPN_OK)
  960. {
  961. DPFERR("Could not get new connection");
  962. DisplayDNError(0,hResultCode);
  963. DNASSERT(FALSE);
  964. goto Failure;
  965. }
  966. pConnection->SetStatus( CONNECTING );
  967. pConnection->SetEndPt(hEndPt);
  968. pConnection->SetSP(pAsyncOp->GetSP());
  969. pConnection->AddRef();
  970. *ppvEndPtContext = pConnection;
  971. //
  972. // Send this player's DNID to the connecting player to enable name table entry
  973. //
  974. if ((hResultCode = DNConnectToPeer3(pdnObject,pAsyncOp->GetDPNID(),pConnection)) != DPN_OK)
  975. {
  976. DPFERR("Could not connect to NewPlayer");
  977. DisplayDNError(0,hr);
  978. DNPerformDisconnect(pdnObject,pConnection,hEndPt,FALSE);
  979. DNConnectToPeerFailed(pdnObject,pAsyncOp->GetDPNID());
  980. goto Failure;
  981. }
  982. }
  983. else
  984. {
  985. DPFX(DPFPREP, 7,"CONNECT completed for NewPlayer connecting to Host");
  986. //
  987. // We are the NewPlayer attempting to CONNECT to the Host.
  988. //
  989. //
  990. // If this CONNECT succeeded, we will cancell any other CONNECTs.
  991. // If this CONNECT failed, we will set the result code on the AsyncOp
  992. // and release it.
  993. //
  994. if (hr == DPN_OK)
  995. {
  996. CAsyncOp *pParent;
  997. pParent = NULL;
  998. pAsyncOp->Lock();
  999. if (pAsyncOp->GetParent())
  1000. {
  1001. pAsyncOp->GetParent()->AddRef();
  1002. pParent = pAsyncOp->GetParent();
  1003. }
  1004. pAsyncOp->Unlock();
  1005. if (pParent)
  1006. {
  1007. DNCancelChildren(pdnObject,pParent);
  1008. pParent->Release();
  1009. pParent = NULL;
  1010. }
  1011. DNASSERT(pParent == NULL);
  1012. }
  1013. else
  1014. {
  1015. DPFERR("Could not CONNECT to Host");
  1016. DisplayDNError(0,hr);
  1017. pAsyncOp->SetResult( hr );
  1018. hResultCode = DPN_OK;
  1019. goto Failure;
  1020. }
  1021. //
  1022. // Allocate and set up a CConnection object and hand a reference to the Protocol
  1023. //
  1024. DNASSERT(pAsyncOp->GetSP() != NULL);
  1025. if ((hResultCode = ConnectionNew(pdnObject,&pConnection)) != DPN_OK)
  1026. {
  1027. DPFERR("Could not get new connection");
  1028. DisplayDNError(0,hResultCode);
  1029. DNASSERT(FALSE);
  1030. goto Failure;
  1031. }
  1032. pConnection->SetStatus( CONNECTING );
  1033. pConnection->SetEndPt(hEndPt);
  1034. pConnection->SetSP(pAsyncOp->GetSP());
  1035. pConnection->AddRef();
  1036. *ppvEndPtContext = pConnection;
  1037. //
  1038. // Ensure that this is the first CONNECT to succeed.
  1039. // If it isn't we will just drop the connection.
  1040. //
  1041. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  1042. if (pdnObject->dwFlags & DN_OBJECT_FLAG_HOST_CONNECTED)
  1043. {
  1044. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  1045. DPFERR("Connect already established - disconnecting");
  1046. DNPerformDisconnect(pdnObject,pConnection,hEndPt,FALSE);
  1047. hResultCode = DPN_OK;
  1048. goto Failure;
  1049. }
  1050. pdnObject->dwFlags |= DN_OBJECT_FLAG_HOST_CONNECTED;
  1051. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  1052. // rodtoll: Modifying so we always store this information so that when we update
  1053. // lobby settings we return the device we actually connected on for clients
  1054. /*
  1055. //
  1056. // For Peer-Peer, we will need the device address we connected on so that
  1057. // we can CONNECT to new players later on.
  1058. //
  1059. if (pdnObject->dwFlags & DN_OBJECT_FLAG_PEER)
  1060. {*/
  1061. if ((hResultCode = DNGetLocalDeviceAddress(pdnObject,hEndPt,&pIDevice)) != DPN_OK)
  1062. {
  1063. DPFERR("Could not determine local address");
  1064. DisplayDNError(0,hResultCode);
  1065. DNASSERT(FALSE);
  1066. DNPerformDisconnect(pdnObject,pConnection,hEndPt,FALSE);
  1067. goto Failure;
  1068. }
  1069. IDirectPlay8Address_AddRef(pIDevice);
  1070. pdnObject->pIDP8ADevice = pIDevice;
  1071. IDirectPlay8Address_Release(pIDevice);
  1072. pIDevice = NULL;
  1073. // }
  1074. //
  1075. // Send player and application info for NewPlayer connecting to Host
  1076. //
  1077. if ((hResultCode = DNConnectToHost1(pdnObject,pConnection)) != DPN_OK)
  1078. {
  1079. DPFERR("Could not CONNECT to Host");
  1080. DisplayDNError(0,hResultCode);
  1081. DNPerformDisconnect(pdnObject,pConnection,hEndPt,FALSE);
  1082. goto Failure;
  1083. }
  1084. }
  1085. pAsyncOp->Lock();
  1086. pAsyncOp->SetResult( DPN_OK );
  1087. pAsyncOp->Unlock();
  1088. pConnection->Release();
  1089. pConnection = NULL;
  1090. hResultCode = DPN_OK;
  1091. Exit:
  1092. //
  1093. // Ensure there are no cancels outstanding
  1094. //
  1095. DNWaitForCancel(pAsyncOp);
  1096. DNASSERT(pAsyncOp != NULL);
  1097. pAsyncOp->Release();
  1098. pAsyncOp = NULL;
  1099. //
  1100. // Release protocol reference
  1101. //
  1102. DNProtocolRelease(pdnObject);
  1103. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  1104. return(hResultCode);
  1105. Failure:
  1106. if (pConnection)
  1107. {
  1108. pConnection->Release();
  1109. pConnection = NULL;
  1110. }
  1111. if (pIDevice)
  1112. {
  1113. IDirectPlay8Address_Release(pIDevice);
  1114. pIDevice = NULL;
  1115. }
  1116. goto Exit;
  1117. }
  1118. #undef DPF_MODNAME
  1119. #define DPF_MODNAME "DNPICompleteDisconnect"
  1120. HRESULT DNPICompleteDisconnect(void *const pvUserContext,
  1121. void *const pvCommandContext,
  1122. const HRESULT hr)
  1123. {
  1124. HRESULT hResultCode;
  1125. CAsyncOp *pAsyncOp;
  1126. DIRECTNETOBJECT *pdnObject;
  1127. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hr [0x%lx]",
  1128. pvCommandContext,hr);
  1129. DNASSERT(pvUserContext != NULL);
  1130. DNASSERT(pvCommandContext != NULL);
  1131. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  1132. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  1133. DNASSERT( pAsyncOp->GetOpType() == ASYNC_OP_DISCONNECT );
  1134. pAsyncOp->Lock();
  1135. DNASSERT(!pAsyncOp->IsComplete());
  1136. pAsyncOp->SetComplete();
  1137. pAsyncOp->Unlock();
  1138. if (pAsyncOp->IsChild())
  1139. {
  1140. pAsyncOp->Orphan();
  1141. }
  1142. //
  1143. // If this completed successfully, we can remove the reference on the connection held by the Protocol
  1144. //
  1145. if (hr == DPN_OK)
  1146. {
  1147. pAsyncOp->Lock();
  1148. if (pAsyncOp->GetConnection())
  1149. {
  1150. pAsyncOp->GetConnection()->Release();
  1151. }
  1152. pAsyncOp->Unlock();
  1153. }
  1154. pAsyncOp->SetResult( hr );
  1155. //
  1156. // Ensure there are no cancels outstanding
  1157. //
  1158. DNWaitForCancel(pAsyncOp);
  1159. pAsyncOp->Release();
  1160. pAsyncOp = NULL;
  1161. //
  1162. // Release Protocol reference
  1163. //
  1164. DNProtocolRelease(pdnObject);
  1165. hResultCode = DPN_OK;
  1166. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  1167. return(hResultCode);
  1168. }
  1169. #undef DPF_MODNAME
  1170. #define DPF_MODNAME "DNPICompleteSend"
  1171. HRESULT DNPICompleteSend(void *const pvUserContext,
  1172. void *const pvCommandContext,
  1173. const HRESULT hr,
  1174. DWORD dwFirstFrameRTT,
  1175. DWORD dwFirstFrameRetryCount)
  1176. {
  1177. HRESULT hResultCode;
  1178. DIRECTNETOBJECT *pdnObject;
  1179. CAsyncOp *pAsyncOp;
  1180. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hr [0x%lx], dwFirstFrameRTT [%i], dwFirstFrameRetryCount [%u]",
  1181. pvCommandContext,hr,dwFirstFrameRTT,dwFirstFrameRetryCount);
  1182. DNASSERT(pvUserContext != NULL);
  1183. DNASSERT(pvCommandContext != NULL);
  1184. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  1185. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  1186. DNASSERT( pAsyncOp->GetOpType() == ASYNC_OP_SEND );
  1187. //
  1188. // Indicate complete and remove from active list
  1189. //
  1190. pAsyncOp->Lock();
  1191. DNASSERT(!pAsyncOp->IsComplete());
  1192. pAsyncOp->SetComplete();
  1193. pAsyncOp->Unlock();
  1194. DNEnterCriticalSection(&pdnObject->csActiveList);
  1195. pAsyncOp->m_bilinkActiveList.RemoveFromList();
  1196. DNLeaveCriticalSection(&pdnObject->csActiveList);
  1197. switch( hr )
  1198. {
  1199. case DPN_OK:
  1200. case DPNERR_ABORTED:
  1201. #pragma TODO( minara, "remove DPNERR_ABORTED" )
  1202. case DPNERR_CONNECTIONLOST:
  1203. case DPNERR_GENERIC:
  1204. case DPNERR_OUTOFMEMORY:
  1205. case DPNERR_TIMEDOUT:
  1206. case DPNERR_USERCANCEL:
  1207. {
  1208. break;
  1209. }
  1210. default:
  1211. {
  1212. DNASSERT(FALSE); // unexpected return code !
  1213. break;
  1214. }
  1215. }
  1216. if (pAsyncOp->IsChild())
  1217. {
  1218. pAsyncOp->Orphan();
  1219. }
  1220. pAsyncOp->SetResult( hr );
  1221. pAsyncOp->SetFirstFrameRTT( dwFirstFrameRTT );
  1222. pAsyncOp->SetFirstFrameRetryCount( dwFirstFrameRetryCount );
  1223. //
  1224. // Ensure there are no cancels outstanding
  1225. //
  1226. DNWaitForCancel(pAsyncOp);
  1227. pAsyncOp->Release();
  1228. pAsyncOp = NULL;
  1229. //
  1230. // Release Protocol reference
  1231. //
  1232. DNProtocolRelease(pdnObject);
  1233. hResultCode = DPN_OK;
  1234. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  1235. return(hResultCode);
  1236. }
  1237. #undef DPF_MODNAME
  1238. #define DPF_MODNAME "DNPIAddressInfoConnect"
  1239. HRESULT DNPIAddressInfoConnect(void *const pvUserContext,
  1240. void *const pvCommandContext,
  1241. const HRESULT hr,
  1242. IDirectPlay8Address *const pHostAddress,
  1243. IDirectPlay8Address *const pDeviceAddress )
  1244. {
  1245. HRESULT hResultCode;
  1246. DIRECTNETOBJECT *pdnObject;
  1247. CAsyncOp *pAsyncOp;
  1248. #ifdef DBG
  1249. TCHAR DP8ABuffer[512] = {0};
  1250. DWORD DP8ASize;
  1251. #endif // DBG
  1252. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hr [0x%lx]",
  1253. pvCommandContext,hr);
  1254. DNASSERT(pvUserContext != NULL);
  1255. DNASSERT(pvCommandContext != NULL);
  1256. DNASSERT(pHostAddress != NULL);
  1257. DNASSERT(pDeviceAddress != NULL);
  1258. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  1259. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  1260. DPFX(DPFPREP, 7,"hr [0x%lx]",hr);
  1261. #ifdef DBG
  1262. DP8ASize = 512;
  1263. IDirectPlay8Address_GetURL(pHostAddress,DP8ABuffer,&DP8ASize);
  1264. DPFX(DPFPREP, 7,"Host address [%s]",DP8ABuffer);
  1265. DP8ASize = 512;
  1266. IDirectPlay8Address_GetURL(pDeviceAddress,DP8ABuffer,&DP8ASize);
  1267. DPFX(DPFPREP, 7,"Device address [%s]",DP8ABuffer);
  1268. #endif // DBG
  1269. hResultCode = DNPerformNextConnect(pdnObject,pAsyncOp,pHostAddress,pDeviceAddress);
  1270. hResultCode = DPN_OK;
  1271. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  1272. return(hResultCode);
  1273. }
  1274. #undef DPF_MODNAME
  1275. #define DPF_MODNAME "DNPIAddressInfoEnum"
  1276. HRESULT DNPIAddressInfoEnum(void *const pvUserContext,
  1277. void *const pvCommandContext,
  1278. const HRESULT hr,
  1279. IDirectPlay8Address *const pHostAddress,
  1280. IDirectPlay8Address *const pDeviceAddress )
  1281. {
  1282. HRESULT hResultCode;
  1283. DIRECTNETOBJECT *pdnObject;
  1284. CAsyncOp *pAsyncOp;
  1285. #ifdef DBG
  1286. TCHAR DP8ABuffer[512] = {0};
  1287. DWORD DP8ASize;
  1288. #endif // DBG
  1289. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hr [0x%lx]",
  1290. pvCommandContext,hr);
  1291. DNASSERT(pvUserContext != NULL);
  1292. DNASSERT(pvCommandContext != NULL);
  1293. DNASSERT(pHostAddress != NULL);
  1294. DNASSERT(pDeviceAddress != NULL);
  1295. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  1296. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  1297. DPFX(DPFPREP, 7,"hr [0x%lx]",hr);
  1298. #ifdef DBG
  1299. DP8ASize = 512;
  1300. IDirectPlay8Address_GetURL(pHostAddress,DP8ABuffer,&DP8ASize);
  1301. DPFX(DPFPREP, 7,"Host address [%s]",DP8ABuffer);
  1302. DP8ASize = 512;
  1303. IDirectPlay8Address_GetURL(pDeviceAddress,DP8ABuffer,&DP8ASize);
  1304. DPFX(DPFPREP, 7,"Device address [%s]",DP8ABuffer);
  1305. #endif // DBG
  1306. //
  1307. // Crack open next enum only if not closing
  1308. //
  1309. if ((hResultCode = DNAddRefLock(pdnObject)) == DPN_OK)
  1310. {
  1311. hResultCode = DNPerformNextEnumQuery(pdnObject,pAsyncOp,pHostAddress,pDeviceAddress);
  1312. DNDecRefLock(pdnObject);
  1313. }
  1314. hResultCode = DPN_OK;
  1315. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  1316. return(hResultCode);
  1317. }
  1318. #undef DPF_MODNAME
  1319. #define DPF_MODNAME "DNPIAddressInfoListen"
  1320. HRESULT DNPIAddressInfoListen(void *const pvUserContext,
  1321. void *const pvCommandContext,
  1322. const HRESULT hr,
  1323. IDirectPlay8Address *const pDeviceAddress )
  1324. {
  1325. HRESULT hResultCode;
  1326. DIRECTNETOBJECT *pdnObject;
  1327. CAsyncOp *pAsyncOp;
  1328. #ifdef DBG
  1329. TCHAR DP8ABuffer[512] = {0};
  1330. DWORD DP8ASize;
  1331. #endif // DBG
  1332. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hr [0x%lx]",
  1333. pvCommandContext,hr);
  1334. DNASSERT(pvUserContext != NULL);
  1335. DNASSERT(pvCommandContext != NULL);
  1336. DNASSERT(pDeviceAddress != NULL);
  1337. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  1338. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  1339. #ifdef DBG
  1340. DP8ASize = 512;
  1341. IDirectPlay8Address_GetURL(pDeviceAddress,DP8ABuffer,&DP8ASize);
  1342. DPFX(DPFPREP, 7,"Device address [%s]",DP8ABuffer);
  1343. #endif // DBG
  1344. #ifndef DPNBUILD_ONLYONEADAPTER
  1345. hResultCode = DNPerformNextListen(pdnObject,pAsyncOp,pDeviceAddress);
  1346. #endif // ! DPNBUILD_ONLYONEADAPTER
  1347. hResultCode = DPN_OK;
  1348. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  1349. return(hResultCode);
  1350. }
  1351. #ifndef DPNBUILD_NOMULTICAST
  1352. #undef DPF_MODNAME
  1353. #define DPF_MODNAME "DNPIIndicateReceiveUnknownSender"
  1354. HRESULT DNPIIndicateReceiveUnknownSender(void *const pvUserContext,
  1355. void *const pvListenCommandContext,
  1356. IDirectPlay8Address *const pSenderAddress,
  1357. void *const pvData,
  1358. const DWORD dwDataSize,
  1359. const HANDLE hBuffer)
  1360. {
  1361. HRESULT hResultCode;
  1362. DIRECTNETOBJECT *pdnObject;
  1363. CAsyncOp *pAsyncOpListen;
  1364. SPGETADDRESSINFODATA spInfoData;
  1365. CAsyncOp *pAsyncOpReceive;
  1366. DPNHANDLE hAsyncOpReceive;
  1367. BOOL fReleaseLock;
  1368. DPFX(DPFPREP, 6,"Parameters: pvListenCommandContext [0x%p], pSenderAddress [0x%p], pvData [0x%p], dwDataSize [%ld], hBuffer [0x%p]",
  1369. pvListenCommandContext,pSenderAddress,pvData,dwDataSize,hBuffer);
  1370. DNASSERT(pvUserContext != NULL);
  1371. DNASSERT(pvListenCommandContext != NULL);
  1372. DNASSERT(pSenderAddress != NULL);
  1373. DNASSERT(pvData != NULL);
  1374. DNASSERT(((DWORD_PTR) pvData & 3) == 0); // data should be DWORD aligned
  1375. DNASSERT(dwDataSize != 0);
  1376. DNASSERT(hBuffer != NULL);
  1377. memset(&spInfoData, 0, sizeof(spInfoData));
  1378. fReleaseLock = FALSE;
  1379. pAsyncOpReceive = NULL;
  1380. hAsyncOpReceive = NULL;
  1381. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  1382. pAsyncOpListen = static_cast<CAsyncOp*>(pvListenCommandContext);
  1383. //
  1384. // Prevent close while in this call-back
  1385. //
  1386. if ((hResultCode = DNAddRefLock(pdnObject)) != DPN_OK)
  1387. {
  1388. DPFX(DPFPREP, 1, "Couldn't lock object (0x%lx), ignoring data.", hResultCode);
  1389. hResultCode = DPN_OK;
  1390. goto Failure;
  1391. }
  1392. fReleaseLock = TRUE;
  1393. //
  1394. // Ensure that this is a valid async op
  1395. //
  1396. if (pAsyncOpListen->GetOpType() != ASYNC_OP_LISTEN_MULTICAST)
  1397. {
  1398. DPFX(DPFPREP, 0, "Receiving data from unknown sender on non-listen-multicast operation (0x%p, type %u)!",
  1399. pAsyncOpListen, pAsyncOpListen->GetOpType());
  1400. DNASSERTX(FALSE, 2);
  1401. hResultCode = DPN_OK;
  1402. goto Failure;
  1403. }
  1404. //
  1405. // User or voice message
  1406. //
  1407. DPFX(DPFPREP, 7,"Received USER message from unknown sender");
  1408. spInfoData.Flags = SP_GET_ADDRESS_INFO_LOCAL_ADAPTER;
  1409. if ((hResultCode = DNPGetListenAddressInfo(pdnObject->pdnProtocolData,pAsyncOpListen->GetProtocolHandle(),&spInfoData)) != DPN_OK)
  1410. {
  1411. DPFERR("Could not get LISTEN device address!");
  1412. DisplayDNError(0,hResultCode);
  1413. DNASSERT(FALSE);
  1414. goto Failure;
  1415. }
  1416. //
  1417. // Create an AsyncOp for this receive
  1418. //
  1419. if ((hResultCode = AsyncOpNew(pdnObject,&pAsyncOpReceive)) != DPN_OK)
  1420. {
  1421. DPFERR("Could not create AsyncOp");
  1422. DisplayDNError(0,hResultCode);
  1423. DNASSERT(FALSE);
  1424. goto Failure;
  1425. }
  1426. if ((hResultCode = pdnObject->HandleTable.Create(pAsyncOpReceive,&hAsyncOpReceive)) != DPN_OK)
  1427. {
  1428. DPFERR("Could not create Handle for AsyncOp");
  1429. DisplayDNError(0,hResultCode);
  1430. DNASSERT(FALSE);
  1431. goto Failure;
  1432. }
  1433. else
  1434. {
  1435. // Add a reference for the HandleTable
  1436. pAsyncOpReceive->AddRef();
  1437. pAsyncOpReceive->Lock();
  1438. pAsyncOpReceive->SetHandle(hAsyncOpReceive);
  1439. pAsyncOpReceive->Unlock();
  1440. }
  1441. pAsyncOpReceive->SetOpType( ASYNC_OP_RECEIVE_BUFFER );
  1442. pAsyncOpReceive->SetSP( pAsyncOpListen->GetSP() );
  1443. //
  1444. // Add buffer to list of active AsyncOp's
  1445. //
  1446. DNEnterCriticalSection(&pdnObject->csActiveList);
  1447. pAsyncOpReceive->m_bilinkActiveList.InsertBefore(&pdnObject->m_bilinkActiveList);
  1448. DNLeaveCriticalSection(&pdnObject->csActiveList);
  1449. hResultCode = DNUserReceiveMulticast(pdnObject,
  1450. NULL,
  1451. pSenderAddress,
  1452. spInfoData.pAddress,
  1453. static_cast<BYTE*>(pvData),
  1454. dwDataSize,
  1455. hAsyncOpReceive);
  1456. if (hResultCode == DPNERR_PENDING)
  1457. {
  1458. pAsyncOpReceive->SetProtocolHandle( hBuffer );
  1459. pAsyncOpReceive->SetCompletion(DNCompleteReceiveBuffer);
  1460. }
  1461. else
  1462. {
  1463. DNEnterCriticalSection(&pdnObject->csActiveList);
  1464. pAsyncOpReceive->m_bilinkActiveList.RemoveFromList();
  1465. DNLeaveCriticalSection(&pdnObject->csActiveList);
  1466. pAsyncOpReceive->Lock();
  1467. if (!pAsyncOpReceive->IsCancelled() && !pAsyncOpReceive->IsComplete())
  1468. {
  1469. pAsyncOpReceive->SetComplete();
  1470. pAsyncOpReceive->Unlock();
  1471. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hAsyncOpReceive, NULL )))
  1472. {
  1473. // Release the HandleTable reference
  1474. pAsyncOpReceive->Release();
  1475. }
  1476. hAsyncOpReceive = NULL;
  1477. }
  1478. else
  1479. {
  1480. pAsyncOpReceive->Unlock();
  1481. }
  1482. //
  1483. // Only allow DPNERR_PENDING or DPN_OK
  1484. //
  1485. hResultCode = DPN_OK;
  1486. }
  1487. IDirectPlay8Address_Release(spInfoData.pAddress);
  1488. spInfoData.pAddress = NULL;
  1489. DNDecRefLock(pdnObject);
  1490. fReleaseLock = FALSE;
  1491. pAsyncOpReceive->Release();
  1492. pAsyncOpReceive = NULL;
  1493. Exit:
  1494. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  1495. return(hResultCode);
  1496. Failure:
  1497. if (hAsyncOpReceive)
  1498. {
  1499. DNEnterCriticalSection(&pdnObject->csActiveList);
  1500. pAsyncOpReceive->m_bilinkActiveList.RemoveFromList();
  1501. DNLeaveCriticalSection(&pdnObject->csActiveList);
  1502. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hAsyncOpReceive, NULL )))
  1503. {
  1504. // Release the HandleTable reference
  1505. pAsyncOpReceive->Release();
  1506. }
  1507. hAsyncOpReceive = 0;
  1508. }
  1509. if (pAsyncOpReceive)
  1510. {
  1511. pAsyncOpReceive->Release();
  1512. pAsyncOpReceive = NULL;
  1513. }
  1514. if (spInfoData.pAddress != NULL)
  1515. {
  1516. IDirectPlay8Address_Release(spInfoData.pAddress);
  1517. spInfoData.pAddress = NULL;
  1518. }
  1519. if (fReleaseLock)
  1520. {
  1521. DNDecRefLock(pdnObject);
  1522. fReleaseLock = FALSE;
  1523. }
  1524. goto Exit;
  1525. }
  1526. #undef DPF_MODNAME
  1527. #define DPF_MODNAME "DNPICompleteMulticastConnect"
  1528. HRESULT DNPICompleteMulticastConnect(void *const pvUserContext,
  1529. void *const pvCommandContext,
  1530. const HRESULT hrProt,
  1531. const HANDLE hEndPt,
  1532. void **const ppvEndPtContext)
  1533. {
  1534. HRESULT hResultCode;
  1535. CAsyncOp *pAsyncOp;
  1536. CAsyncOp *pConnectParent;
  1537. CConnection *pConnection;
  1538. DIRECTNETOBJECT *pdnObject;
  1539. DPFX(DPFPREP, 6,"Parameters: pvCommandContext [0x%p], hrProt [0x%lx], hEndPt [0x%p]",
  1540. pvCommandContext,hrProt,hEndPt);
  1541. DNASSERT(pvUserContext != NULL);
  1542. DNASSERT(pvCommandContext != NULL);
  1543. pConnection = NULL;
  1544. pdnObject = static_cast<DIRECTNETOBJECT*>(pvUserContext);
  1545. pAsyncOp = static_cast<CAsyncOp*>(pvCommandContext);
  1546. DNASSERT( pAsyncOp->GetOpType() == ASYNC_OP_CONNECT_MULTICAST_SEND || pAsyncOp->GetOpType() == ASYNC_OP_CONNECT_MULTICAST_RECEIVE );
  1547. //
  1548. // Indicate complete and remove from active list
  1549. //
  1550. pAsyncOp->Lock();
  1551. DNASSERT(!pAsyncOp->IsComplete());
  1552. pAsyncOp->SetComplete();
  1553. pAsyncOp->Unlock();
  1554. DNEnterCriticalSection(&pdnObject->csActiveList);
  1555. pAsyncOp->m_bilinkActiveList.RemoveFromList();
  1556. DNLeaveCriticalSection(&pdnObject->csActiveList);
  1557. //
  1558. // Clear connect parent from DirectNet object
  1559. //
  1560. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  1561. pConnectParent = pdnObject->pConnectParent;
  1562. pdnObject->pConnectParent = NULL;
  1563. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  1564. if (pConnectParent)
  1565. {
  1566. pConnectParent->Release();
  1567. pConnectParent = NULL;
  1568. }
  1569. //
  1570. // Save multicast endpoint if this was successful
  1571. //
  1572. if (hrProt == DPN_OK)
  1573. {
  1574. //
  1575. // Allocate and set up a CConnection object and hand a reference to the Protocol
  1576. //
  1577. DNASSERT(pAsyncOp->GetSP() != NULL);
  1578. if ((hResultCode = ConnectionNew(pdnObject,&pConnection)) != DPN_OK)
  1579. {
  1580. DPFERR("Could not get new connection");
  1581. DisplayDNError(0,hResultCode);
  1582. DNASSERT(FALSE);
  1583. goto Failure;
  1584. }
  1585. pConnection->SetStatus( CONNECTED );
  1586. pConnection->SetEndPt(hEndPt);
  1587. pConnection->SetSP(pAsyncOp->GetSP());
  1588. pConnection->AddRef();
  1589. *ppvEndPtContext = pConnection;
  1590. if (pAsyncOp->GetOpType() == ASYNC_OP_CONNECT_MULTICAST_SEND)
  1591. {
  1592. //
  1593. // We will keep a reference on the connection object on the DirectNet object
  1594. //
  1595. pConnection->MakeMulticastSender();
  1596. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  1597. pdnObject->pMulticastSend = pConnection;
  1598. pConnection = NULL;
  1599. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  1600. }
  1601. else
  1602. {
  1603. //
  1604. // We will keep a reference on the connection object in the list off the DirectNet object
  1605. //
  1606. pConnection->MakeMulticastReceiver();
  1607. if (pAsyncOp->GetParent())
  1608. {
  1609. pConnection->SetContext( pAsyncOp->GetParent()->GetContext() );
  1610. }
  1611. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  1612. pConnection->m_bilinkMulticast.InsertBefore(&pdnObject->m_bilinkMulticast);
  1613. pConnection = NULL;
  1614. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  1615. }
  1616. }
  1617. if (pAsyncOp->IsChild())
  1618. {
  1619. pAsyncOp->Orphan();
  1620. }
  1621. pAsyncOp->Lock();
  1622. pAsyncOp->SetResult( hrProt );
  1623. pAsyncOp->Unlock();
  1624. hResultCode = DPN_OK;
  1625. Exit:
  1626. DNASSERT(pConnection == NULL);
  1627. //
  1628. // Ensure there are no cancels outstanding
  1629. //
  1630. DNWaitForCancel(pAsyncOp);
  1631. DNASSERT(pAsyncOp != NULL);
  1632. pAsyncOp->Release();
  1633. pAsyncOp = NULL;
  1634. //
  1635. // Release protocol reference
  1636. //
  1637. DNProtocolRelease(pdnObject);
  1638. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  1639. return( hResultCode );
  1640. Failure:
  1641. if (pConnection)
  1642. {
  1643. pConnection->Release();
  1644. pConnection = NULL;
  1645. }
  1646. goto Exit;
  1647. }
  1648. #endif // DPNBUILD_NOMULTICAST
  1649. #undef DPF_MODNAME
  1650. #define DPF_MODNAME "DNProtocolAddRef"
  1651. void DNProtocolAddRef(DIRECTNETOBJECT *const pdnObject)
  1652. {
  1653. LONG lRefCount;
  1654. DPFX(DPFPREP, 8,"(0x%p) Parameters: (none)",pdnObject);
  1655. lRefCount = DNInterlockedIncrement((LONG*)&pdnObject->lProtocolRefCount);
  1656. DPFX(DPFPREP, 8,"(0x%p) Returning (lRefCount = [%ld])",pdnObject,lRefCount);
  1657. }
  1658. #undef DPF_MODNAME
  1659. #define DPF_MODNAME "DNProtocolRelease"
  1660. void DNProtocolRelease(DIRECTNETOBJECT *const pdnObject)
  1661. {
  1662. LONG lRefCount;
  1663. DPFX(DPFPREP, 8,"(0x%p) Parameters: (none)",pdnObject);
  1664. lRefCount = DNInterlockedDecrement((LONG*)&pdnObject->lProtocolRefCount);
  1665. DNASSERT(lRefCount >= 0);
  1666. if (lRefCount == 0)
  1667. {
  1668. DPFX(DPFPREP, 9,"Signalling protocol shutdown !");
  1669. if (pdnObject->hProtocolShutdownEvent)
  1670. {
  1671. pdnObject->hProtocolShutdownEvent->Set();
  1672. }
  1673. }
  1674. DPFX(DPFPREP, 8,"(0x%p) Returning (lRefCount = [%ld])",pdnObject,lRefCount);
  1675. }