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.

629 lines
20 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Enum.cpp
  6. * Content: Enumeration routines
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 04/10/00 mjn Created
  12. * 04/17/00 mjn Fixed DNCompleteEnumQuery to clean up properly
  13. * 04/18/00 mjn Return User Buffer in DNProcessEnumQuery
  14. * 04/19/00 mjn Removed DPN_BUFFER_DESC from DPNMSG_ENUM_HOSTS_QUERY and DPNMSG_ENUM_HOSTS_RESPONSE structs
  15. * 05/02/00 mjn Allow application to reject ENUM_QUERY's
  16. * 06/25/00 mjn Fixed payload problem in DNProcessEnumQuery()
  17. * 07/10/00 mjn Removed DNCompleteEnumQuery() and DNCompleteEnumResponse()
  18. * 07/12/00 mjn Ensure connected before replying to ENUMs
  19. * 07/29/00 mjn Verify enum responses sizes
  20. * 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  21. * 08/05/00 mjn Ensure cancelled operations don't proceed
  22. * 08/29/00 mjn Cancel EnumHosts if non-DPN_OK returned from response notification
  23. * 09/04/00 mjn Added CApplicationDesc
  24. * 09/14/00 mjn AddRef Protocol refcount when invoking protocol
  25. * 01/22/01 mjn Add SP reference on AsyncOp in DNProcessEnumQuery()
  26. * 01/25/01 mjn Fixed 64-bit alignment problem in received messages
  27. * 03/13/01 mjn Don't copy user response buffer when responding to enums
  28. *@@END_MSINTERNAL
  29. *
  30. ***************************************************************************/
  31. #include "dncorei.h"
  32. //**********************************************************************
  33. // ------------------------------
  34. // DNProcessEnumQuery - process enum query
  35. //
  36. // Entry: Pointer to this DNet interface object
  37. // Pointer to the associated listen operation
  38. // Pointer to protocol's enum data
  39. //
  40. // Exit: Nothing
  41. // ------------------------------
  42. #undef DPF_MODNAME
  43. #define DPF_MODNAME "DNProcessEnumQuery"
  44. void DNProcessEnumQuery(DIRECTNETOBJECT *const pdnObject,
  45. CAsyncOp *const pListen,
  46. const PROTOCOL_ENUM_DATA *const pEnumQueryData )
  47. {
  48. HRESULT hResultCode;
  49. DPNMSG_ENUM_HOSTS_QUERY AppData;
  50. CPackedBuffer PackedBuffer;
  51. CRefCountBuffer *pRefCountBuffer;
  52. CAsyncOp *pAsyncOp;
  53. HANDLE hProtocol;
  54. const DN_ENUM_QUERY_PAYLOAD *pEnumQueryPayload;
  55. DN_ENUM_RESPONSE_OP_DATA *pEnumResponseOpData;
  56. DN_ENUM_RESPONSE_PAYLOAD *pEnumResponsePayload;
  57. DWORD dwPayloadOffset;
  58. IDP8ServiceProvider *pIDP8SP;
  59. SPGETCAPSDATA spGetCapsData;
  60. CServiceProvider *pSP;
  61. DWORD dwBufferCount;
  62. BOOL fNeedToReturnBuffer;
  63. DPFX(DPFPREP, 6,"Parameters: pListen [0x%p], pEnumQueryData [0x%p]",pListen,pEnumQueryData);
  64. DNASSERT( pdnObject != NULL );
  65. DNASSERT( pListen != NULL );
  66. DNASSERT( pEnumQueryData != NULL );
  67. pAsyncOp = NULL;
  68. pRefCountBuffer = NULL;
  69. pIDP8SP = NULL;
  70. pSP = NULL;
  71. fNeedToReturnBuffer = FALSE; // Is this needed ?
  72. //
  73. // Ensure we are in a position to reply to this message.
  74. // We must be CONNECTED and not be HOST_MIGRATING
  75. //
  76. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  77. if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTED) || (pdnObject->dwFlags & DN_OBJECT_FLAG_HOST_MIGRATING))
  78. {
  79. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  80. DPFX(DPFPREP, 7, "Not connected or host is migrating (object 0x%p flags = 0x%x), ignoring enum.", pdnObject, pdnObject->dwFlags);
  81. goto Failure;
  82. }
  83. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  84. //
  85. // Check to see if this message is for this game type. Since the application
  86. // GUID cannot be changed while the session is running, there's no need to
  87. // enter a critical section.
  88. //
  89. pEnumQueryPayload = reinterpret_cast<DN_ENUM_QUERY_PAYLOAD*>( pEnumQueryData->ReceivedData.pBufferData );
  90. if ( pEnumQueryPayload == NULL )
  91. {
  92. //
  93. // no enum payload (there needs to be at least one byte!)
  94. //
  95. DPFX(DPFPREP, 4, "No enum payload, object 0x%p ignoring enum.", pdnObject);
  96. goto Failure;
  97. }
  98. dwPayloadOffset = 0;
  99. switch ( pEnumQueryPayload->QueryType )
  100. {
  101. //
  102. // an application guid was specified, make sure it matches this application's
  103. // guid before further processing
  104. //
  105. case DN_ENUM_QUERY_WITH_APPLICATION_GUID:
  106. {
  107. if ( pEnumQueryData->ReceivedData.dwBufferSize < sizeof( DN_ENUM_QUERY_PAYLOAD ) )
  108. {
  109. DNASSERTX( ! "Received data too small to be valid enum query with application guid!", 2 );
  110. goto Failure;
  111. }
  112. if ( !pdnObject->ApplicationDesc.IsEqualApplicationGuid( &pEnumQueryPayload->guidApplication ) )
  113. {
  114. #ifdef DBG
  115. GUID guidApplication;
  116. //
  117. // GUID might not be aligned, so copy it to a temp variable
  118. //
  119. guidApplication = pEnumQueryPayload->guidApplication;
  120. DPFX(DPFPREP, 7, "Application GUID {%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X} doesn't match, object 0x%p, ignoring enum.",
  121. guidApplication.Data1,
  122. guidApplication.Data2,
  123. guidApplication.Data3,
  124. guidApplication.Data4[0],
  125. guidApplication.Data4[1],
  126. guidApplication.Data4[2],
  127. guidApplication.Data4[3],
  128. guidApplication.Data4[4],
  129. guidApplication.Data4[5],
  130. guidApplication.Data4[6],
  131. guidApplication.Data4[7],
  132. pdnObject);
  133. #endif // DBG
  134. goto Failure;
  135. }
  136. dwPayloadOffset = sizeof( DN_ENUM_QUERY_PAYLOAD );
  137. break;
  138. }
  139. //
  140. // no application guid was specified, continue processing
  141. //
  142. case DN_ENUM_QUERY_WITHOUT_APPLICATION_GUID:
  143. {
  144. if ( pEnumQueryData->ReceivedData.dwBufferSize < ( sizeof( DN_ENUM_QUERY_PAYLOAD ) - sizeof( GUID ) ) )
  145. {
  146. DNASSERTX( ! "Received data too small to be valid enum query without application guid!", 2 );
  147. goto Failure;
  148. }
  149. dwPayloadOffset = sizeof( DN_ENUM_QUERY_PAYLOAD ) - sizeof( GUID );
  150. break;
  151. }
  152. default:
  153. {
  154. DNASSERTX( ! "Unrecognized enum query payload type!", 2 );
  155. goto Failure;
  156. break;
  157. }
  158. }
  159. //
  160. // buld message structure, be nice and clear the user payload pointer if
  161. // there is no payload
  162. //
  163. AppData.dwSize = sizeof( AppData );
  164. AppData.pAddressSender = pEnumQueryData->pSenderAddress;
  165. AppData.pAddressDevice = pEnumQueryData->pDeviceAddress;
  166. DPFX(DPFPREP, 7,"AppData.pAddressSender: [0x%p]",AppData.pAddressSender);
  167. DPFX(DPFPREP, 7,"AppData.pAddressDevice: [0x%p]",AppData.pAddressDevice);
  168. if (pEnumQueryData->ReceivedData.dwBufferSize > dwPayloadOffset)
  169. {
  170. DNASSERT( pEnumQueryData->ReceivedData.pBufferData );
  171. DNASSERT( pEnumQueryData->ReceivedData.dwBufferSize );
  172. AppData.pvReceivedData = static_cast<void*>(static_cast<BYTE*>(pEnumQueryData->ReceivedData.pBufferData) + dwPayloadOffset);
  173. AppData.dwReceivedDataSize = pEnumQueryData->ReceivedData.dwBufferSize - dwPayloadOffset;
  174. }
  175. else
  176. {
  177. AppData.pvReceivedData = NULL;
  178. AppData.dwReceivedDataSize = 0;
  179. }
  180. //
  181. // Response Info
  182. //
  183. AppData.pvResponseData = NULL;
  184. AppData.dwResponseDataSize = 0;
  185. AppData.pvResponseContext = NULL;
  186. //
  187. // Determine max size of response
  188. // - Get SP interface from listen SP (listen's parent)
  189. // - Get SP caps on the interface to determine the total available buffer size
  190. // - Figure out what the DNET enum response size will be
  191. // - Determine space available to user
  192. //
  193. DNASSERT(pListen->GetParent() != NULL);
  194. DNASSERT(pListen->GetParent()->GetSP() != NULL);
  195. pListen->GetParent()->GetSP()->AddRef();
  196. pSP = pListen->GetParent()->GetSP();
  197. if ((hResultCode = pSP->GetInterfaceRef( &pIDP8SP )) != DPN_OK)
  198. {
  199. DPFERR("Could not get ListenSP SP interface");
  200. DisplayDNError(0,hResultCode);
  201. DNASSERT(FALSE);
  202. goto Failure;
  203. }
  204. memset( &spGetCapsData, 0x00, sizeof( SPGETCAPSDATA ) );
  205. spGetCapsData.dwSize = sizeof( SPGETCAPSDATA );
  206. spGetCapsData.hEndpoint = INVALID_HANDLE_VALUE;
  207. if ((hResultCode = IDP8ServiceProvider_GetCaps( pIDP8SP, &spGetCapsData )) != DPN_OK)
  208. {
  209. DPFERR("Could not get SP caps");
  210. DisplayDNError(0,hResultCode);
  211. goto Failure;
  212. }
  213. IDP8ServiceProvider_Release( pIDP8SP );
  214. pIDP8SP = NULL;
  215. PackedBuffer.Initialize(NULL,0);
  216. PackedBuffer.AddToFront(NULL,sizeof(DN_ENUM_RESPONSE_PAYLOAD));
  217. pdnObject->ApplicationDesc.PackInfo(&PackedBuffer,DN_APPDESCINFO_FLAG_SESSIONNAME|DN_APPDESCINFO_FLAG_RESERVEDDATA|
  218. DN_APPDESCINFO_FLAG_APPRESERVEDDATA);
  219. AppData.dwMaxResponseDataSize = spGetCapsData.dwEnumFrameSize - PackedBuffer.GetSizeRequired();
  220. //
  221. // pass message to the user
  222. //
  223. hResultCode = DNUserEnumQuery(pdnObject,&AppData);
  224. //
  225. // Only ENUMs which are accepted get responded to
  226. //
  227. if (hResultCode != DPN_OK)
  228. {
  229. DPFX(DPFPREP, 9, "EnumQuery rejected");
  230. DisplayDNError(9, hResultCode);
  231. goto Failure;
  232. }
  233. //
  234. // get an async operation to track the progress of the response
  235. //
  236. if ((hResultCode = AsyncOpNew(pdnObject,&pAsyncOp)) != DPN_OK)
  237. {
  238. DPFERR("Could not allocate Async Op struct for enum response");
  239. DisplayDNError( 0, hResultCode );
  240. DNASSERT( FALSE );
  241. goto Failure;
  242. }
  243. pAsyncOp->SetOpType( ASYNC_OP_ENUM_RESPONSE );
  244. //
  245. // compute the size needed to pack up an application description with any
  246. // user data and send it back
  247. //
  248. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  249. PackedBuffer.Initialize(NULL,0);
  250. PackedBuffer.AddToFront(NULL,sizeof(DN_ENUM_RESPONSE_PAYLOAD));
  251. hResultCode = pdnObject->ApplicationDesc.PackInfo(&PackedBuffer,DN_APPDESCINFO_FLAG_SESSIONNAME|
  252. DN_APPDESCINFO_FLAG_RESERVEDDATA|DN_APPDESCINFO_FLAG_APPRESERVEDDATA);
  253. DNASSERT( hResultCode == DPNERR_BUFFERTOOSMALL );
  254. //
  255. // Ensure this enum response will fit in SP enum frame - only indicate this if there was a response
  256. //
  257. if (((AppData.pvResponseData != NULL) && (AppData.dwResponseDataSize != 0)) &&
  258. (PackedBuffer.GetSizeRequired() + AppData.dwResponseDataSize > spGetCapsData.dwEnumFrameSize))
  259. {
  260. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  261. DPFERR("Enum response is too large");
  262. DNUserReturnBuffer(pdnObject,DPNERR_ENUMRESPONSETOOLARGE,AppData.pvResponseData,AppData.pvResponseContext);
  263. goto Failure;
  264. }
  265. hResultCode = RefCountBufferNew(pdnObject,
  266. PackedBuffer.GetSizeRequired(),
  267. EnumReplyMemoryBlockAlloc,
  268. EnumReplyMemoryBlockFree,
  269. &pRefCountBuffer);
  270. if ( hResultCode != DPN_OK )
  271. {
  272. DNASSERT( FALSE );
  273. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  274. goto Failure;
  275. }
  276. PackedBuffer.Initialize(pRefCountBuffer->GetBufferAddress(),
  277. pRefCountBuffer->GetBufferSize());
  278. pEnumResponsePayload = static_cast<DN_ENUM_RESPONSE_PAYLOAD*>(PackedBuffer.GetHeadAddress());
  279. hResultCode = PackedBuffer.AddToFront(NULL,sizeof(DN_ENUM_RESPONSE_PAYLOAD));
  280. if (hResultCode != DPN_OK)
  281. {
  282. DNASSERT(FALSE);
  283. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  284. goto Failure;
  285. }
  286. if ((AppData.pvResponseData != NULL) && (AppData.dwResponseDataSize != 0))
  287. {
  288. pEnumResponsePayload->dwResponseOffset = pRefCountBuffer->GetBufferSize();
  289. pEnumResponsePayload->dwResponseSize = AppData.dwResponseDataSize;
  290. }
  291. else
  292. {
  293. pEnumResponsePayload->dwResponseOffset = 0;
  294. pEnumResponsePayload->dwResponseSize = 0;
  295. }
  296. pdnObject->ApplicationDesc.PackInfo(&PackedBuffer,DN_APPDESCINFO_FLAG_SESSIONNAME|DN_APPDESCINFO_FLAG_RESERVEDDATA|
  297. DN_APPDESCINFO_FLAG_APPRESERVEDDATA);
  298. if ( hResultCode != DPN_OK )
  299. {
  300. DNASSERT( FALSE );
  301. goto Failure;
  302. }
  303. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  304. //
  305. // build enum response and send it down to the protocol
  306. //
  307. pEnumResponseOpData = pAsyncOp->GetLocalEnumResponseOpData();
  308. pEnumResponseOpData->BufferDesc[DN_ENUM_BUFFERDESC_RESPONSE_DN_PAYLOAD].pBufferData = pRefCountBuffer->GetBufferAddress();
  309. pEnumResponseOpData->BufferDesc[DN_ENUM_BUFFERDESC_RESPONSE_DN_PAYLOAD].dwBufferSize = pRefCountBuffer->GetBufferSize();
  310. pAsyncOp->SetCompletion( DNCompleteEnumResponse );
  311. pAsyncOp->SetRefCountBuffer( pRefCountBuffer );
  312. pRefCountBuffer->Release();
  313. pRefCountBuffer = NULL;
  314. if ((AppData.pvResponseData != NULL) && (AppData.dwResponseDataSize != 0))
  315. {
  316. pEnumResponseOpData->BufferDesc[DN_ENUM_BUFFERDESC_RESPONSE_USER_PAYLOAD].pBufferData = static_cast<BYTE*>(AppData.pvResponseData);
  317. pEnumResponseOpData->BufferDesc[DN_ENUM_BUFFERDESC_RESPONSE_USER_PAYLOAD].dwBufferSize = AppData.dwResponseDataSize;
  318. pEnumResponseOpData->pvUserContext = AppData.pvResponseContext;
  319. dwBufferCount = DN_ENUM_BUFFERDESC_RESPONSE_COUNT;
  320. }
  321. else
  322. {
  323. pEnumResponseOpData->BufferDesc[DN_ENUM_BUFFERDESC_RESPONSE_USER_PAYLOAD].pBufferData = NULL;
  324. pEnumResponseOpData->BufferDesc[DN_ENUM_BUFFERDESC_RESPONSE_USER_PAYLOAD].dwBufferSize = 0;
  325. pEnumResponseOpData->pvUserContext = NULL;
  326. dwBufferCount = DN_ENUM_BUFFERDESC_RESPONSE_COUNT - 1;
  327. }
  328. DNASSERT(pListen->GetParent() != NULL);
  329. DNASSERT(pListen->GetParent()->GetSP() != NULL);
  330. DNASSERT(pListen->GetParent()->GetSP()->GetHandle() != NULL);
  331. //
  332. // AddRef Protocol so that it won't go away until this completes
  333. //
  334. DNProtocolAddRef(pdnObject);
  335. pAsyncOp->AddRef();
  336. hResultCode = DNPEnumRespond( pdnObject->pdnProtocolData,
  337. pListen->GetParent()->GetSP()->GetHandle(),
  338. pEnumQueryData->hEnumQuery,
  339. &pEnumResponseOpData->BufferDesc[DN_ENUM_BUFFERDESC_RESPONSE_DN_PAYLOAD],
  340. dwBufferCount,
  341. 0,
  342. reinterpret_cast<void*>(pAsyncOp),
  343. &hProtocol);
  344. if ( hResultCode != DPNERR_PENDING )
  345. {
  346. pAsyncOp->Release();
  347. DNProtocolRelease(pdnObject);
  348. goto Failure;
  349. }
  350. //
  351. // Save Protocol Handle
  352. //
  353. pAsyncOp->Lock();
  354. if (pAsyncOp->IsCancelled())
  355. {
  356. HRESULT hrCancel;
  357. pAsyncOp->Unlock();
  358. DPFX(DPFPREP, 7,"Operation marked for cancel");
  359. if ((hrCancel = DNPCancelCommand(pdnObject->pdnProtocolData,hProtocol)) == DPN_OK)
  360. {
  361. hResultCode = DPNERR_USERCANCEL;
  362. goto Failure;
  363. }
  364. DPFERR("Could not cancel operation");
  365. DisplayDNError(0,hrCancel);
  366. pAsyncOp->Lock();
  367. }
  368. pAsyncOp->SetSP( pSP );
  369. pAsyncOp->SetProtocolHandle(hProtocol);
  370. pAsyncOp->Unlock();
  371. pAsyncOp->Release();
  372. pAsyncOp = NULL;
  373. pSP->Release();
  374. pSP = NULL;
  375. Exit:
  376. DPFX(DPFPREP, 6,"Returning");
  377. return;
  378. Failure:
  379. if (pAsyncOp)
  380. {
  381. pAsyncOp->Release();
  382. pAsyncOp = NULL;
  383. }
  384. if (pRefCountBuffer)
  385. {
  386. pRefCountBuffer->Release();
  387. pRefCountBuffer = NULL;
  388. }
  389. if (pIDP8SP)
  390. {
  391. IDP8ServiceProvider_Release(pIDP8SP);
  392. pIDP8SP = NULL;
  393. }
  394. if (pSP)
  395. {
  396. pSP->Release();
  397. pSP = NULL;
  398. }
  399. goto Exit;
  400. }
  401. //**********************************************************************
  402. //**********************************************************************
  403. // ------------------------------
  404. // DNProcessEnumResponse - process response to enum query
  405. //
  406. // Entry: Pointer to this DNet interface object
  407. // Pointer to the associated enum operation
  408. // Pointer to protocol's enum response data
  409. //
  410. // Exit: Nothing
  411. // ------------------------------
  412. #undef DPF_MODNAME
  413. #define DPF_MODNAME "DNProcessEnumResponse"
  414. void DNProcessEnumResponse(DIRECTNETOBJECT *const pdnObject,
  415. CAsyncOp *const pAsyncOp,
  416. const PROTOCOL_ENUM_RESPONSE_DATA *const pEnumResponseData)
  417. {
  418. HRESULT hResultCode;
  419. DPNMSG_ENUM_HOSTS_RESPONSE AppData;
  420. BYTE *pWorkingItem;
  421. UNALIGNED DN_ENUM_RESPONSE_PAYLOAD *pEnumResponsePayload;
  422. DPN_APPLICATION_DESC dpnAppDesc;
  423. UNALIGNED DPN_APPLICATION_DESC_INFO *pInfo;
  424. BYTE AppDescReservedData[DPN_MAX_APPDESC_RESERVEDDATA_SIZE];
  425. DNASSERT( pdnObject != NULL );
  426. DNASSERT( pAsyncOp != NULL );
  427. DNASSERT( pEnumResponseData != NULL );
  428. pWorkingItem = pEnumResponseData->ReceivedData.pBufferData;
  429. //
  430. // Unpack the ENUM response.
  431. // It will be in the following format:
  432. // <UserResponseOffset>
  433. // <UserResponseSize>
  434. // <AppDescInfo>
  435. //
  436. //
  437. // Verify buffer size
  438. //
  439. if (pEnumResponseData->ReceivedData.dwBufferSize < (sizeof(DN_ENUM_RESPONSE_PAYLOAD) + sizeof(DPN_APPLICATION_DESC_INFO)))
  440. {
  441. DPFERR("Received invalid enum response - buffer is smaller than minimum size");
  442. goto Exit;
  443. }
  444. pEnumResponsePayload = reinterpret_cast<DN_ENUM_RESPONSE_PAYLOAD*>(pEnumResponseData->ReceivedData.pBufferData);
  445. //
  446. // Application Description
  447. //
  448. pInfo = reinterpret_cast<DPN_APPLICATION_DESC_INFO*>(pEnumResponsePayload + 1);
  449. memset(&dpnAppDesc,0,sizeof(DPN_APPLICATION_DESC));
  450. if (pInfo->dwSessionNameOffset)
  451. {
  452. if ((pInfo->dwSessionNameOffset > pEnumResponseData->ReceivedData.dwBufferSize) ||
  453. (pInfo->dwSessionNameOffset+pInfo->dwSessionNameSize > pEnumResponseData->ReceivedData.dwBufferSize))
  454. {
  455. DPFERR("Received invalid enum response - session name is outside of buffer");
  456. goto Exit;
  457. }
  458. dpnAppDesc.pwszSessionName = reinterpret_cast<WCHAR*>(pWorkingItem + pInfo->dwSessionNameOffset);
  459. }
  460. if (pInfo->dwReservedDataOffset)
  461. {
  462. if ((pInfo->dwReservedDataOffset > pEnumResponseData->ReceivedData.dwBufferSize) ||
  463. (pInfo->dwReservedDataOffset+pInfo->dwReservedDataSize > pEnumResponseData->ReceivedData.dwBufferSize))
  464. {
  465. DPFERR("Received invalid enum response - reserved data is outside of buffer");
  466. goto Exit;
  467. }
  468. dpnAppDesc.pvReservedData = static_cast<void*>(pWorkingItem + pInfo->dwReservedDataOffset);
  469. dpnAppDesc.dwReservedDataSize = pInfo->dwReservedDataSize;
  470. //
  471. // If we understand the reserved data, we want to pad the buffer so the user doesn't
  472. // assume the data is less than DPN_MAX_APPDESC_RESERVEDDATA_SIZE bytes long.
  473. //
  474. if ((dpnAppDesc.dwReservedDataSize == sizeof(SPSESSIONDATA_XNET)) &&
  475. (*((DWORD*) dpnAppDesc.pvReservedData) == SPSESSIONDATAINFO_XNET))
  476. {
  477. SPSESSIONDATA_XNET * pSessionDataXNet;
  478. pSessionDataXNet = (SPSESSIONDATA_XNET*) AppDescReservedData;
  479. memcpy(pSessionDataXNet, dpnAppDesc.pvReservedData, dpnAppDesc.dwReservedDataSize);
  480. memset((pSessionDataXNet + 1),
  481. (((BYTE*) (&pSessionDataXNet->ullKeyID))[1] ^ ((BYTE*) (&pSessionDataXNet->guidKey))[2]),
  482. (DPN_MAX_APPDESC_RESERVEDDATA_SIZE - sizeof(SPSESSIONDATA_XNET)));
  483. dpnAppDesc.pvReservedData = AppDescReservedData;
  484. dpnAppDesc.dwReservedDataSize = DPN_MAX_APPDESC_RESERVEDDATA_SIZE;
  485. }
  486. }
  487. if (pInfo->dwApplicationReservedDataOffset)
  488. {
  489. if ((pInfo->dwApplicationReservedDataOffset > pEnumResponseData->ReceivedData.dwBufferSize) ||
  490. (pInfo->dwApplicationReservedDataOffset+pInfo->dwApplicationReservedDataSize > pEnumResponseData->ReceivedData.dwBufferSize))
  491. {
  492. DPFERR("Received invalid enum response - application reserved data is outside of buffer");
  493. goto Exit;
  494. }
  495. dpnAppDesc.pvApplicationReservedData = static_cast<void*>(pWorkingItem + pInfo->dwApplicationReservedDataOffset);
  496. dpnAppDesc.dwApplicationReservedDataSize = pInfo->dwApplicationReservedDataSize;
  497. }
  498. dpnAppDesc.guidApplication = pInfo->guidApplication;
  499. dpnAppDesc.guidInstance = pInfo->guidInstance;
  500. dpnAppDesc.dwFlags = pInfo->dwFlags;
  501. dpnAppDesc.dwCurrentPlayers = pInfo->dwCurrentPlayers;
  502. dpnAppDesc.dwMaxPlayers = pInfo->dwMaxPlayers;
  503. dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  504. //
  505. // Fill in AppData
  506. //
  507. AppData.dwSize = sizeof( AppData );
  508. AppData.pAddressSender = pEnumResponseData->pSenderAddress;
  509. AppData.pAddressDevice = pEnumResponseData->pDeviceAddress;
  510. AppData.pApplicationDescription = &dpnAppDesc;
  511. AppData.dwRoundTripLatencyMS = pEnumResponseData->dwRoundTripTime;
  512. if (pEnumResponsePayload->dwResponseOffset)
  513. {
  514. if ((pEnumResponsePayload->dwResponseOffset > pEnumResponseData->ReceivedData.dwBufferSize) ||
  515. (pEnumResponsePayload->dwResponseOffset+pEnumResponsePayload->dwResponseSize > pEnumResponseData->ReceivedData.dwBufferSize))
  516. {
  517. DPFERR("Received invalid enum response - response data is outside of buffer");
  518. goto Exit;
  519. }
  520. AppData.pvResponseData = (pEnumResponseData->ReceivedData.pBufferData + pEnumResponsePayload->dwResponseOffset);
  521. AppData.dwResponseDataSize = pEnumResponsePayload->dwResponseSize;
  522. }
  523. else
  524. {
  525. AppData.pvResponseData = NULL;
  526. AppData.dwResponseDataSize = 0;
  527. }
  528. AppData.pvUserContext = pAsyncOp->GetContext();
  529. //
  530. // pass message to the user
  531. //
  532. hResultCode = DNUserEnumResponse(pdnObject,&AppData);
  533. //
  534. // Check to see if this is to be cancelled
  535. //
  536. if (hResultCode != DPN_OK)
  537. {
  538. CAsyncOp *pCancelOp = NULL;
  539. //
  540. // Get top level operation (may be async op handle)
  541. //
  542. pAsyncOp->Lock();
  543. pCancelOp = pAsyncOp;
  544. while (pCancelOp->IsChild())
  545. {
  546. DNASSERT(pCancelOp->GetParent() != NULL);
  547. pCancelOp = pCancelOp->GetParent();
  548. }
  549. pCancelOp->AddRef();
  550. pAsyncOp->Unlock();
  551. //
  552. // Cancel
  553. //
  554. DNCancelChildren(pdnObject,pCancelOp);
  555. pCancelOp->Release();
  556. pCancelOp = NULL;
  557. }
  558. Exit:
  559. return;
  560. }