]> wimlib.net Git - wimlib/blob - include/wimlib/wof.h
system compression: try to attach WOF if compression fails
[wimlib] / include / wimlib / wof.h
1 /*
2  * wof.h
3  *
4  * Definitions for the Windows Overlay File System 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;
174          * also the number of 'struct WimOverlay_dat_entry_1' that follow.  */
175         le32 num_entries_1;
176
177         /* Set to number of WIMs registered;
178          * also the number of 'struct WimOverlay_dat_entry_2' that follow.  */
179         le32 num_entries_2;
180
181         /* Set to 0  */
182         le32 unknown_0x14;
183
184         struct WimOverlay_dat_entry_1 entry_1s[];
185 } _packed_attribute;
186
187 /* Location information about a WIM data source  */
188 struct WimOverlay_dat_entry_2 {
189         /* Set to 0  */
190         le32 unknown_0x00;
191
192         /* Set to 0  */
193         le32 unknown_0x04;
194
195         /* Size, in bytes, of this 'struct WimOverlay_dat_entry_2', including
196          * wim_file_name and its null terminator.  */
197         le32 entry_2_length;
198
199         /* Set to 0  */
200         le32 unknown_0x0C;
201
202         /* Set to 5  */
203         le32 unknown_0x10;
204
205         struct {
206                 /* Set to 1  */
207                 le32 unknown_0x14;
208
209                 /* Size of this inner structure, in bytes.  */
210                 le32 inner_struct_size;
211
212                 /* Set to 5  */
213                 le32 unknown_0x1C;
214
215                 /* Set to 6  */
216                 le32 unknown_0x20;
217
218                 /* Set to 0  */
219                 le32 unknown_0x24;
220
221                 /* Set to 0x48  */
222                 le32 unknown_0x28;
223
224                 /* Set to 0  */
225                 le32 unknown_0x2C;
226
227                 /*************************
228                  * Partition information
229                  ************************/
230
231                 /* Partition identifier  */
232                 union {
233                         /* (For MBR-formatted disks)  */
234                         struct {
235                                 /* Offset, in bytes, of the MBR partition, from
236                                  * the beginning of the disk.  */
237                                 le64 part_start_offset;
238
239                                 /* Set to 0  */
240                                 le64 padding;
241                         } mbr;
242
243                         /* (For GPT-formatted disks)  */
244                         struct {
245                                 /* Unique GUID of the GPT partition  */
246                                 u8 part_unique_guid[16];
247                         } gpt;
248                 } partition;
249
250                 /* Set to 0  */
251                 le32 unknown_0x40;
252
253                 /***********************
254                  * Disk information
255                  **********************/
256
257                 /* 1 for MBR, 0 for GPT  */
258                 le32 partition_table_type;
259         #define WIMOVERLAY_PARTITION_TYPE_MBR 1
260         #define WIMOVERLAY_PARTITION_TYPE_GPT 0
261
262                 /* Disk identifier  */
263                 union {
264                         /* (For MBR-formatted disks)  */
265                         struct {
266                                 /* 4-byte ID of the MBR disk  */
267                                 le32 disk_id;
268
269                                 /* Set to 0  */
270                                 le32 padding[3];
271                         } mbr;
272
273                         /* (For GPT-formatted disks)  */
274                         struct {
275                                 /* GUID of the GPT disk  */
276                                 u8 disk_guid[16];
277                         } gpt;
278                 } disk;
279
280                 /* Set to 0.  (This is the right size for some sort of optional
281                  * GUID...)  */
282                 le32 unknown_0x58[4];
283
284                 /**************************
285                  * Location in filesystem
286                  *************************/
287
288                 /* Null-terminated path to WIM file.  Begins with \ but does
289                  * *not* include drive letter!  */
290                 utf16lechar wim_file_name[];
291         } _packed_attribute;
292 } _packed_attribute;
293
294 static inline void
295 wof_check_structs(void)
296 {
297         STATIC_ASSERT(sizeof(struct WimOverlay_dat_header) == 24);
298         STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_1) == 40);
299         STATIC_ASSERT(sizeof(struct WimOverlay_dat_entry_2) == 104);
300 }
301
302 /*****************************************************************************
303  *
304  * --- FSCTL_SET_EXTERNAL_BACKING ---
305  *
306  * Sets the backing source of a file.
307  *
308  * DeviceType:  9 (FILE_DEVICE_FILE_SYSTEM)
309  * Access:      0 (FILE_ANY_ACCESS)
310  * Function:    195
311  * Method:      0 (METHOD_BUFFERED)
312  *
313  * Input buffer:  'struct wof_external_info' followed by provider-specific data
314  * ('struct wim_provider_external_info' in the case of WIM).
315  *
316  * Output buffer: None
317  */
318 #define FSCTL_SET_EXTERNAL_BACKING 0x9030C
319
320 struct wim_provider_external_info {
321
322         /* Set to WIM_PROVIDER_CURRENT_VERSION.  */
323         u32 version;
324
325         /* 0 when WIM provider active, otherwise
326          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
327          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
328         u32 flags;
329
330         /* Integer ID that identifies the WIM.  Get this with the
331          * FSCTL_ADD_OVERLAY ioctl.  */
332         u64 data_source_id;
333
334         /* SHA-1 message digest of the file's unnamed data stream.  */
335         u8 unnamed_data_stream_hash[20];
336 };
337
338 struct file_provider_external_info {
339
340         /* Set to FILE_PROVIDER_CURRENT_VERSION.  */
341         u32 version;
342
343         u32 compression_format;
344 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K       0
345 #define FILE_PROVIDER_COMPRESSION_FORMAT_LZX            1
346 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS8K       2
347 #define FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS16K      3
348 };
349
350 /*****************************************************************************
351  *
352  * --- FSCTL_GET_EXTERNAL_BACKING ---
353  *
354  * Get external backing information for the specified file.
355  *
356  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
357  * Access:     0 (FILE_ANY_ACCESS)
358  * Function:   196
359  * Method:     0 (METHOD_BUFFERED)
360  *
361  * Input buffer: None
362  * Output buffer:  'struct wof_external_info' followed by provider-specific data
363  * ('struct wim_provider_external_info' in the case of WIM).
364  */
365 #define FSCTL_GET_EXTERNAL_BACKING 0x90310
366
367 /*****************************************************************************
368  *
369  * --- FSCTL_DELETE_EXTERNAL_BACKING ---
370  *
371  * Copy a file from its backing source to its volume, then disassociate it from
372  * its backing provider.
373  *
374  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
375  * Access:     0 (FILE_ANY_ACCESS)
376  * Function:   197
377  * Method:     0 (METHOD_BUFFERED)
378  *
379  * Input buffer: None
380  * Output buffer: None
381  */
382 #define FSCTL_DELETE_EXTERNAL_BACKING 0x90314
383
384 /*****************************************************************************
385  *
386  * --- FSCTL_ENUM_EXTERNAL_BACKING ---
387  *
388  * Enumerate externally backed files on a volume.
389  *
390  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
391  * Access:     0 (FILE_ANY_ACCESS)
392  * Function:   198
393  * Method:     0 (METHOD_BUFFERED)
394  *
395  * Input buffer: None
396  * Output buffer: A 16-byte buffer that receives the 128-bit file ID for the
397  * next externally backed file.
398  *
399  * The handle used may be either the volume handle or the handle for any file or
400  * directory on the volume.
401  *
402  * When all externally backed files on the volume have been enumerated, the
403  * function fails with ERROR_NO_MORE_FILES.
404  */
405 #define FSCTL_ENUM_EXTERNAL_BACKING 0x90318
406
407 /*****************************************************************************
408  *
409  * --- FSCTL_ENUM_OVERLAY ---
410  *
411  * Enumerates the volume's overlay sources from the specified provider.
412  *
413  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
414  * Access:     0 (FILE_ANY_ACCESS)
415  * Function:   199
416  * Method:     3 (METHOD_NEITHER)
417  *
418  * Input buffer:  'struct wof_external_info' to specify the provider for which
419  * to enumerate the overlay sources.
420  *
421  * Output buffer:  Provider-specific data.  For the WIM provider, an array of
422  * 'struct wim_provider_overlay_entry'.
423  *
424  * This ioctl must be performed on the volume handle, such as \\.\C:
425  */
426 #define FSCTL_ENUM_OVERLAY 0x9031F
427
428 struct wim_provider_overlay_entry {
429         /* Byte offset of the next entry from the beginning of this structure,
430          * or 0 if there are no more entries.  */
431         u32 next_entry_offset;
432
433         u32 padding;
434
435         /* Identifier for the WIM file.  */
436         u64 data_source_id;
437
438         /* GUID of the WIM file.  */
439         u8 guid[16];
440
441         /* Byte offset of the WIM's file name from the beginning of this
442          * structure.  */
443         u32 wim_file_name_offset;
444
445         /* Type of WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM.  */
446         u32 wim_type;
447
448         /* Index of the image in the WIM to use??? (This doesn't really make
449          * sense, since WIM files combine file data "blobs" for all images into
450          * a single table.  Set to 1 if unsure...)  */
451         u32 wim_index;
452
453         /* 0 when WIM provider active, otherwise
454          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
455          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
456         u32 flags;
457
458         /* Full path to the WIM in the NT device namespace, e.g.
459          * "\Device\HardDiskVolume2\test.wim".  Seems to be null-terminated,
460          * although you probably shouldn't assume so.  */
461         wchar_t wim_file_name[];
462 };
463
464
465 /*****************************************************************************
466  *
467  * --- FSCTL_ADD_OVERLAY ---
468  *
469  * Adds a new external backing source to a volume.
470  *
471  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
472  * Access:     2 (FILE_WRITE_ACCESS)
473  * Function:   204
474  * Method:     0 (METHOD_BUFFERED)
475  *
476  * Input buffer:  'struct wof_external_info' followed by provider-specific data
477  * ('struct wim_provider_add_overlay_input' in the case of WIM).
478  *
479  * Output buffer:  Buffer large enough to receive any information resulting from
480  * the add operation.  For the WIM provider, this must be an 8 byte buffer that
481  * receives the 64-bit WIM file ID.
482  *
483  * This ioctl must be performed on the volume handle, such as \\.\C:
484  */
485 #define FSCTL_ADD_OVERLAY 0x98330
486
487 struct wim_provider_add_overlay_input {
488
489         /* Type of WIM file.  */
490         u32 wim_type;
491 #define WIM_BOOT_OS_WIM         0
492 #define WIM_BOOT_NOT_OS_WIM     1
493
494         /* Index of the image in the WIM to use??? (This doesn't really make
495          * sense, since WIM files combine file data "blobs" for all images into
496          * a single table.  Set to 1 if unsure...)  */
497         u32 wim_index;
498
499         /* Byte offset of wim_file_name in this buffer, not including the
500          * preceding 'struct wof_external_info' (should be 16).  */
501         u32 wim_file_name_offset;
502
503         /* Number of bytes in wim_file_name.  */
504         u32 wim_file_name_length;
505
506         /* Full path to the WIM, e.g. "\??\C:\test-wimboot.wim".
507          * Does NOT need to be null terminated (MS docs claim otherwise).  */
508         wchar_t wim_file_name[];
509 };
510
511 /*****************************************************************************
512  *
513  * --- FSCTL_REMOVE_OVERLAY ---
514  *
515  * Removes an external backing source from a volume.
516  *
517  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
518  * Access:     2 (FILE_WRITE_ACCESS)
519  * Function:   205
520  * Method:     0 (METHOD_BUFFERED)
521  *
522  * Input buffer:  'struct wof_external_info' followed by provider-specific data
523  * ('struct wim_provider_remove_overlay_input' in the case of WIM).
524  *
525  * Output buffer:  None
526  *
527  * This ioctl must be performed on the volume handle, such as \\.\C:
528  */
529 #define FSCTL_REMOVE_OVERLAY 0x98334
530
531 struct wim_provider_remove_overlay_input {
532         /* Integer ID that identifies the WIM.  */
533         u64 data_source_id;
534 };
535
536
537 /*****************************************************************************
538  *
539  * --- FSCTL_UPDATE_OVERLAY ---
540  *
541  * Updates an overlay source for a volume.
542  *
543  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
544  * Access:     2 (FILE_WRITE_ACCESS)
545  * Function:   206
546  * Method:     0 (METHOD_BUFFERED)
547  *
548  * Input buffer:  'struct wof_external_info' followed by provider-specific data
549  * ('struct wim_provider_update_overlay_input' in the case of WIM).
550  *
551  * Output buffer:  None
552  *
553  * This ioctl must be performed on the volume handle, such as \\.\C:
554  */
555 #define FSCTL_UPDATE_OVERLAY 0x98338
556
557 struct wim_provider_update_overlay_input {
558         /* Integer ID that identifies the WIM data source.  */
559         u64 data_source_id;
560
561         /* Byte offset of wim_file_name in this buffer, not including the
562          * preceding 'struct wof_external_info' (should be 16).  */
563         u32 wim_file_name_offset;
564
565         /* Number of bytes in wim_file_name.  */
566         u32 wim_file_name_length;
567
568         /* Full path to the WIM, e.g. "\??\C:\test-wimboot.wim".
569          * Does NOT need to be null terminated (MS docs claim otherwise).
570          * This WIM must be renamed from the original WIM, or at least be an
571          * identical copy of it!  (Maybe the WIM's GUID field is checked.)  */
572         wchar_t wim_file_name[];
573 };
574
575 #endif /* _WOF_H_ */