mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 19:26:32 +00:00
Move some profile stuff to NDK and fix some bugs in the executive implementation, as well as support segmented profile objects
svn path=/trunk/; revision=20426
This commit is contained in:
@@ -55,44 +55,56 @@ extern ULONG NTSYSAPI NtBuildNumber;
|
||||
//
|
||||
// Invalid Handle Value Constant
|
||||
//
|
||||
#define INVALID_HANDLE_VALUE (HANDLE)-1
|
||||
#define INVALID_HANDLE_VALUE (HANDLE)-1
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Increments
|
||||
//
|
||||
#define MUTANT_INCREMENT 1
|
||||
#define MUTANT_INCREMENT 1
|
||||
|
||||
//
|
||||
// Callback Object Access Mask
|
||||
//
|
||||
#define CALLBACK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x0001)
|
||||
#define CALLBACK_EXECUTE (STANDARD_RIGHTS_EXECUTE|SYNCHRONIZE|0x0001)
|
||||
#define CALLBACK_WRITE (STANDARD_RIGHTS_WRITE|SYNCHRONIZE|0x0001)
|
||||
#define CALLBACK_READ (STANDARD_RIGHTS_READ|SYNCHRONIZE|0x0001)
|
||||
#define CALLBACK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x0001)
|
||||
#define CALLBACK_EXECUTE (STANDARD_RIGHTS_EXECUTE|SYNCHRONIZE|0x0001)
|
||||
#define CALLBACK_WRITE (STANDARD_RIGHTS_WRITE|SYNCHRONIZE|0x0001)
|
||||
#define CALLBACK_READ (STANDARD_RIGHTS_READ|SYNCHRONIZE|0x0001)
|
||||
|
||||
//
|
||||
// Event Object Access Masks
|
||||
//
|
||||
#ifdef NTOS_MODE_USER
|
||||
#define EVENT_QUERY_STATE 0x0001
|
||||
#define EVENT_QUERY_STATE 0x0001
|
||||
|
||||
//
|
||||
// Semaphore Object Acess Masks
|
||||
//
|
||||
#define SEMAPHORE_QUERY_STATE 0x0001
|
||||
#define SEMAPHORE_QUERY_STATE 0x0001
|
||||
#endif
|
||||
|
||||
//
|
||||
// Event Pair Access Masks
|
||||
//
|
||||
#define EVENT_PAIR_ALL_ACCESS 0x1F0000L
|
||||
#define EVENT_PAIR_ALL_ACCESS 0x1F0000L
|
||||
|
||||
//
|
||||
// Profile Object Access Masks
|
||||
//
|
||||
#define PROFILE_CONTROL 0x0001
|
||||
#define PROFILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | PROFILE_CONTROL)
|
||||
|
||||
//
|
||||
// Maximum Parameters for NtRaiseHardError
|
||||
//
|
||||
#define MAXIMUM_HARDERROR_PARAMETERS 4
|
||||
#define MAXIMUM_HARDERROR_PARAMETERS 4
|
||||
|
||||
//
|
||||
// Pushlock Wait Block Flags
|
||||
//
|
||||
#define EX_PUSH_LOCK_FLAGS_EXCLUSIVE 1
|
||||
#define EX_PUSH_LOCK_FLAGS_WAIT 2
|
||||
|
||||
//
|
||||
// Shutdown types for NtShutdownSystem
|
||||
@@ -271,7 +283,20 @@ typedef struct _EX_FAST_REF
|
||||
} EX_FAST_REF, *PEX_FAST_REF;
|
||||
|
||||
//
|
||||
// Executive Fast Reference Wait Block
|
||||
// Executive Cache-Aware Rundown Reference Descriptor
|
||||
//
|
||||
typedef struct _EX_RUNDOWN_REF_CACHE_AWARE
|
||||
{
|
||||
union
|
||||
{
|
||||
ULONG_PTR Count;
|
||||
PVOID Ptr;
|
||||
};
|
||||
PVOID PoolToFree;
|
||||
} EX_RUNDOWN_REF_CACHE_AWARE, *PEX_RUNDOWN_REF_CACHE_AWARE;
|
||||
|
||||
//
|
||||
// Executive Rundown Wait Block
|
||||
//
|
||||
typedef struct _EX_RUNDOWN_WAIT_BLOCK
|
||||
{
|
||||
@@ -279,6 +304,32 @@ typedef struct _EX_RUNDOWN_WAIT_BLOCK
|
||||
KEVENT RundownEvent;
|
||||
} EX_RUNDOWN_WAIT_BLOCK, *PEX_RUNDOWN_WAIT_BLOCK;
|
||||
|
||||
//
|
||||
// Executive Pushlock Wait Block
|
||||
//
|
||||
#ifndef __GNUC__ // WARNING! PUSHLOCKS WILL NOT WORK IN GCC FOR NOW!!!
|
||||
__declspec(align(16))
|
||||
#endif
|
||||
typedef struct _EX_PUSH_LOCK_WAIT_BLOCK
|
||||
{
|
||||
union
|
||||
{
|
||||
KGATE WakeGate;
|
||||
KEVENT WakeEvent;
|
||||
};
|
||||
struct _EX_PUSH_LOCK_WAIT_BLOCK *Next;
|
||||
struct _EX_PUSH_LOCK_WAIT_BLOCK *Last;
|
||||
struct _EX_PUSH_LOCK_WAIT_BLOCK *Previous;
|
||||
LONG ShareCount;
|
||||
LONG Flags;
|
||||
#if DBG
|
||||
BOOL Signaled;
|
||||
EX_PUSH_LOCK NewValue;
|
||||
EX_PUSH_LOCK OldValue;
|
||||
PEX_PUSH_LOCK PushLock;
|
||||
#endif
|
||||
} EX_PUSH_LOCK_WAIT_BLOCK, *PEX_PUSH_LOCK_WAIT_BLOCK;
|
||||
|
||||
//
|
||||
// Callback Object
|
||||
//
|
||||
@@ -290,6 +341,25 @@ typedef struct _CALLBACK_OBJECT
|
||||
ULONG AllowMultipleCallbacks;
|
||||
} CALLBACK_OBJECT , *PCALLBACK_OBJECT;
|
||||
|
||||
//
|
||||
// Profile OBject
|
||||
//
|
||||
typedef struct _EPROFILE
|
||||
{
|
||||
PEPROCESS Process;
|
||||
PVOID ImageBase;
|
||||
SIZE_T ImageSize;
|
||||
PVOID Buffer;
|
||||
ULONG BufferSize;
|
||||
ULONG BucketSize;
|
||||
PKPROFILE KeProfile;
|
||||
PVOID LockedBuffer;
|
||||
PMDL Mdl;
|
||||
ULONG Segment;
|
||||
KPROFILE_SOURCE ProfileSource;
|
||||
KAFFINITY Affinity;
|
||||
} EPROFILE, *PEPROFILE;
|
||||
|
||||
//
|
||||
// Handle Table Structures
|
||||
//
|
||||
|
||||
+164
-118
@@ -1,65 +1,55 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PROJECT: ReactOS Kernel
|
||||
* FILE: ntoskrnl/ex/profile.c
|
||||
* PURPOSE: Support for Executive Profile Objects
|
||||
*
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
* PROGRAMMERS: Alex Ionescu ([email protected])
|
||||
* Thomas Weidenmueller
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#if defined (ALLOC_PRAGMA)
|
||||
#pragma alloc_text(INIT, ExpInitializeProfileImplementation)
|
||||
#endif
|
||||
|
||||
/* FIXME: NDK This structure is a *GUESS* -- Alex */
|
||||
typedef struct _EPROFILE {
|
||||
PEPROCESS Process;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize;
|
||||
ULONG BucketSize;
|
||||
PVOID Buffer;
|
||||
ULONG BufferSize;
|
||||
PKPROFILE KeProfile;
|
||||
KPROFILE_SOURCE ProfileSource;
|
||||
KAFFINITY Affinity;
|
||||
PMDL Mdl;
|
||||
PVOID LockedBuffer;
|
||||
} EPROFILE, *PEPROFILE;
|
||||
#define TAG_PROFILE TAG('P', 'r', 'o', 'f')
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
POBJECT_TYPE ExProfileObjectType = NULL;
|
||||
KMUTEX ExpProfileMutex;
|
||||
|
||||
static KMUTEX ExpProfileMutex;
|
||||
|
||||
#define PROFILE_CONTROL 1
|
||||
|
||||
static GENERIC_MAPPING ExpProfileMapping = {
|
||||
GENERIC_MAPPING ExpProfileMapping =
|
||||
{
|
||||
STANDARD_RIGHTS_READ | PROFILE_CONTROL,
|
||||
STANDARD_RIGHTS_WRITE | PROFILE_CONTROL,
|
||||
STANDARD_RIGHTS_EXECUTE | PROFILE_CONTROL,
|
||||
STANDARD_RIGHTS_ALL};
|
||||
PROFILE_ALL_ACCESS
|
||||
};
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
NTAPI
|
||||
ExpDeleteProfile(PVOID ObjectBody)
|
||||
{
|
||||
PEPROFILE Profile;
|
||||
ULONG State;
|
||||
|
||||
/* Typecast the Object */
|
||||
Profile = (PEPROFILE)ObjectBody;
|
||||
|
||||
/* Check if there if the Profile was started */
|
||||
if (Profile->LockedBuffer) {
|
||||
|
||||
if (Profile->LockedBuffer)
|
||||
{
|
||||
/* Stop the Profile */
|
||||
KeStopProfile(Profile->KeProfile);
|
||||
State = KeStopProfile(Profile->KeProfile);
|
||||
ASSERT(State != FALSE);
|
||||
|
||||
/* Unmap the Locked Buffer */
|
||||
MmUnmapLockedPages(Profile->LockedBuffer, Profile->Mdl);
|
||||
@@ -67,28 +57,22 @@ ExpDeleteProfile(PVOID ObjectBody)
|
||||
ExFreePool(Profile->Mdl);
|
||||
}
|
||||
|
||||
/* Check if a Process is associated */
|
||||
if (Profile->Process != NULL) {
|
||||
|
||||
/* Dereference it */
|
||||
ObDereferenceObject(Profile->Process);
|
||||
Profile->Process = NULL;
|
||||
}
|
||||
/* Check if a Process is associated and reference it */
|
||||
if (Profile->Process) ObDereferenceObject(Profile->Process);
|
||||
}
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
STDCALL
|
||||
NTAPI
|
||||
ExpInitializeProfileImplementation(VOID)
|
||||
{
|
||||
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
||||
UNICODE_STRING Name;
|
||||
|
||||
/* Initialize the Mutex to lock the States */
|
||||
KeInitializeMutex(&ExpProfileMutex, 0x40);
|
||||
|
||||
DPRINT("Creating Profile Object Type\n");
|
||||
|
||||
|
||||
/* Initialize the Mutex to lock the States */
|
||||
KeInitializeMutex(&ExpProfileMutex, 64);
|
||||
|
||||
/* Create the Event Pair Object Type */
|
||||
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
||||
RtlInitUnicodeString(&Name, L"Profile");
|
||||
@@ -97,12 +81,12 @@ ExpInitializeProfileImplementation(VOID)
|
||||
ObjectTypeInitializer.GenericMapping = ExpProfileMapping;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.DeleteProcedure = ExpDeleteProfile;
|
||||
ObjectTypeInitializer.ValidAccessMask = STANDARD_RIGHTS_ALL;
|
||||
ObjectTypeInitializer.ValidAccessMask = PROFILE_ALL_ACCESS;
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExProfileObjectType);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NTAPI
|
||||
NtCreateProfile(OUT PHANDLE ProfileHandle,
|
||||
IN HANDLE Process OPTIONAL,
|
||||
IN PVOID ImageBase,
|
||||
@@ -119,33 +103,79 @@ NtCreateProfile(OUT PHANDLE ProfileHandle,
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
ULONG Segment = 0, Log2 = 0;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Easy way out */
|
||||
if(BufferSize == 0) return STATUS_INVALID_PARAMETER_7;
|
||||
if(!BufferSize) return STATUS_INVALID_PARAMETER_7;
|
||||
|
||||
/* Check the Parameters for validity */
|
||||
if(PreviousMode != KernelMode) {
|
||||
/* Check if this is a low-memory profile */
|
||||
if ((!BucketSize) && (ImageBase < (PVOID)(0x10000)))
|
||||
{
|
||||
/* Validate size */
|
||||
if (BufferSize < sizeof(ULONG)) return STATUS_INVALID_PARAMETER_7;
|
||||
|
||||
_SEH_TRY {
|
||||
/* This will become a segmented profile object */
|
||||
Segment = (ULONG)ImageBase;
|
||||
ImageBase = 0;
|
||||
|
||||
/* Recalculate the bucket size */
|
||||
BucketSize = ImageSize / (BufferSize / sizeof(ULONG));
|
||||
|
||||
/* Convert it to log2 */
|
||||
BucketSize--;
|
||||
while (BucketSize >>= 1) Log2++;
|
||||
BucketSize += Log2 + 1;
|
||||
}
|
||||
|
||||
/* Validate bucket size */
|
||||
if ((BucketSize > 31) || (BucketSize < 2))
|
||||
{
|
||||
DPRINT1("Bucket size invalid\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Make sure that the buckets can map the range */
|
||||
if ((ImageSize >> (BucketSize - 2)) > BufferSize)
|
||||
{
|
||||
DPRINT1("Bucket size too small\n");
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Make sure that the range isn't too gigantic */
|
||||
if (((ULONG_PTR)ImageBase + ImageSize) < ImageSize)
|
||||
{
|
||||
DPRINT1("Range too big\n");
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Check if we were called from user-mode */
|
||||
if(PreviousMode != KernelMode)
|
||||
{
|
||||
/* Entry SEH */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Make sure that the handle pointer is valid */
|
||||
ProbeForWriteHandle(ProfileHandle);
|
||||
|
||||
/* Check if the buffer is valid */
|
||||
ProbeForWrite(Buffer,
|
||||
BufferSize,
|
||||
sizeof(ULONG));
|
||||
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
||||
|
||||
}
|
||||
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
} _SEH_END;
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* Bail out if we failed */
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Check if a process was specified */
|
||||
if (Process) {
|
||||
|
||||
if (Process)
|
||||
{
|
||||
/* Reference it */
|
||||
Status = ObReferenceObjectByHandle(Process,
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
@@ -154,15 +184,18 @@ NtCreateProfile(OUT PHANDLE ProfileHandle,
|
||||
(PVOID*)&pProcess,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return(Status);
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Segmented profile objects cannot be used system-wide */
|
||||
if (Segment) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* No process was specified, which means a System-Wide Profile */
|
||||
pProcess = NULL;
|
||||
|
||||
/* For this, we need to check the Privilege */
|
||||
if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege, PreviousMode)) {
|
||||
|
||||
if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege, PreviousMode))
|
||||
{
|
||||
DPRINT1("NtCreateProfile: Caller requires the SeSystemProfilePrivilege privilege!\n");
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
@@ -181,7 +214,7 @@ NtCreateProfile(OUT PHANDLE ProfileHandle,
|
||||
NULL,
|
||||
sizeof(EPROFILE),
|
||||
0,
|
||||
0,
|
||||
sizeof(EPROFILE) + sizeof(KPROFILE),
|
||||
(PVOID*)&Profile);
|
||||
if (!NT_SUCCESS(Status)) return(Status);
|
||||
|
||||
@@ -192,6 +225,8 @@ NtCreateProfile(OUT PHANDLE ProfileHandle,
|
||||
Profile->BufferSize = BufferSize;
|
||||
Profile->BucketSize = BucketSize;
|
||||
Profile->LockedBuffer = NULL;
|
||||
Profile->Segment = Segment;
|
||||
Profile->ProfileSource = ProfileSource;
|
||||
Profile->Affinity = Affinity;
|
||||
Profile->Process = pProcess;
|
||||
|
||||
@@ -205,29 +240,31 @@ NtCreateProfile(OUT PHANDLE ProfileHandle,
|
||||
ObDereferenceObject(Profile);
|
||||
|
||||
/* Check for Success */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Dereference Process on failure */
|
||||
if (pProcess) ObDereferenceObject(pProcess);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Copy the created handle back to the caller*/
|
||||
_SEH_TRY {
|
||||
|
||||
/* Enter SEH */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Copy the created handle back to the caller*/
|
||||
*ProfileHandle = hProfile;
|
||||
|
||||
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
||||
|
||||
}
|
||||
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
} _SEH_END;
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NTAPI
|
||||
NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter,
|
||||
OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
|
||||
{
|
||||
@@ -235,43 +272,50 @@ NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter,
|
||||
LARGE_INTEGER PerfFrequency;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
/* Check the Parameters for validity */
|
||||
if(PreviousMode != KernelMode) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
/* Check if we were called from user-mode */
|
||||
if(PreviousMode != KernelMode)
|
||||
{
|
||||
/* Entry SEH Block */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Make sure the counter and frequency are valid */
|
||||
ProbeForWriteLargeInteger(PerformanceCounter);
|
||||
|
||||
ProbeForWriteLargeInteger(PerformanceFrequency);
|
||||
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
||||
|
||||
if (PerformanceFrequency)
|
||||
{
|
||||
ProbeForWriteLargeInteger(PerformanceFrequency);
|
||||
}
|
||||
}
|
||||
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
} _SEH_END;
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* If the pointers are invalid, bail out */
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
/* Enter a new SEH Block */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Query the Kernel */
|
||||
*PerformanceCounter = KeQueryPerformanceCounter(&PerfFrequency);
|
||||
|
||||
/* Return Frequency if requested */
|
||||
if(PerformanceFrequency) {
|
||||
|
||||
*PerformanceFrequency = PerfFrequency;
|
||||
}
|
||||
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
||||
|
||||
if(PerformanceFrequency) *PerformanceFrequency = PerfFrequency;
|
||||
}
|
||||
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
} _SEH_END;
|
||||
|
||||
/* Return status to caller */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NTAPI
|
||||
NtStartProfile(IN HANDLE ProfileHandle)
|
||||
{
|
||||
PEPROFILE Profile;
|
||||
@@ -279,7 +323,6 @@ NtStartProfile(IN HANDLE ProfileHandle)
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
PVOID TempLockedBuffer;
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get the Object */
|
||||
@@ -299,8 +342,8 @@ NtStartProfile(IN HANDLE ProfileHandle)
|
||||
NULL);
|
||||
|
||||
/* The Profile can still be enabled though, so handle that */
|
||||
if (Profile->LockedBuffer) {
|
||||
|
||||
if (Profile->LockedBuffer)
|
||||
{
|
||||
/* Release our lock, dereference and return */
|
||||
KeReleaseMutex(&ExpProfileMutex, FALSE);
|
||||
ObDereferenceObject(Profile);
|
||||
@@ -310,7 +353,7 @@ NtStartProfile(IN HANDLE ProfileHandle)
|
||||
/* Allocate a Kernel Profile Object. */
|
||||
KeProfile = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(EPROFILE),
|
||||
TAG('P', 'r', 'o', 'f'));
|
||||
TAG_PROFILE);
|
||||
|
||||
/* Allocate the Mdl Structure */
|
||||
Profile->Mdl = MmCreateMdl(NULL, Profile->Buffer, Profile->BufferSize);
|
||||
@@ -344,13 +387,12 @@ NtStartProfile(IN HANDLE ProfileHandle)
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NTAPI
|
||||
NtStopProfile(IN HANDLE ProfileHandle)
|
||||
{
|
||||
PEPROFILE Profile;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get the Object */
|
||||
@@ -370,8 +412,8 @@ NtStopProfile(IN HANDLE ProfileHandle)
|
||||
NULL);
|
||||
|
||||
/* Make sure the Profile Object is really Started */
|
||||
if (!Profile->LockedBuffer) {
|
||||
|
||||
if (!Profile->LockedBuffer)
|
||||
{
|
||||
Status = STATUS_PROFILING_NOT_STARTED;
|
||||
goto Exit;
|
||||
}
|
||||
@@ -395,51 +437,55 @@ Exit:
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource,
|
||||
NTAPI
|
||||
NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource,
|
||||
OUT PULONG Interval)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
ULONG ReturnInterval;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Check the Parameters for validity */
|
||||
if(PreviousMode != KernelMode) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
/* Check if we were called from user-mode */
|
||||
if(PreviousMode != KernelMode)
|
||||
{
|
||||
/* Enter SEH Block */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Validate interval */
|
||||
ProbeForWriteUlong(Interval);
|
||||
|
||||
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
||||
|
||||
}
|
||||
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
} _SEH_END;
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* If pointer was invalid, bail out */
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Query the Interval */
|
||||
ReturnInterval = KeQueryIntervalProfile(ProfileSource);
|
||||
|
||||
/* Return the data */
|
||||
_SEH_TRY {
|
||||
|
||||
/* Enter SEH block for return */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Return the data */
|
||||
*Interval = ReturnInterval;
|
||||
|
||||
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
||||
|
||||
}
|
||||
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* Return Success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NTAPI
|
||||
NtSetIntervalProfile(IN ULONG Interval,
|
||||
IN KPROFILE_SOURCE Source)
|
||||
{
|
||||
|
||||
@@ -188,7 +188,7 @@ KeStartProfile(
|
||||
PVOID Buffer
|
||||
);
|
||||
|
||||
VOID
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeStopProfile(struct _KPROFILE* Profile);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user