* include/ddk/zw.h: Corrected declarations of NtCreateProfile,

NtQueryIntervalProfile, NtSetIntervalProfile.
* include/ddk/zwtypes.h: Added definitions of KPROFILE_SOURCE.
* ntoskrnl/include/internal/ke.h: Added the interrupted EIP as a
parameter to KiUpdateSystemTime for profiling purposes.
* ntoskrnl/include/internal/nt: Added declaration for profiling
support initialization.
* ntoskrnl/ke/timer.c (KiUpdateSystemTime, KeExpireTimers): Call
the profiling code on a timer interrupt with the interrupt EIP.
* ntoskrnl/ke/i386/irq.c (KiDispatchInterrupt): Pass the
interrupted EIP to KiUpdateSystemTime.
* ntoskrnl/mm/virtual.c (NtReadVirtualMemory, NtWriteVirtualMemory):
Release the MDLs used properly.
* ntoskrnl/nt/nt.c: Call the profiling support initialization.
* ntoskrnl/nt/ntevent.c (NtCreateEvent): Don't try copying the
ObjectAttributes parameter if it is NULL.
* ntoskrnl/nt/profile.c: Implemented profiling.

svn path=/trunk/; revision=1701
This commit is contained in:
David Welch 2001-03-16 16:05:34 +00:00
parent 18f3b6c58b
commit 18015b2244
12 changed files with 594 additions and 57 deletions

View file

@ -1,3 +1,23 @@
2001-03-16 David Welch <welch@cwcom.net>
* include/ddk/zw.h: Corrected declarations of NtCreateProfile,
NtQueryIntervalProfile, NtSetIntervalProfile.
* include/ddk/zwtypes.h: Added definitions of KPROFILE_SOURCE.
* ntoskrnl/include/internal/ke.h: Added the interrupted EIP as a
parameter to KiUpdateSystemTime for profiling purposes.
* ntoskrnl/include/internal/nt: Added declaration for profiling
support initialization.
* ntoskrnl/ke/timer.c (KiUpdateSystemTime, KeExpireTimers): Call
the profiling code on a timer interrupt with the interrupt EIP.
* ntoskrnl/ke/i386/irq.c (KiDispatchInterrupt): Pass the interrupted
EIP to KiUpdateSystemTime.
* ntoskrnl/mm/virtual.c (NtReadVirtualMemory, NtWriteVirtualMemory):
Release the MDLs used properly.
* ntoskrnl/nt/nt.c: Call the profiling support initialization.
* ntoskrnl/nt/ntevent.c (NtCreateEvent): Don't try copying the
ObjectAttributes parameter if it is NULL.
* ntoskrnl/nt/profile.c: Implemented profiling.
2001-03-16 David Welch <welch@cwcom.net>
* ntoskrnl/include/internal/safe.h: Corrected typo.

View file

@ -1,5 +1,5 @@
/* $Id: zw.h,v 1.40 2001/01/02 00:46:10 ekohl Exp $
/* $Id: zw.h,v 1.41 2001/03/16 16:05:32 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -816,17 +816,15 @@ ZwCreateProcess(
NTSTATUS
STDCALL
NtCreateProfile(
OUT PHANDLE ProfileHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG ImageBase,
NtCreateProfile(OUT PHANDLE ProfileHandle,
IN HANDLE ProcessHandle,
IN PVOID ImageBase,
IN ULONG ImageSize,
IN ULONG Granularity,
OUT PVOID Buffer,
OUT PULONG Buffer,
IN ULONG ProfilingSize,
IN ULONG ClockSource,
IN ULONG ProcessorMask
);
IN KPROFILE_SOURCE Source,
IN ULONG ProcessorMask);
NTSTATUS
STDCALL
@ -3031,14 +3029,14 @@ NTSTATUS
STDCALL
NtQueryIntervalProfile(
OUT PULONG Interval,
OUT PULONG ClockSource
OUT KPROFILE_SOURCE ClockSource
);
NTSTATUS
STDCALL
ZwQueryIntervalProfile(
OUT PULONG Interval,
OUT PULONG ClockSource
OUT KPROFILE_SOURCE ClockSource
);
@ -4396,14 +4394,14 @@ NTSTATUS
STDCALL
NtSetIntervalProfile(
ULONG Interval,
ULONG ClockSource
KPROFILE_SOURCE ClockSource
);
NTSTATUS
STDCALL
ZwSetIntervalProfile(
ULONG Interval,
ULONG ClockSource
KPROFILE_SOURCE ClockSource
);

View file

@ -1,6 +1,11 @@
#ifndef __INCLUDE_DDK_ZWTYPES_H
#define __INCLUDE_DDK_ZWTYPES_H
typedef enum _KPROFILE_SOURCE
{
ProfileTime
} KPROFILE_SOURCE;
#define NtCurrentProcess() ( (HANDLE) 0xFFFFFFFF )
#define NtCurrentThread() ( (HANDLE) 0xFFFFFFFE )

View file

@ -78,7 +78,7 @@ typedef struct _KTRAP_FRAME
USHORT Reserved9;
} KTRAP_FRAME, *PKTRAP_FRAME;
VOID KiUpdateSystemTime (KIRQL oldIrql);
VOID KiUpdateSystemTime (KIRQL oldIrql, ULONG Eip);
VOID KeAcquireDispatcherDatabaseLock(BOOLEAN Wait);
VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait);
@ -127,5 +127,7 @@ VOID KeInit2(VOID);
BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame);
VOID
NtEarlyInitVdm(VOID);
VOID
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip);
#endif

View file

@ -4,3 +4,4 @@ VOID NtInitializeSemaphoreImplementation(VOID);
VOID NtInitializeMutantImplementation(VOID);
VOID NtInitializeTimerImplementation(VOID);
NTSTATUS NiInitPort(VOID);
VOID NtInitializeProfileImplementation(VOID);

View file

@ -1,4 +1,4 @@
/* $Id: mdl.c,v 1.6 2001/03/07 16:48:42 dwelch Exp $
/* $Id: mdl.c,v 1.7 2001/03/16 16:05:33 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -74,8 +74,7 @@ IoBuildPartialMdl(PMDL SourceMdl,
}
}
VOID
STDCALL
VOID STDCALL
IoFreeMdl(PMDL Mdl)
{
MmUnmapLockedPages(MmGetSystemAddressForMdl(Mdl), Mdl);

View file

@ -1,4 +1,4 @@
/* $Id: irq.c,v 1.7 2001/03/14 23:19:14 dwelch Exp $
/* $Id: irq.c,v 1.8 2001/03/16 16:05:34 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -154,7 +154,7 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe)
if (irq==0)
{
KiUpdateSystemTime(old_level);
KiUpdateSystemTime(old_level, Trapframe->Eip);
}
else
{

View file

@ -1,4 +1,4 @@
/* $Id: timer.c,v 1.41 2001/03/14 23:19:14 dwelch Exp $
/* $Id: timer.c,v 1.42 2001/03/16 16:05:33 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -403,6 +403,7 @@ KeExpireTimers(PKDPC Dpc,
{
PLIST_ENTRY current_entry = NULL;
PKTIMER current = NULL;
ULONG Eip = (ULONG)Arg1;
DPRINT("KeExpireTimers()\n");
@ -422,12 +423,14 @@ KeExpireTimers(PKDPC Dpc,
}
}
KiAddProfileEvent(ProfileTime, Eip);
KeReleaseSpinLockFromDpcLevel(&TimerListLock);
}
VOID
KiUpdateSystemTime (KIRQL oldIrql)
KiUpdateSystemTime (KIRQL oldIrql, ULONG Eip)
/*
* FUNCTION: Handles a timer interrupt
*/
@ -463,7 +466,7 @@ KiUpdateSystemTime (KIRQL oldIrql)
/*
* Queue a DPC that will expire timers
*/
KeInsertQueueDpc(&ExpireTimerDpc, 0, 0);
KeInsertQueueDpc(&ExpireTimerDpc, (PVOID)Eip, 0);
}

View file

@ -1,4 +1,4 @@
/* $Id: virtual.c,v 1.42 2001/03/13 16:25:54 dwelch Exp $
/* $Id: virtual.c,v 1.43 2001/03/16 16:05:34 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel
@ -1347,6 +1347,13 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
KeDetachProcess();
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
ObDereferenceObject(Process);
*NumberOfBytesRead = NumberOfBytesToRead;
@ -1411,6 +1418,13 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
ObDereferenceObject(Process);
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
*NumberOfBytesWritten = NumberOfBytesToWrite;
DPRINT("Finished NtWriteVirtualMemory()\n");

View file

@ -1,4 +1,4 @@
/* $Id: nt.c,v 1.6 2001/02/04 17:28:13 ekohl Exp $
/* $Id: nt.c,v 1.7 2001/03/16 16:05:34 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -25,6 +25,7 @@ VOID NtInit(VOID)
NtInitializeSemaphoreImplementation();
NtInitializeTimerImplementation();
NiInitPort();
NtInitializeProfileImplementation();
}
/* EOF */

View file

@ -132,18 +132,27 @@ NtCreateEvent(OUT PHANDLE UnsafeEventHandle,
PKEVENT Event;
HANDLE EventHandle;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
OBJECT_ATTRIBUTES SafeObjectAttributes;
POBJECT_ATTRIBUTES ObjectAttributes;
Status = MmCopyFromCaller(&ObjectAttributes, UnsafeObjectAttributes,
if (UnsafeObjectAttributes != NULL)
{
Status = MmCopyFromCaller(&SafeObjectAttributes, UnsafeObjectAttributes,
sizeof(OBJECT_ATTRIBUTES));
if (!NT_SUCCESS(Status))
{
return(Status);
}
ObjectAttributes = &SafeObjectAttributes;
}
else
{
ObjectAttributes = NULL;
}
Event = ObCreateObject(&EventHandle,
DesiredAccess,
&ObjectAttributes,
ObjectAttributes,
ExEventObjectType);
KeInitializeEvent(Event,
ManualReset ? NotificationEvent : SynchronizationEvent,

View file

@ -1,7 +1,24 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/nt/Profile.c
* FILE: ntoskrnl/nt/profile.c
* PURPOSE: Support for profiling
* PROGRAMMER: Nobody
* UPDATE HISTORY:
@ -11,42 +28,510 @@
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <internal/mm.h>
#include <internal/ps.h>
#include <internal/pool.h>
#include <limits.h>
#include <internal/safe.h>
#include <internal/debug.h>
/* TYPES ********************************************************************/
typedef struct _KPROCESS_PROFILE
{
LIST_ENTRY ProfileListHead;
LIST_ENTRY ListEntry;
HANDLE Pid;
} KPROCESS_PROFILE, *PKPROCESS_PROFILE;
typedef struct _KPROFILE
{
CSHORT Type;
CSHORT Name;
LIST_ENTRY ListEntry;
PVOID Base;
ULONG Size;
ULONG BucketShift;
PMDL BufferMdl;
PULONG Buffer;
ULONG BufferSize;
ULONG ProcessorMask;
BOOLEAN Started;
PEPROCESS Process;
} KPROFILE, *PKPROFILE;
/* GLOBALS *******************************************************************/
POBJECT_TYPE EXPORTED ExProfileObjectType = NULL;
static GENERIC_MAPPING ExpProfileMapping = {
STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE,
STANDARD_RIGHTS_ALL};
/*
* Size of the profile hash table
*/
#define PROFILE_HASH_TABLE_SIZE (32)
/*
* Table of lists of per-process profiling data structures hashed by PID.
*/
static LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE];
/*
* Head of the list of profile data structures for the kernel
*/
static LIST_ENTRY SystemProfileList;
/*
* Lock that protects the profiling data structures
*/
static KSPIN_LOCK ProfileListLock;
static BOOLEAN ProfileInitDone = FALSE;
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL NtCreateProfile(OUT PHANDLE ProfileHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG ImageBase,
VOID STATIC
KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip)
/*
* Add a profile event to the profile objects for a particular process
* or the system
*/
{
PKPROFILE current;
PLIST_ENTRY current_entry;
current_entry = ListHead->Flink;
while (current_entry != ListHead)
{
current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry);
if (current->Base > Eip)
{
return;
}
if (current->Base <= Eip && (current->Base + current->Size) > Eip &&
current->Started)
{
ULONG Bucket;
Bucket = ((ULONG)(Eip - current->Base)) >> current->BucketShift;
if ((Bucket*4) < current->BufferSize)
{
current->Buffer[Bucket]++;
}
}
current_entry = current_entry->Flink;
}
}
VOID
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip)
/*
* Add a profile event
*/
{
HANDLE Pid;
PKPROCESS_PROFILE current;
PLIST_ENTRY current_entry;
PLIST_ENTRY ListHead;
if (!ProfileInitDone)
{
return;
}
Pid = PsGetCurrentProcessId();
ListHead =
ProcessProfileListHashTable[(ULONG)Pid % PROFILE_HASH_TABLE_SIZE].Flink;
KeAcquireSpinLockAtDpcLevel(&ProfileListLock);
current_entry = ListHead;
while (current_entry != ListHead)
{
current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, ListEntry);
if (current->Pid == Pid)
{
KiAddProfileEventToProcess(&current->ProfileListHead, (PVOID)Eip);
break;
}
current_entry = current_entry->Flink;
}
KiAddProfileEventToProcess(&SystemProfileList, (PVOID)Eip);
KeReleaseSpinLockFromDpcLevel(&ProfileListLock);
}
VOID
KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile)
/*
* Insert a profile object into the list for a process or the system
*/
{
PKPROFILE current;
PLIST_ENTRY current_entry;
current_entry = ListHead;
while (current_entry != ListHead)
{
current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry);
if (current->Base > Profile->Base)
{
Profile->ListEntry.Flink = current_entry;
Profile->ListEntry.Blink = current_entry->Blink;
current_entry->Blink->Flink = &Profile->ListEntry;
current_entry->Blink = &Profile->ListEntry;
return;
}
current_entry = current_entry->Flink;
}
InsertTailList(ListHead, &Profile->ListEntry);
}
VOID
KiInsertProfile(PKPROFILE Profile)
/*
* Insert a profile into the relevant data structures
*/
{
KIRQL oldIrql;
KeAcquireSpinLock(&ProfileListLock, &oldIrql);
if (Profile->Process == NULL)
{
KiInsertProfileIntoProcess(&SystemProfileList, Profile);
}
else
{
ULONG Pid;
PKPROCESS_PROFILE current;
PLIST_ENTRY current_entry;
PLIST_ENTRY ListHead;
Pid = Profile->Process->UniqueProcessId;
ListHead = &ProcessProfileListHashTable[Pid % PROFILE_HASH_TABLE_SIZE];
current_entry = ListHead;
while(current_entry != ListHead)
{
current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE,
ListEntry);
if (current->Pid == (HANDLE)Pid)
{
KiInsertProfileIntoProcess(&current->ProfileListHead, Profile);
KeReleaseSpinLock(&ProfileListLock, oldIrql);
return;
}
current_entry = current_entry->Flink;
}
current = ExAllocatePool(NonPagedPool, sizeof(KPROCESS_PROFILE));
current->Pid = (HANDLE)Pid;
InitializeListHead(&current->ProfileListHead);
InsertTailList(ListHead, &current->ListEntry);
KiInsertProfileIntoProcess(&current->ProfileListHead, Profile);
}
KeReleaseSpinLock(&ProfileListLock, oldIrql);
}
VOID KiRemoveProfile(PKPROFILE Profile)
{
KIRQL oldIrql;
KeAcquireSpinLock(&ProfileListLock, &oldIrql);
if (Profile->Process == NULL)
{
RemoveEntryList(&Profile->ListEntry);
}
else
{
ULONG Pid;
PLIST_ENTRY ListHead;
PKPROCESS_PROFILE current;
PLIST_ENTRY current_entry;
RemoveEntryList(&Profile->ListEntry);
Pid = Profile->Process->UniqueProcessId;
ListHead = &ProcessProfileListHashTable[Pid % PROFILE_HASH_TABLE_SIZE];
current_entry = ListHead;
while(current_entry != ListHead)
{
current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE,
ListEntry);
if (current->Pid == (HANDLE)Pid)
{
if (IsListEmpty(&current->ProfileListHead))
{
RemoveEntryList(&current->ListEntry);
ExFreePool(current);
}
KeReleaseSpinLock(&ProfileListLock, oldIrql);
return;
}
current_entry = current_entry->Flink;
}
KeBugCheck(0);
}
KeReleaseSpinLock(&ProfileListLock, oldIrql);
}
VOID
KiDeleteProfile(PVOID ObjectBody)
{
PKPROFILE Profile;
Profile = (PKPROFILE)ObjectBody;
KiRemoveProfile(Profile);
if (Profile->Process != NULL)
{
ObDereferenceObject(Profile->Process);
Profile->Process = NULL;
}
if (Profile->BufferMdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Profile->BufferMdl->MappedSystemVa,
Profile->BufferMdl);
}
MmUnlockPages(Profile->BufferMdl);
ExFreePool(Profile->BufferMdl);
Profile->BufferMdl = NULL;
}
VOID
NtInitializeProfileImplementation(VOID)
{
ULONG i;
InitializeListHead(&SystemProfileList);
for (i = 0; i < PROFILE_HASH_TABLE_SIZE; i++)
{
InitializeListHead(&ProcessProfileListHashTable[i]);
}
KeInitializeSpinLock(&ProfileListLock);
ProfileInitDone = TRUE;
ExProfileObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
RtlCreateUnicodeString(&ExProfileObjectType->TypeName, L"Profile");
ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F');
ExProfileObjectType->MaxObjects = ULONG_MAX;
ExProfileObjectType->MaxHandles = ULONG_MAX;
ExProfileObjectType->TotalObjects = 0;
ExProfileObjectType->TotalHandles = 0;
ExProfileObjectType->PagedPoolCharge = 0;
ExProfileObjectType->NonpagedPoolCharge = sizeof(KPROFILE);
ExProfileObjectType->Mapping = &ExpProfileMapping;
ExProfileObjectType->Dump = NULL;
ExProfileObjectType->Open = NULL;
ExProfileObjectType->Close = NULL;
ExProfileObjectType->Delete = KiDeleteProfile;
ExProfileObjectType->Parse = NULL;
ExProfileObjectType->Security = NULL;
ExProfileObjectType->QueryName = NULL;
ExProfileObjectType->OkayToClose = NULL;
ExProfileObjectType->Create = NULL;
}
NTSTATUS STDCALL
NtCreateProfile(OUT PHANDLE UnsafeProfileHandle,
IN HANDLE ProcessHandle,
IN PVOID ImageBase,
IN ULONG ImageSize,
IN ULONG Granularity,
OUT PVOID Buffer,
IN ULONG ProfilingSize,
IN ULONG ClockSource,
OUT PULONG Buffer,
IN ULONG BufferSize,
IN KPROFILE_SOURCE Source,
IN ULONG ProcessorMask)
{
UNIMPLEMENTED;
HANDLE ProfileHandle;
NTSTATUS Status;
PKPROFILE Profile;
PEPROCESS Process;
/*
* Reference the associated process
*/
if (ProcessHandle != NULL)
{
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
PsProcessType,
UserMode,
(PVOID*)&Process,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
}
else
{
Process = NULL;
}
NTSTATUS STDCALL NtQueryIntervalProfile(OUT PULONG Interval,
OUT PULONG ClockSource)
/*
* Check the parameters
*/
if ((Process == NULL && ImageBase < (PVOID)KERNEL_BASE) ||
(Process != NULL && ImageBase >= (PVOID)KERNEL_BASE))
{
UNIMPLEMENTED;
return(STATUS_INVALID_PARAMETER_3);
}
if (((ImageSize >> Granularity) * 4) >= BufferSize)
{
return(STATUS_BUFFER_TOO_SMALL);
}
if (Source != ProfileTime)
{
return(STATUS_INVALID_PARAMETER_9);
}
if (ProcessorMask != 0)
{
return(STATUS_INVALID_PARAMETER_10);
}
NTSTATUS STDCALL NtSetIntervalProfile(IN ULONG Interval,
IN ULONG ClockSource)
/*
* Create the object
*/
Profile = ObCreateObject(&ProfileHandle,
STANDARD_RIGHTS_ALL,
NULL,
ExProfileObjectType);
/*
* Initialize it
*/
Profile->Base = ImageBase;
Profile->Size = ImageSize;
Profile->BucketShift = Granularity;
Profile->BufferMdl = MmCreateMdl(NULL, Buffer, BufferSize);
MmProbeAndLockPages(Profile->BufferMdl, UserMode, IoWriteAccess);
Profile->Buffer = MmGetSystemAddressForMdl(Profile->BufferMdl);
Profile->BufferSize = BufferSize;
Profile->ProcessorMask = ProcessorMask;
Profile->Started = FALSE;
Profile->Process = Process;
/*
* Insert the profile into the profile list data structures
*/
KiInsertProfile(Profile);
/*
* Copy the created handle back to the caller
*/
Status = MmCopyToCaller(UnsafeProfileHandle, &ProfileHandle, sizeof(HANDLE));
if (!NT_SUCCESS(Status))
{
UNIMPLEMENTED;
ObDereferenceObject(Profile);
ZwClose(ProfileHandle);
return(Status);
}
NTSTATUS STDCALL NtStartProfile(IN HANDLE ProfileHandle)
{
UNIMPLEMENTED;
ObDereferenceObject(Profile);
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL NtStopProfile(IN HANDLE ProfileHandle)
NTSTATUS STDCALL
NtQueryIntervalProfile(OUT PULONG UnsafeInterval,
OUT KPROFILE_SOURCE Source)
{
UNIMPLEMENTED;
NTSTATUS Status;
if (Source == ProfileTime)
{
ULONG Interval;
/* FIXME: What units does this use, for now nanoseconds */
Interval = 100;
Status = MmCopyToCaller(UnsafeInterval, &Interval, sizeof(ULONG));
if (!NT_SUCCESS(Status))
{
return(Status);
}
return(STATUS_SUCCESS);
}
return(STATUS_INVALID_PARAMETER_2);
}
NTSTATUS STDCALL
NtSetIntervalProfile(IN ULONG Interval,
IN KPROFILE_SOURCE Source)
{
return(STATUS_NOT_IMPLEMENTED);
}
NTSTATUS STDCALL
NtStartProfile(IN HANDLE ProfileHandle)
{
NTSTATUS Status;
PKPROFILE Profile;
Status = ObReferenceObjectByHandle(ProfileHandle,
STANDARD_RIGHTS_ALL,
ExProfileObjectType,
UserMode,
(PVOID*)&Profile,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Profile->Started = TRUE;
ObDereferenceObject(Profile);
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtStopProfile(IN HANDLE ProfileHandle)
{
NTSTATUS Status;
PKPROFILE Profile;
Status = ObReferenceObjectByHandle(ProfileHandle,
STANDARD_RIGHTS_ALL,
ExProfileObjectType,
UserMode,
(PVOID*)&Profile,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Profile->Started = FALSE;
ObDereferenceObject(Profile);
return(STATUS_SUCCESS);
}