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