diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 9d820bffbb0..b0f9e6202f6 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -2077,15 +2077,32 @@ NTSTATUS WINAPI ExInitializeResourceLite(PERESOURCE Resource) /*********************************************************************** * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@) */ -void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside, - PALLOCATE_FUNCTION Allocate, - PFREE_FUNCTION Free, - ULONG Flags, - SIZE_T Size, - ULONG Tag, - USHORT Depth) +void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST lookaside, + PALLOCATE_FUNCTION allocate, + PFREE_FUNCTION free, + ULONG flags, + SIZE_T size, + 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 cbf8bdca5a6..bd1070c1134 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -575,6 +575,35 @@ static void test_stack_callout(void) else win_skip("KeExpandKernelStackAndCalloutEx is not available\n"); } +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.AllocateMisses == 0, "Expected 0 got %u\n", list.L.AllocateMisses); + ok(list.L.TotalFrees == 0, "Expected 0 got %u\n", list.L.TotalFrees); + ok(list.L.FreeMisses == 0, "Expected 0 got %u\n", list.L.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.LastAllocateMisses == 0,"Expected 0 got %u\n", list.L.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); + ok(list.L.MaximumDepth == 256, "Expected 256 got %u\n", list.L.MaximumDepth); + ok(list.L.Type == NonPagedPool, "Expected NonPagedPool got %u\n", list.L.Type); + ExDeleteNPagedLookasideList(&list); +} + static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -605,6 +634,7 @@ static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) test_load_driver(); test_sync(); test_stack_callout(); + test_lookaside_list(); /* print process report */ if (test_input->winetest_debug) diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 03af14dbc15..c3e2a16f235 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -153,20 +153,18 @@ typedef struct _KWAIT_BLOCK { USHORT WaitType; } KWAIT_BLOCK, *PKWAIT_BLOCK, *RESTRICTED_POINTER PRKWAIT_BLOCK; -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; #define FM_LOCK_BIT 0x1 @@ -193,6 +191,11 @@ typedef struct _VPB { WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)]; } VPB, *PVPB; +#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE 0x0008 +#define POOL_RAISE_IF_ALLOCATION_FAILURE 0x0010 +#define POOL_COLD_ALLOCATION 0x0100 +#define POOL_NX_ALLOCATION 0x0200 + typedef enum _POOL_TYPE { NonPagedPool, PagedPool, @@ -1232,6 +1235,84 @@ 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)) + +#define GENERAL_LOOKASIDE_LAYOUT \ + 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]; + +typedef struct LOOKASIDE_ALIGN _GENERAL_LOOKASIDE +{ + GENERAL_LOOKASIDE_LAYOUT +} GENERAL_LOOKASIDE; + +typedef struct _GENERAL_LOOKASIDE_POOL +{ + GENERAL_LOOKASIDE_LAYOUT +} GENERAL_LOOKASIDE_POOL, *PGENERAL_LOOKASIDE_POOL; + +typedef struct _LOOKASIDE_LIST_EX +{ + GENERAL_LOOKASIDE_POOL L; +} LOOKASIDE_LIST_EX; + +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; @@ -1384,8 +1465,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); LIST_ENTRY * WINAPI ExInterlockedRemoveHeadList(LIST_ENTRY*,KSPIN_LOCK*); diff --git a/include/winnt.h b/include/winnt.h index 3a8295f1cac..2b489382303 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -757,6 +757,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)) #define CONTAINING_RECORD(address, type, field) \ ((type *)((PCHAR)(address) - offsetof(type, field)))