From 36bd8e4497945604cda44057c9dbb500080700a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Tue, 6 Jun 2017 23:42:56 +0200 Subject: [PATCH] ntoskrnl.exe: Implement ExInitializeNPagedLookasideList. --- dlls/ntoskrnl.exe/ntoskrnl.c | 19 +++++++++- dlls/ntoskrnl.exe/tests/driver.c | 37 +++++++++++++++++-- include/ddk/wdm.h | 76 ++++++++++++++++++++++++++++++++++++++-- include/winnt.h | 2 ++ 4 files changed, 127 insertions(+), 7 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 0fea91b..4bd0ff7 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -2029,7 +2029,24 @@ void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside, ULONG Tag, USHORT Depth) { - FIXME( "stub: %p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth ); + TRACE( "%p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth ); + + RtlInitializeSListHead( &Lookaside->L.u.ListHead ); + Lookaside->L.Depth = 4; + Lookaside->L.MaximumDepth = 256; + Lookaside->L.TotalAllocates = 0; + Lookaside->L.u2.AllocateMisses = 0; + Lookaside->L.TotalFrees = 0; + Lookaside->L.u3.FreeMisses = 0; + Lookaside->L.Type = NonPagedPool | Flags; + Lookaside->L.Tag = Tag; + Lookaside->L.Size = Size; + Lookaside->L.u4.Allocate = Allocate ? Allocate : ExAllocatePoolWithTag; + Lookaside->L.u5.Free = Free ? Free : ExFreePool; + Lookaside->L.LastTotalAllocates = 0; + Lookaside->L.u6.LastAllocateMisses = 0; + + /* FIXME: insert in global list of lookadside lists */ } /*********************************************************************** diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 57aaa28..ab55b48 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -22,6 +22,9 @@ #include +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -238,6 +241,33 @@ static void test_version(void) ok(*pNtBuildNumber == build, "Expected build number %u, got %u\n", build, *pNtBuildNumber); } +static void test_lookaside_list(void) +{ + NPAGED_LOOKASIDE_LIST list; + ULONG tag = 0x454e4957; /* WINE */ + + ExInitializeNPagedLookasideList(&list, NULL, NULL, POOL_NX_ALLOCATION, LOOKASIDE_MINIMUM_BLOCK_SIZE, tag, 0); + ok(list.L.Depth == 4, "Expected 4 got %u\n", list.L.Depth); + ok(list.L.MaximumDepth == 256, "Expected 256 got %u\n", list.L.MaximumDepth); + ok(list.L.TotalAllocates == 0, "Expected 0 got %u\n", list.L.TotalAllocates); + ok(list.L.u2.AllocateMisses == 0, "Expected 0 got %u\n", list.L.u2.AllocateMisses); + ok(list.L.TotalFrees == 0, "Expected 0 got %u\n", list.L.TotalFrees); + ok(list.L.u3.FreeMisses == 0, "Expected 0 got %u\n", list.L.u3.FreeMisses); + ok(list.L.Type == (NonPagedPool|POOL_NX_ALLOCATION), + "Expected NonPagedPool|POOL_NX_ALLOCATION got %u\n", list.L.Type); + ok(list.L.Tag == tag, "Expected %x got %x\n", tag, list.L.Tag); + ok(list.L.Size == LOOKASIDE_MINIMUM_BLOCK_SIZE, + "Expected %u got %u\n", LOOKASIDE_MINIMUM_BLOCK_SIZE, list.L.Size); + ok(list.L.LastTotalAllocates == 0,"Expected 0 got %u\n", list.L.LastTotalAllocates); + ok(list.L.u6.LastAllocateMisses == 0,"Expected 0 got %u\n", list.L.u6.LastAllocateMisses); + ExDeleteNPagedLookasideList(&list); + + list.L.Depth = 0; + ExInitializeNPagedLookasideList(&list, NULL, NULL, 0, LOOKASIDE_MINIMUM_BLOCK_SIZE, tag, 20); + ok(list.L.Depth == 4, "Expected 4 got %u\n", list.L.Depth); + ExDeleteNPagedLookasideList(&list); +} + static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -266,6 +296,7 @@ static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) test_init_funcs(); test_load_driver(); test_version(); + test_lookaside_list(); /* print process report */ if (test_input->winetest_debug) @@ -317,7 +348,7 @@ static NTSTATUS test_load_driver_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp) { - irp->IoStatus.Status = STATUS_SUCCESS; + irp->IoStatus.u.Status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } @@ -342,14 +373,14 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp) break; } - irp->IoStatus.Status = status; + irp->IoStatus.u.Status = status; IoCompleteRequest(irp, IO_NO_INCREMENT); return status; } static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp) { - irp->IoStatus.Status = STATUS_SUCCESS; + irp->IoStatus.u.Status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 0cd1673..ed27180 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -144,20 +144,18 @@ typedef enum _KWAIT_REASON MaximumWaitReason, } KWAIT_REASON; -typedef struct _ALLOCATE_FUNCTION *PALLOCATE_FUNCTION; typedef struct _IO_TIMER *PIO_TIMER; typedef struct _IO_TIMER_ROUTINE *PIO_TIMER_ROUTINE; typedef struct _ETHREAD *PETHREAD; -typedef struct _FREE_FUNCTION *PFREE_FUNCTION; typedef struct _KTHREAD *PKTHREAD, *PRKTHREAD; typedef struct _EPROCESS *PEPROCESS; typedef struct _ERESOURCE *PERESOURCE; typedef struct _IO_WORKITEM *PIO_WORKITEM; -typedef struct _NPAGED_LOOKASIDE_LIST *PNPAGED_LOOKASIDE_LIST; typedef struct _PAGED_LOOKASIDE_LIST *PPAGED_LOOKASIDE_LIST; typedef struct _OBJECT_TYPE *POBJECT_TYPE; typedef struct _OBJECT_HANDLE_INFORMATION *POBJECT_HANDLE_INFORMATION; typedef struct _ZONE_HEADER *PZONE_HEADER; +typedef struct _LOOKASIDE_LIST_EX *PLOOKASIDE_LIST_EX; typedef struct _FAST_MUTEX { @@ -182,6 +180,11 @@ typedef struct _VPB { WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)]; } VPB, *PVPB; +#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE 0x8 +#define POOL_RAISE_IF_ALLOCATION_FAILURE 0x10 +#define POOL_COLD_ALLOCATION 0x100 +#define POOL_NX_ALLOCATION 0x200 + typedef enum _POOL_TYPE { NonPagedPool, PagedPool, @@ -1221,6 +1224,71 @@ typedef struct _KLOCK_QUEUE_HANDLE { KIRQL OldIrql; } KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE; +typedef void * (NTAPI *PALLOCATE_FUNCTION)(POOL_TYPE, SIZE_T, ULONG); +typedef void * (NTAPI *PALLOCATE_FUNCTION_EX)(POOL_TYPE, SIZE_T, ULONG, PLOOKASIDE_LIST_EX); +typedef void (NTAPI *PFREE_FUNCTION)(void *); +typedef void (NTAPI *PFREE_FUNCTION_EX)(void *, PLOOKASIDE_LIST_EX); + +#ifdef _WIN64 +#define LOOKASIDE_ALIGN DECLSPEC_CACHEALIGN +#else +#define LOOKASIDE_ALIGN +#endif + +#define LOOKASIDE_MINIMUM_BLOCK_SIZE (RTL_SIZEOF_THROUGH_FIELD(SLIST_ENTRY, Next)) + +typedef struct LOOKASIDE_ALIGN _GENERAL_LOOKASIDE +{ + union + { + SLIST_HEADER ListHead; + SINGLE_LIST_ENTRY SingleListHead; + } DUMMYUNIONNAME; + USHORT Depth; + USHORT MaximumDepth; + ULONG TotalAllocates; + union + { + ULONG AllocateMisses; + ULONG AllocateHits; + } DUMMYUNIONNAME2; + ULONG TotalFrees; + union + { + ULONG FreeMisses; + ULONG FreeHits; + } DUMMYUNIONNAME3; + POOL_TYPE Type; + ULONG Tag; + ULONG Size; + union + { + PALLOCATE_FUNCTION_EX AllocateEx; + PALLOCATE_FUNCTION Allocate; + } DUMMYUNIONNAME4; + union + { + PFREE_FUNCTION_EX FreeEx; + PFREE_FUNCTION Free; + } DUMMYUNIONNAME5; + LIST_ENTRY ListEntry; + ULONG LastTotalAllocates; + union + { + ULONG LastAllocateMisses; + ULONG LastAllocateHits; + } DUMMYUNIONNAME6; + ULONG Future[2]; +} GENERAL_LOOKASIDE; + +typedef struct LOOKASIDE_ALIGN _NPAGED_LOOKASIDE_LIST +{ + GENERAL_LOOKASIDE L; +#if defined(__i386__) + KSPIN_LOCK Lock__ObsoleteButDoNotDelete; +#endif +} NPAGED_LOOKASIDE_LIST, *PNPAGED_LOOKASIDE_LIST; + typedef NTSTATUS (NTAPI EX_CALLBACK_FUNCTION)(void *CallbackContext, void *Argument1, void *Argument2); typedef EX_CALLBACK_FUNCTION *PEX_CALLBACK_FUNCTION; @@ -1373,8 +1441,10 @@ PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG); PVOID WINAPI ExAllocatePoolWithQuotaTag(POOL_TYPE,SIZE_T,ULONG); +void WINAPI ExDeleteNPagedLookasideList(PNPAGED_LOOKASIDE_LIST); void WINAPI ExFreePool(PVOID); void WINAPI ExFreePoolWithTag(PVOID,ULONG); +void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST,PALLOCATE_FUNCTION,PFREE_FUNCTION,ULONG,SIZE_T,ULONG,USHORT); PSLIST_ENTRY WINAPI ExInterlockedPopEntrySList(PSLIST_HEADER,PKSPIN_LOCK); PSLIST_ENTRY WINAPI ExInterlockedPushEntrySList(PSLIST_HEADER,PSLIST_ENTRY,PKSPIN_LOCK); void WINAPI ExReleaseFastMutexUnsafe(PFAST_MUTEX); diff --git a/include/winnt.h b/include/winnt.h index f1c49f2..90efd6a 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -755,6 +755,8 @@ typedef struct _MEMORY_BASIC_INFORMATION #define UNICODE_STRING_MAX_CHARS 32767 #define FIELD_OFFSET(type, field) ((LONG)offsetof(type, field)) +#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field)) +#define RTL_SIZEOF_THROUGH_FIELD(type, field) (FIELD_OFFSET(type, field) + RTL_FIELD_SIZE(type, field)) #ifdef __GNUC__ # define CONTAINING_RECORD(address, type, field) ({ \ -- 1.9.1