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.

1309 lines
39 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. buffer.c
  5. Abstract:
  6. This module contains routines for handling non-bufferring TDI
  7. providers. The AFD interface assumes that bufferring will be done
  8. below AFD; if the TDI provider doesn't buffer, then AFD must.
  9. Author:
  10. David Treadwell (davidtr) 21-Feb-1992
  11. Revision History:
  12. --*/
  13. #include "afdp.h"
  14. PAFD_BUFFER
  15. AfdInitializeBuffer (
  16. IN PVOID MemBlock,
  17. IN ULONG BufferDataSize,
  18. IN ULONG AddressSize
  19. );
  20. #if DBG
  21. VOID
  22. AfdFreeBufferReal (
  23. PVOID AfdBuffer
  24. );
  25. #endif
  26. #ifdef ALLOC_PRAGMA
  27. #pragma alloc_text( PAGEAFD, AfdAllocateBuffer )
  28. #pragma alloc_text( PAGEAFD, AfdFreeBuffer )
  29. #if DBG
  30. #pragma alloc_text( PAGEAFD, AfdFreeBufferReal )
  31. #endif
  32. #pragma alloc_text( PAGEAFD, AfdCalculateBufferSize )
  33. #pragma alloc_text( PAGEAFD, AfdInitializeBuffer )
  34. #pragma alloc_text( PAGEAFD, AfdGetBuffer )
  35. #pragma alloc_text( PAGEAFD, AfdReturnBuffer )
  36. #pragma alloc_text( PAGEAFD, AfdAllocateBufferTag )
  37. #pragma alloc_text( PAGEAFD, AfdFreeBufferTag )
  38. #pragma alloc_text( PAGEAFD, AfdAllocateRemoteAddress )
  39. #pragma alloc_text( PAGEAFD, AfdFreeRemoteAddress )
  40. #pragma alloc_text( PAGEAFD, AfdInitializeBufferTag )
  41. #pragma alloc_text( PAGEAFD, AfdGetBufferTag )
  42. #pragma alloc_text( INIT, AfdInitializeBufferManager)
  43. #endif
  44. PVOID
  45. AfdAllocateBuffer (
  46. IN POOL_TYPE PoolType,
  47. IN SIZE_T NumberOfBytes,
  48. IN ULONG Tag
  49. )
  50. /*++
  51. Routine Description:
  52. Used by the lookaside list allocation function to allocate a new
  53. AFD buffer structure. The returned structure will be fully
  54. initialized.
  55. Arguments:
  56. PoolType - passed to ExAllocatePoolWithTag.
  57. NumberOfBytes - the number of bytes required for the data buffer
  58. portion of the AFD buffer.
  59. Tag - passed to ExAllocatePoolWithTag.
  60. Return Value:
  61. PVOID - a fully initialized PAFD_BUFFER, or NULL if the allocation
  62. attempt fails.
  63. --*/
  64. {
  65. ULONG dataLength;
  66. PVOID memBlock;
  67. //
  68. // Get nonpaged pool for the buffer.
  69. //
  70. memBlock = AFD_ALLOCATE_POOL( PoolType, NumberOfBytes, Tag );
  71. if ( memBlock == NULL ) {
  72. return NULL;
  73. }
  74. if (NumberOfBytes==AfdLookasideLists->SmallBufferList.L.Size) {
  75. dataLength = AfdSmallBufferSize;
  76. }
  77. else if (NumberOfBytes==AfdLookasideLists->MediumBufferList.L.Size) {
  78. dataLength = AfdMediumBufferSize;
  79. }
  80. else if (NumberOfBytes==AfdLookasideLists->LargeBufferList.L.Size) {
  81. dataLength = AfdLargeBufferSize;
  82. }
  83. else {
  84. ASSERT (FALSE);
  85. }
  86. //
  87. // Initialize the buffer and return a pointer to it.
  88. //
  89. #if DBG
  90. {
  91. PAFD_BUFFER afdBuffer = AfdInitializeBuffer( memBlock, dataLength, AfdStandardAddressLength );
  92. ASSERT ((PCHAR)afdBuffer+sizeof (AFD_BUFFER)<=(PCHAR)memBlock+NumberOfBytes &&
  93. (PCHAR)afdBuffer->Buffer+dataLength<=(PCHAR)memBlock+NumberOfBytes &&
  94. (PCHAR)afdBuffer->Irp+IoSizeOfIrp(AfdIrpStackSize-1)<=(PCHAR)memBlock+NumberOfBytes &&
  95. (PCHAR)afdBuffer->Mdl+MmSizeOfMdl(afdBuffer->Buffer, dataLength)<=(PCHAR)memBlock+NumberOfBytes &&
  96. (PCHAR)afdBuffer->TdiInfo.RemoteAddress+AfdStandardAddressLength<=(PCHAR)memBlock+NumberOfBytes);
  97. return afdBuffer;
  98. }
  99. #else
  100. return AfdInitializeBuffer( memBlock, dataLength, AfdStandardAddressLength );
  101. #endif
  102. } // AfdAllocateBuffer
  103. VOID
  104. NTAPI
  105. AfdFreeBuffer (
  106. PVOID AfdBuffer
  107. )
  108. {
  109. ASSERT( ((PAFD_BUFFER)AfdBuffer)->BufferLength == AfdSmallBufferSize ||
  110. ((PAFD_BUFFER)AfdBuffer)->BufferLength == AfdMediumBufferSize ||
  111. ((PAFD_BUFFER)AfdBuffer)->BufferLength == AfdLargeBufferSize );
  112. #if DBG
  113. AfdFreeBufferReal (AfdBuffer);
  114. }
  115. VOID
  116. NTAPI
  117. AfdFreeBufferReal (
  118. PVOID AfdBuffer
  119. )
  120. {
  121. #endif
  122. {
  123. PAFD_BUFFER hdr = AfdBuffer;
  124. switch (hdr->Placement) {
  125. case AFD_PLACEMENT_BUFFER:
  126. AfdBuffer = hdr->Buffer;
  127. break;
  128. case AFD_PLACEMENT_HDR:
  129. AfdBuffer = hdr;
  130. break;
  131. case AFD_PLACEMENT_MDL:
  132. AfdBuffer = hdr->Mdl;
  133. break;
  134. case AFD_PLACEMENT_IRP:
  135. AfdBuffer = hdr->Irp;
  136. break;
  137. default:
  138. ASSERT (!"Unknown placement!");
  139. __assume (0);
  140. }
  141. if (hdr->AlignmentAdjusted) {
  142. //
  143. // The original memory block was adjusted to meet alignment
  144. // requirement of AFD buffers.
  145. // The amount of adjustment should be stored in the space
  146. // used for adjustment (right below the first piece).
  147. //
  148. ASSERT ((*(((PSIZE_T)AfdBuffer)-1))>0 &&
  149. (*(((PSIZE_T)AfdBuffer)-1))<AfdBufferAlignment);
  150. AfdBuffer = (PUCHAR)AfdBuffer - (*(((PSIZE_T)AfdBuffer)-1));
  151. }
  152. AFD_FREE_POOL (AfdBuffer, AFD_DATA_BUFFER_POOL_TAG);
  153. }
  154. }
  155. PVOID
  156. AfdAllocateBufferTag (
  157. IN POOL_TYPE PoolType,
  158. IN SIZE_T NumberOfBytes,
  159. IN ULONG Tag
  160. )
  161. /*++
  162. Routine Description:
  163. Used by the lookaside list allocation function to allocate a new
  164. AFD buffer tag structure. The returned structure will be fully
  165. initialized.
  166. Arguments:
  167. PoolType - passed to ExAllocatePoolWithTag.
  168. NumberOfBytes - the number of bytes required for the data buffer
  169. portion of the AFD buffer tag (0).
  170. Tag - passed to ExAllocatePoolWithTag.
  171. Return Value:
  172. PVOID - a fully initialized PAFD_BUFFER_TAG, or NULL if the allocation
  173. attempt fails.
  174. --*/
  175. {
  176. PAFD_BUFFER_TAG afdBufferTag;
  177. //
  178. // The requested length must be the same as buffer tag size
  179. //
  180. ASSERT(NumberOfBytes == sizeof (AFD_BUFFER_TAG) );
  181. //
  182. // Get nonpaged pool for the buffer tag.
  183. //
  184. afdBufferTag = AFD_ALLOCATE_POOL( PoolType, sizeof (AFD_BUFFER_TAG), Tag );
  185. if ( afdBufferTag == NULL ) {
  186. return NULL;
  187. }
  188. //
  189. // Initialize the buffer tag and return a pointer to it.
  190. //
  191. AfdInitializeBufferTag( afdBufferTag, 0 );
  192. return afdBufferTag;
  193. } // AfdAllocateBufferTag
  194. VOID
  195. NTAPI
  196. AfdFreeBufferTag (
  197. PVOID AfdBufferTag
  198. )
  199. {
  200. AFD_FREE_POOL (AfdBufferTag, AFD_DATA_BUFFER_POOL_TAG);
  201. }
  202. PVOID
  203. AfdAllocateRemoteAddress (
  204. IN POOL_TYPE PoolType,
  205. IN SIZE_T NumberOfBytes,
  206. IN ULONG Tag
  207. )
  208. /*++
  209. Routine Description:
  210. Used by the lookaside list allocation function to allocate a new
  211. remote address structure. The returned structure will be fully
  212. initialized.
  213. Arguments:
  214. PoolType - passed to ExAllocatePoolWithTag.
  215. NumberOfBytes - the number of bytes required for the data buffer
  216. portion of the AFD buffer tag (0).
  217. Tag - passed to ExAllocatePoolWithTag.
  218. Return Value:
  219. PVOID - a fully initialized remote address, or NULL if the allocation
  220. attempt fails.
  221. --*/
  222. {
  223. //
  224. // The requested length must be the same as standard address size
  225. //
  226. ASSERT(NumberOfBytes == AfdStandardAddressLength );
  227. //
  228. // Get nonpaged pool for the remote address.
  229. //
  230. return AFD_ALLOCATE_POOL( PoolType, AfdStandardAddressLength, Tag );
  231. } // AfdAllocateRemoteAddress
  232. VOID
  233. NTAPI
  234. AfdFreeRemoteAddress (
  235. PVOID AfdBufferTag
  236. )
  237. {
  238. AFD_FREE_POOL (AfdBufferTag, AFD_REMOTE_ADDRESS_POOL_TAG);
  239. }
  240. ULONG
  241. AfdCalculateBufferSize (
  242. IN ULONG BufferDataSize,
  243. IN ULONG AddressSize
  244. )
  245. /*++
  246. Routine Description:
  247. Determines the size of an AFD buffer structure given the amount of
  248. data that the buffer contains.
  249. Arguments:
  250. BufferDataSize - data length of the buffer.
  251. AddressSize - length of address structure for the buffer.
  252. Return Value:
  253. Number of bytes needed for an AFD_BUFFER structure for data of
  254. this size.
  255. --*/
  256. {
  257. ULONG irpSize;
  258. ULONG mdlSize;
  259. ULONG hdrSize;
  260. ULONG size;
  261. //
  262. // Determine the sizes of the various components of an AFD_BUFFER
  263. // structure.
  264. //
  265. hdrSize = sizeof (AFD_BUFFER);
  266. irpSize = IoSizeOfIrp( AfdIrpStackSize-1 );
  267. //
  268. // For mdl size calculation we rely on ex guarantee that buffer will be
  269. // aligned on the page boundary (for allocations >= PAGE_SIZE)
  270. // or will not spawn pages (for allocations < PAGE_SIZE).
  271. //
  272. mdlSize = (CLONG)MmSizeOfMdl( NULL, BufferDataSize );
  273. size = ALIGN_UP_A(hdrSize,AFD_MINIMUM_BUFFER_ALIGNMENT) +
  274. ALIGN_UP_A(irpSize,AFD_MINIMUM_BUFFER_ALIGNMENT) +
  275. ALIGN_UP_A(mdlSize,AFD_MINIMUM_BUFFER_ALIGNMENT) +
  276. ALIGN_UP_A(BufferDataSize,AFD_MINIMUM_BUFFER_ALIGNMENT) +
  277. AddressSize;
  278. if (size>=PAGE_SIZE)
  279. return size;
  280. else {
  281. size += AfdAlignmentOverhead;
  282. if (size>=PAGE_SIZE) {
  283. return PAGE_SIZE;
  284. }
  285. else
  286. return size;
  287. }
  288. } // AfdCalculateBufferSize
  289. PAFD_BUFFER
  290. AfdGetBuffer (
  291. IN ULONG BufferDataSize,
  292. IN ULONG AddressSize,
  293. IN PEPROCESS Process
  294. )
  295. /*++
  296. Routine Description:
  297. Obtains a buffer of the appropriate size for the caller. Uses
  298. the preallocated buffers if possible, or else allocates a new buffer
  299. structure if required.
  300. Arguments:
  301. BufferDataSize - the size of the data buffer that goes along with the
  302. buffer structure.
  303. AddressSize - size of the address field required for the buffer.
  304. Return Value:
  305. PAFD_BUFFER - a pointer to an AFD_BUFFER structure, or NULL if one
  306. was not available or could not be allocated.
  307. --*/
  308. {
  309. ULONG bufferSize;
  310. PNPAGED_LOOKASIDE_LIST lookasideList;
  311. NTSTATUS status;
  312. //
  313. // If possible, allocate the buffer from one of the lookaside lists.
  314. //
  315. if ( AddressSize <= AfdStandardAddressLength &&
  316. BufferDataSize <= AfdLargeBufferSize ) {
  317. PAFD_BUFFER afdBuffer;
  318. if ( BufferDataSize <= AfdSmallBufferSize ) {
  319. lookasideList = &AfdLookasideLists->SmallBufferList;
  320. } else if ( BufferDataSize <= AfdMediumBufferSize ) {
  321. lookasideList = &AfdLookasideLists->MediumBufferList;
  322. } else {
  323. lookasideList = &AfdLookasideLists->LargeBufferList;
  324. }
  325. afdBuffer = ExAllocateFromNPagedLookasideList( lookasideList );
  326. if ( afdBuffer != NULL) {
  327. if (!afdBuffer->Lookaside) {
  328. status = PsChargeProcessPoolQuota (
  329. (PEPROCESS)((ULONG_PTR)Process & (~AFDB_RAISE_ON_FAILURE)),
  330. NonPagedPool,
  331. lookasideList->L.Size);
  332. if (!NT_SUCCESS (status)) {
  333. AfdFreeBuffer (afdBuffer);
  334. goto ExitQuotaFailure;
  335. }
  336. AfdRecordQuotaHistory(
  337. process,
  338. (LONG)lookasideList->L.Size,
  339. "BuffAlloc ",
  340. afdBuffer
  341. );
  342. AfdRecordPoolQuotaCharged(lookasideList->L.Size);
  343. }
  344. #if DBG
  345. RtlGetCallersAddress(
  346. &afdBuffer->Caller,
  347. &afdBuffer->CallersCaller
  348. );
  349. #endif
  350. return afdBuffer;
  351. }
  352. }
  353. else if (AddressSize<=0xFFFF) {
  354. PVOID memBlock;
  355. LONG sz;
  356. //
  357. // Couldn't find an appropriate buffer that was preallocated.
  358. // Allocate one manually. If the buffer size requested was
  359. // zero bytes, give them four bytes. This is because some of
  360. // the routines like MmSizeOfMdl() cannot handle getting passed
  361. // in a length of zero.
  362. //
  363. // !!! It would be good to ROUND_TO_PAGES for this allocation
  364. // if appropriate, then use entire buffer size.
  365. //
  366. if ( BufferDataSize == 0 ) {
  367. BufferDataSize = sizeof(ULONG);
  368. }
  369. bufferSize = AfdCalculateBufferSize( BufferDataSize, AddressSize );
  370. //
  371. // Check for overflow.
  372. //
  373. if (bufferSize>=BufferDataSize && bufferSize>=AddressSize) {
  374. memBlock = AFD_ALLOCATE_POOL(
  375. NonPagedPool,
  376. bufferSize,
  377. AFD_DATA_BUFFER_POOL_TAG
  378. );
  379. if ( memBlock != NULL) {
  380. status = PsChargeProcessPoolQuota (
  381. (PEPROCESS)((ULONG_PTR)Process & (~AFDB_RAISE_ON_FAILURE)),
  382. NonPagedPool,
  383. sz = BufferDataSize
  384. +AfdBufferOverhead
  385. +AddressSize
  386. -AfdStandardAddressLength
  387. +BufferDataSize<PAGE_SIZE
  388. ? min (AfdAlignmentOverhead, PAGE_SIZE-BufferDataSize)
  389. : 0);
  390. if (NT_SUCCESS (status)) {
  391. PAFD_BUFFER afdBuffer;
  392. //
  393. // Initialize the AFD buffer structure and return it.
  394. //
  395. afdBuffer = AfdInitializeBuffer( memBlock, BufferDataSize, AddressSize );
  396. ASSERT ((PCHAR)afdBuffer+sizeof (AFD_BUFFER)<=(PCHAR)memBlock+bufferSize &&
  397. (PCHAR)afdBuffer->Buffer+BufferDataSize<=(PCHAR)memBlock+bufferSize &&
  398. (PCHAR)afdBuffer->Irp+IoSizeOfIrp(AfdIrpStackSize-1)<=(PCHAR)memBlock+bufferSize &&
  399. (PCHAR)afdBuffer->Mdl+MmSizeOfMdl(afdBuffer->Buffer, BufferDataSize)<=(PCHAR)memBlock+bufferSize &&
  400. (PCHAR)afdBuffer->TdiInfo.RemoteAddress+AddressSize<=(PCHAR)memBlock+bufferSize);
  401. AfdRecordPoolQuotaCharged(sz);
  402. AfdRecordQuotaHistory(
  403. process,
  404. sz,
  405. "BuffAlloc ",
  406. afdBuffer
  407. );
  408. #if DBG
  409. RtlGetCallersAddress(
  410. &afdBuffer->Caller,
  411. &afdBuffer->CallersCaller
  412. );
  413. #endif
  414. return afdBuffer;
  415. }
  416. else {
  417. AFD_FREE_POOL (memBlock, AFD_DATA_BUFFER_POOL_TAG);
  418. goto ExitQuotaFailure;
  419. }
  420. } // memblock==NULL
  421. } // overflow
  422. }
  423. else {
  424. // TDI does not support addresses > USHORT
  425. ASSERT (FALSE);
  426. }
  427. //
  428. // This is default status code.
  429. // Quota failures jump directly to the
  430. // label below to raise the status returned by
  431. // the quota charging code if requested by the caller..
  432. //
  433. status = STATUS_INSUFFICIENT_RESOURCES;
  434. ExitQuotaFailure:
  435. if ((ULONG_PTR)Process & AFDB_RAISE_ON_FAILURE) {
  436. ExRaiseStatus (status);
  437. }
  438. return NULL;
  439. } // AfdGetBuffer
  440. PAFD_BUFFER_TAG
  441. AfdGetBufferTag (
  442. IN ULONG AddressSize,
  443. IN PEPROCESS Process
  444. )
  445. /*++
  446. Routine Description:
  447. Obtains a buffer for tagging TDSU received via chained indication. Uses
  448. the preallocated buffers if possible, or else allocates a new buffer
  449. structure if required.
  450. Arguments:
  451. AddressSize - size of the address field required for the buffer.
  452. Return Value:
  453. PAFD_BUFFER_TAG - a pointer to an AFD_BUFFER_TAG structure, or NULL if one
  454. was not available or could not be allocated.
  455. --*/
  456. {
  457. PAFD_BUFFER_TAG afdBufferTag;
  458. ULONG bufferSize;
  459. NTSTATUS status;
  460. if ( AddressSize <= AfdStandardAddressLength) {
  461. if (AddressSize>0)
  462. AddressSize = AfdStandardAddressLength;
  463. afdBufferTag = ExAllocateFromNPagedLookasideList(
  464. &AfdLookasideLists->BufferTagList );
  465. if ( afdBufferTag != NULL &&
  466. ( AddressSize==0 ||
  467. (afdBufferTag->TdiInfo.RemoteAddress =
  468. ExAllocateFromNPagedLookasideList(
  469. &AfdLookasideLists->RemoteAddrList ))!=NULL ) ) {
  470. afdBufferTag->AllocatedAddressLength = (USHORT)AddressSize;
  471. if (!afdBufferTag->Lookaside) {
  472. status = PsChargeProcessPoolQuota (
  473. (PEPROCESS)((ULONG_PTR)Process & (~AFDB_RAISE_ON_FAILURE)),
  474. NonPagedPool,
  475. sizeof (AFD_BUFFER_TAG)+AddressSize);
  476. if (!NT_SUCCESS (status)) {
  477. if ((afdBufferTag->TdiInfo.RemoteAddress!=NULL) &&
  478. (afdBufferTag->TdiInfo.RemoteAddress != (PVOID)(afdBufferTag+1))) {
  479. ExFreeToNPagedLookasideList( &AfdLookasideLists->RemoteAddrList,
  480. afdBufferTag->TdiInfo.RemoteAddress );
  481. }
  482. AFD_FREE_POOL (afdBufferTag, AFD_DATA_BUFFER_POOL_TAG);
  483. goto ExitQuotaFailure;
  484. }
  485. AfdRecordQuotaHistory(
  486. process,
  487. (LONG)(sizeof (AFD_BUFFER_TAG)+AddressSize),
  488. "BuffAlloc ",
  489. afdBufferTag
  490. );
  491. AfdRecordPoolQuotaCharged(sizeof (AFD_BUFFER_TAG)+AddressSize);
  492. }
  493. #if DBG
  494. RtlGetCallersAddress(
  495. &afdBufferTag->Caller,
  496. &afdBufferTag->CallersCaller
  497. );
  498. #endif
  499. return afdBufferTag;
  500. } // afdBufferTag==NULL || RemoteAddress==NULL
  501. }
  502. else if (AddressSize<=0xFFFF) {
  503. bufferSize = sizeof (AFD_BUFFER_TAG) + AddressSize;
  504. afdBufferTag = AFD_ALLOCATE_POOL(
  505. NonPagedPool,
  506. bufferSize,
  507. AFD_DATA_BUFFER_POOL_TAG
  508. );
  509. if (afdBufferTag!=NULL) {
  510. status = PsChargeProcessPoolQuota (
  511. (PEPROCESS)((ULONG_PTR)Process & (~AFDB_RAISE_ON_FAILURE)),
  512. NonPagedPool,
  513. bufferSize);
  514. if (NT_SUCCESS (status)) {
  515. //
  516. // Initialize the AFD buffer structure and return it.
  517. //
  518. AfdInitializeBufferTag (afdBufferTag, AddressSize);
  519. AfdRecordQuotaHistory(
  520. process,
  521. (LONG)bufferSize,
  522. "BuffAlloc ",
  523. afdBufferTag
  524. );
  525. AfdRecordPoolQuotaCharged(bufferSize);
  526. #if DBG
  527. RtlGetCallersAddress(
  528. &afdBufferTag->Caller,
  529. &afdBufferTag->CallersCaller
  530. );
  531. #endif
  532. return afdBufferTag;
  533. }
  534. else {
  535. AFD_FREE_POOL (afdBufferTag, AFD_DATA_BUFFER_POOL_TAG);
  536. goto ExitQuotaFailure;
  537. }
  538. }
  539. }
  540. else {
  541. // TDI does not support addresses > USHORT
  542. ASSERT (FALSE);
  543. }
  544. //
  545. // This is default status code.
  546. // Quota failures jump directly to the
  547. // label below to raise the status returned by
  548. // the quota charging code if requested by the caller..
  549. //
  550. status = STATUS_INSUFFICIENT_RESOURCES;
  551. ExitQuotaFailure:
  552. if ((ULONG_PTR)Process & AFDB_RAISE_ON_FAILURE) {
  553. ExRaiseStatus (status);
  554. }
  555. return NULL;
  556. }
  557. VOID
  558. AfdReturnBuffer (
  559. IN PAFD_BUFFER_HEADER AfdBufferHeader,
  560. IN PEPROCESS Process
  561. )
  562. /*++
  563. Routine Description:
  564. Returns an AFD buffer to the appropriate global list, or frees
  565. it if necessary.
  566. Arguments:
  567. AfdBufferHeader - points to the AFD_BUFFER_HEADER structure to return or free.
  568. Return Value:
  569. None.
  570. --*/
  571. {
  572. if (AfdBufferHeader->BufferLength!=AfdBufferTagSize) {
  573. PNPAGED_LOOKASIDE_LIST lookasideList;
  574. PAFD_BUFFER AfdBuffer = CONTAINING_RECORD (AfdBufferHeader, AFD_BUFFER, Header);
  575. ASSERT (IS_VALID_AFD_BUFFER (AfdBuffer));
  576. //
  577. // Most of the AFD buffer must be zeroed when returning the buffer.
  578. //
  579. ASSERT( !AfdBuffer->ExpeditedData );
  580. ASSERT( AfdBuffer->Mdl->ByteCount == AfdBuffer->BufferLength );
  581. ASSERT( AfdBuffer->Mdl->Next == NULL );
  582. //
  583. // If appropriate, return the buffer to one of the AFD buffer
  584. // lookaside lists.
  585. //
  586. if (AfdBuffer->AllocatedAddressLength == AfdStandardAddressLength &&
  587. AfdBuffer->BufferLength <= AfdLargeBufferSize) {
  588. if (AfdBuffer->BufferLength==AfdSmallBufferSize) {
  589. lookasideList = &AfdLookasideLists->SmallBufferList;
  590. } else if (AfdBuffer->BufferLength == AfdMediumBufferSize) {
  591. lookasideList = &AfdLookasideLists->MediumBufferList;
  592. } else {
  593. ASSERT (AfdBuffer->BufferLength==AfdLargeBufferSize);
  594. lookasideList = &AfdLookasideLists->LargeBufferList;
  595. }
  596. if (!AfdBuffer->Lookaside) {
  597. PsReturnPoolQuota (Process, NonPagedPool, lookasideList->L.Size);
  598. AfdRecordQuotaHistory(
  599. Process,
  600. -(LONG)lookasideList->L.Size,
  601. "BuffDealloc ",
  602. AfdBuffer
  603. );
  604. AfdRecordPoolQuotaReturned(
  605. lookasideList->L.Size
  606. );
  607. AfdBuffer->Lookaside = TRUE;
  608. }
  609. ExFreeToNPagedLookasideList( lookasideList, AfdBuffer );
  610. return;
  611. }
  612. // The buffer was not from a lookaside list allocation, so just free
  613. // the pool we used for it.
  614. //
  615. ASSERT (AfdBuffer->Lookaside==FALSE);
  616. {
  617. LONG sz;
  618. PsReturnPoolQuota (Process,
  619. NonPagedPool,
  620. sz=AfdBuffer->BufferLength
  621. +AfdBufferOverhead
  622. +AfdBuffer->AllocatedAddressLength
  623. -AfdStandardAddressLength
  624. +AfdBuffer->BufferLength<PAGE_SIZE
  625. ? min (AfdAlignmentOverhead, PAGE_SIZE-AfdBuffer->BufferLength)
  626. : 0);
  627. AfdRecordQuotaHistory(
  628. Process,
  629. -(LONG)sz,
  630. "BuffDealloc ",
  631. AfdBuffer
  632. );
  633. AfdRecordPoolQuotaReturned(
  634. sz
  635. );
  636. }
  637. #if DBG
  638. AfdFreeBufferReal (AfdBuffer);
  639. #else
  640. AfdFreeBuffer (AfdBuffer);
  641. #endif
  642. return;
  643. }
  644. else {
  645. PAFD_BUFFER_TAG AfdBufferTag = CONTAINING_RECORD (AfdBufferHeader, AFD_BUFFER_TAG, Header);
  646. ASSERT( !AfdBufferTag->ExpeditedData );
  647. if (AfdBufferTag->NdisPacket) {
  648. AfdBufferTag->NdisPacket = FALSE;
  649. TdiReturnChainedReceives (&AfdBufferTag->Context, 1);
  650. }
  651. if (AfdBufferTag->TdiInfo.RemoteAddress != (PVOID)(AfdBufferTag+1)) {
  652. if (AfdBufferTag->TdiInfo.RemoteAddress!=NULL) {
  653. ASSERT (AfdBufferTag->AllocatedAddressLength==AfdStandardAddressLength);
  654. ExFreeToNPagedLookasideList( &AfdLookasideLists->RemoteAddrList,
  655. AfdBufferTag->TdiInfo.RemoteAddress );
  656. AfdBufferTag->TdiInfo.RemoteAddress = NULL;
  657. }
  658. else {
  659. ASSERT (AfdBufferTag->AllocatedAddressLength==0);
  660. }
  661. if (!AfdBufferTag->Lookaside) {
  662. LONG sz;
  663. PsReturnPoolQuota (
  664. Process,
  665. NonPagedPool,
  666. sz=sizeof (AFD_BUFFER_TAG)
  667. + AfdBufferTag->AllocatedAddressLength);
  668. AfdRecordQuotaHistory(
  669. Process,
  670. -(LONG)sz,
  671. "BuffDealloc ",
  672. AfdBufferTag
  673. );
  674. AfdRecordPoolQuotaReturned(
  675. sz
  676. );
  677. AfdBufferTag->Lookaside = TRUE;
  678. }
  679. ExFreeToNPagedLookasideList( &AfdLookasideLists->BufferTagList, AfdBufferTag );
  680. }
  681. else {
  682. LONG sz;
  683. ASSERT (AfdBufferTag->AllocatedAddressLength>AfdStandardAddressLength);
  684. ASSERT (AfdBufferTag->Lookaside == FALSE);
  685. PsReturnPoolQuota (
  686. Process,
  687. NonPagedPool,
  688. sz = sizeof (AFD_BUFFER_TAG)
  689. + AfdBufferTag->AllocatedAddressLength);
  690. AfdRecordQuotaHistory(
  691. Process,
  692. -(LONG)sz,
  693. "BuffDealloc ",
  694. AfdBufferTag
  695. );
  696. AfdRecordPoolQuotaReturned(
  697. sz
  698. );
  699. AFD_FREE_POOL(
  700. AfdBufferTag,
  701. AFD_DATA_BUFFER_POOL_TAG
  702. );
  703. }
  704. }
  705. } // AfdReturnBuffer
  706. PAFD_BUFFER
  707. AfdInitializeBuffer (
  708. IN PVOID MemoryBlock,
  709. IN ULONG BufferDataSize,
  710. IN ULONG AddressSize
  711. )
  712. /*++
  713. Routine Description:
  714. Initializes an AFD buffer. Sets up fields in the actual AFD_BUFFER
  715. structure and initializes the IRP and MDL associated with the
  716. buffer. This routine assumes that the caller has properly allocated
  717. sufficient space for all this.
  718. Arguments:
  719. AfdBuffer - points to the AFD_BUFFER structure to initialize.
  720. BufferDataSize - the size of the data buffer that goes along with the
  721. buffer structure.
  722. AddressSize - the size of data allocated for the address buffer.
  723. ListHead - the global list this buffer belongs to, or NULL if it
  724. doesn't belong on any list. This routine does NOT place the
  725. buffer structure on the list.
  726. Return Value:
  727. None.
  728. --*/
  729. {
  730. USHORT irpSize;
  731. SIZE_T mdlSize;
  732. SIZE_T hdrSize;
  733. PAFD_BUFFER hdr;
  734. PMDL mdl;
  735. PIRP irp;
  736. PVOID buf;
  737. PVOID addr;
  738. UCHAR placement;
  739. SIZE_T alignment;
  740. #ifdef AFD_CHECK_ALIGNMENT
  741. PLONG alignmentCounters = (PLONG)&AfdAlignmentTable[AfdAlignmentTableSize];
  742. #endif
  743. irpSize = IoSizeOfIrp( AfdIrpStackSize-1 );
  744. mdlSize = (ULONG)MmSizeOfMdl( NULL, BufferDataSize );
  745. hdrSize = sizeof (AFD_BUFFER);
  746. //
  747. // Compute the index into (mis)alignment table to determine
  748. // what placement of the buffer block elements (e.g. hdr, IRP, MDL,
  749. // and data buffer itself) we need to choose to compensate and
  750. // align data buffer on AfdBufferAlignment boundary.
  751. //
  752. ASSERT ((PtrToUlong(MemoryBlock)%AFD_MINIMUM_BUFFER_ALIGNMENT)==0);
  753. if (PAGE_ALIGN (MemoryBlock)==MemoryBlock) {
  754. //
  755. // For page-aligned blocks (which are >= page size),
  756. // we always place the buffer first.
  757. //
  758. placement = AFD_PLACEMENT_BUFFER;
  759. }
  760. else {
  761. placement = AfdAlignmentTable[
  762. (PtrToUlong(MemoryBlock)&(AfdBufferAlignment-1))/AFD_MINIMUM_BUFFER_ALIGNMENT];
  763. }
  764. #ifdef AFD_CHECK_ALIGNMENT
  765. InterlockedIncrement (&alignmentCounters[
  766. (PtrToUlong(MemoryBlock)&(AfdBufferAlignment-1))/AFD_MINIMUM_BUFFER_ALIGNMENT]);
  767. #endif
  768. switch (placement) {
  769. case AFD_PLACEMENT_BUFFER:
  770. //
  771. // Perfect case: the memory is aready aligned as we need it.
  772. //
  773. buf = ALIGN_UP_A_POINTER(MemoryBlock, AfdBufferAlignment);
  774. alignment = (PUCHAR)buf-(PUCHAR)MemoryBlock;
  775. ASSERT (alignment<=AfdAlignmentOverhead);
  776. hdr = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, AFD_BUFFER);
  777. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, IRP);
  778. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)irp+irpSize, MDL);
  779. addr = (PCHAR)mdl+mdlSize;
  780. break;
  781. //
  782. // Other cases, we use hdr, mdl, and IRP to try to compensate
  783. // and have the data buffer aligned at the AfdBufferAlignment
  784. // boundary.
  785. //
  786. case AFD_PLACEMENT_HDR:
  787. hdr = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, AFD_BUFFER);
  788. alignment = (PUCHAR)hdr-(PUCHAR)MemoryBlock;
  789. ASSERT (alignment<=AfdAlignmentOverhead);
  790. buf = ALIGN_UP_A_POINTER((PCHAR)hdr+hdrSize, AfdBufferAlignment);
  791. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, IRP);
  792. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)irp+irpSize, MDL);
  793. addr = (PCHAR)mdl+mdlSize;
  794. break;
  795. case AFD_PLACEMENT_MDL:
  796. mdl = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, MDL);
  797. alignment = (PUCHAR)mdl-(PUCHAR)MemoryBlock;
  798. ASSERT (alignment<=AfdAlignmentOverhead);
  799. buf = ALIGN_UP_A_POINTER((PCHAR)mdl+mdlSize, AfdBufferAlignment);
  800. hdr = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, AFD_BUFFER);
  801. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, IRP);
  802. addr = (PCHAR)irp+irpSize;
  803. break;
  804. case AFD_PLACEMENT_IRP:
  805. irp = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, IRP);
  806. alignment = (PUCHAR)irp-(PUCHAR)MemoryBlock;
  807. ASSERT (alignment<=AfdAlignmentOverhead);
  808. buf = ALIGN_UP_A_POINTER((PCHAR)irp+irpSize, AfdBufferAlignment);
  809. hdr = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, AFD_BUFFER);
  810. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, MDL);
  811. addr = (PCHAR)mdl+mdlSize;
  812. break;
  813. case AFD_PLACEMENT_HDR_IRP:
  814. hdr = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, AFD_BUFFER);
  815. alignment = (PUCHAR)hdr-(PUCHAR)MemoryBlock;
  816. ASSERT (alignment<=AfdAlignmentOverhead);
  817. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, IRP);
  818. buf = ALIGN_UP_A_POINTER((PCHAR)irp+irpSize, AfdBufferAlignment);
  819. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, MDL);
  820. addr = (PCHAR)mdl+mdlSize;
  821. break;
  822. case AFD_PLACEMENT_HDR_MDL:
  823. hdr = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, AFD_BUFFER);
  824. alignment = (PUCHAR)hdr-(PUCHAR)MemoryBlock;
  825. ASSERT (alignment<=AfdAlignmentOverhead);
  826. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, MDL);
  827. buf = ALIGN_UP_A_POINTER((PCHAR)mdl+mdlSize, AfdBufferAlignment);
  828. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, IRP);
  829. addr = (PCHAR)irp+irpSize;
  830. break;
  831. case AFD_PLACEMENT_IRP_MDL:
  832. irp = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, IRP);
  833. alignment = (PUCHAR)irp-(PUCHAR)MemoryBlock;
  834. ASSERT (alignment<=AfdAlignmentOverhead);
  835. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)irp+irpSize, MDL);
  836. buf = ALIGN_UP_A_POINTER((PCHAR)mdl+mdlSize, AfdBufferAlignment);
  837. hdr = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, AFD_BUFFER);
  838. addr = (PCHAR)hdr+hdrSize;
  839. break;
  840. case AFD_PLACEMENT_HDR_IRP_MDL:
  841. hdr = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, AFD_BUFFER);
  842. alignment = (PUCHAR)hdr-(PUCHAR)MemoryBlock;
  843. ASSERT (alignment<=AfdAlignmentOverhead);
  844. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, IRP);
  845. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)irp+irpSize, MDL);
  846. buf = ALIGN_UP_A_POINTER((PCHAR)mdl+mdlSize, AfdBufferAlignment);
  847. addr = (PCHAR)buf+BufferDataSize;
  848. break;
  849. default:
  850. ASSERT (!"Unknown placement!");
  851. __assume (0);
  852. }
  853. //
  854. // Initialize the AfdBuffer - most fields need to be 0.
  855. //
  856. RtlZeroMemory( hdr, sizeof(*hdr) );
  857. //
  858. // Setup buffer
  859. //
  860. hdr->Buffer = buf;
  861. hdr->BufferLength = BufferDataSize;
  862. //
  863. // We just need to store first two bits of placement
  864. // so we know which part comes first to free it properly.
  865. //
  866. hdr->Placement = placement & 3;
  867. //
  868. // If we have to align the memory block to meet the requirement
  869. // store this information right below the first piece.
  870. //
  871. if (alignment!=0) {
  872. C_ASSERT (AFD_MINIMUM_BUFFER_ALIGNMENT>=sizeof (SIZE_T));
  873. C_ASSERT ((AFD_MINIMUM_BUFFER_ALIGNMENT & (sizeof(SIZE_T)-1))==0);
  874. ASSERT (alignment>=sizeof (SIZE_T));
  875. hdr->AlignmentAdjusted = TRUE;
  876. *(((PSIZE_T)(((PUCHAR)MemoryBlock)+alignment))-1) = alignment;
  877. }
  878. //
  879. // Initialize the IRP pointer.
  880. //
  881. hdr->Irp = irp;
  882. IoInitializeIrp( hdr->Irp, irpSize, (CCHAR)(AfdIrpStackSize-1) );
  883. hdr->Irp->MdlAddress = mdl;
  884. //
  885. // Set up the MDL pointer.
  886. //
  887. hdr->Mdl = mdl;
  888. MmInitializeMdl( hdr->Mdl, buf, BufferDataSize );
  889. MmBuildMdlForNonPagedPool( hdr->Mdl );
  890. //
  891. // Set up the address buffer pointer.
  892. //
  893. if (AddressSize>0) {
  894. hdr->TdiInfo.RemoteAddress = ALIGN_UP_TO_TYPE_POINTER(addr, TRANSPORT_ADDRESS);;
  895. hdr->AllocatedAddressLength = (USHORT)AddressSize;
  896. }
  897. #if DBG
  898. hdr->BufferListEntry.Flink = UIntToPtr( 0xE0E1E2E3 );
  899. hdr->BufferListEntry.Blink = UIntToPtr( 0xE4E5E6E7 );
  900. #endif
  901. return hdr;
  902. } // AfdInitializeBuffer
  903. VOID
  904. AfdInitializeBufferTag (
  905. IN PAFD_BUFFER_TAG AfdBufferTag,
  906. IN CLONG AddressSize
  907. )
  908. /*++
  909. Routine Description:
  910. Initializes an AFD buffer. Sets up fields in the actual AFD_BUFFER
  911. structure and initializes the IRP and MDL associated with the
  912. buffer. This routine assumes that the caller has properly allocated
  913. sufficient space for all this.
  914. Arguments:
  915. AfdBuffer - points to the AFD_BUFFER structure to initialize.
  916. BufferDataSize - the size of the data buffer that goes along with the
  917. buffer structure.
  918. AddressSize - the size of data allocated for the address buffer.
  919. ListHead - the global list this buffer belongs to, or NULL if it
  920. doesn't belong on any list. This routine does NOT place the
  921. buffer structure on the list.
  922. Return Value:
  923. None.
  924. --*/
  925. {
  926. AfdBufferTag->Mdl = NULL;
  927. AfdBufferTag->BufferLength = AfdBufferTagSize;
  928. AfdBufferTag->TdiInfo.RemoteAddress = AddressSize ? AfdBufferTag+1 : NULL;
  929. AfdBufferTag->AllocatedAddressLength = (USHORT)AddressSize;
  930. AfdBufferTag->Flags = 0;
  931. #if DBG
  932. AfdBufferTag->BufferListEntry.Flink = UIntToPtr( 0xE0E1E2E3 );
  933. AfdBufferTag->BufferListEntry.Blink = UIntToPtr( 0xE4E5E6E7 );
  934. AfdBufferTag->Caller = NULL;
  935. AfdBufferTag->CallersCaller = NULL;
  936. #endif
  937. }
  938. VOID
  939. AfdInitializeBufferManager (
  940. VOID
  941. )
  942. {
  943. SIZE_T irpSize = ALIGN_UP_A(IoSizeOfIrp (AfdIrpStackSize-1), AFD_MINIMUM_BUFFER_ALIGNMENT);
  944. SIZE_T hdrSize = ALIGN_UP_A(sizeof (AFD_BUFFER), AFD_MINIMUM_BUFFER_ALIGNMENT);
  945. SIZE_T mdlSize = ALIGN_UP_A(MmSizeOfMdl (NULL, PAGE_SIZE),AFD_MINIMUM_BUFFER_ALIGNMENT);
  946. UCHAR placement;
  947. ULONG i;
  948. ULONG currentOverhead;
  949. //
  950. // Initialize the alignment table.
  951. // This table is used to determine what kind of element
  952. // placement to use in AFD_BUFFER depending on the alignment
  953. // of the memory block returned by the executive pool manager.
  954. // The goal is to align the data buffer on the cache line
  955. // boundary. However, since executive only guarantees alignment of
  956. // it's blocks at the CPU alignment requirements, we need to
  957. // adjust and potentially waste up to CACHE_LIST_SIZE-CPU_ALIGNMENT_SIZE.
  958. // With some machines having cache line alignment at 128 such memory
  959. // waste is prohibitive (small buffers with default size of 128 will double
  960. // in size).
  961. // The table below allows us to rearrange pieces in AFD_BUFFER structure,
  962. // namely, the header, IRP, MDL, and data buffer, so that pieces with
  963. // lower alignment requirement can be used to consume the space needed
  964. // to adjust the memory block to the cache line boundary.
  965. //
  966. // AfdAlignmentTable has an entry for each possible case of memory block
  967. // misaligned against cache line size. For example, in typical X86 system
  968. // case executive pool manager always returns blocks aligned on 8 byte bounday,
  969. // while cache lines are typically 64 bytes long, so memory manager can
  970. // theoretically return blocks misaligned against cache by:
  971. // 8, 16, 24, 32, 40, 48, 56.
  972. // For each of these cases we will try to adjust the alignment by using
  973. // any possible combination of header, IRP, and MDL. There will be some
  974. // cases that cannot be adjusted exactly, and we will have to pad.
  975. //
  976. //
  977. // First initialize the table assuming the data buffer is placed first.
  978. //
  979. RtlFillMemory (AfdAlignmentTable, AfdAlignmentTableSize, AFD_PLACEMENT_BUFFER);
  980. #ifdef AFD_CHECK_ALIGNMENT
  981. RtlZeroMemory (&AfdAlignmentTable[AfdAlignmentTableSize],
  982. AfdAlignmentTableSize*sizeof(LONG));
  983. #endif
  984. //
  985. // Now identify the entries that can be padded with some combination of
  986. // header, IRP, and MDL:
  987. // extract the bits that can be used for padding
  988. // reverse to get corresponding memory block alignments
  989. // divide by the step of the alignment table
  990. // make sure we won't go past table size (last entry => 0 entry).
  991. //
  992. #define AfdInitAlignmentTableRow(_size,_plcmnt) \
  993. AfdAlignmentTable[ \
  994. ((AfdBufferAlignment-(_size&(AfdBufferAlignment-1))) \
  995. /AFD_MINIMUM_BUFFER_ALIGNMENT) \
  996. &(AfdAlignmentTableSize-1)] = _plcmnt
  997. //
  998. // We let placements beginning with header override others,
  999. // since it is more natural and easier to debug (header has references
  1000. // to other pieces).
  1001. //
  1002. AfdInitAlignmentTableRow(mdlSize,AFD_PLACEMENT_MDL);
  1003. AfdInitAlignmentTableRow(irpSize,AFD_PLACEMENT_IRP);
  1004. AfdInitAlignmentTableRow((irpSize+mdlSize),AFD_PLACEMENT_IRP_MDL);
  1005. AfdInitAlignmentTableRow((hdrSize+mdlSize),AFD_PLACEMENT_HDR_MDL);
  1006. AfdInitAlignmentTableRow((hdrSize+irpSize),AFD_PLACEMENT_HDR_IRP);
  1007. AfdInitAlignmentTableRow((hdrSize+irpSize+mdlSize),AFD_PLACEMENT_HDR_IRP_MDL);
  1008. AfdInitAlignmentTableRow(hdrSize,AFD_PLACEMENT_HDR);
  1009. //
  1010. // Now scan the table from top to bottom and fill entries that do not have
  1011. // exact match using the above combinations. Use the closest entry above and
  1012. // in the process compute how much do we need to pad in addition to padding
  1013. // achieved via placement.
  1014. //
  1015. AfdAlignmentOverhead = 0;
  1016. currentOverhead = 0;
  1017. //
  1018. // By default use the placement of aligned block.
  1019. //
  1020. placement = AfdAlignmentTable[0];
  1021. for (i=AfdAlignmentTableSize-1; i>0; i--) {
  1022. if (AfdAlignmentTable[i]==AFD_PLACEMENT_BUFFER) {
  1023. AfdAlignmentTable[i] = placement;
  1024. currentOverhead += AFD_MINIMUM_BUFFER_ALIGNMENT;
  1025. }
  1026. else {
  1027. placement = AfdAlignmentTable[i];
  1028. if (AfdAlignmentOverhead<currentOverhead) {
  1029. AfdAlignmentOverhead = currentOverhead;
  1030. }
  1031. currentOverhead = 0;
  1032. }
  1033. }
  1034. if (AfdAlignmentOverhead<currentOverhead) {
  1035. AfdAlignmentOverhead = currentOverhead;
  1036. }
  1037. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1038. "AfdInitializeBufferManager: Alignment requirements: MM-%d, cache-%d, overhead-%d\n",
  1039. AFD_MINIMUM_BUFFER_ALIGNMENT,
  1040. AfdBufferAlignment,
  1041. AfdAlignmentOverhead));
  1042. {
  1043. CLONG oldBufferLengthForOnePage = AfdBufferLengthForOnePage;
  1044. AfdBufferOverhead = AfdCalculateBufferSize( PAGE_SIZE, AfdStandardAddressLength) - PAGE_SIZE;
  1045. AfdBufferLengthForOnePage = ALIGN_DOWN_A(
  1046. PAGE_SIZE-AfdBufferOverhead,
  1047. AFD_MINIMUM_BUFFER_ALIGNMENT);
  1048. if (AfdLargeBufferSize==oldBufferLengthForOnePage) {
  1049. AfdLargeBufferSize = AfdBufferLengthForOnePage;
  1050. }
  1051. }
  1052. }