]> wimlib.net Git - wimlib/blob - include/wimlib/wof.h
Improve random number generation
[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 following copying information applies to this specific source code file:
10  *
11  * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
12  *
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").
17  *
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.
21  *
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/>.
24  */
25
26 #ifndef _WOF_H_
27 #define _WOF_H_
28
29 #include "wimlib/compiler.h"
30 #include "wimlib/types.h"
31
32 /*
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.
37  *
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:
41  *
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
47  *
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.
51  *
52  * WOF provides various ioctls that control its operation.  For example,
53  * FSCTL_SET_EXTERNAL_BACKING sets up a file as externally backed.
54  *
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.
61  *
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.
64  */
65
66
67 /* Current version of the WOF driver/protocol  */
68 #define WOF_CURRENT_VERSION             1
69
70 /* Specifies the WIM backing provider  */
71 #define WOF_PROVIDER_WIM                1
72
73 /* Specifies the "file" backing provider (a.k.a. System Compression)  */
74 #define WOF_PROVIDER_FILE               2
75
76 /* The current version of the WIM backing provider  */
77 #define WIM_PROVIDER_CURRENT_VERSION    1
78
79 /* The current version of the file backing provider  */
80 #define FILE_PROVIDER_CURRENT_VERSION   1
81
82 /* Identifies a backing provider for a specific overlay service version.  */
83 struct wof_external_info {
84
85         /* Version of the overlay service supported by the backing provider.
86          * Set to WOF_CURRENT_VERSION.  */
87         u32 version;
88
89         /* Identifier for the backing provider.  Example value:
90          * WOF_PROVIDER_WIM.  */
91         u32 provider;
92 };
93
94
95 /*
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.)
100  *
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.
104  */
105 struct wim_provider_rpdata {
106         /* Set to 2.  Uncertain meaning.  */
107         le32 version;
108
109         /* 0 when WIM provider active, otherwise
110          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
111          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
112         le32 flags;
113
114         /* Integer ID that identifies the WIM.  */
115         le64 data_source_id;
116
117         /* SHA-1 message digest of the file's unnamed data stream.  */
118         u8 unnamed_data_stream_hash[20];
119
120         /* SHA-1 message digest of the WIM's blob table as stored on disk.  */
121         u8 blob_table_hash[20];
122
123         /* Uncompressed size of the file's unnamed data stream, in bytes.  */
124         le64 unnamed_data_stream_size;
125
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;
131
132         /* Byte offset of the file's unnamed data stream in the WIM.  */
133         le64 unnamed_data_stream_offset_in_wim;
134 } _packed_attribute;
135
136 /* WIM-specific information about a WIM data source  */
137 struct WimOverlay_dat_entry_1 {
138
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.  */
142         le64 data_source_id;
143
144         /* Byte offset, from the beginning of the file, of the corresponding
145          * 'struct WimOverlay_dat_entry_2' for this WIM data source.  */
146         le32 entry_2_offset;
147
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
150          * terminator.  */
151         le32 entry_2_length;
152
153         /* Type of the WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM.  */
154         le32 wim_type;
155
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...)  */
159         le32 wim_index;
160
161         /* GUID of the WIM file (copied from the WIM header, offset +0x18).  */
162         u8 guid[16];
163 } _packed_attribute;
164
165 /*
166  * Format of file: "\System Volume Information\WimOverlay.dat"
167  *
168  * Not documented by Microsoft.
169  *
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.
174  */
175 struct WimOverlay_dat_header {
176         /* Set to WIMOVERLAY_DAT_MAGIC  */
177         le32 magic;
178 #define WIMOVERLAY_DAT_MAGIC 0x66436F57
179
180         /* Set to 1 (WIM_PROVIDER_CURRENT_VERSION)  */
181         le32 wim_provider_version;
182
183         /* Set to 0x00000028  */
184         le32 unknown_0x08;
185
186         /* Set to number of WIMs registered (listed in the file)  */
187         le32 num_entries;
188
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;
192
193         struct WimOverlay_dat_entry_1 entry_1s[];
194 } _packed_attribute;
195
196 /* Location information about a WIM data source  */
197 struct WimOverlay_dat_entry_2 {
198         /* Set to 0  */
199         le32 unknown_0x00;
200
201         /* Set to 0  */
202         le32 unknown_0x04;
203
204         /* Size, in bytes, of this 'struct WimOverlay_dat_entry_2', including
205          * wim_file_name and its null terminator.  */
206         le32 entry_2_length;
207
208         /* Set to 0  */
209         le32 unknown_0x0C;
210
211         /* Set to 5  */
212         le32 unknown_0x10;
213
214         struct {
215                 /* Set to 1  */
216                 le32 unknown_0x14;
217
218                 /* Size of this inner structure, in bytes.  */
219                 le32 inner_struct_size;
220
221                 /* Set to 5  */
222                 le32 unknown_0x1C;
223
224                 /* Set to 6  */
225                 le32 unknown_0x20;
226
227                 /* Set to 0  */
228                 le32 unknown_0x24;
229
230                 /* Set to 0x48  */
231                 le32 unknown_0x28;
232
233                 /* Set to 0  */
234                 le32 unknown_0x2C;
235
236                 /*************************
237                  * Partition information
238                  ************************/
239
240                 /* Partition identifier  */
241                 union {
242                         /* (For MBR-formatted disks)  */
243                         struct {
244                                 /* Offset, in bytes, of the MBR partition, from
245                                  * the beginning of the disk.  */
246                                 le64 part_start_offset;
247
248                                 /* Set to 0  */
249                                 le64 padding;
250                         } mbr;
251
252                         /* (For GPT-formatted disks)  */
253                         struct {
254                                 /* Unique GUID of the GPT partition  */
255                                 u8 part_unique_guid[16];
256                         } gpt;
257                 } partition;
258
259                 /* Set to 0  */
260                 le32 unknown_0x40;
261
262                 /***********************
263                  * Disk information
264                  **********************/
265
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
270
271                 /* Disk identifier  */
272                 union {
273                         /* (For MBR-formatted disks)  */
274                         struct {
275                                 /* 4-byte ID of the MBR disk  */
276                                 le32 disk_id;
277
278                                 /* Set to 0  */
279                                 le32 padding[3];
280                         } mbr;
281
282                         /* (For GPT-formatted disks)  */
283                         struct {
284                                 /* GUID of the GPT disk  */
285                                 u8 disk_guid[16];
286                         } gpt;
287                 } disk;
288
289                 /* Set to 0.  (This is the right size for some sort of optional
290                  * GUID...)  */
291                 le32 unknown_0x58[4];
292
293                 /**************************
294                  * Location in filesystem
295                  *************************/
296
297                 /* Null-terminated path to WIM file.  Begins with \ but does
298                  * *not* include drive letter!  */
299                 utf16lechar wim_file_name[];
300         } _packed_attribute;
301 } _packed_attribute;
302
303 static _unused_attribute void
304 wof_check_structs(void)
305 {
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);
309 }
310
311 /*****************************************************************************
312  *
313  * --- FSCTL_SET_EXTERNAL_BACKING ---
314  *
315  * Sets the backing source of a file.
316  *
317  * DeviceType:  9 (FILE_DEVICE_FILE_SYSTEM)
318  * Access:      0 (FILE_ANY_ACCESS)
319  * Function:    195
320  * Method:      0 (METHOD_BUFFERED)
321  *
322  * Input buffer:  'struct wof_external_info' followed by provider-specific data
323  * ('struct wim_provider_external_info' in the case of WIM).
324  *
325  * Output buffer: None
326  */
327 #define FSCTL_SET_EXTERNAL_BACKING 0x9030C
328
329 struct wim_provider_external_info {
330
331         /* Set to WIM_PROVIDER_CURRENT_VERSION.  */
332         u32 version;
333
334         /* 0 when WIM provider active, otherwise
335          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
336          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
337         u32 flags;
338
339         /* Integer ID that identifies the WIM.  Get this with the
340          * FSCTL_ADD_OVERLAY ioctl.  */
341         u64 data_source_id;
342
343         /* SHA-1 message digest of the file's unnamed data stream.  */
344         u8 unnamed_data_stream_hash[20];
345 };
346
347 struct file_provider_external_info {
348
349         /* Set to FILE_PROVIDER_CURRENT_VERSION.  */
350         u32 version;
351
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
357 };
358
359 /*****************************************************************************
360  *
361  * --- FSCTL_GET_EXTERNAL_BACKING ---
362  *
363  * Get external backing information for the specified file.
364  *
365  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
366  * Access:     0 (FILE_ANY_ACCESS)
367  * Function:   196
368  * Method:     0 (METHOD_BUFFERED)
369  *
370  * Input buffer: None
371  * Output buffer:  'struct wof_external_info' followed by provider-specific data
372  * ('struct wim_provider_external_info' in the case of WIM).
373  */
374 #define FSCTL_GET_EXTERNAL_BACKING 0x90310
375
376 #define STATUS_OBJECT_NOT_EXTERNALLY_BACKED     0xC000046D
377
378 /*****************************************************************************
379  *
380  * --- FSCTL_DELETE_EXTERNAL_BACKING ---
381  *
382  * Copy a file from its backing source to its volume, then disassociate it from
383  * its backing provider.
384  *
385  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
386  * Access:     0 (FILE_ANY_ACCESS)
387  * Function:   197
388  * Method:     0 (METHOD_BUFFERED)
389  *
390  * Input buffer: None
391  * Output buffer: None
392  */
393 #define FSCTL_DELETE_EXTERNAL_BACKING 0x90314
394
395 /*****************************************************************************
396  *
397  * --- FSCTL_ENUM_EXTERNAL_BACKING ---
398  *
399  * Enumerate externally backed files on a volume.
400  *
401  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
402  * Access:     0 (FILE_ANY_ACCESS)
403  * Function:   198
404  * Method:     0 (METHOD_BUFFERED)
405  *
406  * Input buffer: None
407  * Output buffer: A 16-byte buffer that receives the 128-bit file ID for the
408  * next externally backed file.
409  *
410  * The handle used may be either the volume handle or the handle for any file or
411  * directory on the volume.
412  *
413  * When all externally backed files on the volume have been enumerated, the
414  * function fails with ERROR_NO_MORE_FILES.
415  */
416 #define FSCTL_ENUM_EXTERNAL_BACKING 0x90318
417
418 /*****************************************************************************
419  *
420  * --- FSCTL_ENUM_OVERLAY ---
421  *
422  * Enumerates the volume's overlay sources from the specified provider.
423  *
424  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
425  * Access:     0 (FILE_ANY_ACCESS)
426  * Function:   199
427  * Method:     3 (METHOD_NEITHER)
428  *
429  * Input buffer:  'struct wof_external_info' to specify the provider for which
430  * to enumerate the overlay sources.
431  *
432  * Output buffer:  Provider-specific data.  For the WIM provider, an array of
433  * 'struct wim_provider_overlay_entry'.
434  *
435  * This ioctl must be performed on the volume handle, such as \\.\C:
436  */
437 #define FSCTL_ENUM_OVERLAY 0x9031F
438
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;
443
444         u32 padding;
445
446         /* Identifier for the WIM file.  */
447         u64 data_source_id;
448
449         /* GUID of the WIM file.  */
450         u8 guid[16];
451
452         /* Byte offset of the WIM's file name from the beginning of this
453          * structure.  */
454         u32 wim_file_name_offset;
455
456         /* Type of WIM file: WIM_BOOT_OS_WIM or WIM_BOOT_NOT_OS_WIM.  */
457         u32 wim_type;
458
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...)  */
462         u32 wim_index;
463
464         /* 0 when WIM provider active, otherwise
465          * WIM_PROVIDER_EXTERNAL_FLAG_NOT_ACTIVE or
466          * WIM_PROVIDER_EXTERNAL_FLAG_SUSPENDED.  */
467         u32 flags;
468
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[];
473 };
474
475
476 /*****************************************************************************
477  *
478  * --- FSCTL_ADD_OVERLAY ---
479  *
480  * Adds a new external backing source to a volume.
481  *
482  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
483  * Access:     2 (FILE_WRITE_ACCESS)
484  * Function:   204
485  * Method:     0 (METHOD_BUFFERED)
486  *
487  * Input buffer:  'struct wof_external_info' followed by provider-specific data
488  * ('struct wim_provider_add_overlay_input' in the case of WIM).
489  *
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.
493  *
494  * This ioctl must be performed on the volume handle, such as \\.\C:
495  */
496 #define FSCTL_ADD_OVERLAY 0x98330
497
498 struct wim_provider_add_overlay_input {
499
500         /* Type of WIM file.  */
501         u32 wim_type;
502 #define WIM_BOOT_OS_WIM         0
503 #define WIM_BOOT_NOT_OS_WIM     1
504
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...)  */
508         u32 wim_index;
509
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;
513
514         /* Number of bytes in wim_file_name.  */
515         u32 wim_file_name_length;
516
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[];
520 };
521
522 /*****************************************************************************
523  *
524  * --- FSCTL_REMOVE_OVERLAY ---
525  *
526  * Removes an external backing source from a volume.
527  *
528  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
529  * Access:     2 (FILE_WRITE_ACCESS)
530  * Function:   205
531  * Method:     0 (METHOD_BUFFERED)
532  *
533  * Input buffer:  'struct wof_external_info' followed by provider-specific data
534  * ('struct wim_provider_remove_overlay_input' in the case of WIM).
535  *
536  * Output buffer:  None
537  *
538  * This ioctl must be performed on the volume handle, such as \\.\C:
539  */
540 #define FSCTL_REMOVE_OVERLAY 0x98334
541
542 struct wim_provider_remove_overlay_input {
543         /* Integer ID that identifies the WIM.  */
544         u64 data_source_id;
545 };
546
547
548 /*****************************************************************************
549  *
550  * --- FSCTL_UPDATE_OVERLAY ---
551  *
552  * Updates an overlay source for a volume.
553  *
554  * DeviceType: 9 (FILE_DEVICE_FILE_SYSTEM)
555  * Access:     2 (FILE_WRITE_ACCESS)
556  * Function:   206
557  * Method:     0 (METHOD_BUFFERED)
558  *
559  * Input buffer:  'struct wof_external_info' followed by provider-specific data
560  * ('struct wim_provider_update_overlay_input' in the case of WIM).
561  *
562  * Output buffer:  None
563  *
564  * This ioctl must be performed on the volume handle, such as \\.\C:
565  */
566 #define FSCTL_UPDATE_OVERLAY 0x98338
567
568 struct wim_provider_update_overlay_input {
569         /* Integer ID that identifies the WIM data source.  */
570         u64 data_source_id;
571
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;
575
576         /* Number of bytes in wim_file_name.  */
577         u32 wim_file_name_length;
578
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[];
584 };
585
586 #endif /* _WOF_H_ */