mirror of https://github.com/lianthony/NT4.0
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.
924 lines
24 KiB
924 lines
24 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
atkbuff.c
|
|
|
|
Abstract:
|
|
|
|
This module contains all the mdl-to-pchar pointer support.
|
|
|
|
Author:
|
|
|
|
Nikhil Kamkolkar (NikhilK) 8-Jun-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "atalknt.h"
|
|
|
|
|
|
|
|
PVOID
|
|
SubsetAnMdl(
|
|
PVOID MasterMdl,
|
|
ULONG ByteOffset,
|
|
ULONG SubsetMdlSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine provides the portable code base with subset opaque
|
|
descriptor functionality.
|
|
|
|
Arguments:
|
|
|
|
MasterMdl - the master mdl
|
|
ByteOffset - offset into the mdl from where the subset is to start
|
|
(subset happens from offset to the size indicated)
|
|
SubsetMdlSize - size of subset mdl
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
PMDL subsetMdl;
|
|
PMDL newCurrentMdl;
|
|
ULONG newByteOffset, length;
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS1,
|
|
("SubsetAnMdl: MDL %lx Offset %lx SubsetSize %lx\n", MasterMdl, ByteOffset, SubsetMdlSize));
|
|
|
|
AtalkGetMdlChainLength(MasterMdl, &length);
|
|
ASSERT(ByteOffset+SubsetMdlSize <= length);
|
|
|
|
//
|
|
// ERROR:
|
|
// Adjust in case of an error, should never happen as portable stack
|
|
// guarantees this.
|
|
//
|
|
|
|
if (ByteOffset+SubsetMdlSize > length) {
|
|
SubsetMdlSize = length-ByteOffset;
|
|
}
|
|
|
|
status = BuildMdlChainFromMdlChain (
|
|
(PMDL)MasterMdl,
|
|
ByteOffset,
|
|
SubsetMdlSize,
|
|
&subsetMdl,
|
|
&newCurrentMdl,
|
|
&newByteOffset,
|
|
&length);
|
|
|
|
ASSERT(status == STATUS_SUCCESS);
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS1,
|
|
("INFO1: SubsetAnMdl - Status %lx System address: %lx", status, MmGetSystemAddressForMdl(subsetMdl)));
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
return((PVOID)NULL);
|
|
}
|
|
|
|
return((PVOID)subsetMdl);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
FreeAnMdl(
|
|
PVOID MdlDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Travels a mdl chain freeing all the elements
|
|
|
|
Arguments:
|
|
|
|
MdlDescriptor - the mdl chain to be freed
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PMDL freeMdl, currentMdl;
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS0,
|
|
("INFO0: FreeAnMdl - Freeing MDL (MAIN): %lx\n", MdlDescriptor));
|
|
|
|
currentMdl = (PMDL)MdlDescriptor;
|
|
while ((freeMdl = currentMdl) != NULL) {
|
|
currentMdl = freeMdl->Next;
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS0,
|
|
("INFO0: FreeAnMdl - Freeing MDL (CHILD): %lx\n", currentMdl));
|
|
|
|
IoFreeMdl(freeMdl);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
PVOID
|
|
MakeAnMdl(
|
|
PCHAR BaseVa,
|
|
ULONG Size
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides the portable code base the ability to describe BaseVa with
|
|
an MDL (returned as a PVOID)
|
|
|
|
Arguments:
|
|
|
|
BaseVa - Start of buffer to be described
|
|
Size - size of the buffer
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PMDL newMdl;
|
|
|
|
//
|
|
// Build the Mdl...
|
|
//
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS0,
|
|
("INFO0: MakeAnMdl - For buffer %lx - Size %d\n", BaseVa, Size));
|
|
|
|
ASSERT(Size != 0);
|
|
|
|
newMdl = IoAllocateMdl (
|
|
BaseVa,
|
|
Size,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
ASSERT(newMdl != NULL);
|
|
|
|
if (newMdl != NULL) {
|
|
|
|
//
|
|
// Now build the mdl assuming the buffers are in non-paged pool
|
|
//
|
|
|
|
MmBuildMdlForNonPagedPool(newMdl);
|
|
}
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS0,
|
|
("INFO0: MakeAnMdl - Returning MDL %lx, BaseVa %lx\n", newMdl, BaseVa));
|
|
|
|
return((PVOID)newMdl);
|
|
}
|
|
|
|
|
|
|
|
|
|
ULONG
|
|
StrlenMdlDescribedArea(
|
|
PVOID MdlDescriptor,
|
|
ULONG ByteOffset
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the length of the opaque descriptor treating it as a
|
|
null-terminated string.
|
|
|
|
Arguments:
|
|
|
|
MdlDescriptor - mdl whose strlen equivalent is to be found
|
|
ByteOffset - Start from byte offset
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG mdlSize;
|
|
|
|
//
|
|
// BUGBUG
|
|
// Change this to do a mdl-version of strlen
|
|
// Adjust for the NULL character at the end now
|
|
//
|
|
|
|
AtalkGetMdlChainLength((PMDL)MdlDescriptor, &mdlSize);
|
|
|
|
ASSERT((mdlSize-ByteOffset-1) >= 0);
|
|
return (mdlSize - ByteOffset - 1);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
MoveMdlAreaToMdlArea(
|
|
PVOID TargetOpaque,
|
|
ULONG TargetOffset,
|
|
PVOID SourceOpaque,
|
|
ULONG SourceOffset,
|
|
ULONG Size
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Used to copy from an area described by an mdl to another area described
|
|
by another mdl. Overlapping mdl's allowed.
|
|
|
|
Arguments:
|
|
|
|
TargetOpaque - destination of the move
|
|
TargetOffset - start from offset into destination
|
|
SourceOpaque - source of the move
|
|
SourceOffset - start from offset into source
|
|
Size - number of bytes to move
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_ERROR,
|
|
("ERROR: MoveMdlAreaToMdlArea - NOT IMPLEMENTED!\n"));
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
CopyDataToMdlDescribedArea(
|
|
PVOID DestinationMdl,
|
|
ULONG DestinationOffset,
|
|
PCHAR SourceBuffer,
|
|
ULONG BytesToCopy
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy from pchar buffer to mdl-described area
|
|
|
|
//
|
|
// BUGBUG: Turn this into a macro
|
|
//
|
|
|
|
Arguments:
|
|
|
|
DestinationMdl - destination buffer mdl
|
|
DestinationOffset - start from offset into destination
|
|
SourceBuffer - source of data
|
|
BytesToCopy - number of bytes to copy
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG bytesCopied = 0;
|
|
NTSTATUS status;
|
|
|
|
status = TdiCopyBufferToMdl (
|
|
SourceBuffer,
|
|
0, // SourceOffset is 0
|
|
BytesToCopy,
|
|
(PMDL)DestinationMdl,
|
|
DestinationOffset,
|
|
&bytesCopied);
|
|
|
|
ASSERT(status == STATUS_SUCCESS);
|
|
ASSERT(bytesCopied == BytesToCopy);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
CopyDataFromMdlDescribedArea(
|
|
PCHAR DestinationBuffer,
|
|
PVOID SourceMdl,
|
|
ULONG SourceOffset,
|
|
ULONG BytesToCopy
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy from mdl-described area to pchar buffer
|
|
|
|
//
|
|
// BUGBUG: Turn this into a macro
|
|
//
|
|
|
|
Arguments:
|
|
|
|
DestinationBuffer - destination buffer
|
|
SourceMdl - source of data
|
|
SourceOffset - start from offset into source
|
|
BytesToCopy - number of bytes to copy
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG bytesCopied = 0;
|
|
ULONG length;
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// BUGBUG: Lots of error situations here...
|
|
// According to Garth there should never be any error situations here...
|
|
//
|
|
|
|
#if DBG
|
|
AtalkGetMdlChainLength(SourceMdl, &length);
|
|
ASSERT(SourceOffset < length);
|
|
ASSERT((SourceOffset+BytesToCopy) <= length);
|
|
#endif
|
|
|
|
status = TdiCopyMdlToBuffer(
|
|
(PMDL)SourceMdl,
|
|
SourceOffset,
|
|
(PVOID)DestinationBuffer,
|
|
0, //Destination offset is 0
|
|
BytesToCopy, //Assume destination can hold specified bytes
|
|
&bytesCopied);
|
|
|
|
ASSERT(status == STATUS_SUCCESS);
|
|
ASSERT(BytesToCopy == bytesCopied);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
BuildMdlChainFromMdlChain (
|
|
IN PMDL CurrentMdl,
|
|
IN ULONG ByteOffset,
|
|
IN ULONG DesiredLength,
|
|
OUT PMDL *Destination,
|
|
OUT PMDL *NewCurrentMdl,
|
|
OUT ULONG *NewByteOffset,
|
|
OUT ULONG *TrueLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
(BORROWED FROM SOME NDIS CODE)
|
|
|
|
BUGBUG: Use a library version as soon as one comes into existence!
|
|
|
|
This routine is called to build an Mdl chain from a source Mdl chain and
|
|
offset into it. We assume we don't know the length of the source Mdl chain,
|
|
and we must allocate and build the Mdls for the destination chain, which
|
|
we do from non-paged pool. Note that this routine, unlike the IO subsystem
|
|
routines, sets the SystemVaMapped bit in the generated Mdls to the same
|
|
value as that in the source Mdls.
|
|
|
|
IT WOULD BE BAD TO USE MmMapLockedPages OR MmProbeAndLockPages ON THE
|
|
DESTINATION MDLS UNLESS YOU TAKE RESPONSIBILITY FOR UNMAPPING THEM!
|
|
|
|
The MDLs that are returned are mapped and locked. (Actually, the pages in
|
|
them are in the same state as those in the source MDLs.)
|
|
|
|
If the system runs out of memory while we are building the destination
|
|
MDL chain, we completely clean up the built chain and return with
|
|
NewCurrentMdl and NewByteOffset set to the current values of CurrentMdl
|
|
and ByteOffset. TrueLength is set to 0.
|
|
|
|
Environment:
|
|
|
|
Kernel Mode, Source Mdls locked. It is recommended, although not required,
|
|
that the source Mdls be mapped and locked prior to calling this routine.
|
|
|
|
Arguments:
|
|
|
|
CurrentMdl - Points to the start of the Mdl chain from which to draw the
|
|
packet.
|
|
|
|
ByteOffset - Offset within this MDL to start the packet at.
|
|
|
|
DesiredLength - The number of bytes to insert into the packet.
|
|
|
|
Destination - returned pointer to the Mdl chain describing the packet.
|
|
|
|
NewCurrentMdl - returned pointer to the Mdl that would be used for the next
|
|
byte of packet. NULL if the source Mdl chain was exhausted.
|
|
|
|
NewByteOffset - returned offset into the NewCurrentMdl for the next byte of
|
|
packet. NULL if the source Mdl chain was exhausted.
|
|
|
|
TrueLength - The actual length of the returned Mdl Chain. If less than
|
|
DesiredLength, the source Mdl chain was exhausted.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if the build of the returned MDL chain succeeded (even if
|
|
shorter than the desired chain).
|
|
|
|
STATUS_INSUFFICIENT_RESOURCES if we ran out of MDLs while building the
|
|
destination chain.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR BaseVa;
|
|
ULONG AvailableBytes;
|
|
PMDL OldMdl;
|
|
PMDL NewMdl;
|
|
|
|
//
|
|
|
|
BaseVa = (PUCHAR)MmGetMdlVirtualAddress(CurrentMdl) + ByteOffset;
|
|
|
|
AvailableBytes = MmGetMdlByteCount (CurrentMdl) - ByteOffset;
|
|
|
|
if (AvailableBytes == 0) {
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_WARNING,
|
|
("WARNING: BuildMdlChainFromMdlChain - AvailBytes: 0!"));
|
|
}
|
|
|
|
|
|
if (AvailableBytes > DesiredLength) {
|
|
AvailableBytes = DesiredLength;
|
|
}
|
|
else if (AvailableBytes < DesiredLength)
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS0,
|
|
("INFO0: BuildMdlChainFromMdlChain - Mdl: %lx Va: %lx Offset: %ld DesiredLength: %lx AvailBytes %lx\n", CurrentMdl, BaseVa, ByteOffset, DesiredLength, AvailableBytes));
|
|
|
|
OldMdl = CurrentMdl;
|
|
*NewCurrentMdl = OldMdl;
|
|
*NewByteOffset = ByteOffset + AvailableBytes;
|
|
*TrueLength = AvailableBytes;
|
|
|
|
|
|
//
|
|
// Build the first Mdl, which could conceivably be the only one...
|
|
//
|
|
|
|
NewMdl = IoAllocateMdl (
|
|
BaseVa,
|
|
AvailableBytes,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
*Destination = NewMdl;
|
|
|
|
if (NewMdl == NULL) {
|
|
*NewByteOffset = ByteOffset;
|
|
*TrueLength = 0;
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_ERROR,
|
|
("ERROR: BuildMdlFromMdl - IoAllocateMdl failed! BaseVa %lx AvailBy %lx\n", BaseVa, AvailableBytes));
|
|
DBGBRK(ATALK_DEBUG_MDL, DEBUG_LEVEL_ERROR);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
IoBuildPartialMdl (
|
|
OldMdl,
|
|
NewMdl,
|
|
BaseVa,
|
|
AvailableBytes);
|
|
|
|
NewMdl->Next = (PMDL)NULL;
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS0,
|
|
("BuildMdletc: (start)Built Mdl: %lx Length: %lx, Next: %lx Va: %lx\n",
|
|
NewMdl, MmGetMdlByteCount (NewMdl),
|
|
NewMdl->Next, MmGetSystemAddressForMdl(NewMdl)));
|
|
|
|
//
|
|
// Was the first Mdl enough data, or are we out of Mdls?
|
|
//
|
|
|
|
if ((AvailableBytes == DesiredLength) || (OldMdl->Next == NULL)) {
|
|
if (*NewByteOffset >= MmGetMdlByteCount (OldMdl)) {
|
|
*NewCurrentMdl = OldMdl->Next;
|
|
*NewByteOffset = 0;
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Need more data, so follow the in Mdl chain to create a packet.
|
|
//
|
|
|
|
OldMdl = OldMdl->Next;
|
|
*NewCurrentMdl = OldMdl;
|
|
|
|
while (OldMdl != NULL) {
|
|
BaseVa = MmGetMdlVirtualAddress (OldMdl);
|
|
AvailableBytes = DesiredLength - *TrueLength;
|
|
if (AvailableBytes > MmGetMdlByteCount (OldMdl)) {
|
|
AvailableBytes = MmGetMdlByteCount (OldMdl);
|
|
}
|
|
|
|
NewMdl->Next = IoAllocateMdl (
|
|
BaseVa,
|
|
AvailableBytes,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
if (NewMdl->Next == NULL) {
|
|
|
|
//
|
|
// ran out of resources. put back what we've used in this call and
|
|
// return the error.
|
|
//
|
|
|
|
while (*Destination != NULL) {
|
|
NewMdl = (*Destination)->Next;
|
|
IoFreeMdl (*Destination);
|
|
*Destination = NewMdl;
|
|
NewMdl = NewMdl->Next;
|
|
}
|
|
|
|
*NewByteOffset = ByteOffset;
|
|
*TrueLength = 0;
|
|
*NewCurrentMdl = CurrentMdl;
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
NewMdl = NewMdl->Next;
|
|
|
|
IoBuildPartialMdl (
|
|
OldMdl,
|
|
NewMdl,
|
|
BaseVa,
|
|
AvailableBytes);
|
|
NewMdl->Next = (PMDL)NULL;
|
|
|
|
*TrueLength += AvailableBytes;
|
|
*NewByteOffset = AvailableBytes;
|
|
|
|
DBGPRINT(ATALK_DEBUG_MDL, DEBUG_LEVEL_INFOCLASS0,
|
|
("BuildMdletc: (continue)Built Mdl: %lx Length: %lx, Next: %lx Va: %lx\n",
|
|
NewMdl, MmGetMdlByteCount (NewMdl),
|
|
NewMdl->Next, MmGetSystemAddressForMdl(NewMdl)));
|
|
|
|
|
|
if (*TrueLength == DesiredLength) {
|
|
if (*NewByteOffset == MmGetMdlByteCount (OldMdl)) {
|
|
*NewCurrentMdl = OldMdl->Next;
|
|
*NewByteOffset = 0;
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
OldMdl = OldMdl->Next;
|
|
*NewCurrentMdl = OldMdl;
|
|
|
|
} // while (mdl chain exists)
|
|
|
|
*NewCurrentMdl = NULL;
|
|
*NewByteOffset = 0;
|
|
return STATUS_SUCCESS;
|
|
|
|
} // BuildMdlChainFromMdlChain
|
|
|
|
|
|
#if 0
|
|
|
|
NTSTATUS
|
|
TdiCopyMdlToBuffer(
|
|
IN PMDL SourceMdlChain,
|
|
IN ULONG SourceOffset,
|
|
IN PVOID DestinationBuffer,
|
|
IN ULONG DestinationOffset,
|
|
IN ULONG DestinationBufferSize,
|
|
OUT PULONG BytesCopied
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine copies data described by the source MDL chain starting at
|
|
the source offset, into a flat buffer specified by the SVA starting at
|
|
the destination offset. A maximum of DestinationBufferSize bytes can
|
|
be copied. The actual number of bytes copied is returned in BytesCopied.
|
|
|
|
Arguments:
|
|
|
|
SourceMdlChain - Pointer to a chain of MDLs describing the source data.
|
|
|
|
SourceOffset - Number of bytes to skip in the source data.
|
|
|
|
DestinationBuffer - Pointer to a flat buffer to copy the data to.
|
|
|
|
DestinationOffset - Number of leading bytes to skip in the destination buffer.
|
|
|
|
DestinationBufferSize - Size of the output buffer, including the offset.
|
|
|
|
BytesCopied - Pointer to a longword where the actual number of bytes
|
|
transferred will be returned.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - status of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
PUCHAR Dest, Src;
|
|
ULONG SrcBytesLeft, DestBytesLeft, BytesSkipped=0;
|
|
ULONG junk;
|
|
|
|
DBGBRK(ATALK_DEBUG_MDL, (0);
|
|
|
|
*BytesCopied = 0;
|
|
|
|
//
|
|
// Skip source bytes.
|
|
//
|
|
|
|
Src = MmGetSystemAddressForMdl (SourceMdlChain);
|
|
|
|
DbgPrint("TdiMoveMdlToBuf: A(Buffer)- %lx Buffer %s\n", Src, Src);
|
|
DbgPrint("StartVa- %lx MappedSystemVa- %lx\n", SourceMdlChain->StartVa, SourceMdlChain->MappedSystemVa);
|
|
junk = (ULONG)SourceMdlChain->StartVa | SourceMdlChain->ByteOffset;
|
|
DbgPrint("Actual src address %lx\n", junk);
|
|
|
|
SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
|
|
while (BytesSkipped < SourceOffset) {
|
|
if (SrcBytesLeft > (SourceOffset - BytesSkipped)) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Skipping part of this MDL.\n");
|
|
SrcBytesLeft -= (SourceOffset - BytesSkipped);
|
|
Src += (SourceOffset - BytesSkipped);
|
|
BytesSkipped = SourceOffset;
|
|
break;
|
|
} else if (SrcBytesLeft == (SourceOffset - BytesSkipped)) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Skipping this exact MDL.\n");
|
|
SourceMdlChain = SourceMdlChain->Next;
|
|
if (SourceMdlChain == NULL) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: MDL chain was all header.\n");
|
|
return STATUS_SUCCESS; // no bytes copied.
|
|
}
|
|
BytesSkipped = SourceOffset;
|
|
Src = MmGetSystemAddressForMdl (SourceMdlChain);
|
|
SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
|
|
break;
|
|
} else {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Skipping all of this MDL & more.\n");
|
|
BytesSkipped += SrcBytesLeft;
|
|
SourceMdlChain = SourceMdlChain->Next;
|
|
if (SourceMdlChain == NULL) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Premature end of MDL chain.\n");
|
|
return STATUS_SUCCESS; // no bytes copied.
|
|
}
|
|
Src = MmGetSystemAddressForMdl (SourceMdlChain);
|
|
SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
|
|
}
|
|
}
|
|
|
|
DbgPrint ("TdiCopyMdlToBuffer: done skipping source bytes.\n");
|
|
|
|
//
|
|
// Skip destination bytes.
|
|
//
|
|
|
|
Dest = (PUCHAR)DestinationBuffer + DestinationOffset;
|
|
DestBytesLeft = DestinationBufferSize - DestinationOffset;
|
|
|
|
//
|
|
// Copy source data into the destination buffer until it's full or
|
|
// we run out of data, whichever comes first.
|
|
//
|
|
|
|
DbgPrint("TDI MoveMdlToData: Moving data...\n");
|
|
|
|
while (DestBytesLeft && SourceMdlChain) {
|
|
if (SrcBytesLeft == 0) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: MDL is empty, skipping to next one.\n");
|
|
SourceMdlChain = SourceMdlChain->Next;
|
|
if (SourceMdlChain == NULL) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: But there are no more MDLs.\n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
Src = MmGetSystemAddressForMdl (SourceMdlChain);
|
|
SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
|
|
continue; // skip 0-length MDL's.
|
|
}
|
|
DbgPrint ("TdiCopyMdlToBuffer: Copying a chunk.\n");
|
|
if (DestBytesLeft == SrcBytesLeft) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Copying exact amount.\n");
|
|
|
|
DbgPrint ("DATA: %s\n", Src);
|
|
|
|
RtlMoveMemory (Dest, Src, DestBytesLeft);
|
|
*BytesCopied += DestBytesLeft;
|
|
return STATUS_SUCCESS;
|
|
} else if (DestBytesLeft < SrcBytesLeft) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Buffer overflow, copying some.\n");
|
|
|
|
DbgPrint ("DATA: %s\n", Src);
|
|
|
|
RtlMoveMemory (Dest, Src, DestBytesLeft);
|
|
*BytesCopied += DestBytesLeft;
|
|
return STATUS_SUCCESS;
|
|
} else {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Copying all of this MDL, & more.\n");
|
|
|
|
DbgPrint ("DATA: %s\n", Src);
|
|
|
|
RtlMoveMemory (Dest, Src, SrcBytesLeft);
|
|
*BytesCopied += SrcBytesLeft;
|
|
DestBytesLeft -= SrcBytesLeft;
|
|
Dest += SrcBytesLeft;
|
|
SrcBytesLeft = 0;
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
} /* TdiCopyMdlToBuffer */
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
TdiCopyBufferToMdl (
|
|
IN PVOID SourceBuffer,
|
|
IN ULONG SourceOffset,
|
|
IN ULONG SourceBytesToCopy,
|
|
IN PMDL DestinationMdlChain,
|
|
IN ULONG DestinationOffset,
|
|
IN PULONG BytesCopied
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine copies data described by the source buffer to the MDL chain
|
|
described by the DestinationMdlChain. The
|
|
|
|
Arguments:
|
|
|
|
SourceBuffer - pointer to the source buffer
|
|
|
|
SourceOffset - Number of bytes to skip in the source data.
|
|
|
|
SourceBytesToCopy - number of bytes to copy from the source buffer
|
|
|
|
DestinationMdlChain - Pointer to a chain of MDLs describing the
|
|
destination buffers.
|
|
|
|
DestinationOffset - Number of bytes to skip in the destination data.
|
|
|
|
BytesCopied - Pointer to a longword where the actual number of bytes
|
|
transferred will be returned.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - status of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
PUCHAR Dest, Src;
|
|
ULONG DestBytesLeft, BytesSkipped=0;
|
|
ULONG junk;
|
|
|
|
DBGBRK(ATALK_DEBUG_MDL, 0);
|
|
|
|
*BytesCopied = 0;
|
|
|
|
//
|
|
// Skip Destination bytes.
|
|
//
|
|
|
|
DbgPrint("TdiMoveBufToMDL: SourceBuffer %s DestMDL\n", SourceBuffer, DestinationMdlChain);
|
|
DbgPrint("DestStartVa- %lx DestMappedSystemVa- %lx\n", DestinationMdlChain->StartVa, DestinationMdlChain->MappedSystemVa);
|
|
junk = (ULONG)DestinationMdlChain->StartVa | DestinationMdlChain->ByteOffset;
|
|
DbgPrint("Actual dest address %lx\n", junk);
|
|
|
|
Dest = MmGetSystemAddressForMdl (DestinationMdlChain);
|
|
DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
|
|
while (BytesSkipped < DestinationOffset) {
|
|
if (DestBytesLeft > (DestinationOffset - BytesSkipped)) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Skipping part of this MDL.\n");
|
|
DestBytesLeft -= (DestinationOffset - BytesSkipped);
|
|
Dest += (DestinationOffset - BytesSkipped);
|
|
BytesSkipped = DestinationOffset;
|
|
break;
|
|
} else if (DestBytesLeft == (DestinationOffset - BytesSkipped)) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Skipping this exact MDL.\n");
|
|
DestinationMdlChain = DestinationMdlChain->Next;
|
|
if (DestinationMdlChain == NULL) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: MDL chain was all header.\n");
|
|
return STATUS_SUCCESS; // no bytes copied.
|
|
}
|
|
BytesSkipped = DestinationOffset;
|
|
Dest = MmGetSystemAddressForMdl (DestinationMdlChain);
|
|
DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
|
|
break;
|
|
} else {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Skipping all of this MDL & more.\n");
|
|
BytesSkipped += DestBytesLeft;
|
|
DestinationMdlChain = DestinationMdlChain->Next;
|
|
if (DestinationMdlChain == NULL) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Premature end of MDL chain.\n");
|
|
return STATUS_SUCCESS; // no bytes copied.
|
|
}
|
|
Dest = MmGetSystemAddressForMdl (DestinationMdlChain);
|
|
DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
|
|
}
|
|
}
|
|
|
|
DbgPrint ("TdiCopyMdlToBuffer: done skipping source bytes.\n");
|
|
|
|
//
|
|
// Skip source bytes.
|
|
//
|
|
|
|
Src = (PUCHAR)SourceBuffer + SourceOffset;
|
|
|
|
//
|
|
// Copy source data into the destination buffer until it's full or
|
|
// we run out of data, whichever comes first.
|
|
//
|
|
|
|
while ((SourceBytesToCopy != 0) && (DestinationMdlChain != NULL)) {
|
|
if (DestBytesLeft == 0) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: MDL is empty, skipping to next one.\n");
|
|
DestinationMdlChain = DestinationMdlChain->Next;
|
|
if (DestinationMdlChain == NULL) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: But there are no more MDLs.\n");
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
Dest = MmGetSystemAddressForMdl (DestinationMdlChain);
|
|
DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
|
|
continue; // skip 0-length MDL's.
|
|
}
|
|
|
|
DbgPrint ("TdiCopyMdlToBuffer: Copying a chunk.\n");
|
|
if (DestBytesLeft >= SourceBytesToCopy) {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Copying exact amount.\n");
|
|
RtlMoveMemory (Dest, Src, SourceBytesToCopy);
|
|
*BytesCopied += SourceBytesToCopy;
|
|
return STATUS_SUCCESS;
|
|
} else {
|
|
DbgPrint ("TdiCopyMdlToBuffer: Copying all of this MDL, & more.\n");
|
|
RtlMoveMemory (Dest, Src, DestBytesLeft);
|
|
*BytesCopied += DestBytesLeft;
|
|
SourceBytesToCopy -= DestBytesLeft;
|
|
Src += DestBytesLeft;
|
|
DestBytesLeft = 0;
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
} /* TdiCopyBufferToMdl */
|
|
|
|
#endif
|