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.

1552 lines
45 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: mcast.cpp
  6. * Content: DirectPlay8 Mcast interface routines
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 10/08/01 vanceo Created
  12. *@@END_MSINTERNAL
  13. *
  14. ***************************************************************************/
  15. #include "dncorei.h"
  16. #ifndef DPNBUILD_NOMULTICAST
  17. //**********************************************************************
  18. // Constant definitions
  19. //**********************************************************************
  20. //**********************************************************************
  21. // Macro definitions
  22. //**********************************************************************
  23. //**********************************************************************
  24. // Structure definitions
  25. //**********************************************************************
  26. //**********************************************************************
  27. // Variable definitions
  28. //**********************************************************************
  29. typedef STDMETHODIMP McastQueryInterface(IDirectPlay8Multicast *pInterface, DP8REFIID riid, LPVOID *ppvObj);
  30. typedef STDMETHODIMP_(ULONG) McastAddRef(IDirectPlay8Multicast *pInterface);
  31. typedef STDMETHODIMP_(ULONG) McastRelease(IDirectPlay8Multicast *pInterface);
  32. typedef STDMETHODIMP McastInitialize(IDirectPlay8Multicast *pInterface, PVOID const pvUserContext, const PFNDPNMESSAGEHANDLER pfn, const DWORD dwFlags);
  33. typedef STDMETHODIMP McastJoin(IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pGroupAddr, IUnknown *const pDeviceInfo, const DPN_SECURITY_DESC *const pdnSecurity, const DPN_SECURITY_CREDENTIALS *const pdnCredentials, void *const pvAsyncContext, DPNHANDLE *const phAsyncHandle, const DWORD dwFlags);
  34. typedef STDMETHODIMP McastClose(IDirectPlay8Multicast *pInterface, const DWORD dwFlags);
  35. typedef STDMETHODIMP McastCreateSenderContext(IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pSenderAddress, void *const pvSenderContext, const DWORD dwFlags);
  36. typedef STDMETHODIMP McastDestroySenderContext(IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pSenderAddress, const DWORD dwFlags);
  37. typedef STDMETHODIMP McastSend(IDirectPlay8Multicast *pInterface, const DPN_BUFFER_DESC *const prgBufferDesc,const DWORD cBufferDesc,const DWORD dwTimeOut, void *const pvAsyncContext, DPNHANDLE *const phAsyncHandle, const DWORD dwFlags);
  38. typedef STDMETHODIMP McastGetGroupAddress(IDirectPlay8Multicast *pInterface, IDirectPlay8Address **const ppAddress, const DWORD dwFlags);
  39. typedef STDMETHODIMP McastGetSendQueueInfo( IDirectPlay8Multicast *pInterface, DWORD *const lpdwNumMsgs, DWORD *const lpdwNumBytes, const DWORD dwFlags);
  40. typedef STDMETHODIMP McastCancelAsyncOperation( IDirectPlay8Multicast *pInterface, const DPNHANDLE hAsyncHandle, const DWORD dwFlags);
  41. typedef STDMETHODIMP McastReturnBuffer( IDirectPlay8Multicast *pInterface, const DPNHANDLE hBufferHandle,const DWORD dwFlags);
  42. typedef STDMETHODIMP McastEnumServiceProviders( IDirectPlay8Multicast *pInterface, const GUID *const pguidServiceProvider, const GUID *const pguidApplication, DPN_SERVICE_PROVIDER_INFO *const pSPInfoBuffer, DWORD *const pcbEnumData, DWORD *const pcReturned, const DWORD dwFlags);
  43. typedef STDMETHODIMP McastEnumMulticastScopes( IDirectPlay8Multicast *pInterface, const GUID *const pguidServiceProvider, const GUID *const pguidDevice, const GUID *const pguidApplication, DPN_MULTICAST_SCOPE_INFO *const pScopeInfoBuffer, PDWORD const pcbEnumData, PDWORD const pcReturned, const DWORD dwFlags);
  44. typedef STDMETHODIMP McastGetSPCaps(IDirectPlay8Multicast *pInterface, const GUID * const pguidSP, DPN_SP_CAPS *const pdpspCaps,const DWORD dwFlags);
  45. typedef STDMETHODIMP McastSetSPCaps(IDirectPlay8Multicast *pInterface, const GUID * const pguidSP, const DPN_SP_CAPS *const pdpspCaps, const DWORD dwFlags);
  46. IDirectPlay8MulticastVtbl DNMcast_Vtbl =
  47. {
  48. (McastQueryInterface*) DN_QueryInterface,
  49. (McastAddRef*) DN_AddRef,
  50. (McastRelease*) DN_Release,
  51. (McastInitialize*) DN_Initialize,
  52. (McastJoin*) DN_Join,
  53. (McastClose*) DN_Close,
  54. (McastCreateSenderContext*) DN_CreateSenderContext,
  55. (McastDestroySenderContext*) DN_DestroySenderContext,
  56. (McastSend*) DN_Send,
  57. (McastGetGroupAddress*) DN_GetGroupAddress,
  58. (McastGetSendQueueInfo*) DN_GetHostSendQueueInfo,
  59. (McastCancelAsyncOperation*) DN_CancelAsyncOperation,
  60. (McastReturnBuffer*) DN_ReturnBuffer,
  61. (McastEnumServiceProviders*) DN_EnumServiceProviders,
  62. (McastEnumMulticastScopes*) DN_EnumMulticastScopes,
  63. (McastGetSPCaps*) DN_GetSPCaps,
  64. (McastSetSPCaps*) DN_SetSPCaps
  65. };
  66. //**********************************************************************
  67. // Function prototypes
  68. //**********************************************************************
  69. //**********************************************************************
  70. // Function definitions
  71. //**********************************************************************
  72. //
  73. // Completion for join connect parent
  74. //
  75. #undef DPF_MODNAME
  76. #define DPF_MODNAME "DNCompleteJoinOperation"
  77. void DNCompleteJoinOperation(DIRECTNETOBJECT *const pdnObject,
  78. CAsyncOp *const pAsyncOp)
  79. {
  80. CServiceProvider *pSP;
  81. IDirectPlay8Address *pIDevice;
  82. pSP = NULL;
  83. pIDevice = NULL;
  84. //
  85. // Save the result code on the parent (if it exists - it will be the CONNECT handle)
  86. //
  87. if (pAsyncOp->GetParent())
  88. {
  89. pAsyncOp->GetParent()->Lock();
  90. pAsyncOp->GetParent()->SetResult( pAsyncOp->GetResult() );
  91. pAsyncOp->GetParent()->Unlock();
  92. if (SUCCEEDED(pdnObject->HandleTable.Destroy( pAsyncOp->GetParent()->GetHandle(), NULL )))
  93. {
  94. // Release the HandleTable reference
  95. pAsyncOp->GetParent()->Release();
  96. }
  97. }
  98. //
  99. // Clear CONNECTING flag, and DISCONNECTING flag in case this was aborted.
  100. // If the connect succeeded, set the CONNECTED flag.
  101. //
  102. DPFX(DPFPREP, 8,"Clearing CONNECTING and DISCONNECTING flags");
  103. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  104. pdnObject->dwFlags &= (~DN_OBJECT_FLAG_CONNECTING | DN_OBJECT_FLAG_DISCONNECTING);
  105. if (pAsyncOp->GetResult() == DPN_OK)
  106. {
  107. pdnObject->dwFlags |= DN_OBJECT_FLAG_CONNECTED;
  108. }
  109. else
  110. {
  111. //
  112. // Clean up DirectNet object
  113. //
  114. pSP = pdnObject->pConnectSP;
  115. pdnObject->pConnectSP = NULL;
  116. pIDevice = pdnObject->pIDP8ADevice;
  117. pdnObject->pIDP8ADevice = NULL;
  118. }
  119. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  120. if (pSP)
  121. {
  122. pSP->Release();
  123. pSP = NULL;
  124. }
  125. if (pIDevice)
  126. {
  127. IDirectPlay8Address_Release(pIDevice);
  128. pIDevice = NULL;
  129. }
  130. DNASSERT( pSP == NULL );
  131. DNASSERT( pIDevice == NULL );
  132. }
  133. //
  134. // Completion for join handle parent
  135. //
  136. #undef DPF_MODNAME
  137. #define DPF_MODNAME "DNCompleteUserJoin"
  138. void DNCompleteUserJoin(DIRECTNETOBJECT *const pdnObject,
  139. CAsyncOp *const pAsyncOp)
  140. {
  141. DNUserJoinComplete( pdnObject,
  142. pAsyncOp->GetHandle(),
  143. pAsyncOp->GetContext(),
  144. pAsyncOp->GetResult());
  145. }
  146. #undef DPF_MODNAME
  147. #define DPF_MODNAME "DN_Join"
  148. STDMETHODIMP DN_Join( IDirectPlay8Multicast *pInterface,
  149. IDirectPlay8Address *const pGroupAddr,
  150. IUnknown *const pDeviceInfo,
  151. const DPN_SECURITY_DESC *const pdnSecurity,
  152. const DPN_SECURITY_CREDENTIALS *const pdnCredentials,
  153. void *const pvAsyncContext,
  154. DPNHANDLE *const phAsyncHandle,
  155. const DWORD dwFlags)
  156. {
  157. HRESULT hResultCode;
  158. HRESULT volatile hrOperation;
  159. DIRECTNETOBJECT *pdnObject;
  160. IDirectPlay8Address *pIGroup;
  161. IDirectPlay8Address *pIDevice;
  162. #ifndef DPNBUILD_ONLYONESP
  163. GUID guidSP;
  164. #endif // ! DPNBUILD_ONLYONESP
  165. #ifndef DPNBUILD_ONLYONEADAPTER
  166. GUID guidAdapter;
  167. #endif // ! DPNBUILD_ONLYONEADAPTER
  168. PVOID pvNewInterface;
  169. DWORD dwListenFlags;
  170. CAsyncOp *pListenParent;
  171. CAsyncOp *pParent;
  172. CAsyncOp *pAsyncOp;
  173. CAsyncOp *pConnectParent;
  174. CAsyncOp *pHandleParent;
  175. CServiceProvider *pSP;
  176. CSyncEvent *pSyncEvent;
  177. HANDLE hEndpoint;
  178. SPGETADDRESSINFODATA spInfoData;
  179. // Variables used when device interface is a DIRECTNETOBJECT
  180. DIRECTNETOBJECT *pdnDeviceObject;
  181. CConnection *pExistingConnection;
  182. CNameTableEntry *pNTEntry;
  183. CServiceProvider *pShareSP;
  184. IDP8ServiceProvider *pShareDP8ServiceProvider;
  185. HANDLE hEndPt;
  186. CCallbackThread CallbackThread;
  187. CAsyncOp *pShareListenParent;
  188. CBilink *pBilink;
  189. CAsyncOp *pShareParent;
  190. IDP8ServiceProvider *pLocalDP8ServiceProvider;
  191. SPSHAREENDPOINTINFODATA spShareData;
  192. DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pGroupAddr [0x%p], pDeviceInfo [0x%p], pdnSecurity [0x%p], pdnCredentials [0x%p], pvAsyncContext [0x%p], phAsyncHandle [0x%p], dwFlags [0x%lx]",
  193. pInterface,pGroupAddr,pDeviceInfo,pdnSecurity,pdnCredentials,pvAsyncContext,phAsyncHandle,dwFlags);
  194. pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
  195. DNASSERT(pdnObject != NULL);
  196. #ifndef DPNBUILD_NOPARAMVAL
  197. if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
  198. {
  199. if( FAILED( hResultCode = DN_ValidateJoin( pInterface, pGroupAddr, pDeviceInfo,
  200. pdnSecurity, pdnCredentials,
  201. pvAsyncContext,phAsyncHandle,dwFlags ) ) )
  202. {
  203. DPFERR( "Error validating join params" );
  204. DPF_RETURN( hResultCode );
  205. }
  206. }
  207. #endif // !DPNBUILD_NOPARAMVAL
  208. // Check to ensure message handler registered
  209. if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
  210. {
  211. DPFERR( "Object is not initialized" );
  212. DPF_RETURN(DPNERR_UNINITIALIZED);
  213. }
  214. // Check to ensure not already connected/connecting
  215. if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING)
  216. {
  217. DPFERR( "Object is already connecting" );
  218. DPF_RETURN(DPNERR_CONNECTING);
  219. }
  220. if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTED)
  221. {
  222. DPFERR( "Object is already connected" );
  223. DPF_RETURN(DPNERR_ALREADYCONNECTED);
  224. }
  225. if (pdnObject->dwFlags & (DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING))
  226. {
  227. DPFERR( "Object is closing or disconnecting" );
  228. DPF_RETURN(DPNERR_ALREADYCLOSING);
  229. }
  230. pIGroup = NULL;
  231. pIDevice = NULL;
  232. pvNewInterface = NULL;
  233. pListenParent = NULL;
  234. pParent = NULL;
  235. pConnectParent = NULL;
  236. pHandleParent = NULL;
  237. pSP = NULL;
  238. pSyncEvent = NULL;
  239. pdnDeviceObject = NULL;
  240. pExistingConnection = NULL;
  241. pNTEntry = NULL;
  242. pShareSP = NULL;
  243. pShareDP8ServiceProvider = NULL;
  244. CallbackThread.Deinitialize();
  245. pShareListenParent = NULL;
  246. pShareParent = NULL;
  247. pLocalDP8ServiceProvider = NULL;
  248. //
  249. // Flag as CONNECTING to prevent other operations here
  250. //
  251. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  252. if (pdnObject->dwFlags & (DN_OBJECT_FLAG_CONNECTING | DN_OBJECT_FLAG_CONNECTED))
  253. {
  254. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  255. hResultCode = DPNERR_ALREADYCONNECTED;
  256. goto Failure;
  257. }
  258. pdnObject->dwFlags |= DN_OBJECT_FLAG_CONNECTING;
  259. // Adding local host flag
  260. //pdnObject->dwFlags |= DN_OBJECT_FLAG_LOCALHOST;
  261. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  262. //
  263. // Duplicate specified Group Address, or create a blank one if NULL
  264. //
  265. if (pGroupAddr != NULL)
  266. {
  267. if ((hResultCode = IDirectPlay8Address_Duplicate(pGroupAddr,&pIGroup)) != DPN_OK)
  268. {
  269. DPFERR("Could not duplicate group address");
  270. DisplayDNError(0,hResultCode);
  271. DNASSERT(FALSE);
  272. goto Failure;
  273. }
  274. }
  275. else
  276. {
  277. #ifdef DPNBUILD_LIBINTERFACE
  278. hResultCode = DP8ACF_CreateInstance(IID_IDirectPlay8Address,
  279. reinterpret_cast<void**>(&pIGroup));
  280. #else // ! DPNBUILD_LIBINTERFACE
  281. hResultCode = COM_CoCreateInstance(CLSID_DirectPlay8Address,
  282. NULL,
  283. CLSCTX_INPROC_SERVER,
  284. IID_IDirectPlay8Address,
  285. reinterpret_cast<void**>(&pIGroup),
  286. FALSE);
  287. #endif // ! DPNBUILD_LIBINTERFACE
  288. if (hResultCode != S_OK)
  289. {
  290. DPFERR("Could not create Group Address");
  291. DisplayDNError(0,hResultCode);
  292. DNASSERT(FALSE);
  293. goto Failure;
  294. }
  295. }
  296. //
  297. // Generate a Device Address from the DPlay interface, or duplicate
  298. // the user's. Start by finding out which type of interface it is.
  299. //
  300. if (((IDirectPlay8Peer_QueryInterface((IDirectPlay8Peer*) pDeviceInfo, IID_IDirectPlay8Peer, &pvNewInterface)) == S_OK) ||
  301. #ifndef DPNBUILD_NOSERVER
  302. ((IDirectPlay8Server_QueryInterface((IDirectPlay8Server*) pDeviceInfo, IID_IDirectPlay8Server, &pvNewInterface)) == S_OK) ||
  303. #endif // ! DPNBUILD_NOSERVER
  304. ((IDirectPlay8Client_QueryInterface((IDirectPlay8Client*) pDeviceInfo, IID_IDirectPlay8Client, &pvNewInterface)) == S_OK) ||
  305. ((IDirectPlay8Multicast_QueryInterface((IDirectPlay8Multicast*) pDeviceInfo, IID_IDirectPlay8Multicast, &pvNewInterface)) == S_OK))
  306. {
  307. //
  308. // It's a DIRECTNETOBJECT.
  309. //
  310. pdnDeviceObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pvNewInterface);
  311. DNEnterCriticalSection(&pdnDeviceObject->csDirectNetObject);
  312. if (! (pdnDeviceObject->dwFlags & DN_OBJECT_FLAG_CONNECTED))
  313. {
  314. DPFERR("DirectPlay device object is not connected or hosting" );
  315. DNLeaveCriticalSection(&pdnDeviceObject->csDirectNetObject);
  316. hResultCode = DPNERR_INVALIDDEVICEADDRESS;
  317. goto Failure;
  318. }
  319. DNLeaveCriticalSection(&pdnDeviceObject->csDirectNetObject);
  320. //
  321. // Get the host player's connection (if not a multicast object).
  322. //
  323. if (! (pdnDeviceObject->dwFlags & DN_OBJECT_FLAG_MULTICAST))
  324. {
  325. if ((hResultCode = pdnDeviceObject->NameTable.GetHostPlayerRef(&pNTEntry)) != DPN_OK)
  326. {
  327. DPFERR("Could not find device object's Host player");
  328. DisplayDNError(0,hResultCode);
  329. hResultCode = DPNERR_INVALIDDEVICEADDRESS;
  330. goto Failure;
  331. }
  332. //
  333. // If we're the host, then the name table entry won't have a valid
  334. // connection object.
  335. //
  336. if (! pNTEntry->IsLocal())
  337. {
  338. hResultCode = pNTEntry->GetConnectionRef(&pExistingConnection);
  339. if (hResultCode != DPN_OK)
  340. {
  341. DPFX(DPFPREP, 0, "Could not find device object's Host player (err = 0x%lx)! Ignoring.",
  342. pdnDeviceObject, pExistingConnection);
  343. DNASSERT(pExistingConnection == NULL);
  344. }
  345. }
  346. pNTEntry->Release();
  347. pNTEntry = NULL;
  348. }
  349. //
  350. // If we got a connection, simply extract its device address.
  351. // If we couldn't get the non-local host player's connection, we
  352. // have to select the device a different way.
  353. //
  354. if (pExistingConnection != NULL)
  355. {
  356. if ((hResultCode = pExistingConnection->GetEndPt(&hEndPt,&CallbackThread)) != DPN_OK)
  357. {
  358. DPFERR( "Couldn't retrieve host player's endpoint" );
  359. DisplayDNError(0, hResultCode);
  360. goto Failure;
  361. }
  362. spInfoData.Flags = SP_GET_ADDRESS_INFO_LOCAL_ADAPTER;
  363. //
  364. // Note that we are calling our Protocol object with the other
  365. // interface's endpoint.
  366. //
  367. hResultCode = DNPCrackEndPointDescriptor(pdnObject->pdnProtocolData, hEndPt,&spInfoData);
  368. if (hResultCode != DPN_OK)
  369. {
  370. DPFERR("Unknown error from DNPCrackEndPointDescriptor");
  371. DisplayDNError(0,hResultCode);
  372. DNASSERT(FALSE);
  373. pExistingConnection->ReleaseEndPt(&CallbackThread);
  374. goto Failure;
  375. }
  376. pIDevice = spInfoData.pAddress;
  377. spInfoData.pAddress = NULL;
  378. pExistingConnection->ReleaseEndPt(&CallbackThread);
  379. pShareSP = pExistingConnection->GetSP();
  380. if (pShareSP == NULL)
  381. {
  382. DPFERR("Could not get host player connection's SP!");
  383. DNASSERT(FALSE);
  384. hResultCode = DPNERR_INVALIDDEVICEADDRESS;
  385. goto Failure;
  386. }
  387. pExistingConnection->Release();
  388. pExistingConnection = NULL;
  389. }
  390. else
  391. {
  392. //
  393. // Get the listen operation.
  394. //
  395. DNEnterCriticalSection(&pdnDeviceObject->csDirectNetObject);
  396. if (pdnDeviceObject->pListenParent == NULL)
  397. {
  398. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  399. DPFERR("Could not find device object's listen parent operation!");
  400. DNASSERT(FALSE);
  401. hResultCode = DPNERR_INVALIDDEVICEADDRESS;
  402. goto Failure;
  403. }
  404. pdnDeviceObject->pListenParent->AddRef();
  405. pShareListenParent = pdnDeviceObject->pListenParent;
  406. DNLeaveCriticalSection(&pdnDeviceObject->csDirectNetObject);
  407. //
  408. // Get the first SP listen.
  409. //
  410. pShareListenParent->Lock();
  411. pBilink = pShareListenParent->m_bilinkParent.GetNext();
  412. if (pBilink == &pShareListenParent->m_bilinkParent)
  413. {
  414. DPFERR("Could not find device object's first listen operation!");
  415. DNASSERT(FALSE);
  416. hResultCode = DPNERR_INVALIDDEVICEADDRESS;
  417. goto Failure;
  418. }
  419. pShareParent = CONTAINING_OBJECT(pBilink,CAsyncOp,m_bilinkChildren);
  420. pShareSP = pShareParent->GetSP();
  421. if (pShareSP == NULL)
  422. {
  423. DPFERR("Could not get first listen operation's SP!");
  424. DNASSERT(FALSE);
  425. hResultCode = DPNERR_INVALIDDEVICEADDRESS;
  426. goto Failure;
  427. }
  428. pShareSP->AddRef();
  429. pShareListenParent->Unlock();
  430. pShareListenParent->Release();
  431. pShareListenParent = NULL;
  432. #ifndef DPNBUILD_ONLYONESP
  433. //
  434. // Get the share SP's GUID.
  435. //
  436. pShareSP->GetGUID(&guidSP);
  437. #endif // ! DPNBUILD_ONLYONESP
  438. //
  439. // Build a device address object.
  440. //
  441. #ifdef DPNBUILD_LIBINTERFACE
  442. hResultCode = DP8ACF_CreateInstance(IID_IDirectPlay8Address,
  443. reinterpret_cast<void**>(&pIDevice));
  444. #else // ! DPNBUILD_LIBINTERFACE
  445. hResultCode = COM_CoCreateInstance(CLSID_DirectPlay8Address,
  446. NULL,
  447. CLSCTX_INPROC_SERVER,
  448. IID_IDirectPlay8Address,
  449. reinterpret_cast<void**>(&pIDevice),
  450. FALSE);
  451. #endif // ! DPNBUILD_LIBINTERFACE
  452. if (hResultCode != S_OK)
  453. {
  454. DPFERR("Could not create Device Address");
  455. DisplayDNError(0,hResultCode);
  456. DNASSERT(FALSE);
  457. goto Failure;
  458. }
  459. #ifndef DPNBUILD_ONLYONESP
  460. if ((hResultCode = IDirectPlay8Address_SetSP(pIDevice,&guidSP)) != DPN_OK)
  461. {
  462. DPFERR("Could not set SP on Device Address");
  463. DisplayDNError(0,hResultCode);
  464. goto Failure;
  465. }
  466. #endif // ! DPNBUILD_ONLYONESP
  467. #ifndef DPNBUILD_ONLYONEADAPTER
  468. //
  469. // For multicast objects we can reuse the same device GUID, too,
  470. // since we know there will be only one.
  471. //
  472. if (pdnDeviceObject->dwFlags & DN_OBJECT_FLAG_MULTICAST)
  473. {
  474. pShareParent->Lock();
  475. DNASSERT(! pShareParent->IsCancelled());
  476. DNASSERT(! pShareParent->m_bilinkParent.IsEmpty());
  477. pAsyncOp = CONTAINING_OBJECT(pParent->m_bilinkParent.GetNext(),CAsyncOp,m_bilinkChildren);
  478. pAsyncOp->Lock();
  479. DNASSERT((! pAsyncOp->IsCancelled()) && (! pAsyncOp->IsComplete()));
  480. DNASSERT(pAsyncOp->m_bilinkChildren.GetNext() == &pShareParent->m_bilinkParent);
  481. hEndpoint = pAsyncOp->GetProtocolHandle();
  482. pAsyncOp->Unlock();
  483. pShareParent->Unlock();
  484. spInfoData.hEndpoint = hEndpoint;
  485. spInfoData.Flags = SP_GET_ADDRESS_INFO_LOCAL_ADAPTER;
  486. //
  487. // Note that we are calling our Protocol object with the other
  488. // interface's endpoint.
  489. //
  490. if ((hResultCode = DNPGetListenAddressInfo(pdnObject->pdnProtocolData, spInfoData.hEndpoint,&spInfoData)) != DPN_OK)
  491. {
  492. DPFERR("Could not get LISTEN device address!");
  493. DisplayDNError(0,hResultCode);
  494. DNASSERT(FALSE);
  495. goto Failure;
  496. }
  497. //
  498. // Retrieve the device GUID from the listen address.
  499. //
  500. if ((hResultCode = IDirectPlay8Address_GetDevice(spInfoData.pAddress, &guidAdapter)) != DPN_OK)
  501. {
  502. DPFERR("Could not get adapter GUID!");
  503. DisplayDNError(0,hResultCode);
  504. DNASSERT(FALSE);
  505. IDirectPlay8Address_Release(spInfoData.pAddress);
  506. spInfoData.pAddress = NULL;
  507. goto Failure;
  508. }
  509. IDirectPlay8Address_Release(spInfoData.pAddress);
  510. spInfoData.pAddress = NULL;
  511. //
  512. // Store the device GUID on our device address.
  513. //
  514. if ((hResultCode = IDirectPlay8Address_SetDevice(pIDevice, &guidAdapter)) != DPN_OK)
  515. {
  516. DPFERR("Could not set adapter GUID!");
  517. DisplayDNError(0,hResultCode);
  518. DNASSERT(FALSE);
  519. goto Failure;
  520. }
  521. }
  522. #endif // ! DPNBUILD_ONLYONEADAPTER
  523. }
  524. //
  525. // Get the share SP's COM interface.
  526. //
  527. if ((hResultCode = pShareSP->GetInterfaceRef(&pShareDP8ServiceProvider)) != DPN_OK)
  528. {
  529. DPFERR("Could not get shared SP interface");
  530. DisplayDNError(0,hResultCode);
  531. DNASSERT(FALSE);
  532. goto Failure;
  533. }
  534. pShareSP->Release();
  535. pShareSP = NULL;
  536. //
  537. // Load our own local instance of that SP.
  538. //
  539. hResultCode = DN_SPEnsureLoaded(pdnObject,
  540. #ifndef DPNBUILD_ONLYONESP
  541. &guidSP,
  542. #endif // ! DPNBUILD_ONLYONESP
  543. #ifndef DPNBUILD_LIBINTERFACE
  544. NULL,
  545. #endif // ! DPNBUILD_LIBINTERFACE
  546. &pSP);
  547. if (hResultCode != DPN_OK)
  548. {
  549. DPFERR("Could not find or load SP");
  550. DisplayDNError(0,hResultCode);
  551. goto Failure;
  552. }
  553. //
  554. // Get the local SP's COM interface.
  555. //
  556. if ((hResultCode = pSP->GetInterfaceRef(&pLocalDP8ServiceProvider)) != DPN_OK)
  557. {
  558. DPFERR("Could not get local SP interface");
  559. DisplayDNError(0,hResultCode);
  560. goto Failure;
  561. }
  562. //
  563. // Tell our SP interface to get its endpoint information from the
  564. // other interface's SP.
  565. //
  566. spShareData.pDP8ServiceProvider = pShareDP8ServiceProvider;
  567. spShareData.dwFlags = 0;
  568. hResultCode = IDP8ServiceProvider_ShareEndpointInfo(pLocalDP8ServiceProvider,
  569. &spShareData);
  570. if (hResultCode != DPN_OK)
  571. {
  572. DPFERR("Could not have SPs share endpoint info");
  573. DisplayDNError(0,hResultCode);
  574. goto Failure;
  575. }
  576. IDP8ServiceProvider_Release(pLocalDP8ServiceProvider);
  577. pLocalDP8ServiceProvider = NULL;
  578. IDP8ServiceProvider_Release(pShareDP8ServiceProvider);
  579. pShareDP8ServiceProvider = NULL;
  580. //
  581. // Release the ref we held on the device object.
  582. //
  583. IDirectPlay8Peer_Release((IDirectPlay8Peer*) pvNewInterface); // all core objects have Release in same location in Vtbl
  584. pvNewInterface = NULL;
  585. }
  586. else if ((IDirectPlay8Address_QueryInterface((IDirectPlay8Address*) pDeviceInfo, IID_IDirectPlay8Address, &pvNewInterface)) == S_OK)
  587. {
  588. //
  589. // It's an address.
  590. //
  591. IDirectPlay8Address_Release((IDirectPlay8Address*) pvNewInterface);
  592. pvNewInterface = NULL;
  593. if ((hResultCode = IDirectPlay8Address_Duplicate(reinterpret_cast<IDirectPlay8Address*>(pDeviceInfo),&pIDevice)) != DPN_OK)
  594. {
  595. DPFERR("Could not duplicate device info");
  596. DisplayDNError(0,hResultCode);
  597. DNASSERT(FALSE);
  598. goto Failure;
  599. }
  600. }
  601. else
  602. {
  603. DPFERR( "Invalid device address, it must be an IDirectPlay8Peer, IDirectPlay8Server, IDirectPlay8Client, IDirectPlay8Multicast, or IDirectPlay8Address object" );
  604. return( DPNERR_INVALIDDEVICEADDRESS );
  605. }
  606. #ifndef DPNBUILD_ONLYONESP
  607. //
  608. // If there is no SP on the group address, then steal it from the device address
  609. //
  610. if ((hResultCode = IDirectPlay8Address_GetSP(pIGroup,&guidSP)) != DPN_OK)
  611. {
  612. if ((hResultCode = IDirectPlay8Address_GetSP(pIDevice,&guidSP)) != DPN_OK)
  613. {
  614. DPFERR("Could not retrieve SP from Device Address");
  615. DisplayDNError(0,hResultCode);
  616. goto Failure;
  617. }
  618. if ((hResultCode = IDirectPlay8Address_SetSP(pIGroup,&guidSP)) != DPN_OK)
  619. {
  620. DPFERR("Could not set SP on Group Address");
  621. DisplayDNError(0,hResultCode);
  622. goto Failure;
  623. }
  624. }
  625. #endif // ! DPNBUILD_ONLYONESP
  626. //
  627. // Ensure SP is loaded, if we haven't already.
  628. //
  629. if (pSP == NULL)
  630. {
  631. hResultCode = DN_SPEnsureLoaded(pdnObject,
  632. #ifndef DPNBUILD_ONLYONESP
  633. &guidSP,
  634. #endif // ! DPNBUILD_ONLYONESP
  635. #ifndef DPNBUILD_LIBINTERFACE
  636. NULL,
  637. #endif // ! DPNBUILD_LIBINTERFACE
  638. &pSP);
  639. if (hResultCode != DPN_OK)
  640. {
  641. DPFERR("Could not find or load SP");
  642. DisplayDNError(0,hResultCode);
  643. goto Failure;
  644. }
  645. }
  646. #ifndef DPNBUILD_ONLYONEADAPTER
  647. //
  648. // Multicast listen device addresses are formed by taking the adapter GUID from
  649. // the user's device address, combined with the entire user specified group address.
  650. // If there is no adapter, then we will pick the best one as reported by the service
  651. // provider (that part occurs inside DNPerformSPListen).
  652. //
  653. if ((hResultCode = IDirectPlay8Address_GetDevice(pIDevice,&guidAdapter)) == DPN_OK)
  654. {
  655. if ((hResultCode = IDirectPlay8Address_SetDevice(pIGroup,&guidAdapter)) != DPN_OK)
  656. {
  657. DPFERR("Could not set SP on Group Address");
  658. DisplayDNError(0,hResultCode);
  659. goto Failure;
  660. }
  661. }
  662. #endif // ! DPNBUILD_ONLYONEADAPTER
  663. dwListenFlags = DN_LISTENFLAGS_MULTICAST;
  664. if (dwFlags & DPNJOIN_ALLOWUNKNOWNSENDERS)
  665. {
  666. dwListenFlags |= DN_LISTENFLAGS_ALLOWUNKNOWNSENDERS;
  667. }
  668. //
  669. // Start multicast listen
  670. //
  671. if ((hResultCode = AsyncOpNew(pdnObject,&pListenParent)) != DPN_OK)
  672. {
  673. DPFERR("Could not create AsyncOp");
  674. DisplayDNError(0,hResultCode);
  675. goto Failure;
  676. }
  677. pListenParent->SetOpType( ASYNC_OP_LISTEN_MULTICAST );
  678. pListenParent->SetOpFlags( dwListenFlags );
  679. pListenParent->MakeParent();
  680. pListenParent->SetCompletion( DNCompleteListen );
  681. // See note above about why it's pIGroup instead of pIDevice.
  682. if ((hResultCode = DNPerformSPListen(pdnObject,pIGroup,pListenParent,&pParent)) != DPN_OK)
  683. {
  684. DPFERR("Could not start LISTEN");
  685. DisplayDNError(0,hResultCode);
  686. goto Failure;
  687. }
  688. pListenParent->AddRef();
  689. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  690. pdnObject->pListenParent = pListenParent;
  691. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  692. pListenParent->Release();
  693. pListenParent = NULL;
  694. //
  695. // Multicast send endpoints are created using the user specified device address for the
  696. // device, and what the SP reports it's using for the multicast listen as the group
  697. // address.
  698. //
  699. pParent->Lock();
  700. DNASSERT(! pParent->IsCancelled());
  701. DNASSERT(! pParent->m_bilinkParent.IsEmpty());
  702. pAsyncOp = CONTAINING_OBJECT(pParent->m_bilinkParent.GetNext(),CAsyncOp,m_bilinkChildren);
  703. pAsyncOp->Lock();
  704. DNASSERT((! pAsyncOp->IsCancelled()) && (! pAsyncOp->IsComplete()));
  705. DNASSERT(pAsyncOp->m_bilinkChildren.GetNext() == &pParent->m_bilinkParent);
  706. hEndpoint = pAsyncOp->GetProtocolHandle();
  707. pAsyncOp->Unlock();
  708. pParent->Unlock();
  709. spInfoData.hEndpoint = hEndpoint;
  710. spInfoData.Flags = SP_GET_ADDRESS_INFO_MULTICAST_GROUP;
  711. if ((hResultCode = DNPGetListenAddressInfo(pdnObject->pdnProtocolData, spInfoData.hEndpoint,&spInfoData)) != DPN_OK)
  712. {
  713. DPFERR("Could not get LISTEN multicast group address!");
  714. DisplayDNError(0,hResultCode);
  715. DNASSERT(FALSE);
  716. goto Failure;
  717. }
  718. // Release the old group address and save this new one.
  719. IDirectPlay8Address_Release(pIGroup);
  720. pIGroup = spInfoData.pAddress;
  721. spInfoData.pAddress = NULL;
  722. //
  723. // If the user did not specify an adapter GUID, we selected one and we need to
  724. // copy that selection over to the connect operation's device address. If the user
  725. // did specify an adapter GUID, then this DNPGetListenAddressInfo will just be
  726. // echoing it back, so there's no harm in copying it in either case.
  727. //
  728. spInfoData.hEndpoint = hEndpoint;
  729. spInfoData.Flags = SP_GET_ADDRESS_INFO_LOCAL_ADAPTER;
  730. if ((hResultCode = DNPGetListenAddressInfo(pdnObject->pdnProtocolData, spInfoData.hEndpoint,&spInfoData)) != DPN_OK)
  731. {
  732. DPFERR("Could not get LISTEN device address!");
  733. DisplayDNError(0,hResultCode);
  734. DNASSERT(FALSE);
  735. goto Failure;
  736. }
  737. #ifndef DPNBUILD_ONLYONEADAPTER
  738. if ((hResultCode = IDirectPlay8Address_GetDevice(spInfoData.pAddress,&guidAdapter)) != DPN_OK)
  739. {
  740. DPFERR("Could not get LISTEN device GUID!");
  741. DisplayDNError(0,hResultCode);
  742. DNASSERT(FALSE);
  743. IDirectPlay8Address_Release(spInfoData.pAddress);
  744. spInfoData.pAddress = NULL;
  745. goto Failure;
  746. }
  747. if ((hResultCode = IDirectPlay8Address_SetDevice(pIDevice,&guidAdapter)) != DPN_OK)
  748. {
  749. DPFERR("Could not set CONNECT device GUID!");
  750. DisplayDNError(0,hResultCode);
  751. DNASSERT(FALSE);
  752. IDirectPlay8Address_Release(spInfoData.pAddress);
  753. spInfoData.pAddress = NULL;
  754. goto Failure;
  755. }
  756. #endif // ! DPNBUILD_ONLYONEADAPTER
  757. //
  758. // Keep device address and connect SP on DirectNet object
  759. //
  760. pSP->AddRef();
  761. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  762. pdnObject->pIDP8ADevice = spInfoData.pAddress; // Transfering reference
  763. spInfoData.pAddress = NULL;
  764. pdnObject->pConnectSP = pSP;
  765. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  766. pParent->Release();
  767. pParent = NULL;
  768. //
  769. // Create parent async op, which will be released when the ENTIRE connection is finished
  770. //
  771. if ((hResultCode = AsyncOpNew(pdnObject,&pConnectParent)) != DPN_OK)
  772. {
  773. DPFERR("Could not create AsyncOp");
  774. DisplayDNError(0,hResultCode);
  775. DNASSERT(FALSE);
  776. goto Failure;
  777. }
  778. pConnectParent->SetOpType( ASYNC_OP_CONNECT_MULTICAST_SEND );
  779. pConnectParent->MakeParent();
  780. pConnectParent->SetResult( DPNERR_NOCONNECTION );
  781. pConnectParent->SetCompletion( DNCompleteJoinOperation );
  782. // pConnectParent->SetReserved(1);
  783. if (dwFlags & DPNCONNECT_SYNC)
  784. {
  785. DPFX(DPFPREP, 5,"Sync operation - create sync event");
  786. if ((hResultCode = SyncEventNew(pdnObject,&pSyncEvent)) != DPN_OK)
  787. {
  788. DPFERR("Could not create synchronization event");
  789. DisplayDNError(0,hResultCode);
  790. DNASSERT(FALSE);
  791. goto Failure;
  792. }
  793. pConnectParent->SetSyncEvent( pSyncEvent );
  794. pConnectParent->SetResultPointer( &hrOperation );
  795. }
  796. else
  797. {
  798. DPFX(DPFPREP, 5,"Async operation - create handle parent");
  799. if ((hResultCode = DNCreateUserHandle(pdnObject,&pHandleParent)) != DPN_OK)
  800. {
  801. DPFERR("Could not create handle parent");
  802. DisplayDNError(0,hResultCode);
  803. DNASSERT(FALSE);
  804. goto Failure;
  805. }
  806. pHandleParent->SetContext( pvAsyncContext );
  807. pHandleParent->Lock();
  808. if (pHandleParent->IsCancelled())
  809. {
  810. pHandleParent->Unlock();
  811. pConnectParent->SetResult( DPNERR_USERCANCEL );
  812. hResultCode = DPNERR_USERCANCEL;
  813. goto Failure;
  814. }
  815. pConnectParent->MakeChild( pHandleParent );
  816. pHandleParent->Unlock();
  817. }
  818. hResultCode = DNPerformConnect(pdnObject,
  819. 0,
  820. pIDevice,
  821. pIGroup,
  822. pSP,
  823. DN_CONNECTFLAGS_MULTICAST_SEND,
  824. pConnectParent);
  825. if (hResultCode != DPN_OK)
  826. {
  827. DPFERR("Could not start CONNECT");
  828. goto Failure;
  829. }
  830. pConnectParent->Release();
  831. pConnectParent = NULL;
  832. pSP->Release();
  833. pSP = NULL;
  834. if (pIGroup)
  835. {
  836. IDirectPlay8Address_Release(pIGroup);
  837. pIGroup = NULL;
  838. }
  839. if (pIDevice)
  840. {
  841. IDirectPlay8Address_Release(pIDevice);
  842. pIDevice = NULL;
  843. }
  844. if (dwFlags & DPNCONNECT_SYNC)
  845. {
  846. if ((hResultCode = pSyncEvent->WaitForEvent()) != DPN_OK)
  847. {
  848. DPFERR("DNSyncEventWait() terminated bizarrely");
  849. DNASSERT(FALSE);
  850. }
  851. else
  852. {
  853. hResultCode = hrOperation;
  854. }
  855. pSyncEvent->ReturnSelfToPool();
  856. pSyncEvent = NULL;
  857. }
  858. else
  859. {
  860. pHandleParent->SetCompletion( DNCompleteUserJoin );
  861. if (phAsyncHandle)
  862. {
  863. *phAsyncHandle = pHandleParent->GetHandle();
  864. }
  865. pHandleParent->Release();
  866. pHandleParent = NULL;
  867. hResultCode = DPNERR_PENDING;
  868. }
  869. Exit:
  870. CallbackThread.Deinitialize();
  871. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  872. return(hResultCode);
  873. Failure:
  874. if (pIGroup)
  875. {
  876. IDirectPlay8Address_Release(pIGroup);
  877. pIGroup = NULL;
  878. }
  879. if (pIDevice)
  880. {
  881. IDirectPlay8Address_Release(pIDevice);
  882. pIDevice = NULL;
  883. }
  884. if (pExistingConnection != NULL)
  885. {
  886. pExistingConnection->Release();
  887. pExistingConnection = NULL;
  888. }
  889. if (pShareListenParent != NULL)
  890. {
  891. pShareListenParent->Unlock();
  892. pShareListenParent->Release();
  893. pShareListenParent = NULL;
  894. }
  895. if (pShareSP != NULL)
  896. {
  897. pShareSP->Release();
  898. pShareSP = NULL;
  899. }
  900. if (pShareDP8ServiceProvider != NULL)
  901. {
  902. IDP8ServiceProvider_Release(pShareDP8ServiceProvider);
  903. pShareDP8ServiceProvider = NULL;
  904. }
  905. if (pLocalDP8ServiceProvider != NULL)
  906. {
  907. IDP8ServiceProvider_Release(pLocalDP8ServiceProvider);
  908. pLocalDP8ServiceProvider = NULL;
  909. }
  910. if (pvNewInterface != NULL)
  911. {
  912. // Even if it's not an address, the Vtbl should be the same.
  913. IDirectPlay8Address_Release((IDirectPlay8Address*) pvNewInterface);
  914. pvNewInterface = NULL;
  915. }
  916. if (pSP)
  917. {
  918. pSP->Release();
  919. pSP = NULL;
  920. }
  921. if (pListenParent)
  922. {
  923. pListenParent->Release();
  924. pListenParent = NULL;
  925. }
  926. if (pListenParent)
  927. {
  928. pParent->Release();
  929. pParent = NULL;
  930. }
  931. if (pConnectParent)
  932. {
  933. if (SUCCEEDED(pdnObject->HandleTable.Destroy( pConnectParent->GetHandle(), NULL )))
  934. {
  935. // Release the HandleTable reference
  936. pConnectParent->Release();
  937. }
  938. pConnectParent->Release();
  939. pConnectParent = NULL;
  940. }
  941. if (pHandleParent)
  942. {
  943. pHandleParent->Release();
  944. pHandleParent = NULL;
  945. }
  946. if (pSyncEvent)
  947. {
  948. pSyncEvent->ReturnSelfToPool();
  949. pSyncEvent = NULL;
  950. }
  951. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  952. pListenParent = pdnObject->pListenParent;
  953. pdnObject->pListenParent = NULL;
  954. pSP = pdnObject->pConnectSP;
  955. pdnObject->pConnectSP = NULL;
  956. pIDevice = pdnObject->pIDP8ADevice;
  957. pdnObject->pIDP8ADevice = NULL;
  958. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  959. if (pListenParent)
  960. {
  961. DNCancelChildren(pdnObject,pListenParent);
  962. pListenParent->Release();
  963. pListenParent = NULL;
  964. }
  965. if (pSP)
  966. {
  967. pSP->Release();
  968. pSP = NULL;
  969. }
  970. if (pIDevice)
  971. {
  972. IDirectPlay8Address_Release(pIDevice);
  973. pIDevice = NULL;
  974. }
  975. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  976. pdnObject->dwFlags &= ~(DN_OBJECT_FLAG_CONNECTING|DN_OBJECT_FLAG_CONNECTED|DN_OBJECT_FLAG_LOCALHOST);
  977. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  978. goto Exit;
  979. } // DN_Join
  980. //
  981. // Completion for create sender context
  982. //
  983. #undef DPF_MODNAME
  984. #define DPF_MODNAME "DNCompleteCreateSenderContext"
  985. void DNCompleteCreateSenderContext(DIRECTNETOBJECT *const pdnObject,
  986. CAsyncOp *const pAsyncOp)
  987. {
  988. }
  989. //
  990. // Associate a context value with a given multicast sender's address
  991. //
  992. #undef DPF_MODNAME
  993. #define DPF_MODNAME "DN_CreateSenderContext"
  994. STDMETHODIMP DN_CreateSenderContext( IDirectPlay8Multicast *pInterface,
  995. IDirectPlay8Address *const pSenderAddress,
  996. void *const pvSenderContext,
  997. const DWORD dwFlags )
  998. {
  999. HRESULT hResultCode;
  1000. PDIRECTNETOBJECT pdnObject;
  1001. IDirectPlay8Address *pIDevice;
  1002. CServiceProvider *pSP;
  1003. CAsyncOp *pConnectParent;
  1004. CSyncEvent *pSyncEvent;
  1005. HRESULT hrConnect;
  1006. DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pSenderAddress [0x%p], pvSenderContext [0x%p], dwFlags [0x%lx]",
  1007. pInterface,pSenderAddress,pvSenderContext,dwFlags);
  1008. pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
  1009. DNASSERT(pdnObject != NULL);
  1010. #ifndef DPNBUILD_NOPARAMVAL
  1011. if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
  1012. {
  1013. if( FAILED( hResultCode = DN_ValidateCreateSenderContext( pInterface, pSenderAddress,
  1014. pvSenderContext, dwFlags ) ) )
  1015. {
  1016. DPFERR( "Error validating params" );
  1017. DPF_RETURN(hResultCode);
  1018. }
  1019. }
  1020. #endif // DPNBUILD_NOPARAMVAL
  1021. if( !(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED) )
  1022. {
  1023. DPFERR( "Object is not initialized" );
  1024. DPF_RETURN( DPNERR_UNINITIALIZED );
  1025. }
  1026. pIDevice = NULL;
  1027. pSP = NULL;
  1028. pConnectParent = NULL;
  1029. pSyncEvent = NULL;
  1030. #pragma BUGBUG( minara, "Need to ensure not closing" )
  1031. //
  1032. // Extract device and SP from DirectNet object
  1033. //
  1034. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  1035. DNASSERT( pdnObject->pConnectSP != NULL );
  1036. DNASSERT( pdnObject->pIDP8ADevice != NULL );
  1037. if (pdnObject->pConnectSP)
  1038. {
  1039. pdnObject->pConnectSP->AddRef();
  1040. pSP = pdnObject->pConnectSP;
  1041. }
  1042. if (pdnObject->pIDP8ADevice)
  1043. {
  1044. IDirectPlay8Address_AddRef(pdnObject->pIDP8ADevice);
  1045. pIDevice = pdnObject->pIDP8ADevice;
  1046. }
  1047. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  1048. if (pSP == NULL || pIDevice == NULL)
  1049. {
  1050. DPFERR("Invalid connect SP or device address");
  1051. hResultCode = DPNERR_GENERIC;
  1052. goto Failure;
  1053. }
  1054. //
  1055. // Create SyncEvent
  1056. //
  1057. if ((hResultCode = SyncEventNew(pdnObject,&pSyncEvent)) != DPN_OK)
  1058. {
  1059. DPFERR("Could not create SyncEvent");
  1060. goto Failure;
  1061. }
  1062. //
  1063. // Create AsyncOp parent
  1064. //
  1065. if ((hResultCode = AsyncOpNew(pdnObject,&pConnectParent)) != DPN_OK)
  1066. {
  1067. DPFERR("Could not create AsyncOp");
  1068. goto Failure;
  1069. }
  1070. pConnectParent->SetOpType( ASYNC_OP_CONNECT_MULTICAST_RECEIVE );
  1071. pConnectParent->SetSyncEvent( pSyncEvent );
  1072. pConnectParent->SetResultPointer( &hrConnect );
  1073. pConnectParent->SetContext( pvSenderContext );
  1074. //
  1075. // We will call connect on the Protocol to associate the sender's endpoint with a context
  1076. // This call to connect must be turned into a synchronous operation since this API call is synchronous
  1077. //
  1078. if ((hResultCode = DNPerformConnect(pdnObject,
  1079. 0,
  1080. pIDevice,
  1081. pSenderAddress,
  1082. pSP,
  1083. DN_CONNECTFLAGS_MULTICAST_RECEIVE,
  1084. pConnectParent)) != DPN_OK)
  1085. {
  1086. DPFERR("Failed to connect");
  1087. DisplayDNError(0,hResultCode);
  1088. goto Failure;
  1089. }
  1090. //
  1091. // Release references and wait for completion
  1092. //
  1093. pConnectParent->SetCompletion( DNCompleteCreateSenderContext );
  1094. pConnectParent->Release();
  1095. pConnectParent = NULL;
  1096. pSP->Release();
  1097. pSP = NULL;
  1098. IDirectPlay8Address_Release(pIDevice);
  1099. pIDevice = NULL;
  1100. pSyncEvent->WaitForEvent();
  1101. pSyncEvent->ReturnSelfToPool();
  1102. pSyncEvent = NULL;
  1103. if (hrConnect == DPN_OK)
  1104. {
  1105. DNUserCreateSenderContext(pdnObject,pvSenderContext);
  1106. }
  1107. hResultCode = hrConnect;
  1108. Exit:
  1109. DNASSERT( pIDevice == NULL );
  1110. DNASSERT( pSP == NULL );
  1111. DNASSERT( pConnectParent == NULL );
  1112. DNASSERT( pSyncEvent == NULL );
  1113. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  1114. return(hResultCode);
  1115. Failure:
  1116. if (pIDevice)
  1117. {
  1118. IDirectPlay8Address_Release(pIDevice);
  1119. pIDevice = NULL;
  1120. }
  1121. if (pSP)
  1122. {
  1123. pSP->Release();
  1124. pSP = NULL;
  1125. }
  1126. if (pConnectParent)
  1127. {
  1128. pConnectParent->Release();
  1129. pConnectParent = NULL;
  1130. }
  1131. if (pSyncEvent)
  1132. {
  1133. pSyncEvent->ReturnSelfToPool();
  1134. pSyncEvent = NULL;
  1135. }
  1136. goto Exit;
  1137. } // DN_CreateSenderContext
  1138. //
  1139. // Removes a previously associated context value from a given multicast sender's address
  1140. //
  1141. #undef DPF_MODNAME
  1142. #define DPF_MODNAME "DN_DestroySenderContext"
  1143. STDMETHODIMP DN_DestroySenderContext( IDirectPlay8Multicast *pInterface,
  1144. IDirectPlay8Address *const pSenderAddress,
  1145. const DWORD dwFlags )
  1146. {
  1147. HRESULT hResultCode;
  1148. DIRECTNETOBJECT *pdnObject;
  1149. CServiceProvider *pSP;
  1150. CConnection *pConnection;
  1151. IDirectPlay8Address *pDevice;
  1152. DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pSenderAddress [0x%p], dwFlags [0x%lx]",
  1153. pInterface,pSenderAddress,dwFlags);
  1154. pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
  1155. DNASSERT(pdnObject != NULL);
  1156. #ifndef DPNBUILD_NOPARAMVAL
  1157. if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
  1158. {
  1159. if( FAILED( hResultCode = DN_ValidateDestroySenderContext( pInterface, pSenderAddress, dwFlags ) ) )
  1160. {
  1161. DPFERR( "Error validating params" );
  1162. DPF_RETURN(hResultCode);
  1163. }
  1164. }
  1165. #endif // DPNBUILD_NOPARAMVAL
  1166. if( !(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED) )
  1167. {
  1168. DPFERR( "Object is not initialized" );
  1169. DPF_RETURN( DPNERR_UNINITIALIZED );
  1170. }
  1171. pSP = NULL;
  1172. pConnection = NULL;
  1173. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  1174. if (pdnObject->pIDP8ADevice)
  1175. {
  1176. IDirectPlay8Address_AddRef(pdnObject->pIDP8ADevice);
  1177. pDevice = pdnObject->pIDP8ADevice;
  1178. }
  1179. if (pdnObject->pConnectSP)
  1180. {
  1181. pdnObject->pConnectSP->AddRef();
  1182. pSP = pdnObject->pConnectSP;
  1183. }
  1184. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  1185. //
  1186. // Get endpoint from address
  1187. //
  1188. if ((hResultCode = DNPGetEndPointContextFromAddress(pdnObject->pdnProtocolData, pSP->GetHandle(),pSenderAddress,pDevice,reinterpret_cast<void**>(&pConnection))) == DPN_OK)
  1189. {
  1190. pConnection->AddRef();
  1191. pConnection->Disconnect();
  1192. pConnection->Release();
  1193. pConnection = NULL;
  1194. }
  1195. //
  1196. // Clean up
  1197. //
  1198. IDirectPlay8Address_Release(pDevice);
  1199. pDevice = NULL;
  1200. pSP->Release();
  1201. pSP = NULL;
  1202. hResultCode = DPN_OK;
  1203. DNASSERT( pSP == NULL );
  1204. DNASSERT( pConnection == NULL );
  1205. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  1206. return(hResultCode);
  1207. } // DN_DestroySenderContext
  1208. //
  1209. // Retrieves the current multicast group address
  1210. //
  1211. #undef DPF_MODNAME
  1212. #define DPF_MODNAME "DN_GetGroupAddress"
  1213. STDMETHODIMP DN_GetGroupAddress(IDirectPlay8Multicast *pInterface,
  1214. IDirectPlay8Address **const ppAddress,
  1215. const DWORD dwFlags)
  1216. {
  1217. HRESULT hResultCode;
  1218. DIRECTNETOBJECT *pdnObject;
  1219. CConnection *pConnection;
  1220. HANDLE hEndPt;
  1221. SPGETADDRESSINFODATA spInfoData;
  1222. CCallbackThread CallbackThread;
  1223. DPFX(DPFPREP, 2,"Parameters : pInterface [0x%p], ppAddress [0x%p], dwFlags [0x%lx]",
  1224. pInterface,ppAddress,dwFlags);
  1225. pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
  1226. DNASSERT(pdnObject != NULL);
  1227. #ifndef DPNBUILD_NOPARAMVAL
  1228. if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
  1229. {
  1230. if( FAILED( hResultCode = DN_ValidateGetGroupAddress( pInterface, ppAddress, dwFlags ) ) )
  1231. {
  1232. DPFX(DPFPREP, 0, "Error validating get group address info hr=[0x%lx]", hResultCode );
  1233. DPF_RETURN( hResultCode );
  1234. }
  1235. }
  1236. #endif // !DPNBUILD_NOPARAMVAL
  1237. // Check to ensure message handler registered
  1238. if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
  1239. {
  1240. DPFERR( "Object is not initialized" );
  1241. DPF_RETURN(DPNERR_UNINITIALIZED);
  1242. }
  1243. if( pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING )
  1244. {
  1245. DPFERR("Object is connecting / starting to host" );
  1246. DPF_RETURN(DPNERR_CONNECTING);
  1247. }
  1248. if ( !(pdnObject->dwFlags & (DN_OBJECT_FLAG_CONNECTED | DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING) ) )
  1249. {
  1250. DPFERR("You must be connected / disconnecting to use this function" );
  1251. DPF_RETURN(DPNERR_NOCONNECTION);
  1252. }
  1253. CallbackThread.Initialize();
  1254. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  1255. if (pdnObject->pMulticastSend != NULL)
  1256. {
  1257. pdnObject->pMulticastSend->AddRef();
  1258. pConnection = pdnObject->pMulticastSend;
  1259. }
  1260. else
  1261. {
  1262. pConnection = NULL;
  1263. }
  1264. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  1265. if (pConnection == NULL)
  1266. {
  1267. DPFERR( "Couldn't retrieve multicast send connection" );
  1268. hResultCode = DPNERR_INVALIDGROUP;
  1269. goto Failure;
  1270. }
  1271. //
  1272. // Get the remote multicast address address
  1273. //
  1274. if ((hResultCode = pConnection->GetEndPt(&hEndPt,&CallbackThread)) != DPN_OK)
  1275. {
  1276. DPFERR( "Couldn't retrieve multicast send endpoint" );
  1277. DisplayDNError(0, hResultCode);
  1278. goto Failure;
  1279. }
  1280. spInfoData.Flags = SP_GET_ADDRESS_INFO_MULTICAST_GROUP;
  1281. hResultCode = DNPCrackEndPointDescriptor(pdnObject->pdnProtocolData, hEndPt,&spInfoData);
  1282. if (hResultCode != DPN_OK)
  1283. {
  1284. DPFERR("Unknown error from DNPCrackEndPointDescriptor");
  1285. DisplayDNError(0,hResultCode);
  1286. DNASSERT(FALSE);
  1287. // Drop through...
  1288. }
  1289. pConnection->ReleaseEndPt(&CallbackThread);
  1290. pConnection->Release();
  1291. pConnection = NULL;
  1292. *ppAddress = spInfoData.pAddress;
  1293. spInfoData.pAddress = NULL;
  1294. Exit:
  1295. CallbackThread.Deinitialize();
  1296. DPF_RETURN(hResultCode);
  1297. Failure:
  1298. if (pConnection)
  1299. {
  1300. pConnection->Release();
  1301. pConnection = NULL;
  1302. }
  1303. goto Exit;
  1304. } // DN_GetGroupAddress
  1305. //
  1306. // Enumerate multicast scopes reported by SP
  1307. //
  1308. #undef DPF_MODNAME
  1309. #define DPF_MODNAME "DN_EnumMulticastScopes"
  1310. STDMETHODIMP DN_EnumMulticastScopes( IDirectPlay8Multicast *pInterface,
  1311. const GUID *const pguidServiceProvider,
  1312. const GUID *const pguidDevice,
  1313. const GUID *const pguidApplication,
  1314. DPN_MULTICAST_SCOPE_INFO *const pScopeInfoBuffer,
  1315. DWORD *const pcbEnumData,
  1316. DWORD *const pcReturned,
  1317. const DWORD dwFlags )
  1318. {
  1319. HRESULT hResultCode;
  1320. PDIRECTNETOBJECT pdnObject;
  1321. DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pguidServiceProvider [0x%p], pguidDevice [0x%p], pguidApplication [0x%p], pScopeInfoBuffer [0x%p], pcbEnumData [0x%p], pcReturned [0x%p], dwFlags [0x%lx]",
  1322. pInterface,pguidServiceProvider,pguidDevice,pguidApplication,pScopeInfoBuffer,pcbEnumData,pcReturned,dwFlags);
  1323. pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
  1324. DNASSERT(pdnObject != NULL);
  1325. #ifndef DPNBUILD_NOPARAMVAL
  1326. if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
  1327. {
  1328. if( FAILED( hResultCode = DN_ValidateEnumMulticastScopes( pInterface, pguidServiceProvider, pguidDevice,
  1329. pguidApplication, pScopeInfoBuffer,
  1330. pcbEnumData, pcReturned, dwFlags ) ) )
  1331. {
  1332. DPFERR( "Error validating params" );
  1333. DPF_RETURN(hResultCode);
  1334. }
  1335. }
  1336. #endif // DPNBUILD_NOPARAMVAL
  1337. if( !(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED) )
  1338. {
  1339. DPFERR( "Object is not initialized" );
  1340. DPF_RETURN( DPNERR_UNINITIALIZED );
  1341. }
  1342. hResultCode = DN_EnumMulticastScopes(pdnObject,
  1343. dwFlags,
  1344. #ifndef DPNBUILD_ONLYONESP
  1345. pguidServiceProvider,
  1346. #endif // ! DPNBUILD_ONLYONESP
  1347. #ifndef DPNBUILD_ONLYONEADAPTER
  1348. pguidDevice,
  1349. #endif // ! DPNBUILD_ONLYONEADAPTER
  1350. #ifndef DPNBUILD_LIBINTERFACE
  1351. pguidApplication,
  1352. #endif // ! DPNBUILD_LIBINTERFACE
  1353. pScopeInfoBuffer,
  1354. pcbEnumData,
  1355. pcReturned);
  1356. DPFX(DPFPREP, 3,"Set: *pcbEnumData [%ld], *pcReturned [%ld]",*pcbEnumData,*pcReturned);
  1357. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  1358. return(hResultCode);
  1359. } // DN_EnumMulticastScopes
  1360. #endif // ! DPNBUILD_NOMULTICAST