ReactOS 0.4.16-dev-927-g467dec4
profile.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/profile.c
5 * PURPOSE: Support for Executive Profile Objects
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Thomas Weidenmueller
8 */
9
10/* INCLUDES *****************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
16/* GLOBALS *******************************************************************/
17
20
22{
27};
28
29/* FUNCTIONS *****************************************************************/
30
31VOID
34{
35 PEPROFILE Profile;
37
38 /* Typecast the Object */
39 Profile = ObjectBody;
40
41 /* Check if there if the Profile was started */
42 if (Profile->LockedBufferAddress)
43 {
44 /* Stop the Profile */
46 ASSERT(State != FALSE);
47
48 /* Unmap the Locked Buffer */
49 MmUnmapLockedPages(Profile->LockedBufferAddress, Profile->Mdl);
50 MmUnlockPages(Profile->Mdl);
51 IoFreeMdl(Profile->Mdl);
53 }
54
55 /* Check if a Process is associated and reference it */
56 if (Profile->Process) ObDereferenceObject(Profile->Process);
57}
58
59CODE_SEG("INIT")
63{
64 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
67 DPRINT("Creating Profile Object Type\n");
68
69 /* Initialize the Mutex to lock the States */
71
72 /* Create the Event Pair Object Type */
73 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
74 RtlInitUnicodeString(&Name, L"Profile");
75 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
76 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KPROFILE);
77 ObjectTypeInitializer.GenericMapping = ExpProfileMapping;
78 ObjectTypeInitializer.PoolType = NonPagedPool;
79 ObjectTypeInitializer.DeleteProcedure = ExpDeleteProfile;
80 ObjectTypeInitializer.ValidAccessMask = PROFILE_ALL_ACCESS;
81 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
82 Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExProfileObjectType);
83 if (!NT_SUCCESS(Status)) return FALSE;
84 return TRUE;
85}
86
91 IN PVOID RangeBase,
92 IN SIZE_T RangeSize,
93 IN ULONG BucketSize,
96 IN KPROFILE_SOURCE ProfileSource,
98{
99 HANDLE hProfile;
100 PEPROFILE Profile;
101 PEPROCESS pProcess;
105 ULONG Log2 = 0;
106 ULONG_PTR Segment = 0;
107 ULONG BucketsRequired;
108 PAGED_CODE();
109
110 /* Easy way out */
112
113 /* Check if this is a low-memory profile */
114 if ((!BucketSize) && (RangeBase < (PVOID)(0x10000)))
115 {
116 /* Validate size */
117 if (BufferSize < sizeof(ULONG)) return STATUS_INVALID_PARAMETER_7;
118
119 /* This will become a segmented profile object */
120 Segment = (ULONG_PTR)RangeBase;
121 RangeBase = 0;
122
123 /* Recalculate the bucket size */
124 BucketSize = RangeSize / (BufferSize / sizeof(ULONG));
125
126 /* Convert it to log2 */
127 BucketSize--;
128 while (BucketSize >>= 1) Log2++;
129 BucketSize += Log2 + 1;
130 }
131
132 /* Validate bucket size */
133 if ((BucketSize > 31) || (BucketSize < 2))
134 {
135 DPRINT1("Bucket size invalid\n");
137 }
138
139 /* Make sure that the buckets can map the range */
140 BucketsRequired = RangeSize >> BucketSize;
141 if (RangeSize & ((1 << BucketSize) - 1))
142 {
143 BucketsRequired++;
144 }
145 if (BucketsRequired > BufferSize / sizeof(ULONG))
146 {
147 DPRINT1("Bucket size too small\n");
149 }
150
151 /* Make sure that the range isn't too gigantic */
152 if (((ULONG_PTR)RangeBase + RangeSize) < RangeSize)
153 {
154 DPRINT1("Range too big\n");
156 }
157
158 /* Check if we were called from user-mode */
160 {
161 /* Entry SEH */
163 {
164 /* Make sure that the handle pointer is valid */
165 ProbeForWriteHandle(ProfileHandle);
166
167 /* Check if the buffer is valid */
170 sizeof(ULONG));
171 }
173 {
174 /* Return the exception code */
176 }
177 _SEH2_END;
178 }
179
180 /* Check if a process was specified */
181 if (Process)
182 {
183 /* Reference it */
188 (PVOID*)&pProcess,
189 NULL);
190 if (!NT_SUCCESS(Status)) return(Status);
191 }
192 else
193 {
194 /* Segmented profile objects cannot be used system-wide */
196
197 /* No process was specified, which means a System-Wide Profile */
198 pProcess = NULL;
199
200 /* For this, we need to check the Privilege */
202 {
203 DPRINT1("NtCreateProfile: Caller requires the SeSystemProfilePrivilege privilege!\n");
205 }
206 }
207
208 /* Create the object */
210 NULL,
211 0,
212 NULL,
213 NULL);
218 NULL,
219 sizeof(EPROFILE),
220 0,
221 sizeof(EPROFILE) + sizeof(KPROFILE),
222 (PVOID*)&Profile);
223 if (!NT_SUCCESS(Status))
224 {
225 /* Dereference the process object if it was specified */
226 if (pProcess) ObDereferenceObject(pProcess);
227
228 /* Return Status */
229 return Status;
230 }
231
232 /* Initialize it */
233 Profile->RangeBase = RangeBase;
234 Profile->RangeSize = RangeSize;
235 Profile->Buffer = Buffer;
236 Profile->BufferSize = BufferSize;
237 Profile->BucketSize = BucketSize;
238 Profile->LockedBufferAddress = NULL;
239 Profile->Segment = Segment;
240 Profile->ProfileSource = ProfileSource;
241 Profile->Affinity = Affinity;
242 Profile->Process = pProcess;
243
244 /* Insert into the Object Tree */
245 Status = ObInsertObject ((PVOID)Profile,
246 NULL,
248 0,
249 NULL,
250 &hProfile);
251
252 /* Check for Success */
253 if (!NT_SUCCESS(Status))
254 {
255 /* Dereference Process on failure */
256 if (pProcess) ObDereferenceObject(pProcess);
257 return Status;
258 }
259
260 /* Enter SEH */
262 {
263 /* Copy the created handle back to the caller*/
264 *ProfileHandle = hProfile;
265 }
267 {
269 }
270 _SEH2_END;
271
272 /* Return Status */
273 return Status;
274}
275
277NTAPI
279 OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
280{
282 LARGE_INTEGER PerfFrequency;
284
285 /* Check if we were called from user-mode */
287 {
288 /* Entry SEH Block */
290 {
291 /* Make sure the counter and frequency are valid */
292 ProbeForWriteLargeInteger(PerformanceCounter);
293 if (PerformanceFrequency)
294 {
295 ProbeForWriteLargeInteger(PerformanceFrequency);
296 }
297 }
299 {
300 /* Return the exception code */
302 }
303 _SEH2_END;
304 }
305
306 /* Enter a new SEH Block */
308 {
309 /* Query the Kernel */
310 *PerformanceCounter = KeQueryPerformanceCounter(&PerfFrequency);
311
312 /* Return Frequency if requested */
313 if (PerformanceFrequency) *PerformanceFrequency = PerfFrequency;
314 }
316 {
317 /* Get the exception code */
319 }
320 _SEH2_END;
321
322 /* Return status to caller */
323 return Status;
324}
325
327NTAPI
329{
330 PEPROFILE Profile;
333 PVOID TempLockedBufferAddress;
335 PAGED_CODE();
336
337 /* Get the Object */
338 Status = ObReferenceObjectByHandle(ProfileHandle,
342 (PVOID*)&Profile,
343 NULL);
344 if (!NT_SUCCESS(Status)) return(Status);
345
346 /* To avoid a Race, wait on the Mutex */
348 Executive,
350 FALSE,
351 NULL);
352
353 /* The Profile can still be enabled though, so handle that */
354 if (Profile->LockedBufferAddress)
355 {
356 /* Release our lock, dereference and return */
358 ObDereferenceObject(Profile);
360 }
361
362 /* Allocate a Kernel Profile Object. */
364 sizeof(*ProfileObject),
366 if (!ProfileObject)
367 {
368 /* Out of memory, fail */
370 ObDereferenceObject(Profile);
372 }
373
374 /* Allocate the Mdl Structure */
375 Profile->Mdl = IoAllocateMdl(Profile->Buffer, Profile->BufferSize, FALSE, FALSE, NULL);
376
377 /* Protect this in SEH as we might raise an exception */
379 {
380 /* Probe and Lock for Write Access */
382 }
384 {
385 /* Release our lock, free the buffer, dereference and return */
387 ObDereferenceObject(Profile);
390 }
391 _SEH2_END;
392
393 /* Map the pages */
394 TempLockedBufferAddress = MmMapLockedPages(Profile->Mdl, KernelMode);
395
396 /* Initialize the Kernel Profile Object */
397 Profile->ProfileObject = ProfileObject;
399 &Profile->Process->Pcb,
400 Profile->RangeBase,
401 Profile->RangeSize,
402 Profile->BucketSize,
403 Profile->ProfileSource,
404 Profile->Affinity);
405
406 /* Start the Profiling */
407 KeStartProfile(ProfileObject, TempLockedBufferAddress);
408
409 /* Now it's safe to save this */
410 Profile->LockedBufferAddress = TempLockedBufferAddress;
411
412 /* Release mutex, dereference and return */
414 ObDereferenceObject(Profile);
415 return STATUS_SUCCESS;
416}
417
419NTAPI
420NtStopProfile(IN HANDLE ProfileHandle)
421{
422 PEPROFILE Profile;
425 PAGED_CODE();
426
427 /* Get the Object */
428 Status = ObReferenceObjectByHandle(ProfileHandle,
432 (PVOID*)&Profile,
433 NULL);
434 if (!NT_SUCCESS(Status)) return(Status);
435
436 /* Get the Mutex */
438 Executive,
440 FALSE,
441 NULL);
442
443 /* Make sure the Profile Object is really Started */
444 if (!Profile->LockedBufferAddress)
445 {
447 goto Exit;
448 }
449
450 /* Stop the Profile */
452
453 /* Unlock the Buffer */
454 MmUnmapLockedPages(Profile->LockedBufferAddress, Profile->Mdl);
455 MmUnlockPages(Profile->Mdl);
456 IoFreeMdl(Profile->Mdl);
458
459 /* Clear the Locked Buffer pointer, meaning the Object is Stopped */
460 Profile->LockedBufferAddress = NULL;
461
462Exit:
463 /* Release Mutex, Dereference and Return */
465 ObDereferenceObject(Profile);
466 return Status;
467}
468
470NTAPI
473{
475 ULONG ReturnInterval;
477 PAGED_CODE();
478
479 /* Check if we were called from user-mode */
481 {
482 /* Enter SEH Block */
484 {
485 /* Validate interval */
487 }
489 {
490 /* Return the exception code */
492 }
493 _SEH2_END;
494 }
495
496 /* Query the Interval */
497 ReturnInterval = (ULONG)KeQueryIntervalProfile(ProfileSource);
498
499 /* Enter SEH block for return */
501 {
502 /* Return the data */
503 *Interval = ReturnInterval;
504 }
506 {
507 /* Get the exception code */
509 }
510 _SEH2_END;
511
512 /* Return Success */
513 return Status;
514}
515
517NTAPI
520{
521 /* Let the Kernel do the job */
523
524 /* Nothing can go wrong */
525 return STATUS_SUCCESS;
526}
#define PAGED_CODE()
#define CODE_SEG(...)
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
unsigned char BOOLEAN
struct NameRec_ * Name
Definition: cdprocs.h:460
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define BufferSize
Definition: mmc.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
ULONG_PTR KAFFINITY
Definition: compat.h:85
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define NonPagedPool
Definition: env_spec_w32.h:307
#define ExGetPreviousMode
Definition: ex.h:143
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
Status
Definition: gdiplustypes.h:25
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(IN PLARGE_INTEGER PerformanceFreq)
Definition: timer.c:138
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:349
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:167
#define OBJ_OPENLINK
Definition: winternl.h:230
enum _KPROFILE_SOURCE KPROFILE_SOURCE
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
PVOID NTAPI MmMapLockedPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode)
Definition: mdlsup.c:818
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:837
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
#define PROFILE_ALL_ACCESS
Definition: extypes.h:131
#define PROFILE_CONTROL
Definition: extypes.h:130
#define KernelMode
Definition: asm.h:38
struct _KPROFILE KPROFILE
@ ProfileObject
Definition: ketypes.h:429
DWORD Interval
Definition: netstat.c:30
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
POBJECT_TYPE ExProfileObjectType
Definition: profile.c:18
NTSTATUS NTAPI NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource, OUT PULONG Interval)
Definition: profile.c:471
NTSTATUS NTAPI NtStopProfile(IN HANDLE ProfileHandle)
Definition: profile.c:420
NTSTATUS NTAPI NtCreateProfile(OUT PHANDLE ProfileHandle, IN HANDLE Process OPTIONAL, IN PVOID RangeBase, IN SIZE_T RangeSize, IN ULONG BucketSize, IN PVOID Buffer, IN ULONG BufferSize, IN KPROFILE_SOURCE ProfileSource, IN KAFFINITY Affinity)
Definition: profile.c:89
BOOLEAN NTAPI ExpInitializeProfileImplementation(VOID)
Definition: profile.c:62
NTSTATUS NTAPI NtStartProfile(IN HANDLE ProfileHandle)
Definition: profile.c:328
VOID NTAPI ExpDeleteProfile(PVOID ObjectBody)
Definition: profile.c:33
KMUTEX ExpProfileMutex
Definition: profile.c:19
GENERIC_MAPPING ExpProfileMapping
Definition: profile.c:21
NTSTATUS NTAPI NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
Definition: profile.c:278
NTSTATUS NTAPI NtSetIntervalProfile(IN ULONG Interval, IN KPROFILE_SOURCE Source)
Definition: profile.c:518
VOID NTAPI KeSetIntervalProfile(ULONG Interval, KPROFILE_SOURCE ProfileSource)
BOOLEAN NTAPI KeStopProfile(struct _KPROFILE *Profile)
ULONG NTAPI KeQueryIntervalProfile(KPROFILE_SOURCE ProfileSource)
VOID NTAPI KeInitializeProfile(struct _KPROFILE *Profile, struct _KPROCESS *Process, PVOID ImageBase, SIZE_T ImageSize, ULONG BucketSize, KPROFILE_SOURCE ProfileSource, KAFFINITY Affinity)
BOOLEAN NTAPI KeStartProfile(struct _KPROFILE *Profile, PVOID Buffer)
const LUID SeSystemProfilePrivilege
Definition: priv.c:30
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
POBJECT_TYPE PsProcessType
Definition: process.c:20
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_PROFILING_NOT_STOPPED
Definition: ntstatus.h:420
#define STATUS_INVALID_PARAMETER_7
Definition: ntstatus.h:481
#define STATUS_PROFILING_NOT_STARTED
Definition: ntstatus.h:419
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1039
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1136
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:184
#define ProbeForWriteLargeInteger(Ptr)
Definition: probe.h:46
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
#define ProbeForWriteUlong(Ptr)
Definition: probe.h:36
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:73
static void Exit(void)
Definition: sock.c:1330
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
KPROCESS Pcb
Definition: pstypes.h:1263
KAFFINITY Affinity
Definition: extypes.h:566
PVOID LockedBufferAddress
Definition: extypes.h:562
PKPROFILE ProfileObject
Definition: extypes.h:561
ULONG BucketSize
Definition: extypes.h:560
PVOID RangeBase
Definition: extypes.h:556
ULONG BufferSize
Definition: extypes.h:559
ULONG_PTR Segment
Definition: extypes.h:564
SIZE_T RangeSize
Definition: extypes.h:557
PEPROCESS Process
Definition: extypes.h:555
KPROFILE_SOURCE ProfileSource
Definition: extypes.h:565
PMDL Mdl
Definition: extypes.h:563
PVOID Buffer
Definition: extypes.h:558
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:365
#define TAG_PROFILE
Definition: tag.h:30
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
_In_ ULONG _In_ ULONG _In_ ULONG _Out_ PKIRQL _Out_ PKAFFINITY Affinity
Definition: halfuncs.h:174
@ Executive
Definition: ketypes.h:415
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
@ IoWriteAccess
Definition: ketypes.h:864
#define ObDereferenceObject
Definition: obfuncs.h:203