[NTOSKRNL]

Implement SystemLookasideInformation case in NtQuerySystemInformation

svn path=/trunk/; revision=62208
This commit is contained in:
Timo Kreuzer 2014-02-16 09:27:01 +00:00
parent c01564fe18
commit 441874c1c3
2 changed files with 202 additions and 3 deletions

View file

@ -180,6 +180,62 @@ ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
return Status; return Status;
} }
VOID
NTAPI
ExUnlockUserBuffer(PMDL Mdl)
{
MmUnlockPages(Mdl);
ExFreePoolWithTag(Mdl, TAG_MDL);
}
NTSTATUS
NTAPI
ExLockUserBuffer(
PVOID BaseAddress,
ULONG Length,
KPROCESSOR_MODE AccessMode,
LOCK_OPERATION Operation,
PVOID *MappedSystemVa,
PMDL *OutMdl)
{
PMDL Mdl;
PAGED_CODE();
*MappedSystemVa = NULL;
*OutMdl = NULL;
/* Allocate an MDL for the buffer */
Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, TRUE, NULL);
if (Mdl == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Enter SEH for probing */
_SEH2_TRY
{
MmProbeAndLockPages(Mdl, AccessMode, Operation);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ExFreePoolWithTag(Mdl, TAG_MDL);
return _SEH2_GetExceptionCode();
}
_SEH2_END;
/* Return the safe kernel mode buffer */
*MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
if (*MappedSystemVa == NULL)
{
ExUnlockUserBuffer(Mdl);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Return the MDL */
*OutMdl = Mdl;
return STATUS_SUCCESS;
}
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
/* /*
@ -1799,13 +1855,151 @@ SSI_DEF(SystemCurrentTimeZoneInformation)
return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer); return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
} }
static
VOID
ExpCopyLookasideInformation(
PSYSTEM_LOOKASIDE_INFORMATION *InfoPointer,
PULONG RemainingPointer,
PLIST_ENTRY ListHead,
BOOLEAN ListUsesMisses)
{
PSYSTEM_LOOKASIDE_INFORMATION Info;
PGENERAL_LOOKASIDE LookasideList;
PLIST_ENTRY ListEntry;
ULONG Remaining;
/* Get info pointer and remaining count of free array element */
Info = *InfoPointer;
Remaining = *RemainingPointer;
/* Loop as long as we have lookaside lists and free array elements */
for (ListEntry = ListHead->Flink;
(ListEntry != ListHead) && (Remaining > 0);
ListEntry = ListEntry->Flink, Remaining--)
{
LookasideList = CONTAINING_RECORD(ListEntry, GENERAL_LOOKASIDE, ListEntry);
/* Fill the next array element */
Info->CurrentDepth = LookasideList->Depth;
Info->MaximumDepth = LookasideList->MaximumDepth;
Info->TotalAllocates = LookasideList->TotalAllocates;
Info->TotalFrees = LookasideList->TotalFrees;
Info->Type = LookasideList->Type;
Info->Tag = LookasideList->Tag;
Info->Size = LookasideList->Size;
/* Check how the lists track misses/hits */
if (ListUsesMisses)
{
/* Copy misses */
Info->AllocateMisses = LookasideList->AllocateMisses;
Info->FreeMisses = LookasideList->FreeMisses;
}
else
{
/* Calculate misses */
Info->AllocateMisses = LookasideList->TotalAllocates
- LookasideList->AllocateHits;
Info->FreeMisses = LookasideList->TotalFrees
- LookasideList->FreeHits;
}
}
/* Return the updated pointer and remaining count */
*InfoPointer = Info;
*RemainingPointer = Remaining;
}
/* Class 45 - Lookaside Information */ /* Class 45 - Lookaside Information */
QSI_DEF(SystemLookasideInformation) QSI_DEF(SystemLookasideInformation)
{ {
/* FIXME */ KPROCESSOR_MODE PreviousMode;
DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n"); PSYSTEM_LOOKASIDE_INFORMATION Info;
return STATUS_NOT_IMPLEMENTED; PMDL Mdl;
ULONG MaxCount, Remaining;
KIRQL OldIrql;
NTSTATUS Status;
/* First we need to lock down the memory, since we are going to access it
at high IRQL */
PreviousMode = ExGetPreviousMode();
Status = ExLockUserBuffer(Buffer,
Size,
PreviousMode,
IoWriteAccess,
(PVOID*)&Info,
&Mdl);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
return Status;
}
/* Calculate how many items we can store */
Remaining = MaxCount = Size / sizeof(SYSTEM_LOOKASIDE_INFORMATION);
if (Remaining == 0)
{
goto Leave;
}
/* Copy info from pool lookaside lists */
ExpCopyLookasideInformation(&Info,
&Remaining,
&ExPoolLookasideListHead,
FALSE);
if (Remaining == 0)
{
goto Leave;
}
/* Copy info from system lookaside lists */
ExpCopyLookasideInformation(&Info,
&Remaining,
&ExSystemLookasideListHead,
TRUE);
if (Remaining == 0)
{
goto Leave;
}
/* Acquire spinlock for ExpNonPagedLookasideListHead */
OldIrql = KfAcquireSpinLock(&ExpNonPagedLookasideListLock);
/* Copy info from non-paged lookaside lists */
ExpCopyLookasideInformation(&Info,
&Remaining,
&ExpNonPagedLookasideListHead,
TRUE);
/* Release spinlock for ExpNonPagedLookasideListHead */
KfReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
if (Remaining == 0)
{
goto Leave;
}
/* Acquire spinlock for ExpPagedLookasideListHead */
OldIrql = KfAcquireSpinLock(&ExpPagedLookasideListLock);
/* Copy info from paged lookaside lists */
ExpCopyLookasideInformation(&Info,
&Remaining,
&ExpPagedLookasideListHead,
TRUE);
/* Release spinlock for ExpPagedLookasideListHead */
KfReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
Leave:
/* Release the locked user buffer */
ExUnlockUserBuffer(Mdl);
/* Return the size of the actually written data */
*ReqSize = (MaxCount - Remaining) * sizeof(SYSTEM_LOOKASIDE_INFORMATION);
return STATUS_SUCCESS;
} }

View file

@ -27,6 +27,11 @@ extern ULONG ExpInitializationPhase;
extern ULONG ExpAltTimeZoneBias; extern ULONG ExpAltTimeZoneBias;
extern LIST_ENTRY ExSystemLookasideListHead; extern LIST_ENTRY ExSystemLookasideListHead;
extern PCALLBACK_OBJECT PowerStateCallback; extern PCALLBACK_OBJECT PowerStateCallback;
extern LIST_ENTRY ExPoolLookasideListHead;
extern LIST_ENTRY ExpNonPagedLookasideListHead;
extern LIST_ENTRY ExpPagedLookasideListHead;
extern KSPIN_LOCK ExpNonPagedLookasideListLock;
extern KSPIN_LOCK ExpPagedLookasideListLock;
typedef struct _EXHANDLE typedef struct _EXHANDLE
{ {