0d2cec26744bea22d102d41747f161479b341b6a
[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.  See
6  * http://msdn.microsoft.com/en-us/library/windows/hardware/ff540367(v=vs.85).aspx
7  * for more information about the documented ioctls.
8  *
9  * The author dedicates this file to the public domain.
10  * You can do whatever you want with this file.
11  */
12
13 #ifndef _WOF_H_
14 #define _WOF_H_
15
16 #include "wimlib/compiler.h"
17 #include "wimlib/types.h"
18
19 /*
20  * The Windows Overlay Filesystem filter (WOF, a.k.a. wof.sys) is a filesystem
21  * filter driver, available in Windows 8.1 and later, which allows files to be
22  * "externally backed", meaning that their data is stored in another location,
23  * possibly in compressed form.
24  *
25  * WOF implements a plug-in mechanism by which a specific "provider" is
26  * responsible for actually externally backing a given file.  The currently
27  * known providers are:
28  *
29  *      - The WIM provider: allows a file to be externally backed by a
30  *        compressed resource in a WIM archive
31  *      - The file provider: allows a file to be "externally backed" by a named
32  *        data stream stored with the file itself, where that named data stream
33  *        has the format of a compressed WIM resource
34  *
35  * For both of these providers, externally backed files are effectively
36  * read-only.  If you try to write to such a file, Windows automatically
37  * decompresses it and turns it into a regular, non-externally-backed file.
38  *
39  * WOF provides various ioctls that control its operation.  For example,
40  * FSCTL_SET_EXTERNAL_BACKING sets up a file as externally backed.
41  *
42  * WOF external backings are implemented using reparse points.  One consequence
43  * of this is that WOF external backings can only be set on files that do not
44  * already have a reparse point set.  Another consequence of this is that it is
45  * possible to create a WOF external backing by manually creating the reparse
46  * point, although this requires dealing with undocumented data structures and
47  * it only works when the WOF driver is not currently attached to the volume.
48  *
49  * Note that only the unnamed data stream portion of a file can be externally
50  * backed.  Other NTFS streams and metadata are not externally backed.
51  */
52
53
54 /* Current version of the WOF driver/protocol  */
55 #define WOF_CURRENT_VERSION             1
56
57 /* Specifies the WIM backing provider  */
58 #define WOF_PROVIDER_WIM                1
59
60 /* Specifies the "file" backing provider (a.k.a. System Compression)  */
61 #define WOF_PROVIDER_FILE               2
62
63 /* The current version of the WIM backing provider  */
64 #define WIM_PROVIDER_CURRENT_VERSION    1
65
66 /* The current version of the file backing provider  */
67 #define FILE_PROVIDER_CURRENT_VERSION   1
68
69 /* Identifies a backing provider for a specific overlay service version.  */
70 struct wof_external_info {
71
72         /* Version of the overlay service supported by the backing provider.
73          * Set to WOF_CURRENT_VERSION.  */
74         u32 version;
75
76         /* Identifier for the backing provider.  Example value:
77          * WOF_PROVIDER_WIM.  */
78         u32 provider;
79 };
80
81
82 /*
83  * Format of the WIM provider reparse data.  This is the data which follows the
84  * portion of the reparse point common to WOF.  (The common portion consists of
85  * a reparse point header where the reparse tag is 0x80000017, then a 'struct
86  * wof_external_info' which specifies the provider.)
87  *
88  * Note that Microsoft does not document any of the reparse point formats for
89  * WOF, although they document the structures which must be passed into the
90  * ioctls, which are often similar.
91  */
92 struct wim_provider_rpdata {
93         /* Set to 2.  Uncertain meaning.  */
94         le32 version;
95
96         /* 0 when WIM provider active, otherwise
97          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
98          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
99         le32 flags;
100
101         /* Integer ID that identifies the WIM.  */
102         le64 data_source_id;
103
104         /* SHA-1 message digest of the file's unnamed data stream.  */
105         u8 unnamed_data_stream_hash[20];
106
107         /* SHA-1 message digest of the WIM's blob table as stored on disk.  */
108         u8 blob_table_hash[20];
109
110         /* Uncompressed size of the file's unnamed data stream, in bytes.  */
111         le64 unnamed_data_stream_size;
112
113         /* Size of the file's unnamed data stream as stored in the WIM file.
114          * If this is the same as unnamed_data_stream_size, then the stream is
115          * uncompressed.  If this is the *not* the same as
116          * unnamed_data_stream_size, then the stream is compressed.  */
117         le64 unnamed_data_stream_size_in_wim;
118
119         /* Byte offset of the file's unnamed data stream in the WIM.  */
120         le64 unnamed_data_stream_offset_in_wim;
121 } _packed_attribute;
122
123 /* WIM-specific information about a WIM data source  */
124 struct WimOverlay_dat_entry_1 {
125
126         /* Identifier for the WIM data source, (normally allocated by
127          * FSCTL_ADD_OVERLAY).  Every 'WimOverlay_dat_entry_1' should have a
128          * different value for this.  */
129         le64 data_source_id;
130
131         /* Byte offset, from the beginning of the file, of the corresponding
132          * 'struct WimOverlay_dat_entry_2' for this WIM data source.  */
133         le32 entry_2_offset;
134
135         /* Size, in bytes, of the corresponding 'struct WimOverlay_dat_entry_2
136          * for this WIM data source, including wim_file_name and its null
137          * terminator.  */
138         le32 entry_2_length;
139
140         /* Type of the WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM.  */
141         le32 wim_type;
142
143         /* Index of the image in the WIM to use??? (This doesn't really make
144          * sense, since WIM files combine file data "blobs" for all images into
145          * a single table.  Set to 1 if unsure...)  */
146         le32 wim_index;
147
148         /* GUID of the WIM file (copied from the WIM header, offset +0x18).  */
149         u8 guid[16];
150 } _packed_attribute;
151
152 /*
153  * Format of file: "\System Volume Information\WimOverlay.dat"
154  *
155  * Not documented by Microsoft.
156  *
157  * The file consists of a 'struct WimOverlay_dat_header' followed by one or more
158  * 'struct WimOverlay_dat_entry_1', followed by the same number of 'struct
159  * WimOverlay_dat_entry_2'.  Note that 'struct WimOverlay_dat_entry_1' is of
160  * fixed length, whereas 'struct WimOverlay_dat_entry_2' is of variable length.
161  */
162 struct WimOverlay_dat_header {
163         /* Set to WIMOVERLAY_DAT_MAGIC  */
164         le32 magic;
165 #define WIMOVERLAY_DAT_MAGIC 0x66436F57
166
167         /* Set to 1 (WIM_PROVIDER_CURRENT_VERSION)  */
168         le32 wim_provider_version;
169
170         /* Set to 0x00000028  */
171         le32 unknown_0x08;
172
173         /* Set to number of WIMs registered (listed in the file)  */
174         le32 num_entries;
175
176         /* The next available data source ID.  This is tracked so that data
177          * source IDs are never reused, even if a WIM is unregistered.  */
178         le64 next_data_source_id;
179
180         struct WimOverlay_dat_entry_1 entry_1s[];
181 } _packed_attribute;
182
183 /* Location information about a WIM data source  */
184 struct WimOverlay_dat_entry_2 {
185         /* Set to 0  */
186         le32 unknown_0x00;
187
188         /* Set to 0  */
189         le32 unknown_0x04;
190
191         /* Size, in bytes, of this 'struct WimOverlay_dat_entry_2', including
192          * wim_file_name and its null terminator.  */
193         le32 entry_2_length;
194
195         /* Set to 0  */
196         le32 unknown_0x0C;
197
198         /* Set to 5  */
199         le32 unknown_0x10;
200
201         struct {
202                 /* Set to 1  */
203                 le32 unknown_0x14;
204
205                 /* Size of this inner structure, in bytes.  */
206                 le32 inner_struct_size;
207
208                 /* Set to 5  */
209                 le32 unknown_0x1C;
210
211                 /* Set to 6  */
212                 le32 unknown_0x20;
213
214                 /* Set to 0  */
215                 le32 unknown_0x24;
216
217                 /* Set to 0x48  */
218                 le32 unknown_0x28;
219
220                 /* Set to 0  */
221                 le32 unknown_0x2C;
222
223                 /*************************
224                  * Partition information
225                  ************************/
226
227                 /* Partition identifier  */
228                 union {
229                         /* (For MBR-formatted disks)  */
230                         struct {
231                                 /* Offset, in bytes, of the MBR partition, from
232                                  * the beginning of the disk.  */
233                                 le64 part_start_offset;
234
235                                 /* Set to 0  */
236                                 le64 padding;
237                         } mbr;
238
239                         /* (For GPT-formatted disks)  */
240                         struct {
241                                 /* Unique GUID of the GPT partition  */
242                                 u8 part_unique_guid[16];
243                         } gpt;
244                 } partition;
245
246                 /* Set to 0  */
247                 le32 unknown_0x40;
248
249                 /***********************
250                  * Disk information
251                  **********************/
252
253                 /* 1 for MBR, 0 for GPT  */
254                 le32 partition_table_type;
255         #define WIMOVERLAY_PARTITION_TYPE_MBR 1
256         #define WIMOVERLAY_PARTITION_TYPE_GPT 0
257
258                 /* Disk identifier  */
259                 union {
260                         /* (For MBR-formatted disks)  */
261                         struct {
262                                 /* 4-byte ID of the MBR disk  */
263                                 le32 disk_id;
264
265                                 /* Set to 0  */
266                                 le32 padding[3];
267                         } mbr;
268
269                         /* (For GPT-formatted disks)  */
270                         struct {
271                                 /* GUID of the GPT disk  */
272                                 u8 disk_guid[16];
273                         } gpt;
274                 } disk;
275
276                 /* Set to 0.  (This is the right size for some sort of optional
277                  * GUID...)  */
278                 le32 unknown_0x58[4];
279
280                 /**************************
281                  * Location in filesystem
282                  *************************/
283
284                 /* Null-terminated path to WIM file.  Begins with \ but does
285                  * *not* include drive letter!  */
286                 utf16lechar wim_file_name[];
287         } _packed_attribute;
288 } _packed_attribute;
289
290 static _unused_attribute void
291 wof_check_structs(void)
292 {
293         STATIC_ASSERT(sizeof(struct WimOverlay_dat_header) == 24);
294         STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_1) == 40);
295         STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_2) == 104);
296 }
297
298 /*****************************************************************************
299  *
300  * --- FSCTL_SET_EXTERNAL_BACKING ---
301  *
302  * Sets the backing source of a file.
303  *
304  * DeviceType:  9 (FILE_DEVICE_FILE_SYSTEM)
305  * Access:      0 (FILE_ANY_ACCESS)
306  * Function:    195
307  * Method:      0 (METHOD_BUFFERED)
308  *
309  * Input buffer:  'struct wof_external_info' followed by provider-specific data
310  * ('struct wim_provider_external_info' in the case of WIM).
311  *
312  * Output buffer: None
313  */
314 #define FSCTL_SET_EXTERNAL_BACKING 0x9030C
315
316 struct wim_provider_external_info {
317
318         /* Set to WIM_PROVIDER_CURRENT_VERSION.  */
319         u32 version;
320
321         /* 0 when WIM provider active, otherwise
322          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
323          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
324         u32 flags;
325
326         /* Integer ID that identifies the WIM.  Get this with the
327          * FSCTL_ADD_OVERLAY ioctl.  */
328         u64 data_source_id;
329
330         /* SHA-1 message digest of the file's unnamed data stream.  */
331         u8 unnamed_data_stream_hash[20];
332 };
333
334 struct file_provider_external_info {
335
336         /* Set to FILE_PROVIDER_CURRENT_VERSION.  */
337         u32 version;
338
339         u32 compression_format;
340 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K       0
341 #define FILE_PROVIDER_COMPRESSION_FORMAT_LZX            1
342 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS8K       2
343 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS16K      3
344 };
345
346 /*****************************************************************************
347  *
348  * --- FSCTL_GET_EXTERNAL_BACKING ---
349  *
350  * Get external backing information for the specified file.
351  *
352  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
353  * Access:     0 (FILE_ANY_ACCESS)
354  * Function:   196
355  * Method:     0 (METHOD_BUFFERED)
356  *
357  * Input buffer: None
358  * Output buffer:  'struct wof_external_info' followed by provider-specific data
359  * ('struct wim_provider_external_info' in the case of WIM).
360  */
361 #define FSCTL_GET_EXTERNAL_BACKING 0x90310
362
363 #define STATUS_OBJECT_NOT_EXTERNALLY_BACKED     0xC000046D
364
365 /*****************************************************************************
366  *
367  * --- FSCTL_DELETE_EXTERNAL_BACKING ---
368  *
369  * Copy a file from its backing source to its volume, then disassociate it from
370  * its backing provider.
371  *
372  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
373  * Access:     0 (FILE_ANY_ACCESS)
374  * Function:   197
375  * Method:     0 (METHOD_BUFFERED)
376  *
377  * Input buffer: None
378  * Output buffer: None
379  */
380 #define FSCTL_DELETE_EXTERNAL_BACKING 0x90314
381
382 /*****************************************************************************
383  *
384  * --- FSCTL_ENUM_EXTERNAL_BACKING ---
385  *
386  * Enumerate externally backed files on a volume.
387  *
388  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
389  * Access:     0 (FILE_ANY_ACCESS)
390  * Function:   198
391  * Method:     0 (METHOD_BUFFERED)
392  *
393  * Input buffer: None
394  * Output buffer: A 16-byte buffer that receives the 128-bit file ID for the
395  * next externally backed file.
396  *
397  * The handle used may be either the volume handle or the handle for any file or
398  * directory on the volume.
399  *
400  * When all externally backed files on the volume have been enumerated, the
401  * function fails with ERROR_NO_MORE_FILES.
402  */
403 #define FSCTL_ENUM_EXTERNAL_BACKING 0x90318
404
405 /*****************************************************************************
406  *
407  * --- FSCTL_ENUM_OVERLAY ---
408  *
409  * Enumerates the volume's overlay sources from the specified provider.
410  *
411  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
412  * Access:     0 (FILE_ANY_ACCESS)
413  * Function:   199
414  * Method:     3 (METHOD_NEITHER)
415  *
416  * Input buffer:  'struct wof_external_info' to specify the provider for which
417  * to enumerate the overlay sources.
418  *
419  * Output buffer:  Provider-specific data.  For the WIM provider, an array of
420  * 'struct wim_provider_overlay_entry'.
421  *
422  * This ioctl must be performed on the volume handle, such as \\.\C:
423  */
424 #define FSCTL_ENUM_OVERLAY 0x9031F
425
426 struct wim_provider_overlay_entry {
427         /* Byte offset of the next entry from the beginning of this structure,
428          * or 0 if there are no more entries.  */
429         u32 next_entry_offset;
430
431         u32 padding;
432
433         /* Identifier for the WIM file.  */
434         u64 data_source_id;
435
436         /* GUID of the WIM file.  */
437         u8 guid[16];
438
439         /* Byte offset of the WIM's file name from the beginning of this
440          * structure.  */
441         u32 wim_file_name_offset;
442
443         /* Type of WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM.  */
444         u32 wim_type;
445
446         /* Index of the image in the WIM to use??? (This doesn't really make
447          * sense, since WIM files combine file data "blobs" for all images into
448          * a single table.  Set to 1 if unsure...)  */
449         u32 wim_index;
450
451         /* 0 when WIM provider active, otherwise
452          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
453          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
454         u32 flags;
455
456         /* Full path to the WIM in the NT device namespace, e.g.
457          * "\Device\HardDiskVolume2\test.wim".  Seems to be null-terminated,
458          * although you probably shouldn't assume so.  */
459         wchar_t wim_file_name[];
460 };
461
462
463 /*****************************************************************************
464  *
465  * --- FSCTL_ADD_OVERLAY ---
466  *
467  * Adds a new external backing source to a volume.
468  *
469  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
470  * Access:     2 (FILE_WRITE_ACCESS)
471  * Function:   204
472  * Method:     0 (METHOD_BUFFERED)
473  *
474  * Input buffer:  'struct wof_external_info' followed by provider-specific data
475  * ('struct wim_provider_add_overlay_input' in the case of WIM).
476  *
477  * Output buffer:  Buffer large enough to receive any information resulting from
478  * the add operation.  For the WIM provider, this must be an 8 byte buffer that
479  * receives the 64-bit WIM file ID.
480  *
481  * This ioctl must be performed on the volume handle, such as \\.\C:
482  */
483 #define FSCTL_ADD_OVERLAY 0x98330
484
485 struct wim_provider_add_overlay_input {
486
487         /* Type of WIM file.  */
488         u32 wim_type;
489 #define WIM_BOOT_OS_WIM         0
490 #define WIM_BOOT_NOT_OS_WIM     1
491
492         /* Index of the image in the WIM to use??? (This doesn't really make
493          * sense, since WIM files combine file data "blobs" for all images into
494          * a single table.  Set to 1 if unsure...)  */
495         u32 wim_index;
496
497         /* Byte offset of wim_file_name in this buffer, not including the
498          * preceding 'struct wof_external_info' (should be 16).  */
499         u32 wim_file_name_offset;
500
501         /* Number of bytes in wim_file_name.  */
502         u32 wim_file_name_length;
503
504         /* Full path to the WIM, e.g. "\??\C:\test-wimboot.wim".
505          * Does NOT need to be null terminated (MS docs claim otherwise).  */
506         wchar_t wim_file_name[];
507 };
508
509 /*****************************************************************************
510  *
511  * --- FSCTL_REMOVE_OVERLAY ---
512  *
513  * Removes an external backing source from a volume.
514  *
515  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
516  * Access:     2 (FILE_WRITE_ACCESS)
517  * Function:   205
518  * Method:     0 (METHOD_BUFFERED)
519  *
520  * Input buffer:  'struct wof_external_info' followed by provider-specific data
521  * ('struct wim_provider_remove_overlay_input' in the case of WIM).
522  *
523  * Output buffer:  None
524  *
525  * This ioctl must be performed on the volume handle, such as \\.\C:
526  */
527 #define FSCTL_REMOVE_OVERLAY 0x98334
528
529 struct wim_provider_remove_overlay_input {
530         /* Integer ID that identifies the WIM.  */
531         u64 data_source_id;
532 };
533
534
535 /*****************************************************************************
536  *
537  * --- FSCTL_UPDATE_OVERLAY ---
538  *
539  * Updates an overlay source for a volume.
540  *
541  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
542  * Access:     2 (FILE_WRITE_ACCESS)
543  * Function:   206
544  * Method:     0 (METHOD_BUFFERED)
545  *
546  * Input buffer:  'struct wof_external_info' followed by provider-specific data
547  * ('struct wim_provider_update_overlay_input' in the case of WIM).
548  *
549  * Output buffer:  None
550  *
551  * This ioctl must be performed on the volume handle, such as \\.\C:
552  */
553 #define FSCTL_UPDATE_OVERLAY 0x98338
554
555 struct wim_provider_update_overlay_input {
556         /* Integer ID that identifies the WIM data source.  */
557         u64 data_source_id;
558
559         /* Byte offset of wim_file_name in this buffer, not including the
560          * preceding 'struct wof_external_info' (should be 16).  */
561         u32 wim_file_name_offset;
562
563         /* Number of bytes in wim_file_name.  */
564         u32 wim_file_name_length;
565
566         /* Full path to the WIM, e.g. "\??\C:\test-wimboot.wim".
567          * Does NOT need to be null terminated (MS docs claim otherwise).
568          * This WIM must be renamed from the original WIM, or at least be an
569          * identical copy of it!  (Maybe the WIM's GUID field is checked.)  */
570         wchar_t wim_file_name[];
571 };
572
573 #endif /* _WOF_H_ */