]> wimlib.net Git - wimlib/blob - include/wimlib/wof.h
4cab2bba081e707edd9a82586b10414ca18387d7
[wimlib] / include / wimlib / wof.h
1 /*
2  * wof.h
3  *
4  * Definitions for the Windows Overlay Filesystem filter (WOF) ioctls, as well
5  * some definitions for associated undocumented data structures.
6  *
7  * Copyright 2022 Eric Biggers
8  *
9  * Permission is hereby granted, free of charge, to any person
10  * obtaining a copy of this software and associated documentation
11  * files (the "Software"), to deal in the Software without
12  * restriction, including without limitation the rights to use,
13  * copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following
16  * conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  */
30
31 #ifndef _WOF_H_
32 #define _WOF_H_
33
34 #include "wimlib/compiler.h"
35 #include "wimlib/types.h"
36
37 /*
38  * The Windows Overlay Filesystem filter (WOF, a.k.a. wof.sys) is a filesystem
39  * filter driver, available in Windows 8.1 and later, which allows files to be
40  * "externally backed", meaning that their data is stored in another location,
41  * possibly in compressed form.
42  *
43  * WOF implements a plug-in mechanism by which a specific "provider" is
44  * responsible for actually externally backing a given file.  The currently
45  * known providers are:
46  *
47  *      - The WIM provider: allows a file to be externally backed by a
48  *        compressed resource in a WIM archive
49  *      - The file provider: allows a file to be "externally backed" by a named
50  *        data stream stored with the file itself, where that named data stream
51  *        has the format of a compressed WIM resource
52  *
53  * For both of these providers, externally backed files are effectively
54  * read-only.  If you try to write to such a file, Windows automatically
55  * decompresses it and turns it into a regular, non-externally-backed file.
56  *
57  * WOF provides various ioctls that control its operation.  For example,
58  * FSCTL_SET_EXTERNAL_BACKING sets up a file as externally backed.
59  *
60  * WOF external backings are implemented using reparse points.  One consequence
61  * of this is that WOF external backings can only be set on files that do not
62  * already have a reparse point set.  Another consequence of this is that it is
63  * possible to create a WOF external backing by manually creating the reparse
64  * point, although this requires dealing with undocumented data structures and
65  * it only works when the WOF driver is not currently attached to the volume.
66  *
67  * Note that only the unnamed data stream portion of a file can be externally
68  * backed.  Other NTFS streams and metadata are not externally backed.
69  */
70
71
72 /*----------------------------------------------------------------------------*
73  *                          WOF ioctl definitions                             *
74  *----------------------------------------------------------------------------*/
75
76 #ifndef WOF_CURRENT_VERSION
77 /* Identifies a file backing provider and the overlay service version it supports.
78  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_wof_external_info */
79 typedef struct _WOF_EXTERNAL_INFO {
80 #define WOF_CURRENT_VERSION 1
81         DWORD Version;
82         DWORD Provider;
83 } WOF_EXTERNAL_INFO, *PWOF_EXTERNAL_INFO;
84 #endif /* WOF_CURRENT_VERSION */
85
86 /* WIM provider ("WIMBoot") */
87 #ifndef WOF_PROVIDER_WIM
88 #define WOF_PROVIDER_WIM 1
89 /*
90  * The identifier and status information for the Windows Image File (WIM)
91  * external backing provider.
92  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_wim_provider_external_info
93  */
94 typedef struct _WIM_PROVIDER_EXTERNAL_INFO {
95 #define WIM_PROVIDER_CURRENT_VERSION 1
96         ULONG         Version;
97         ULONG         Flags;
98         LARGE_INTEGER DataSourceId;
99 #define WIM_PROVIDER_HASH_SIZE 20
100         UCHAR         ResourceHash[WIM_PROVIDER_HASH_SIZE];
101 } WIM_PROVIDER_EXTERNAL_INFO, *PWIM_PROVIDER_EXTERNAL_INFO;
102 #endif /* WOF_PROVIDER_WIM */
103
104 /* File provider ("system compression") */
105 #ifndef WOF_PROVIDER_FILE
106 #define WOF_PROVIDER_FILE 2
107 /* Defines metadata specific to files provided by WOF_PROVIDER_FILE.
108  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_provider_external_info_v1 */
109 typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 {
110 #define FILE_PROVIDER_CURRENT_VERSION 1
111         DWORD Version;
112 #define FILE_PROVIDER_COMPRESSION_XPRESS4K      0
113 #define FILE_PROVIDER_COMPRESSION_LZX           1
114 #define FILE_PROVIDER_COMPRESSION_XPRESS8K      2
115 #define FILE_PROVIDER_COMPRESSION_XPRESS16K     3
116         DWORD Algorithm;
117         DWORD Flags;
118 } FILE_PROVIDER_EXTERNAL_INFO_V1, *PFILE_PROVIDER_EXTERNAL_INFO_V1;
119 #endif /* WOF_PROVIDER_FILE */
120
121 /* Sets the backing source for a file.
122  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-set-external-backing */
123 #ifndef FSCTL_SET_EXTERNAL_BACKING
124 #define FSCTL_SET_EXTERNAL_BACKING \
125         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 195, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
126 #endif
127
128 /* Gets the backing information for a file from an external backing provider.
129  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-get-external-backing */
130 #ifndef FSCTL_GET_EXTERNAL_BACKING
131 #define FSCTL_GET_EXTERNAL_BACKING \
132         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 196, METHOD_BUFFERED, FILE_ANY_ACCESS)
133 #endif
134
135 #ifndef STATUS_OBJECT_NOT_EXTERNALLY_BACKED
136 #define STATUS_OBJECT_NOT_EXTERNALLY_BACKED     0xC000046D
137 #endif
138
139 /* Removes the association of a file with an external backing provider.
140  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-delete-external-backing */
141 #ifndef FSCTL_DELETE_EXTERNAL_BACKING
142 #define FSCTL_DELETE_EXTERNAL_BACKING \
143         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 197, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
144 #endif
145
146 /* Begins or continues an enumeration of files on a volume that have a backing source.
147  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-enum-external-backing */
148 #ifndef FSCTL_ENUM_EXTERNAL_BACKING
149 #define FSCTL_ENUM_EXTERNAL_BACKING \
150         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 198, METHOD_BUFFERED, FILE_ANY_ACCESS)
151 #endif
152
153 /* Enumerates all the data sources from a backing provider for a specified volume.
154  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-enum-overlay */
155 #ifndef FSCTL_ENUM_OVERLAY
156 #define FSCTL_ENUM_OVERLAY \
157         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 199, METHOD_NEITHER, FILE_ANY_ACCESS)
158 typedef struct _WIM_PROVIDER_OVERLAY_ENTRY {
159         ULONG NextEntryOffset;
160         LARGE_INTEGER DataSourceId;
161         GUID WimGuid;
162         ULONG WimFileNameOffset;
163         ULONG WimType;
164         ULONG WimIndex;
165         ULONG Flags;
166 } WIM_PROVIDER_OVERLAY_ENTRY, *PWIM_PROVIDER_OVERLAY_ENTRY;
167 #endif /* FSCTL_ENUM_OVERLAY */
168
169 /* Add a new external backing source to a volume's namespace.
170  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-add-overlay */
171 #ifndef FSCTL_ADD_OVERLAY
172 #define FSCTL_ADD_OVERLAY \
173         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 204, METHOD_BUFFERED, FILE_WRITE_DATA)
174 typedef struct _WIM_PROVIDER_ADD_OVERLAY_INPUT {
175 #define WIM_BOOT_NOT_OS_WIM     0
176 #define WIM_BOOT_OS_WIM         1
177         ULONG WimType;
178         ULONG WimIndex;
179         ULONG WimFileNameOffset;
180         ULONG WimFileNameLength;
181 } WIM_PROVIDER_ADD_OVERLAY_INPUT, *PWIM_PROVIDER_ADD_OVERLAY_INPUT;
182 #endif /* FSCTL_ADD_OVERLAY */
183
184 /* Removes a backing source from a volume.
185  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-remove-overlay */
186 #ifndef FSCTL_REMOVE_OVERLAY
187 #define FSCTL_REMOVE_OVERLAY \
188         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 205, METHOD_BUFFERED, FILE_WRITE_DATA)
189 typedef struct _WIM_PROVIDER_REMOVE_OVERLAY_INPUT {
190         LARGE_INTEGER DataSourceId;
191 } WIM_PROVIDER_REMOVE_OVERLAY_INPUT, *PWIM_PROVIDER_REMOVE_OVERLAY_INPUT;
192 #endif /* FSCTL_REMOVE_OVERLAY */
193
194 /* Updates a new data source identifier for a backing source attached to a volume.
195  * Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/fsctl-update-overlay */
196 #ifndef FSCTL_UPDATE_OVERLAY
197 #define FSCTL_UPDATE_OVERLAY \
198         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 206, METHOD_BUFFERED, FILE_WRITE_DATA)
199 typedef struct _WIM_PROVIDER_UPDATE_OVERLAY_INPUT {
200         LARGE_INTEGER DataSourceId;
201         ULONG         WimFileNameOffset;
202         ULONG         WimFileNameLength;
203 } WIM_PROVIDER_UPDATE_OVERLAY_INPUT, *PWIM_PROVIDER_UPDATE_OVERLAY_INPUT;
204 #endif /* FSCTL_UPDATE_OVERLAY */
205
206 /*----------------------------------------------------------------------------*
207  *        WOF reparse point and WimOverlay.dat structs (undocumented)         *
208  *----------------------------------------------------------------------------*/
209
210 /*
211  * Format of the WIM provider reparse data.  This is the data which follows the
212  * portion of the reparse point common to WOF.  (The common portion consists of
213  * a reparse point header where the reparse tag is 0x80000017, then a
214  * WOF_EXTERNAL_INFO struct which specifies the provider.)
215  *
216  * Note that Microsoft does not document any of the reparse point formats for
217  * WOF, although they document the structures which must be passed into the
218  * ioctls, which are often similar.
219  */
220 struct wim_provider_rpdata {
221         /* Set to 2.  Uncertain meaning.  */
222         le32 version;
223
224         /* 0 when WIM provider active, otherwise
225          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
226          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
227         le32 flags;
228
229         /* Integer ID that identifies the WIM.  */
230         le64 data_source_id;
231
232         /* SHA-1 message digest of the file's unnamed data stream.  */
233         u8 unnamed_data_stream_hash[20];
234
235         /* SHA-1 message digest of the WIM's blob table as stored on disk.  */
236         u8 blob_table_hash[20];
237
238         /* Uncompressed size of the file's unnamed data stream, in bytes.  */
239         le64 unnamed_data_stream_size;
240
241         /* Size of the file's unnamed data stream as stored in the WIM file.
242          * If this is the same as unnamed_data_stream_size, then the stream is
243          * uncompressed.  If this is the *not* the same as
244          * unnamed_data_stream_size, then the stream is compressed.  */
245         le64 unnamed_data_stream_size_in_wim;
246
247         /* Byte offset of the file's unnamed data stream in the WIM.  */
248         le64 unnamed_data_stream_offset_in_wim;
249 } _packed_attribute;
250
251 /* WIM-specific information about a WIM data source  */
252 struct WimOverlay_dat_entry_1 {
253
254         /* Identifier for the WIM data source, (normally allocated by
255          * FSCTL_ADD_OVERLAY).  Every 'WimOverlay_dat_entry_1' should have a
256          * different value for this.  */
257         le64 data_source_id;
258
259         /* Byte offset, from the beginning of the file, of the corresponding
260          * 'struct WimOverlay_dat_entry_2' for this WIM data source.  */
261         le32 entry_2_offset;
262
263         /* Size, in bytes, of the corresponding 'struct WimOverlay_dat_entry_2
264          * for this WIM data source, including wim_file_name and its null
265          * terminator.  */
266         le32 entry_2_length;
267
268         /* Type of the WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM.  */
269         le32 wim_type;
270
271         /* Index of the image in the WIM to use??? (This doesn't really make
272          * sense, since WIM files combine file data "blobs" for all images into
273          * a single table.  Set to 1 if unsure...)  */
274         le32 wim_index;
275
276         /* GUID of the WIM file (copied from the WIM header, offset +0x18).  */
277         u8 guid[16];
278 } _packed_attribute;
279
280 /*
281  * Format of file: "\System Volume Information\WimOverlay.dat"
282  *
283  * Not documented by Microsoft.
284  *
285  * The file consists of a 'struct WimOverlay_dat_header' followed by one or more
286  * 'struct WimOverlay_dat_entry_1', followed by the same number of 'struct
287  * WimOverlay_dat_entry_2'.  Note that 'struct WimOverlay_dat_entry_1' is of
288  * fixed length, whereas 'struct WimOverlay_dat_entry_2' is of variable length.
289  */
290 struct WimOverlay_dat_header {
291         /* Set to WIMOVERLAY_DAT_MAGIC  */
292         le32 magic;
293 #define WIMOVERLAY_DAT_MAGIC 0x66436F57
294
295         /* Set to 1 (WIM_PROVIDER_CURRENT_VERSION)  */
296         le32 wim_provider_version;
297
298         /* Set to 0x00000028  */
299         le32 unknown_0x08;
300
301         /* Set to number of WIMs registered (listed in the file)  */
302         le32 num_entries;
303
304         /* The next available data source ID.  This is tracked so that data
305          * source IDs are never reused, even if a WIM is unregistered.  */
306         le64 next_data_source_id;
307
308         struct WimOverlay_dat_entry_1 entry_1s[];
309 } _packed_attribute;
310
311 /* Location information about a WIM data source  */
312 struct WimOverlay_dat_entry_2 {
313         /* Set to 0  */
314         le32 unknown_0x00;
315
316         /* Set to 0  */
317         le32 unknown_0x04;
318
319         /* Size, in bytes, of this 'struct WimOverlay_dat_entry_2', including
320          * wim_file_name and its null terminator.  */
321         le32 entry_2_length;
322
323         /* Set to 0  */
324         le32 unknown_0x0C;
325
326         /* Set to 5  */
327         le32 unknown_0x10;
328
329         struct {
330                 /* Set to 1  */
331                 le32 unknown_0x14;
332
333                 /* Size of this inner structure, in bytes.  */
334                 le32 inner_struct_size;
335
336                 /* Set to 5  */
337                 le32 unknown_0x1C;
338
339                 /* Set to 6  */
340                 le32 unknown_0x20;
341
342                 /* Set to 0  */
343                 le32 unknown_0x24;
344
345                 /* Set to 0x48  */
346                 le32 unknown_0x28;
347
348                 /* Set to 0  */
349                 le32 unknown_0x2C;
350
351                 /*************************
352                  * Partition information
353                  ************************/
354
355                 /* Partition identifier  */
356                 union {
357                         /* (For MBR-formatted disks)  */
358                         struct {
359                                 /* Offset, in bytes, of the MBR partition, from
360                                  * the beginning of the disk.  */
361                                 le64 part_start_offset;
362
363                                 /* Set to 0  */
364                                 le64 padding;
365                         } mbr;
366
367                         /* (For GPT-formatted disks)  */
368                         struct {
369                                 /* Unique GUID of the GPT partition  */
370                                 u8 part_unique_guid[16];
371                         } gpt;
372                 } partition;
373
374                 /* Set to 0  */
375                 le32 unknown_0x40;
376
377                 /***********************
378                  * Disk information
379                  **********************/
380
381                 /* 1 for MBR, 0 for GPT  */
382                 le32 partition_table_type;
383         #define WIMOVERLAY_PARTITION_TYPE_MBR 1
384         #define WIMOVERLAY_PARTITION_TYPE_GPT 0
385
386                 /* Disk identifier  */
387                 union {
388                         /* (For MBR-formatted disks)  */
389                         struct {
390                                 /* 4-byte ID of the MBR disk  */
391                                 le32 disk_id;
392
393                                 /* Set to 0  */
394                                 le32 padding[3];
395                         } mbr;
396
397                         /* (For GPT-formatted disks)  */
398                         struct {
399                                 /* GUID of the GPT disk  */
400                                 u8 disk_guid[16];
401                         } gpt;
402                 } disk;
403
404                 /* Set to 0.  (This is the right size for some sort of optional
405                  * GUID...)  */
406                 le32 unknown_0x58[4];
407
408                 /**************************
409                  * Location in filesystem
410                  *************************/
411
412                 /* Null-terminated path to WIM file.  Begins with \ but does
413                  * *not* include drive letter!  */
414                 utf16lechar wim_file_name[];
415         } _packed_attribute;
416 } _packed_attribute;
417
418 static _unused_attribute void
419 wof_check_structs(void)
420 {
421         STATIC_ASSERT(sizeof(struct WimOverlay_dat_header) == 24);
422         STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_1) == 40);
423         STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_2) == 104);
424 }
425
426 #endif /* _WOF_H_ */