HVGDK_MINI.H

The public symbol file NTKRPAMP.PDB for the original release of Windows 10 tells that the kernel is built with the HVGDK_MINI.H header at

d:\th.public.fre\internal\minwin\priv_sdk\inc

and draws from it the following type definitions:

Line Number Type
449 union _HV_PARTITION_PRIVILEGE_MASK
717 struct _HV_X64_HYPERVISOR_FEATURES

The header HVGDK_MINI.H is not known in any Device Driver Kit (DDK) or Windows Driver Kit (WDK). There was, however, an HVGDK.H in the WDK for Windows 7. It defines the HV_PARTITION_PRIVILEGE_MASK at line 2653. That’s no small difference. It may mean that the reduction suggested by the MINI suffix was of thousands of lines. More likely, though, is that separating material to another header brought with it a substantial rearrangement.

Anti-Trust Settlement Forensics

For the record, Microsoft’s possibly accidental inclusion of private symbol files for URLMON.DLL in downloadable packages of public symbols shows that many more types were accessible to the source code for URLMON.DLL from including HVGDK_MINI.H when building for the original release of 32-bit Windows 10:

Line Number Type
431 struct _HV_HYPERVISOR_VERSION_INFO
449 union _HV_PARTITION_PRIVILEGE_MASK
565 union _HV_X64_PLATFORM_CAPABILITIES
650 enum _HV_CPUID_FUNCTION
689 struct _HV_VENDOR_AND_MAX_FUNCTION
700 struct _HV_HYPERVISOR_INTERFACE_INFO
717 struct _HV_X64_HYPERVISOR_FEATURES
811 struct _HV_X64_ENLIGHTENMENT_INFORMATION
885 struct _HV_IMPLEMENTATION_LIMITS
917 struct _HV_X64_HYPERVISOR_HARDWARE_FEATURES
960 struct _HV_X64_HYPERVISOR_CPU_MANAGEMENT_FEATURES
1062 struct _HV_HYPERVISOR_SVM_FEATURES
1089 union _HV_CPUID_RESULT
1101 unnamed struct for VersionAndFeatures in
union _HV_CPUID_RESULT

None of these types are known from headers that Microsoft publishes for either kernel-mode or user-mode programming for Windows 10 by programmers outside Microsoft. Most were not yet defined for Windows 7 and therefore were not published even in the short-lived HVGDK.H. Indeed, most are not disclosed even as type information in other symbol files except for the Windows 8.1 kernel. Aside from the curiosity of their appearance for just one version, there is also that the symbol files for the Windows 8.1 kernel have type information for one enumeration that the symbol files for the Windows 8.1 URLMON do not. This is the HV_HYPERVISOR_INTERFACE. How this happened is not known: more research is required.

The point to singling out URLMON.DLL is of course that it is part of Internet Explorer. It was first distributed with Internet Explorer. Even for Windows 10 its version numbering still follows that of Internet Explorer. Microsoft defended an anti-trust suit that was largely motivated by complaints that Microsoft’s development and distribution of Internet Explorer in competition with other web browsers benefited from Microsoft’s monopoly control of the operating system that these web browsers run on. Among the complaints is that Microsoft’s programmers of Internet Explorer had access to programming resources for Windows that were not available to the programmers of competing web browsers. Plainly they did!

Whether such access got Internet Exlorer any direct benefit is another question. Whether it got an indirect benefit, as with faster or easier development just from knowing more than was explicitly used, is also another question. The evidence here is just that they did have the alleged access and still had it many years after the supposed enforcement of a settlement that ought to have seen the access removed. Either that or the access has been arranged since, which some would say is worse for its surely deliberate contempt of the settlement.

Related Headers

The published symbol files for URLMON.DLL also suggest a little of how HVGDK_MINI.H comes to exist. As noted above, Microsoft published an HVGDK.H for Windows 7 but never for any later version. Also described above from symbol files for Windows 8 and higher, some types that are defined in the Windows 7 HVGDK.H are later defined in HVGDK_MINI.H. The natural supposition is that HVGDK_MINI.H was extracted from HVGDK.H, but does the latter still exist and is the former the only extract? The answers look to be yes and no, respectively.

Symbol files for URLMON.DLL in Windows 8 and higher confirm the continued existence of a header named HVGDK.H and the existence of an otherwise unknown HVGDK_EXT.H. These are not in the same directory as HVGDK_MINI.H. For the original Windows 10, they are instead at

d:\th.public.fre\internal\vm\inc

as if to suggest they are specialised to a “vm” project, separate from the “minkernel” and not as any sort of SDK, private or otherwise. No type definitions are reported from these headers and it may indeed be that URLMON.DLL would be no different if built without access to these headers. What is reported is that the two paths that have the various HVGDK headers are named in -I switches that are given to the compiler only when building source files while the current directory is

d:\th\inetcore\lib\common\iel1_sp

The source files are all in this directory’s parent: strcmpii.cpp, ieisos_sp.cpp, easyclassfactory.cpp, brproc.cpp, handlehelpers.cpp, dxhardwaredenylist.cpp, dxgiadapterwrapper.cpp, gcount.cpp, lrieutil.cpp, privacieutil.cpp, ieprocesshelper.cpp, strutil.cpp, hashtable.cpp, iecrypt.cpp, ieverdetect.cpp, ieisos_phonentimpl.cpp, cmptime.cpp, useraccess.cpp, idllib.cpp, ishost_sp.cpp and arrayimpl.cpp.

The point to the tedium of listing them, aside from noticing that several are plainly named for Internet Explorer, is that this—meaning their names and their inclusion of system-level headers that aren’t generally available to the programmers of web browsers—is what can be learnt from forensic analysis of an Internet Explorer DLL at the distance of having only the symbol files. For supervising Microsoft’s compliance with the anti-trust settlement, the Technical Committee had source code. Whatever this supervision achieved, however it was conducted, it evidently did not establish at Microsoft any persistent caution that Microsoft’s web browser in competition with others must not have the anti-competitive advantage of being programmed with access to definitions for Microsoft’s monopoly product that are withheld from the competitors. It might not be too cynical to suspect that what was established at Microsoft is an attitude that inevitably inadequate supervision lets Microsoft get away with pretty much whatever it wants.

There is here an enduring lesson for governments: advanced technology might still be influenced through business, legal and political mechanisms but it is too advanced for enforcement. Probably everyone knows, but it’s as well to have a record.

Other Forensics

The most complete catalogue that I know of types defined in HVGDK_MINI.H is from type information not in any symbol files but in a statically linked library. That object files and libraries (which are essentially archives of object files) can have type information is often overlooked, even by experts at reverse engineering. Type information is retained in only very few libraries that Microsoft publishes for programmers to link their code to. It seems fair to suspect that almost all cases, especially in any WDK or Software Development Kit (SDK), are oversights. Still, they are as openly published as are any symbol files that Microsoft publishes as debugging support. In some ways type information in libraries is better than in symbol files, and in some ways worse. Their forensic value is less because the libraries are typically developed separately from the operating system. Type information in a library is immaterial to the library’s role as supplier of code for a linker’s resolution of external references. Even in a library that is clearly targeted to one version of the operating system, its type information can be a long way out of date, and often is. Against this is that type information in a library or object file is sometimes—rarely, but sometimes—much more extensive than in symbol files because there hasn’t yet been any selection according to use.

Two statically linked libraries in open distribution are known to have type information from compiling HVGDK_MINI.H. One is relatively recent, only for Windows 10 but continuing at least to the 2004 release, and has obvious relevance to the Hypervisor. It is named KDHV.LIB. Microsoft distributes it among the programming samples in the package of Debugging Tools for Windows. If only for the version that targets the original Windows 10, its type information from HVGDK_MINI.H comes from compiling two source files. Their names, kdhvintel.c and kdhvhc.c, likely don’t matter. What does is that the type information is already selected according to what the compiler used for each object. What used means in this context can be surprising, but the essential point is that although the private symbols in this library cover many more hypervisor types than do the public symbols for the kernel, the library is not much of a gold mine.

The other library is. It is named CLFSMGMT.LIB. That it has no obvious relevance to any hypervisor may be why it seems to have escaped the attention of most researchers (including me in 2016 when I first wrote about Hyper-V support). Yet this library knows of HVGDK_MINI.H as far back as Windows Vista—curiously without knowing of HVGDK.H even in the library’s versions for Windows 7. This is a very odd library. Microsoft distributes it only with the SDK, not the WDK. The Windows 10 SDK even puts it in a subdirectory named “um” as if to make explicit that it’s for user-mode programming. Yet the library has kernel-mode code to support the CLFS.SYS file system driver. This mixture of modes may explain the curious way it got built. Still, take its publication as a gift.

What makes CLFSMGMT.LIB a gold mine for hypervisor studies is that its type information from HVGDK_MINI.H comes from precompilation. This type information is therefore not of types that have got used but of types that might get used. Speaking again of the version for the original Windows 10, just for concreteness, the library archives five objects. Four are compiled from C++ source files that are particular to the library’s contribution to its project. Again the names likely don’t matter: public_interface.cpp, managed_log.cpp, managed_client.cpp and log_collection.cpp. Each is compiled using a pre-compiled header. The fifth object in the library, stdpch.obj, is what was precompiled from a (pre-processed) C++ source file named pch_hdr.src to use for the other source files where they would #include stdpch.h.

The lesson here goes several ways. For programmers, even at Microsoft, understand that if you throw everything but the kitchen sink into a precompiled header that you create by compiling a source file into an object file, then the object file contains pretty much everything but the kitchen sink! If the project was to build a library of archived object files, then be sure to exempt this object file from the archive—well, unless you really do mean that reverse engineers should have everything but the kitchen sink. For commentators on reverse engineering, especially if taking the line that information supposedly found by reverse engineering couldn’t possibly have been found without source code, please think a little more about what some techniques of building from source code may let slip into the finished product. For reverse engineers, remember that symbol files aren’t everything. Even a software manufacturer as careful as Microsoft sometimes builds the software in ways that reveal far more than intended.

The table that follows is of user-defined types (classes, enumerations, structures and unions) for which the CLFSMGMT.LIB from the SDK for the original release of Windows 10 shows the type as defined in HVGDK_MINI.H:

Line Number Type
82 union _HV_UINT128
84 anonymous struct in
union _HV_UINT128
97 struct _HV_UINT256
108 struct _HV_UINT512
326 enum _HV_HYPERVISOR_INTERFACE
341 enum _HV_SERVICE_BRANCH
369 enum _HV_GUEST_OS_VENDOR
375 enum _HV_GUEST_OS_MICROSOFT_IDS
386 enum _HV_GUEST_OS_OPENSOURCE_IDS
401 union _HV_GUEST_OS_ID_CONTENTS
404 anonymous struct in
union _HV_GUEST_OS_ID_CONTENTS
417 unnamed struct for OpenSource in
union _HV_GUEST_OS_ID_CONTENTS
431 struct _HV_HYPERVISOR_VERSION_INFO
449 union _HV_PARTITION_PRIVILEGE_MASK
452 anonymous struct in
union _HV_PARTITION_PRIVILEGE_MASK
565 union _HV_X64_PLATFORM_CAPABILITIES
567 anonymous struct in
union _HV_X64_PLATFORM_CAPABILITIES
650 enum _HV_CPUID_FUNCTION
689 struct _HV_VENDOR_AND_MAX_FUNCTION
700 struct _HV_HYPERVISOR_INTERFACE_INFO
717 struct _HV_X64_HYPERVISOR_FEATURES
811 struct _HV_X64_ENLIGHTENMENT_INFORMATION
885 struct _HV_IMPLEMENTATION_LIMITS
917 struct _HV_X64_HYPERVISOR_HARDWARE_FEATURES
960 struct _HV_X64_HYPERVISOR_CPU_MANAGEMENT_FEATURES
1062 struct _HV_HYPERVISOR_SVM_FEATURES
1089 union _HV_CPUID_RESULT
1091 anonymous struct in
union _HV_CPUID_RESULT
1101 unnamed struct for VersionAndFeatures in
union _HV_CPUID_RESULT
1157 union _HV_X64_MSR_HYPERCALL_CONTENTS
1160 anonymous struct in
union _HV_X64_MSR_HYPERCALL_CONTENTS
1183 union _HV_REGISTER_VP_ASSIST_PAGE
1186 anonymous struct in
union _HV_REGISTER_VP_ASSIST_PAGE
1316 union _HV_X64_MSR_RESET_CONTENTS
1319 anonymous struct in
union _HV_X64_MSR_RESET_CONTENTS
1358 struct _HV_VIRTUAL_APIC_ASSIST
1360 anonymous union in
struct _HV_VIRTUAL_APIC_ASSIST
1363 anonymous struct in
anonymous union in
struct _HV_VIRTUAL_APIC_ASSIST
1373 enum _HV_CALL_CODE
1979 union _HV_HYPERCALL_INPUT
1984 anonymous struct in
union _HV_HYPERCALL_INPUT
1999 union _HV_HYPERCALL_OUTPUT
2004 anonymous struct in
union _HV_HYPERCALL_OUTPUT
2031 union _HV_GVA_RANGE_SIMPLE
2035 anonymous struct in
union _HV_GVA_RANGE_SIMPLE
2052 union _HV_GVA_RANGE_EXTENDED
2056 anonymous struct in
union _HV_GVA_RANGE_EXTENDED
2078 anonymous struct in
union _HV_GVA_RANGE_EXTENDED
2108 union _HV_GVA_RANGE
2146 struct _HV_INPUT_FLUSH_VIRTUAL_ADDRESS_SPACE_HEADER
2160 struct _HV_INPUT_FLUSH_VIRTUAL_ADDRESS_SPACE
2171 struct _HV_INPUT_FLUSH_VIRTUAL_ADDRESS_LIST
2181 struct _HV_OUTPUT_GET_PARTITION_ID
2192 struct _HV_INPUT_SEND_SYNTHETIC_CLUSTER_IPI
2244 union _HV_X64_MSR_REFERENCE_TSC_CONTENTS
2247 anonymous struct in
union _HV_X64_MSR_REFERENCE_TSC_CONTENTS
2266 struct _HV_REFERENCE_TSC_PAGE
2302 enum _HV_INTERRUPT_TYPE
2339 union _HV_SYNIC_SINT
2342 anonymous struct in
union _HV_SYNIC_SINT
2407 enum _HV_ARCHITECTURE
2415 struct _HV_X64_SEGMENT_REGISTER
2420 anonymous union in
struct _HV_X64_SEGMENT_REGISTER
2422 anonymous struct in
anonymous union in
struct _HV_X64_SEGMENT_REGISTER
2439 struct _HV_X64_TABLE_REGISTER
2453 union _HV_X64_XSAVE_XFEM_REGISTER
2457 anonymous struct in
union _HV_X64_XSAVE_XFEM_REGISTER
2463 anonymous struct in
union _HV_X64_XSAVE_XFEM_REGISTER
2477 struct _HV_X64_XSAVE_HEADER
2503 union _HV_X64_FP_CONTROL_STATUS_REGISTER
2506 anonymous struct in
union _HV_X64_FP_CONTROL_STATUS_REGISTER
2514 anonymous union in
anonymous struct in
union _HV_X64_FP_CONTROL_STATUS_REGISTER
2519 anonymous struct in
anonymous union in
anonymous struct in
union _HV_X64_FP_CONTROL_STATUS_REGISTER
2528 union _HV_X64_XMM_CONTROL_STATUS_REGISTER
2531 anonymous struct in
union _HV_X64_XMM_CONTROL_STATUS_REGISTER
2533 anonymous union in
anonymous struct in
union _HV_X64_XMM_CONTROL_STATUS_REGISTER
2538 anonymous struct in
anonymous union in
anonymous struct in
union _HV_X64_XMM_CONTROL_STATUS_REGISTER
2549 union _HV_X64_FP_REGISTER
2552 anonymous struct in
union _HV_X64_FP_REGISTER
2561 union _HV_X64_FP_MMX_REGISTER
2573 union _HV_X64_FX_REGISTERS
2575 anonymous struct in
union _HV_X64_FX_REGISTERS
2604 union _HV_X64_X_REGISTERS
2606 anonymous struct in
union _HV_X64_X_REGISTERS
2612 anonymous union in
anonymous struct in
union _HV_X64_X_REGISTERS
2645 union _HV_X64_XSAVE_AREA
2651 struct _HV_X64_CONTEXT
2779 anonymous union in
struct _HV_X64_CONTEXT
2800 struct _HV_ARM64_CONTEXT
2924 struct _HV_VP_CONTEXT
2938 anonymous union in
struct _HV_VP_CONTEXT
2950 struct _HV_X64_MSR_STIMER_CONFIG_CONTENTS
2952 anonymous union in
struct _HV_X64_MSR_STIMER_CONFIG_CONTENTS
2955 anonymous struct in
anonymous union in
struct _HV_X64_MSR_STIMER_CONFIG_CONTENTS
2979 union _HV_PORT_ID
2983 anonymous struct in
union _HV_PORT_ID
3002 enum _HV_MESSAGE_TYPE
3061 union _HV_SYNIC_SIMP
3064 anonymous struct in
union _HV_SYNIC_SIMP
3082 enum HV_EVENTLOG_TYPE
3094 struct _HV_EVENTLOG_MESSAGE_PAYLOAD
3106 union _HV_MESSAGE_FLAGS
3109 anonymous struct in
union _HV_MESSAGE_FLAGS
3120 struct _HV_MESSAGE_HEADER
3126 anonymous union in
struct _HV_MESSAGE_HEADER
3138 struct _HV_TIMER_MESSAGE_PAYLOAD
3150 struct _HV_MESSAGE
3153 anonymous union in
struct _HV_MESSAGE
3165 struct _HV_MESSAGE_PAGE
3176 union _HV_X64_MSR_NPIEP_CONFIG_CONTENTS
3179 anonymous struct in
union _HV_X64_MSR_NPIEP_CONFIG_CONTENTS
3227 struct _HV_INPUT_POST_DEBUG_DATA
3234 struct _HV_OUTPUT_POST_DEBUG_DATA
3239 struct _HV_INPUT_RETRIEVE_DEBUG_DATA
3246 struct _HV_OUTPUT_RETRIEVE_DEBUG_DATA
3253 struct _HV_DEBUG_NET_DATA
3271 struct _HV_INPUT_RESET_DEBUG_SESSION
3276 struct _HV_OUTPUT_RESET_DEBUG_SESSION
3300 union _HV_CRASH_CTL_REG_CONTENTS
3303 anonymous struct in
union _HV_CRASH_CTL_REG_CONTENTS
3336 union _HV_INPUT_VTL
3339 anonymous struct in
union _HV_INPUT_VTL
3351 struct _HV_INITIAL_VP_CONTEXT
3425 union _HV_ENABLE_PARTITION_VTL_FLAGS
3428 anonymous struct in
union _HV_ENABLE_PARTITION_VTL_FLAGS
3435 struct _HV_INPUT_ENABLE_PARTITION_VTL
3450 struct _HV_INPUT_DISABLE_PARTITION_VTL
3465 struct _HV_INPUT_ENABLE_VP_VTL
3480 struct _HV_INPUT_DISABLE_VP_VTL
3493 union _HV_VTL_RETURN_INPUT
3497 anonymous struct in
union _HV_VTL_RETURN_INPUT
3513 enum _HV_VTL_MBEC_MODE
3527 union _HV_REGISTER_VSM_VP_VTL_CONTROL
3530 anonymous struct in
union _HV_REGISTER_VSM_VP_VTL_CONTROL
3546 union _HV_REGISTER_VSM_CODE_PAGE_OFFSETS
3549 anonymous struct in
union _HV_REGISTER_VSM_CODE_PAGE_OFFSETS
3564 union _HV_REGISTER_VSM_PARTITION_STATUS
3567 anonymous struct in
union _HV_REGISTER_VSM_PARTITION_STATUS
3582 union _HV_REGISTER_VSM_VP_STATUS
3585 anonymous struct in
union _HV_REGISTER_VSM_VP_STATUS
3594 enum _HV_REGISTER_NAME
3601 union _HV_REGISTER_VSM_VINA
3604 anonymous struct in
union _HV_REGISTER_VSM_VINA
3640 union _HV_REGISTER_VSM_CAPABILITIES
3643 anonymous struct in
union _HV_REGISTER_VSM_CAPABILITIES
3663 union _HV_REGISTER_VSM_VP_SECURE_VTL_CONFIG
3666 anonymous struct in
union _HV_REGISTER_VSM_VP_SECURE_VTL_CONFIG
3681 union _HV_REGISTER_VSM_PARTITION_CONFIG
3684 anonymous struct in
union _HV_REGISTER_VSM_PARTITION_CONFIG
3696 enum _HV_VTL_ENTRY_REASON
3717 struct _HV_VP_VTL_CONTROL
3730 unnamed union for VinaStatus in
struct _HV_VP_VTL_CONTROL
3733 anonymous struct in
unnamed union for VinaStatus in
struct _HV_VP_VTL_CONTROL
3749 anonymous union in
struct _HV_VP_VTL_CONTROL
3751 anonymous struct in
anonymous union in
struct _HV_VP_VTL_CONTROL
3757 anonymous struct in
anonymous union in
struct _HV_VP_VTL_CONTROL
3775 struct _HV_VP_ASSIST_PAGE
4363 union _HV_EXPLICIT_SUSPEND_REGISTER
4366 anonymous struct in
union _HV_EXPLICIT_SUSPEND_REGISTER
4369 anonymous struct in
union _HV_EXPLICIT_SUSPEND_REGISTER
4373 union _HV_INTERCEPT_SUSPEND_REGISTER
4383 union _HV_X64_INTERRUPT_STATE_REGISTER
4386 anonymous struct in
union _HV_X64_INTERRUPT_STATE_REGISTER
4396 enum _HV_X64_PENDING_INTERRUPTION_TYPE
4403 union _HV_X64_PENDING_INTERRUPTION_REGISTER
4406 anonymous struct in
union _HV_X64_PENDING_INTERRUPTION_REGISTER
4453 union _HV_REGISTER_VALUE
4494 struct _HV_REGISTER_ASSOC
4501 struct _HV_INPUT_SET_VP_REGISTERS
4517 struct _HV_INPUT_GET_VP_REGISTERS
4528 union _HV_REGISTER_CR_INTERCEPT_CONTROL
4531 anonymous struct in
union _HV_REGISTER_CR_INTERCEPT_CONTROL
4559 struct _HV_INPUT_START_VIRTUAL_PROCESSOR
4569 struct _HV_INPUT_GET_VP_INDEX_FROM_APIC_ID
4591 struct _HV_INPUT_MODIFY_VTL_PROTECTION_MASK

Not listed above are the types that HVGDK_MINI.H apparently defines in conditional blocks for the 32-bit and 64-bit ARM platforms. These can be found by inspecting the ARM-specific CLFSMGMT.LIB. They fill some of the gaps between the Intel-specific definitions.

For instance, that  _HV_X64_HYPERVISOR_FEATURES is defined at line 717 survives into the x86 and x64 builds of the library. These show nothing of a _HV_ARM64_HYPERVISOR_FEATURES, presumably because its definition was eliminated by the preprocessor’s interpretation of some sort of #if directive. The ARM builds similarly miss the X64 structure but show that _HV_ARM64_HYPERVISOR_FEATURES is defined at line 775, i.e., between _HV_X64_HYPERVISOR_FEATURES and _HV_X64_ENLIGHTENMENT_INFORMATION.

It would be a sound guess, but is not knowable from the libraries, that such paired definitions as those of _HV_X64_HYPERVISOR_FEATURES and _HV_AMD64_HYPERVISOR_FEATURES are followed by definitions of macros, in this case HV_HYPERVISOR_FEATURES, that equate to the appropriate type for whichever platform the source code is built for.

That the types have platform-specific names means that conditional compilation to eliminate the “wrong” one causes no error. Conditional compilation does indeed look to have been skipped for _HV_X64_CONTEXT and _HV_AMD64_CONTEXT. Each library for the original Windows 10 has both. This is deliberate, so that both are nested within the multi-platform HV_VP_CONTEXT.