Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

profile.c File Reference

#include "exp.h"

Go to the source code of this file.

Classes

struct  _EPROFILE

Defines

#define ACTIVE_PROFILE_LIMIT   8

Typedefs

typedef _EPROFILE EPROFILE
typedef _EPROFILEPEPROFILE

Functions

BOOLEAN ExpProfileInitialization ()
VOID ExpProfileDelete (IN PVOID Object)
NTSTATUS NtCreateProfile (OUT PHANDLE ProfileHandle, IN HANDLE Process OPTIONAL, IN PVOID RangeBase, IN SIZE_T RangeSize, IN ULONG BucketSize, IN PULONG Buffer, IN ULONG BufferSize, IN KPROFILE_SOURCE ProfileSource, IN KAFFINITY Affinity)
NTSTATUS NtStartProfile (IN HANDLE ProfileHandle)
NTSTATUS NtStopProfile (IN HANDLE ProfileHandle)
NTSTATUS NtSetIntervalProfile (IN ULONG Interval, IN KPROFILE_SOURCE Source)
NTSTATUS NtQueryIntervalProfile (IN KPROFILE_SOURCE ProfileSource, OUT PULONG Interval)
NTSTATUS NtQueryPerformanceCounter (OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)

Variables

POBJECT_TYPE ExProfileObjectType
KMUTEX ExpProfileStateMutex
ULONG ExpCurrentProfileUsage = 0
GENERIC_MAPPING ExpProfileMapping


Define Documentation

#define ACTIVE_PROFILE_LIMIT   8
 

Definition at line 64 of file ex/profile.c.

Referenced by NtStartProfile().


Typedef Documentation

typedef struct _EPROFILE EPROFILE
 

Referenced by NtCreateProfile().

typedef struct _EPROFILE * PEPROFILE
 

Referenced by ExpProfileDelete(), NtCreateProfile(), NtStartProfile(), and NtStopProfile().


Function Documentation

VOID ExpProfileDelete IN PVOID  Object  ) 
 

Definition at line 145 of file ex/profile.c.

References ASSERT, ExFreePool(), FALSE, KeStopProfile(), _EPROFILE::LockedBufferAddress, _EPROFILE::Mdl, MmUnlockPages(), MmUnmapLockedPages(), NULL, ObDereferenceObject, PEPROFILE, _EPROFILE::Process, and _EPROFILE::ProfileObject.

Referenced by ExpProfileInitialization().

00151 : 00152 00153 00154 This routine is called by the object management procedures whenever 00155 the last reference to a profile object has been removed. This routine 00156 stops profiling, returns locked buffers and pages, dereferences the 00157 specified process and returns. 00158 00159 Arguments: 00160 00161 Object - a pointer to the body of the profile object. 00162 00163 Return Value: 00164 00165 None. 00166 00167 --*/ 00168 00169 { 00170 PEPROFILE Profile; 00171 BOOLEAN State; 00172 PEPROCESS ProcessAddress; 00173 00174 Profile = (PEPROFILE)Object; 00175 00176 if (Profile->LockedBufferAddress != NULL) { 00177 00178 // 00179 // Stop profiling and unlock the buffers and deallocate pool. 00180 // 00181 00182 State = KeStopProfile (Profile->ProfileObject); 00183 ASSERT (State != FALSE); 00184 00185 MmUnmapLockedPages (Profile->LockedBufferAddress, Profile->Mdl); 00186 MmUnlockPages (Profile->Mdl); 00187 ExFreePool (Profile->ProfileObject); 00188 } 00189 00190 if (Profile->Process != NULL) { 00191 ProcessAddress = CONTAINING_RECORD(Profile->Process, EPROCESS, Pcb); 00192 ObDereferenceObject ((PVOID)ProcessAddress); 00193 } 00194 00195 return; 00196 }

BOOLEAN ExpProfileInitialization  ) 
 

Definition at line 79 of file ex/profile.c.

References ExpProfileDelete(), ExpProfileMapping, ExpProfileStateMutex, ExProfileObjectType, KeInitializeMutex(), L, MUTEX_LEVEL_EX_PROFILE, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObjectType(), RtlInitUnicodeString(), and Status.

00084 : 00085 00086 This function creates the profile object type descriptor at system 00087 initialization and stores the address of the object type descriptor 00088 in global storage. 00089 00090 Arguments: 00091 00092 None. 00093 00094 Return Value: 00095 00096 A value of TRUE is returned if the profile object type descriptor is 00097 successfully initialized. Otherwise a value of FALSE is returned. 00098 00099 --*/ 00100 00101 { 00102 00103 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 00104 NTSTATUS Status; 00105 UNICODE_STRING TypeName; 00106 00107 // 00108 // Initialize mutex for synchronizing start and stop operations. 00109 // 00110 00111 KeInitializeMutex (&ExpProfileStateMutex, MUTEX_LEVEL_EX_PROFILE); 00112 00113 // 00114 // Initialize string descriptor. 00115 // 00116 00117 RtlInitUnicodeString(&TypeName, L"Profile"); 00118 00119 // 00120 // Create event object type descriptor. 00121 // 00122 00123 RtlZeroMemory(&ObjectTypeInitializer,sizeof(ObjectTypeInitializer)); 00124 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 00125 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 00126 ObjectTypeInitializer.PoolType = NonPagedPool; 00127 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EPROFILE); 00128 ObjectTypeInitializer.ValidAccessMask = PROFILE_ALL_ACCESS; 00129 ObjectTypeInitializer.DeleteProcedure = ExpProfileDelete; 00130 ObjectTypeInitializer.GenericMapping = ExpProfileMapping; 00131 00132 Status = ObCreateObjectType(&TypeName, 00133 &ObjectTypeInitializer, 00134 (PSECURITY_DESCRIPTOR)NULL, 00135 &ExProfileObjectType); 00136 00137 // 00138 // If the event object type descriptor was successfully created, then 00139 // return a value of TRUE. Otherwise return a value of FALSE. 00140 // 00141 00142 return (BOOLEAN)(NT_SUCCESS(Status)); 00143 } VOID

NTSTATUS NtCreateProfile OUT PHANDLE  ProfileHandle,
IN HANDLE Process  OPTIONAL,
IN PVOID  RangeBase,
IN SIZE_T  RangeSize,
IN ULONG  BucketSize,
IN PULONG  Buffer,
IN ULONG  BufferSize,
IN KPROFILE_SOURCE  ProfileSource,
IN KAFFINITY  Affinity
 

Definition at line 199 of file ex/profile.c.

References Buffer, BufferSize, DbgPrint, EPROFILE, EXCEPTION_EXECUTE_HANDLER, ExProfileObjectType, FALSE, Handle, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObDereferenceObject, ObInsertObject(), ObjectAttributes, ObReferenceObjectByHandle(), _EPROCESS::Pcb, PEPROFILE, ProbeForWrite(), ProbeForWriteHandle, PsProcessType, SeSinglePrivilegeCheck(), SeSystemProfilePrivilege, Status, and USHORT.

Referenced by main().

00213 : 00214 00215 This function creates a profile object. 00216 00217 Arguments: 00218 00219 ProfileHandle - Supplies a pointer to a variable that will receive 00220 the profile object handle. 00221 00222 Process - Optionally, supplies the handle to the process whose 00223 address space to profile. If the value is NULL (0), then 00224 all address spaces are included in the profile. 00225 00226 RangeBase - Supplies the address of the first byte of the address 00227 space for which profiling information is to be collected. 00228 00229 00230 RangeSize - Supplies the size of the range to profile in the 00231 address space. RangeBase and RangeSize are interpreted 00232 such that RangeBase <= address < RangeBase+RangeSize 00233 will generate a profile hit. 00234 00235 BucketSize - Supplies the LOG base 2 of the size of the profiling 00236 bucket. Thus, BucketSize = 2 yields four-byte 00237 buckets, BucketSize = 7 yields 128-byte buckets. 00238 All profile hits in a given bucket will increment 00239 the corresponding counter in Buffer. Buckets 00240 cannot be smaller than a ULONG. The acceptable range 00241 of this value is 2 to 30 inclusive. 00242 00243 Buffer - Supplies an array of ULONGs. Each ULONG is a hit counter, 00244 which records the number of hits of the corresponding 00245 bucket. 00246 00247 BufferSize - Size in bytes of Buffer. 00248 00249 ProfileSource - Supplies the source for the profile interrupt 00250 00251 Affinity - Supplies the processor set for the profile interrupt 00252 00253 Return Value: 00254 00255 TBS 00256 00257 --*/ 00258 00259 { 00260 00261 PEPROFILE Profile; 00262 HANDLE Handle; 00263 KPROCESSOR_MODE PreviousMode; 00264 NTSTATUS Status; 00265 PEPROCESS ProcessAddress; 00266 OBJECT_ATTRIBUTES ObjectAttributes; 00267 BOOLEAN HasPrivilege = FALSE; 00268 ULONG Segment = FALSE; 00269 USHORT PowerOf2; 00270 00271 // 00272 // Verify that the base and size arguments are reasonable. 00273 // 00274 00275 if (BufferSize == 0) { 00276 return STATUS_INVALID_PARAMETER_7; 00277 } 00278 00279 #ifdef i386 00280 // 00281 // sleazy use of bucket size. If bucket size is zero, and 00282 // RangeBase < 64K, then create a profile object to attach 00283 // to a non-flat code segment. In this case, RangeBase is 00284 // the non-flat CS for this profile object. 00285 // 00286 00287 if ((BucketSize == 0) && (RangeBase < (PVOID)(64 * 1024))) { 00288 00289 if (BufferSize < sizeof(ULONG)) { 00290 return STATUS_INVALID_PARAMETER_7; 00291 } 00292 00293 Segment = (ULONG)RangeBase; 00294 RangeBase = 0; 00295 BucketSize = RangeSize / (BufferSize / sizeof(ULONG)); 00296 00297 // 00298 // Convert Bucket size of log2(BucketSize) 00299 // 00300 PowerOf2 = 0; 00301 BucketSize = BucketSize - 1; 00302 while (BucketSize >>= 1) { 00303 PowerOf2++; 00304 } 00305 00306 BucketSize = PowerOf2 + 1; 00307 00308 if (BucketSize < 2) { 00309 BucketSize = 2; 00310 } 00311 } 00312 #endif 00313 00314 if ((BucketSize > 31) || (BucketSize < 2)) { 00315 return STATUS_INVALID_PARAMETER; 00316 } 00317 00318 if ((RangeSize >> (BucketSize - 2)) > BufferSize) { 00319 return STATUS_BUFFER_TOO_SMALL; 00320 } 00321 00322 if (((ULONG_PTR)RangeBase + RangeSize) < RangeSize) { 00323 return STATUS_BUFFER_OVERFLOW; 00324 } 00325 00326 // 00327 // Establish an exception handler, probe the output handle address, and 00328 // attempt to create a profile object. If the probe fails, then return the 00329 // exception code as the service status. Otherwise return the status value 00330 // returned by the object insertion routine. 00331 // 00332 00333 try { 00334 // 00335 // Get previous processor mode and probe output handle address if 00336 // necessary. 00337 // 00338 00339 PreviousMode = KeGetPreviousMode (); 00340 00341 if (PreviousMode != KernelMode) { 00342 ProbeForWriteHandle(ProfileHandle); 00343 00344 ProbeForWrite(Buffer, 00345 BufferSize, 00346 sizeof(ULONG)); 00347 } 00348 00349 // 00350 // If an exception occurs during the probe of the output handle address, 00351 // then always handle the exception and return the exception code as the 00352 // status value. 00353 // 00354 00355 } except (EXCEPTION_EXECUTE_HANDLER) { 00356 return GetExceptionCode(); 00357 } 00358 00359 // 00360 // TODO post NT5: 00361 // 00362 // Currently, if a process isn't specified, there is no privilege check if 00363 // RangeBase > MM_HIGHEST_USER_ADDRESS. 00364 // The check for user-space addresses is SeSystemProfilePrivilege. 00365 // Querying a specific process requires only PROCESS_QUERY_INFORMATION. 00366 // 00367 // The spec says: 00368 // 00369 // Process - If specified, a handle to a process which describes the address space to profile. 00370 // If not present, then all address spaces are included in the profile. 00371 // Profiling a process requires PROCESS_QUERY_INFORMATION access to that process and 00372 // SeProfileSingleProcessPrivilege privilege. 00373 // Profiling all processes requires SeSystemProfilePrivilege privilege. 00374 // 00375 // So two changes appear needed. 00376 // A check on SeProfileSingleProcessPrivilege needs to be added to the single process case, 00377 // and SeSystemProfilePrivilege privilege should be required for both user and system address profiling. 00378 // 00379 00380 00381 if (!ARGUMENT_PRESENT(Process)) { 00382 00383 // 00384 // Don't attach segmented profile objects to all processes 00385 // 00386 00387 if (Segment) { 00388 return STATUS_INVALID_PARAMETER; 00389 } 00390 00391 // 00392 // Profile all processes. Make sure that the specified 00393 // address range is in system space, unless SeSystemProfilePrivilege. 00394 // 00395 00396 if (RangeBase <= MM_HIGHEST_USER_ADDRESS) { 00397 00398 // 00399 // Check for privilege before allowing a user to profile 00400 // all processes and USER addresses. 00401 // 00402 00403 if (PreviousMode != KernelMode) { 00404 HasPrivilege = SeSinglePrivilegeCheck( 00405 SeSystemProfilePrivilege, 00406 PreviousMode 00407 ); 00408 00409 if (!HasPrivilege) { 00410 #if DBG 00411 DbgPrint("SeSystemProfilePrivilege needed to profile all USER addresses.\n"); 00412 #endif //DBG 00413 return( STATUS_PRIVILEGE_NOT_HELD ); 00414 } 00415 00416 } 00417 } 00418 00419 ProcessAddress = NULL; 00420 00421 00422 } else { 00423 00424 // 00425 // Reference the specified process. 00426 // 00427 00428 Status = ObReferenceObjectByHandle ( Process, 00429 PROCESS_QUERY_INFORMATION, 00430 PsProcessType, 00431 PreviousMode, 00432 (PVOID *)&ProcessAddress, 00433 NULL ); 00434 00435 if (!NT_SUCCESS(Status)) { 00436 return Status; 00437 } 00438 } 00439 00440 InitializeObjectAttributes( &ObjectAttributes, 00441 NULL, 00442 OBJ_EXCLUSIVE, 00443 NULL, 00444 NULL ); 00445 00446 Status = ObCreateObject( KernelMode, 00447 ExProfileObjectType, 00448 &ObjectAttributes, 00449 PreviousMode, 00450 NULL, 00451 sizeof(EPROFILE), 00452 0, 00453 sizeof(EPROFILE) + sizeof(KPROFILE), 00454 (PVOID *)&Profile); 00455 00456 // 00457 // If the profile object was successfully allocated, initialize 00458 // the profile object. 00459 // 00460 if (NT_SUCCESS(Status)) { 00461 00462 00463 if (ProcessAddress != NULL) { 00464 Profile->Process = &ProcessAddress->Pcb; 00465 } else { 00466 Profile->Process = NULL; 00467 } 00468 00469 Profile->RangeBase = RangeBase; 00470 Profile->RangeSize = RangeSize; 00471 Profile->Buffer = Buffer; 00472 Profile->BufferSize = BufferSize; 00473 Profile->BucketSize = BucketSize; 00474 Profile->LockedBufferAddress = NULL; 00475 Profile->Segment = Segment; 00476 Profile->ProfileSource = ProfileSource; 00477 Profile->Affinity = Affinity; 00478 00479 Status = ObInsertObject(Profile, 00480 NULL, 00481 PROFILE_CONTROL, 00482 0, 00483 (PVOID *)NULL, 00484 &Handle); 00485 // 00486 // If the profile object was successfully inserted in the current 00487 // process' handle table, then attempt to write the profile object 00488 // handle value. If the write attempt fails, then do not report 00489 // an error. When the caller attempts to access the handle value, 00490 // an access violation will occur. 00491 // 00492 if (NT_SUCCESS(Status)) { 00493 try { 00494 *ProfileHandle = Handle; 00495 } except(EXCEPTION_EXECUTE_HANDLER) { 00496 } 00497 } 00498 } 00499 00500 // 00501 // If we failed, remove our reference to the process object. 00502 // 00503 if (!NT_SUCCESS(Status)) { 00504 if (ProcessAddress != NULL) { 00505 ObDereferenceObject ((PVOID)ProcessAddress); 00506 } 00507 } 00508 00509 // 00510 // Return service status. 00511 // 00512 00513 return Status; 00514 }

NTSTATUS NtQueryIntervalProfile IN KPROFILE_SOURCE  ProfileSource,
OUT PULONG  Interval
 

Definition at line 788 of file ex/profile.c.

References EXCEPTION_EXECUTE_HANDLER, KeQueryIntervalProfile(), KernelMode, KPROCESSOR_MODE, and ProbeForWriteUlong.

00795 : 00796 00797 This routine queries the system-wide interval (and thus the profiling 00798 rate) for profiling. 00799 00800 Arguments: 00801 00802 Source - Specifies the profile source to be queried. 00803 00804 Interval - Returns the sampling interval in 100ns units. 00805 00806 Return Value: 00807 00808 TBS 00809 00810 --*/ 00811 00812 { 00813 ULONG CapturedInterval; 00814 KPROCESSOR_MODE PreviousMode; 00815 00816 PreviousMode = KeGetPreviousMode (); 00817 if (PreviousMode != KernelMode) { 00818 00819 // 00820 // Probe accessibility of user's buffer. 00821 // 00822 00823 try { 00824 ProbeForWriteUlong (Interval); 00825 00826 } except (EXCEPTION_EXECUTE_HANDLER) { 00827 00828 // 00829 // If an exception occurs during the probe or capture 00830 // of the initial values, then handle the exception and 00831 // return the exception code as the status value. 00832 // 00833 00834 return GetExceptionCode(); 00835 } 00836 } 00837 00838 CapturedInterval = KeQueryIntervalProfile (ProfileSource); 00839 00840 try { 00841 *Interval = CapturedInterval; 00842 00843 } except (EXCEPTION_EXECUTE_HANDLER) { 00844 NOTHING; 00845 } 00846 00847 return STATUS_SUCCESS; 00848 }

NTSTATUS NtQueryPerformanceCounter OUT PLARGE_INTEGER  PerformanceCounter,
OUT PLARGE_INTEGER PerformanceFrequency  OPTIONAL
 

Definition at line 851 of file ex/profile.c.

References EXCEPTION_EXECUTE_HANDLER, KeQueryPerformanceCounter(), KernelMode, KPROCESSOR_MODE, and ProbeForWrite().

Referenced by LdrpInitialize(), LdrpInitializeProcess(), LdrpMapDll(), NapDllInit(), and RtlpDebugPageHeapCreate().

00858 : 00859 00860 This function returns current value of performance counter and, 00861 optionally, the frequency of the performance counter. 00862 00863 Performance frequency is the frequency of the performance counter 00864 in Hertz, i.e., counts/second. Note that this value is implementation 00865 dependent. If the implementation does not have hardware to support 00866 performance timing, the value returned is 0. 00867 00868 Arguments: 00869 00870 PerformanceCounter - supplies the address of a variable to receive 00871 the current Performance Counter value. 00872 00873 PerformanceFrequency - Optionally, supplies the address of a 00874 variable to receive the performance counter frequency. 00875 00876 Return Value: 00877 00878 STATUS_ACCESS_VIOLATION or STATUS_SUCCESS. 00879 00880 --*/ 00881 00882 { 00883 KPROCESSOR_MODE PreviousMode; 00884 LARGE_INTEGER KernelPerformanceFrequency; 00885 00886 PreviousMode = KeGetPreviousMode(); 00887 if (PreviousMode != KernelMode) { 00888 00889 // 00890 // Probe accessibility of user's buffer. 00891 // 00892 00893 try { 00894 ProbeForWrite ( PerformanceCounter, 00895 sizeof (LARGE_INTEGER), 00896 sizeof (ULONG) 00897 ); 00898 00899 if (ARGUMENT_PRESENT(PerformanceFrequency)) { 00900 ProbeForWrite ( PerformanceFrequency, 00901 sizeof (LARGE_INTEGER), 00902 sizeof (ULONG) 00903 ); 00904 } 00905 00906 } except (EXCEPTION_EXECUTE_HANDLER) { 00907 00908 // 00909 // If an exception occurs during the probe or capture 00910 // of the initial values, then handle the exception and 00911 // return the exception code as the status value. 00912 // 00913 00914 return GetExceptionCode(); 00915 } 00916 } 00917 00918 try { 00919 *PerformanceCounter = KeQueryPerformanceCounter ( 00920 (PLARGE_INTEGER)&KernelPerformanceFrequency ); 00921 if (ARGUMENT_PRESENT(PerformanceFrequency)) { 00922 *PerformanceFrequency = KernelPerformanceFrequency; 00923 } 00924 } except (EXCEPTION_EXECUTE_HANDLER) { 00925 return GetExceptionCode(); 00926 } 00927 00928 return STATUS_SUCCESS; 00929 } }

NTSTATUS NtSetIntervalProfile IN ULONG  Interval,
IN KPROFILE_SOURCE  Source
 

Definition at line 757 of file ex/profile.c.

References KeSetIntervalProfile().

00764 : 00765 00766 This routine allows the system-wide interval (and thus the profiling 00767 rate) for profiling to be set. 00768 00769 Arguments: 00770 00771 Interval - Supplies the sampling interval in 100ns units. 00772 00773 Source - Specifies the profile source to be set. 00774 00775 Return Value: 00776 00777 TBS 00778 00779 --*/ 00780 00781 { 00782 00783 KeSetIntervalProfile (Interval, Source); 00784 return STATUS_SUCCESS; 00785 }

NTSTATUS NtStartProfile IN HANDLE  ProfileHandle  ) 
 

Definition at line 517 of file ex/profile.c.

References ACTIVE_PROFILE_LIMIT, ASSERT, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, Executive, ExFreePool(), ExpCurrentProfileUsage, ExpProfileStateMutex, ExProfileObjectType, FALSE, IoWriteAccess, KeInitializeProfile(), KeReleaseMutex(), KernelMode, KeStartProfile(), KeWaitForSingleObject(), KPROCESSOR_MODE, MmCached, MmInitializeMdl, MmMapLockedPagesSpecifyCache(), MmProbeAndLockPages(), MmSizeOfMdl(), MmUnlockPages(), MmUnmapLockedPages(), NonPagedPool, NormalPagePriority, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PEPROFILE, ProfileObject, and Status.

Referenced by main().

00523 : 00524 00525 The NtStartProfile routine starts the collecting data for the 00526 specified profile object. This involved allocating nonpaged 00527 pool to lock the specified buffer in memory, creating a kernel 00528 profile object and starting collecting on that profile object. 00529 00530 Arguments: 00531 00532 ProfileHandle - Supplies the profile handle to start profiling on. 00533 00534 Return Value: 00535 00536 TBS 00537 00538 --*/ 00539 00540 { 00541 00542 KPROCESSOR_MODE PreviousMode; 00543 NTSTATUS Status; 00544 PEPROFILE Profile; 00545 PKPROFILE ProfileObject; 00546 PVOID LockedVa; 00547 BOOLEAN State; 00548 00549 PreviousMode = KeGetPreviousMode(); 00550 00551 Status = ObReferenceObjectByHandle( ProfileHandle, 00552 PROFILE_CONTROL, 00553 ExProfileObjectType, 00554 PreviousMode, 00555 (PVOID *)&Profile, 00556 NULL); 00557 if (!NT_SUCCESS(Status)) { 00558 return Status; 00559 } 00560 00561 // 00562 // Acquire the profile state mutex so two threads can't 00563 // operate on the same profile object simultaneously. 00564 // 00565 00566 KeWaitForSingleObject( &ExpProfileStateMutex, 00567 Executive, 00568 KernelMode, 00569 FALSE, 00570 (PLARGE_INTEGER)NULL); 00571 00572 // 00573 // Make sure profiling is not already enabled. 00574 // 00575 00576 if (Profile->LockedBufferAddress != NULL) { 00577 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00578 ObDereferenceObject ((PVOID)Profile); 00579 return STATUS_PROFILING_NOT_STOPPED; 00580 } 00581 00582 if (ExpCurrentProfileUsage == ACTIVE_PROFILE_LIMIT) { 00583 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00584 ObDereferenceObject ((PVOID)Profile); 00585 return STATUS_PROFILING_AT_LIMIT; 00586 } 00587 00588 ProfileObject = ExAllocatePoolWithTag (NonPagedPool, 00589 MmSizeOfMdl(Profile->Buffer, 00590 Profile->BufferSize) + 00591 sizeof(KPROFILE), 00592 'forP'); 00593 00594 if (ProfileObject == NULL) { 00595 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00596 ObDereferenceObject ((PVOID)Profile); 00597 return STATUS_INSUFFICIENT_RESOURCES; 00598 } 00599 00600 Profile->Mdl = (PMDL)(ProfileObject + 1); 00601 Profile->ProfileObject = ProfileObject; 00602 00603 // 00604 // Probe and lock the specified buffer. 00605 // 00606 00607 MmInitializeMdl(Profile->Mdl, Profile->Buffer, Profile->BufferSize); 00608 00609 try { 00610 00611 LockedVa = NULL; 00612 00613 MmProbeAndLockPages (Profile->Mdl, 00614 PreviousMode, 00615 IoWriteAccess ); 00616 00617 LockedVa = (PVOID)43; // flag to notice MmMapLockedPages failed. 00618 00619 LockedVa = MmMapLockedPagesSpecifyCache (Profile->Mdl, 00620 KernelMode, 00621 MmCached, 00622 NULL, 00623 FALSE, 00624 NormalPagePriority); 00625 00626 } except (EXCEPTION_EXECUTE_HANDLER) { 00627 00628 if (LockedVa == (PVOID)43 ) { 00629 MmUnlockPages (Profile->Mdl); 00630 } 00631 ExFreePool (ProfileObject); 00632 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00633 ObDereferenceObject ((PVOID)Profile); 00634 return GetExceptionCode(); 00635 } 00636 00637 if (LockedVa == NULL) { 00638 MmUnlockPages (Profile->Mdl); 00639 ExFreePool (ProfileObject); 00640 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00641 ObDereferenceObject ((PVOID)Profile); 00642 return STATUS_INSUFFICIENT_RESOURCES; 00643 } 00644 00645 // 00646 // Initialize the profile object. 00647 // 00648 00649 KeInitializeProfile (ProfileObject, 00650 Profile->Process, 00651 Profile->RangeBase, 00652 Profile->RangeSize, 00653 Profile->BucketSize, 00654 Profile->Segment, 00655 Profile->ProfileSource, 00656 Profile->Affinity); 00657 try { 00658 State = KeStartProfile (ProfileObject, LockedVa); 00659 ASSERT (State != FALSE); 00660 00661 } except (EXCEPTION_EXECUTE_HANDLER) { 00662 00663 MmUnlockPages (Profile->Mdl); 00664 MmUnmapLockedPages (LockedVa, Profile->Mdl); 00665 ExFreePool (ProfileObject); 00666 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00667 ObDereferenceObject ((PVOID)Profile); 00668 return GetExceptionCode(); 00669 } 00670 00671 Profile->LockedBufferAddress = LockedVa; 00672 00673 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00674 ObDereferenceObject ((PVOID)Profile); 00675 00676 return STATUS_SUCCESS; 00677 }

NTSTATUS NtStopProfile IN HANDLE  ProfileHandle  ) 
 

Definition at line 680 of file ex/profile.c.

References ASSERT, Executive, ExFreePool(), ExpProfileStateMutex, ExProfileObjectType, FALSE, KeReleaseMutex(), KernelMode, KeStopProfile(), KeWaitForSingleObject(), KPROCESSOR_MODE, MmUnlockPages(), MmUnmapLockedPages(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PEPROFILE, and Status.

Referenced by main().

00686 : 00687 00688 The NtStopProfile routine stops collecting data for the 00689 specified profile object. This involves stopping the data 00690 collection on the profile object, unlocking the locked buffers, 00691 and deallocating the pool for the MDL and profile object. 00692 00693 Arguments: 00694 00695 ProfileHandle - Supplies a the profile handle to stop profiling. 00696 00697 Return Value: 00698 00699 TBS 00700 00701 --*/ 00702 00703 { 00704 00705 PEPROFILE Profile; 00706 KPROCESSOR_MODE PreviousMode; 00707 NTSTATUS Status; 00708 BOOLEAN State; 00709 00710 PreviousMode = KeGetPreviousMode(); 00711 00712 Status = ObReferenceObjectByHandle( ProfileHandle, 00713 PROFILE_CONTROL, 00714 ExProfileObjectType, 00715 PreviousMode, 00716 (PVOID *)&Profile, 00717 NULL); 00718 00719 if (!NT_SUCCESS(Status)) { 00720 return Status; 00721 } 00722 00723 KeWaitForSingleObject( &ExpProfileStateMutex, 00724 Executive, 00725 KernelMode, 00726 FALSE, 00727 (PLARGE_INTEGER)NULL); 00728 00729 // 00730 // Check to see if profiling is not active. 00731 // 00732 00733 if (Profile->LockedBufferAddress == NULL) { 00734 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00735 ObDereferenceObject ((PVOID)Profile); 00736 return STATUS_PROFILING_NOT_STARTED; 00737 } 00738 00739 // 00740 // Stop profiling and unlock the buffer. 00741 // 00742 00743 State = KeStopProfile (Profile->ProfileObject); 00744 ASSERT (State != FALSE); 00745 00746 MmUnmapLockedPages (Profile->LockedBufferAddress, Profile->Mdl); 00747 MmUnlockPages (Profile->Mdl); 00748 ExFreePool (Profile->ProfileObject); 00749 Profile->LockedBufferAddress = NULL; 00750 KeReleaseMutex (&ExpProfileStateMutex, FALSE); 00751 00752 ObDereferenceObject ((PVOID)Profile); 00753 return STATUS_SUCCESS; 00754 }


Variable Documentation

ULONG ExpCurrentProfileUsage = 0
 

Definition at line 55 of file ex/profile.c.

Referenced by NtStartProfile().

GENERIC_MAPPING ExpProfileMapping
 

Initial value:

{ STANDARD_RIGHTS_READ | PROFILE_CONTROL, STANDARD_RIGHTS_WRITE | PROFILE_CONTROL, STANDARD_RIGHTS_EXECUTE | PROFILE_CONTROL, PROFILE_ALL_ACCESS }

Definition at line 57 of file ex/profile.c.

Referenced by ExpProfileInitialization().

KMUTEX ExpProfileStateMutex
 

Definition at line 53 of file ex/profile.c.

Referenced by ExpProfileInitialization(), NtStartProfile(), and NtStopProfile().

POBJECT_TYPE ExProfileObjectType
 

Definition at line 51 of file ex/profile.c.

Referenced by ExpProfileInitialization(), NtCreateProfile(), NtStartProfile(), and NtStopProfile().


Generated on Sat May 15 19:45:20 2004 for test by doxygen 1.3.7