2005-03-13 18:41:59 +00:00
|
|
|
/*
|
2005-01-26 13:58:37 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
2005-01-07 06:54:27 +00:00
|
|
|
* PROJECT: ReactOS kernel
|
2005-03-13 18:41:59 +00:00
|
|
|
* FILE: ntoskrnl/ex/profile.c
|
|
|
|
* PURPOSE: Support for Executive Profile Objects
|
2005-05-09 01:38:29 +00:00
|
|
|
*
|
2005-03-13 18:41:59 +00:00
|
|
|
* PROGRAMMERS: Alex Ionescu
|
2005-01-07 06:54:27 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#include <internal/debug.h>
|
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* 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;
|
2005-01-07 06:54:27 +00:00
|
|
|
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
|
|
|
POBJECT_TYPE EXPORTED ExProfileObjectType = NULL;
|
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
static KMUTEX ExpProfileMutex;
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
#define PROFILE_CONTROL 1
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
static GENERIC_MAPPING ExpProfileMapping = {
|
|
|
|
STANDARD_RIGHTS_READ | PROFILE_CONTROL,
|
|
|
|
STANDARD_RIGHTS_WRITE | PROFILE_CONTROL,
|
|
|
|
STANDARD_RIGHTS_EXECUTE | PROFILE_CONTROL,
|
|
|
|
STANDARD_RIGHTS_ALL};
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2005-03-13 18:41:59 +00:00
|
|
|
STDCALL
|
|
|
|
ExpDeleteProfile(PVOID ObjectBody)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-03-13 18:41:59 +00:00
|
|
|
PEPROFILE Profile;
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Typecast the Object */
|
|
|
|
Profile = (PEPROFILE)ObjectBody;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Check if there if the Profile was started */
|
|
|
|
if (Profile->LockedBuffer) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Stop the Profile */
|
|
|
|
KeStopProfile(Profile->KeProfile);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Unmap the Locked Buffer */
|
|
|
|
MmUnmapLockedPages(Profile->LockedBuffer, Profile->Mdl);
|
|
|
|
MmUnlockPages(Profile->Mdl);
|
|
|
|
ExFreePool(Profile->Mdl);
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Check if a Process is associated */
|
|
|
|
if (Profile->Process != NULL) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Dereference it */
|
|
|
|
ObDereferenceObject(Profile->Process);
|
|
|
|
Profile->Process = NULL;
|
|
|
|
}
|
|
|
|
}
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2005-03-13 18:41:59 +00:00
|
|
|
INIT_FUNCTION
|
|
|
|
ExpInitializeProfileImplementation(VOID)
|
|
|
|
{
|
|
|
|
/* Initialize the Mutex to lock the States */
|
|
|
|
KeInitializeMutex(&ExpProfileMutex, 0x40);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Create the Object Type */
|
|
|
|
ExProfileObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
|
|
|
|
RtlInitUnicodeString(&ExProfileObjectType->TypeName, L"Profile");
|
|
|
|
ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F');
|
|
|
|
ExProfileObjectType->PeakObjects = 0;
|
|
|
|
ExProfileObjectType->PeakHandles = 0;
|
|
|
|
ExProfileObjectType->TotalObjects = 0;
|
|
|
|
ExProfileObjectType->TotalHandles = 0;
|
|
|
|
ExProfileObjectType->PagedPoolCharge = 0;
|
|
|
|
ExProfileObjectType->NonpagedPoolCharge = sizeof(EPROFILE);
|
|
|
|
ExProfileObjectType->Mapping = &ExpProfileMapping;
|
|
|
|
ExProfileObjectType->Dump = NULL;
|
|
|
|
ExProfileObjectType->Open = NULL;
|
|
|
|
ExProfileObjectType->Close = NULL;
|
|
|
|
ExProfileObjectType->Delete = ExpDeleteProfile;
|
|
|
|
ExProfileObjectType->Parse = NULL;
|
2005-05-15 04:56:52 +00:00
|
|
|
ExProfileObjectType->Open = NULL;
|
2005-03-13 18:41:59 +00:00
|
|
|
ExProfileObjectType->Security = NULL;
|
|
|
|
ExProfileObjectType->QueryName = NULL;
|
|
|
|
ExProfileObjectType->OkayToClose = NULL;
|
|
|
|
ObpCreateTypeObject(ExProfileObjectType);
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
|
|
|
STDCALL
|
2005-01-07 06:54:27 +00:00
|
|
|
NtCreateProfile(OUT PHANDLE ProfileHandle,
|
2005-03-13 18:41:59 +00:00
|
|
|
IN HANDLE Process OPTIONAL,
|
2005-05-09 01:38:29 +00:00
|
|
|
IN PVOID ImageBase,
|
|
|
|
IN ULONG ImageSize,
|
2005-03-13 18:41:59 +00:00
|
|
|
IN ULONG BucketSize,
|
|
|
|
IN PVOID Buffer,
|
|
|
|
IN ULONG BufferSize,
|
|
|
|
IN KPROFILE_SOURCE ProfileSource,
|
|
|
|
IN KAFFINITY Affinity)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-03-13 18:41:59 +00:00
|
|
|
HANDLE hProfile;
|
|
|
|
PEPROFILE Profile;
|
|
|
|
PEPROCESS pProcess;
|
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Easy way out */
|
|
|
|
if(BufferSize == 0) return STATUS_INVALID_PARAMETER_7;
|
|
|
|
|
|
|
|
/* Check the Parameters for validity */
|
|
|
|
if(PreviousMode != KernelMode) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
_SEH_TRY {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
ProbeForWrite(ProfileHandle,
|
|
|
|
sizeof(HANDLE),
|
|
|
|
sizeof(ULONG));
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
ProbeForWrite(Buffer,
|
|
|
|
BufferSize,
|
|
|
|
sizeof(ULONG));
|
2005-05-06 22:25:30 +00:00
|
|
|
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
} _SEH_END;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
if(!NT_SUCCESS(Status)) return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Check if a process was specified */
|
|
|
|
if (Process) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Reference it */
|
|
|
|
Status = ObReferenceObjectByHandle(Process,
|
|
|
|
PROCESS_QUERY_INFORMATION,
|
|
|
|
PsProcessType,
|
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)&pProcess,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) return(Status);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
} else {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* No process was specified, which means a System-Wide Profile */
|
|
|
|
pProcess = NULL;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* For this, we need to check the Privilege */
|
|
|
|
if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege, PreviousMode)) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
DPRINT1("NtCreateProfile: Caller requires the SeSystemProfilePrivilege privilege!\n");
|
|
|
|
return STATUS_PRIVILEGE_NOT_HELD;
|
|
|
|
}
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Create the object */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
Status = ObCreateObject(KernelMode,
|
|
|
|
ExProfileObjectType,
|
|
|
|
&ObjectAttributes,
|
|
|
|
PreviousMode,
|
|
|
|
NULL,
|
|
|
|
sizeof(EPROFILE),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(PVOID*)&Profile);
|
|
|
|
if (!NT_SUCCESS(Status)) return(Status);
|
|
|
|
|
|
|
|
/* Initialize it */
|
|
|
|
Profile->ImageBase = ImageBase;
|
|
|
|
Profile->ImageSize = ImageSize;
|
|
|
|
Profile->Buffer = Buffer;
|
|
|
|
Profile->BufferSize = BufferSize;
|
|
|
|
Profile->BucketSize = BucketSize;
|
|
|
|
Profile->LockedBuffer = NULL;
|
|
|
|
Profile->Affinity = Affinity;
|
|
|
|
Profile->Process = pProcess;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Insert into the Object Tree */
|
|
|
|
Status = ObInsertObject ((PVOID)Profile,
|
2005-01-22 13:34:27 +00:00
|
|
|
NULL,
|
2005-03-13 18:41:59 +00:00
|
|
|
PROFILE_CONTROL,
|
2005-01-22 13:34:27 +00:00
|
|
|
0,
|
|
|
|
NULL,
|
2005-03-13 18:41:59 +00:00
|
|
|
&hProfile);
|
|
|
|
ObDereferenceObject(Profile);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Check for Success */
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Dereference Process on failure */
|
|
|
|
if (pProcess) ObDereferenceObject(pProcess);
|
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Copy the created handle back to the caller*/
|
|
|
|
_SEH_TRY {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
*ProfileHandle = hProfile;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-05-06 22:25:30 +00:00
|
|
|
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
} _SEH_END;
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Return Status */
|
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
2005-03-13 18:41:59 +00:00
|
|
|
STDCALL
|
|
|
|
NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter,
|
|
|
|
OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-03-13 18:41:59 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
|
|
|
LARGE_INTEGER PerfFrequency;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Check the Parameters for validity */
|
|
|
|
if(PreviousMode != KernelMode) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
_SEH_TRY {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
ProbeForWrite(PerformanceCounter,
|
|
|
|
sizeof(LARGE_INTEGER),
|
|
|
|
sizeof(ULONG));
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
ProbeForWrite(PerformanceFrequency,
|
|
|
|
sizeof(LARGE_INTEGER),
|
|
|
|
sizeof(ULONG));
|
2005-05-06 22:25:30 +00:00
|
|
|
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
} _SEH_END;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
if(!NT_SUCCESS(Status)) return Status;
|
2005-01-22 13:34:27 +00:00
|
|
|
}
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
_SEH_TRY {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Query the Kernel */
|
|
|
|
*PerformanceCounter = KeQueryPerformanceCounter(&PerfFrequency);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Return Frequency if requested */
|
|
|
|
if(PerformanceFrequency) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
*PerformanceFrequency = PerfFrequency;
|
|
|
|
}
|
2005-05-06 22:25:30 +00:00
|
|
|
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-01-22 13:34:27 +00:00
|
|
|
Status = _SEH_GetExceptionCode();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
} _SEH_END;
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
|
|
|
STDCALL
|
2005-01-07 06:54:27 +00:00
|
|
|
NtStartProfile(IN HANDLE ProfileHandle)
|
|
|
|
{
|
2005-03-13 18:41:59 +00:00
|
|
|
PEPROFILE Profile;
|
|
|
|
PKPROFILE KeProfile;
|
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
|
|
|
PVOID TempLockedBuffer;
|
|
|
|
NTSTATUS Status;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Get the Object */
|
|
|
|
Status = ObReferenceObjectByHandle(ProfileHandle,
|
|
|
|
PROFILE_CONTROL,
|
|
|
|
ExProfileObjectType,
|
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)&Profile,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) return(Status);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* To avoid a Race, wait on the Mutex */
|
2005-05-09 01:38:29 +00:00
|
|
|
KeWaitForSingleObject(&ExpProfileMutex,
|
2005-03-13 18:41:59 +00:00
|
|
|
Executive,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* The Profile can still be enabled though, so handle that */
|
|
|
|
if (Profile->LockedBuffer) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Release our lock, dereference and return */
|
|
|
|
KeReleaseMutex(&ExpProfileMutex, FALSE);
|
|
|
|
ObDereferenceObject(Profile);
|
|
|
|
return STATUS_PROFILING_NOT_STOPPED;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Allocate a Kernel Profile Object. */
|
2005-05-09 01:38:29 +00:00
|
|
|
KeProfile = ExAllocatePoolWithTag(NonPagedPool,
|
2005-03-13 18:41:59 +00:00
|
|
|
sizeof(EPROFILE),
|
|
|
|
TAG('P', 'r', 'o', 'f'));
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Allocate the Mdl Structure */
|
|
|
|
Profile->Mdl = MmCreateMdl(NULL, Profile->Buffer, Profile->BufferSize);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Probe and Lock for Write Access */
|
|
|
|
MmProbeAndLockPages(Profile->Mdl, PreviousMode, IoWriteAccess);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Map the pages */
|
|
|
|
TempLockedBuffer = MmMapLockedPages(Profile->Mdl, KernelMode);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Initialize the Kernel Profile Object */
|
|
|
|
Profile->KeProfile = KeProfile;
|
|
|
|
KeInitializeProfile(KeProfile,
|
|
|
|
(PKPROCESS)Profile->Process,
|
|
|
|
Profile->ImageBase,
|
|
|
|
Profile->ImageSize,
|
|
|
|
Profile->BucketSize,
|
|
|
|
Profile->ProfileSource,
|
|
|
|
Profile->Affinity);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Start the Profiling */
|
|
|
|
KeStartProfile(KeProfile, TempLockedBuffer);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Now it's safe to save this */
|
|
|
|
Profile->LockedBuffer = TempLockedBuffer;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Release mutex, dereference and return */
|
|
|
|
KeReleaseMutex(&ExpProfileMutex, FALSE);
|
|
|
|
ObDereferenceObject(Profile);
|
|
|
|
return STATUS_SUCCESS;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
NTSTATUS
|
2005-05-09 01:38:29 +00:00
|
|
|
STDCALL
|
2005-01-07 06:54:27 +00:00
|
|
|
NtStopProfile(IN HANDLE ProfileHandle)
|
|
|
|
{
|
2005-03-13 18:41:59 +00:00
|
|
|
PEPROFILE Profile;
|
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
|
|
|
NTSTATUS Status;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Get the Object */
|
|
|
|
Status = ObReferenceObjectByHandle(ProfileHandle,
|
|
|
|
PROFILE_CONTROL,
|
|
|
|
ExProfileObjectType,
|
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)&Profile,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) return(Status);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Get the Mutex */
|
2005-05-09 01:38:29 +00:00
|
|
|
KeWaitForSingleObject(&ExpProfileMutex,
|
2005-03-13 18:41:59 +00:00
|
|
|
Executive,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Make sure the Profile Object is really Started */
|
|
|
|
if (!Profile->LockedBuffer) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
Status = STATUS_PROFILING_NOT_STARTED;
|
|
|
|
goto Exit;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Stop the Profile */
|
|
|
|
KeStopProfile(Profile->KeProfile);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Unlock the Buffer */
|
|
|
|
MmUnmapLockedPages(Profile->LockedBuffer, Profile->Mdl);
|
|
|
|
MmUnlockPages(Profile->Mdl);
|
|
|
|
ExFreePool(Profile->KeProfile);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Clear the Locked Buffer pointer, meaning the Object is Stopped */
|
|
|
|
Profile->LockedBuffer = NULL;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
Exit:
|
|
|
|
/* Release Mutex, Dereference and Return */
|
|
|
|
KeReleaseMutex(&ExpProfileMutex, FALSE);
|
|
|
|
ObDereferenceObject(Profile);
|
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
|
|
|
STDCALL
|
2005-03-13 18:41:59 +00:00
|
|
|
NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource,
|
|
|
|
OUT PULONG Interval)
|
|
|
|
{
|
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
|
|
|
ULONG ReturnInterval;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Check the Parameters for validity */
|
|
|
|
if(PreviousMode != KernelMode) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
_SEH_TRY {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
ProbeForWrite(Interval,
|
|
|
|
sizeof(ULONG),
|
|
|
|
sizeof(ULONG));
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-05-06 22:25:30 +00:00
|
|
|
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
} _SEH_END;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
if(!NT_SUCCESS(Status)) return Status;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Query the Interval */
|
|
|
|
ReturnInterval = KeQueryIntervalProfile(ProfileSource);
|
|
|
|
|
|
|
|
/* Return the data */
|
|
|
|
_SEH_TRY {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
*Interval = ReturnInterval;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-05-06 22:25:30 +00:00
|
|
|
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
Status = _SEH_GetExceptionCode();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
} _SEH_END;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
|
|
/* Return Success */
|
2005-03-13 18:41:59 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
|
|
|
STDCALL
|
2005-03-13 18:41:59 +00:00
|
|
|
NtSetIntervalProfile(IN ULONG Interval,
|
|
|
|
IN KPROFILE_SOURCE Source)
|
|
|
|
{
|
|
|
|
/* Let the Kernel do the job */
|
|
|
|
KeSetIntervalProfile(Interval, Source);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-13 18:41:59 +00:00
|
|
|
/* Nothing can go wrong */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|