Geoff Chappell - Software Analyst
This page lists the 146 functions and variables that are newly exported from the Windows kernel in version 3.50. It is here thought that no service packs of version 3.50 added to these exports, but beware that only SP3 has yet been obtained for inspection.
To convey more detail with less text, the page relies heavily on several types of shortcut.
The first is that although a few of the kernel’s exports are of variables rather than functions, I tend to talk of all as functions, hoping that no confusion will be caused by the loose terminology. The variables are indicated by a parenthetical “data” after their first appearance in the Functions column.
Documentation status is summarised by colour coding. (Had the website’s scripts run as expected, then hovering over any colour-coded text would produce a tooltip that shows why the text is coloured.) (To decode a colour, hover for a tooltip.)
Functions that appear to be completely undocumented are highlighted yellow. If a function is documented now but was not documented in the first contemporaneous Device Driver Kit (DDK), Windows Driver Kit (WDK) or Installable File System (IFS) Kit, then it is shaded yellow to retain some of its previous status. If a function is documented as reserved or obsolete, it is shaded red or shaded grey, respectively. Otherwise, functions that have their own non-trivial documentation are left with no background colour.
Many undocumented functions and some variables have C-language declarations in one or another header file. To show them as being not completely undocumented they are shaded orange, except for one special case. Some declarations are known only from “minwin” headers that Microsoft published in early editions of the WDK for Windows 10 which seem since to have been withdrawn. These are highlighted orange to indicate that public disclosure even of the declaration was exceptional.
The default understanding is that exporting continues for all later versions, and in both the x86 and x64 builds. Exceptions are sketched in a column headed Export History.
The description “x86 only” means that the function is not exported from any known x64 build but is exported from the x86 build of at least some version that has an x64 build. If it had already ceased as an export before Windows Server 2003 SP1, the “x86 only” is left unstated.
That a function is “discontinued in” some version means that the function is exported up to but not including the stated version and not in any later version unless “restored”.
It’s nothing but fair to note that the majority of these functions were not documented immediately. Even more were then or later said to require later versions. These misrepresentations of actual availability show also in C-language declarations for the functions’ use in programming. Conveying these differences between what the kernel exported and what Microsoft presented for drivers to import is the concern of columns headed Documentation History and Declaration History.
Conventions still in development!
While no DDK for Windows NT 3.50 is found for reference, the default assumption throughout the following table is that whatever is known about a function’s documentation or declarations from the DDK for Windows NT 3.51 can’t be said to have differed for version 3.50.
Many functions in these early versions may have got their first documentation or declaration because their use was specially anticipated for installable file system (IFS) drivers. Microsoft published a separate IFS Kit for these, apparently starting from Windows 2000. For Windows Vista, the IFS Kit was merged into the WDK. Between, there are known to have been IFS Kits for Windows XP and Windows Server 2003, but I have not obtained either for inspection. Where applicable DDK versions are left to the imprecision of “5.1 (IFS) to 6.0”, whatever is described is known from the IFS section of the WDK for Windows Vista and is excluded from the IFS Kit for Windows 2000 and from the ordinary DDK for all of Windows 2000, Windows XP and Windows Server 2003.
As much as I might like to condense into one table as much as might be imagined is possible to summarise about all these functions’ history of availability both in the binary and according to the documentation and headers, many functions both individually and in groups demand additional explanation in text. I therefore break the tabulation according to Microsoft’s scheme of prefixes for separate areas of functionality within the otherwise monolithic kernel. Each function has its own row in one table, but please be sure to check for explanatory text before and (more usually) after the table.
Function | Export History |
---|---|
CcGetLsnForFileObject |
Function | Export History | Documentation History | Declaration History |
---|---|---|---|
ExAcquireFastMutexUnsafe | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExAcquireResourceExclusiveLite | since 6.1, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExAcquireResourceSharedLite | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExAcquireSharedWaitForExclusive | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExAllocatePoolWithQuotaTag | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExAllocatePoolWithTag | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExConvertExclusiveToSharedLite | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExDeleteResourceLite | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExDisableResourceBoostLite | before 5.0 (IFS), undocumented;
before 5.1 (IFS) to 6.0, declared |
since 6.0, declared start is 5.0 | |
ExGetExclusiveWaiterCount | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExGetSharedWaiterCount | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExInitializeResourceLite | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExInterlockedAddLargeStatistic | x86 only | before 5.0, declared; since 6.1 revision, documented start is 5.0 |
|
ExInterlockedExtendZone | before 5.0, documented | since 5.1, deprecated; since 6.0, declared start is 5.0 |
|
ExIsResourceAcquiredExclusiveLite | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExIsResourceAcquiredSharedLite | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExReleaseFastMutexUnsafe | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExReleaseResourceForThreadLite | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
ExReleaseResourceLite | before 5.0, declared; since 6.1 revision, documented start is 5.0 |
since 6.0, declared start is 5.0 | |
ExfInterlockedAddUlong | x86 only | ||
ExfInterlockedInsertHeadList | x86 only | ||
ExfInterlockedInsertTailList | x86 only | ||
ExfInterlockedPopEntryList | x86 only | before 6.1, declared | |
ExfInterlockedPushEntryList | x86 only | before 6.1, declared | |
ExfInterlockedRemoveHeadList | x86 only | ||
Exfi386InterlockedDecrementLong | x86 only | in 6.0 only, reserved | |
Exfi386InterlockedExchangeUlong | x86 only | in 6.0 only, reserved | |
Exfi386InterlockedIncrementLong | x86 only | in 6.0 only, reserved |
The ExIsResourceAcquiredSharedLite function is another rarity that changes its prototype while documented. If changes from returning a USHORT to returning a ULONG in version 5.0, but the documentation doesn’t catch up until version 6.0.
Function | Documentation History | Declaration History |
---|---|---|
FsRtlAllocatePoolWithQuotaTag | before 5.0 (IFS), undocumented | |
FsRtlAllocatePoolWithTag | before 5.0 (IFS), undocumented | |
FsRtlNotifyFullChangeDirectory | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
FsRtlNotifyFullReportChange | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
FsRtlNotifyInitializeSync | before 5.0 (IFS), undocumented;
since 6.1, documented start is 5.0 |
since 6.0, declared start is 5.0 |
FsRtlNotifyUninitializeSync | before 5.0 (IFS), undocumented;
since 6.1, documented start is 5.0 |
since 6.0, declared start is 5.0 |
FsRtlSplitLargeMcb | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
FsRtlTruncateLargeMcb | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
FsRtlTruncateMcb | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
Function | Documentation History | Declaration History |
---|---|---|
IoAssignResources | before 5.0, documented | since 5.1, deprecated; since 6.0, declared start is 5.0 |
IoEnqueueIrp | ||
IoGetDeviceToVerify | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
IoGetFileObjectGenericMapping | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
IoGetInitialStack | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
IoGetRequestorProcess | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
IoGetTopLevelIrp | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
IoIsSystemThread | before 5.0 (IFS), undocumented;
before 5.1 (IFS) to 6.0, declared |
since 6.0, declared start is 5.0 |
IoPageRead | before 5.0 (IFS), undocumented;
before 5.1 (IFS) to 6.0, declared |
since 6.0, declared start is 5.0 |
IoSetDeviceToVerify | before 5.0 (IFS), undocumented;
before 5.1 (IFS) to 6.0, declared |
since 6.0, declared start is 5.0 |
IoSetTopLevelIrp | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
IoSynchronousPageWrite | before 5.0 (IFS), undocumented;
before 5.1 (IFS) to 6.0, declared |
since 6.0, declared start is 5.0 |
IoThreadToProcess | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
IofCallDriver | since 6.0, declared start is 5.0 | |
IofCompleteRequest | since 6.0, declared start is 5.0 |
Function | Export History | Documentation History | Declaration History |
---|---|---|---|
KeClearEvent | since 6.1 revision, documented start is 5.0 | ||
KeDeregisterBugCheckCallback | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
KeEnterCriticalRegion | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
KeFindConfigurationNextEntry | |||
KeInitializeQueue | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 | |
KeInsertQueue | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 | |
KeLoaderBlock (data) | |||
KeReadStateMutant | before 5.1 (IFS) to 6.0, undocumented | since 6.0, declared start is 5.0 | |
KeReadStateQueue | before 5.0 (IFS), undocumented;
before 5.1 (IFS) to 6.0, declared |
since 6.0, declared start is 5.0 | |
KeRegisterBugCheckCallback | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 | |
KeRemoveQueue | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 | |
KeSetEventBoostPriority | |||
KeTickCount (data) | x86 only | ||
KefAcquireSpinLockAtDpcLevel | x86 only | since 6.0, declared start is 5.0 | |
KefReleaseSpinLockFromDpcLevel | x86 only | before 2018, declared; since 6.1 revision, documented start is 5.0 |
since 6.0, declared start is 5.0 |
Documentation of KeDeregisterBugCheckCallback and KeRegisterBugCheckCallback is marked “This is preliminary documentation and subject to change” in the DDK for Windows XP.
Though KeEnterCriticalRegion and KeLeaveCriticalRegion plainly are a pair, the one needing always to be balanced by the other, one preceded the other as an exported function. It is here thought that KeEnterCriticalRegion existed in version 3.10 only as the same macro that Microsoft published in NTDDK.H for versions 3.51 up to and including 5.1 (presumably by oversight since it cannot compile without a definition of the KernelApcDisable member of the opaque KTHREAD).
What documentation I see online today, 17th September 2020, for KefReleaseSpinLockFromDpcLevel is dated 30th April 2018 as is most other online documentation since Microsoft’s reorganisation of it in terms of which headers declare which functions. Who knows when this documentation was written but its publication plausibly is just a side-effect of the reorganisation. What little is presented as Remarks is just for the long-documented KeReleaseSpinLockFromDpcLevel and the page has no partner for KefAcquireSpinLockAtDpcLevel. Still, documented it is.
Function | Documentation History | Declaration History |
---|---|---|
MmCanFileBeTruncated | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
MmDisableModifiedWriteOfSection | ||
MmIsRecursiveIoFault | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
MmIsThisAnNtAsSystem | before 5.2 SP1, documented | since 6.0, declared start is 5.0 |
MmLockPagableImageSection | ||
MmMapMemoryDumpMdl | ||
MmUnlockPagableImageSection | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
Documentation of MmIsThisAnNtAsSystem as obsolete is qualified: even now in 2020 it is “obsolete for Windows XP and later versions”.
Function | Documentation History |
---|---|
NlsMbOemCodePageTag (data) | |
NlsOemLeadByteInfo (data) | before 5.0 (IFS), undocumented |
Both NlsMbOemCodePageTag and NlsOemLeadByteInfo are declared through macros—NLS_MB_OEM_CODE_PAGE_TAG and NLS_OEM_LEAD_BYTE_INFO, respectively—but neither is known to have ever been documented.
The functions whose names begin with Nt correspond closely to functions whose names have the Zw prefix instead (see below). Put aside some general points about how the two differ—see The Native API— and documentation of an Nt function is to a large extent implied by documentation of the corresponding Zw function.
Though this correspondence will have been understood well enough by all competent kernel-mode programmers, Microsoft didn’t make it explicit until some time after releasing the WDK for Windows Vista. This is here taken as an intention to leave the Nt functions undocumented (if not declared) before version 6.1.
Documentation in the WDK for Windows 7 gives each Nt function its own page and directs attention to the page for the corresponding Zw function. The Zw documentation might then be treated as counting for both, except that the Nt documentation warns expressly “Do not call this routine from kernel-mode code.” This is here taken as documenting the Nt functions as reserved in version 6.1 (certainly for kernel-mode use, which is this survey’s focus).
Microsoft loosened the text significantly for Windows 8 to note that the Nt and Zw versions “can behave differently” and to refer to a page of guidance. These changes, though slight, are taken here as formally permitting the Nt functions’ kernel-mode use, such that they must now be counted as documented (though delayed).
While each Nt function is documented only by reference to the Zw function, whatever documented availability Microsoft gives for the latter is here taken as intended also for the former. In the headers, however, the two functions necessarily each have their own declaration (if they have any), and so any “declared start” shown below is specifically for the Nt function.
Function | Documentation History | Declaration History |
---|---|---|
NtDeleteFile | before 6.1, undocumented; documented start is 5.1; before 6.2, reserved |
not declared |
NtOpenProcess | before 6.1, declared; since 6.1 revision, documented start is 5.0; before 6.2, reserved |
|
NtQueryInformationProcess |
Function | Export History | Documentation History | Declaration History |
---|---|---|---|
ObGetObjectPointerCount | discontinued in 5.1 | before 5.0 (IFS), undocumented | |
ObMakeTemporaryObject | before 5.0 (IFS), undocumented;
before 5.1 (IFS) to 6.0, declared |
since 6.0, declared start is 5.0 | |
ObfDereferenceObject | since 6.0, declared start is 5.0 |
Function | Documentation History | Declaration History |
---|---|---|
PsGetProcessExitTime | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
PsIsThreadTerminating | before 5.0 (IFS), undocumented;
since 6.1, documented start is 5.0 |
since 6.0, declared start is 5.0 |
PsLookupProcessThreadByCid | ||
PsSetCreateProcessNotifyRoutine | before 4.0, undocumented; before 5.0, declared; since 6.1 revision, documented start is 5.0 |
since 6.0, declared start is 5.0 |
Function | Documentation History | Declaration History |
---|---|---|
RtlCompressBuffer | before 5.1 (IFS) to 6.0, undocumented;
before 6.1, reserved; since 6.1, documented start is 5.1 |
since 6.0, declared start is 5.1 |
RtlDecompressBuffer | before 5.1 (IFS) to 6.0, undocumented;
before 6.1, reserved; since 6.1, documented start is 5.1 |
since 6.0, declared start is 5.1 |
RtlDecompressFragment | before 5.1 (IFS) to 6.0, undocumented;
before 6.1, reserved; since 6.1, documented start is 5.1 |
since 6.0, declared start is 5.1 |
RtlDowncaseUnicodeString | before 5.0 (IFS), undocumented | since 6.0, declared start is 5.0 |
RtlGetCompressionWorkSpaceSize | before 5.1 (IFS), undocumented;
before 6.1, reserved; since 6.1, documented start is 5.1 |
since 6.0, declared start is 5.1 |
RtlxAnsiStringToUnicodeSize | before 6.0, declared; since 6.1 revision, documented start is 5.0 |
since 6.0, declared start is 5.0 |
RtlxOemStringToUnicodeSize | before 5.0 (IFS), undocumented;
before 6.1, declared |
since 6.0, declared start is 5.0 |
RtlxUnicodeStringToAnsiSize | before 5.0, undocumented; since 6.1 revision, documented start is 5.0 |
since 6.0, declared start is 5.0 |
RtlxUnicodeStringToOemSize | before 5.0 (IFS), undocumented;
before 6.1, declared |
since 6.0, declared start is 5.0 |
Function | Documentation History | Declaration History |
---|---|---|
SeValidSecurityDescriptor | before 5.0, declared; since 6.1 revision, documented start is 5.0 |
since 6.0, declared start is 5.0 |
Function | Documentation History | Declaration History |
---|---|---|
ZwConnectPort | in 5.1 (IFS) to 6.0, declared | in 6.0, declared start is 6.0 |
ZwCreateEvent | before 5.0 (IFS), undocumented;
before 5.1 (IFS), declared; documented start is 5.1 |
since 6.0, declared start is 5.0 |
ZwDeleteFile | before 5.1 (IFS), undocumented;
documented start is 5.1 |
since 6.0, declared start is 5.0 |
ZwFlushInstructionCache | ||
ZwFsControlFile | before 5.1 (IFS) to 6.0, undocumented;
since 6.1 revision, documented start is 5.0 |
since 6.0, declared start is 5.0 |
ZwOpenEvent | before 6.0, undocumented; documented start is 5.2 |
since 6.0, declared start is 5.2 |
ZwQueryDirectoryFile | before 5.0 (IFS), undocumented;
since 5.1 (IFS), documented start is 5.1 |
before 5.1 (IFS), not declared; since 6.0, declared start is 5.0 |
ZwQuerySection | ||
ZwRequestWaitReplyPort | in 5.1 (IFS) to 6.0, declared | in 6.0, declared start is 5.0 |
ZwSetEvent | before 5.0 (IFS), undocumented;
before 5.1 (IFS), declared; documented start is 5.1 |
since 6.0, declared start is 5.0 |
ZwSetInformationFile | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
ZwSetInformationThread | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
ZwWaitForSingleObject | before 5.0 (IFS), undocumented;
before 5.1 (IFS), declared; documented start is 5.1 |
since 6.0, declared start is 5.0 |
Though ZwQueryDirectoryFile is documented in the Windows 2000 IFS Kit, it comes with a warning in red that “This is preliminary documentation and subject to change” and the NTIFS.H from the same kit does not declare the function. Presumably, the documentation was settled in time for the Windows XP IFS Kit and Microsoft has ever since meant that Windows XP is when the function became documented for use. A declaration was perhaps also settled on as early as the Windows XP IFS Kit. Certainly, a declaration is presented in the WDK for Windoiws Vista, but with a conditional-compilation block that doesn’t agree with the documentation.
Function | Export History | Documentation History | Declaration History |
---|---|---|---|
_abnormal_termination | x86 only | before 2012, declared | |
_global_unwind2 | x86 only | ||
_purecall | before 2012, undocumented | not declared | |
_snprintf | |||
_snwprintf | |||
_strlwr | |||
_strupr | |||
_wcsicmp | |||
atoi | |||
atol | |||
isdigit | |||
islower | |||
isprint | |||
isspace | |||
isupper | |||
isxdigit | |||
mbstowcs | |||
memchr | |||
memcpy | |||
memmove | |||
memset | |||
qsort | |||
rand | |||
srand | |||
strchr | |||
strncmp | |||
strrchr | |||
swprintf | |||
tolower | |||
toupper | |||
vsprintf | |||
wcscat | |||
wcscmp | |||
wcsncmp | |||
wcsncpy | |||
wcsrchr |
Visual Studio documentation has long documented the _abnormal_termination function indirectly as AbnormalTermination. Whether this is presented as a macro or is said to be an “intrinsic function”, it is documented for use in the __finally block of a termination handler. Documentation for Visual Studio 2012 gives the function its own page but is clear that it “is not intended to be called from user code.” This is here taken as reason to count the function (not the macro) as reserved.
The _global_unwind2 function has long been an internal routine for the CRT library’s implementation of several functions: _except_handler2 (already exported from the version 3.10 kernel); its successors (of which _except_handler3 is an x86-only export for version 5.0 and higher); and the documented CRT function longjmp (which is not a kernel export for any x86 build of any version). The version 3.10 kernel has it but does not export it. Why it ever got exported in kernel mode is not known. It anyway is not known ever to have been documented, not only as an export from the kernel but even as an implementation detail of Microsoft’s CRT library. That said, it is named on a page of Internal CRT Globals and Functions, which seems to have been prepared for Visual Studio 2015.
Microsoft’s C++ compiler generates references to the _purecall function when a virtual function table is emitted for a base class that has any pure virtual member function. The first explicit documentation that I know of is that the function has its own page in the Alphabetical Function Reference within the C Run-Time Library Reference for Visual Studio 2012.
If only for cross-referencing, note that a dozen of the kernel’s original exports do not survive to version 3.50:
None had yet been documented. Four were sooner (version 3.50) or later (5.0) documented as obsolete, one as reserved. For who knows what reason, this pruning temporarily removed ProbeForRead—but not its close companion, ProbeForWrite—from use by external callers such as drivers who surely would have valued it for validating parameters received from user-mode callers. It doesn’t return to the interface until version 5.0, but at least then it got documented.