/* * wof.h * * Definitions for the Windows Overlay Filesystem filter (WOF) ioctls, as well * some definitions for associated undocumented data structures. * * Copyright 2022 Eric Biggers * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _WOF_H_ #define _WOF_H_ #include "wimlib/compiler.h" #include "wimlib/types.h" #ifdef _WIN32 /* * The Windows Overlay Filesystem filter (WOF, a.k.a. wof.sys) is a filesystem * filter driver, available in Windows 8.1 and later, which allows files to be * "externally backed", meaning that their data is stored in another location, * possibly in compressed form. * * WOF implements a plug-in mechanism by which a specific "provider" is * responsible for actually externally backing a given file. The currently * known providers are: * * - The WIM provider: allows a file to be externally backed by a * compressed resource in a WIM archive * - The file provider: allows a file to be "externally backed" by a named * data stream stored with the file itself, where that named data stream * has the format of a compressed WIM resource * * For both of these providers, externally backed files are effectively * read-only. If you try to write to such a file, Windows automatically * decompresses it and turns it into a regular, non-externally-backed file. * * WOF provides various ioctls that control its operation. For example, * FSCTL_SET_EXTERNAL_BACKING sets up a file as externally backed. * * WOF external backings are implemented using reparse points. One consequence * of this is that WOF external backings can only be set on files that do not * already have a reparse point set. Another consequence of this is that it is * possible to create a WOF external backing by manually creating the reparse * point, although this requires dealing with undocumented data structures and * it only works when the WOF driver is not currently attached to the volume. * * Note that only the unnamed data stream portion of a file can be externally * backed. Other NTFS streams and metadata are not externally backed. */ /*----------------------------------------------------------------------------* * WOF ioctl definitions * *----------------------------------------------------------------------------*/ #ifndef WOF_CURRENT_VERSION /* Identifies a file backing provider and the overlay service version it supports. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_wof_external_info */ typedef struct _WOF_EXTERNAL_INFO { #define WOF_CURRENT_VERSION 1 DWORD Version; DWORD Provider; } WOF_EXTERNAL_INFO, *PWOF_EXTERNAL_INFO; #endif /* WOF_CURRENT_VERSION */ /* WIM provider ("WIMBoot") */ #ifndef WOF_PROVIDER_WIM #define WOF_PROVIDER_WIM 1 /* * The identifier and status information for the Windows Image File (WIM) * external backing provider. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_wim_provider_external_info */ typedef struct _WIM_PROVIDER_EXTERNAL_INFO { #define WIM_PROVIDER_CURRENT_VERSION 1 ULONG Version; ULONG Flags; LARGE_INTEGER DataSourceId; #define WIM_PROVIDER_HASH_SIZE 20 UCHAR ResourceHash[WIM_PROVIDER_HASH_SIZE]; } WIM_PROVIDER_EXTERNAL_INFO, *PWIM_PROVIDER_EXTERNAL_INFO; #endif /* WOF_PROVIDER_WIM */ /* File provider ("system compression") */ #ifndef WOF_PROVIDER_FILE #define WOF_PROVIDER_FILE 2 /* Defines metadata specific to files provided by WOF_PROVIDER_FILE. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_provider_external_info_v1 */ typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 { #define FILE_PROVIDER_CURRENT_VERSION 1 DWORD Version; #define FILE_PROVIDER_COMPRESSION_XPRESS4K 0 #define FILE_PROVIDER_COMPRESSION_LZX 1 #define FILE_PROVIDER_COMPRESSION_XPRESS8K 2 #define FILE_PROVIDER_COMPRESSION_XPRESS16K 3 DWORD Algorithm; DWORD Flags; } FILE_PROVIDER_EXTERNAL_INFO_V1, *PFILE_PROVIDER_EXTERNAL_INFO_V1; #endif /* WOF_PROVIDER_FILE */ /* Sets the backing source for a file. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-set-external-backing */ #ifndef FSCTL_SET_EXTERNAL_BACKING #define FSCTL_SET_EXTERNAL_BACKING \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 195, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) #endif /* Gets the backing information for a file from an external backing provider. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-get-external-backing */ #ifndef FSCTL_GET_EXTERNAL_BACKING #define FSCTL_GET_EXTERNAL_BACKING \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 196, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif #ifndef STATUS_OBJECT_NOT_EXTERNALLY_BACKED #define STATUS_OBJECT_NOT_EXTERNALLY_BACKED 0xC000046D #endif /* Removes the association of a file with an external backing provider. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-delete-external-backing */ #ifndef FSCTL_DELETE_EXTERNAL_BACKING #define FSCTL_DELETE_EXTERNAL_BACKING \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 197, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) #endif /* Begins or continues an enumeration of files on a volume that have a backing source. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-enum-external-backing */ #ifndef FSCTL_ENUM_EXTERNAL_BACKING #define FSCTL_ENUM_EXTERNAL_BACKING \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 198, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif /* Enumerates all the data sources from a backing provider for a specified volume. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-enum-overlay */ #ifndef FSCTL_ENUM_OVERLAY #define FSCTL_ENUM_OVERLAY \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 199, METHOD_NEITHER, FILE_ANY_ACCESS) #endif typedef struct _WIM_PROVIDER_OVERLAY_ENTRY { ULONG NextEntryOffset; LARGE_INTEGER DataSourceId; GUID WimGuid; ULONG WimFileNameOffset; ULONG WimType; ULONG WimIndex; ULONG Flags; } WIM_PROVIDER_OVERLAY_ENTRY, *PWIM_PROVIDER_OVERLAY_ENTRY; /* Add a new external backing source to a volume's namespace. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-add-overlay */ #ifndef FSCTL_ADD_OVERLAY #define FSCTL_ADD_OVERLAY \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 204, METHOD_BUFFERED, FILE_WRITE_DATA) #endif typedef struct _WIM_PROVIDER_ADD_OVERLAY_INPUT { #define WIM_BOOT_NOT_OS_WIM 0 #define WIM_BOOT_OS_WIM 1 ULONG WimType; ULONG WimIndex; ULONG WimFileNameOffset; ULONG WimFileNameLength; } WIM_PROVIDER_ADD_OVERLAY_INPUT, *PWIM_PROVIDER_ADD_OVERLAY_INPUT; /* Removes a backing source from a volume. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-remove-overlay */ #ifndef FSCTL_REMOVE_OVERLAY #define FSCTL_REMOVE_OVERLAY \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 205, METHOD_BUFFERED, FILE_WRITE_DATA) #endif typedef struct _WIM_PROVIDER_REMOVE_OVERLAY_INPUT { LARGE_INTEGER DataSourceId; } WIM_PROVIDER_REMOVE_OVERLAY_INPUT, *PWIM_PROVIDER_REMOVE_OVERLAY_INPUT; /* Updates a new data source identifier for a backing source attached to a volume. * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-update-overlay */ #ifndef FSCTL_UPDATE_OVERLAY #define FSCTL_UPDATE_OVERLAY \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 206, METHOD_BUFFERED, FILE_WRITE_DATA) #endif typedef struct _WIM_PROVIDER_UPDATE_OVERLAY_INPUT { LARGE_INTEGER DataSourceId; ULONG WimFileNameOffset; ULONG WimFileNameLength; } WIM_PROVIDER_UPDATE_OVERLAY_INPUT, *PWIM_PROVIDER_UPDATE_OVERLAY_INPUT; /*----------------------------------------------------------------------------* * WOF reparse point and WimOverlay.dat structs (undocumented) * *----------------------------------------------------------------------------*/ /* * Format of the WIM provider reparse data. This is the data which follows the * portion of the reparse point common to WOF. (The common portion consists of * a reparse point header where the reparse tag is 0x80000017, then a * WOF_EXTERNAL_INFO struct which specifies the provider.) * * Note that Microsoft does not document any of the reparse point formats for * WOF, although they document the structures which must be passed into the * ioctls, which are often similar. */ struct wim_provider_rpdata { /* Set to 2. Uncertain meaning. */ le32 version; /* 0 when WIM provider active, otherwise * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED. */ le32 flags; /* Integer ID that identifies the WIM. */ le64 data_source_id; /* SHA-1 message digest of the file's unnamed data stream. */ u8 unnamed_data_stream_hash[20]; /* SHA-1 message digest of the WIM's blob table as stored on disk. */ u8 blob_table_hash[20]; /* Uncompressed size of the file's unnamed data stream, in bytes. */ le64 unnamed_data_stream_size; /* Size of the file's unnamed data stream as stored in the WIM file. * If this is the same as unnamed_data_stream_size, then the stream is * uncompressed. If this is the *not* the same as * unnamed_data_stream_size, then the stream is compressed. */ le64 unnamed_data_stream_size_in_wim; /* Byte offset of the file's unnamed data stream in the WIM. */ le64 unnamed_data_stream_offset_in_wim; } __attribute__((packed)); /* WIM-specific information about a WIM data source */ struct WimOverlay_dat_entry_1 { /* Identifier for the WIM data source, (normally allocated by * FSCTL_ADD_OVERLAY). Every 'WimOverlay_dat_entry_1' should have a * different value for this. */ le64 data_source_id; /* Byte offset, from the beginning of the file, of the corresponding * 'struct WimOverlay_dat_entry_2' for this WIM data source. */ le32 entry_2_offset; /* Size, in bytes, of the corresponding 'struct WimOverlay_dat_entry_2 * for this WIM data source, including wim_file_name and its null * terminator. */ le32 entry_2_length; /* Type of the WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM. */ le32 wim_type; /* Index of the image in the WIM to use??? (This doesn't really make * sense, since WIM files combine file data "blobs" for all images into * a single table. Set to 1 if unsure...) */ le32 wim_index; /* GUID of the WIM file (copied from the WIM header, offset +0x18). */ u8 guid[16]; } __attribute__((packed)); /* * Format of file: "\System Volume Information\WimOverlay.dat" * * Not documented by Microsoft. * * The file consists of a 'struct WimOverlay_dat_header' followed by one or more * 'struct WimOverlay_dat_entry_1', followed by the same number of 'struct * WimOverlay_dat_entry_2'. Note that 'struct WimOverlay_dat_entry_1' is of * fixed length, whereas 'struct WimOverlay_dat_entry_2' is of variable length. */ struct WimOverlay_dat_header { /* Set to WIMOVERLAY_DAT_MAGIC */ le32 magic; #define WIMOVERLAY_DAT_MAGIC 0x66436F57 /* Set to 1 (WIM_PROVIDER_CURRENT_VERSION) */ le32 wim_provider_version; /* Set to 0x00000028 */ le32 unknown_0x08; /* Set to number of WIMs registered (listed in the file) */ le32 num_entries; /* The next available data source ID. This is tracked so that data * source IDs are never reused, even if a WIM is unregistered. */ le64 next_data_source_id; struct WimOverlay_dat_entry_1 entry_1s[]; } __attribute__((packed)); /* Location information about a WIM data source */ struct WimOverlay_dat_entry_2 { /* Set to 0 */ le32 unknown_0x00; /* Set to 0 */ le32 unknown_0x04; /* Size, in bytes, of this 'struct WimOverlay_dat_entry_2', including * wim_file_name and its null terminator. */ le32 entry_2_length; /* Set to 0 */ le32 unknown_0x0C; /* Set to 5 */ le32 unknown_0x10; struct { /* Set to 1 */ le32 unknown_0x14; /* Size of this inner structure, in bytes. */ le32 inner_struct_size; /* Set to 5 */ le32 unknown_0x1C; /* Set to 6 */ le32 unknown_0x20; /* Set to 0 */ le32 unknown_0x24; /* Set to 0x48 */ le32 unknown_0x28; /* Set to 0 */ le32 unknown_0x2C; /************************* * Partition information ************************/ /* Partition identifier */ union { /* (For MBR-formatted disks) */ struct { /* Offset, in bytes, of the MBR partition, from * the beginning of the disk. */ le64 part_start_offset; /* Set to 0 */ le64 padding; } mbr; /* (For GPT-formatted disks) */ struct { /* Unique GUID of the GPT partition */ u8 part_unique_guid[16]; } gpt; } partition; /* Set to 0 */ le32 unknown_0x40; /*********************** * Disk information **********************/ /* 1 for MBR, 0 for GPT */ le32 partition_table_type; #define WIMOVERLAY_PARTITION_TYPE_MBR 1 #define WIMOVERLAY_PARTITION_TYPE_GPT 0 /* Disk identifier */ union { /* (For MBR-formatted disks) */ struct { /* 4-byte ID of the MBR disk */ le32 disk_id; /* Set to 0 */ le32 padding[3]; } mbr; /* (For GPT-formatted disks) */ struct { /* GUID of the GPT disk */ u8 disk_guid[16]; } gpt; } disk; /* Set to 0. (This is the right size for some sort of optional * GUID...) */ le32 unknown_0x58[4]; /************************** * Location in filesystem *************************/ /* Null-terminated path to WIM file. Begins with \ but does * *not* include drive letter! */ utf16lechar wim_file_name[]; } __attribute__((packed)); } __attribute__((packed)); static void __attribute__((unused)) wof_check_structs(void) { STATIC_ASSERT(sizeof(struct WimOverlay_dat_header) == 24); STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_1) == 40); STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_2) == 104); } #endif /* _WIN32 */ #endif /* _WOF_H_ */