Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

569 lines
11 KiB

/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
miniport.c
Abstract:
NDIS wrapper functions
Author:
Sean Selitrennikoff (SeanSe) 05-Oct-93
Jameel Hyder (JameelH) Re-organization 01-Jun-95
Environment:
Kernel mode, FSD
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Define the module number for debug code.
//
#define MODULE_NUMBER MODULE_MINISUB
#undef NdisAllocateSpinLock
#undef NdisFreeSpinLock
#undef NdisAcquireSpinLock
#undef NdisReleaseSpinLock
#undef NdisDprAcquireSpinLock
#undef NdisDprReleaseSpinLock
#undef NdisFreeBuffer
#undef NdisQueryBuffer
#undef NdisQueryBufferOffset
#undef NdisGetFirstBufferFromPacket
#undef NDIS_BUFFER_TO_SPAN_PAGES
#undef NdisGetBufferPhysicalArraySize
#undef NdisEqualString
#undef NdisInitAnsiString
#undef NdisAnsiStringToUnicodeString
#undef NdisInitUnicodeString
#undef NdisUnicodeStringToAnsiString
#undef NdisInterlockedIncrement
#undef NdisInterlockedDecrement
#undef NdisInterlockedAddUlong
#undef NdisInterlockedInsertHeadList
#undef NdisInterlockedInsertTailList
#undef NdisInterlockedRemoveHeadList
#undef NdisInterlockedPushEntryList
#undef NdisInterlockedPopEntryList
VOID
NdisAllocateSpinLock(
IN PNDIS_SPIN_LOCK SpinLock
)
{
INITIALIZE_SPIN_LOCK(&SpinLock->SpinLock);
}
VOID
NdisFreeSpinLock(
IN PNDIS_SPIN_LOCK SpinLock
)
{
UNREFERENCED_PARAMETER(SpinLock);
}
VOID
NdisAcquireSpinLock(
IN PNDIS_SPIN_LOCK SpinLock
)
{
NDIS_ACQUIRE_SPIN_LOCK(SpinLock, &SpinLock->OldIrql);
}
VOID
NdisReleaseSpinLock(
IN PNDIS_SPIN_LOCK SpinLock
)
{
NDIS_RELEASE_SPIN_LOCK(SpinLock, SpinLock->OldIrql);
}
VOID
NdisDprAcquireSpinLock(
IN PNDIS_SPIN_LOCK SpinLock
)
{
NDIS_ACQUIRE_SPIN_LOCK_DPC(SpinLock);
SpinLock->OldIrql = DISPATCH_LEVEL;
}
VOID
NdisDprReleaseSpinLock(
IN PNDIS_SPIN_LOCK SpinLock
)
{
NDIS_RELEASE_SPIN_LOCK_DPC(SpinLock);
}
VOID
NdisFreeBuffer(
IN PNDIS_BUFFER Buffer
)
{
IoFreeMdl(Buffer);
}
VOID
NdisQueryBuffer(
IN PNDIS_BUFFER Buffer,
OUT PVOID * VirtualAddress OPTIONAL,
OUT PUINT Length
)
{
if (ARGUMENT_PRESENT(VirtualAddress))
{
*VirtualAddress = MDL_ADDRESS(Buffer);
}
*Length = MDL_SIZE(Buffer);
}
VOID
NdisQueryBufferOffset(
IN PNDIS_BUFFER Buffer,
OUT PUINT Offset,
OUT PUINT Length
)
{
*Offset = MDL_OFFSET(Buffer);
*Length = MDL_SIZE(Buffer);
}
VOID
NdisGetFirstBufferFromPacket(
IN PNDIS_PACKET Packet,
OUT PNDIS_BUFFER * FirstBuffer,
OUT PVOID * FirstBufferVA,
OUT PUINT FirstBufferLength,
OUT PUINT TotalBufferLength
)
{
PNDIS_BUFFER pBuf;
pBuf = Packet->Private.Head;
*FirstBuffer = pBuf;
*FirstBufferVA = MmGetMdlVirtualAddress(pBuf);
*FirstBufferLength =
*TotalBufferLength = MmGetMdlByteCount(pBuf);
for (pBuf = pBuf->Next;
pBuf != NULL;
pBuf = pBuf->Next)
{
*TotalBufferLength += MmGetMdlByteCount(pBuf);
}
}
ULONG
NDIS_BUFFER_TO_SPAN_PAGES(
IN PNDIS_BUFFER Buffer
)
{
if (MDL_SIZE(Buffer) == 0)
{
return 1;
}
return COMPUTE_PAGES_SPANNED(MDL_VA(Buffer), MDL_SIZE(Buffer));
}
VOID
NdisGetBufferPhysicalArraySize(
IN PNDIS_BUFFER Buffer,
OUT PUINT ArraySize
)
{
if (MDL_SIZE(Buffer) == 0)
{
*ArraySize = 1;
}
else
{
*ArraySize = COMPUTE_PAGES_SPANNED(MDL_VA(Buffer), MDL_SIZE(Buffer));
}
}
BOOLEAN
NdisEqualString(
IN PNDIS_STRING String1,
IN PNDIS_STRING String2,
IN BOOLEAN CaseInsensitive
)
{
return RtlEqualUnicodeString(String1, String2, CaseInsensitive);
}
VOID
NdisInitAnsiString(
IN OUT PANSI_STRING DestinationString,
IN PCSZ SourceString
)
{
RtlInitAnsiString(DestinationString, SourceString);
}
VOID
NdisInitUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString
)
{
RtlInitUnicodeString(DestinationString, SourceString);
}
NDIS_STATUS
NdisAnsiStringToUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PANSI_STRING SourceString
)
{
NDIS_STATUS Status;
Status = RtlAnsiStringToUnicodeString(DestinationString,
SourceString,
FALSE);
return Status;
}
NDIS_STATUS
NdisUnicodeStringToAnsiString(
IN OUT PANSI_STRING DestinationString,
IN PUNICODE_STRING SourceString
)
{
NDIS_STATUS Status;
Status = RtlUnicodeStringToAnsiString(DestinationString,
SourceString,
FALSE);
return Status;
}
VOID
NdisMStartBufferPhysicalMapping(
IN NDIS_HANDLE MiniportAdapterHandle,
IN PNDIS_BUFFER Buffer,
IN ULONG PhysicalMapRegister,
IN BOOLEAN WriteToDevice,
OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray,
OUT PUINT ArraySize
)
{
NdisMStartBufferPhysicalMappingMacro(MiniportAdapterHandle,
Buffer,
PhysicalMapRegister,
WriteToDevice,
PhysicalAddressArray,
ArraySize);
}
VOID
NdisMCompleteBufferPhysicalMapping(
IN NDIS_HANDLE MiniportAdapterHandle,
IN PNDIS_BUFFER Buffer,
IN ULONG PhysicalMapRegister
)
{
NdisMCompleteBufferPhysicalMappingMacro(MiniportAdapterHandle,
Buffer,
PhysicalMapRegister);
}
ULONG
NdisInterlockedIncrement(
IN PULONG Addend
)
/*++
Return Value:
(eax) < 0 (but not necessarily -1) if result of add < 0
(eax) == 0 if result of add == 0
(eax) > 0 (but not necessarily +1) if result of add > 0
--*/
{
return(InterlockedIncrement(Addend));
}
ULONG
NdisInterlockedDecrement(
IN PULONG Addend
)
/*++
Return Value:
(eax) < 0 (but not necessarily -1) if result of add < 0
(eax) == 0 if result of add == 0
(eax) > 0 (but not necessarily +1) if result of add > 0
--*/
{
return(InterlockedDecrement(Addend));
}
ULONG
NdisInterlockedAddUlong(
IN PULONG Addend,
IN ULONG Increment,
IN PNDIS_SPIN_LOCK SpinLock
)
{
return(ExInterlockedAddUlong(Addend,Increment, &SpinLock->SpinLock));
}
PLIST_ENTRY
NdisInterlockedInsertHeadList(
IN PLIST_ENTRY ListHead,
IN PLIST_ENTRY ListEntry,
IN PNDIS_SPIN_LOCK SpinLock
)
{
return(ExInterlockedInsertHeadList(ListHead,ListEntry,&SpinLock->SpinLock));
}
PLIST_ENTRY
NdisInterlockedInsertTailList(
IN PLIST_ENTRY ListHead,
IN PLIST_ENTRY ListEntry,
IN PNDIS_SPIN_LOCK SpinLock
)
{
return(ExInterlockedInsertTailList(ListHead,ListEntry,&SpinLock->SpinLock));
}
PLIST_ENTRY
NdisInterlockedRemoveHeadList(
IN PLIST_ENTRY ListHead,
IN PNDIS_SPIN_LOCK SpinLock
)
{
return(ExInterlockedRemoveHeadList(ListHead, &SpinLock->SpinLock));
}
PSINGLE_LIST_ENTRY
NdisInterlockedPushEntryList(
IN PSINGLE_LIST_ENTRY ListHead,
IN PSINGLE_LIST_ENTRY ListEntry,
IN PNDIS_SPIN_LOCK Lock
)
{
return(ExInterlockedPushEntryList(ListHead, ListEntry, &Lock->SpinLock));
}
PSINGLE_LIST_ENTRY
NdisInterlockedPopEntryList(
IN PSINGLE_LIST_ENTRY ListHead,
IN PNDIS_SPIN_LOCK Lock
)
{
return(ExInterlockedPopEntryList(ListHead, &Lock->SpinLock));
}
//
// Logging support for miniports
//
NDIS_STATUS
NdisMCreateLog(
IN NDIS_HANDLE MiniportAdapterHandle,
IN UINT Size,
OUT PNDIS_HANDLE LogHandle
)
{
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
PNDIS_LOG Log = NULL;
NDIS_STATUS Status;
KIRQL OldIrql;
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
if (Miniport->Log != NULL)
{
Status = NDIS_STATUS_FAILURE;
}
else
{
Log = ALLOC_FROM_POOL(sizeof(NDIS_LOG) + Size, NDIS_TAG_DBG_LOG);
if (Log != NULL)
{
Status = NDIS_STATUS_SUCCESS;
Miniport->Log = Log;
INITIALIZE_SPIN_LOCK(&Log->LogLock);
Log->Miniport = Miniport;
Log->Irp = NULL;
Log->TotalSize = Size;
Log->CurrentSize = 0;
Log->InPtr = 0;
Log->OutPtr = 0;
}
else
{
Status = NDIS_STATUS_RESOURCES;
}
}
*LogHandle = Log;
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
return Status;
}
VOID
NdisMCloseLog(
IN NDIS_HANDLE LogHandle
)
{
PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
PNDIS_MINIPORT_BLOCK Miniport;
KIRQL OldIrql;
Miniport = Log->Miniport;
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
Miniport->Log = NULL;
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
FREE_POOL(Log);
}
NDIS_STATUS
NdisMWriteLogData(
IN NDIS_HANDLE LogHandle,
IN PVOID LogBuffer,
IN UINT LogBufferSize
)
{
PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
NDIS_STATUS Status;
KIRQL OldIrql;
UINT AmtToCopy;
ACQUIRE_SPIN_LOCK(&Log->LogLock, &OldIrql);
if (LogBufferSize <= Log->TotalSize)
{
if (LogBufferSize <= (Log->TotalSize - Log->InPtr))
{
//
// Can copy the entire buffer
//
CopyMemory(Log->LogBuf+Log->InPtr, LogBuffer, LogBufferSize);
}
else
{
//
// We are going to wrap around. Copy it in two chunks.
//
AmtToCopy = Log->TotalSize - Log->InPtr;
CopyMemory(Log->LogBuf+Log->InPtr,
LogBuffer,
AmtToCopy);
CopyMemory(Log->LogBuf + 0,
(PUCHAR)LogBuffer+AmtToCopy,
LogBufferSize - AmtToCopy);
}
//
// Update the current size
//
Log->CurrentSize += LogBufferSize;
if (Log->CurrentSize > Log->TotalSize)
Log->CurrentSize = Log->TotalSize;
//
// Update the InPtr and possibly the outptr
//
Log->InPtr += LogBufferSize;
if (Log->InPtr >= Log->TotalSize)
{
Log->InPtr -= Log->TotalSize;
}
if (Log->CurrentSize == Log->TotalSize)
{
Log->OutPtr = Log->InPtr;
}
//
// Check if there is a pending Irp to complete
//
if (Log->Irp != NULL)
{
PIRP Irp = Log->Irp;
Log->Irp = NULL;
//
// If the InPtr is lagging the OutPtr. then we can simply
// copy the data over in one shot.
//
AmtToCopy = MDL_SIZE(Irp->MdlAddress);
if (AmtToCopy > Log->CurrentSize)
AmtToCopy = Log->CurrentSize;
if ((Log->TotalSize - Log->OutPtr) >= AmtToCopy)
{
CopyMemory(MDL_ADDRESS(Irp->MdlAddress),
Log->LogBuf+Log->OutPtr,
AmtToCopy);
}
else
{
CopyMemory(MDL_ADDRESS(Irp->MdlAddress),
Log->LogBuf+Log->OutPtr,
Log->TotalSize-Log->OutPtr);
CopyMemory((PUCHAR)MDL_ADDRESS(Irp->MdlAddress)+Log->TotalSize-Log->OutPtr,
Log->LogBuf,
AmtToCopy - (Log->TotalSize-Log->OutPtr));
}
Log->CurrentSize -= AmtToCopy;
Log->OutPtr += AmtToCopy;
if (Log->OutPtr >= Log->TotalSize)
Log->OutPtr -= Log->TotalSize;
Irp->IoStatus.Information = AmtToCopy;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
}
else
{
Status = NDIS_STATUS_BUFFER_OVERFLOW;
}
RELEASE_SPIN_LOCK(&Log->LogLock, OldIrql);
return Status;
}
VOID
NdisMFlushLog(
IN NDIS_HANDLE LogHandle
)
{
PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
KIRQL OldIrql;
ACQUIRE_SPIN_LOCK(&Log->LogLock, &OldIrql);
Log->InPtr = 0;
Log->OutPtr = 0;
Log->CurrentSize = 0;
RELEASE_SPIN_LOCK(&Log->LogLock, OldIrql);
}