Source code of Windows XP (NT5)
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.

622 lines
18 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Send.cpp
  6. * Content: This file contains code which implements the front end of the
  7. * SendData API. It also contains code to Get and Release Message
  8. * Descriptors (MSD) with the FPM package.
  9. *
  10. * History:
  11. * Date By Reason
  12. * ==== == ======
  13. * 11/06/98 ejs Created
  14. * 07/01/2000 masonb Assumed Ownership
  15. *
  16. ****************************************************************************/
  17. #include "dnproti.h"
  18. /*
  19. ** Direct Net Protocol -- Send Data
  20. **
  21. ** Data is always address to a PlayerID, which is represented internally
  22. ** by an End Point Descriptor (EPD).
  23. **
  24. ** Data can be sent reliably or unreliably using the same API with the appropriate
  25. ** class of service flag set.
  26. **
  27. ** Sends are never delivered directly to the SP because there will always be
  28. ** a possibility that the thread might block. So to guarentee immediate return
  29. ** we will always queue the packet and submit it on our dedicated sending thread.
  30. */
  31. #if (DN_SENDFLAGS_SET_USER_FLAG - PACKET_COMMAND_USER_1)
  32. This will not compile. Flags must be equal
  33. #endif
  34. #if (DN_SENDFLAGS_SET_USER_FLAG_TWO - PACKET_COMMAND_USER_2)
  35. This will not compile. Flags must be equal
  36. #endif
  37. // locals
  38. VOID SendDatagram(PMSD, PEPD);
  39. VOID SendReliable(PMSD, PEPD);
  40. #undef DPF_MODNAME
  41. #define DPF_MODNAME "PROTOCOL"
  42. /*
  43. ** Send Data
  44. **
  45. ** This routine will initiate a data transfer with the specified endpoint. It will
  46. ** normally start the operation and then return immediately, returning a handle used to
  47. ** indicate completion of the operation at a later time.
  48. */
  49. #undef DPF_MODNAME
  50. #define DPF_MODNAME "DNPSendData"
  51. HRESULT
  52. DNPSendData( PProtocolData pPData,
  53. HANDLE hDestination,
  54. UINT uiBufferCount,
  55. PBUFFERDESC pBufferDesc,
  56. UINT uiTimeout,
  57. ULONG ulFlags,
  58. PVOID pvContext, // User context returned upon completion
  59. PHANDLE phHandle) // Returned completion handle
  60. {
  61. PEPD pEPD;
  62. PMSD pMSD;
  63. PFMD pFMD;
  64. UINT i;
  65. UINT Length = 0;
  66. PSPD pSPD;
  67. ULONG ulFrameFlags;
  68. BYTE bCommand;
  69. // Following variables are used for mapping buffers to frames
  70. PBUFFERDESC FromBuffer, ToBuffer;
  71. UINT TotalRemain, FromRemain, ToRemain, size;
  72. PCHAR FromPtr;
  73. #ifdef DEBUG
  74. INT FromBufferCount;
  75. #endif
  76. // End of variables for mapping frames
  77. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pPData[%p], hDestination[%x], uiBufferCount[%x], pBufferDesc[%p], uiTimeout[%x], ulFlags[%x], pvContext[%p], phHandle[%p]", pPData, hDestination, uiBufferCount, pBufferDesc, uiTimeout, ulFlags, pvContext, phHandle);
  78. // Unified Send Processing -- Do this for all classes of service
  79. // We will do all of the work to build up the frames and create the send command before we check
  80. // the state of the EPD, that way we don't have to have complicated code to handle an endpoint that
  81. // goes away between the top and bottom of this function and we don't have to hold the EPDLock while
  82. // we do all of the buffer manipulation.
  83. pEPD = (PEPD) hDestination;
  84. ASSERT_EPD(pEPD);
  85. // Bump reference count on this baby
  86. if(!LOCK_EPD(pEPD, "LOCK (SEND)"))
  87. {
  88. // This would only happen if the Core had this pointer around from earlier. If this were the first
  89. // time this pointer was used, the Core would not have heard about it yet because Connect is not
  90. // complete. Hitting this assert indicates a bug in the Core.
  91. ASSERT(0);
  92. DPFX(DPFPREP,0, "(%p) Rejecting Send on unreferenced EPD, returning DPNERR_INVALIDENDPOINT", pEPD);
  93. return DPNERR_INVALIDENDPOINT;
  94. }
  95. // Count the bytes in all user buffers
  96. for(i=0; i < uiBufferCount; i++)
  97. {
  98. Length += pBufferDesc[i].dwBufferSize;
  99. }
  100. ASSERT(Length != 0);
  101. // Allocate and fill out a Message Descriptor for this operation
  102. if( (pMSD = static_cast<PMSD>( MSDPool->Get(MSDPool) )) == NULL)
  103. {
  104. DPFX(DPFPREP,0, "Failed to allocate MSD, returning DPNERR_OUTOFMEMORY");
  105. Lock(&pEPD->EPLock);
  106. RELEASE_EPD(pEPD, "UNLOCK (SEND)");
  107. return DPNERR_OUTOFMEMORY;
  108. }
  109. // Copy SendData parameters into the Message Descriptor
  110. pMSD->ulSendFlags = ulFlags; // Store the actual flags passed into the API call
  111. pMSD->Context = pvContext;
  112. pMSD->iMsgLength = Length;
  113. pMSD->uiFrameCount = (Length + pEPD->uiUserFrameLength - 1) / pEPD->uiUserFrameLength; // round up
  114. DPFX(DPFPREP, DPF_FRAMECNT_LVL, "Initialize Frame count, pMSD[%p], framecount[%u]", pMSD, pMSD->uiFrameCount);
  115. if(ulFlags & DN_SENDFLAGS_RELIABLE)
  116. {
  117. pMSD->CommandID = COMMAND_ID_SEND_RELIABLE;
  118. ulFrameFlags = FFLAGS_RELIABLE;
  119. bCommand = PACKET_COMMAND_DATA | PACKET_COMMAND_RELIABLE;
  120. }
  121. else
  122. {
  123. pMSD->CommandID = COMMAND_ID_SEND_DATAGRAM;
  124. ulFrameFlags = 0;
  125. bCommand = PACKET_COMMAND_DATA;
  126. }
  127. if(!(ulFlags & DN_SENDFLAGS_NON_SEQUENTIAL))
  128. {
  129. bCommand |= PACKET_COMMAND_SEQUENTIAL;
  130. }
  131. bCommand |= (ulFlags & (DN_SENDFLAGS_SET_USER_FLAG | DN_SENDFLAGS_SET_USER_FLAG_TWO)); // preserve user flag values
  132. // Map user buffers directly into frame's buffer descriptors
  133. //
  134. // We will loop through each required frame, filling out buffer descriptors
  135. // from those provided as parameters. Frames may span user buffers or vica-versa...
  136. TotalRemain = Length;
  137. #ifdef DEBUG
  138. FromBufferCount = uiBufferCount - 1; // sanity check
  139. #endif
  140. FromBuffer = pBufferDesc;
  141. FromRemain = FromBuffer->dwBufferSize;
  142. FromPtr = reinterpret_cast<PCHAR>( (FromBuffer++)->pBufferData ); // note post-increment to next descriptor
  143. for(i=0; i<pMSD->uiFrameCount; i++)
  144. {
  145. ASSERT(TotalRemain > 0);
  146. // Grab a new frame
  147. if( (pFMD = static_cast<PFMD>( FMDPool->Get(FMDPool) )) == NULL)
  148. {
  149. // MSD_Release will clean up any previous frames if this isn't the first.
  150. Lock(&pMSD->CommandLock);
  151. RELEASE_MSD(pMSD, "Base Ref"); // MSD Release operation will also free frames
  152. Lock(&pEPD->EPLock);
  153. RELEASE_EPD(pEPD, "UNLOCK (SEND)");
  154. DPFX(DPFPREP,0, "Failed to allocate FMD, returning DPNERR_OUTOFMEMORY");
  155. return DPNERR_OUTOFMEMORY;
  156. }
  157. pFMD->pMSD = pMSD; // Link frame back to message
  158. pFMD->pEPD = pEPD;
  159. pFMD->CommandID = pMSD->CommandID;
  160. pFMD->bPacketFlags = bCommand; // save packet flags for each frame
  161. pFMD->blMSDLinkage.InsertBefore( &pMSD->blFrameList);
  162. ToRemain = pEPD->uiUserFrameLength;
  163. ToBuffer = pFMD->rgBufferList; // Address first user buffer desc
  164. pFMD->uiFrameLength = pEPD->uiUserFrameLength; // Assume we fill frame- only need to change size of last one
  165. pFMD->ulFFlags = ulFrameFlags; // Set control flags for frame (Sequential, Reliable)
  166. // Until this frame is full
  167. while((ToRemain != 0) && (TotalRemain != 0))
  168. {
  169. size = MIN(FromRemain, ToRemain); // choose smaller of framesize or buffersize
  170. FromRemain -= size;
  171. ToRemain -= size;
  172. TotalRemain -= size;
  173. ToBuffer->dwBufferSize = size; // Fill in the next frame descriptor
  174. (ToBuffer++)->pBufferData = reinterpret_cast<BYTE*>( FromPtr ); // note post-increment
  175. pFMD->SendDataBlock.dwBufferCount++; // Count buffers as we add them
  176. // Get next user buffer
  177. if((FromRemain == 0) && (TotalRemain != 0))
  178. {
  179. FromRemain = FromBuffer->dwBufferSize;
  180. FromPtr = reinterpret_cast<PCHAR>( (FromBuffer++)->pBufferData ); // note post-increment to next descriptor
  181. #ifdef DEBUG
  182. FromBufferCount--; // Keep this code honest...
  183. ASSERT(FromBufferCount >= 0);
  184. #endif
  185. }
  186. else
  187. { // Either filled this frame, or have mapped the whole send
  188. FromPtr += size; // advance ptr to start next frame (if any)
  189. pFMD->uiFrameLength = pEPD->uiUserFrameLength - ToRemain; // wont be full at end of message
  190. }
  191. } // While (frame not full)
  192. } // For (each frame in message)
  193. pFMD->ulFFlags |= FFLAGS_END_OF_MESSAGE; // Mark last frame with EOM
  194. pFMD->bPacketFlags |= PACKET_COMMAND_END_MSG; // Set EOM in frame
  195. ASSERT(FromBufferCount == 0);
  196. ASSERT(TotalRemain == 0);
  197. Lock(&pMSD->CommandLock);
  198. Lock(&pEPD->EPLock);
  199. // Don't allow sends if we are not connected or if a disconnect has been initiated
  200. if( ((pEPD->ulEPFlags & (EPFLAGS_END_POINT_IN_USE | EPFLAGS_STATE_CONNECTED)) !=
  201. (EPFLAGS_END_POINT_IN_USE | EPFLAGS_STATE_CONNECTED))
  202. || (pEPD->ulEPFlags & EPFLAGS_SENT_DISCONNECT))
  203. {
  204. RELEASE_EPD(pEPD, "UNLOCK (SEND)"); // Releases EPLock
  205. pMSD->uiFrameCount = 0;
  206. // MSD_Release will clean up all of the frames
  207. RELEASE_MSD(pMSD, "Base Ref"); // MSD Release operation will also free frames
  208. DPFX(DPFPREP,0, "(%p) Rejecting Send on invalid EPD, returning DPNERR_INVALIDENDPOINT", pEPD);
  209. return DPNERR_INVALIDENDPOINT;
  210. }
  211. pSPD = pEPD->pSPD;
  212. ASSERT_SPD(pSPD);
  213. pMSD->pSPD = pSPD;
  214. pMSD->pEPD = pEPD;
  215. // hang the message off a global command queue
  216. #ifdef DEBUG
  217. Lock(&pSPD->SPLock);
  218. pMSD->blSPLinkage.InsertBefore( &pSPD->blMessageList);
  219. pMSD->ulMsgFlags1 |= MFLAGS_ONE_ON_GLOBAL_LIST;
  220. Unlock(&pSPD->SPLock);
  221. #endif
  222. *phHandle = pMSD; // We will use the MSD as our handle.
  223. // Enqueue the message before setting the timeout
  224. EnqueueMessage(pMSD, pEPD);
  225. Unlock(&pEPD->EPLock);
  226. if(uiTimeout != 0)
  227. {
  228. LOCK_MSD(pMSD, "Send Timeout Timer"); // Add reference for timer
  229. DPFX(DPFPREP,7, "(%p) Setting Timeout Send Timer", pEPD);
  230. SetMyTimer(uiTimeout, 100, TimeoutSend, pMSD, &pMSD->TimeoutTimer, &pMSD->TimeoutTimerUnique);
  231. }
  232. Unlock(&pMSD->CommandLock);
  233. return DPNERR_PENDING;
  234. }
  235. /*
  236. ** Enqueue Message
  237. **
  238. ** Add complete MSD to the appropriate send queue, and kick start sending process if necessary.
  239. **
  240. ** ** This routine is called and returns with EPD->EPLOCK held **
  241. */
  242. #undef DPF_MODNAME
  243. #define DPF_MODNAME "EnqueueMessage"
  244. VOID
  245. EnqueueMessage(PMSD pMSD, PEPD pEPD)
  246. {
  247. // Place Message in appriopriate priority queue. Datagrams get enqueued twice (!). They get put in the Master
  248. // queue where they are processed FIFO with all messages of the same priority. Datagrams also get placed in a priority
  249. // specific queue of only datagrams which is drawn from when the reliable stream is blocked.
  250. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  251. if(pMSD->ulSendFlags & DN_SENDFLAGS_HIGH_PRIORITY)
  252. {
  253. DPFX(DPFPREP,7, "(%p) Placing message on High Priority Q", pEPD);
  254. pMSD->blQLinkage.InsertBefore( &pEPD->blHighPriSendQ);
  255. pEPD->uiMsgSentHigh++;
  256. }
  257. else if (pMSD->ulSendFlags & DN_SENDFLAGS_LOW_PRIORITY)
  258. {
  259. DPFX(DPFPREP,7, "(%p) Placing message on Low Priority Q", pEPD);
  260. pMSD->blQLinkage.InsertBefore( &pEPD->blLowPriSendQ);
  261. pEPD->uiMsgSentLow++;
  262. }
  263. else
  264. {
  265. DPFX(DPFPREP,7, "(%p) Placing message on Normal Priority Q", pEPD);
  266. pMSD->blQLinkage.InsertBefore( &pEPD->blNormPriSendQ);
  267. pEPD->uiMsgSentNorm++;
  268. }
  269. #ifdef DEBUG
  270. pMSD->ulMsgFlags2 |= MFLAGS_TWO_ENQUEUED;
  271. #endif
  272. pEPD->uiQueuedMessageCount++;
  273. pEPD->ulEPFlags |= EPFLAGS_SDATA_READY; // Note that there is *something* in one or more queues
  274. // If the session is not currently in the send pipeline then we will want to insert it here as long as the
  275. // the stream is not blocked.
  276. if(((pEPD->ulEPFlags & EPFLAGS_IN_PIPELINE)==0) && (pEPD->ulEPFlags & EPFLAGS_STREAM_UNBLOCKED))
  277. {
  278. ASSERT(pEPD->SendTimer == NULL);
  279. DPFX(DPFPREP,7, "(%p) Send On Idle Link -- Returning to pipeline", pEPD);
  280. pEPD->ulEPFlags |= EPFLAGS_IN_PIPELINE;
  281. LOCK_EPD(pEPD, "LOCK (pipeline)"); // Add Ref for pipeline Q
  282. // We dont call send on users thread, but we dont have a dedicated send thread either. Use a thread
  283. // from the timer-worker pool to submit the sends to SP
  284. DPFX(DPFPREP,7, "(%p) Scheduling Send Thread", pEPD);
  285. ScheduleTimerThread(ScheduledSend, pEPD, &pEPD->SendTimer, &pEPD->SendTimerUnique);
  286. }
  287. else if ((pEPD->ulEPFlags & EPFLAGS_IN_PIPELINE)==0)
  288. {
  289. DPFX(DPFPREP,7, "(%p) Declining to re-enter pipeline on blocked stream", pEPD);
  290. }
  291. else
  292. {
  293. DPFX(DPFPREP,7, "(%p) Already in pipeline", pEPD);
  294. }
  295. }
  296. #undef DPF_MODNAME
  297. #define DPF_MODNAME "TimeoutSend"
  298. VOID CALLBACK
  299. TimeoutSend(PVOID uID, UINT uMsg, PVOID dwUser)
  300. {
  301. PMSD pMSD = (PMSD) dwUser;
  302. PEPD pEPD = pMSD->pEPD;
  303. DPFX(DPFPREP,7, "(%p) Timeout Send pMSD=%p, RefCnt=%d", pEPD, pMSD, pMSD->lRefCnt);
  304. Lock(&pMSD->CommandLock);
  305. if((pMSD->TimeoutTimer != uID)||(pMSD->TimeoutTimerUnique != uMsg))
  306. {
  307. DPFX(DPFPREP,7, "(%p) Ignoring late send timeout timer, pMSD[%p]", pEPD, pMSD);
  308. RELEASE_MSD(pMSD, "Timeout Timer"); // releases EPLock
  309. return;
  310. }
  311. pMSD->TimeoutTimer = NULL;
  312. if(pMSD->ulMsgFlags1 & (MFLAGS_ONE_CANCELLED | MFLAGS_ONE_TIMEDOUT))
  313. {
  314. DPFX(DPFPREP,7, "(%p) Timed out send has completed already pMSD=%p", pEPD, pMSD);
  315. RELEASE_MSD(pMSD, "Send Timout Timer"); // Releases CommandLock
  316. return;
  317. }
  318. pMSD->ulMsgFlags1 |= MFLAGS_ONE_TIMEDOUT;
  319. DPFX(DPFPREP,7, "(%p) Calling DoCancel to cancel pMSD=%p", pEPD, pMSD);
  320. if(DoCancel(pMSD, DPNERR_TIMEDOUT) == DPN_OK) // Releases CommandLock
  321. {
  322. ASSERT_EPD(pEPD);
  323. if(pMSD->ulSendFlags & DN_SENDFLAGS_HIGH_PRIORITY)
  324. {
  325. pEPD->uiMsgTOHigh++;
  326. }
  327. else if(pMSD->ulSendFlags & DN_SENDFLAGS_LOW_PRIORITY)
  328. {
  329. pEPD->uiMsgTOLow++;
  330. }
  331. else
  332. {
  333. pEPD->uiMsgTONorm++;
  334. }
  335. }
  336. else
  337. {
  338. DPFX(DPFPREP,7, "(%p) DoCancel did not succeed pMSD=%p", pEPD, pMSD);
  339. }
  340. Lock(&pMSD->CommandLock);
  341. RELEASE_MSD(pMSD, "Send Timout Timer"); // Release Ref for timer
  342. }
  343. /***********************
  344. ========SPACER==========
  345. ************************/
  346. /*
  347. ** MSD Pool support routines
  348. **
  349. ** These are the functions called by Fixed Pool Manager as it handles MSDs.
  350. */
  351. #define pELEMENT ((PMSD) pElement)
  352. #undef DPF_MODNAME
  353. #define DPF_MODNAME "MSD_Allocate"
  354. BOOL MSD_Allocate(PVOID pElement)
  355. {
  356. DPFX(DPFPREP,7, "(%p) Allocating new MSD", pELEMENT);
  357. ZeroMemory(pELEMENT, sizeof(messagedesc));
  358. if (DNInitializeCriticalSection(&pELEMENT->CommandLock) == FALSE)
  359. {
  360. DPFX(DPFPREP,0, "Failed to initialize MSD CS");
  361. return FALSE;
  362. }
  363. DebugSetCriticalSectionRecursionCount(&pELEMENT->CommandLock,0);
  364. pELEMENT->blFrameList.Initialize();
  365. pELEMENT->blQLinkage.Initialize();
  366. pELEMENT->blSPLinkage.Initialize();
  367. pELEMENT->Sign = MSD_SIGN;
  368. pELEMENT->lRefCnt = -1;
  369. // NOTE: pELEMENT->pEPD NULL'd by ZeroMemory above
  370. return TRUE;
  371. }
  372. // Get is called each time an MSD is used
  373. #undef DPF_MODNAME
  374. #define DPF_MODNAME "MSD_Get"
  375. VOID MSD_Get(PVOID pElement)
  376. {
  377. DPFX(DPFPREP,DPF_REFCNT_FINAL_LVL, "CREATING MSD %p", pELEMENT);
  378. // NOTE: First sizeof(PVOID) bytes will have been overwritten by the pool code,
  379. // we must set them to acceptable values.
  380. pELEMENT->CommandID = COMMAND_ID_NONE;
  381. pELEMENT->ulMsgFlags1 = MFLAGS_ONE_IN_USE; // Dont need InUse flag since we have RefCnt
  382. pELEMENT->lRefCnt = 0; // One initial reference
  383. pELEMENT->hCommand = 0;
  384. ASSERT_MSD(pELEMENT);
  385. }
  386. /*
  387. ** MSD Release
  388. **
  389. ** This is called with the CommandLock held. The Lock should not be
  390. ** freed until the INUSE flag is cleared. This is to synchronize with
  391. ** last minute Cancel threads waiting on lock.
  392. **
  393. ** When freeing a message desc we will free all frame descriptors
  394. ** attached to it first.
  395. */
  396. #undef DPF_MODNAME
  397. #define DPF_MODNAME "MSD_Release"
  398. VOID MSD_Release(PVOID pElement)
  399. {
  400. CBilink *pLink;
  401. PFMD pFMD;
  402. ASSERT_MSD(pELEMENT);
  403. AssertCriticalSectionIsTakenByThisThread(&pELEMENT->CommandLock, TRUE);
  404. DPFX(DPFPREP,DPF_REFCNT_FINAL_LVL, "RELEASING MSD %p", pELEMENT);
  405. ASSERT(pELEMENT->ulMsgFlags1 & MFLAGS_ONE_IN_USE);
  406. ASSERT(pELEMENT->lRefCnt == -1);
  407. ASSERT((pELEMENT->ulMsgFlags1 & MFLAGS_ONE_ON_GLOBAL_LIST)==0);
  408. while( (pLink = pELEMENT->blFrameList.GetNext()) != &pELEMENT->blFrameList)
  409. {
  410. pLink->RemoveFromList(); // remove from bilink
  411. pFMD = CONTAINING_RECORD(pLink, FMD, blMSDLinkage);
  412. ASSERT_FMD(pFMD);
  413. RELEASE_FMD(pFMD, "MSD Frame List"); // If this is still submitted it will be referenced and wont be released here.
  414. }
  415. ASSERT(pELEMENT->blFrameList.IsEmpty());
  416. ASSERT(pELEMENT->blQLinkage.IsEmpty());
  417. ASSERT(pELEMENT->blSPLinkage.IsEmpty());
  418. ASSERT(pELEMENT->uiFrameCount == 0);
  419. pELEMENT->ulMsgFlags1 = 0;
  420. pELEMENT->ulMsgFlags2 = 0;
  421. ASSERT(pELEMENT->pEPD == NULL); // This should have gotten cleaned up before here.
  422. Unlock(&pELEMENT->CommandLock);
  423. }
  424. #undef DPF_MODNAME
  425. #define DPF_MODNAME "MSD_Free"
  426. VOID MSD_Free(PVOID pElement)
  427. {
  428. DNDeleteCriticalSection(&pELEMENT->CommandLock);
  429. }
  430. #undef pELEMENT
  431. /*
  432. ** FMD Pool support routines
  433. */
  434. #define pELEMENT ((PFMD) pElement)
  435. #undef DPF_MODNAME
  436. #define DPF_MODNAME "FMD_Allocate"
  437. BOOL FMD_Allocate(PVOID pElement)
  438. {
  439. DPFX(DPFPREP,7, "(%p) Allocating new FMD", pELEMENT);
  440. pELEMENT->Sign = FMD_SIGN;
  441. pELEMENT->ulFFlags = 0;
  442. pELEMENT->lRefCnt = 0;
  443. pELEMENT->blMSDLinkage.Initialize();
  444. pELEMENT->blQLinkage.Initialize();
  445. pELEMENT->blWindowLinkage.Initialize();
  446. return TRUE;
  447. }
  448. // Get is called each time an MSD is used
  449. //
  450. // Probably dont need to do this everytime, but some random SP might
  451. // munch the parameters someday and that could be bad if I dont...
  452. #undef DPF_MODNAME
  453. #define DPF_MODNAME "FMD_Get"
  454. VOID FMD_Get(PVOID pElement)
  455. {
  456. DPFX(DPFPREP,DPF_REFCNT_FINAL_LVL, "CREATING FMD %p", pELEMENT);
  457. // NOTE: First sizeof(PVOID) bytes will have been overwritten by the pool code,
  458. // we must set them to acceptable values.
  459. pELEMENT->CommandID = 0;
  460. pELEMENT->lpImmediatePointer = (LPVOID) pELEMENT->ImmediateData;
  461. pELEMENT->SendDataBlock.pBuffers = (PBUFFERDESC) &pELEMENT->uiImmediateLength;
  462. pELEMENT->SendDataBlock.dwBufferCount = 1; // always count one buffer for immediate data
  463. pELEMENT->SendDataBlock.dwFlags = 0;
  464. pELEMENT->SendDataBlock.pvContext = pElement;
  465. pELEMENT->SendDataBlock.hCommand = 0;
  466. pELEMENT->ulFFlags = 0;
  467. pELEMENT->bSubmitted = FALSE;
  468. pELEMENT->bPacketFlags = 0;
  469. pELEMENT->lRefCnt = 1; // Assign first reference
  470. ASSERT_FMD(pELEMENT);
  471. }
  472. #undef DPF_MODNAME
  473. #define DPF_MODNAME "FMD_Release"
  474. VOID FMD_Release(PVOID pElement)
  475. {
  476. DPFX(DPFPREP,DPF_REFCNT_FINAL_LVL, "RELEASING FMD %p", pELEMENT);
  477. ASSERT_FMD(pELEMENT);
  478. ASSERT(pELEMENT->lRefCnt == 0);
  479. ASSERT(pELEMENT->bSubmitted == FALSE);
  480. pELEMENT->pMSD = NULL;
  481. ASSERT(pELEMENT->blMSDLinkage.IsEmpty());
  482. ASSERT(pELEMENT->blQLinkage.IsEmpty());
  483. ASSERT(pELEMENT->blWindowLinkage.IsEmpty());
  484. }
  485. #undef DPF_MODNAME
  486. #define DPF_MODNAME "FMD_Free"
  487. VOID FMD_Free(PVOID pElement)
  488. {
  489. }
  490. #undef pELEMENT