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.

3687 lines
96 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Request.cpp
  6. * Content: Requested operations
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 03/18/00 mjn Created
  12. * 04/16/00 mjn DNSendMessage uses CAsyncOp
  13. * 04/19/00 mjn Update NameTable operations to use DN_WORKER_JOB_SEND_NAMETABLE_OPERATION
  14. * 04/24/00 mjn Updated Group and Info operations to use CAsyncOp's
  15. * 05/03/00 mjn Use GetHostPlayerRef() rather than GetHostPlayer()
  16. * 05/16/00 mjn Better locking during User notifications
  17. * 05/31/00 mjn Added operation specific SYNC flags
  18. * 06/26/00 mjn Replaced DPNADDCLIENTTOGROUP_SYNC DPNADDPLAYERTOGROUP_SYNC
  19. * mjn Replaced DPNREMOVECLIENTFROMGROUP_SYNC with DPNREMOVEPLAYERFROMGROUP_SYNC
  20. * 07/26/00 mjn Fixed locking problem with CAsyncOp::MakeChild()
  21. * 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  22. * 08/05/00 mjn Added pParent to DNSendGroupMessage and DNSendMessage()
  23. * mjn Added DNProcessFailedRequest()
  24. * 08/06/00 mjn Added CWorkerJob
  25. * 08/07/00 mjn Added DNRequestIntegrityCheck(),DNHostCheckIntegrity(),DNProcessCheckIntegrity(),DNHostFixIntegrity()
  26. * 08/08/00 mjn Mark groups created after CREATE_GROUP
  27. * 08/09/00 mjn Made requests and host operations more robust for host migration
  28. * 08/15/00 mjn Keep request operations if HostPlayer or connection is unavailable
  29. * 09/05/00 mjn Removed dwIndex from CNameTable::InsertEntry()
  30. * 09/13/00 mjn Perform queued operations after creating group in DNConnectToHost2()
  31. * 09/26/00 mjn Removed locking from CNameTable::SetVersion() and CNameTable::GetNewVersion()
  32. * 10/10/00 mjn Return DPN_OK from Host operations if unable to get reference on local player
  33. * 10/13/00 mjn Update version if FindPlayer fails in DNProcessXXX() functions
  34. * 01/09/01 mjn Prevent asynchronous group/info operations from being cancelled
  35. * 01/25/01 mjn Fixed 64-bit alignment problem in received messages
  36. * 04/13/01 mjn Remove requests from request list when operations received from host
  37. * 07/24/01 mjn Added DPNBUILD_NOSERVER compile flag
  38. *@@END_MSINTERNAL
  39. *
  40. ***************************************************************************/
  41. #include "dncorei.h"
  42. //**********************************************************************
  43. // Constant definitions
  44. //**********************************************************************
  45. //**********************************************************************
  46. // Macro definitions
  47. //**********************************************************************
  48. //**********************************************************************
  49. // Structure definitions
  50. //**********************************************************************
  51. //**********************************************************************
  52. // Variable definitions
  53. //**********************************************************************
  54. //**********************************************************************
  55. // Function prototypes
  56. //**********************************************************************
  57. //**********************************************************************
  58. // Function definitions
  59. //**********************************************************************
  60. #undef DPF_MODNAME
  61. #define DPF_MODNAME "DNRequestWorker"
  62. HRESULT DNRequestWorker(DIRECTNETOBJECT *const pdnObject,
  63. DWORD dwMsgId,
  64. CRefCountBuffer* pRefCountBuffer,
  65. void *const pvRequestContext,
  66. void *const pvUserContext,
  67. DPNHANDLE *const phAsyncOp,
  68. const DWORD dwFlags)
  69. {
  70. HRESULT hResultCode;
  71. CAsyncOp *pRequest;
  72. CAsyncOp *pHandleParent;
  73. CSyncEvent *pSyncEvent;
  74. CNameTableEntry *pHostPlayer;
  75. CConnection *pConnection;
  76. HRESULT volatile hrOperation;
  77. pRequest = NULL;
  78. pHandleParent = NULL;
  79. pSyncEvent = NULL;
  80. pHostPlayer = NULL;
  81. pConnection = NULL;
  82. //
  83. // Create synchronization event if necessary
  84. //
  85. DBG_CASSERT(DPNOP_SYNC == DPNCREATEGROUP_SYNC);
  86. DBG_CASSERT(DPNOP_SYNC == DPNDESTROYGROUP_SYNC);
  87. DBG_CASSERT(DPNOP_SYNC == DPNADDPLAYERTOGROUP_SYNC);
  88. DBG_CASSERT(DPNOP_SYNC == DPNREMOVEPLAYERFROMGROUP_SYNC);
  89. DBG_CASSERT(DPNOP_SYNC == DPNSETGROUPINFO_SYNC);
  90. DBG_CASSERT(DPNOP_SYNC == DPNSETCLIENTINFO_SYNC);
  91. DBG_CASSERT(DPNOP_SYNC == DPNSETSERVERINFO_SYNC);
  92. DBG_CASSERT(DPNOP_SYNC == DPNSETPEERINFO_SYNC);
  93. if (dwFlags & DPNOP_SYNC)
  94. {
  95. if ((hResultCode = SyncEventNew(pdnObject,&pSyncEvent)) != DPN_OK)
  96. {
  97. DPFERR("Could not create synchronization event");
  98. DisplayDNError(0,hResultCode);
  99. DNASSERT(FALSE);
  100. goto Failure;
  101. }
  102. }
  103. else
  104. {
  105. if ((hResultCode = DNCreateUserHandle(pdnObject,&pHandleParent)) != DPN_OK)
  106. {
  107. DPFERR("Could not create user HANDLE");
  108. DisplayDNError(0,hResultCode);
  109. DNASSERT(FALSE);
  110. goto Failure;
  111. }
  112. }
  113. //
  114. // Get host connection for request operation.
  115. // We will procede even if we can't get it, just so that the operation will be re-tried at host migration
  116. // or cancelled at close
  117. //
  118. if ((hResultCode = pdnObject->NameTable.GetHostPlayerRef( &pHostPlayer )) == DPN_OK)
  119. {
  120. if ((hResultCode = pHostPlayer->GetConnectionRef( &pConnection )) != DPN_OK)
  121. {
  122. DPFERR("Could not get host connection reference");
  123. DisplayDNError(0,hResultCode);
  124. }
  125. pHostPlayer->Release();
  126. pHostPlayer = NULL;
  127. }
  128. else
  129. {
  130. DPFERR("Could not find Host player");
  131. DisplayDNError(0,hResultCode);
  132. }
  133. //
  134. // Send request
  135. //
  136. hResultCode = DNPerformRequest( pdnObject,
  137. dwMsgId,
  138. pRefCountBuffer->BufferDescAddress(),
  139. pConnection,
  140. pHandleParent,
  141. &pRequest );
  142. if (pConnection)
  143. {
  144. pConnection->Release();
  145. pConnection = NULL;
  146. }
  147. //
  148. // Wait for SyncEvent or create async user HANDLE
  149. //
  150. pRequest->SetContext( pvRequestContext );
  151. if (dwFlags & DPNOP_SYNC)
  152. {
  153. pRequest->SetSyncEvent( pSyncEvent );
  154. pRequest->SetResultPointer( &hrOperation );
  155. pRequest->Release();
  156. pRequest = NULL;
  157. pSyncEvent->WaitForEvent();
  158. pSyncEvent->ReturnSelfToPool();
  159. pSyncEvent = NULL;
  160. hResultCode = hrOperation;
  161. }
  162. else
  163. {
  164. pRequest->Release();
  165. pRequest = NULL;
  166. if (phAsyncOp)
  167. {
  168. *phAsyncOp = pHandleParent->GetHandle();
  169. }
  170. pHandleParent->SetCompletion( DNCompleteAsyncHandle );
  171. pHandleParent->SetContext( pvUserContext );
  172. pHandleParent->SetCannotCancel();
  173. pHandleParent->Release();
  174. pHandleParent = NULL;
  175. hResultCode = DPNERR_PENDING;
  176. }
  177. Exit:
  178. return(hResultCode);
  179. Failure:
  180. if (pHostPlayer)
  181. {
  182. pHostPlayer->Release();
  183. pHostPlayer = NULL;
  184. }
  185. if (pConnection)
  186. {
  187. pConnection->Release();
  188. pConnection = NULL;
  189. }
  190. if (pRequest)
  191. {
  192. pRequest->Release();
  193. pRequest = NULL;
  194. }
  195. if (pHandleParent)
  196. {
  197. pHandleParent->Release();
  198. pHandleParent = NULL;
  199. }
  200. if (pSyncEvent)
  201. {
  202. pSyncEvent->ReturnSelfToPool();
  203. pSyncEvent = NULL;
  204. }
  205. goto Exit;
  206. }
  207. #undef DPF_MODNAME
  208. #define DPF_MODNAME "DNRequestCreateGroup"
  209. HRESULT DNRequestCreateGroup(DIRECTNETOBJECT *const pdnObject,
  210. const PWSTR pwszName,
  211. const DWORD dwNameSize,
  212. const PVOID pvData,
  213. const DWORD dwDataSize,
  214. const DWORD dwGroupFlags,
  215. void *const pvGroupContext,
  216. void *const pvUserContext,
  217. DPNHANDLE *const phAsyncOp,
  218. const DWORD dwFlags)
  219. {
  220. HRESULT hResultCode;
  221. CRefCountBuffer *pRefCountBuffer;
  222. CPackedBuffer packedBuffer;
  223. DN_INTERNAL_MESSAGE_REQ_CREATE_GROUP *pMsg;
  224. DPFX(DPFPREP, 4,"Parameters: pwszName [%ls], pvData [0x%p], dwDataSize [%ld], dwGroupFlags [0x%lx], pvUserContext [0x%p], dwFlags [0x%lx]",
  225. pwszName,pvData,dwDataSize,dwGroupFlags,pvUserContext,dwFlags);
  226. DNASSERT(pdnObject != NULL);
  227. pRefCountBuffer = NULL;
  228. //
  229. // Create REQUEST
  230. //
  231. // Create buffer
  232. hResultCode = RefCountBufferNew(pdnObject,
  233. sizeof(DN_INTERNAL_MESSAGE_REQ_CREATE_GROUP) + dwNameSize + dwDataSize,
  234. MemoryBlockAlloc,
  235. MemoryBlockFree,
  236. &pRefCountBuffer);
  237. if (hResultCode != DPN_OK)
  238. {
  239. DPFERR("Could not create new RefCountBuffer");
  240. DisplayDNError(0,hResultCode);
  241. DNASSERT(FALSE);
  242. goto Failure;
  243. }
  244. packedBuffer.Initialize(pRefCountBuffer->GetBufferAddress(),pRefCountBuffer->GetBufferSize());
  245. pMsg = static_cast<DN_INTERNAL_MESSAGE_REQ_CREATE_GROUP*>(packedBuffer.GetHeadAddress());
  246. if ((hResultCode = packedBuffer.AddToFront(NULL,sizeof(DN_INTERNAL_MESSAGE_REQ_CREATE_GROUP))) != DPN_OK)
  247. {
  248. DPFERR("Could not reserve space at front of buffer");
  249. DisplayDNError(0,hResultCode);
  250. DNASSERT(FALSE);
  251. goto Failure;
  252. }
  253. // Flags
  254. pMsg->dwGroupFlags = dwGroupFlags;
  255. pMsg->dwInfoFlags = 0;
  256. // Add Name
  257. if (dwNameSize)
  258. {
  259. if ((hResultCode = packedBuffer.AddToBack(pwszName,dwNameSize)) != DPN_OK)
  260. {
  261. DPFERR("Could not add Name to packed buffer");
  262. DisplayDNError(0,hResultCode);
  263. DNASSERT(FALSE);
  264. goto Failure;
  265. }
  266. pMsg->dwNameOffset = packedBuffer.GetTailOffset();
  267. pMsg->dwNameSize = dwNameSize;
  268. pMsg->dwInfoFlags |= DPNINFO_NAME;
  269. }
  270. else
  271. {
  272. pMsg->dwNameOffset = 0;
  273. pMsg->dwNameSize = 0;
  274. }
  275. // Add Data
  276. if (dwDataSize)
  277. {
  278. if ((hResultCode = packedBuffer.AddToBack(pvData,dwDataSize)) != DPN_OK)
  279. {
  280. DPFERR("Could not add Data to packed buffer");
  281. DisplayDNError(0,hResultCode);
  282. DNASSERT(FALSE);
  283. goto Failure;
  284. }
  285. pMsg->dwDataOffset = packedBuffer.GetTailOffset();
  286. pMsg->dwDataSize = dwDataSize;
  287. pMsg->dwInfoFlags |= DPNINFO_DATA;
  288. }
  289. else
  290. {
  291. pMsg->dwDataOffset = 0;
  292. pMsg->dwDataSize = 0;
  293. }
  294. // Test against FAILED so DPNSUCCESS_PENDING doesn't show up as a failure
  295. if (FAILED(hResultCode = DNRequestWorker(pdnObject, DN_MSG_INTERNAL_REQ_CREATE_GROUP, pRefCountBuffer, pvGroupContext, pvUserContext, phAsyncOp, dwFlags)))
  296. {
  297. DPFERR("Could not perform request");
  298. DisplayDNError(0,hResultCode);
  299. DNASSERT(FALSE);
  300. goto Failure;
  301. }
  302. Exit:
  303. if (pRefCountBuffer)
  304. {
  305. pRefCountBuffer->Release();
  306. pRefCountBuffer = NULL;
  307. }
  308. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  309. return(hResultCode);
  310. Failure:
  311. goto Exit;
  312. }
  313. #undef DPF_MODNAME
  314. #define DPF_MODNAME "DNRequestDestroyGroup"
  315. HRESULT DNRequestDestroyGroup(DIRECTNETOBJECT *const pdnObject,
  316. const DPNID dpnidGroup,
  317. PVOID const pvUserContext,
  318. DPNHANDLE *const phAsyncOp,
  319. const DWORD dwFlags)
  320. {
  321. HRESULT hResultCode;
  322. CRefCountBuffer *pRefCountBuffer;
  323. DN_INTERNAL_MESSAGE_REQ_DESTROY_GROUP *pMsg;
  324. DPFX(DPFPREP, 4,"Parameters: dpnidGroup [0x%lx], pvUserContext [0x%p], phAsyncOp [0x%p], dwFlags [0x%lx]",
  325. dpnidGroup,pvUserContext,phAsyncOp,dwFlags);
  326. DNASSERT(pdnObject != NULL);
  327. DNASSERT(dpnidGroup != 0);
  328. pRefCountBuffer = NULL;
  329. //
  330. // Create REQUEST
  331. //
  332. hResultCode = RefCountBufferNew(pdnObject,
  333. sizeof(DN_INTERNAL_MESSAGE_REQ_DESTROY_GROUP),
  334. MemoryBlockAlloc,
  335. MemoryBlockFree,
  336. &pRefCountBuffer);
  337. if (hResultCode != DPN_OK)
  338. {
  339. DPFERR("Could not allocate count buffer (request destroy group)");
  340. DisplayDNError(0,hResultCode);
  341. DNASSERT(FALSE);
  342. goto Failure;
  343. }
  344. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_DESTROY_GROUP*>(pRefCountBuffer->GetBufferAddress());
  345. pMsg->dpnidGroup = dpnidGroup;
  346. // Test against FAILED so DPNSUCCESS_PENDING doesn't show up as a failure
  347. if (FAILED(hResultCode = DNRequestWorker(pdnObject, DN_MSG_INTERNAL_REQ_DESTROY_GROUP, pRefCountBuffer, NULL, pvUserContext, phAsyncOp, dwFlags)))
  348. {
  349. DPFERR("Could not perform request");
  350. DisplayDNError(0,hResultCode);
  351. DNASSERT(FALSE);
  352. goto Failure;
  353. }
  354. Exit:
  355. if (pRefCountBuffer)
  356. {
  357. pRefCountBuffer->Release();
  358. pRefCountBuffer = NULL;
  359. }
  360. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  361. return(hResultCode);
  362. Failure:
  363. goto Exit;
  364. }
  365. #undef DPF_MODNAME
  366. #define DPF_MODNAME "DNRequestAddPlayerToGroup"
  367. HRESULT DNRequestAddPlayerToGroup(DIRECTNETOBJECT *const pdnObject,
  368. const DPNID dpnidGroup,
  369. const DPNID dpnidPlayer,
  370. PVOID const pvUserContext,
  371. DPNHANDLE *const phAsyncOp,
  372. const DWORD dwFlags)
  373. {
  374. HRESULT hResultCode;
  375. CRefCountBuffer *pRefCountBuffer;
  376. CPackedBuffer packedBuffer;
  377. DN_INTERNAL_MESSAGE_REQ_ADD_PLAYER_TO_GROUP *pMsg;
  378. DPFX(DPFPREP, 4,"Parameters: dpnidGroup [0x%lx], dpnidPlayer [0x%lx], pvUserContext [0x%p], phAsyncOp [0x%p], dwFlags [0x%lx]",
  379. dpnidGroup,dpnidPlayer,pvUserContext,phAsyncOp,dwFlags);
  380. DNASSERT(pdnObject != NULL);
  381. DNASSERT(dpnidGroup != 0);
  382. pRefCountBuffer = NULL;
  383. //
  384. // Create REQUEST
  385. //
  386. hResultCode = RefCountBufferNew(pdnObject,
  387. sizeof(DN_INTERNAL_MESSAGE_REQ_ADD_PLAYER_TO_GROUP),
  388. MemoryBlockAlloc,
  389. MemoryBlockFree,
  390. &pRefCountBuffer);
  391. if (hResultCode != DPN_OK)
  392. {
  393. DPFERR("Could not allocate count buffer (request destroy group)");
  394. DisplayDNError(0,hResultCode);
  395. DNASSERT(FALSE);
  396. goto Failure;
  397. }
  398. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_ADD_PLAYER_TO_GROUP*>(pRefCountBuffer->GetBufferAddress());
  399. pMsg->dpnidGroup = dpnidGroup;
  400. pMsg->dpnidPlayer = dpnidPlayer;
  401. // Test against FAILED so DPNSUCCESS_PENDING doesn't show up as a failure
  402. if (FAILED(hResultCode = DNRequestWorker(pdnObject, DN_MSG_INTERNAL_REQ_ADD_PLAYER_TO_GROUP, pRefCountBuffer, NULL, pvUserContext, phAsyncOp, dwFlags)))
  403. {
  404. DPFERR("Could not perform request");
  405. DisplayDNError(0,hResultCode);
  406. DNASSERT(FALSE);
  407. goto Failure;
  408. }
  409. Exit:
  410. if (pRefCountBuffer)
  411. {
  412. pRefCountBuffer->Release();
  413. pRefCountBuffer = NULL;
  414. }
  415. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  416. return(hResultCode);
  417. Failure:
  418. goto Exit;
  419. }
  420. #undef DPF_MODNAME
  421. #define DPF_MODNAME "DNRequestDeletePlayerFromGroup"
  422. HRESULT DNRequestDeletePlayerFromGroup(DIRECTNETOBJECT *const pdnObject,
  423. const DPNID dpnidGroup,
  424. const DPNID dpnidPlayer,
  425. PVOID const pvUserContext,
  426. DPNHANDLE *const phAsyncOp,
  427. const DWORD dwFlags)
  428. {
  429. HRESULT hResultCode;
  430. CRefCountBuffer *pRefCountBuffer;
  431. CPackedBuffer packedBuffer;
  432. DN_INTERNAL_MESSAGE_REQ_DELETE_PLAYER_FROM_GROUP *pMsg;
  433. DPFX(DPFPREP, 4,"Parameters: dpnidGroup [0x%lx], dpnidPlayer [0x%lx], pvUserContext [0x%p], phAsyncOp [0x%p], dwFlags [0x%lx]",
  434. dpnidGroup,dpnidPlayer,pvUserContext,phAsyncOp,dwFlags);
  435. DNASSERT(pdnObject != NULL);
  436. DNASSERT(dpnidGroup != 0);
  437. pRefCountBuffer = NULL;
  438. //
  439. // Create REQUEST
  440. //
  441. hResultCode = RefCountBufferNew(pdnObject,
  442. sizeof(DN_INTERNAL_MESSAGE_REQ_DELETE_PLAYER_FROM_GROUP),
  443. MemoryBlockAlloc,
  444. MemoryBlockFree,
  445. &pRefCountBuffer);
  446. if (hResultCode != DPN_OK)
  447. {
  448. DPFERR("Could not allocate count buffer (request destroy group)");
  449. DisplayDNError(0,hResultCode);
  450. DNASSERT(FALSE);
  451. goto Failure;
  452. }
  453. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_DELETE_PLAYER_FROM_GROUP*>(pRefCountBuffer->GetBufferAddress());
  454. pMsg->dpnidGroup = dpnidGroup;
  455. pMsg->dpnidPlayer = dpnidPlayer;
  456. // Test against FAILED so DPNSUCCESS_PENDING doesn't show up as a failure
  457. if (FAILED(hResultCode = DNRequestWorker(pdnObject, DN_MSG_INTERNAL_REQ_DELETE_PLAYER_FROM_GROUP, pRefCountBuffer, NULL, pvUserContext, phAsyncOp, dwFlags)))
  458. {
  459. DPFERR("Could not perform request");
  460. DisplayDNError(0,hResultCode);
  461. DNASSERT(FALSE);
  462. goto Failure;
  463. }
  464. Exit:
  465. if (pRefCountBuffer)
  466. {
  467. pRefCountBuffer->Release();
  468. pRefCountBuffer = NULL;
  469. }
  470. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  471. return(hResultCode);
  472. Failure:
  473. goto Exit;
  474. }
  475. #undef DPF_MODNAME
  476. #define DPF_MODNAME "DNRequestUpdateInfo"
  477. HRESULT DNRequestUpdateInfo(DIRECTNETOBJECT *const pdnObject,
  478. const DPNID dpnid,
  479. const PWSTR pwszName,
  480. const DWORD dwNameSize,
  481. const PVOID pvData,
  482. const DWORD dwDataSize,
  483. const DWORD dwInfoFlags,
  484. PVOID const pvUserContext,
  485. DPNHANDLE *const phAsyncOp,
  486. const DWORD dwFlags)
  487. {
  488. HRESULT hResultCode;
  489. CRefCountBuffer *pRefCountBuffer;
  490. CPackedBuffer packedBuffer;
  491. DN_INTERNAL_MESSAGE_REQ_UPDATE_INFO *pMsg;
  492. DPFX(DPFPREP, 4,"Parameters: pwszName [0x%p], pvData [0x%p], dwInfoFlags [%ld], dwGroupFlags [0x%lx], pvUserContext [0x%p], dwFlags [0x%lx]",
  493. pwszName,pvData,dwDataSize,dwInfoFlags,pvUserContext,dwFlags);
  494. DNASSERT(pdnObject != NULL);
  495. pRefCountBuffer = NULL;
  496. //
  497. // Create REQUEST
  498. //
  499. // Create buffer
  500. hResultCode = RefCountBufferNew(pdnObject,
  501. sizeof(DN_INTERNAL_MESSAGE_REQ_UPDATE_INFO) + dwNameSize + dwDataSize,
  502. MemoryBlockAlloc,
  503. MemoryBlockFree,
  504. &pRefCountBuffer);
  505. if (hResultCode != DPN_OK)
  506. {
  507. DPFERR("Could not create new RefCountBuffer");
  508. DisplayDNError(0,hResultCode);
  509. DNASSERT(FALSE);
  510. goto Failure;
  511. }
  512. packedBuffer.Initialize(pRefCountBuffer->GetBufferAddress(),pRefCountBuffer->GetBufferSize());
  513. pMsg = static_cast<DN_INTERNAL_MESSAGE_REQ_UPDATE_INFO*>(packedBuffer.GetHeadAddress());
  514. if ((hResultCode = packedBuffer.AddToFront(NULL,sizeof(DN_INTERNAL_MESSAGE_REQ_UPDATE_INFO))) != DPN_OK)
  515. {
  516. DPFERR("Could not reserve space at front of buffer");
  517. DisplayDNError(0,hResultCode);
  518. DNASSERT(FALSE);
  519. goto Failure;
  520. }
  521. // Add Name
  522. if ((dwInfoFlags & DPNINFO_NAME) && dwNameSize)
  523. {
  524. if ((hResultCode = packedBuffer.AddToBack(pwszName,dwNameSize)) != DPN_OK)
  525. {
  526. DPFERR("Could not add Name to packed buffer");
  527. DisplayDNError(0,hResultCode);
  528. DNASSERT(FALSE);
  529. goto Failure;
  530. }
  531. pMsg->dwNameOffset = packedBuffer.GetTailOffset();
  532. pMsg->dwNameSize = dwNameSize;
  533. }
  534. else
  535. {
  536. pMsg->dwNameOffset = 0;
  537. pMsg->dwNameSize = 0;
  538. }
  539. // Add Data
  540. if ((dwInfoFlags & DPNINFO_DATA) && dwDataSize)
  541. {
  542. if ((hResultCode = packedBuffer.AddToBack(pvData,dwDataSize)) != DPN_OK)
  543. {
  544. DPFERR("Could not add Data to packed buffer");
  545. DisplayDNError(0,hResultCode);
  546. DNASSERT(FALSE);
  547. goto Failure;
  548. }
  549. pMsg->dwDataOffset = packedBuffer.GetTailOffset();
  550. pMsg->dwDataSize = dwDataSize;
  551. }
  552. else
  553. {
  554. pMsg->dwDataOffset = 0;
  555. pMsg->dwDataSize = 0;
  556. }
  557. // Remaining fields
  558. pMsg->dpnid = dpnid;
  559. pMsg->dwInfoFlags = dwInfoFlags;
  560. // Test against FAILED so DPNSUCCESS_PENDING doesn't show up as a failure
  561. if (FAILED(hResultCode = DNRequestWorker(pdnObject, DN_MSG_INTERNAL_REQ_UPDATE_INFO, pRefCountBuffer, NULL, pvUserContext, phAsyncOp, dwFlags)))
  562. {
  563. DPFERR("Could not perform request");
  564. DisplayDNError(0,hResultCode);
  565. goto Failure;
  566. }
  567. Exit:
  568. if (pRefCountBuffer)
  569. {
  570. pRefCountBuffer->Release();
  571. pRefCountBuffer = NULL;
  572. }
  573. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  574. return(hResultCode);
  575. Failure:
  576. goto Exit;
  577. }
  578. // DNRequestIntegrityCheck
  579. //
  580. // In the case where a non-host player detects a disconnect from another non-host player,
  581. // the detecting player will request the host to perform an integrity check to prevent a
  582. // disjoint game from occurring. The host will ping the disconnected player, and if a
  583. // response is received, the host will disconnect the detecting player. If no response
  584. // is received, presumably the disconnected player is in fact dropping, and a DESTROY_PLAYER
  585. // message will be sent out.
  586. #undef DPF_MODNAME
  587. #define DPF_MODNAME "DNRequestIntegrityCheck"
  588. HRESULT DNRequestIntegrityCheck(DIRECTNETOBJECT *const pdnObject,
  589. const DPNID dpnidTarget)
  590. {
  591. HRESULT hResultCode;
  592. CRefCountBuffer *pRefCountBuffer;
  593. CNameTableEntry *pHostPlayer;
  594. CNameTableEntry *pNTEntry;
  595. CConnection *pConnection;
  596. CAsyncOp *pRequest;
  597. DN_INTERNAL_MESSAGE_REQ_INTEGRITY_CHECK *pMsg;
  598. DPFX(DPFPREP, 6,"Parameters: dpnidTarget [0x%lx]",dpnidTarget);
  599. pRefCountBuffer = NULL;
  600. pHostPlayer = NULL;
  601. pNTEntry = NULL;
  602. pConnection = NULL;
  603. pRequest = NULL;
  604. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  605. if (pdnObject->dwFlags & (DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING))
  606. {
  607. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  608. DPFERR("Closing - aborting");
  609. hResultCode = DPN_OK;
  610. goto Failure;
  611. }
  612. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  613. //
  614. // Determine if player is still in NameTable - maybe the Host has already deleted him
  615. //
  616. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnidTarget,&pNTEntry)) != DPN_OK)
  617. {
  618. DPFERR("Target player not in NameTable");
  619. DisplayDNError(0,hResultCode);
  620. hResultCode = DPN_OK;
  621. goto Failure;
  622. }
  623. pNTEntry->Lock();
  624. if (!pNTEntry->IsAvailable())
  625. {
  626. pNTEntry->Unlock();
  627. hResultCode = DPN_OK;
  628. goto Failure;
  629. }
  630. pNTEntry->Unlock();
  631. pNTEntry->Release();
  632. pNTEntry = NULL;
  633. //
  634. // Create request message
  635. //
  636. hResultCode = RefCountBufferNew(pdnObject,
  637. sizeof(DN_INTERNAL_MESSAGE_REQ_INTEGRITY_CHECK),
  638. MemoryBlockAlloc,
  639. MemoryBlockFree,
  640. &pRefCountBuffer);
  641. if (hResultCode != DPN_OK)
  642. {
  643. DPFERR("Could not create RefCountBuffer");
  644. DisplayDNError(0,hResultCode);
  645. goto Failure;
  646. }
  647. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_INTEGRITY_CHECK*>(pRefCountBuffer->GetBufferAddress());
  648. pMsg->dpnidTarget = dpnidTarget;
  649. //
  650. // Get host connection for request operation
  651. //
  652. if ((hResultCode = pdnObject->NameTable.GetHostPlayerRef( &pHostPlayer )) != DPN_OK)
  653. {
  654. DPFERR("Could not get host player reference");
  655. DisplayDNError(0,hResultCode);
  656. goto Failure;
  657. }
  658. if ((hResultCode = pHostPlayer->GetConnectionRef( &pConnection )) != DPN_OK)
  659. {
  660. DPFERR("Could not get host connection reference");
  661. DisplayDNError(0,hResultCode);
  662. goto Failure;
  663. }
  664. pHostPlayer->Release();
  665. pHostPlayer = NULL;
  666. //
  667. // Send request
  668. //
  669. if ((hResultCode = DNPerformRequest(pdnObject,
  670. DN_MSG_INTERNAL_REQ_INTEGRITY_CHECK,
  671. pRefCountBuffer->BufferDescAddress(),
  672. pConnection,
  673. NULL,
  674. &pRequest)) != DPNERR_PENDING)
  675. {
  676. DPFERR("Could not perform request (INTEGRITY_CHECK)");
  677. DisplayDNError(0,hResultCode);
  678. goto Failure;
  679. }
  680. pConnection->Release();
  681. pConnection = NULL;
  682. pRefCountBuffer->Release();
  683. pRefCountBuffer = NULL;
  684. pRequest->Release();
  685. pRequest = NULL;
  686. hResultCode = DPN_OK;
  687. Exit:
  688. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  689. return(hResultCode);
  690. Failure:
  691. if (pRefCountBuffer)
  692. {
  693. pRefCountBuffer->Release();
  694. pRefCountBuffer = NULL;
  695. }
  696. if (pNTEntry)
  697. {
  698. pNTEntry->Release();
  699. pNTEntry = NULL;
  700. }
  701. if (pHostPlayer)
  702. {
  703. pHostPlayer->Release();
  704. pHostPlayer = NULL;
  705. }
  706. if (pConnection)
  707. {
  708. pConnection->Release();
  709. pConnection = NULL;
  710. }
  711. if (pRequest)
  712. {
  713. pRequest->Release();
  714. pRequest = NULL;
  715. }
  716. goto Exit;
  717. }
  718. // HOST OPERATIONS
  719. //
  720. // The Host will perform an operation and if in PEER mode, will inform
  721. // other players of the operation. These messages will contain the
  722. // DPNID of the player requesting the operation along with the HANDLE
  723. // supplied with the request.
  724. #undef DPF_MODNAME
  725. #define DPF_MODNAME "DNHostProcessRequest"
  726. HRESULT DNHostProcessRequest(DIRECTNETOBJECT *const pdnObject,
  727. const DWORD dwMsgId,
  728. PVOID const pv,
  729. const DPNID dpnidRequesting)
  730. {
  731. HRESULT hResultCode;
  732. UNALIGNED DN_INTERNAL_MESSAGE_REQ_PROCESS_COMPLETION *pRequest;
  733. DPFX(DPFPREP, 6,"Parameters: dwMsgId [0x%lx], pv [0x%p], dpnidRequesting [0x%lx]",
  734. dwMsgId,pv,dpnidRequesting);
  735. DNASSERT(pdnObject != NULL);
  736. DNASSERT(pv != NULL);
  737. DNASSERT(dpnidRequesting != 0);
  738. pRequest = static_cast<DN_INTERNAL_MESSAGE_REQ_PROCESS_COMPLETION*>(pv);
  739. switch(dwMsgId)
  740. {
  741. case DN_MSG_INTERNAL_REQ_CREATE_GROUP:
  742. {
  743. UNALIGNED DN_INTERNAL_MESSAGE_REQ_CREATE_GROUP *pCreateGroup;
  744. PWSTR pwszName;
  745. PVOID pvData;
  746. DPFX(DPFPREP, 7,"DN_MSG_INTERNAL_REQ_CREATE_GROUP");
  747. pCreateGroup = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_CREATE_GROUP*>(pRequest + 1);
  748. if (pCreateGroup->dwNameSize)
  749. {
  750. pwszName = reinterpret_cast<WCHAR*>(reinterpret_cast<BYTE*>(pCreateGroup) + pCreateGroup->dwNameOffset);
  751. }
  752. else
  753. {
  754. pwszName = NULL;
  755. }
  756. if (pCreateGroup->dwDataSize)
  757. {
  758. pvData = static_cast<void*>(reinterpret_cast<BYTE*>(pCreateGroup) + pCreateGroup->dwDataOffset);
  759. }
  760. else
  761. {
  762. pvData = NULL;
  763. }
  764. DNHostCreateGroup( pdnObject,
  765. pwszName,
  766. pCreateGroup->dwNameSize,
  767. pvData,
  768. pCreateGroup->dwDataSize,
  769. pCreateGroup->dwInfoFlags,
  770. pCreateGroup->dwGroupFlags,
  771. NULL,
  772. NULL,
  773. dpnidRequesting,
  774. pRequest->hCompletionOp,
  775. NULL,
  776. 0 );
  777. break;
  778. }
  779. case DN_MSG_INTERNAL_REQ_DESTROY_GROUP:
  780. {
  781. UNALIGNED DN_INTERNAL_MESSAGE_REQ_DESTROY_GROUP *pDestroyGroup;
  782. DPFX(DPFPREP, 7,"DN_MSG_INTERNAL_REQ_DESTROY_GROUP");
  783. pDestroyGroup = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_DESTROY_GROUP*>(pRequest + 1);
  784. DNHostDestroyGroup( pdnObject,
  785. pDestroyGroup->dpnidGroup,
  786. NULL,
  787. dpnidRequesting,
  788. pRequest->hCompletionOp,
  789. NULL,
  790. 0 );
  791. break;
  792. }
  793. case DN_MSG_INTERNAL_REQ_ADD_PLAYER_TO_GROUP:
  794. {
  795. UNALIGNED DN_INTERNAL_MESSAGE_REQ_ADD_PLAYER_TO_GROUP *pAddPlayerToGroup;
  796. DPFX(DPFPREP, 7,"DN_MSG_INTERNAL_REQ_ADD_PLAYER_TO_GROUP");
  797. pAddPlayerToGroup = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_ADD_PLAYER_TO_GROUP*>(pRequest + 1);
  798. DNHostAddPlayerToGroup( pdnObject,
  799. pAddPlayerToGroup->dpnidGroup,
  800. pAddPlayerToGroup->dpnidPlayer,
  801. NULL,
  802. dpnidRequesting,
  803. pRequest->hCompletionOp,
  804. NULL,
  805. 0 );
  806. break;
  807. }
  808. case DN_MSG_INTERNAL_REQ_DELETE_PLAYER_FROM_GROUP:
  809. {
  810. UNALIGNED DN_INTERNAL_MESSAGE_REQ_DELETE_PLAYER_FROM_GROUP *pDeletePlayerFromGroup;
  811. DPFX(DPFPREP, 7,"DN_MSG_INTERNAL_REQ_DELETE_PLAYER_FROM_GROUP");
  812. pDeletePlayerFromGroup = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_DELETE_PLAYER_FROM_GROUP*>(pRequest + 1);
  813. DNHostDeletePlayerFromGroup(pdnObject,
  814. pDeletePlayerFromGroup->dpnidGroup,
  815. pDeletePlayerFromGroup->dpnidPlayer,
  816. NULL,
  817. dpnidRequesting,
  818. pRequest->hCompletionOp,
  819. NULL,
  820. 0);
  821. break;
  822. }
  823. case DN_MSG_INTERNAL_REQ_UPDATE_INFO:
  824. {
  825. UNALIGNED DN_INTERNAL_MESSAGE_REQ_UPDATE_INFO *pUpdateInfo;
  826. PWSTR pwszName;
  827. PVOID pvData;
  828. DPFX(DPFPREP, 7,"DN_MSG_INTERNAL_REQ_UPDATE_INFO");
  829. pUpdateInfo = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_UPDATE_INFO*>(pRequest + 1);
  830. if (pUpdateInfo->dwNameSize)
  831. {
  832. pwszName = reinterpret_cast<WCHAR*>(reinterpret_cast<BYTE*>(pUpdateInfo) + pUpdateInfo->dwNameOffset);
  833. }
  834. else
  835. {
  836. pwszName = NULL;
  837. }
  838. if (pUpdateInfo->dwDataSize)
  839. {
  840. pvData = reinterpret_cast<void*>(reinterpret_cast<BYTE*>(pUpdateInfo) + pUpdateInfo->dwDataOffset);
  841. }
  842. else
  843. {
  844. pvData = NULL;
  845. }
  846. DNHostUpdateInfo(pdnObject,
  847. pUpdateInfo->dpnid,
  848. pwszName,
  849. pUpdateInfo->dwNameSize,
  850. pvData,
  851. pUpdateInfo->dwDataSize,
  852. pUpdateInfo->dwInfoFlags,
  853. NULL,
  854. dpnidRequesting,
  855. pRequest->hCompletionOp,
  856. NULL,
  857. 0);
  858. break;
  859. }
  860. case DN_MSG_INTERNAL_REQ_INTEGRITY_CHECK:
  861. {
  862. UNALIGNED DN_INTERNAL_MESSAGE_REQ_INTEGRITY_CHECK *pIntegrityCheck;
  863. CNameTableEntry *pLocalPlayer;
  864. DPFX(DPFPREP, 7,"DN_MSG_INTERNAL_REQ_INTEGRITY_CHECK");
  865. pIntegrityCheck = reinterpret_cast<DN_INTERNAL_MESSAGE_REQ_INTEGRITY_CHECK*>(pRequest + 1);
  866. //
  867. // If we submitted this request, this is being called during host migration,
  868. // so remove it from the handle table since we will destroy the dropped player anyways.
  869. // Otherwise, we will perform the integrity check
  870. //
  871. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) == DPN_OK)
  872. {
  873. if (pLocalPlayer->GetDPNID() == dpnidRequesting)
  874. {
  875. CAsyncOp* pAsyncOp;
  876. if (SUCCEEDED(pdnObject->HandleTable.Destroy( pRequest->hCompletionOp, (PVOID*)&pAsyncOp )))
  877. {
  878. // Release the HandleTable reference
  879. pAsyncOp->Release();
  880. }
  881. }
  882. else
  883. {
  884. DNHostCheckIntegrity(pdnObject,pIntegrityCheck->dpnidTarget,dpnidRequesting);
  885. }
  886. pLocalPlayer->Release();
  887. pLocalPlayer = NULL;
  888. }
  889. break;
  890. }
  891. default:
  892. {
  893. DPFERR("How did we get here ?");
  894. DNASSERT(FALSE);
  895. }
  896. }
  897. DPFX(DPFPREP, 6,"Returning: DPN_OK");
  898. return(DPN_OK);
  899. }
  900. #undef DPF_MODNAME
  901. #define DPF_MODNAME "DNHostFailRequest"
  902. void DNHostFailRequest(DIRECTNETOBJECT *const pdnObject,
  903. const DPNID dpnid,
  904. const DPNHANDLE hCompletionOp,
  905. const HRESULT hr)
  906. {
  907. HRESULT hResultCode;
  908. CNameTableEntry *pNTEntry;
  909. CRefCountBuffer *pRefCountBuffer;
  910. CConnection *pConnection;
  911. DN_INTERNAL_MESSAGE_REQUEST_FAILED *pMsg;
  912. DNASSERT(pdnObject != NULL);
  913. DNASSERT(dpnid != NULL);
  914. pNTEntry = NULL;
  915. pRefCountBuffer = NULL;
  916. pConnection = NULL;
  917. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnid,&pNTEntry)) != DPN_OK)
  918. {
  919. DPFERR("Could not find NameTableEntry");
  920. DisplayDNError(0,hResultCode);
  921. goto Failure;
  922. }
  923. hResultCode = RefCountBufferNew(pdnObject,
  924. sizeof(DN_INTERNAL_MESSAGE_REQUEST_FAILED),
  925. MemoryBlockAlloc,
  926. MemoryBlockFree,
  927. &pRefCountBuffer);
  928. if (hResultCode != DPN_OK)
  929. {
  930. DPFERR("Could not create new RefCountBuffer");
  931. DisplayDNError(0,hResultCode);
  932. DNASSERT(FALSE);
  933. goto Failure;
  934. }
  935. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_REQUEST_FAILED*>(pRefCountBuffer->GetBufferAddress());
  936. pMsg->hCompletionOp = hCompletionOp;
  937. pMsg->hResultCode = hr;
  938. if ((hResultCode = pNTEntry->GetConnectionRef( &pConnection )) == DPN_OK)
  939. {
  940. hResultCode = DNSendMessage(pdnObject,
  941. pConnection,
  942. DN_MSG_INTERNAL_REQUEST_FAILED,
  943. dpnid,
  944. pRefCountBuffer->BufferDescAddress(),
  945. 1,
  946. pRefCountBuffer,
  947. 0,
  948. DN_SENDFLAGS_RELIABLE,
  949. NULL,
  950. NULL);
  951. pConnection->Release();
  952. pConnection = NULL;
  953. }
  954. pNTEntry->Release();
  955. pNTEntry = NULL;
  956. pRefCountBuffer->Release();
  957. pRefCountBuffer = NULL;
  958. Exit:
  959. return;
  960. Failure:
  961. if (pNTEntry)
  962. {
  963. pNTEntry->Release();
  964. pNTEntry = NULL;
  965. }
  966. if (pRefCountBuffer)
  967. {
  968. pRefCountBuffer->Release();
  969. pRefCountBuffer = NULL;
  970. }
  971. goto Exit;
  972. }
  973. #undef DPF_MODNAME
  974. #define DPF_MODNAME "DNHostCreateGroup"
  975. HRESULT DNHostCreateGroup(DIRECTNETOBJECT *const pdnObject,
  976. PWSTR pwszName,
  977. const DWORD dwNameSize,
  978. void *const pvData,
  979. const DWORD dwDataSize,
  980. const DWORD dwInfoFlags,
  981. const DWORD dwGroupFlags,
  982. void *const pvGroupContext,
  983. void *const pvUserContext,
  984. const DPNID dpnidOwner,
  985. const DPNHANDLE hCompletionOp,
  986. DPNHANDLE *const phAsyncOp,
  987. const DWORD dwFlags)
  988. {
  989. HRESULT hResultCode;
  990. HRESULT hrOperation;
  991. void *pvContext;
  992. BOOL fHostRequested;
  993. CNameTableEntry *pLocalPlayer;
  994. CNameTableEntry *pNTEntry;
  995. CPackedBuffer packedBuffer;
  996. CRefCountBuffer *pRefCountBuffer;
  997. CAsyncOp *pHandleParent;
  998. CAsyncOp *pRequest;
  999. CWorkerJob *pWorkerJob;
  1000. DN_INTERNAL_MESSAGE_CREATE_GROUP *pMsg;
  1001. DPFX(DPFPREP, 4,"Parameters: pwszName [0x%p], dwNameSize [%ld], pvData [0x%p], dwDataSize [%ld], dwInfoFlags [0x%lx], dwGroupFlags [0x%lx], pvGroupContext [0x%p], pvUserContext [0x%p], dpnidOwner [0x%lx], hCompletionOp [0x%lx], phAsyncOp [0x%p], dwFlags [0x%lx]",
  1002. pwszName,dwNameSize,pvData,dwDataSize,dwInfoFlags,dwGroupFlags,pvGroupContext,pvUserContext,dpnidOwner,hCompletionOp,phAsyncOp,dwFlags);
  1003. DNASSERT(pdnObject != NULL);
  1004. //
  1005. // If this is called from DN_CreateGroup(),
  1006. // hCompletion=0
  1007. // dpnidOwner = DPNID of Host
  1008. // pvGroupContext is valid
  1009. // pvUserContext is valid
  1010. //
  1011. // If this is called by a REQUEST,
  1012. // hCompletion = REQUEST handle of requesting player
  1013. // dpnidOwner = DPNID of requesting player
  1014. // pvGroupContext is not valid
  1015. //
  1016. // If this is called at HostMigration,
  1017. // hCompletion = REQUEST handle on THIS (now Host) player
  1018. // dpnidOwner = DPNID of THIS (now Host) player
  1019. // pvGroupContext is invalid
  1020. // pvUserContext is invalid
  1021. //
  1022. pLocalPlayer = NULL;
  1023. pNTEntry = NULL;
  1024. pRefCountBuffer = NULL;
  1025. pWorkerJob = NULL;
  1026. pHandleParent = NULL;
  1027. pRequest = NULL;
  1028. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  1029. {
  1030. DPFERR("Could not get local player reference");
  1031. DisplayDNError(0,hResultCode);
  1032. return(DPN_OK); // Ignore and continue (!)
  1033. }
  1034. if (pLocalPlayer->GetDPNID() == dpnidOwner)
  1035. {
  1036. fHostRequested = TRUE;
  1037. }
  1038. else
  1039. {
  1040. fHostRequested = FALSE;
  1041. }
  1042. pLocalPlayer->Release();
  1043. pLocalPlayer = NULL;
  1044. //
  1045. // Get group context if this is a Host Migration re-try by finding REQUEST AsyncOp
  1046. //
  1047. if ((fHostRequested) && (hCompletionOp != 0))
  1048. {
  1049. if ((hResultCode = pdnObject->HandleTable.Find( hCompletionOp,(PVOID*)&pRequest )) != DPN_OK)
  1050. {
  1051. DPFERR("Could not find REQUEST AsyncOp");
  1052. DisplayDNError(0,hResultCode);
  1053. DNASSERT(FALSE);
  1054. goto Failure;
  1055. }
  1056. else
  1057. {
  1058. // We would normally AddRef pRequest in the success case, but since we need to release it
  1059. // next we will eliminate both.
  1060. }
  1061. pvContext = pRequest->GetContext();
  1062. // pRequest->Release(); // Don't need since we are balancing with HandleTable ref
  1063. pRequest = NULL;
  1064. }
  1065. else
  1066. {
  1067. pvContext = pvGroupContext;
  1068. }
  1069. //
  1070. // Create and fill in NameTableEntry
  1071. //
  1072. if ((hResultCode = NameTableEntryNew(pdnObject,&pNTEntry)) != DPN_OK)
  1073. {
  1074. DPFERR("Could not create new NameTableEntry");
  1075. DisplayDNError(0,hResultCode);
  1076. DNASSERT(FALSE);
  1077. goto Failure;
  1078. }
  1079. pNTEntry->MakeGroup();
  1080. // This function takes the lock internally
  1081. pNTEntry->UpdateEntryInfo(pwszName,dwNameSize,pvData,dwDataSize,dwInfoFlags, FALSE);
  1082. pNTEntry->SetOwner( dpnidOwner );
  1083. pNTEntry->SetContext( pvContext );
  1084. if (dwGroupFlags & DPNGROUP_AUTODESTRUCT)
  1085. {
  1086. pNTEntry->MakeAutoDestructGroup();
  1087. }
  1088. //
  1089. // Add Group to NameTable
  1090. //
  1091. #pragma TODO(minara,"Check to see if Autodestruct owner is still in NameTable")
  1092. #pragma TODO(minara,"This should happen after getting a NameTable version number - as DESTROY player will clean up")
  1093. #pragma TODO(minara,"We should send out a NOP in this case")
  1094. hrOperation = pdnObject->NameTable.AddEntry(pNTEntry);
  1095. if (hrOperation != DPN_OK)
  1096. {
  1097. DPFERR("Could not add NameTableEntry to NameTable");
  1098. DisplayDNError(0,hResultCode);
  1099. if (!fHostRequested)
  1100. {
  1101. DNHostFailRequest(pdnObject,dpnidOwner,hCompletionOp,hrOperation);
  1102. }
  1103. }
  1104. else
  1105. {
  1106. BOOL fNotify;
  1107. fNotify = FALSE;
  1108. pNTEntry->Lock();
  1109. if (!pNTEntry->IsAvailable() && !pNTEntry->IsDisconnecting())
  1110. {
  1111. pNTEntry->MakeAvailable();
  1112. pNTEntry->NotifyAddRef();
  1113. pNTEntry->NotifyAddRef();
  1114. pNTEntry->SetInUse();
  1115. fNotify = TRUE;
  1116. }
  1117. pNTEntry->Unlock();
  1118. if (fNotify)
  1119. {
  1120. DNUserCreateGroup(pdnObject,pNTEntry);
  1121. pNTEntry->PerformQueuedOperations();
  1122. pdnObject->NameTable.PopulateGroup( pNTEntry );
  1123. }
  1124. //
  1125. // Send CREATE_GROUP message
  1126. //
  1127. if (pdnObject->dwFlags & DN_OBJECT_FLAG_PEER)
  1128. {
  1129. // Determine size of message
  1130. packedBuffer.Initialize(NULL,0);
  1131. packedBuffer.AddToFront(NULL,sizeof(DN_INTERNAL_MESSAGE_CREATE_GROUP));
  1132. pNTEntry->PackEntryInfo(&packedBuffer);
  1133. // Create buffer
  1134. if ((hResultCode = RefCountBufferNew(pdnObject,packedBuffer.GetSizeRequired(),MemoryBlockAlloc,MemoryBlockFree,&pRefCountBuffer)) != DPN_OK)
  1135. {
  1136. DPFERR("Could not create RefCountBuffer");
  1137. DisplayDNError(0,hResultCode);
  1138. DNASSERT(FALSE);
  1139. goto Failure;
  1140. }
  1141. packedBuffer.Initialize(pRefCountBuffer->GetBufferAddress(),pRefCountBuffer->GetBufferSize());
  1142. pMsg = static_cast<DN_INTERNAL_MESSAGE_CREATE_GROUP*>(packedBuffer.GetHeadAddress());
  1143. if ((hResultCode = packedBuffer.AddToFront(NULL,sizeof(DN_INTERNAL_MESSAGE_CREATE_GROUP))) != DPN_OK)
  1144. {
  1145. DPFERR("Could not reserve front of buffer");
  1146. DisplayDNError(0,hResultCode);
  1147. DNASSERT(FALSE);
  1148. goto Failure;
  1149. }
  1150. if ((hResultCode = pNTEntry->PackEntryInfo(&packedBuffer)) != DPN_OK)
  1151. {
  1152. DPFERR("Could not pack NameTableEntry");
  1153. DisplayDNError(0,hResultCode);
  1154. DNASSERT(FALSE);
  1155. goto Failure;
  1156. }
  1157. pMsg->dpnidRequesting = dpnidOwner;
  1158. pMsg->hCompletionOp = hCompletionOp;
  1159. //
  1160. // SEND CreateGroup messages via WorkerThread
  1161. //
  1162. if ((hResultCode = WorkerJobNew(pdnObject,&pWorkerJob)) != DPN_OK)
  1163. {
  1164. DPFERR("Could not create new WorkerJob");
  1165. DisplayDNError(0,hResultCode);
  1166. DNASSERT(FALSE);
  1167. goto Failure;
  1168. }
  1169. pWorkerJob->SetJobType( WORKER_JOB_SEND_NAMETABLE_OPERATION );
  1170. pWorkerJob->SetSendNameTableOperationMsgId( DN_MSG_INTERNAL_CREATE_GROUP );
  1171. pWorkerJob->SetSendNameTableOperationVersion( pNTEntry->GetVersion() );
  1172. pWorkerJob->SetSendNameTableOperationDPNIDExclude( 0 );
  1173. pWorkerJob->SetRefCountBuffer( pRefCountBuffer );
  1174. DNQueueWorkerJob(pdnObject,pWorkerJob);
  1175. pWorkerJob = NULL;
  1176. pRefCountBuffer->Release();
  1177. pRefCountBuffer = NULL;
  1178. }
  1179. }
  1180. pNTEntry->Release();
  1181. pNTEntry = NULL;
  1182. //
  1183. // If this was called by the local (Host) player,
  1184. // Check to see if this was an original operation or a re-try from HostMigration
  1185. //
  1186. // If this was an original operation,
  1187. // See if we need an Async HANDLE for the user
  1188. // Otherwise
  1189. // Clean up the outstanding operation
  1190. //
  1191. if (fHostRequested)
  1192. {
  1193. if (hCompletionOp == 0) // Original
  1194. {
  1195. //
  1196. // If this fails, or is synchronous, return the operation result immediately
  1197. //
  1198. if (!(dwFlags & DPNCREATEGROUP_SYNC) && (hrOperation == DPN_OK))
  1199. {
  1200. if ((hResultCode = DNCreateUserHandle(pdnObject,&pHandleParent)) != DPN_OK)
  1201. {
  1202. DPFERR("Could not create Async HANDLE");
  1203. DisplayDNError(0,hResultCode);
  1204. DNASSERT(FALSE);
  1205. goto Failure;
  1206. }
  1207. pHandleParent->SetCompletion( DNCompleteAsyncHandle );
  1208. pHandleParent->SetContext( pvUserContext );
  1209. pHandleParent->SetResult( hrOperation );
  1210. pHandleParent->SetCannotCancel();
  1211. *phAsyncOp = pHandleParent->GetHandle();
  1212. pHandleParent->Release();
  1213. pHandleParent = NULL;
  1214. hResultCode = DPNERR_PENDING;
  1215. }
  1216. else
  1217. {
  1218. hResultCode = hrOperation;
  1219. }
  1220. }
  1221. else // Host Migration re-try
  1222. {
  1223. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pRequest )))
  1224. {
  1225. pRequest->SetResult( hrOperation );
  1226. // Release the HandleTable reference
  1227. pRequest->Release();
  1228. }
  1229. pRequest = NULL;
  1230. hResultCode = DPN_OK;
  1231. }
  1232. }
  1233. else
  1234. {
  1235. hResultCode = DPN_OK;
  1236. }
  1237. Exit:
  1238. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  1239. return(hResultCode);
  1240. Failure:
  1241. if (!fHostRequested)
  1242. {
  1243. DNHostFailRequest(pdnObject,dpnidOwner,hCompletionOp,hrOperation);
  1244. }
  1245. else
  1246. {
  1247. //
  1248. // If a completion op was specified and this was requested by the Host, this is a
  1249. // retry of an operation during Host migration. In this case, we want to set the
  1250. // result (failure code) of the completion op, and remove it from the HandleTable.
  1251. //
  1252. if (hCompletionOp)
  1253. {
  1254. CAsyncOp *pHostCompletionOp;
  1255. pHostCompletionOp = NULL;
  1256. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pHostCompletionOp )))
  1257. {
  1258. pHostCompletionOp->SetResult( hResultCode );
  1259. // Release the HandleTable reference
  1260. pHostCompletionOp->Release();
  1261. }
  1262. pHostCompletionOp = NULL;
  1263. DNASSERT(pHostCompletionOp == NULL);
  1264. }
  1265. }
  1266. if (pHandleParent)
  1267. {
  1268. pHandleParent->Release();
  1269. pHandleParent = NULL;
  1270. }
  1271. if (pRequest)
  1272. {
  1273. pRequest->Release();
  1274. pRequest = NULL;
  1275. }
  1276. if (pRefCountBuffer)
  1277. {
  1278. pRefCountBuffer->Release();
  1279. pRefCountBuffer = NULL;
  1280. }
  1281. if (pNTEntry)
  1282. {
  1283. pNTEntry->Release();
  1284. pNTEntry = NULL;
  1285. }
  1286. if (pLocalPlayer)
  1287. {
  1288. pLocalPlayer->Release();
  1289. pLocalPlayer = NULL;
  1290. }
  1291. goto Exit;
  1292. }
  1293. #undef DPF_MODNAME
  1294. #define DPF_MODNAME "DNHostDestroyGroup"
  1295. HRESULT DNHostDestroyGroup(DIRECTNETOBJECT *const pdnObject,
  1296. const DPNID dpnid,
  1297. void *const pvUserContext,
  1298. const DPNID dpnidRequesting,
  1299. const DPNHANDLE hCompletionOp,
  1300. DPNHANDLE *const phAsyncOp,
  1301. const DWORD dwFlags)
  1302. {
  1303. HRESULT hResultCode;
  1304. HRESULT hrOperation;
  1305. DWORD dwVersion;
  1306. BOOL fHostRequested;
  1307. CNameTableEntry *pLocalPlayer;
  1308. CRefCountBuffer *pRefCountBuffer;
  1309. CAsyncOp *pHandleParent;
  1310. CWorkerJob *pWorkerJob;
  1311. DN_INTERNAL_MESSAGE_DESTROY_GROUP *pMsg;
  1312. DPFX(DPFPREP, 4,"Parameters: dpnid [0x%lx], pvUserContext [0x%p], dpnidRequesting [0x%lx], hCompletionOp [0x%lx], phAsyncOp [0x%p], dwFlags [0x%lx]",
  1313. dpnid,pvUserContext,dpnidRequesting,hCompletionOp,phAsyncOp,dwFlags);
  1314. DNASSERT(pdnObject != NULL);
  1315. DNASSERT(dpnid != 0);
  1316. DNASSERT(dpnidRequesting != 0);
  1317. //
  1318. // If this is called from DN_DestroyGroup(),
  1319. // hCompletion=0
  1320. // dpnidRequesting = DPNID of Host
  1321. // pvUserContext is valid
  1322. //
  1323. // If this is called by a REQUEST,
  1324. // hCompletion = REQUEST handle of requesting player
  1325. // dpnidRequesting = DPNID of requesting player
  1326. // pvUserContext is not valid
  1327. //
  1328. // If this is called at HostMigration,
  1329. // hCompletion = REQUEST handle on THIS (now Host) player
  1330. // dpnidRequesting = DPNID of THIS (now Host) player
  1331. // pvUserContext is invalid
  1332. //
  1333. pLocalPlayer = NULL;
  1334. pRefCountBuffer = NULL;
  1335. pHandleParent = NULL;
  1336. pWorkerJob = NULL;
  1337. //
  1338. // Determine if this is being requested by the Host
  1339. //
  1340. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  1341. {
  1342. DPFERR("Could not get local player reference");
  1343. DisplayDNError(0,hResultCode);
  1344. return(DPN_OK); // Ignore and continue (!)
  1345. }
  1346. if (pLocalPlayer->GetDPNID() == dpnidRequesting)
  1347. {
  1348. fHostRequested = TRUE;
  1349. }
  1350. else
  1351. {
  1352. fHostRequested = FALSE;
  1353. }
  1354. pLocalPlayer->Release();
  1355. pLocalPlayer = NULL;
  1356. //
  1357. // Remove Group from NameTable
  1358. //
  1359. dwVersion = 0;
  1360. hrOperation = pdnObject->NameTable.DeleteGroup(dpnid,&dwVersion);
  1361. if (hrOperation != DPN_OK)
  1362. {
  1363. DPFERR("Could not delete group from NameTable");
  1364. DisplayDNError(0,hResultCode);
  1365. if (!fHostRequested)
  1366. {
  1367. DNHostFailRequest(pdnObject,dpnidRequesting,hCompletionOp,hrOperation);
  1368. }
  1369. }
  1370. else
  1371. {
  1372. //
  1373. // Send DESTROY_GROUP message
  1374. //
  1375. if (pdnObject->dwFlags & DN_OBJECT_FLAG_PEER)
  1376. {
  1377. // Create buffer
  1378. if ((hResultCode = RefCountBufferNew(pdnObject,sizeof(DN_INTERNAL_MESSAGE_DESTROY_GROUP),MemoryBlockAlloc,MemoryBlockFree,&pRefCountBuffer)) != DPN_OK)
  1379. {
  1380. DPFERR("Could not create RefCountBuffer");
  1381. DisplayDNError(0,hResultCode);
  1382. DNASSERT(FALSE);
  1383. goto Failure;
  1384. }
  1385. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_DESTROY_GROUP*>(pRefCountBuffer->GetBufferAddress());
  1386. pMsg->dpnidGroup = dpnid;
  1387. pMsg->dwVersion = dwVersion;
  1388. pMsg->dwVersionNotUsed = 0;
  1389. pMsg->dpnidRequesting = dpnidRequesting;
  1390. pMsg->hCompletionOp = hCompletionOp;
  1391. //
  1392. // SEND DestroyGroup messages via WorkerThread
  1393. //
  1394. if ((hResultCode = WorkerJobNew(pdnObject,&pWorkerJob)) != DPN_OK)
  1395. {
  1396. DPFERR("Could not create new WorkerJob");
  1397. DisplayDNError(0,hResultCode);
  1398. DNASSERT(FALSE);
  1399. goto Failure;
  1400. }
  1401. pWorkerJob->SetJobType( WORKER_JOB_SEND_NAMETABLE_OPERATION );
  1402. pWorkerJob->SetSendNameTableOperationMsgId( DN_MSG_INTERNAL_DESTROY_GROUP );
  1403. pWorkerJob->SetSendNameTableOperationVersion( dwVersion );
  1404. pWorkerJob->SetSendNameTableOperationDPNIDExclude( 0 );
  1405. pWorkerJob->SetRefCountBuffer( pRefCountBuffer );
  1406. DNQueueWorkerJob(pdnObject,pWorkerJob);
  1407. pWorkerJob = NULL;
  1408. pRefCountBuffer->Release();
  1409. pRefCountBuffer = NULL;
  1410. }
  1411. }
  1412. //
  1413. // If this was called by the local (Host) player,
  1414. // Check to see if this was an original operation or a re-try from HostMigration
  1415. //
  1416. // If this was an original operation,
  1417. // See if we need an Async HANDLE for the user
  1418. // Otherwise
  1419. // Clean up the outstanding operation
  1420. //
  1421. if (fHostRequested)
  1422. {
  1423. if (hCompletionOp == 0) // Original
  1424. {
  1425. //
  1426. // If this fails, or is synchronous, return the operation result immediately
  1427. //
  1428. if (!(dwFlags & DPNDESTROYGROUP_SYNC) && (hrOperation == DPN_OK))
  1429. {
  1430. if ((hResultCode = DNCreateUserHandle(pdnObject,&pHandleParent)) != DPN_OK)
  1431. {
  1432. DPFERR("Could not create Async HANDLE");
  1433. DisplayDNError(0,hResultCode);
  1434. DNASSERT(FALSE);
  1435. goto Failure;
  1436. }
  1437. pHandleParent->SetCompletion( DNCompleteAsyncHandle );
  1438. pHandleParent->SetContext( pvUserContext );
  1439. pHandleParent->SetResult( hrOperation );
  1440. pHandleParent->SetCannotCancel();
  1441. *phAsyncOp = pHandleParent->GetHandle();
  1442. pHandleParent->Release();
  1443. pHandleParent = NULL;
  1444. hResultCode = DPNERR_PENDING;
  1445. }
  1446. else
  1447. {
  1448. hResultCode = hrOperation;
  1449. }
  1450. }
  1451. else // Host Migration re-try
  1452. {
  1453. CAsyncOp *pRequest;
  1454. pRequest = NULL;
  1455. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pRequest )))
  1456. {
  1457. pRequest->SetResult( hrOperation );
  1458. // Release the HandleTable reference
  1459. pRequest->Release();
  1460. }
  1461. pRequest = NULL;
  1462. hResultCode = DPN_OK;
  1463. }
  1464. }
  1465. else
  1466. {
  1467. hResultCode = DPN_OK;
  1468. }
  1469. Exit:
  1470. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  1471. return(hResultCode);
  1472. Failure:
  1473. if (!fHostRequested)
  1474. {
  1475. DNHostFailRequest(pdnObject,dpnidRequesting,hCompletionOp,hrOperation);
  1476. }
  1477. else
  1478. {
  1479. //
  1480. // If a completion op was specified and this was requested by the Host, this is a
  1481. // retry of an operation during Host migration. In this case, we want to set the
  1482. // result (failure code) of the completion op, and remove it from the HandleTable.
  1483. //
  1484. if (hCompletionOp)
  1485. {
  1486. CAsyncOp *pHostCompletionOp;
  1487. pHostCompletionOp = NULL;
  1488. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pHostCompletionOp )))
  1489. {
  1490. pHostCompletionOp->SetResult( hResultCode );
  1491. // Release the HandleTable reference
  1492. pHostCompletionOp->Release();
  1493. }
  1494. pHostCompletionOp = NULL;
  1495. DNASSERT(pHostCompletionOp == NULL);
  1496. }
  1497. }
  1498. if (pHandleParent)
  1499. {
  1500. pHandleParent->Release();
  1501. pHandleParent = NULL;
  1502. }
  1503. if (pRefCountBuffer)
  1504. {
  1505. pRefCountBuffer->Release();
  1506. pRefCountBuffer = NULL;
  1507. }
  1508. if (pLocalPlayer)
  1509. {
  1510. pLocalPlayer->Release();
  1511. pLocalPlayer = NULL;
  1512. }
  1513. goto Exit;
  1514. }
  1515. #undef DPF_MODNAME
  1516. #define DPF_MODNAME "DNHostAddPlayerToGroup"
  1517. HRESULT DNHostAddPlayerToGroup(DIRECTNETOBJECT *const pdnObject,
  1518. const DPNID dpnidGroup,
  1519. const DPNID dpnidPlayer,
  1520. void *const pvUserContext,
  1521. const DPNID dpnidRequesting,
  1522. const DPNHANDLE hCompletionOp,
  1523. DPNHANDLE *const phAsyncOp,
  1524. const DWORD dwFlags)
  1525. {
  1526. HRESULT hResultCode;
  1527. HRESULT hrOperation;
  1528. DWORD dwVersion;
  1529. BOOL fHostRequested;
  1530. CNameTableEntry *pLocalPlayer;
  1531. CNameTableEntry *pPlayer;
  1532. CNameTableEntry *pGroup;
  1533. CRefCountBuffer *pRefCountBuffer;
  1534. CAsyncOp *pHandleParent;
  1535. CWorkerJob *pWorkerJob;
  1536. DN_INTERNAL_MESSAGE_ADD_PLAYER_TO_GROUP *pMsg;
  1537. DPFX(DPFPREP, 4,"Parameters: dpnidGroup [0x%lx], dpnidPlayer [0x%lx], pvUserContext [0x%p], dpnidRequesting [0x%lx], hCompletionOp [0x%lx], phAsyncOp [0x%p], dwFlags [0x%lx]",
  1538. dpnidGroup,dpnidPlayer,pvUserContext,dpnidRequesting,hCompletionOp,phAsyncOp,dwFlags);
  1539. DNASSERT(pdnObject != NULL);
  1540. DNASSERT(dpnidGroup != 0);
  1541. DNASSERT(dpnidPlayer != 0);
  1542. DNASSERT(dpnidRequesting != 0);
  1543. //
  1544. // If this is called from DN_AddPlayerToGroup(),
  1545. // hCompletion=0
  1546. // dpnidRequesting = DPNID of Host
  1547. // pvUserContext is valid
  1548. //
  1549. // If this is called by a REQUEST,
  1550. // hCompletion = REQUEST handle of requesting player
  1551. // dpnidRequesting = DPNID of requesting player
  1552. // pvUserContext is not valid
  1553. //
  1554. // If this is called at HostMigration,
  1555. // hCompletion = REQUEST handle on THIS (now Host) player
  1556. // dpnidRequesting = DPNID of THIS (now Host) player
  1557. // pvUserContext is invalid
  1558. //
  1559. pLocalPlayer = NULL;
  1560. pGroup = NULL;
  1561. pPlayer = NULL;
  1562. pRefCountBuffer = NULL;
  1563. pHandleParent = NULL;
  1564. pWorkerJob = NULL;
  1565. //
  1566. // Determine if this is being requested by the Host
  1567. //
  1568. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  1569. {
  1570. DPFERR("Could not get local player reference");
  1571. DisplayDNError(0,hResultCode);
  1572. return(DPN_OK); // Ignore and continue (!)
  1573. }
  1574. if (pLocalPlayer->GetDPNID() == dpnidRequesting)
  1575. {
  1576. fHostRequested = TRUE;
  1577. }
  1578. else
  1579. {
  1580. fHostRequested = FALSE;
  1581. }
  1582. pLocalPlayer->Release();
  1583. pLocalPlayer = NULL;
  1584. //
  1585. // See if the player and group are still in the NameTable
  1586. // (this has to happen after we set fHostRequested so we can gracefully handle errors)
  1587. //
  1588. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnidGroup,&pGroup)) != DPN_OK)
  1589. {
  1590. DPFERR("Could not find group");
  1591. DisplayDNError(0,hResultCode);
  1592. hResultCode = DPNERR_INVALIDGROUP;
  1593. hrOperation = DPNERR_INVALIDGROUP;
  1594. goto Failure;
  1595. }
  1596. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnidPlayer,&pPlayer)) != DPN_OK)
  1597. {
  1598. DPFERR("Could not find player");
  1599. DisplayDNError(0,hResultCode);
  1600. hResultCode = DPNERR_INVALIDPLAYER;
  1601. hrOperation = DPNERR_INVALIDPLAYER;
  1602. goto Failure;
  1603. }
  1604. //
  1605. // Add Player To Group
  1606. //
  1607. dwVersion = 0;
  1608. hrOperation = pdnObject->NameTable.AddPlayerToGroup(pGroup,pPlayer,&dwVersion);
  1609. pGroup->Release();
  1610. pGroup = NULL;
  1611. pPlayer->Release();
  1612. pPlayer = NULL;
  1613. if (hrOperation != DPN_OK)
  1614. {
  1615. DPFERR("Could not add player to group");
  1616. DisplayDNError(0,hResultCode);
  1617. if (!fHostRequested)
  1618. {
  1619. DNHostFailRequest(pdnObject,dpnidRequesting,hCompletionOp,hrOperation);
  1620. }
  1621. }
  1622. else
  1623. {
  1624. //
  1625. // Send ADD_PLAYER_TO_GROUP message
  1626. //
  1627. if (pdnObject->dwFlags & DN_OBJECT_FLAG_PEER)
  1628. {
  1629. // Create buffer
  1630. if ((hResultCode = RefCountBufferNew(pdnObject,sizeof(DN_INTERNAL_MESSAGE_ADD_PLAYER_TO_GROUP),MemoryBlockAlloc,MemoryBlockFree,&pRefCountBuffer)) != DPN_OK)
  1631. {
  1632. DPFERR("Could not create RefCountBuffer");
  1633. DisplayDNError(0,hResultCode);
  1634. DNASSERT(FALSE);
  1635. goto Failure;
  1636. }
  1637. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_ADD_PLAYER_TO_GROUP*>(pRefCountBuffer->GetBufferAddress());
  1638. pMsg->dpnidGroup = dpnidGroup;
  1639. pMsg->dpnidPlayer = dpnidPlayer;
  1640. pMsg->dwVersion = dwVersion;
  1641. pMsg->dwVersionNotUsed = 0;
  1642. pMsg->dpnidRequesting = dpnidRequesting;
  1643. pMsg->hCompletionOp = hCompletionOp;
  1644. //
  1645. // SEND AddPlayerToGroup messages via WorkerThread
  1646. //
  1647. if ((hResultCode = WorkerJobNew(pdnObject,&pWorkerJob)) != DPN_OK)
  1648. {
  1649. DPFERR("Could not create new WorkerJob");
  1650. DisplayDNError(0,hResultCode);
  1651. DNASSERT(FALSE);
  1652. goto Failure;
  1653. }
  1654. pWorkerJob->SetJobType( WORKER_JOB_SEND_NAMETABLE_OPERATION );
  1655. pWorkerJob->SetSendNameTableOperationMsgId( DN_MSG_INTERNAL_ADD_PLAYER_TO_GROUP );
  1656. pWorkerJob->SetSendNameTableOperationVersion( dwVersion );
  1657. pWorkerJob->SetSendNameTableOperationDPNIDExclude( 0 );
  1658. pWorkerJob->SetRefCountBuffer( pRefCountBuffer );
  1659. DNQueueWorkerJob(pdnObject,pWorkerJob);
  1660. pWorkerJob = NULL;
  1661. pRefCountBuffer->Release();
  1662. pRefCountBuffer = NULL;
  1663. }
  1664. }
  1665. //
  1666. // If this was called by the local (Host) player,
  1667. // Check to see if this was an original operation or a re-try from HostMigration
  1668. //
  1669. // If this was an original operation,
  1670. // See if we need an Async HANDLE for the user
  1671. // Otherwise
  1672. // Clean up the outstanding operation
  1673. //
  1674. if (fHostRequested)
  1675. {
  1676. if (hCompletionOp == 0) // Original
  1677. {
  1678. //
  1679. // If this fails, or is synchronous, return the operation result immediately
  1680. //
  1681. if (!(dwFlags & DPNADDPLAYERTOGROUP_SYNC) && (hrOperation == DPN_OK))
  1682. {
  1683. if ((hResultCode = DNCreateUserHandle(pdnObject,&pHandleParent)) != DPN_OK)
  1684. {
  1685. DPFERR("Could not create Async HANDLE");
  1686. DisplayDNError(0,hResultCode);
  1687. DNASSERT(FALSE);
  1688. goto Failure;
  1689. }
  1690. pHandleParent->SetCompletion( DNCompleteAsyncHandle );
  1691. pHandleParent->SetContext( pvUserContext );
  1692. pHandleParent->SetResult( hrOperation );
  1693. pHandleParent->SetCannotCancel();
  1694. *phAsyncOp = pHandleParent->GetHandle();
  1695. pHandleParent->Release();
  1696. pHandleParent = NULL;
  1697. hResultCode = DPNERR_PENDING;
  1698. }
  1699. else
  1700. {
  1701. hResultCode = hrOperation;
  1702. }
  1703. }
  1704. else // Host Migration re-try
  1705. {
  1706. CAsyncOp *pRequest;
  1707. pRequest = NULL;
  1708. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pRequest )))
  1709. {
  1710. pRequest->SetResult( hrOperation );
  1711. // Release the HandleTable reference
  1712. pRequest->Release();
  1713. }
  1714. pRequest = NULL;
  1715. hResultCode = DPN_OK;
  1716. }
  1717. }
  1718. else
  1719. {
  1720. hResultCode = DPN_OK;
  1721. }
  1722. Exit:
  1723. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  1724. return(hResultCode);
  1725. Failure:
  1726. if (!fHostRequested)
  1727. {
  1728. DNHostFailRequest(pdnObject,dpnidRequesting,hCompletionOp,hrOperation);
  1729. }
  1730. else
  1731. {
  1732. //
  1733. // If a completion op was specified and this was requested by the Host, this is a
  1734. // retry of an operation during Host migration. In this case, we want to set the
  1735. // result (failure code) of the completion op, and remove it from the HandleTable.
  1736. //
  1737. if (hCompletionOp)
  1738. {
  1739. CAsyncOp *pHostCompletionOp;
  1740. pHostCompletionOp = NULL;
  1741. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pHostCompletionOp )))
  1742. {
  1743. pHostCompletionOp->SetResult( hResultCode );
  1744. // Release the HandleTable reference
  1745. pHostCompletionOp->Release();
  1746. }
  1747. pHostCompletionOp = NULL;
  1748. DNASSERT(pHostCompletionOp == NULL);
  1749. }
  1750. }
  1751. if (pHandleParent)
  1752. {
  1753. pHandleParent->Release();
  1754. pHandleParent = NULL;
  1755. }
  1756. if (pRefCountBuffer)
  1757. {
  1758. pRefCountBuffer->Release();
  1759. pRefCountBuffer = NULL;
  1760. }
  1761. if (pLocalPlayer)
  1762. {
  1763. pLocalPlayer->Release();
  1764. pLocalPlayer = NULL;
  1765. }
  1766. if (pGroup)
  1767. {
  1768. pGroup->Release();
  1769. pGroup = NULL;
  1770. }
  1771. if (pPlayer)
  1772. {
  1773. pPlayer->Release();
  1774. pPlayer = NULL;
  1775. }
  1776. goto Exit;
  1777. }
  1778. #undef DPF_MODNAME
  1779. #define DPF_MODNAME "DNHostDeletePlayerFromGroup"
  1780. HRESULT DNHostDeletePlayerFromGroup(DIRECTNETOBJECT *const pdnObject,
  1781. const DPNID dpnidGroup,
  1782. const DPNID dpnidPlayer,
  1783. void *const pvUserContext,
  1784. const DPNID dpnidRequesting,
  1785. const DPNHANDLE hCompletionOp,
  1786. DPNHANDLE *const phAsyncOp,
  1787. const DWORD dwFlags)
  1788. {
  1789. HRESULT hResultCode;
  1790. HRESULT hrOperation;
  1791. DWORD dwVersion;
  1792. BOOL fHostRequested;
  1793. CNameTableEntry *pLocalPlayer;
  1794. CNameTableEntry *pGroup;
  1795. CNameTableEntry *pPlayer;
  1796. CRefCountBuffer *pRefCountBuffer;
  1797. CAsyncOp *pHandleParent;
  1798. CWorkerJob *pWorkerJob;
  1799. DN_INTERNAL_MESSAGE_DELETE_PLAYER_FROM_GROUP *pMsg;
  1800. DPFX(DPFPREP, 4,"Parameters: dpnidGroup [0x%lx], dpnidPlayer [0x%lx], pvUserContext [0x%p], dpnidRequesting [0x%lx], hCompletionOp [0x%lx], phAsyncOp [0x%p], dwFlags [0x%lx]",
  1801. dpnidGroup,dpnidPlayer,pvUserContext,dpnidRequesting,hCompletionOp,phAsyncOp,dwFlags);
  1802. DNASSERT(pdnObject != NULL);
  1803. DNASSERT(dpnidGroup != 0);
  1804. DNASSERT(dpnidPlayer != 0);
  1805. DNASSERT(dpnidRequesting != 0);
  1806. //
  1807. // If this is called from DN_DeletePlayerFromGroup(),
  1808. // hCompletion=0
  1809. // dpnidRequesting = DPNID of Host
  1810. // pvUserContext is valid
  1811. //
  1812. // If this is called by a REQUEST,
  1813. // hCompletion = REQUEST handle of requesting player
  1814. // dpnidRequesting = DPNID of requesting player
  1815. // pvUserContext is not valid
  1816. //
  1817. // If this is called at HostMigration,
  1818. // hCompletion = REQUEST handle on THIS (now Host) player
  1819. // dpnidRequesting = DPNID of THIS (now Host) player
  1820. // pvUserContext is invalid
  1821. //
  1822. pLocalPlayer = NULL;
  1823. pGroup = NULL;
  1824. pPlayer = NULL;
  1825. pRefCountBuffer = NULL;
  1826. pHandleParent = NULL;
  1827. pWorkerJob = NULL;
  1828. //
  1829. // Determine if this is being requested by the Host
  1830. //
  1831. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  1832. {
  1833. DPFERR("Could not get local player reference");
  1834. DisplayDNError(0,hResultCode);
  1835. return(DPN_OK); // Ignore and continue (!)
  1836. }
  1837. if (pLocalPlayer->GetDPNID() == dpnidRequesting)
  1838. {
  1839. fHostRequested = TRUE;
  1840. }
  1841. else
  1842. {
  1843. fHostRequested = FALSE;
  1844. }
  1845. pLocalPlayer->Release();
  1846. pLocalPlayer = NULL;
  1847. //
  1848. // See if the player and group are still in the NameTable
  1849. // (this has to happen after we set fHostRequested so we can gracefully handle errors)
  1850. //
  1851. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnidGroup,&pGroup)) != DPN_OK)
  1852. {
  1853. DPFERR("Could not find group");
  1854. DisplayDNError(0,hResultCode);
  1855. hResultCode = DPNERR_INVALIDGROUP;
  1856. hrOperation = DPNERR_INVALIDGROUP;
  1857. goto Failure;
  1858. }
  1859. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnidPlayer,&pPlayer)) != DPN_OK)
  1860. {
  1861. DPFERR("Could not find player");
  1862. DisplayDNError(0,hResultCode);
  1863. hResultCode = DPNERR_INVALIDPLAYER;
  1864. hrOperation = DPNERR_INVALIDPLAYER;
  1865. goto Failure;
  1866. }
  1867. //
  1868. // Delete Player From Group
  1869. //
  1870. dwVersion = 0;
  1871. hrOperation = pdnObject->NameTable.RemovePlayerFromGroup(pGroup,pPlayer,&dwVersion);
  1872. if (hrOperation != DPN_OK)
  1873. {
  1874. DPFERR("Could not delete player from group");
  1875. DisplayDNError(0,hrOperation);
  1876. if (!fHostRequested)
  1877. {
  1878. DNHostFailRequest(pdnObject,dpnidRequesting,hCompletionOp,hrOperation);
  1879. }
  1880. }
  1881. else
  1882. {
  1883. //
  1884. // Send DELETE_PLAYER_FROM_GROUP message if successful
  1885. //
  1886. if (pdnObject->dwFlags & DN_OBJECT_FLAG_PEER)
  1887. {
  1888. // Create buffer
  1889. if ((hResultCode = RefCountBufferNew(pdnObject,sizeof(DN_INTERNAL_MESSAGE_DELETE_PLAYER_FROM_GROUP),MemoryBlockAlloc,MemoryBlockFree,&pRefCountBuffer)) != DPN_OK)
  1890. {
  1891. DPFERR("Could not create RefCountBuffer");
  1892. DisplayDNError(0,hResultCode);
  1893. DNASSERT(FALSE);
  1894. goto Failure;
  1895. }
  1896. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_DELETE_PLAYER_FROM_GROUP*>(pRefCountBuffer->GetBufferAddress());
  1897. pMsg->dpnidGroup = dpnidGroup;
  1898. pMsg->dpnidPlayer = dpnidPlayer;
  1899. pMsg->dwVersion = dwVersion;
  1900. pMsg->dwVersionNotUsed = 0;
  1901. pMsg->dpnidRequesting = dpnidRequesting;
  1902. pMsg->hCompletionOp = hCompletionOp;
  1903. //
  1904. // SEND DeletePlayerFromGroup messages via WorkerThread
  1905. //
  1906. if ((hResultCode = WorkerJobNew(pdnObject,&pWorkerJob)) != DPN_OK)
  1907. {
  1908. DPFERR("Could not create new WorkerJob");
  1909. DisplayDNError(0,hResultCode);
  1910. DNASSERT(FALSE);
  1911. goto Failure;
  1912. }
  1913. pWorkerJob->SetJobType( WORKER_JOB_SEND_NAMETABLE_OPERATION );
  1914. pWorkerJob->SetSendNameTableOperationMsgId( DN_MSG_INTERNAL_DELETE_PLAYER_FROM_GROUP );
  1915. pWorkerJob->SetSendNameTableOperationVersion( dwVersion );
  1916. pWorkerJob->SetSendNameTableOperationDPNIDExclude( 0 );
  1917. pWorkerJob->SetRefCountBuffer( pRefCountBuffer );
  1918. DNQueueWorkerJob(pdnObject,pWorkerJob);
  1919. pWorkerJob = NULL;
  1920. pRefCountBuffer->Release();
  1921. pRefCountBuffer = NULL;
  1922. }
  1923. }
  1924. pGroup->Release();
  1925. pGroup = NULL;
  1926. pPlayer->Release();
  1927. pPlayer = NULL;
  1928. //
  1929. // If this was called by the local (Host) player,
  1930. // Check to see if this was an original operation or a re-try from HostMigration
  1931. //
  1932. // If this was an original operation,
  1933. // See if we need an Async HANDLE for the user
  1934. // Otherwise
  1935. // Clean up the outstanding operation
  1936. //
  1937. if (fHostRequested)
  1938. {
  1939. if (hCompletionOp == 0) // Original
  1940. {
  1941. //
  1942. // If this fails, or is synchronous, return the operation result immediately
  1943. //
  1944. if (!(dwFlags & DPNREMOVEPLAYERFROMGROUP_SYNC) && (hrOperation == DPN_OK))
  1945. {
  1946. if ((hResultCode = DNCreateUserHandle(pdnObject,&pHandleParent)) != DPN_OK)
  1947. {
  1948. DPFERR("Could not create Async HANDLE");
  1949. DisplayDNError(0,hResultCode);
  1950. DNASSERT(FALSE);
  1951. goto Failure;
  1952. }
  1953. pHandleParent->SetCompletion( DNCompleteAsyncHandle );
  1954. pHandleParent->SetContext( pvUserContext );
  1955. pHandleParent->SetResult( hrOperation );
  1956. pHandleParent->SetCannotCancel();
  1957. *phAsyncOp = pHandleParent->GetHandle();
  1958. pHandleParent->Release();
  1959. pHandleParent = NULL;
  1960. hResultCode = DPNERR_PENDING;
  1961. }
  1962. else
  1963. {
  1964. hResultCode = hrOperation;
  1965. }
  1966. }
  1967. else // Host Migration re-try
  1968. {
  1969. CAsyncOp *pRequest;
  1970. pRequest = NULL;
  1971. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pRequest )))
  1972. {
  1973. pRequest->SetResult( hrOperation );
  1974. // Release the HandleTable reference
  1975. pRequest->Release();
  1976. }
  1977. pRequest = NULL;
  1978. hResultCode = DPN_OK;
  1979. }
  1980. }
  1981. else
  1982. {
  1983. hResultCode = DPN_OK;
  1984. }
  1985. Exit:
  1986. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  1987. return(hResultCode);
  1988. Failure:
  1989. if (!fHostRequested)
  1990. {
  1991. DNHostFailRequest(pdnObject,dpnidRequesting,hCompletionOp,hrOperation);
  1992. }
  1993. else
  1994. {
  1995. //
  1996. // If a completion op was specified and this was requested by the Host, this is a
  1997. // retry of an operation during Host migration. In this case, we want to set the
  1998. // result (failure code) of the completion op, and remove it from the HandleTable.
  1999. //
  2000. if (hCompletionOp)
  2001. {
  2002. CAsyncOp *pHostCompletionOp;
  2003. pHostCompletionOp = NULL;
  2004. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pHostCompletionOp )))
  2005. {
  2006. pHostCompletionOp->SetResult( hResultCode );
  2007. // Release the HandleTable reference
  2008. pHostCompletionOp->Release();
  2009. }
  2010. pHostCompletionOp = NULL;
  2011. DNASSERT(pHostCompletionOp == NULL);
  2012. }
  2013. }
  2014. if (pHandleParent)
  2015. {
  2016. pHandleParent->Release();
  2017. pHandleParent = NULL;
  2018. }
  2019. if (pRefCountBuffer)
  2020. {
  2021. pRefCountBuffer->Release();
  2022. pRefCountBuffer = NULL;
  2023. }
  2024. if (pLocalPlayer)
  2025. {
  2026. pLocalPlayer->Release();
  2027. pLocalPlayer = NULL;
  2028. }
  2029. if (pGroup)
  2030. {
  2031. pGroup->Release();
  2032. pGroup = NULL;
  2033. }
  2034. if (pPlayer)
  2035. {
  2036. pPlayer->Release();
  2037. pPlayer = NULL;
  2038. }
  2039. goto Exit;
  2040. }
  2041. #undef DPF_MODNAME
  2042. #define DPF_MODNAME "DNHostUpdateInfo"
  2043. HRESULT DNHostUpdateInfo(DIRECTNETOBJECT *const pdnObject,
  2044. const DPNID dpnid,
  2045. PWSTR pwszName,
  2046. const DWORD dwNameSize,
  2047. void *const pvData,
  2048. const DWORD dwDataSize,
  2049. const DWORD dwInfoFlags,
  2050. void *const pvUserContext,
  2051. const DPNID dpnidRequesting,
  2052. const DPNHANDLE hCompletionOp,
  2053. DPNHANDLE *const phAsyncOp,
  2054. const DWORD dwFlags)
  2055. {
  2056. HRESULT hResultCode;
  2057. HRESULT hrOperation;
  2058. DWORD dwSize;
  2059. DWORD dwVersion;
  2060. BOOL fHostRequested;
  2061. CNameTableEntry *pLocalPlayer;
  2062. CNameTableEntry *pNTEntry;
  2063. CPackedBuffer packedBuffer;
  2064. CRefCountBuffer *pRefCountBuffer;
  2065. CAsyncOp *pHandleParent;
  2066. CWorkerJob *pWorkerJob;
  2067. DN_INTERNAL_MESSAGE_UPDATE_INFO *pMsg;
  2068. DPFX(DPFPREP, 4,"Parameters: dpnid [0x%lx], pwszName [0x%p], dwNameSize [%ld], pvData [0x%p], dwDataSize [%ld], dwInfoFlags [0x%lx], pvUserContext [0x%p], dpnidRequesting [0x%lx], hCompletionOp [0x%lx], phAsyncOp [0x%p], dwFlags [0x%lx]",
  2069. dpnid,pwszName,dwNameSize,pvData,dwDataSize,dwInfoFlags,pvUserContext,dpnidRequesting,hCompletionOp,phAsyncOp,dwFlags);
  2070. DNASSERT(pdnObject != NULL);
  2071. DNASSERT(dpnid != 0);
  2072. DNASSERT(dpnidRequesting != 0);
  2073. pLocalPlayer = NULL;
  2074. pNTEntry = NULL;
  2075. pRefCountBuffer = NULL;
  2076. pHandleParent = NULL;
  2077. pWorkerJob = NULL;
  2078. //
  2079. // Determine if this is being requested by the Host
  2080. //
  2081. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  2082. {
  2083. DPFERR("Could not get local player reference");
  2084. DisplayDNError(0,hResultCode);
  2085. return(DPN_OK); // Ignore and continue (!)
  2086. }
  2087. if (pLocalPlayer->GetDPNID() == dpnidRequesting)
  2088. {
  2089. fHostRequested = TRUE;
  2090. }
  2091. else
  2092. {
  2093. fHostRequested = FALSE;
  2094. }
  2095. pLocalPlayer->Release();
  2096. pLocalPlayer = NULL;
  2097. //
  2098. // Update Info
  2099. //
  2100. hrOperation = pdnObject->NameTable.FindEntry(dpnid,&pNTEntry);
  2101. if (hrOperation != DPN_OK)
  2102. {
  2103. DPFERR("Could not find entry");
  2104. DisplayDNError(0,hResultCode);
  2105. if (!fHostRequested)
  2106. {
  2107. DNHostFailRequest(pdnObject,dpnidRequesting,hCompletionOp,hrOperation);
  2108. }
  2109. }
  2110. else
  2111. {
  2112. // This function takes the lock internally
  2113. pNTEntry->UpdateEntryInfo(pwszName,dwNameSize,pvData,dwDataSize,dwInfoFlags, (pdnObject->dwFlags & (DN_OBJECT_FLAG_PEER)) ? TRUE : !fHostRequested);
  2114. pdnObject->NameTable.WriteLock();
  2115. pdnObject->NameTable.GetNewVersion( &dwVersion );
  2116. pdnObject->NameTable.Unlock();
  2117. //
  2118. // Send UPDATE_INFO message
  2119. //
  2120. #ifndef DPNBUILD_NOSERVER
  2121. if (pdnObject->dwFlags & (DN_OBJECT_FLAG_PEER | DN_OBJECT_FLAG_SERVER))
  2122. #else
  2123. if (pdnObject->dwFlags & (DN_OBJECT_FLAG_PEER))
  2124. #endif // DPNBUILD_NOSERVER
  2125. {
  2126. // Create buffer
  2127. dwSize = sizeof(DN_INTERNAL_MESSAGE_UPDATE_INFO) + dwNameSize + dwDataSize;
  2128. if ((hResultCode = RefCountBufferNew(pdnObject,dwSize,MemoryBlockAlloc,MemoryBlockFree,&pRefCountBuffer)) != DPN_OK)
  2129. {
  2130. DPFERR("Could not create RefCountBuffer");
  2131. DisplayDNError(0,hResultCode);
  2132. DNASSERT(FALSE);
  2133. goto Failure;
  2134. }
  2135. packedBuffer.Initialize(pRefCountBuffer->GetBufferAddress(),pRefCountBuffer->GetBufferSize());
  2136. pMsg = static_cast<DN_INTERNAL_MESSAGE_UPDATE_INFO*>(packedBuffer.GetHeadAddress());
  2137. if ((hResultCode = packedBuffer.AddToFront(NULL,sizeof(DN_INTERNAL_MESSAGE_UPDATE_INFO))) != DPN_OK)
  2138. {
  2139. DPFERR("Could not reserve front of buffer");
  2140. DisplayDNError(0,hResultCode);
  2141. DNASSERT(FALSE);
  2142. goto Failure;
  2143. }
  2144. if ((dwInfoFlags & DPNINFO_NAME) && (pwszName) && (dwNameSize))
  2145. {
  2146. if ((hResultCode = packedBuffer.AddToBack(pwszName,dwNameSize)) != DPN_OK)
  2147. {
  2148. DPFERR("Could not add Name to back of buffer");
  2149. DisplayDNError(0,hResultCode);
  2150. DNASSERT(FALSE);
  2151. goto Failure;
  2152. }
  2153. pMsg->dwNameOffset = packedBuffer.GetTailOffset();
  2154. pMsg->dwNameSize = dwNameSize;
  2155. }
  2156. else
  2157. {
  2158. pMsg->dwNameOffset = 0;
  2159. pMsg->dwNameSize = 0;
  2160. }
  2161. if ((dwInfoFlags & DPNINFO_DATA) && (pvData) && (dwDataSize))
  2162. {
  2163. if ((hResultCode = packedBuffer.AddToBack(pvData,dwDataSize)) != DPN_OK)
  2164. {
  2165. DPFERR("Could not add Data to back of buffer");
  2166. DisplayDNError(0,hResultCode);
  2167. DNASSERT(FALSE);
  2168. goto Failure;
  2169. }
  2170. pMsg->dwDataOffset = packedBuffer.GetTailOffset();
  2171. pMsg->dwDataSize = dwDataSize;
  2172. }
  2173. else
  2174. {
  2175. pMsg->dwDataOffset = 0;
  2176. pMsg->dwDataSize = 0;
  2177. }
  2178. pMsg->dpnid = dpnid;
  2179. pMsg->dwInfoFlags = dwInfoFlags;
  2180. pMsg->dwVersion = dwVersion;
  2181. pMsg->dwVersionNotUsed = 0;
  2182. pMsg->dpnidRequesting = dpnidRequesting;
  2183. pMsg->hCompletionOp = hCompletionOp;
  2184. //
  2185. // SEND UpdateInfo messages via WorkerThread
  2186. //
  2187. if ((hResultCode = WorkerJobNew(pdnObject,&pWorkerJob)) != DPN_OK)
  2188. {
  2189. DPFERR("Could not create new WorkerJob");
  2190. DisplayDNError(0,hResultCode);
  2191. DNASSERT(FALSE);
  2192. goto Failure;
  2193. }
  2194. #ifndef DPNBUILD_NOSERVER
  2195. if (pdnObject->dwFlags & DN_OBJECT_FLAG_PEER)
  2196. #endif // DPNBUILD_NOSERVER
  2197. {
  2198. pWorkerJob->SetJobType( WORKER_JOB_SEND_NAMETABLE_OPERATION );
  2199. pWorkerJob->SetSendNameTableOperationDPNIDExclude( 0 );
  2200. }
  2201. #ifndef DPNBUILD_NOSERVER
  2202. else if ((pdnObject->dwFlags & DN_OBJECT_FLAG_SERVER) && fHostRequested)
  2203. {
  2204. // Send to everyone except the server
  2205. pWorkerJob->SetJobType( WORKER_JOB_SEND_NAMETABLE_OPERATION );
  2206. pWorkerJob->SetSendNameTableOperationDPNIDExclude( dpnidRequesting );
  2207. }
  2208. else
  2209. {
  2210. DNASSERT(pdnObject->dwFlags & DN_OBJECT_FLAG_SERVER);
  2211. // This will be responding to a client that requested its
  2212. // info updated via SetClientInfo
  2213. // Use the Exclude DPNID as the address to send to
  2214. pWorkerJob->SetJobType( WORKER_JOB_SEND_NAMETABLE_OPERATION_CLIENT );
  2215. pWorkerJob->SetSendNameTableOperationDPNIDExclude( dpnidRequesting );
  2216. }
  2217. #endif // DPNBUILD_NOSERVER
  2218. pWorkerJob->SetSendNameTableOperationMsgId( DN_MSG_INTERNAL_UPDATE_INFO );
  2219. pWorkerJob->SetSendNameTableOperationVersion( dwVersion );
  2220. pWorkerJob->SetRefCountBuffer( pRefCountBuffer );
  2221. DNQueueWorkerJob(pdnObject,pWorkerJob);
  2222. pWorkerJob = NULL;
  2223. pRefCountBuffer->Release();
  2224. pRefCountBuffer = NULL;
  2225. }
  2226. }
  2227. pNTEntry->Release();
  2228. pNTEntry = NULL;
  2229. //
  2230. // If this was called by the local (Host) player,
  2231. // Check to see if this was an original operation or a re-try from HostMigration
  2232. //
  2233. // If this was an original operation,
  2234. // See if we need an Async HANDLE for the user
  2235. // Otherwise
  2236. // Clean up the outstanding operation
  2237. //
  2238. if (fHostRequested)
  2239. {
  2240. if (hCompletionOp == 0) // Original
  2241. {
  2242. DBG_CASSERT( DPNSETGROUPINFO_SYNC == DPNSETCLIENTINFO_SYNC );
  2243. DBG_CASSERT( DPNSETCLIENTINFO_SYNC == DPNSETSERVERINFO_SYNC );
  2244. DBG_CASSERT( DPNSETSERVERINFO_SYNC == DPNSETPEERINFO_SYNC );
  2245. //
  2246. // If this fails, or is synchronous, return the operation result immediately
  2247. //
  2248. if (!(dwFlags & (DPNSETGROUPINFO_SYNC | DPNSETCLIENTINFO_SYNC | DPNSETSERVERINFO_SYNC | DPNSETPEERINFO_SYNC))
  2249. && (hrOperation == DPN_OK))
  2250. {
  2251. if ((hResultCode = DNCreateUserHandle(pdnObject,&pHandleParent)) != DPN_OK)
  2252. {
  2253. DPFERR("Could not create Async HANDLE");
  2254. DisplayDNError(0,hResultCode);
  2255. DNASSERT(FALSE);
  2256. goto Failure;
  2257. }
  2258. pHandleParent->SetCompletion( DNCompleteAsyncHandle );
  2259. pHandleParent->SetContext( pvUserContext );
  2260. pHandleParent->SetResult( hrOperation );
  2261. pHandleParent->SetCannotCancel();
  2262. *phAsyncOp = pHandleParent->GetHandle();
  2263. pHandleParent->Release();
  2264. pHandleParent = NULL;
  2265. hResultCode = DPNERR_PENDING;
  2266. }
  2267. else
  2268. {
  2269. hResultCode = hrOperation;
  2270. }
  2271. }
  2272. else // Host Migration re-try
  2273. {
  2274. CAsyncOp *pRequest;
  2275. pRequest = NULL;
  2276. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pRequest )))
  2277. {
  2278. pRequest->SetResult( hrOperation );
  2279. // Release the HandleTable reference
  2280. pRequest->Release();
  2281. }
  2282. pRequest = NULL;
  2283. hResultCode = DPN_OK;
  2284. }
  2285. }
  2286. else
  2287. {
  2288. hResultCode = DPN_OK;
  2289. }
  2290. Exit:
  2291. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  2292. return(hResultCode);
  2293. Failure:
  2294. if (!fHostRequested)
  2295. {
  2296. DNHostFailRequest(pdnObject,dpnidRequesting,hCompletionOp,hrOperation);
  2297. }
  2298. else
  2299. {
  2300. //
  2301. // If a completion op was specified and this was requested by the Host, this is a
  2302. // retry of an operation during Host migration. In this case, we want to set the
  2303. // result (failure code) of the completion op, and remove it from the HandleTable.
  2304. //
  2305. if (hCompletionOp)
  2306. {
  2307. CAsyncOp *pHostCompletionOp;
  2308. pHostCompletionOp = NULL;
  2309. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hCompletionOp, (PVOID*)&pHostCompletionOp )))
  2310. {
  2311. pHostCompletionOp->SetResult( hResultCode );
  2312. // Release the HandleTable reference
  2313. pHostCompletionOp->Release();
  2314. }
  2315. pHostCompletionOp = NULL;
  2316. DNASSERT(pHostCompletionOp == NULL);
  2317. }
  2318. }
  2319. if (pHandleParent)
  2320. {
  2321. pHandleParent->Release();
  2322. pHandleParent = NULL;
  2323. }
  2324. if (pRefCountBuffer)
  2325. {
  2326. pRefCountBuffer->Release();
  2327. pRefCountBuffer = NULL;
  2328. }
  2329. if (pNTEntry)
  2330. {
  2331. pNTEntry->Release();
  2332. pNTEntry = NULL;
  2333. }
  2334. if (pLocalPlayer)
  2335. {
  2336. pLocalPlayer->Release();
  2337. pLocalPlayer = NULL;
  2338. }
  2339. goto Exit;
  2340. }
  2341. // DNHostCheckIntegrity
  2342. //
  2343. // The host has been asked to perform an integrity check. We will send a message to the
  2344. // target player with the DPNID of the requesting player. If this is returned to us, we
  2345. // will destroy the requesting player.
  2346. #undef DPF_MODNAME
  2347. #define DPF_MODNAME "DNHostCheckIntegrity"
  2348. HRESULT DNHostCheckIntegrity(DIRECTNETOBJECT *const pdnObject,
  2349. const DPNID dpnidTarget,
  2350. const DPNID dpnidRequesting)
  2351. {
  2352. HRESULT hResultCode;
  2353. CNameTableEntry *pNTEntry;
  2354. CConnection *pConnection;
  2355. CRefCountBuffer *pRefCountBuffer;
  2356. DN_INTERNAL_MESSAGE_INTEGRITY_CHECK *pMsg;
  2357. DPFX(DPFPREP, 6,"Parameters: dpnidTarget [0x%lx], dpnidRequesting [0x%lx]",dpnidTarget,dpnidRequesting);
  2358. pNTEntry = NULL;
  2359. pConnection = NULL;
  2360. pRefCountBuffer = NULL;
  2361. //
  2362. // Ensure that the target player is still in the NameTable, as we might have deleted him already
  2363. //
  2364. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnidTarget,&pNTEntry)) != DPN_OK)
  2365. {
  2366. DPFERR("Could not find integrity check target in NameTable - probably deleted already");
  2367. DisplayDNError(0,hResultCode);
  2368. hResultCode = DPN_OK;
  2369. goto Failure;
  2370. }
  2371. if ((hResultCode = pNTEntry->GetConnectionRef( &pConnection )) != DPN_OK)
  2372. {
  2373. DPFERR("Could not get target player connection reference - probably deleted already");
  2374. DisplayDNError(0,hResultCode);
  2375. hResultCode = DPN_OK;
  2376. goto Failure;
  2377. }
  2378. pNTEntry->Release();
  2379. pNTEntry = NULL;
  2380. //
  2381. // Create the message
  2382. //
  2383. hResultCode = RefCountBufferNew(pdnObject,
  2384. sizeof(DN_INTERNAL_MESSAGE_INTEGRITY_CHECK),
  2385. MemoryBlockAlloc,
  2386. MemoryBlockFree,
  2387. &pRefCountBuffer);
  2388. if (hResultCode != DPN_OK)
  2389. {
  2390. DPFERR("Could not create RefCountBuffer");
  2391. DisplayDNError(0,hResultCode);
  2392. DNASSERT(FALSE);
  2393. goto Failure;
  2394. }
  2395. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_INTEGRITY_CHECK*>(pRefCountBuffer->GetBufferAddress());
  2396. pMsg->dpnidRequesting = dpnidRequesting;
  2397. //
  2398. // Send message
  2399. //
  2400. if ((hResultCode = DNSendMessage( pdnObject,
  2401. pConnection,
  2402. DN_MSG_INTERNAL_INTEGRITY_CHECK,
  2403. dpnidTarget,
  2404. pRefCountBuffer->BufferDescAddress(),
  2405. 1,
  2406. pRefCountBuffer,
  2407. 0,
  2408. DN_SENDFLAGS_RELIABLE,
  2409. NULL,
  2410. NULL )) != DPNERR_PENDING)
  2411. {
  2412. DPFERR("Could not send message - probably deleted already");
  2413. DisplayDNError(0,hResultCode);
  2414. DNASSERT(hResultCode != DPN_OK); // it was sent guaranteed, it should not return immediately
  2415. hResultCode = DPN_OK;
  2416. goto Failure;
  2417. }
  2418. pConnection->Release();
  2419. pConnection = NULL;
  2420. pRefCountBuffer->Release();
  2421. pRefCountBuffer = NULL;
  2422. hResultCode = DPN_OK;
  2423. Exit:
  2424. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  2425. return(hResultCode);
  2426. Failure:
  2427. if (pNTEntry)
  2428. {
  2429. pNTEntry->Release();
  2430. pNTEntry = NULL;
  2431. }
  2432. if (pConnection)
  2433. {
  2434. pConnection->Release();
  2435. pConnection = NULL;
  2436. }
  2437. if (pRefCountBuffer)
  2438. {
  2439. pRefCountBuffer->Release();
  2440. pRefCountBuffer = NULL;
  2441. }
  2442. goto Exit;
  2443. }
  2444. // DNHostFixIntegrity
  2445. //
  2446. // The host has received a response from a player whose session integrity was being checked.
  2447. // The player who requested this check will be dropped.
  2448. #undef DPF_MODNAME
  2449. #define DPF_MODNAME "DNHostFixIntegrity"
  2450. HRESULT DNHostFixIntegrity(DIRECTNETOBJECT *const pdnObject,
  2451. void *const pvBuffer)
  2452. {
  2453. HRESULT hResultCode;
  2454. CNameTableEntry *pNTEntry;
  2455. CConnection *pConnection;
  2456. CRefCountBuffer *pRefCountBuffer;
  2457. UNALIGNED DN_INTERNAL_MESSAGE_INTEGRITY_CHECK_RESPONSE *pResponse;
  2458. DN_INTERNAL_MESSAGE_TERMINATE_SESSION *pMsg;
  2459. DPFX(DPFPREP, 6,"Parameters: pvBuffer [0x%p]",pvBuffer);
  2460. DNASSERT(pdnObject != NULL);
  2461. DNASSERT(pvBuffer != NULL);
  2462. pNTEntry = NULL;
  2463. pConnection = NULL;
  2464. pRefCountBuffer = NULL;
  2465. pResponse = static_cast<DN_INTERNAL_MESSAGE_INTEGRITY_CHECK_RESPONSE*>(pvBuffer);
  2466. //
  2467. // Get requesting player's connection - they may have already dropped
  2468. //
  2469. if ((hResultCode = pdnObject->NameTable.FindEntry(pResponse->dpnidRequesting,&pNTEntry)) != DPN_OK)
  2470. {
  2471. DPFERR("Could not find player in NameTable - may have dropped");
  2472. DisplayDNError(0,hResultCode);
  2473. goto Failure;
  2474. }
  2475. if ((hResultCode = pNTEntry->GetConnectionRef( &pConnection )) != DPN_OK)
  2476. {
  2477. DPFERR("Could not get player connection reference");
  2478. DisplayDNError(0,hResultCode);
  2479. goto Failure;
  2480. }
  2481. pNTEntry->Release();
  2482. pNTEntry = NULL;
  2483. //
  2484. // Build terminate message
  2485. //
  2486. if ((hResultCode = RefCountBufferNew(pdnObject,sizeof(DN_INTERNAL_MESSAGE_TERMINATE_SESSION),MemoryBlockAlloc,MemoryBlockFree,&pRefCountBuffer)) != DPN_OK)
  2487. {
  2488. DPFERR("Could not allocate RefCountBuffer");
  2489. DisplayDNError(0,hResultCode);
  2490. goto Failure;
  2491. }
  2492. pMsg = reinterpret_cast<DN_INTERNAL_MESSAGE_TERMINATE_SESSION*>(pRefCountBuffer->GetBufferAddress());
  2493. pMsg->dwTerminateDataOffset = 0;
  2494. pMsg->dwTerminateDataSize = 0;
  2495. //
  2496. // Send message to player to exit
  2497. //
  2498. hResultCode = DNSendMessage(pdnObject,
  2499. pConnection,
  2500. DN_MSG_INTERNAL_TERMINATE_SESSION,
  2501. pResponse->dpnidRequesting,
  2502. pRefCountBuffer->BufferDescAddress(),
  2503. 1,
  2504. pRefCountBuffer,
  2505. 0,
  2506. DN_SENDFLAGS_RELIABLE,
  2507. NULL,
  2508. NULL);
  2509. pConnection->Release();
  2510. pConnection = NULL;
  2511. pRefCountBuffer->Release();
  2512. pRefCountBuffer = NULL;
  2513. //
  2514. // Disconnect player
  2515. //
  2516. hResultCode = DNHostDisconnect(pdnObject,pResponse->dpnidRequesting,DPNDESTROYPLAYERREASON_HOSTDESTROYEDPLAYER);
  2517. Exit:
  2518. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  2519. return(hResultCode);
  2520. Failure:
  2521. if (pRefCountBuffer)
  2522. {
  2523. pRefCountBuffer->Release();
  2524. pRefCountBuffer = NULL;
  2525. }
  2526. if (pNTEntry)
  2527. {
  2528. pNTEntry->Release();
  2529. pNTEntry = NULL;
  2530. }
  2531. if (pConnection)
  2532. {
  2533. pConnection->Release();
  2534. pConnection = NULL;
  2535. }
  2536. goto Exit;
  2537. }
  2538. #undef DPF_MODNAME
  2539. #define DPF_MODNAME "DNProcessCreateGroup"
  2540. HRESULT DNProcessCreateGroup(DIRECTNETOBJECT *const pdnObject,
  2541. void *const pvBuffer)
  2542. {
  2543. HRESULT hResultCode;
  2544. CNameTableEntry *pLocalPlayer;
  2545. CNameTableEntry *pNTEntry;
  2546. CAsyncOp *pRequest;
  2547. UNALIGNED DN_NAMETABLE_ENTRY_INFO *pInfo;
  2548. UNALIGNED DN_INTERNAL_MESSAGE_CREATE_GROUP *pMsg;
  2549. BOOL fNotify;
  2550. DPFX(DPFPREP, 4,"Parameters: pvBuffer [0x%p]",pvBuffer);
  2551. DNASSERT(pdnObject != NULL);
  2552. DNASSERT(pvBuffer != NULL);
  2553. pRequest = NULL;
  2554. pLocalPlayer = NULL;
  2555. pNTEntry = NULL;
  2556. pMsg = static_cast<DN_INTERNAL_MESSAGE_CREATE_GROUP*>(pvBuffer);
  2557. pInfo = reinterpret_cast<DN_NAMETABLE_ENTRY_INFO*>(pMsg + 1);
  2558. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  2559. {
  2560. DPFERR("Could not get local player reference");
  2561. DisplayDNError(0,hResultCode);
  2562. goto Failure;
  2563. }
  2564. //
  2565. // Create Group
  2566. //
  2567. if ((hResultCode = NameTableEntryNew(pdnObject,&pNTEntry)) != DPN_OK)
  2568. {
  2569. DPFERR("Could not create new NameTableEntry");
  2570. DisplayDNError(0,hResultCode);
  2571. DNASSERT(FALSE);
  2572. goto Failure;
  2573. }
  2574. if ((hResultCode = pNTEntry->UnpackEntryInfo(pInfo,static_cast<BYTE*>(pvBuffer))) != DPN_OK)
  2575. {
  2576. DPFERR("Could not unpack NameTableEntry");
  2577. DisplayDNError(0,hResultCode);
  2578. DNASSERT(FALSE);
  2579. goto Failure;
  2580. }
  2581. //
  2582. // Get async op if we requested this operation - it has the group context on it
  2583. //
  2584. if (pMsg->dpnidRequesting == pLocalPlayer->GetDPNID())
  2585. {
  2586. pdnObject->HandleTable.Lock();
  2587. if ((hResultCode = pdnObject->HandleTable.Find( pMsg->hCompletionOp,(PVOID*)&pRequest )) != DPN_OK)
  2588. {
  2589. pdnObject->HandleTable.Unlock();
  2590. DPFERR("Could not find REQUEST AsyncOp");
  2591. DisplayDNError(0,hResultCode);
  2592. DNASSERT(FALSE);
  2593. goto Failure;
  2594. }
  2595. else
  2596. {
  2597. pRequest->AddRef();
  2598. pdnObject->HandleTable.Unlock();
  2599. }
  2600. pNTEntry->SetContext( pRequest->GetContext() );
  2601. }
  2602. pLocalPlayer->Release();
  2603. pLocalPlayer = NULL;
  2604. //
  2605. // Add Group to NameTable
  2606. //
  2607. if ((hResultCode = pdnObject->NameTable.InsertEntry(pNTEntry)) != DPN_OK)
  2608. {
  2609. DPFERR("Could not update NameTable");
  2610. DisplayDNError(0,hResultCode);
  2611. DNASSERT(FALSE);
  2612. goto Failure;
  2613. }
  2614. pdnObject->NameTable.WriteLock();
  2615. pdnObject->NameTable.SetVersion(pNTEntry->GetVersion());
  2616. pdnObject->NameTable.Unlock();
  2617. fNotify = FALSE;
  2618. pNTEntry->Lock();
  2619. if (!pNTEntry->IsAvailable() && !pNTEntry->IsDisconnecting())
  2620. {
  2621. pNTEntry->MakeAvailable();
  2622. pNTEntry->NotifyAddRef();
  2623. pNTEntry->NotifyAddRef();
  2624. pNTEntry->SetInUse();
  2625. fNotify = TRUE;
  2626. }
  2627. pNTEntry->Unlock();
  2628. if (fNotify)
  2629. {
  2630. DNUserCreateGroup(pdnObject,pNTEntry);
  2631. pNTEntry->PerformQueuedOperations();
  2632. }
  2633. pNTEntry->Release();
  2634. pNTEntry = NULL;
  2635. //
  2636. // If this is a completion, set result and remove it from the request list and handle table
  2637. //
  2638. if (pRequest)
  2639. {
  2640. DNEnterCriticalSection(&pdnObject->csActiveList);
  2641. pRequest->m_bilinkActiveList.RemoveFromList();
  2642. DNLeaveCriticalSection(&pdnObject->csActiveList);
  2643. pRequest->SetResult( DPN_OK );
  2644. if (SUCCEEDED(pdnObject->HandleTable.Destroy( pMsg->hCompletionOp, NULL )))
  2645. {
  2646. // Release the HandleTable reference
  2647. pRequest->Release();
  2648. }
  2649. pRequest->Release();
  2650. pRequest = NULL;
  2651. }
  2652. hResultCode = DPN_OK;
  2653. Exit:
  2654. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  2655. return(hResultCode);
  2656. Failure:
  2657. if (pRequest)
  2658. {
  2659. pRequest->Release();
  2660. pRequest = NULL;
  2661. }
  2662. if (pNTEntry)
  2663. {
  2664. pNTEntry->Release();
  2665. pNTEntry = NULL;
  2666. }
  2667. if (pLocalPlayer)
  2668. {
  2669. pLocalPlayer->Release();
  2670. pLocalPlayer = NULL;
  2671. }
  2672. goto Exit;
  2673. }
  2674. #undef DPF_MODNAME
  2675. #define DPF_MODNAME "DNProcessDestroyGroup"
  2676. HRESULT DNProcessDestroyGroup(DIRECTNETOBJECT *const pdnObject,
  2677. void *const pvBuffer)
  2678. {
  2679. HRESULT hResultCode;
  2680. DWORD dwVersion;
  2681. CNameTableEntry *pLocalPlayer;
  2682. CAsyncOp *pRequest;
  2683. UNALIGNED DN_INTERNAL_MESSAGE_DESTROY_GROUP *pMsg;
  2684. DPFX(DPFPREP, 4,"Parameters: pvBuffer [0x%p]",pvBuffer);
  2685. DNASSERT(pdnObject != NULL);
  2686. DNASSERT(pvBuffer != NULL);
  2687. pLocalPlayer = NULL;
  2688. pRequest = NULL;
  2689. pMsg = static_cast<DN_INTERNAL_MESSAGE_DESTROY_GROUP*>(pvBuffer);
  2690. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  2691. {
  2692. DPFERR("Could not get local player reference");
  2693. DisplayDNError(0,hResultCode);
  2694. goto Failure;
  2695. }
  2696. //
  2697. // Destroy Group
  2698. //
  2699. dwVersion = pMsg->dwVersion;
  2700. if ((hResultCode = pdnObject->NameTable.DeleteGroup(pMsg->dpnidGroup,&dwVersion)) != DPN_OK)
  2701. {
  2702. DPFERR("Could not delete group from NameTable");
  2703. DisplayDNError(0,hResultCode);
  2704. //
  2705. // Update version in any event (to prevent NameTable hangs)
  2706. //
  2707. pdnObject->NameTable.WriteLock();
  2708. pdnObject->NameTable.SetVersion( pMsg->dwVersion );
  2709. pdnObject->NameTable.Unlock();
  2710. goto Failure;
  2711. }
  2712. //
  2713. // If this is a completion, set the result and remove it from the request list and handle table
  2714. //
  2715. if (pMsg->dpnidRequesting == pLocalPlayer->GetDPNID())
  2716. {
  2717. if ((hResultCode = pdnObject->HandleTable.Destroy( pMsg->hCompletionOp,(PVOID*)&pRequest )) != DPN_OK)
  2718. {
  2719. DPFERR("Could not find REQUEST AsyncOp");
  2720. DisplayDNError(0,hResultCode);
  2721. DNASSERT(FALSE);
  2722. goto Failure;
  2723. }
  2724. DNEnterCriticalSection(&pdnObject->csActiveList);
  2725. pRequest->m_bilinkActiveList.RemoveFromList();
  2726. DNLeaveCriticalSection(&pdnObject->csActiveList);
  2727. pRequest->SetResult( DPN_OK );
  2728. pRequest->Release();
  2729. pRequest = NULL;
  2730. }
  2731. pLocalPlayer->Release();
  2732. pLocalPlayer = NULL;
  2733. hResultCode = DPN_OK;
  2734. Exit:
  2735. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  2736. return(hResultCode);
  2737. Failure:
  2738. if (pRequest)
  2739. {
  2740. pRequest->Release();
  2741. pRequest = NULL;
  2742. }
  2743. if (pLocalPlayer)
  2744. {
  2745. pLocalPlayer->Release();
  2746. pLocalPlayer = NULL;
  2747. }
  2748. goto Exit;
  2749. }
  2750. #undef DPF_MODNAME
  2751. #define DPF_MODNAME "DNProcessAddPlayerToGroup"
  2752. HRESULT DNProcessAddPlayerToGroup(DIRECTNETOBJECT *const pdnObject,
  2753. void *const pvBuffer)
  2754. {
  2755. HRESULT hResultCode;
  2756. DWORD dwVersion;
  2757. CNameTableEntry *pLocalPlayer;
  2758. CNameTableEntry *pGroup;
  2759. CNameTableEntry *pPlayer;
  2760. CAsyncOp *pRequest;
  2761. UNALIGNED DN_INTERNAL_MESSAGE_ADD_PLAYER_TO_GROUP *pMsg;
  2762. DPFX(DPFPREP, 4,"Parameters: pvBuffer [0x%p]",pvBuffer);
  2763. DNASSERT(pdnObject != NULL);
  2764. DNASSERT(pvBuffer != NULL);
  2765. pLocalPlayer = NULL;
  2766. pGroup = NULL;
  2767. pPlayer = NULL;
  2768. pRequest = NULL;
  2769. pMsg = static_cast<DN_INTERNAL_MESSAGE_ADD_PLAYER_TO_GROUP*>(pvBuffer);
  2770. //
  2771. // Get NameTable entries
  2772. //
  2773. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  2774. {
  2775. DPFERR("Could not get local player reference");
  2776. DisplayDNError(0,hResultCode);
  2777. goto Failure;
  2778. }
  2779. if ((hResultCode = pdnObject->NameTable.FindEntry(pMsg->dpnidGroup,&pGroup)) != DPN_OK)
  2780. {
  2781. DPFERR("Could not find group");
  2782. DisplayDNError(0,hResultCode);
  2783. //
  2784. // Update version in any event (to prevent NameTable hangs)
  2785. //
  2786. pdnObject->NameTable.WriteLock();
  2787. pdnObject->NameTable.SetVersion( pMsg->dwVersion );
  2788. pdnObject->NameTable.Unlock();
  2789. goto Failure;
  2790. }
  2791. if ((hResultCode = pdnObject->NameTable.FindEntry(pMsg->dpnidPlayer,&pPlayer)) != DPN_OK)
  2792. {
  2793. DPFERR("Could not find player");
  2794. DisplayDNError(0,hResultCode);
  2795. //
  2796. // Update version in any event (to prevent NameTable hangs)
  2797. //
  2798. pdnObject->NameTable.WriteLock();
  2799. pdnObject->NameTable.SetVersion( pMsg->dwVersion );
  2800. pdnObject->NameTable.Unlock();
  2801. goto Failure;
  2802. }
  2803. //
  2804. // Add Player To Group
  2805. //
  2806. dwVersion = pMsg->dwVersion;
  2807. if ((hResultCode = pdnObject->NameTable.AddPlayerToGroup(pGroup,pPlayer,&dwVersion)) != DPN_OK)
  2808. {
  2809. DPFERR("Could not add player to group");
  2810. DisplayDNError(0,hResultCode);
  2811. DNASSERT(FALSE);
  2812. goto Failure;
  2813. }
  2814. pGroup->Release();
  2815. pGroup = NULL;
  2816. pPlayer->Release();
  2817. pPlayer = NULL;
  2818. //
  2819. // If this is a completion, set result and remove it from the request list and handle table
  2820. //
  2821. if (pMsg->dpnidRequesting == pLocalPlayer->GetDPNID())
  2822. {
  2823. if ((hResultCode = pdnObject->HandleTable.Destroy( pMsg->hCompletionOp,(PVOID*)&pRequest )) != DPN_OK)
  2824. {
  2825. DPFERR("Could not find REQUEST AsyncOp");
  2826. DisplayDNError(0,hResultCode);
  2827. DNASSERT(FALSE);
  2828. goto Failure;
  2829. }
  2830. DNEnterCriticalSection(&pdnObject->csActiveList);
  2831. pRequest->m_bilinkActiveList.RemoveFromList();
  2832. DNLeaveCriticalSection(&pdnObject->csActiveList);
  2833. pRequest->SetResult( DPN_OK );
  2834. pRequest->Release();
  2835. pRequest = NULL;
  2836. }
  2837. pLocalPlayer->Release();
  2838. pLocalPlayer = NULL;
  2839. hResultCode = DPN_OK;
  2840. Exit:
  2841. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  2842. return(hResultCode);
  2843. Failure:
  2844. if (pRequest)
  2845. {
  2846. pRequest->Release();
  2847. pRequest = NULL;
  2848. }
  2849. if (pLocalPlayer)
  2850. {
  2851. pLocalPlayer->Release();
  2852. pLocalPlayer = NULL;
  2853. }
  2854. if (pGroup)
  2855. {
  2856. pGroup->Release();
  2857. pGroup = NULL;
  2858. }
  2859. if (pPlayer)
  2860. {
  2861. pPlayer->Release();
  2862. pPlayer = NULL;
  2863. }
  2864. goto Exit;
  2865. }
  2866. #undef DPF_MODNAME
  2867. #define DPF_MODNAME "DNProcessDeletePlayerFromGroup"
  2868. HRESULT DNProcessDeletePlayerFromGroup(DIRECTNETOBJECT *const pdnObject,
  2869. void *const pvBuffer)
  2870. {
  2871. HRESULT hResultCode;
  2872. DWORD dwVersion;
  2873. CNameTableEntry *pLocalPlayer;
  2874. CNameTableEntry *pGroup;
  2875. CNameTableEntry *pPlayer;
  2876. CAsyncOp *pRequest;
  2877. UNALIGNED DN_INTERNAL_MESSAGE_DELETE_PLAYER_FROM_GROUP *pMsg;
  2878. DPFX(DPFPREP, 4,"Parameters: pvBuffer [0x%p]",pvBuffer);
  2879. DNASSERT(pdnObject != NULL);
  2880. DNASSERT(pvBuffer != NULL);
  2881. pLocalPlayer = NULL;
  2882. pGroup = NULL;
  2883. pPlayer = NULL;
  2884. pRequest = NULL;
  2885. pMsg = static_cast<DN_INTERNAL_MESSAGE_DELETE_PLAYER_FROM_GROUP*>(pvBuffer);
  2886. //
  2887. // Get NameTable entries
  2888. //
  2889. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  2890. {
  2891. DPFERR("Could not get local player reference");
  2892. DisplayDNError(0,hResultCode);
  2893. goto Failure;
  2894. }
  2895. if ((hResultCode = pdnObject->NameTable.FindEntry(pMsg->dpnidGroup,&pGroup)) != DPN_OK)
  2896. {
  2897. DPFERR("Could not find group");
  2898. DisplayDNError(0,hResultCode);
  2899. //
  2900. // Update version in any event (to prevent NameTable hangs)
  2901. //
  2902. pdnObject->NameTable.WriteLock();
  2903. pdnObject->NameTable.SetVersion( pMsg->dwVersion );
  2904. pdnObject->NameTable.Unlock();
  2905. goto Failure;
  2906. }
  2907. if ((hResultCode = pdnObject->NameTable.FindEntry(pMsg->dpnidPlayer,&pPlayer)) != DPN_OK)
  2908. {
  2909. DPFERR("Could not find player");
  2910. DisplayDNError(0,hResultCode);
  2911. //
  2912. // Update version in any event (to prevent NameTable hangs)
  2913. //
  2914. pdnObject->NameTable.WriteLock();
  2915. pdnObject->NameTable.SetVersion( pMsg->dwVersion );
  2916. pdnObject->NameTable.Unlock();
  2917. goto Failure;
  2918. }
  2919. //
  2920. // Delete Player From Group
  2921. //
  2922. dwVersion = pMsg->dwVersion;
  2923. if ((hResultCode = pdnObject->NameTable.RemovePlayerFromGroup(pGroup,pPlayer,&dwVersion)) != DPN_OK)
  2924. {
  2925. DPFERR("Could not delete player from group");
  2926. DisplayDNError(0,hResultCode);
  2927. goto Failure;
  2928. }
  2929. pGroup->Release();
  2930. pGroup = NULL;
  2931. pPlayer->Release();
  2932. pPlayer = NULL;
  2933. //
  2934. // If this is a completion, set the result and remove it from the request list and handle table
  2935. //
  2936. if (pMsg->dpnidRequesting == pLocalPlayer->GetDPNID())
  2937. {
  2938. if ((hResultCode = pdnObject->HandleTable.Destroy( pMsg->hCompletionOp,(PVOID*)&pRequest )) != DPN_OK)
  2939. {
  2940. DPFERR("Could not find REQUEST AsyncOp");
  2941. DisplayDNError(0,hResultCode);
  2942. DNASSERT(FALSE);
  2943. goto Failure;
  2944. }
  2945. DNEnterCriticalSection(&pdnObject->csActiveList);
  2946. pRequest->m_bilinkActiveList.RemoveFromList();
  2947. DNLeaveCriticalSection(&pdnObject->csActiveList);
  2948. pRequest->SetResult( DPN_OK );
  2949. pRequest->Release();
  2950. pRequest = NULL;
  2951. }
  2952. pLocalPlayer->Release();
  2953. pLocalPlayer = NULL;
  2954. hResultCode = DPN_OK;
  2955. Exit:
  2956. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  2957. return(hResultCode);
  2958. Failure:
  2959. if (pRequest)
  2960. {
  2961. pRequest->Release();
  2962. pRequest = NULL;
  2963. }
  2964. if (pLocalPlayer)
  2965. {
  2966. pLocalPlayer->Release();
  2967. pLocalPlayer = NULL;
  2968. }
  2969. if (pGroup)
  2970. {
  2971. pGroup->Release();
  2972. pGroup = NULL;
  2973. }
  2974. if (pPlayer)
  2975. {
  2976. pPlayer->Release();
  2977. pPlayer = NULL;
  2978. }
  2979. goto Exit;
  2980. }
  2981. #undef DPF_MODNAME
  2982. #define DPF_MODNAME "DNProcessUpdateInfo"
  2983. HRESULT DNProcessUpdateInfo(DIRECTNETOBJECT *const pdnObject,
  2984. void *const pvBuffer)
  2985. {
  2986. HRESULT hResultCode;
  2987. PWSTR pwszName;
  2988. PVOID pvData;
  2989. CNameTableEntry *pLocalPlayer;
  2990. CNameTableEntry *pNTEntry;
  2991. CAsyncOp *pRequest;
  2992. UNALIGNED DN_INTERNAL_MESSAGE_UPDATE_INFO *pMsg;
  2993. BOOL fDoUpdate = TRUE;
  2994. DPFX(DPFPREP, 4,"Parameters: pvBuffer [0x%p]",pvBuffer);
  2995. DNASSERT(pdnObject != NULL);
  2996. DNASSERT(pvBuffer != NULL);
  2997. pLocalPlayer = NULL;
  2998. pNTEntry = NULL;
  2999. pRequest = NULL;
  3000. pMsg = static_cast<DN_INTERNAL_MESSAGE_UPDATE_INFO*>(pvBuffer);
  3001. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  3002. {
  3003. DPFERR("Could not get local player reference");
  3004. DisplayDNError(0,hResultCode);
  3005. goto Failure;
  3006. }
  3007. if (pdnObject->dwFlags & DN_OBJECT_FLAG_PEER)
  3008. {
  3009. //
  3010. // Update Info
  3011. //
  3012. if ((hResultCode = pdnObject->NameTable.FindEntry(pMsg->dpnid,&pNTEntry)) != DPN_OK)
  3013. {
  3014. DPFERR("Could not find NameTableEntry");
  3015. DisplayDNError(0,hResultCode);
  3016. //
  3017. // Update version in any event (to prevent NameTable hangs)
  3018. //
  3019. pdnObject->NameTable.WriteLock();
  3020. pdnObject->NameTable.SetVersion( pMsg->dwVersion );
  3021. pdnObject->NameTable.Unlock();
  3022. goto Failure;
  3023. }
  3024. }
  3025. else
  3026. {
  3027. DNASSERT(pdnObject->dwFlags & DN_OBJECT_FLAG_CLIENT);
  3028. // We are either being told that the host info has changed by a call
  3029. // on the Host to SetServerInfo, or we are being told that our own
  3030. // request to the server to change this Client's info has completed.
  3031. if ((hResultCode = pdnObject->NameTable.GetHostPlayerRef(&pNTEntry)) != DPN_OK)
  3032. {
  3033. DPFERR("Could not find Host NameTableEntry");
  3034. DisplayDNError(0,hResultCode);
  3035. DNASSERT(FALSE);
  3036. goto Failure;
  3037. }
  3038. if (pNTEntry->GetDPNID() == pMsg->dpnid)
  3039. {
  3040. DPFX(DPFPREP, 5,"Updating server info");
  3041. }
  3042. else if (pLocalPlayer->GetDPNID() == pMsg->dpnid)
  3043. {
  3044. fDoUpdate = FALSE;
  3045. DPFX(DPFPREP, 5,"Completing updating client info");
  3046. }
  3047. else
  3048. {
  3049. DPFERR("Received UpdateInfo for bad DPNID");
  3050. DisplayDNError(0,hResultCode);
  3051. DNASSERT(FALSE);
  3052. goto Failure;
  3053. }
  3054. }
  3055. if (fDoUpdate)
  3056. {
  3057. if ((pMsg->dwInfoFlags & DPNINFO_NAME) && (pMsg->dwNameOffset))
  3058. {
  3059. pwszName = reinterpret_cast<WCHAR*>(static_cast<BYTE*>(pvBuffer) + pMsg->dwNameOffset);
  3060. }
  3061. else
  3062. {
  3063. pwszName = NULL;
  3064. }
  3065. if ((pMsg->dwInfoFlags & DPNINFO_DATA) && (pMsg->dwDataOffset))
  3066. {
  3067. pvData = static_cast<void*>(static_cast<BYTE*>(pvBuffer) + pMsg->dwDataOffset);
  3068. }
  3069. else
  3070. {
  3071. pvData = NULL;
  3072. }
  3073. // This function takes the lock internally
  3074. pNTEntry->UpdateEntryInfo(pwszName,pMsg->dwNameSize,pvData,pMsg->dwDataSize,pMsg->dwInfoFlags, TRUE);
  3075. }
  3076. pNTEntry->Release();
  3077. pNTEntry = NULL;
  3078. //
  3079. // Set NameTable version
  3080. //
  3081. pdnObject->NameTable.WriteLock();
  3082. pdnObject->NameTable.SetVersion(pMsg->dwVersion);
  3083. pdnObject->NameTable.Unlock();
  3084. //
  3085. // If this is a completion, set the result and remove it from the request list and handle table
  3086. //
  3087. if (pMsg->dpnidRequesting == pLocalPlayer->GetDPNID())
  3088. {
  3089. if ((hResultCode = pdnObject->HandleTable.Destroy( pMsg->hCompletionOp,(PVOID*)&pRequest )) != DPN_OK)
  3090. {
  3091. DPFERR("Could not find REQUEST AsyncOp");
  3092. DisplayDNError(0,hResultCode);
  3093. DNASSERT(FALSE);
  3094. goto Failure;
  3095. }
  3096. DNEnterCriticalSection(&pdnObject->csActiveList);
  3097. pRequest->m_bilinkActiveList.RemoveFromList();
  3098. DNLeaveCriticalSection(&pdnObject->csActiveList);
  3099. pRequest->SetResult( DPN_OK );
  3100. pRequest->Release();
  3101. pRequest = NULL;
  3102. }
  3103. pLocalPlayer->Release();
  3104. pLocalPlayer = NULL;
  3105. hResultCode = DPN_OK;
  3106. Exit:
  3107. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  3108. return(hResultCode);
  3109. Failure:
  3110. if (pRequest)
  3111. {
  3112. pRequest->Release();
  3113. pRequest = NULL;
  3114. }
  3115. if (pLocalPlayer)
  3116. {
  3117. pLocalPlayer->Release();
  3118. pLocalPlayer = NULL;
  3119. }
  3120. goto Exit;
  3121. }
  3122. #undef DPF_MODNAME
  3123. #define DPF_MODNAME "DNProcessFailedRequest"
  3124. HRESULT DNProcessFailedRequest(DIRECTNETOBJECT *const pdnObject,
  3125. void *const pvBuffer)
  3126. {
  3127. HRESULT hResultCode;
  3128. CAsyncOp *pRequest;
  3129. UNALIGNED DN_INTERNAL_MESSAGE_REQUEST_FAILED *pMsg;
  3130. DPFX(DPFPREP, 4,"Parameters: pvBuffer [0x%p]",pvBuffer);
  3131. DNASSERT(pdnObject != NULL);
  3132. DNASSERT(pvBuffer != NULL);
  3133. pRequest = NULL;
  3134. pMsg = static_cast<DN_INTERNAL_MESSAGE_REQUEST_FAILED*>(pvBuffer);
  3135. //
  3136. // Update request using handle to HRESULT passed back by Host, and remove request from request list and handle table
  3137. //
  3138. if ((hResultCode = pdnObject->HandleTable.Destroy( pMsg->hCompletionOp, (PVOID*)&pRequest )) == DPN_OK)
  3139. {
  3140. DNASSERT( pMsg->hCompletionOp != 0 );
  3141. DNEnterCriticalSection(&pdnObject->csActiveList);
  3142. pRequest->m_bilinkActiveList.RemoveFromList();
  3143. DNLeaveCriticalSection(&pdnObject->csActiveList);
  3144. pRequest->SetResult( pMsg->hResultCode );
  3145. pRequest->Release();
  3146. pRequest = NULL;
  3147. }
  3148. hResultCode = DPN_OK;
  3149. DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode);
  3150. return(hResultCode);
  3151. }
  3152. // DNProcessCheckIntegrity
  3153. //
  3154. // The host is performing an integrity check and is asking the local player (us) if we are still
  3155. // in the session. We will respond that we are, and the host will drop the requesting player.
  3156. #undef DPF_MODNAME
  3157. #define DPF_MODNAME "DNProcessCheckIntegrity"
  3158. HRESULT DNProcessCheckIntegrity(DIRECTNETOBJECT *const pdnObject,
  3159. void *const pvBuffer)
  3160. {
  3161. HRESULT hResultCode;
  3162. CNameTableEntry *pHostPlayer;
  3163. CConnection *pConnection;
  3164. CRefCountBuffer *pRefCountBuffer;
  3165. UNALIGNED DN_INTERNAL_MESSAGE_INTEGRITY_CHECK *pMsg;
  3166. DN_INTERNAL_MESSAGE_INTEGRITY_CHECK_RESPONSE *pResponse;
  3167. DPFX(DPFPREP, 6,"Parameters: pvBuffer [0x%p]",pvBuffer);
  3168. DNASSERT(pdnObject != NULL);
  3169. DNASSERT(pvBuffer != NULL);
  3170. pHostPlayer = NULL;
  3171. pConnection = NULL;
  3172. pRefCountBuffer = NULL;
  3173. //
  3174. // Get host player connection to respond to
  3175. //
  3176. if ((hResultCode = pdnObject->NameTable.GetHostPlayerRef( &pHostPlayer )) != DPN_OK)
  3177. {
  3178. DPFERR("Could not get host player reference");
  3179. DisplayDNError(0,hResultCode);
  3180. goto Failure;
  3181. }
  3182. if ((hResultCode = pHostPlayer->GetConnectionRef( &pConnection )) != DPN_OK)
  3183. {
  3184. DPFERR("Could not get host player connection reference");
  3185. DisplayDNError(0,hResultCode);
  3186. goto Failure;
  3187. }
  3188. pHostPlayer->Release();
  3189. pHostPlayer = NULL;
  3190. //
  3191. // Create response
  3192. //
  3193. if ((hResultCode = RefCountBufferNew(pdnObject,sizeof(DN_INTERNAL_MESSAGE_INTEGRITY_CHECK_RESPONSE),MemoryBlockAlloc,MemoryBlockFree,&pRefCountBuffer)) != DPN_OK)
  3194. {
  3195. DPFERR("Could not create RefCountBuffer");
  3196. DisplayDNError(0,hResultCode);
  3197. DNASSERT(FALSE);
  3198. goto Failure;
  3199. }
  3200. pResponse = reinterpret_cast<DN_INTERNAL_MESSAGE_INTEGRITY_CHECK_RESPONSE*>(pRefCountBuffer->GetBufferAddress());
  3201. pMsg = static_cast<DN_INTERNAL_MESSAGE_INTEGRITY_CHECK*>(pvBuffer);
  3202. pResponse->dpnidRequesting = pMsg->dpnidRequesting;
  3203. //
  3204. // Send response
  3205. //
  3206. if ((hResultCode = DNSendMessage( pdnObject,
  3207. pConnection,
  3208. DN_MSG_INTERNAL_INTEGRITY_CHECK_RESPONSE,
  3209. pConnection->GetDPNID(),
  3210. pRefCountBuffer->BufferDescAddress(),
  3211. 1,
  3212. pRefCountBuffer,
  3213. 0,
  3214. DN_SENDFLAGS_RELIABLE,
  3215. NULL,
  3216. NULL )) != DPNERR_PENDING)
  3217. {
  3218. DPFERR("Could not send integrity check response");
  3219. DisplayDNError(0,hResultCode);
  3220. DNASSERT(hResultCode != DPN_OK); // it was sent guaranteed, it should not return immediately
  3221. goto Failure;
  3222. }
  3223. pConnection->Release();
  3224. pConnection = NULL;
  3225. pRefCountBuffer->Release();
  3226. pRefCountBuffer = NULL;
  3227. hResultCode = DPN_OK;
  3228. Exit:
  3229. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  3230. return(hResultCode);
  3231. Failure:
  3232. if (pHostPlayer)
  3233. {
  3234. pHostPlayer->Release();
  3235. pHostPlayer = NULL;
  3236. }
  3237. if (pConnection)
  3238. {
  3239. pConnection->Release();
  3240. pConnection = NULL;
  3241. }
  3242. if (pRefCountBuffer)
  3243. {
  3244. pRefCountBuffer->Release();
  3245. pRefCountBuffer = NULL;
  3246. }
  3247. goto Exit;
  3248. }