Geoff Chappell - Software Analyst
The table below lists the 69 exports from the HAL in version 3.10. These functions (and one variable) are in effect the original programming interface for the HAL. They represent nearly three quarters of all HAL exports that have ever existed. All but a handful are still exported as of version 10.0. Just over a half of these original exports are documented, though mostly as obsolete or reserved.
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.
Function | Export History | Documentation History | Declaration History |
---|---|---|---|
HalAcquireDisplayOwnership | x64 since 2004, forwarded to kernel | before 6.0, declared | since 5.2, deprecated since 6.0, declared start is 5.0 |
HalAllocateAdapterChannel | x64 since 2004, forwarded to kernel | before 3.50 to 3.51, undocumented before 6.0, declared |
since 5.2, deprecated since 6.0, declared start is 5.0 |
HalAllocateCommonBuffer | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
HalBeginSystemInterrupt | x86 only | ||
HalCalibratePerformanceCounter | x64 since 2004, forwarded to kernel | ||
HalDisableSystemInterrupt | discontinued in 6.0 | ||
HalDisplayString | x64 since 2004, forwarded to kernel | ||
HalEnableSystemInterrupt | discontinued in 6.0 | ||
HalEndSystemInterrupt | x86 only | ||
HalFlushCommonBuffer | x64 since 2004, forwarded to kernel | ||
HalFreeCommonBuffer | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
HalGetAdapter | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
HalGetBusData | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
HalGetEnvironmentVariable | x64 since 2004, forwarded to kernel | ||
HalGetInterruptVector | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
HalHandleNMI | x64 since 2004, forwarded to kernel | ||
HalInitSystem | x64 since 2004, forwarded to kernel | ||
HalInitializeProcessor | x64 since 2004, forwarded to kernel | ||
HalMakeBeep | x64 since 2004, forwarded to kernel | before 5.0, undocumented before 6.0, declared |
since 5.2, deprecated since 6.0, declared start is 5.0 |
HalQueryDisplayParameters | x64 since 2004, forwarded to kernel | ||
HalQueryRealTimeClock | x64 since 2004, forwarded to kernel | ||
HalReadDmaCounter | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
HalReportResourceUsage | x64 since 2004, forwarded to kernel | ||
HalRequestIpi | x64 since 2004, forwarded to kernel | ||
HalRequestSoftwareInterrupt | x64 since 2004, forwarded to kernel | ||
HalReturnToFirmware | x64 since 2004, forwarded to kernel | before 6.1, undocumented before 6.2, documented start is 5.1 since 6.2, documented start is 5.2 |
not declared, except in “minwin” |
HalSetDisplayParameters | x64 since 2004, forwarded to kernel | ||
HalSetEnvironmentVariable | x64 since 2004, forwarded to kernel | ||
HalSetProfileInterval | x64 since 2004, forwarded to kernel | ||
HalSetRealTimeClock | x64 since 2004, forwarded to kernel | ||
HalStartNextProcessor | x64 since 2004, forwarded to kernel | ||
HalStartProfileInterrupt | x64 since 2004, forwarded to kernel | ||
HalStopProfileInterrupt | x64 since 2004, forwarded to kernel | ||
HalTranslateBusAddress | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
The particularities of how the few Hal functions that have ever been documented (and some of the Io functions too) became obsolete or reserved are a separate story. Here it must suffice to note that starting with the DDK for Windows 2000 most of these functions are replaced by inline definitions, and some are not declared at all, depending on macros USE_DMA_MACROS and NO_LEGACY_DRIVERS.
The whole documentation of most functions that are shown above as reserved is just that the name is in a list, but HalReturnToFirmware has its own page with a prototype and rudimentary description. Indeed, it’s not explicitly reserved, but is instead said to be “not supported and should not be used.” While splitting hairs, note that its documentation in the WDK for Windows 7 says the function is “Available in Microsoft Windows Server 2003 and Windows XP.” Whether this is meant to exclude the function’s continuation to Windows Vista and beyond is not known. The WDK for Windows 8 explicitly allows later versions, but somehow for the price that the function is no longer available on Windows XP.
Function | Export History | Documentation History | Declaration History |
---|---|---|---|
IoAssignDriveLetters | discontinued in 6.1 |
||
IoFlushAdapterBuffers | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
IoFreeAdapterChannel | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
IoFreeMapRegisters | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
IoMapTransfer | x64 since 2004, forwarded to kernel | before 5.0, documented | since 5.1, deprecated since 6.0, declared start is 5.0 |
IoReadPartitionTable | x64 since 2004, forwarded to kernel | before 5.1, documented | since 5.1, deprecated since 6.0, declared start is 5.1 |
IoSetPartitionInformation | x64 since 2004, forwarded to kernel | before 5.1, documented | since 5.1, deprecated since 6.0, declared start is 5.1 |
IoWritePartitionTable | x64 since 2004, forwarded to kernel | before 5.1, documented | since 5.1, deprecated since 6.0, declared start is 5.1 |
Starting with version 5.1, IoAssignDriveLetters (only to version 6.0), IoReadPartitionTable, IoSetPartitionInformation and IoWritePartitionTable are also exported from the kernel. The HAL’s implementations are just stubs that call the corresponding but substantial implementations in the kernel. Stubs, in contrast to forwards, are needed for the x86 architecture because the HAL and kernel functions have different calling conventions: __stdcall and __fastcall, respectively. Though this need does not apply to the x64 architecture, no special case was made for forwarding the x64 functions until Version 2004 has the x64 HAL forward all its exports to the kernel.
Function | Export History |
---|---|
KdComPortInUse (data) | x64 since 2004, forwarded to kernel |
KdPortGetByte | discontinued in 5.1 |
KdPortInitialize | discontinued in 5.1 |
KdPortPollByte | discontinued in 5.1 |
KdPortPutByte | discontinued in 5.1 |
KdPortRestore | discontinued in 5.1 |
KdPortSave | discontinued in 5.1 |
The HAL’s role in debugging the kernel through a serial port ceased when Windows XP allowed IEEE1394 as a significantly faster alternative. The work was separated to a replacable module whose internal name is KDCOM.DLL even if a different filename is chosen by the loader from a boot option. The kernel imports functions from this module instead of from the HAL. The HAL functions that earlier kernels had called, and which ought never to have been called except from the kernel, were dropped. The exported variable, however, presented a compatibility problem. Though KdComPortInUse never was formally documented, nor declared in any DDK header, Microsoft had long published sample code that shows the variable’s use—indeed, its all-but-necessary use—by serial drivers such as might be written by arbitrary non-Microsoft programmers. Its exporting has needed to continue.
Function | Export History | Documentation History | Declaration History |
---|---|---|---|
KeAcquireSpinLock | x86 only; since 6.2, forwarded to kernel |
since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
KeFlushWriteBuffer | x64 since 2004, forwarded to kernel | before 5.1, declared | |
KeGetCurrentIrql | x86 only | since 6.1 revision, documented start is 5.0 | |
KeLowerIrql | x86 only | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
KeQueryPerformanceCounter | x64 since 2004, forwarded to kernel | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
KeRaiseIrql | x86 only | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
KeReleaseSpinLock | x86 only; since 6.2, forwarded to kernel |
since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
KeStallExecutionProcessor | x64 since 2004, forwarded to kernel | since 6.1 revision, documented start is 5.0 | since 6.0, declared start is 5.0 |
Though the Interrupt Request Level (IRQL) is fundamental to kernel-mode programming, it is originally the business of the HAL, not the kernel. Functions that raise, lower or get the IRQL started as HAL exports and remain so for the x86. The x64 processor, however, has built-in support for the IRQL through the cr8 register. The x64 functions that work with the IRQL have only ever been exported from the kernel, not the HAL.
Whether the IRQL is controlled by the HAL or the kernel affects a division of functionality for the spin lock. Acquiring and releasing a spin lock can have two parts to it: the synchronisation itself, necessarily, and a change of IRQL, possibly. On the x64, both are the kernel’s work, which means again that x64 functions for spin locks have only ever been exported from the kernel, not the HAL. The x86 division of labour is that the kernel handles the synchronisation itself but leaves the changes of IRQL to the HAL. The original division of functionality is that the generality is with the HAL. The KeAcquireSpinLock and KeReleaseSpinLock functions may change the IRQL and are exported from the HAL, which calls the kernel to handle the synchronisation. Windows 8 changes this division so the generality is with the kernel. All functions that work with these synchronisation objects are exported from the kernel, which calls the HAL for changing the IRQL. The HAL’s exports for the general work remain, but not as implemented functions: they continue only as forwards to the kernel.
Not since ancient times do x86 drivers import the Ke functions that raise or lower the Interrupt Request Level (IRQL) whether directly or while acquiring or releasing a spin lock. These are well known to be redirected by macros to the Kf variants, plausibly as early as the DDK for Windows NT 3.50 (which is not yet obtained for reference). The macros depend on their targets’ declarations, of course.
Function | Export History | Documentation History |
---|---|---|
READ_PORT_BUFFER_UCHAR | x86 only | since 6.2, documented start is 5.0 |
READ_PORT_BUFFER_ULONG | x86 only | since 6.2, documented start is 5.0 |
READ_PORT_BUFFER_USHORT | x86 only | since 6.2, documented start is 5.0 |
READ_PORT_UCHAR | x86 only | since 6.2, documented start is 5.0 |
READ_PORT_ULONG | x86 only | since 6.2, documented start is 5.0 |
READ_PORT_USHORT | x86 only | since 6.2, documented start is 5.0 |
WRITE_PORT_BUFFER_UCHAR | x86 only | since 6.2, documented start is 5.0 |
WRITE_PORT_BUFFER_ULONG | x86 only | since 6.2, documented start is 5.0 |
WRITE_PORT_BUFFER_USHORT | x86 only | since 6.2, documented start is 5.0 |
WRITE_PORT_UCHAR | x86 only | since 6.2, documented start is 5.0 |
WRITE_PORT_ULONG | x86 only | since 6.2, documented start is 5.0 |
WRITE_PORT_USHORT | x86 only | since 6.2, documented start is 5.0 |
The READ_PORT and WRITE_PORT functions have x64 support as inlined routines defined in WDM.H. Exported or not, they abstract the reading of I/O registers in I/O space. The kernel exports counterparts that do the same but from memory space. All have been documented from the start under some such heading as Hardware Abstraction Layer Routines which may be just separate enough that they were missed when a revision of the WDK for Windows 7 spuriously dated to Windows 2000 all the other ancient documented (but not yet obsolete) functions. Of course this was “fixed” in the very next WDK.