Geoff Chappell, Software Analyst
This function obtains the profile interval that is currently set for a given profile source.
NTSTATUS NtQueryIntervalProfile ( KPROFILE_SOURCE ProfileSource, ULONG *Interval);
in version 3.51 and higher, but
NTSTATUS NtQueryIntervalProfile (ULONG *Interval);
in versions 3.10 and 3.50.
The ProfileSource argument selects a possible source of profile interrupts.
The Interval argument is the address of a variable that is to receive what is currently set as the interval between profile interrupts that have the given source. The unit of measurement depends on the source.
The function returns STATUS_SUCCESS if successful, else a negative error code.
If the given profile source is not supported, the function declares success but the interval is reported as zero.
The NtQueryIntervalProfile function and its alias ZwQueryIntervalProfile are exported by name from NTDLL in version 3.10 and higher. In kernel mode, where ZwQueryIntervalProfile is a stub and NtQueryIntervalProfile is the implementation, neither is exported until the 1607 release of Windows exports the stub.
Neither NtQueryIntervalProfile nor its alias is documented. As ZwQueryIntervalProfile, it is declared in the ZWAPI.H file from the Enterprise edition of the Windows Driver Kit (WDK) for the 1511 release of Windows 10.
The semi-documented repackaging of NtQueryIntervalProfile in a higher-level user-mode module (than NTDLL) is the TraceSampledProfileIntervalInfo (0x05) information class of the ADVAPI32 and SECHOST function TraceQueryInformation. Not that the documentation spells it out, but the information buffer to provide for this information class is the TRACE_PROFILE_INTERVAL. Though the structure appears to be undocumented, a C-language definition is available in EVNTRACE.H. That structure’s non-zero Source on input is in fact a KPROFILE_SOURCE and becomes the ProfileSource argument to NtQueryIntervalProfile.
The following implementation notes come mainly from inspection of the kernel from the original release of Windows 10. They may some day get revised to account for other versions. Where anything is written about earlier versions, take it not as an attempt at presenting a comprehensive history but as a bonus from my being unable to resist a quick trip down memory lane. I have no programme of revisiting this analysis for later releases. Updates mean just that I happen to have noticed something and to have found time to add it.
If executing for a user-mode request, which looks to be necessary given that the function is not exported in kernel mode and is not called internally, the variable at Interval must start in user-mode address space and be writable. Failure at this defence is failure for the function, typically showing as a return of STATUS_ACCESS_VIOLATION. If writing to the variable for a successful return causes an exception, the function still returns STATUS_SUCCESS.
All profile sources other than ProfileAlignmentFixup (0x01) are managed by the HAL. The kernel queries the HAL via the HalQuerySystemInformation pointer in the kernel’s HAL_DISPATCH, specifically for the information class HalProfileSourceInformation (0x01). If this call succeeds and the HAL indicates that the given ProfileSource is supported, then whatever interval it produces in the requested information becomes the interval that the function reports. Otherwise, the function reports that the interval is zero. Either way, the function returns STATUS_SUCCESS.
For ProfileAlignmentFixup, the function reports whatever interval was last set for this profile source. If no interval has yet been set, the interval is reported as zero. Either way, the function returns STATUS_SUCCESS.
Beware that profile sources are global. The interval can be changed by any sufficiently privileged process’s call to NtSetIntervalProfile for the same profile source. An interval reported by NtQueryIntervalProfile can be stale even by the time the function returns.