2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/mdl.c
5 * PURPOSE: I/O Wrappers for MDL Allocation and Deallocation
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES *****************************************************************/
15 /* FUNCTIONS *****************************************************************/
22 IoAllocateMdl(IN PVOID VirtualAddress
,
24 IN BOOLEAN SecondaryBuffer
,
25 IN BOOLEAN ChargeQuota
,
32 /* Make sure we got a valid length */
35 /* Fail if allocation is over 2GB */
36 if (Length
& 0x80000000) return NULL
;
38 /* Calculate the number of pages for the allocation */
39 Size
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress
, Length
);
42 /* This is bigger then our fixed-size MDLs. Calculate real size */
43 Size
*= sizeof(PFN_NUMBER
);
45 if (Size
> MAXUSHORT
) return NULL
;
49 /* Use an internal fixed MDL size */
50 Size
= (23 * sizeof(PFN_NUMBER
)) + sizeof(MDL
);
51 Flags
|= MDL_ALLOCATED_FIXED_SIZE
;
53 /* Allocate one from the lookaside list */
54 Mdl
= IopAllocateMdlFromLookaside(LookasideMdlList
);
57 /* Check if we don't have an mdl yet */
60 /* Allocate one from pool */
61 Mdl
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_MDL
);
62 if (!Mdl
) return NULL
;
66 MmInitializeMdl(Mdl
, VirtualAddress
, Length
);
67 Mdl
->MdlFlags
|= Flags
;
69 /* Check if an IRP was given too */
72 /* Check if it came with a secondary buffer */
75 /* Insert the MDL at the end */
77 while (p
->Next
) p
= p
->Next
;
82 /* Otherwise, insert it directly */
83 Irp
->MdlAddress
= Mdl
;
87 /* Return the allocated mdl */
96 IoBuildPartialMdl(IN PMDL SourceMdl
,
98 IN PVOID VirtualAddress
,
101 PPFN_NUMBER TargetPages
= (PPFN_NUMBER
)(TargetMdl
+ 1);
102 PPFN_NUMBER SourcePages
= (PPFN_NUMBER
)(SourceMdl
+ 1);
104 ULONG FlagsMask
= (MDL_IO_PAGE_READ
|
105 MDL_SOURCE_IS_NONPAGED_POOL
|
106 MDL_MAPPED_TO_SYSTEM_VA
|
109 /* Calculate the offset */
110 Offset
= (ULONG
)((ULONG_PTR
)VirtualAddress
-
111 (ULONG_PTR
)SourceMdl
->StartVa
) -
112 SourceMdl
->ByteOffset
;
114 /* Check if we don't have a length and calculate it */
115 if (!Length
) Length
= SourceMdl
->ByteCount
- Offset
;
117 /* Write the process, start VA and byte data */
118 TargetMdl
->StartVa
= (PVOID
)PAGE_ROUND_DOWN(VirtualAddress
);
119 TargetMdl
->Process
= SourceMdl
->Process
;
120 TargetMdl
->ByteCount
= Length
;
121 TargetMdl
->ByteOffset
= BYTE_OFFSET(VirtualAddress
);
123 /* Recalculate the length in pages */
124 Length
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress
, Length
);
126 /* Set the MDL Flags */
127 TargetMdl
->MdlFlags
&= (MDL_ALLOCATED_FIXED_SIZE
| MDL_ALLOCATED_MUST_SUCCEED
);
128 TargetMdl
->MdlFlags
|= SourceMdl
->MdlFlags
& FlagsMask
;
129 TargetMdl
->MdlFlags
|= MDL_PARTIAL
;
131 /* Set the mapped VA */
132 TargetMdl
->MappedSystemVa
= (PCHAR
)SourceMdl
->MappedSystemVa
+ Offset
;
134 /* Now do the copy */
135 Offset
= ((ULONG_PTR
)TargetMdl
->StartVa
- (ULONG_PTR
)SourceMdl
->StartVa
) >>
137 SourcePages
+= Offset
;
138 RtlCopyMemory(TargetPages
, SourcePages
, Length
* sizeof(PFN_NUMBER
));
148 /* Tell Mm to reuse the MDL */
149 MmPrepareMdlForReuse(Mdl
);
151 /* Check if this was a pool allocation */
152 if (!(Mdl
->MdlFlags
& MDL_ALLOCATED_FIXED_SIZE
))
154 /* Free it from the pool */
155 ExFreePoolWithTag(Mdl
, TAG_MDL
);
159 /* Free it from the lookaside */
160 IopFreeMdlFromLookaside(Mdl
, LookasideMdlList
);