4 * Definitions for the Windows Overlay Filesystem filter (WOF) ioctls, as well
5 * some definitions for associated undocumented data structures. See
6 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff540367(v=vs.85).aspx
7 * for more information about the documented ioctls.
9 * The following copying information applies to this specific source code file:
11 * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
13 * To the extent possible under law, the author(s) have dedicated all copyright
14 * and related and neighboring rights to this software to the public domain
15 * worldwide via the Creative Commons Zero 1.0 Universal Public Domain
16 * Dedication (the "CC0").
18 * This software is distributed in the hope that it will be useful, but WITHOUT
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 * FOR A PARTICULAR PURPOSE. See the CC0 for more details.
22 * You should have received a copy of the CC0 along with this software; if not
23 * see <http://creativecommons.org/publicdomain/zero/1.0/>.
29 #include "wimlib/compiler.h"
30 #include "wimlib/types.h"
33 * The Windows Overlay Filesystem filter (WOF, a.k.a. wof.sys) is a filesystem
34 * filter driver, available in Windows 8.1 and later, which allows files to be
35 * "externally backed", meaning that their data is stored in another location,
36 * possibly in compressed form.
38 * WOF implements a plug-in mechanism by which a specific "provider" is
39 * responsible for actually externally backing a given file. The currently
40 * known providers are:
42 * - The WIM provider: allows a file to be externally backed by a
43 * compressed resource in a WIM archive
44 * - The file provider: allows a file to be "externally backed" by a named
45 * data stream stored with the file itself, where that named data stream
46 * has the format of a compressed WIM resource
48 * For both of these providers, externally backed files are effectively
49 * read-only. If you try to write to such a file, Windows automatically
50 * decompresses it and turns it into a regular, non-externally-backed file.
52 * WOF provides various ioctls that control its operation. For example,
53 * FSCTL_SET_EXTERNAL_BACKING sets up a file as externally backed.
55 * WOF external backings are implemented using reparse points. One consequence
56 * of this is that WOF external backings can only be set on files that do not
57 * already have a reparse point set. Another consequence of this is that it is
58 * possible to create a WOF external backing by manually creating the reparse
59 * point, although this requires dealing with undocumented data structures and
60 * it only works when the WOF driver is not currently attached to the volume.
62 * Note that only the unnamed data stream portion of a file can be externally
63 * backed. Other NTFS streams and metadata are not externally backed.
67 /* Current version of the WOF driver/protocol */
68 #define WOF_CURRENT_VERSION 1
70 /* Specifies the WIM backing provider */
71 #define WOF_PROVIDER_WIM 1
73 /* Specifies the "file" backing provider (a.k.a. System Compression) */
74 #define WOF_PROVIDER_FILE 2
76 /* The current version of the WIM backing provider */
77 #define WIM_PROVIDER_CURRENT_VERSION 1
79 /* The current version of the file backing provider */
80 #define FILE_PROVIDER_CURRENT_VERSION 1
82 /* Identifies a backing provider for a specific overlay service version. */
83 struct wof_external_info {
85 /* Version of the overlay service supported by the backing provider.
86 * Set to WOF_CURRENT_VERSION. */
89 /* Identifier for the backing provider. Example value:
90 * WOF_PROVIDER_WIM. */
96 * Format of the WIM provider reparse data. This is the data which follows the
97 * portion of the reparse point common to WOF. (The common portion consists of
98 * a reparse point header where the reparse tag is 0x80000017, then a 'struct
99 * wof_external_info' which specifies the provider.)
101 * Note that Microsoft does not document any of the reparse point formats for
102 * WOF, although they document the structures which must be passed into the
103 * ioctls, which are often similar.
105 struct wim_provider_rpdata {
106 /* Set to 2. Uncertain meaning. */
109 /* 0 when WIM provider active, otherwise
110 * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
111 * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED. */
114 /* Integer ID that identifies the WIM. */
117 /* SHA-1 message digest of the file's unnamed data stream. */
118 u8 unnamed_data_stream_hash[20];
120 /* SHA-1 message digest of the WIM's blob table as stored on disk. */
121 u8 blob_table_hash[20];
123 /* Uncompressed size of the file's unnamed data stream, in bytes. */
124 le64 unnamed_data_stream_size;
126 /* Size of the file's unnamed data stream as stored in the WIM file.
127 * If this is the same as unnamed_data_stream_size, then the stream is
128 * uncompressed. If this is the *not* the same as
129 * unnamed_data_stream_size, then the stream is compressed. */
130 le64 unnamed_data_stream_size_in_wim;
132 /* Byte offset of the file's unnamed data stream in the WIM. */
133 le64 unnamed_data_stream_offset_in_wim;
136 /* WIM-specific information about a WIM data source */
137 struct WimOverlay_dat_entry_1 {
139 /* Identifier for the WIM data source, (normally allocated by
140 * FSCTL_ADD_OVERLAY). Every 'WimOverlay_dat_entry_1' should have a
141 * different value for this. */
144 /* Byte offset, from the beginning of the file, of the corresponding
145 * 'struct WimOverlay_dat_entry_2' for this WIM data source. */
148 /* Size, in bytes, of the corresponding 'struct WimOverlay_dat_entry_2
149 * for this WIM data source, including wim_file_name and its null
153 /* Type of the WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM. */
156 /* Index of the image in the WIM to use??? (This doesn't really make
157 * sense, since WIM files combine file data "blobs" for all images into
158 * a single table. Set to 1 if unsure...) */
161 /* GUID of the WIM file (copied from the WIM header, offset +0x18). */
166 * Format of file: "\System Volume Information\WimOverlay.dat"
168 * Not documented by Microsoft.
170 * The file consists of a 'struct WimOverlay_dat_header' followed by one or more
171 * 'struct WimOverlay_dat_entry_1', followed by the same number of 'struct
172 * WimOverlay_dat_entry_2'. Note that 'struct WimOverlay_dat_entry_1' is of
173 * fixed length, whereas 'struct WimOverlay_dat_entry_2' is of variable length.
175 struct WimOverlay_dat_header {
176 /* Set to WIMOVERLAY_DAT_MAGIC */
178 #define WIMOVERLAY_DAT_MAGIC 0x66436F57
180 /* Set to 1 (WIM_PROVIDER_CURRENT_VERSION) */
181 le32 wim_provider_version;
183 /* Set to 0x00000028 */
186 /* Set to number of WIMs registered (listed in the file) */
189 /* The next available data source ID. This is tracked so that data
190 * source IDs are never reused, even if a WIM is unregistered. */
191 le64 next_data_source_id;
193 struct WimOverlay_dat_entry_1 entry_1s[];
196 /* Location information about a WIM data source */
197 struct WimOverlay_dat_entry_2 {
204 /* Size, in bytes, of this 'struct WimOverlay_dat_entry_2', including
205 * wim_file_name and its null terminator. */
218 /* Size of this inner structure, in bytes. */
219 le32 inner_struct_size;
236 /*************************
237 * Partition information
238 ************************/
240 /* Partition identifier */
242 /* (For MBR-formatted disks) */
244 /* Offset, in bytes, of the MBR partition, from
245 * the beginning of the disk. */
246 le64 part_start_offset;
252 /* (For GPT-formatted disks) */
254 /* Unique GUID of the GPT partition */
255 u8 part_unique_guid[16];
262 /***********************
264 **********************/
266 /* 1 for MBR, 0 for GPT */
267 le32 partition_table_type;
268 #define WIMOVERLAY_PARTITION_TYPE_MBR 1
269 #define WIMOVERLAY_PARTITION_TYPE_GPT 0
271 /* Disk identifier */
273 /* (For MBR-formatted disks) */
275 /* 4-byte ID of the MBR disk */
282 /* (For GPT-formatted disks) */
284 /* GUID of the GPT disk */
289 /* Set to 0. (This is the right size for some sort of optional
291 le32 unknown_0x58[4];
293 /**************************
294 * Location in filesystem
295 *************************/
297 /* Null-terminated path to WIM file. Begins with \ but does
298 * *not* include drive letter! */
299 utf16lechar wim_file_name[];
303 static _unused_attribute void
304 wof_check_structs(void)
306 STATIC_ASSERT(sizeof(struct WimOverlay_dat_header) == 24);
307 STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_1) == 40);
308 STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_2) == 104);
311 /*****************************************************************************
313 * --- FSCTL_SET_EXTERNAL_BACKING ---
315 * Sets the backing source of a file.
317 * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
318 * Access: 0 (FILE_ANY_ACCESS)
320 * Method: 0 (METHOD_BUFFERED)
322 * Input buffer: 'struct wof_external_info' followed by provider-specific data
323 * ('struct wim_provider_external_info' in the case of WIM).
325 * Output buffer: None
327 #define FSCTL_SET_EXTERNAL_BACKING 0x9030C
329 struct wim_provider_external_info {
331 /* Set to WIM_PROVIDER_CURRENT_VERSION. */
334 /* 0 when WIM provider active, otherwise
335 * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
336 * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED. */
339 /* Integer ID that identifies the WIM. Get this with the
340 * FSCTL_ADD_OVERLAY ioctl. */
343 /* SHA-1 message digest of the file's unnamed data stream. */
344 u8 unnamed_data_stream_hash[20];
347 struct file_provider_external_info {
349 /* Set to FILE_PROVIDER_CURRENT_VERSION. */
352 u32 compression_format;
353 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K 0
354 #define FILE_PROVIDER_COMPRESSION_FORMAT_LZX 1
355 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS8K 2
356 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS16K 3
359 /*****************************************************************************
361 * --- FSCTL_GET_EXTERNAL_BACKING ---
363 * Get external backing information for the specified file.
365 * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
366 * Access: 0 (FILE_ANY_ACCESS)
368 * Method: 0 (METHOD_BUFFERED)
371 * Output buffer: 'struct wof_external_info' followed by provider-specific data
372 * ('struct wim_provider_external_info' in the case of WIM).
374 #define FSCTL_GET_EXTERNAL_BACKING 0x90310
376 #define STATUS_OBJECT_NOT_EXTERNALLY_BACKED 0xC000046D
378 /*****************************************************************************
380 * --- FSCTL_DELETE_EXTERNAL_BACKING ---
382 * Copy a file from its backing source to its volume, then disassociate it from
383 * its backing provider.
385 * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
386 * Access: 0 (FILE_ANY_ACCESS)
388 * Method: 0 (METHOD_BUFFERED)
391 * Output buffer: None
393 #define FSCTL_DELETE_EXTERNAL_BACKING 0x90314
395 /*****************************************************************************
397 * --- FSCTL_ENUM_EXTERNAL_BACKING ---
399 * Enumerate externally backed files on a volume.
401 * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
402 * Access: 0 (FILE_ANY_ACCESS)
404 * Method: 0 (METHOD_BUFFERED)
407 * Output buffer: A 16-byte buffer that receives the 128-bit file ID for the
408 * next externally backed file.
410 * The handle used may be either the volume handle or the handle for any file or
411 * directory on the volume.
413 * When all externally backed files on the volume have been enumerated, the
414 * function fails with ERROR_NO_MORE_FILES.
416 #define FSCTL_ENUM_EXTERNAL_BACKING 0x90318
418 /*****************************************************************************
420 * --- FSCTL_ENUM_OVERLAY ---
422 * Enumerates the volume's overlay sources from the specified provider.
424 * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
425 * Access: 0 (FILE_ANY_ACCESS)
427 * Method: 3 (METHOD_NEITHER)
429 * Input buffer: 'struct wof_external_info' to specify the provider for which
430 * to enumerate the overlay sources.
432 * Output buffer: Provider-specific data. For the WIM provider, an array of
433 * 'struct wim_provider_overlay_entry'.
435 * This ioctl must be performed on the volume handle, such as \\.\C:
437 #define FSCTL_ENUM_OVERLAY 0x9031F
439 struct wim_provider_overlay_entry {
440 /* Byte offset of the next entry from the beginning of this structure,
441 * or 0 if there are no more entries. */
442 u32 next_entry_offset;
446 /* Identifier for the WIM file. */
449 /* GUID of the WIM file. */
452 /* Byte offset of the WIM's file name from the beginning of this
454 u32 wim_file_name_offset;
456 /* Type of WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM. */
459 /* Index of the image in the WIM to use??? (This doesn't really make
460 * sense, since WIM files combine file data "blobs" for all images into
461 * a single table. Set to 1 if unsure...) */
464 /* 0 when WIM provider active, otherwise
465 * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
466 * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED. */
469 /* Full path to the WIM in the NT device namespace, e.g.
470 * "\Device\HardDiskVolume2\test.wim". Seems to be null-terminated,
471 * although you probably shouldn't assume so. */
472 wchar_t wim_file_name[];
476 /*****************************************************************************
478 * --- FSCTL_ADD_OVERLAY ---
480 * Adds a new external backing source to a volume.
482 * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
483 * Access: 2 (FILE_WRITE_ACCESS)
485 * Method: 0 (METHOD_BUFFERED)
487 * Input buffer: 'struct wof_external_info' followed by provider-specific data
488 * ('struct wim_provider_add_overlay_input' in the case of WIM).
490 * Output buffer: Buffer large enough to receive any information resulting from
491 * the add operation. For the WIM provider, this must be an 8 byte buffer that
492 * receives the 64-bit WIM file ID.
494 * This ioctl must be performed on the volume handle, such as \\.\C:
496 #define FSCTL_ADD_OVERLAY 0x98330
498 struct wim_provider_add_overlay_input {
500 /* Type of WIM file. */
502 #define WIM_BOOT_OS_WIM 0
503 #define WIM_BOOT_NOT_OS_WIM 1
505 /* Index of the image in the WIM to use??? (This doesn't really make
506 * sense, since WIM files combine file data "blobs" for all images into
507 * a single table. Set to 1 if unsure...) */
510 /* Byte offset of wim_file_name in this buffer, not including the
511 * preceding 'struct wof_external_info' (should be 16). */
512 u32 wim_file_name_offset;
514 /* Number of bytes in wim_file_name. */
515 u32 wim_file_name_length;
517 /* Full path to the WIM, e.g. "\??\C:\test-wimboot.wim".
518 * Does NOT need to be null terminated (MS docs claim otherwise). */
519 wchar_t wim_file_name[];
522 /*****************************************************************************
524 * --- FSCTL_REMOVE_OVERLAY ---
526 * Removes an external backing source from a volume.
528 * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
529 * Access: 2 (FILE_WRITE_ACCESS)
531 * Method: 0 (METHOD_BUFFERED)
533 * Input buffer: 'struct wof_external_info' followed by provider-specific data
534 * ('struct wim_provider_remove_overlay_input' in the case of WIM).
536 * Output buffer: None
538 * This ioctl must be performed on the volume handle, such as \\.\C:
540 #define FSCTL_REMOVE_OVERLAY 0x98334
542 struct wim_provider_remove_overlay_input {
543 /* Integer ID that identifies the WIM. */
548 /*****************************************************************************
550 * --- FSCTL_UPDATE_OVERLAY ---
552 * Updates an overlay source for a volume.
554 * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
555 * Access: 2 (FILE_WRITE_ACCESS)
557 * Method: 0 (METHOD_BUFFERED)
559 * Input buffer: 'struct wof_external_info' followed by provider-specific data
560 * ('struct wim_provider_update_overlay_input' in the case of WIM).
562 * Output buffer: None
564 * This ioctl must be performed on the volume handle, such as \\.\C:
566 #define FSCTL_UPDATE_OVERLAY 0x98338
568 struct wim_provider_update_overlay_input {
569 /* Integer ID that identifies the WIM data source. */
572 /* Byte offset of wim_file_name in this buffer, not including the
573 * preceding 'struct wof_external_info' (should be 16). */
574 u32 wim_file_name_offset;
576 /* Number of bytes in wim_file_name. */
577 u32 wim_file_name_length;
579 /* Full path to the WIM, e.g. "\??\C:\test-wimboot.wim".
580 * Does NOT need to be null terminated (MS docs claim otherwise).
581 * This WIM must be renamed from the original WIM, or at least be an
582 * identical copy of it! (Maybe the WIM's GUID field is checked.) */
583 wchar_t wim_file_name[];