mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 04:13:18 +00:00
593 lines
12 KiB
C
593 lines
12 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS NDIS library
|
|
* FILE: ndis/misc.c
|
|
*/
|
|
|
|
#include "ndissys.h"
|
|
|
|
extern LONG CancelId;
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
#undef NdisInterlockedAddUlong
|
|
VOID
|
|
EXPORT
|
|
NdisInterlockedAddUlong (
|
|
IN PULONG Addend,
|
|
IN ULONG Increment,
|
|
IN PNDIS_SPIN_LOCK SpinLock)
|
|
{
|
|
ExInterlockedAddUlong ( Addend, Increment, &SpinLock->SpinLock );
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
EXPORT
|
|
NdisInterlockedAddLargeInteger(
|
|
IN PLARGE_INTEGER Addend,
|
|
IN LARGE_INTEGER Increment,
|
|
IN PNDIS_SPIN_LOCK SpinLock)
|
|
{
|
|
/* This needs to be verified. The documentation
|
|
* seems to be missing but it is exported by
|
|
* NDIS 5.1 so I'm implementing it like the other
|
|
* interlocked routines
|
|
*/
|
|
|
|
ExInterlockedAddLargeInteger(Addend, Increment, &SpinLock->SpinLock);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG
|
|
EXPORT
|
|
NdisCompareAnsiString(
|
|
IN PNDIS_ANSI_STRING String1,
|
|
IN PNDIS_ANSI_STRING String2,
|
|
BOOLEAN CaseInSensitive)
|
|
{
|
|
/* This one needs to be verified also. See the
|
|
* comment in NdisInterlockedAddLargeInteger
|
|
*/
|
|
|
|
return RtlCompareString(String1, String2, CaseInSensitive);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG
|
|
EXPORT
|
|
NdisCompareUnicodeString(
|
|
IN PNDIS_STRING String1,
|
|
IN PNDIS_STRING String2,
|
|
IN BOOLEAN CaseInSensitive)
|
|
{
|
|
/* This one needs to be verified also. See the
|
|
* comment in NdisInterlockedAddLargeInteger
|
|
*/
|
|
|
|
return RtlCompareUnicodeString(String1, String2, CaseInSensitive);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
#undef NdisInterlockedInsertHeadList
|
|
PLIST_ENTRY
|
|
EXPORT
|
|
NdisInterlockedInsertHeadList(
|
|
IN PLIST_ENTRY ListHead,
|
|
IN PLIST_ENTRY ListEntry,
|
|
IN PNDIS_SPIN_LOCK SpinLock)
|
|
{
|
|
return ExInterlockedInsertHeadList ( ListHead, ListEntry, &SpinLock->SpinLock );
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
#undef NdisInterlockedInsertTailList
|
|
PLIST_ENTRY
|
|
EXPORT
|
|
NdisInterlockedInsertTailList(
|
|
IN PLIST_ENTRY ListHead,
|
|
IN PLIST_ENTRY ListEntry,
|
|
IN PNDIS_SPIN_LOCK SpinLock)
|
|
{
|
|
return ExInterlockedInsertTailList ( ListHead, ListEntry, &SpinLock->SpinLock );
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
#undef NdisInterlockedRemoveHeadList
|
|
PLIST_ENTRY
|
|
EXPORT
|
|
NdisInterlockedRemoveHeadList(
|
|
IN PLIST_ENTRY ListHead,
|
|
IN PNDIS_SPIN_LOCK SpinLock)
|
|
{
|
|
return ExInterlockedRemoveHeadList ( ListHead, &SpinLock->SpinLock );
|
|
}
|
|
|
|
typedef struct _NDIS_HANDLE_OBJECT
|
|
{
|
|
HANDLE FileHandle;
|
|
BOOLEAN Mapped;
|
|
ULONG FileLength;
|
|
PVOID MapBuffer;
|
|
} NDIS_HANDLE_OBJECT, *PNDIS_HANDLE_OBJECT;
|
|
|
|
FORCEINLINE
|
|
PNDIS_HANDLE_OBJECT
|
|
NDIS_HANDLE_TO_POBJECT ( NDIS_HANDLE handle )
|
|
{
|
|
return (PNDIS_HANDLE_OBJECT)handle;
|
|
}
|
|
|
|
FORCEINLINE
|
|
NDIS_HANDLE
|
|
NDIS_POBJECT_TO_HANDLE ( PNDIS_HANDLE_OBJECT obj )
|
|
{
|
|
return (NDIS_HANDLE)obj;
|
|
}
|
|
|
|
static const WCHAR NDIS_FILE_FOLDER[] = L"\\SystemRoot\\System32\\Drivers\\";
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
EXPORT
|
|
NdisMapFile(
|
|
OUT PNDIS_STATUS Status,
|
|
OUT PVOID *MappedBuffer,
|
|
IN NDIS_HANDLE FileHandle)
|
|
{
|
|
PNDIS_HANDLE_OBJECT HandleObject = (PNDIS_HANDLE_OBJECT) FileHandle;
|
|
|
|
NDIS_DbgPrint(MAX_TRACE, ("called: FileHandle 0x%x\n", FileHandle));
|
|
|
|
if (HandleObject->Mapped)
|
|
{
|
|
/* If a file already mapped we will return an error code */
|
|
NDIS_DbgPrint(MIN_TRACE, ("File already mapped\n"));
|
|
*Status = NDIS_STATUS_ALREADY_MAPPED;
|
|
return;
|
|
}
|
|
|
|
HandleObject->Mapped = TRUE;
|
|
*MappedBuffer = HandleObject->MapBuffer;
|
|
|
|
/* Set returned status */
|
|
*Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
EXPORT
|
|
NdisUnmapFile(
|
|
IN NDIS_HANDLE FileHandle)
|
|
{
|
|
PNDIS_HANDLE_OBJECT HandleObject = (PNDIS_HANDLE_OBJECT) FileHandle;
|
|
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
HandleObject->Mapped = FALSE;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
EXPORT
|
|
NdisCloseFile(
|
|
IN NDIS_HANDLE FileHandle)
|
|
{
|
|
PNDIS_HANDLE_OBJECT FileHandleObject;
|
|
|
|
ASSERT_IRQL(PASSIVE_LEVEL);
|
|
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
ASSERT ( FileHandle );
|
|
|
|
FileHandleObject = NDIS_HANDLE_TO_POBJECT(FileHandle);
|
|
|
|
ASSERT ( FileHandleObject->FileHandle );
|
|
|
|
if ( FileHandleObject->Mapped )
|
|
NdisUnmapFile ( FileHandle );
|
|
if ( FileHandleObject->MapBuffer )
|
|
ExFreePool ( FileHandleObject->MapBuffer );
|
|
|
|
ZwClose ( FileHandleObject->FileHandle );
|
|
|
|
memset ( FileHandleObject, 0, sizeof(NDIS_HANDLE_OBJECT) );
|
|
|
|
ExFreePool ( FileHandleObject );
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
EXPORT
|
|
NdisOpenFile(
|
|
OUT PNDIS_STATUS Status,
|
|
OUT PNDIS_HANDLE FileHandle,
|
|
OUT PUINT FileLength,
|
|
IN PNDIS_STRING FileName,
|
|
IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress)
|
|
{
|
|
HANDLE NtFileHandle = NULL;
|
|
NDIS_STRING FullFileName;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
PNDIS_HANDLE_OBJECT FileHandleObject = NULL;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
FILE_STANDARD_INFORMATION StandardInfo;
|
|
UINT NtFileLength;
|
|
NTSTATUS NtStatus;
|
|
|
|
ASSERT_IRQL(PASSIVE_LEVEL);
|
|
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
ASSERT ( Status && FileName );
|
|
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
FullFileName.Buffer = NULL;
|
|
|
|
FullFileName.Length = sizeof(NDIS_FILE_FOLDER) - sizeof(UNICODE_NULL);
|
|
FullFileName.MaximumLength = FileName->MaximumLength + FullFileName.Length;
|
|
FullFileName.Buffer = ExAllocatePool ( NonPagedPool, FullFileName.MaximumLength );
|
|
|
|
if ( !FullFileName.Buffer )
|
|
{
|
|
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
|
|
*Status = NDIS_STATUS_RESOURCES;
|
|
goto cleanup;
|
|
}
|
|
|
|
FileHandleObject = ExAllocatePool ( NonPagedPool, sizeof(NDIS_HANDLE_OBJECT) );
|
|
if ( !FileHandleObject )
|
|
{
|
|
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
|
|
*Status = NDIS_STATUS_RESOURCES;
|
|
goto cleanup;
|
|
}
|
|
memset ( FileHandleObject, 0, sizeof(NDIS_HANDLE_OBJECT) );
|
|
|
|
memmove ( FullFileName.Buffer, NDIS_FILE_FOLDER, FullFileName.Length );
|
|
NtStatus = RtlAppendUnicodeStringToString ( &FullFileName, FileName );
|
|
if ( !NT_SUCCESS(NtStatus) )
|
|
{
|
|
NDIS_DbgPrint(MIN_TRACE, ("RtlAppendUnicodeStringToString failed (%x)\n", NtStatus));
|
|
*Status = NDIS_STATUS_FAILURE;
|
|
goto cleanup;
|
|
}
|
|
|
|
InitializeObjectAttributes ( &ObjectAttributes,
|
|
&FullFileName,
|
|
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
|
|
NULL,
|
|
NULL );
|
|
|
|
NtStatus = ZwCreateFile (
|
|
&NtFileHandle,
|
|
FILE_READ_DATA|SYNCHRONIZE,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL, // PLARGE_INTEGER AllocationSize
|
|
0, // ULONG FileAttributes
|
|
FILE_SHARE_READ, // ULONG ShareAccess
|
|
FILE_OPEN, // ULONG CreateDisposition
|
|
FILE_SYNCHRONOUS_IO_NONALERT, // ULONG CreateOptions
|
|
0, // PVOID EaBuffer
|
|
0 ); // ULONG EaLength
|
|
|
|
if ( !NT_SUCCESS(NtStatus) )
|
|
{
|
|
NDIS_DbgPrint(MIN_TRACE, ("ZwCreateFile failed (%x) Name %wZ\n", NtStatus, FileName));
|
|
*Status = NDIS_STATUS_FILE_NOT_FOUND;
|
|
goto cleanup;
|
|
}
|
|
|
|
NtStatus = ZwQueryInformationFile(
|
|
NtFileHandle,
|
|
&IoStatusBlock,
|
|
&StandardInfo,
|
|
sizeof(StandardInfo),
|
|
FileStandardInformation);
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
NDIS_DbgPrint(MIN_TRACE, ("ZwQueryInformationFile failed (%x) Name %wZ\n", NtStatus, FileName));
|
|
*Status = NDIS_STATUS_ERROR_READING_FILE;
|
|
goto cleanup;
|
|
}
|
|
if (StandardInfo.EndOfFile.HighPart != 0 || StandardInfo.EndOfFile.LowPart == 0)
|
|
{
|
|
NDIS_DbgPrint(MIN_TRACE, ("ZwQueryInformationFile failed Name %wZ\n", FileName));
|
|
*Status = NDIS_STATUS_ERROR_READING_FILE;
|
|
goto cleanup;
|
|
}
|
|
NtFileLength = StandardInfo.EndOfFile.LowPart;
|
|
|
|
FileHandleObject->MapBuffer = ExAllocatePool( NonPagedPool, NtFileLength );
|
|
if (!FileHandleObject->MapBuffer)
|
|
{
|
|
NDIS_DbgPrint(MIN_TRACE, ("ExAllocatePool failed Name %wZ\n", FileName));
|
|
*Status = NDIS_STATUS_ERROR_READING_FILE;
|
|
goto cleanup;
|
|
}
|
|
|
|
NtStatus = ZwReadFile(
|
|
NtFileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
FileHandleObject->MapBuffer,
|
|
NtFileLength,
|
|
NULL,
|
|
NULL);
|
|
if ( !NT_SUCCESS(NtStatus) || IoStatusBlock.Information != NtFileLength )
|
|
{
|
|
NDIS_DbgPrint(MIN_TRACE, ("ZwReadFile failed (%x) Name %wZ\n", NtStatus, FileName));
|
|
*Status = NDIS_STATUS_ERROR_READING_FILE;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
if ( FullFileName.Buffer != NULL )
|
|
{
|
|
ExFreePool ( FullFileName.Buffer );
|
|
FullFileName.Buffer = NULL;
|
|
}
|
|
if ( !NT_SUCCESS(*Status) )
|
|
{
|
|
if ( FileHandleObject )
|
|
{
|
|
if ( FileHandleObject->MapBuffer )
|
|
ExFreePool( FileHandleObject->MapBuffer );
|
|
ExFreePool ( FileHandleObject );
|
|
}
|
|
*FileHandle = NULL;
|
|
}
|
|
else
|
|
{
|
|
FileHandleObject->FileHandle = NtFileHandle;
|
|
*FileHandle = NDIS_POBJECT_TO_HANDLE(FileHandleObject);
|
|
*FileLength = NtFileLength;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
CCHAR
|
|
EXPORT
|
|
NdisSystemProcessorCount(
|
|
VOID)
|
|
{
|
|
return KeNumberProcessors;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
EXPORT
|
|
NdisGetCurrentProcessorCounts(
|
|
OUT PULONG pIdleCount,
|
|
OUT PULONG pKernelAndUser,
|
|
OUT PULONG pIndex)
|
|
/*
|
|
* FUNCTION:
|
|
* ARGUMENTS:
|
|
* NOTES:
|
|
* NDIS 5.0
|
|
*/
|
|
{
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
ExGetCurrentProcessorCounts( (PULONG) pIdleCount, (PULONG) pKernelAndUser, (PULONG) pIndex);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
EXPORT
|
|
NdisGetSystemUpTime(OUT PULONG pSystemUpTime)
|
|
{
|
|
ULONG Increment;
|
|
LARGE_INTEGER TickCount;
|
|
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
/* Get the increment and current tick count */
|
|
Increment = KeQueryTimeIncrement();
|
|
KeQueryTickCount(&TickCount);
|
|
|
|
/* Convert to milliseconds and return */
|
|
TickCount.QuadPart *= Increment;
|
|
TickCount.QuadPart /= (10 * 1000);
|
|
*pSystemUpTime = TickCount.LowPart;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
#undef NdisInterlockedDecrement
|
|
LONG
|
|
EXPORT
|
|
NdisInterlockedDecrement(
|
|
IN PLONG Addend)
|
|
/*
|
|
* FUNCTION:
|
|
* ARGUMENTS:
|
|
* NOTES:
|
|
* NDIS 5.0
|
|
*/
|
|
{
|
|
return InterlockedDecrement ( Addend );
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
#undef NdisInterlockedIncrement
|
|
LONG
|
|
EXPORT
|
|
NdisInterlockedIncrement(
|
|
IN PLONG Addend)
|
|
/*
|
|
* FUNCTION:
|
|
* ARGUMENTS:
|
|
* NOTES:
|
|
* NDIS 5.0
|
|
*/
|
|
{
|
|
return InterlockedIncrement ( Addend );
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
#undef NdisInterlockedPopEntrySList
|
|
PSINGLE_LIST_ENTRY
|
|
EXPORT
|
|
NdisInterlockedPopEntrySList(
|
|
IN PSLIST_HEADER ListHead,
|
|
IN PKSPIN_LOCK Lock)
|
|
/*
|
|
* FUNCTION:
|
|
* ARGUMENTS:
|
|
* NOTES:
|
|
* NDIS 5.0
|
|
*/
|
|
{
|
|
return (PSINGLE_LIST_ENTRY)ExInterlockedPopEntrySList ( ListHead, Lock );
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
#undef NdisInterlockedPushEntrySList
|
|
PSINGLE_LIST_ENTRY
|
|
EXPORT
|
|
NdisInterlockedPushEntrySList(
|
|
IN PSLIST_HEADER ListHead,
|
|
IN PSINGLE_LIST_ENTRY ListEntry,
|
|
IN PKSPIN_LOCK Lock)
|
|
/*
|
|
* FUNCTION:
|
|
* ARGUMENTS:
|
|
* NOTES:
|
|
* NDIS 5.0
|
|
*/
|
|
{
|
|
return (PSINGLE_LIST_ENTRY)ExInterlockedPushEntrySList ( ListHead, (PSLIST_ENTRY)ListEntry, Lock );
|
|
}
|
|
|
|
|
|
VOID
|
|
NTAPI
|
|
ndisProcWorkItemHandler(PVOID pContext)
|
|
{
|
|
PNDIS_WORK_ITEM pNdisItem = (PNDIS_WORK_ITEM)pContext;
|
|
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
pNdisItem->Routine(pNdisItem, pNdisItem->Context);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
EXPORT
|
|
NdisScheduleWorkItem(
|
|
IN PNDIS_WORK_ITEM pWorkItem)
|
|
{
|
|
PWORK_QUEUE_ITEM pntWorkItem = (PWORK_QUEUE_ITEM)pWorkItem->WrapperReserved;
|
|
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
ExInitializeWorkItem(pntWorkItem, ndisProcWorkItemHandler, pWorkItem);
|
|
ExQueueWorkItem(pntWorkItem, DelayedWorkQueue);
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
EXPORT
|
|
NdisGetCurrentProcessorCpuUsage(
|
|
PULONG pCpuUsage)
|
|
/*
|
|
* FUNCTION: Returns how busy the current processor is as a percentage
|
|
* ARGUMENTS:
|
|
* pCpuUsage = Pointer to a buffer to place CPU usage
|
|
*/
|
|
{
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
ExGetCurrentProcessorCpuUsage(pCpuUsage);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG
|
|
EXPORT
|
|
NdisGetSharedDataAlignment(VOID)
|
|
{
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
return KeGetRecommendedSharedDataAlignment();
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
UINT
|
|
EXPORT
|
|
NdisGetVersion(VOID)
|
|
{
|
|
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
|
|
|
return NDIS_VERSION;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
UCHAR
|
|
EXPORT
|
|
NdisGeneratePartialCancelId(VOID)
|
|
{
|
|
UCHAR PartialCancelId;
|
|
|
|
PartialCancelId = (UCHAR)InterlockedIncrement(&CancelId);
|
|
|
|
NDIS_DbgPrint(MAX_TRACE, ("Cancel ID %u\n", PartialCancelId));
|
|
|
|
return PartialCancelId;
|
|
}
|
|
|
|
/* EOF */
|