]> wimlib.net Git - wimlib/blob - src/win32_apply.c
7800e5994a5adf0aecda4532d32fc4a455c99359
[wimlib] / src / win32_apply.c
1 /*
2  * win32_apply.c - Windows-specific code for applying files from a WIM image.
3  */
4
5 /*
6  * Copyright (C) 2013, 2014 Eric Biggers
7  *
8  * This file is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the Free
10  * Software Foundation; either version 3 of the License, or (at your option) any
11  * later version.
12  *
13  * This file is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this file; if not, see http://www.gnu.org/licenses/.
20  */
21
22 #ifdef __WIN32__
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "wimlib/win32_common.h"
29
30 #include "wimlib/apply.h"
31 #include "wimlib/capture.h" /* for mangle_pat() and match_pattern_list()  */
32 #include "wimlib/dentry.h"
33 #include "wimlib/error.h"
34 #include "wimlib/lookup_table.h"
35 #include "wimlib/metadata.h"
36 #include "wimlib/reparse.h"
37 #include "wimlib/textfile.h"
38 #include "wimlib/xml.h"
39 #include "wimlib/wimboot.h"
40
41 struct win32_apply_ctx {
42
43         /* Extract flags, the pointer to the WIMStruct, etc.  */
44         struct apply_ctx common;
45
46         /* WIMBoot information, only filled in if WIMLIB_EXTRACT_FLAG_WIMBOOT
47          * was provided  */
48         struct {
49                 u64 data_source_id;
50                 struct string_set *prepopulate_pats;
51                 void *mem_prepopulate_pats;
52                 u8 wim_lookup_table_hash[SHA1_HASH_SIZE];
53                 bool wof_running;
54                 bool tried_to_load_prepopulate_list;
55         } wimboot;
56
57         /* Open handle to the target directory  */
58         HANDLE h_target;
59
60         /* NT namespace path to the target directory (buffer allocated)  */
61         UNICODE_STRING target_ntpath;
62
63         /* Temporary buffer for building paths (buffer allocated)  */
64         UNICODE_STRING pathbuf;
65
66         /* Object attributes to reuse for opening files in the target directory.
67          * (attr.ObjectName == &pathbuf) and (attr.RootDirectory == h_target).
68          */
69         OBJECT_ATTRIBUTES attr;
70
71         /* Temporary I/O status block for system calls  */
72         IO_STATUS_BLOCK iosb;
73
74         /* Allocated buffer for creating "printable" paths from our
75          * target-relative NT paths  */
76         wchar_t *print_buffer;
77
78         /* Allocated buffer for reading stream data when it cannot be extracted
79          * directly  */
80         u8 *data_buffer;
81
82         /* Pointer to the next byte in @data_buffer to fill  */
83         u8 *data_buffer_ptr;
84
85         /* Size allocated in @data_buffer  */
86         size_t data_buffer_size;
87
88         /* Current offset in the raw encrypted file being written  */
89         size_t encrypted_offset;
90
91         /* Current size of the raw encrypted file being written  */
92         size_t encrypted_size;
93
94         /* Temporary buffer for reparse data  */
95         struct reparse_buffer_disk rpbuf;
96
97         /* Temporary buffer for reparse data of "fixed" absolute symbolic links
98          * and junctions  */
99         struct reparse_buffer_disk rpfixbuf;
100
101         /* Array of open handles to filesystem streams currently being written
102          */
103         HANDLE open_handles[MAX_OPEN_STREAMS];
104
105         /* Number of handles in @open_handles currently open (filled in from the
106          * beginning of the array)  */
107         unsigned num_open_handles;
108
109         /* List of dentries, joined by @tmp_list, that need to have reparse data
110          * extracted as soon as the whole stream has been read into
111          * @data_buffer.  */
112         struct list_head reparse_dentries;
113
114         /* List of dentries, joined by @tmp_list, that need to have raw
115          * encrypted data extracted as soon as the whole stream has been read
116          * into @data_buffer.  */
117         struct list_head encrypted_dentries;
118
119         /* Number of files for which we didn't have permission to set the full
120          * security descriptor.  */
121         unsigned long partial_security_descriptors;
122
123         /* Number of files for which we didn't have permission to set any part
124          * of the security descriptor.  */
125         unsigned long no_security_descriptors;
126
127         /* Number of files for which we couldn't set the short name.  */
128         unsigned long num_short_name_failures;
129
130         /* Have we tried to enable short name support on the target volume yet?
131          */
132         bool tried_to_enable_short_names;
133 };
134
135 /* Get the drive letter from a Windows path, or return the null character if the
136  * path is relative.  */
137 static wchar_t
138 get_drive_letter(const wchar_t *path)
139 {
140         /* Skip \\?\ prefix  */
141         if (!wcsncmp(path, L"\\\\?\\", 4))
142                 path += 4;
143
144         /* Return drive letter if valid  */
145         if (((path[0] >= L'a' && path[0] <= L'z') ||
146              (path[0] >= L'A' && path[0] <= L'Z')) && path[1] == L':')
147                 return path[0];
148
149         return L'\0';
150 }
151
152 static void
153 get_vol_flags(const wchar_t *target, DWORD *vol_flags_ret,
154               bool *short_names_supported_ret)
155 {
156         wchar_t filesystem_name[MAX_PATH + 1];
157         wchar_t drive[4];
158         wchar_t *volume = NULL;
159
160         *vol_flags_ret = 0;
161         *short_names_supported_ret = false;
162
163         drive[0] = get_drive_letter(target);
164         if (drive[0]) {
165                 drive[1] = L':';
166                 drive[2] = L'\\';
167                 drive[3] = L'\0';
168                 volume = drive;
169         }
170
171         if (!GetVolumeInformation(volume, NULL, 0, NULL, NULL,
172                                   vol_flags_ret, filesystem_name,
173                                   ARRAY_LEN(filesystem_name)))
174         {
175                 DWORD err = GetLastError();
176                 set_errno_from_win32_error(err);
177                 WARNING_WITH_ERRNO("Failed to get volume information for "
178                                    "\"%ls\" (err=%"PRIu32")",
179                                    target, (u32)err);
180                 return;
181         }
182
183         if (wcsstr(filesystem_name, L"NTFS")) {
184                 /* FILE_SUPPORTS_HARD_LINKS is only supported on Windows 7 and
185                  * later.  Force it on anyway if filesystem is NTFS.  */
186                 *vol_flags_ret |= FILE_SUPPORTS_HARD_LINKS;
187
188                 /* There's no volume flag for short names, but according to the
189                  * MS documentation they are only user-settable on NTFS.  */
190                 *short_names_supported_ret = true;
191         }
192 }
193
194 static int
195 win32_get_supported_features(const wchar_t *target,
196                              struct wim_features *supported_features)
197 {
198         DWORD vol_flags;
199         bool short_names_supported;
200
201         /* Query the features of the target volume.  */
202
203         get_vol_flags(target, &vol_flags, &short_names_supported);
204
205         supported_features->archive_files = 1;
206         supported_features->hidden_files = 1;
207         supported_features->system_files = 1;
208
209         if (vol_flags & FILE_FILE_COMPRESSION)
210                 supported_features->compressed_files = 1;
211
212         if (vol_flags & FILE_SUPPORTS_ENCRYPTION) {
213                 supported_features->encrypted_files = 1;
214                 supported_features->encrypted_directories = 1;
215         }
216
217         supported_features->not_context_indexed_files = 1;
218
219         /* Don't do anything with FILE_SUPPORTS_SPARSE_FILES.  */
220
221         if (vol_flags & FILE_NAMED_STREAMS)
222                 supported_features->named_data_streams = 1;
223
224         if (vol_flags & FILE_SUPPORTS_HARD_LINKS)
225                 supported_features->hard_links = 1;
226
227         if (vol_flags & FILE_SUPPORTS_REPARSE_POINTS)
228                 supported_features->reparse_points = 1;
229
230         if (vol_flags & FILE_PERSISTENT_ACLS)
231                 supported_features->security_descriptors = 1;
232
233         if (short_names_supported)
234                 supported_features->short_names = 1;
235
236         supported_features->timestamps = 1;
237
238         /* Note: Windows does not support case sensitive filenames!  At least
239          * not without changing the registry and rebooting...  */
240
241         return 0;
242 }
243
244 /* Load the patterns from [PrepopulateList] of WimBootCompress.ini in the WIM
245  * image being extracted.  */
246 static int
247 load_prepopulate_pats(struct win32_apply_ctx *ctx)
248 {
249         const wchar_t *path = L"\\Windows\\System32\\WimBootCompress.ini";
250         struct wim_dentry *dentry;
251         struct wim_lookup_table_entry *lte;
252         int ret;
253         void *buf;
254         struct string_set *s;
255         void *mem;
256         struct text_file_section sec;
257
258         ctx->wimboot.tried_to_load_prepopulate_list = true;
259
260         dentry = get_dentry(ctx->common.wim, path, WIMLIB_CASE_INSENSITIVE);
261         if (!dentry ||
262             (dentry->d_inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
263                                               FILE_ATTRIBUTE_REPARSE_POINT |
264                                               FILE_ATTRIBUTE_ENCRYPTED)) ||
265             !(lte = inode_unnamed_lte(dentry->d_inode, ctx->common.wim->lookup_table)))
266         {
267                 WARNING("%ls does not exist in WIM image!", path);
268                 return WIMLIB_ERR_PATH_DOES_NOT_EXIST;
269         }
270
271         ret = read_full_stream_into_alloc_buf(lte, &buf);
272         if (ret)
273                 return ret;
274
275         s = CALLOC(1, sizeof(struct string_set));
276         if (!s) {
277                 FREE(buf);
278                 return WIMLIB_ERR_NOMEM;
279         }
280
281         sec.name = T("PrepopulateList");
282         sec.strings = s;
283
284         ret = do_load_text_file(path, buf, lte->size, &mem, &sec, 1,
285                                 LOAD_TEXT_FILE_REMOVE_QUOTES |
286                                         LOAD_TEXT_FILE_NO_WARNINGS,
287                                 mangle_pat);
288         BUILD_BUG_ON(OS_PREFERRED_PATH_SEPARATOR != WIM_PATH_SEPARATOR);
289         FREE(buf);
290         if (ret) {
291                 FREE(s);
292                 return ret;
293         }
294         ctx->wimboot.prepopulate_pats = s;
295         ctx->wimboot.mem_prepopulate_pats = mem;
296         return 0;
297 }
298
299 /* Returns %true if the path to @dentry matches a pattern in [PrepopulateList]
300  * of WimBootCompress.ini.  Otherwise returns %false.
301  *
302  * @dentry must have had its full path calculated.  */
303 static bool
304 in_prepopulate_list(struct wim_dentry *dentry,
305                     const struct win32_apply_ctx *ctx)
306 {
307         const struct string_set *pats = ctx->wimboot.prepopulate_pats;
308
309         if (!pats || !pats->num_strings)
310                 return false;
311
312         return match_pattern_list(dentry->_full_path,
313                                   wcslen(dentry->_full_path), pats);
314 }
315
316 static const wchar_t *
317 current_path(struct win32_apply_ctx *ctx);
318
319 static void
320 build_extraction_path(const struct wim_dentry *dentry,
321                       struct win32_apply_ctx *ctx);
322
323 #define WIM_BACKING_NOT_ENABLED         -1
324 #define WIM_BACKING_NOT_POSSIBLE        -2
325 #define WIM_BACKING_EXCLUDED            -3
326
327 /*
328  * Determines if the unnamed data stream of a file will be created as an
329  * external backing, as opposed to a standard extraction.
330  */
331 static int
332 win32_will_externally_back(struct wim_dentry *dentry, struct apply_ctx *_ctx)
333 {
334         struct win32_apply_ctx *ctx = (struct win32_apply_ctx *)_ctx;
335         struct wim_lookup_table_entry *stream;
336         int ret;
337
338         if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT))
339                 return WIM_BACKING_NOT_ENABLED;
340
341         if (!ctx->wimboot.tried_to_load_prepopulate_list) {
342                 ret = load_prepopulate_pats(ctx);
343                 if (ret == WIMLIB_ERR_NOMEM)
344                         return ret;
345         }
346
347         if (dentry->d_inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
348                                              FILE_ATTRIBUTE_REPARSE_POINT |
349                                              FILE_ATTRIBUTE_ENCRYPTED))
350                 return WIM_BACKING_NOT_POSSIBLE;
351
352         stream = inode_unnamed_lte_resolved(dentry->d_inode);
353
354         if (!stream ||
355             stream->resource_location != RESOURCE_IN_WIM ||
356             stream->rspec->wim != ctx->common.wim ||
357             stream->size != stream->rspec->uncompressed_size)
358                 return WIM_BACKING_NOT_POSSIBLE;
359
360         ret = calculate_dentry_full_path(dentry);
361         if (ret)
362                 return ret;
363
364         if (in_prepopulate_list(dentry, ctx))
365                 return WIM_BACKING_EXCLUDED;
366
367         return 0;
368 }
369
370 static int
371 set_external_backing(HANDLE h, struct wim_dentry *dentry, struct win32_apply_ctx *ctx)
372 {
373         int ret;
374
375         ret = win32_will_externally_back(dentry, &ctx->common);
376         if (ret > 0) /* Error.  */
377                 return ret;
378
379         if (ret < 0 && ret != WIM_BACKING_EXCLUDED)
380                 return 0; /* Not externally backing, other than due to exclusion.  */
381
382         build_extraction_path(dentry, ctx);
383
384         if (ret == WIM_BACKING_EXCLUDED) {
385                 /* Not externally backing due to exclusion.  */
386                 union wimlib_progress_info info;
387
388                 info.wimboot_exclude.path_in_wim = dentry->_full_path;
389                 info.wimboot_exclude.extraction_path = current_path(ctx);
390
391                 return call_progress(ctx->common.progfunc,
392                                      WIMLIB_PROGRESS_MSG_WIMBOOT_EXCLUDE,
393                                      &info, ctx->common.progctx);
394         } else {
395                 /* Externally backing.  */
396                 return wimboot_set_pointer(h,
397                                            current_path(ctx),
398                                            inode_unnamed_lte_resolved(dentry->d_inode),
399                                            ctx->wimboot.data_source_id,
400                                            ctx->wimboot.wim_lookup_table_hash,
401                                            ctx->wimboot.wof_running);
402         }
403 }
404
405 /* Calculates the SHA-1 message digest of the WIM's lookup table.  */
406 static int
407 hash_lookup_table(WIMStruct *wim, u8 hash[SHA1_HASH_SIZE])
408 {
409         return wim_reshdr_to_hash(&wim->hdr.lookup_table_reshdr, wim, hash);
410 }
411
412 /* Prepare for doing a "WIMBoot" extraction by loading patterns from
413  * [PrepopulateList] of WimBootCompress.ini and allocating a WOF data source ID
414  * on the target volume.  */
415 static int
416 start_wimboot_extraction(struct win32_apply_ctx *ctx)
417 {
418         int ret;
419         WIMStruct *wim = ctx->common.wim;
420
421         if (!ctx->wimboot.tried_to_load_prepopulate_list) {
422                 ret = load_prepopulate_pats(ctx);
423                 if (ret == WIMLIB_ERR_NOMEM)
424                         return ret;
425         }
426
427         if (!wim_info_get_wimboot(wim->wim_info, wim->current_image))
428                 WARNING("Image is not marked as WIMBoot compatible!");
429
430         ret = hash_lookup_table(ctx->common.wim,
431                                 ctx->wimboot.wim_lookup_table_hash);
432         if (ret)
433                 return ret;
434
435         return wimboot_alloc_data_source_id(wim->filename,
436                                             wim->hdr.guid,
437                                             wim->current_image,
438                                             ctx->common.target,
439                                             &ctx->wimboot.data_source_id,
440                                             &ctx->wimboot.wof_running);
441 }
442
443 static void
444 build_win32_extraction_path(const struct wim_dentry *dentry,
445                             struct win32_apply_ctx *ctx);
446
447 /* Sets WimBoot=1 in the extracted SYSTEM registry hive.
448  *
449  * WIMGAPI does this, and it's possible that it's important.
450  * But I don't know exactly what this value means to Windows.  */
451 static int
452 end_wimboot_extraction(struct win32_apply_ctx *ctx)
453 {
454         struct wim_dentry *dentry;
455         wchar_t subkeyname[32];
456         LONG res;
457         LONG res2;
458         HKEY key;
459         DWORD value;
460
461         dentry = get_dentry(ctx->common.wim, L"\\Windows\\System32\\config\\SYSTEM",
462                             WIMLIB_CASE_INSENSITIVE);
463
464         if (!dentry || !will_extract_dentry(dentry))
465                 goto out;
466
467         if (!will_extract_dentry(wim_get_current_root_dentry(ctx->common.wim)))
468                 goto out;
469
470         /* Not bothering to use the native routines (e.g. NtLoadKey()) for this.
471          * If this doesn't work, you probably also have many other problems.  */
472
473         build_win32_extraction_path(dentry, ctx);
474
475         randomize_char_array_with_alnum(subkeyname, 20);
476         subkeyname[20] = L'\0';
477
478         res = RegLoadKey(HKEY_LOCAL_MACHINE, subkeyname, ctx->pathbuf.Buffer);
479         if (res)
480                 goto out_check_res;
481
482         wcscpy(&subkeyname[20], L"\\Setup");
483
484         res = RegCreateKeyEx(HKEY_LOCAL_MACHINE, subkeyname, 0, NULL,
485                              REG_OPTION_BACKUP_RESTORE, 0, NULL, &key, NULL);
486         if (res)
487                 goto out_unload_key;
488
489         value = 1;
490
491         res = RegSetValueEx(key, L"WimBoot", 0, REG_DWORD,
492                             (const BYTE *)&value, sizeof(DWORD));
493         if (res)
494                 goto out_close_key;
495
496         res = RegFlushKey(key);
497
498 out_close_key:
499         res2 = RegCloseKey(key);
500         if (!res)
501                 res = res2;
502 out_unload_key:
503         subkeyname[20] = L'\0';
504         RegUnLoadKey(HKEY_LOCAL_MACHINE, subkeyname);
505 out_check_res:
506         if (res) {
507                 /* Warning only.  */
508                 set_errno_from_win32_error(res);
509                 WARNING_WITH_ERRNO("Failed to set \\Setup: dword \"WimBoot\"=1 value "
510                                    "in registry hive \"%ls\" (err=%"PRIu32")",
511                                    ctx->pathbuf.Buffer, (u32)res);
512         }
513 out:
514         return 0;
515 }
516
517 /* Returns the number of wide characters needed to represent the path to the
518  * specified @dentry, relative to the target directory, when extracted.
519  *
520  * Does not include null terminator (not needed for NtCreateFile).  */
521 static size_t
522 dentry_extraction_path_length(const struct wim_dentry *dentry)
523 {
524         size_t len = 0;
525         const struct wim_dentry *d;
526
527         d = dentry;
528         do {
529                 len += d->d_extraction_name_nchars + 1;
530                 d = d->d_parent;
531         } while (!dentry_is_root(d) && will_extract_dentry(d));
532
533         return --len;  /* No leading slash  */
534 }
535
536 /* Returns the length of the longest string that might need to be appended to
537  * the path to an alias of an inode to open or create a named data stream.
538  *
539  * If the inode has no named data streams, this will be 0.  Otherwise, this will
540  * be 1 plus the length of the longest-named data stream, since the data stream
541  * name must be separated from the path by the ':' character.  */
542 static size_t
543 inode_longest_named_data_stream_spec(const struct wim_inode *inode)
544 {
545         size_t max = 0;
546         for (u16 i = 0; i < inode->i_num_ads; i++) {
547                 size_t len = inode->i_ads_entries[i].stream_name_nbytes;
548                 if (len > max)
549                         max = len;
550         }
551         if (max)
552                 max = 1 + (max / sizeof(wchar_t));
553         return max;
554 }
555
556 /* Find the length, in wide characters, of the longest path needed for
557  * extraction of any file in @dentry_list relative to the target directory.
558  *
559  * Accounts for named data streams, but does not include null terminator (not
560  * needed for NtCreateFile).  */
561 static size_t
562 compute_path_max(struct list_head *dentry_list)
563 {
564         size_t max = 0;
565         const struct wim_dentry *dentry;
566
567         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
568                 size_t len;
569
570                 len = dentry_extraction_path_length(dentry);
571
572                 /* Account for named data streams  */
573                 len += inode_longest_named_data_stream_spec(dentry->d_inode);
574
575                 if (len > max)
576                         max = len;
577         }
578
579         return max;
580 }
581
582 /* Build the path at which to extract the @dentry, relative to the target
583  * directory.
584  *
585  * The path is saved in ctx->pathbuf.  */
586 static void
587 build_extraction_path(const struct wim_dentry *dentry,
588                       struct win32_apply_ctx *ctx)
589 {
590         size_t len;
591         wchar_t *p;
592         const struct wim_dentry *d;
593
594         len = dentry_extraction_path_length(dentry);
595
596         ctx->pathbuf.Length = len * sizeof(wchar_t);
597         p = ctx->pathbuf.Buffer + len;
598         for (d = dentry;
599              !dentry_is_root(d->d_parent) && will_extract_dentry(d->d_parent);
600              d = d->d_parent)
601         {
602                 p -= d->d_extraction_name_nchars;
603                 wmemcpy(p, d->d_extraction_name, d->d_extraction_name_nchars);
604                 *--p = '\\';
605         }
606         /* No leading slash  */
607         p -= d->d_extraction_name_nchars;
608         wmemcpy(p, d->d_extraction_name, d->d_extraction_name_nchars);
609 }
610
611 /* Build the path at which to extract the @dentry, relative to the target
612  * directory, adding the suffix for a named data stream.
613  *
614  * The path is saved in ctx->pathbuf.  */
615 static void
616 build_extraction_path_with_ads(const struct wim_dentry *dentry,
617                                struct win32_apply_ctx *ctx,
618                                const wchar_t *stream_name,
619                                size_t stream_name_nchars)
620 {
621         wchar_t *p;
622
623         build_extraction_path(dentry, ctx);
624
625         /* Add :NAME for named data stream  */
626         p = ctx->pathbuf.Buffer + (ctx->pathbuf.Length / sizeof(wchar_t));
627         *p++ = L':';
628         wmemcpy(p, stream_name, stream_name_nchars);
629         ctx->pathbuf.Length += (1 + stream_name_nchars) * sizeof(wchar_t);
630 }
631
632 /* Build the Win32 namespace path to the specified @dentry when extracted.
633  *
634  * The path is saved in ctx->pathbuf and will be null terminated.
635  *
636  * XXX: We could get rid of this if it wasn't needed for the file encryption
637  * APIs, and the registry manipulation in WIMBoot mode.  */
638 static void
639 build_win32_extraction_path(const struct wim_dentry *dentry,
640                             struct win32_apply_ctx *ctx)
641 {
642         build_extraction_path(dentry, ctx);
643
644         /* Prepend target_ntpath to our relative path, then change \??\ into \\?\  */
645
646         memmove(ctx->pathbuf.Buffer +
647                         (ctx->target_ntpath.Length / sizeof(wchar_t)) + 1,
648                 ctx->pathbuf.Buffer, ctx->pathbuf.Length);
649         memcpy(ctx->pathbuf.Buffer, ctx->target_ntpath.Buffer,
650                 ctx->target_ntpath.Length);
651         ctx->pathbuf.Buffer[ctx->target_ntpath.Length / sizeof(wchar_t)] = L'\\';
652         ctx->pathbuf.Length += ctx->target_ntpath.Length + sizeof(wchar_t);
653         ctx->pathbuf.Buffer[ctx->pathbuf.Length / sizeof(wchar_t)] = L'\0';
654
655         wimlib_assert(ctx->pathbuf.Length >= 4 * sizeof(wchar_t) &&
656                       !wmemcmp(ctx->pathbuf.Buffer, L"\\??\\", 4));
657
658         ctx->pathbuf.Buffer[1] = L'\\';
659
660 }
661
662 /* Returns a "printable" representation of the last relative NT path that was
663  * constructed with build_extraction_path() or build_extraction_path_with_ads().
664  *
665  * This will be overwritten by the next call to this function.  */
666 static const wchar_t *
667 current_path(struct win32_apply_ctx *ctx)
668 {
669         wchar_t *p = ctx->print_buffer;
670
671         p = wmempcpy(p, ctx->common.target, ctx->common.target_nchars);
672         *p++ = L'\\';
673         p = wmempcpy(p, ctx->pathbuf.Buffer, ctx->pathbuf.Length / sizeof(wchar_t));
674         *p = L'\0';
675         return ctx->print_buffer;
676 }
677
678 /*
679  * Ensures the target directory exists and opens a handle to it, in preparation
680  * of using paths relative to it.
681  */
682 static int
683 prepare_target(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
684 {
685         int ret;
686         NTSTATUS status;
687         size_t path_max;
688
689         /* Open handle to the target directory (possibly creating it).  */
690
691         ret = win32_path_to_nt_path(ctx->common.target, &ctx->target_ntpath);
692         if (ret)
693                 return ret;
694
695         ctx->attr.Length = sizeof(ctx->attr);
696         ctx->attr.ObjectName = &ctx->target_ntpath;
697
698         status = (*func_NtCreateFile)(&ctx->h_target,
699                                       FILE_TRAVERSE,
700                                       &ctx->attr,
701                                       &ctx->iosb,
702                                       NULL,
703                                       0,
704                                       FILE_SHARE_VALID_FLAGS,
705                                       FILE_OPEN_IF,
706                                       FILE_DIRECTORY_FILE |
707                                               FILE_OPEN_REPARSE_POINT |
708                                               FILE_OPEN_FOR_BACKUP_INTENT,
709                                       NULL,
710                                       0);
711
712         if (!NT_SUCCESS(status)) {
713                 set_errno_from_nt_status(status);
714                 ERROR_WITH_ERRNO("Can't open or create directory \"%ls\" "
715                                  "(status=0x%08"PRIx32")",
716                                  ctx->common.target, (u32)status);
717                 return WIMLIB_ERR_OPENDIR;
718         }
719
720         path_max = compute_path_max(dentry_list);
721
722         /* Add some extra for building Win32 paths for the file encryption APIs
723          * ...  */
724         path_max += 2 + (ctx->target_ntpath.Length / sizeof(wchar_t));
725
726         ctx->pathbuf.MaximumLength = path_max * sizeof(wchar_t);
727         ctx->pathbuf.Buffer = MALLOC(ctx->pathbuf.MaximumLength);
728         if (!ctx->pathbuf.Buffer)
729                 return WIMLIB_ERR_NOMEM;
730
731         ctx->attr.RootDirectory = ctx->h_target;
732         ctx->attr.ObjectName = &ctx->pathbuf;
733
734         ctx->print_buffer = MALLOC((ctx->common.target_nchars + 1 + path_max + 1) *
735                                    sizeof(wchar_t));
736         if (!ctx->print_buffer)
737                 return WIMLIB_ERR_NOMEM;
738
739         return 0;
740 }
741
742 /* When creating an inode that will have a short (DOS) name, we create it using
743  * the long name associated with the short name.  This ensures that the short
744  * name gets associated with the correct long name.  */
745 static struct wim_dentry *
746 first_extraction_alias(const struct wim_inode *inode)
747 {
748         struct list_head *next = inode->i_extraction_aliases.next;
749         struct wim_dentry *dentry;
750
751         do {
752                 dentry = list_entry(next, struct wim_dentry,
753                                     d_extraction_alias_node);
754                 if (dentry_has_short_name(dentry))
755                         break;
756                 next = next->next;
757         } while (next != &inode->i_extraction_aliases);
758         return dentry;
759 }
760
761 /*
762  * Set or clear FILE_ATTRIBUTE_COMPRESSED if the inherited value is different
763  * from the desired value.
764  *
765  * Note that you can NOT override the inherited value of
766  * FILE_ATTRIBUTE_COMPRESSED directly with NtCreateFile().
767  */
768 static int
769 adjust_compression_attribute(HANDLE h, const struct wim_dentry *dentry,
770                              struct win32_apply_ctx *ctx)
771 {
772         const bool compressed = (dentry->d_inode->i_attributes &
773                                  FILE_ATTRIBUTE_COMPRESSED);
774
775         if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)
776                 return 0;
777
778         if (!ctx->common.supported_features.compressed_files)
779                 return 0;
780
781         FILE_BASIC_INFORMATION info;
782         NTSTATUS status;
783         USHORT compression_state;
784
785         /* Get current attributes  */
786         status = (*func_NtQueryInformationFile)(h, &ctx->iosb,
787                                                 &info, sizeof(info),
788                                                 FileBasicInformation);
789         if (NT_SUCCESS(status) &&
790             compressed == !!(info.FileAttributes & FILE_ATTRIBUTE_COMPRESSED))
791         {
792                 /* Nothing needs to be done.  */
793                 return 0;
794         }
795
796         /* Set the new compression state  */
797
798         if (compressed)
799                 compression_state = COMPRESSION_FORMAT_DEFAULT;
800         else
801                 compression_state = COMPRESSION_FORMAT_NONE;
802
803         status = (*func_NtFsControlFile)(h,
804                                          NULL,
805                                          NULL,
806                                          NULL,
807                                          &ctx->iosb,
808                                          FSCTL_SET_COMPRESSION,
809                                          &compression_state,
810                                          sizeof(USHORT),
811                                          NULL,
812                                          0);
813         if (NT_SUCCESS(status))
814                 return 0;
815
816         set_errno_from_nt_status(status);
817         ERROR_WITH_ERRNO("Can't %s compression attribute on \"%ls\" "
818                          "(status=0x%08"PRIx32")",
819                          (compressed ? "set" : "clear"),
820                          current_path(ctx), status);
821         return WIMLIB_ERR_SET_ATTRIBUTES;
822 }
823
824 /*
825  * Clear FILE_ATTRIBUTE_ENCRYPTED if the file or directory is not supposed to be
826  * encrypted.
827  *
828  * You can provide FILE_ATTRIBUTE_ENCRYPTED to NtCreateFile() to set it on the
829  * created file.  However, the file or directory will otherwise default to the
830  * encryption state of the parent directory.  This function works around this
831  * limitation by using DecryptFile() to remove FILE_ATTRIBUTE_ENCRYPTED on files
832  * (and directories) that are not supposed to have it set.
833  *
834  * Regardless of whether it succeeds or fails, this function may close the
835  * handle to the file.  If it does, it sets it to NULL.
836  */
837 static int
838 maybe_clear_encryption_attribute(HANDLE *h_ptr, const struct wim_dentry *dentry,
839                                  struct win32_apply_ctx *ctx)
840 {
841         if (dentry->d_inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED)
842                 return 0;
843
844         if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)
845                 return 0;
846
847         if (!ctx->common.supported_features.encrypted_files)
848                 return 0;
849
850         FILE_BASIC_INFORMATION info;
851         NTSTATUS status;
852         BOOL bret;
853
854         /* Get current attributes  */
855         status = (*func_NtQueryInformationFile)(*h_ptr, &ctx->iosb,
856                                                 &info, sizeof(info),
857                                                 FileBasicInformation);
858         if (NT_SUCCESS(status) &&
859             !(info.FileAttributes & FILE_ATTRIBUTE_ENCRYPTED))
860         {
861                 /* Nothing needs to be done.  */
862                 return 0;
863         }
864
865         /* Set the new encryption state  */
866
867         /* Due to Windows' crappy file encryption APIs, we need to close the
868          * handle to the file so we don't get ERROR_SHARING_VIOLATION.  We also
869          * hack together a Win32 path, although we will use the \\?\ prefix so
870          * it will actually be a NT path in disguise...  */
871         (*func_NtClose)(*h_ptr);
872         *h_ptr = NULL;
873
874         build_win32_extraction_path(dentry, ctx);
875
876         bret = DecryptFile(ctx->pathbuf.Buffer, 0);
877
878         /* Restore the NT namespace path  */
879         build_extraction_path(dentry, ctx);
880
881         if (!bret) {
882                 DWORD err = GetLastError();
883                 set_errno_from_win32_error(err);
884                 ERROR_WITH_ERRNO("Can't decrypt file \"%ls\" (err=%"PRIu32")",
885                                   current_path(ctx), (u32)err);
886                 return WIMLIB_ERR_SET_ATTRIBUTES;
887         }
888         return 0;
889 }
890
891 /* Try to enable short name support on the target volume.  If successful, return
892  * true.  If unsuccessful, issue a warning and return false.  */
893 static bool
894 try_to_enable_short_names(const wchar_t *volume)
895 {
896         HANDLE h;
897         FILE_FS_PERSISTENT_VOLUME_INFORMATION info;
898         BOOL bret;
899         DWORD bytesReturned;
900
901         h = CreateFile(volume, GENERIC_WRITE,
902                        FILE_SHARE_VALID_FLAGS, NULL, OPEN_EXISTING,
903                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
904         if (h == INVALID_HANDLE_VALUE)
905                 goto fail;
906
907         info.VolumeFlags = 0;
908         info.FlagMask = PERSISTENT_VOLUME_STATE_SHORT_NAME_CREATION_DISABLED;
909         info.Version = 1;
910         info.Reserved = 0;
911
912         bret = DeviceIoControl(h, FSCTL_SET_PERSISTENT_VOLUME_STATE,
913                                &info, sizeof(info), NULL, 0,
914                                &bytesReturned, NULL);
915
916         CloseHandle(h);
917
918         if (!bret)
919                 goto fail;
920         return true;
921
922 fail:
923         WARNING("Failed to enable short name support on %ls "
924                 "(err=%"PRIu32")", volume + 4, (u32)GetLastError());
925         return false;
926 }
927
928 /* Set the short name on the open file @h which has been created at the location
929  * indicated by @dentry.
930  *
931  * Note that this may add, change, or remove the short name.
932  *
933  * @h must be opened with DELETE access.
934  *
935  * Returns 0 or WIMLIB_ERR_SET_SHORT_NAME.  The latter only happens in
936  * STRICT_SHORT_NAMES mode.
937  */
938 static int
939 set_short_name(HANDLE h, const struct wim_dentry *dentry,
940                struct win32_apply_ctx *ctx)
941 {
942
943         if (!ctx->common.supported_features.short_names)
944                 return 0;
945
946         /*
947          * Note: The size of the FILE_NAME_INFORMATION buffer must be such that
948          * FileName contains at least 2 wide characters (4 bytes).  Otherwise,
949          * NtSetInformationFile() will return STATUS_INFO_LENGTH_MISMATCH.  This
950          * is despite the fact that FileNameLength can validly be 0 or 2 bytes,
951          * with the former case being removing the existing short name if
952          * present, rather than setting one.
953          *
954          * The null terminator is seemingly optional, but to be safe we include
955          * space for it and zero all unused space.
956          */
957
958         size_t bufsize = offsetof(FILE_NAME_INFORMATION, FileName) +
959                          max(dentry->short_name_nbytes, sizeof(wchar_t)) +
960                          sizeof(wchar_t);
961         u8 buf[bufsize] _aligned_attribute(8);
962         FILE_NAME_INFORMATION *info = (FILE_NAME_INFORMATION *)buf;
963         NTSTATUS status;
964
965         memset(buf, 0, bufsize);
966
967         info->FileNameLength = dentry->short_name_nbytes;
968         memcpy(info->FileName, dentry->short_name, dentry->short_name_nbytes);
969
970 retry:
971         status = (*func_NtSetInformationFile)(h, &ctx->iosb, info, bufsize,
972                                               FileShortNameInformation);
973         if (NT_SUCCESS(status))
974                 return 0;
975
976         if (status == STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME) {
977                 if (dentry->short_name_nbytes == 0)
978                         return 0;
979                 if (!ctx->tried_to_enable_short_names) {
980                         wchar_t volume[7];
981                         int ret;
982
983                         ctx->tried_to_enable_short_names = true;
984
985                         ret = win32_get_drive_path(ctx->common.target,
986                                                    volume);
987                         if (ret)
988                                 return ret;
989                         if (try_to_enable_short_names(volume))
990                                 goto retry;
991                 }
992         }
993
994         /* By default, failure to set short names is not an error (since short
995          * names aren't too important anymore...).  */
996         if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES)) {
997                 ctx->num_short_name_failures++;
998                 return 0;
999         }
1000
1001         if (status == STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME) {
1002                 ERROR("Can't set short name when short "
1003                       "names are not enabled on the volume!");
1004         } else {
1005                 ERROR("Can't set short name on \"%ls\" (status=0x%08"PRIx32")",
1006                       current_path(ctx), (u32)status);
1007         }
1008         return WIMLIB_ERR_SET_SHORT_NAME;
1009 }
1010
1011 /*
1012  * A wrapper around NtCreateFile() to make it slightly more usable...
1013  * This uses the path currently constructed in ctx->pathbuf.
1014  *
1015  * Also, we always specify FILE_OPEN_FOR_BACKUP_INTENT and
1016  * FILE_OPEN_REPARSE_POINT.
1017  */
1018 static NTSTATUS
1019 do_create_file(PHANDLE FileHandle,
1020                ACCESS_MASK DesiredAccess,
1021                PLARGE_INTEGER AllocationSize,
1022                ULONG FileAttributes,
1023                ULONG CreateDisposition,
1024                ULONG CreateOptions,
1025                struct win32_apply_ctx *ctx)
1026 {
1027         return (*func_NtCreateFile)(FileHandle,
1028                                     DesiredAccess,
1029                                     &ctx->attr,
1030                                     &ctx->iosb,
1031                                     AllocationSize,
1032                                     FileAttributes,
1033                                     FILE_SHARE_VALID_FLAGS,
1034                                     CreateDisposition,
1035                                     CreateOptions |
1036                                         FILE_OPEN_FOR_BACKUP_INTENT |
1037                                         FILE_OPEN_REPARSE_POINT,
1038                                     NULL,
1039                                     0);
1040 }
1041
1042 /* Like do_create_file(), but builds the extraction path of the @dentry first.
1043  */
1044 static NTSTATUS
1045 create_file(PHANDLE FileHandle,
1046             ACCESS_MASK DesiredAccess,
1047             PLARGE_INTEGER AllocationSize,
1048             ULONG FileAttributes,
1049             ULONG CreateDisposition,
1050             ULONG CreateOptions,
1051             const struct wim_dentry *dentry,
1052             struct win32_apply_ctx *ctx)
1053 {
1054         build_extraction_path(dentry, ctx);
1055         return do_create_file(FileHandle,
1056                               DesiredAccess,
1057                               AllocationSize,
1058                               FileAttributes,
1059                               CreateDisposition,
1060                               CreateOptions,
1061                               ctx);
1062 }
1063
1064 /* Create empty named data streams.
1065  *
1066  * Since these won't have 'struct wim_lookup_table_entry's, they won't show up
1067  * in the call to extract_stream_list().  Hence the need for the special case.
1068  */
1069 static int
1070 create_any_empty_ads(const struct wim_dentry *dentry,
1071                      struct win32_apply_ctx *ctx)
1072 {
1073         const struct wim_inode *inode = dentry->d_inode;
1074         LARGE_INTEGER allocation_size;
1075         bool path_modified = false;
1076         int ret = 0;
1077
1078         if (!ctx->common.supported_features.named_data_streams)
1079                 return 0;
1080
1081         for (u16 i = 0; i < inode->i_num_ads; i++) {
1082                 const struct wim_ads_entry *entry;
1083                 NTSTATUS status;
1084                 HANDLE h;
1085
1086                 entry = &inode->i_ads_entries[i];
1087
1088                 /* Not named?  */
1089                 if (!entry->stream_name_nbytes)
1090                         continue;
1091
1092                 /* Not empty?  */
1093                 if (entry->lte)
1094                         continue;
1095
1096                 /* Probably setting the allocation size to 0 has no effect, but
1097                  * we might as well try.  */
1098                 allocation_size.QuadPart = 0;
1099
1100                 build_extraction_path_with_ads(dentry, ctx,
1101                                                entry->stream_name,
1102                                                entry->stream_name_nbytes /
1103                                                         sizeof(wchar_t));
1104                 path_modified = true;
1105                 status = do_create_file(&h, FILE_WRITE_DATA, &allocation_size,
1106                                         0, FILE_SUPERSEDE, 0, ctx);
1107                 if (!NT_SUCCESS(status)) {
1108                         set_errno_from_nt_status(status);
1109                         ERROR_WITH_ERRNO("Can't create \"%ls\" "
1110                                          "(status=0x%08"PRIx32")",
1111                                          current_path(ctx), (u32)status);
1112                         ret = WIMLIB_ERR_OPEN;
1113                         break;
1114                 }
1115                 (*func_NtClose)(h);
1116         }
1117         /* Restore the path to the dentry itself  */
1118         if (path_modified)
1119                 build_extraction_path(dentry, ctx);
1120         return ret;
1121 }
1122
1123 /*
1124  * Creates the directory named by @dentry, or uses an existing directory at that
1125  * location.  If necessary, sets the short name and/or fixes compression and
1126  * encryption attributes.
1127  *
1128  * Returns 0, WIMLIB_ERR_MKDIR, or WIMLIB_ERR_SET_SHORT_NAME.
1129  */
1130 static int
1131 create_directory(const struct wim_dentry *dentry,
1132                  struct win32_apply_ctx *ctx)
1133 {
1134         HANDLE h;
1135         NTSTATUS status;
1136         int ret;
1137         ULONG attrib;
1138
1139         /* Special attributes:
1140          *
1141          * Use FILE_ATTRIBUTE_ENCRYPTED if the directory needs to have it set.
1142          * This doesn't work for FILE_ATTRIBUTE_COMPRESSED (unfortunately).
1143          *
1144          * Don't specify FILE_ATTRIBUTE_DIRECTORY; it gets set anyway as a
1145          * result of the FILE_DIRECTORY_FILE option.  */
1146         attrib = (dentry->d_inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED);
1147
1148         /* DELETE is needed for set_short_name().
1149          * GENERIC_READ and GENERIC_WRITE are needed for
1150          * adjust_compression_attribute().  */
1151         status = create_file(&h, GENERIC_READ | GENERIC_WRITE | DELETE, NULL,
1152                              attrib, FILE_OPEN_IF, FILE_DIRECTORY_FILE,
1153                              dentry, ctx);
1154         if (!NT_SUCCESS(status)) {
1155                 set_errno_from_nt_status(status);
1156                 ERROR_WITH_ERRNO("Can't create directory \"%ls\" "
1157                                  "(status=0x%08"PRIx32")",
1158                                  current_path(ctx), (u32)status);
1159                 return WIMLIB_ERR_MKDIR;
1160         }
1161
1162         ret = set_short_name(h, dentry, ctx);
1163
1164         if (!ret)
1165                 ret = adjust_compression_attribute(h, dentry, ctx);
1166
1167         if (!ret)
1168                 ret = maybe_clear_encryption_attribute(&h, dentry, ctx);
1169                 /* May close the handle!!! */
1170
1171         if (h)
1172                 (*func_NtClose)(h);
1173         return ret;
1174 }
1175
1176 /*
1177  * Create all the directories being extracted, other than the target directory
1178  * itself.
1179  *
1180  * Note: we don't honor directory hard links.  However, we don't allow them to
1181  * exist in WIM images anyway (see inode_fixup.c).
1182  */
1183 static int
1184 create_directories(struct list_head *dentry_list,
1185                    struct win32_apply_ctx *ctx)
1186 {
1187         const struct wim_dentry *dentry;
1188         int ret;
1189
1190         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
1191
1192                 if (!(dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY))
1193                         continue;
1194
1195                 /* Note: Here we include files with
1196                  * FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT, but we
1197                  * wait until later to actually set the reparse data.  */
1198
1199                 /* If the root dentry is being extracted, it was already done so
1200                  * in prepare_target().  */
1201                 if (!dentry_is_root(dentry)) {
1202                         ret = create_directory(dentry, ctx);
1203                         if (ret)
1204                                 return ret;
1205
1206                         ret = create_any_empty_ads(dentry, ctx);
1207                         if (ret)
1208                                 return ret;
1209                 }
1210
1211                 ret = report_file_created(&ctx->common);
1212                 if (ret)
1213                         return ret;
1214         }
1215         return 0;
1216 }
1217
1218 /*
1219  * Creates the nondirectory file named by @dentry.
1220  *
1221  * On success, returns an open handle to the file in @h_ret, with GENERIC_READ,
1222  * GENERIC_WRITE, and DELETE access.  Also, the path to the file will be saved
1223  * in ctx->pathbuf.  On failure, returns WIMLIB_ERR_OPEN.
1224  */
1225 static int
1226 create_nondirectory_inode(HANDLE *h_ret, const struct wim_dentry *dentry,
1227                           struct win32_apply_ctx *ctx)
1228 {
1229         const struct wim_inode *inode;
1230         ULONG attrib;
1231         NTSTATUS status;
1232         bool retried = false;
1233
1234         inode = dentry->d_inode;
1235
1236         /* If the file already exists and has FILE_ATTRIBUTE_SYSTEM and/or
1237          * FILE_ATTRIBUTE_HIDDEN, these must be specified in order to supersede
1238          * the file.
1239          *
1240          * Normally the user shouldn't be trying to overwrite such files anyway,
1241          * but we at least provide FILE_ATTRIBUTE_SYSTEM and
1242          * FILE_ATTRIBUTE_HIDDEN if the WIM inode has those attributes so that
1243          * we catch the case where the user extracts the same files to the same
1244          * location more than one time.
1245          *
1246          * Also specify FILE_ATTRIBUTE_ENCRYPTED if the file needs to be
1247          * encrypted.
1248          *
1249          * In NO_ATTRIBUTES mode just don't specify any attributes at all.
1250          */
1251         if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES) {
1252                 attrib = 0;
1253         } else {
1254                 attrib = (inode->i_attributes & (FILE_ATTRIBUTE_SYSTEM |
1255                                                  FILE_ATTRIBUTE_HIDDEN |
1256                                                  FILE_ATTRIBUTE_ENCRYPTED));
1257         }
1258         build_extraction_path(dentry, ctx);
1259 retry:
1260         status = do_create_file(h_ret, GENERIC_READ | GENERIC_WRITE | DELETE,
1261                                 NULL, attrib, FILE_SUPERSEDE,
1262                                 FILE_NON_DIRECTORY_FILE, ctx);
1263         if (NT_SUCCESS(status)) {
1264                 int ret;
1265
1266                 ret = adjust_compression_attribute(*h_ret, dentry, ctx);
1267                 if (ret) {
1268                         (*func_NtClose)(*h_ret);
1269                         return ret;
1270                 }
1271
1272                 ret = maybe_clear_encryption_attribute(h_ret, dentry, ctx);
1273                 /* May close the handle!!! */
1274
1275                 if (ret) {
1276                         if (*h_ret)
1277                                 (*func_NtClose)(*h_ret);
1278                         return ret;
1279                 }
1280
1281                 if (!*h_ret) {
1282                         /* Re-open the handle so that we can return it on
1283                          * success.  */
1284                         status = do_create_file(h_ret,
1285                                                 GENERIC_READ |
1286                                                         GENERIC_WRITE | DELETE,
1287                                                 NULL, 0, FILE_OPEN,
1288                                                 FILE_NON_DIRECTORY_FILE, ctx);
1289                         if (!NT_SUCCESS(status))
1290                                 goto fail;
1291                 }
1292
1293                 ret = create_any_empty_ads(dentry, ctx);
1294                 if (ret) {
1295                         (*func_NtClose)(*h_ret);
1296                         return ret;
1297                 }
1298                 return 0;
1299         }
1300
1301         if (status == STATUS_ACCESS_DENIED && !retried) {
1302                 /* We also can't supersede an existing file that has
1303                  * FILE_ATTRIBUTE_READONLY set; doing so causes NtCreateFile()
1304                  * to return STATUS_ACCESS_DENIED .  The only workaround seems
1305                  * to be to explicitly remove FILE_ATTRIBUTE_READONLY on the
1306                  * existing file, then try again.  */
1307
1308                 FILE_BASIC_INFORMATION info;
1309                 HANDLE h;
1310
1311                 status = do_create_file(&h, FILE_WRITE_ATTRIBUTES, NULL, 0,
1312                                         FILE_OPEN, FILE_NON_DIRECTORY_FILE, ctx);
1313                 if (!NT_SUCCESS(status))
1314                         goto fail;
1315
1316                 memset(&info, 0, sizeof(info));
1317                 info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1318
1319                 status = (*func_NtSetInformationFile)(h, &ctx->iosb,
1320                                                       &info, sizeof(info),
1321                                                       FileBasicInformation);
1322                 (*func_NtClose)(h);
1323                 if (!NT_SUCCESS(status))
1324                         goto fail;
1325                 retried = true;
1326                 goto retry;
1327         }
1328 fail:
1329         set_errno_from_nt_status(status);
1330         ERROR_WITH_ERRNO("Can't create file \"%ls\" (status=0x%08"PRIx32")",
1331                          current_path(ctx), (u32)status);
1332         return WIMLIB_ERR_OPEN;
1333 }
1334
1335 /* Creates a hard link at the location named by @dentry to the file represented
1336  * by the open handle @h.  Or, if the target volume does not support hard links,
1337  * create a separate file instead.  */
1338 static int
1339 create_link(HANDLE h, const struct wim_dentry *dentry,
1340             struct win32_apply_ctx *ctx)
1341 {
1342         if (ctx->common.supported_features.hard_links) {
1343
1344                 build_extraction_path(dentry, ctx);
1345
1346                 size_t bufsize = offsetof(FILE_LINK_INFORMATION, FileName) +
1347                                  ctx->pathbuf.Length + sizeof(wchar_t);
1348                 u8 buf[bufsize] _aligned_attribute(8);
1349                 FILE_LINK_INFORMATION *info = (FILE_LINK_INFORMATION *)buf;
1350                 NTSTATUS status;
1351
1352                 info->ReplaceIfExists = TRUE;
1353                 info->RootDirectory = ctx->attr.RootDirectory;
1354                 info->FileNameLength = ctx->pathbuf.Length;
1355                 memcpy(info->FileName, ctx->pathbuf.Buffer, ctx->pathbuf.Length);
1356                 info->FileName[info->FileNameLength / 2] = L'\0';
1357
1358                 /* Note: the null terminator isn't actually necessary,
1359                  * but if you don't add the extra character, you get
1360                  * STATUS_INFO_LENGTH_MISMATCH when FileNameLength
1361                  * happens to be 2  */
1362
1363                 status = (*func_NtSetInformationFile)(h, &ctx->iosb,
1364                                                       info, bufsize,
1365                                                       FileLinkInformation);
1366                 if (NT_SUCCESS(status))
1367                         return 0;
1368                 ERROR("Failed to create link \"%ls\" (status=0x%08"PRIx32")",
1369                       current_path(ctx), (u32)status);
1370                 return WIMLIB_ERR_LINK;
1371         } else {
1372                 HANDLE h2;
1373                 int ret;
1374
1375                 ret = create_nondirectory_inode(&h2, dentry, ctx);
1376                 if (ret)
1377                         return ret;
1378
1379                 (*func_NtClose)(h2);
1380                 return 0;
1381         }
1382 }
1383
1384 /* Given an inode (represented by the open handle @h) for which one link has
1385  * been created (named by @first_dentry), create the other links.
1386  *
1387  * Or, if the target volume does not support hard links, create separate files.
1388  *
1389  * Note: This uses ctx->pathbuf and does not reset it.
1390  */
1391 static int
1392 create_links(HANDLE h, const struct wim_dentry *first_dentry,
1393              struct win32_apply_ctx *ctx)
1394 {
1395         const struct wim_inode *inode;
1396         const struct list_head *next;
1397         const struct wim_dentry *dentry;
1398         int ret;
1399
1400         inode = first_dentry->d_inode;
1401         next = inode->i_extraction_aliases.next;
1402         do {
1403                 dentry = list_entry(next, struct wim_dentry,
1404                                     d_extraction_alias_node);
1405                 if (dentry != first_dentry) {
1406                         ret = create_link(h, dentry, ctx);
1407                         if (ret)
1408                                 return ret;
1409                 }
1410                 next = next->next;
1411         } while (next != &inode->i_extraction_aliases);
1412         return 0;
1413 }
1414
1415 /* Create a nondirectory file, including all links.  */
1416 static int
1417 create_nondirectory(const struct wim_inode *inode, struct win32_apply_ctx *ctx)
1418 {
1419         struct wim_dentry *first_dentry;
1420         HANDLE h;
1421         int ret;
1422
1423         first_dentry = first_extraction_alias(inode);
1424
1425         /* Create first link.  */
1426         ret = create_nondirectory_inode(&h, first_dentry, ctx);
1427         if (ret)
1428                 return ret;
1429
1430         /* Set short name.  */
1431         ret = set_short_name(h, first_dentry, ctx);
1432
1433         /* Create additional links, OR if hard links are not supported just
1434          * create more files.  */
1435         if (!ret)
1436                 ret = create_links(h, first_dentry, ctx);
1437
1438         /* "WIMBoot" extraction: set external backing by the WIM file if needed.  */
1439         if (!ret && unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT))
1440                 ret = set_external_backing(h, first_dentry, ctx);
1441
1442         (*func_NtClose)(h);
1443         return ret;
1444 }
1445
1446 /* Create all the nondirectory files being extracted, including all aliases
1447  * (hard links).  */
1448 static int
1449 create_nondirectories(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
1450 {
1451         const struct wim_dentry *dentry;
1452         const struct wim_inode *inode;
1453         int ret;
1454
1455         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
1456                 inode = dentry->d_inode;
1457                 if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
1458                         continue;
1459                 /* Call create_nondirectory() only once per inode  */
1460                 if (dentry == inode_first_extraction_dentry(inode)) {
1461                         ret = create_nondirectory(inode, ctx);
1462                         if (ret)
1463                                 return ret;
1464                 }
1465                 ret = report_file_created(&ctx->common);
1466                 if (ret)
1467                         return ret;
1468         }
1469         return 0;
1470 }
1471
1472 static void
1473 close_handles(struct win32_apply_ctx *ctx)
1474 {
1475         for (unsigned i = 0; i < ctx->num_open_handles; i++)
1476                 (*func_NtClose)(ctx->open_handles[i]);
1477 }
1478
1479 /* Prepare to read the next stream, which has size @stream_size, into an
1480  * in-memory buffer.  */
1481 static int
1482 prepare_data_buffer(struct win32_apply_ctx *ctx, u64 stream_size)
1483 {
1484         if (stream_size > ctx->data_buffer_size) {
1485                 /* Larger buffer needed.  */
1486                 void *new_buffer;
1487                 if ((size_t)stream_size != stream_size)
1488                         return WIMLIB_ERR_NOMEM;
1489                 new_buffer = REALLOC(ctx->data_buffer, stream_size);
1490                 if (!new_buffer)
1491                         return WIMLIB_ERR_NOMEM;
1492                 ctx->data_buffer = new_buffer;
1493                 ctx->data_buffer_size = stream_size;
1494         }
1495         /* On the first call this changes data_buffer_ptr from NULL, which tells
1496          * extract_chunk() that the data buffer needs to be filled while reading
1497          * the stream data.  */
1498         ctx->data_buffer_ptr = ctx->data_buffer;
1499         return 0;
1500 }
1501
1502 static int
1503 begin_extract_stream_instance(const struct wim_lookup_table_entry *stream,
1504                               struct wim_dentry *dentry,
1505                               const wchar_t *stream_name,
1506                               struct win32_apply_ctx *ctx)
1507 {
1508         const struct wim_inode *inode = dentry->d_inode;
1509         size_t stream_name_nchars = 0;
1510         FILE_ALLOCATION_INFORMATION alloc_info;
1511         HANDLE h;
1512         NTSTATUS status;
1513
1514         if (unlikely(stream_name))
1515                 stream_name_nchars = wcslen(stream_name);
1516
1517         if (unlikely(stream_name_nchars)) {
1518                 build_extraction_path_with_ads(dentry, ctx,
1519                                                stream_name, stream_name_nchars);
1520         } else {
1521                 build_extraction_path(dentry, ctx);
1522         }
1523
1524         /* Reparse point?  */
1525         if (unlikely(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)
1526             && (stream_name_nchars == 0))
1527         {
1528                 if (!ctx->common.supported_features.reparse_points)
1529                         return 0;
1530
1531                 /* We can't write the reparse stream directly; we must set it
1532                  * with FSCTL_SET_REPARSE_POINT, which requires that all the
1533                  * data be available.  So, stage the data in a buffer.  */
1534
1535                 list_add_tail(&dentry->tmp_list, &ctx->reparse_dentries);
1536                 return prepare_data_buffer(ctx, stream->size);
1537         }
1538
1539         /* Encrypted file?  */
1540         if (unlikely(inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED)
1541             && (stream_name_nchars == 0))
1542         {
1543                 if (!ctx->common.supported_features.encrypted_files)
1544                         return 0;
1545
1546                 /* We can't write encrypted file streams directly; we must use
1547                  * WriteEncryptedFileRaw(), which requires providing the data
1548                  * through a callback function.  This can't easily be combined
1549                  * with our own callback-based approach.
1550                  *
1551                  * The current workaround is to simply read the stream into
1552                  * memory and write the encrypted file from that.
1553                  *
1554                  * TODO: This isn't sufficient for extremely large encrypted
1555                  * files.  Perhaps we should create an extra thread to write
1556                  * such files...  */
1557                 list_add_tail(&dentry->tmp_list, &ctx->encrypted_dentries);
1558                 return prepare_data_buffer(ctx, stream->size);
1559         }
1560
1561         if (ctx->num_open_handles == MAX_OPEN_STREAMS) {
1562                 /* XXX: Fix this.  But because of the checks in
1563                  * extract_stream_list(), this can now only happen on a
1564                  * filesystem that does not support hard links.  */
1565                 ERROR("Can't extract data: too many open files!");
1566                 return WIMLIB_ERR_UNSUPPORTED;
1567         }
1568
1569         /* Open a new handle  */
1570         status = do_create_file(&h,
1571                                 FILE_WRITE_DATA | SYNCHRONIZE,
1572                                 NULL, 0, FILE_OPEN_IF,
1573                                 FILE_SEQUENTIAL_ONLY |
1574                                         FILE_SYNCHRONOUS_IO_NONALERT,
1575                                 ctx);
1576         if (!NT_SUCCESS(status)) {
1577                 set_errno_from_nt_status(status);
1578                 ERROR_WITH_ERRNO("Can't open \"%ls\" for writing "
1579                                  "(status=0x%08"PRIx32")",
1580                                  current_path(ctx), (u32)status);
1581                 return WIMLIB_ERR_OPEN;
1582         }
1583
1584         ctx->open_handles[ctx->num_open_handles++] = h;
1585
1586         /* Allocate space for the data.  */
1587         alloc_info.AllocationSize.QuadPart = stream->size;
1588         (*func_NtSetInformationFile)(h, &ctx->iosb,
1589                                      &alloc_info, sizeof(alloc_info),
1590                                      FileAllocationInformation);
1591         return 0;
1592 }
1593
1594 /* Set the reparse data @rpbuf of length @rpbuflen on the extracted file
1595  * corresponding to the WIM dentry @dentry.  */
1596 static int
1597 do_set_reparse_data(const struct wim_dentry *dentry,
1598                     const void *rpbuf, u16 rpbuflen,
1599                     struct win32_apply_ctx *ctx)
1600 {
1601         NTSTATUS status;
1602         HANDLE h;
1603
1604         status = create_file(&h, GENERIC_WRITE, NULL,
1605                              0, FILE_OPEN, 0, dentry, ctx);
1606         if (!NT_SUCCESS(status))
1607                 goto fail;
1608
1609         status = (*func_NtFsControlFile)(h, NULL, NULL, NULL,
1610                                          &ctx->iosb, FSCTL_SET_REPARSE_POINT,
1611                                          (void *)rpbuf, rpbuflen,
1612                                          NULL, 0);
1613         (*func_NtClose)(h);
1614
1615         if (NT_SUCCESS(status))
1616                 return 0;
1617
1618         /* On Windows, by default only the Administrator can create symbolic
1619          * links for some reason.  By default we just issue a warning if this
1620          * appears to be the problem.  Use WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS
1621          * to get a hard error.  */
1622         if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS)
1623             && (status == STATUS_PRIVILEGE_NOT_HELD ||
1624                 status == STATUS_ACCESS_DENIED)
1625             && (dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
1626                 dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT))
1627         {
1628                 WARNING("Can't create symbolic link \"%ls\"!              \n"
1629                         "          (Need Administrator rights, or at least "
1630                         "the\n"
1631                         "          SeCreateSymbolicLink privilege.)",
1632                         current_path(ctx));
1633                 return 0;
1634         }
1635
1636 fail:
1637         set_errno_from_nt_status(status);
1638         ERROR_WITH_ERRNO("Can't set reparse data on \"%ls\" "
1639                          "(status=0x%08"PRIx32")",
1640                          current_path(ctx), (u32)status);
1641         return WIMLIB_ERR_SET_REPARSE_DATA;
1642 }
1643
1644 /* Given a Windows NT namespace path, such as \??\e:\Windows\System32, return a
1645  * pointer to the suffix of the path that begins with the device directly, such
1646  * as e:\Windows\System32.  */
1647 static const wchar_t *
1648 skip_nt_toplevel_component(const wchar_t *path, size_t path_nchars)
1649 {
1650         static const wchar_t * const dirs[] = {
1651                 L"\\??\\",
1652                 L"\\DosDevices\\",
1653                 L"\\Device\\",
1654         };
1655         size_t first_dir_len = 0;
1656         const wchar_t * const end = path + path_nchars;
1657
1658         for (size_t i = 0; i < ARRAY_LEN(dirs); i++) {
1659                 size_t len = wcslen(dirs[i]);
1660                 if (len <= (end - path) && !wcsnicmp(path, dirs[i], len)) {
1661                         first_dir_len = len;
1662                         break;
1663                 }
1664         }
1665         if (first_dir_len == 0)
1666                 return path;
1667         path += first_dir_len;
1668         while (path != end && *path == L'\\')
1669                 path++;
1670         return path;
1671 }
1672
1673 /* Given a Windows NT namespace path, such as \??\e:\Windows\System32, return a
1674  * pointer to the suffix of the path that is device-relative, such as
1675  * Windows\System32.
1676  *
1677  * The path has an explicit length and is not necessarily null terminated.
1678  *
1679  * If the path just something like \??\e: then the returned pointer will point
1680  * just past the colon.  In this case the length of the result will be 0
1681  * characters.  */
1682 static const wchar_t *
1683 get_device_relative_path(const wchar_t *path, size_t path_nchars)
1684 {
1685         const wchar_t * const orig_path = path;
1686         const wchar_t * const end = path + path_nchars;
1687
1688         path = skip_nt_toplevel_component(path, path_nchars);
1689         if (path == orig_path)
1690                 return orig_path;
1691
1692         path = wmemchr(path, L'\\', (end - path));
1693         if (!path)
1694                 return end;
1695         do {
1696                 path++;
1697         } while (path != end && *path == L'\\');
1698         return path;
1699 }
1700
1701 /*
1702  * Given a reparse point buffer for a symbolic link or junction, adjust its
1703  * contents so that the target of the link is consistent with the new location
1704  * of the files.
1705  */
1706 static void
1707 try_rpfix(u8 *rpbuf, u16 *rpbuflen_p, struct win32_apply_ctx *ctx)
1708 {
1709         struct reparse_data rpdata;
1710         size_t orig_subst_name_nchars;
1711         const wchar_t *relpath;
1712         size_t relpath_nchars;
1713         size_t target_ntpath_nchars;
1714         size_t fixed_subst_name_nchars;
1715         const wchar_t *fixed_print_name;
1716         size_t fixed_print_name_nchars;
1717
1718         if (parse_reparse_data(rpbuf, *rpbuflen_p, &rpdata)) {
1719                 /* Do nothing if the reparse data is invalid.  */
1720                 return;
1721         }
1722
1723         if (rpdata.rptag == WIM_IO_REPARSE_TAG_SYMLINK &&
1724             (rpdata.rpflags & SYMBOLIC_LINK_RELATIVE))
1725         {
1726                 /* Do nothing if it's a relative symbolic link.  */
1727                 return;
1728         }
1729
1730         /* Build the new substitute name from the NT namespace path to the
1731          * target directory, then a path separator, then the "device relative"
1732          * part of the old substitute name.  */
1733
1734         orig_subst_name_nchars = rpdata.substitute_name_nbytes / sizeof(wchar_t);
1735
1736         relpath = get_device_relative_path(rpdata.substitute_name,
1737                                            orig_subst_name_nchars);
1738         relpath_nchars = orig_subst_name_nchars -
1739                          (relpath - rpdata.substitute_name);
1740
1741         target_ntpath_nchars = ctx->target_ntpath.Length / sizeof(wchar_t);
1742
1743         fixed_subst_name_nchars = target_ntpath_nchars;
1744         if (relpath_nchars)
1745                 fixed_subst_name_nchars += 1 + relpath_nchars;
1746         wchar_t fixed_subst_name[fixed_subst_name_nchars];
1747
1748         wmemcpy(fixed_subst_name, ctx->target_ntpath.Buffer,
1749                 target_ntpath_nchars);
1750         if (relpath_nchars) {
1751                 fixed_subst_name[target_ntpath_nchars] = L'\\';
1752                 wmemcpy(&fixed_subst_name[target_ntpath_nchars + 1],
1753                         relpath, relpath_nchars);
1754         }
1755         /* Doesn't need to be null-terminated.  */
1756
1757         /* Print name should be Win32, but not all NT names can even be
1758          * translated to Win32 names.  But we can at least delete the top-level
1759          * directory, such as \??\, and this will have the expected result in
1760          * the usual case.  */
1761         fixed_print_name = skip_nt_toplevel_component(fixed_subst_name,
1762                                                       fixed_subst_name_nchars);
1763         fixed_print_name_nchars = fixed_subst_name_nchars - (fixed_print_name -
1764                                                              fixed_subst_name);
1765
1766         rpdata.substitute_name = fixed_subst_name;
1767         rpdata.substitute_name_nbytes = fixed_subst_name_nchars * sizeof(wchar_t);
1768         rpdata.print_name = (wchar_t *)fixed_print_name;
1769         rpdata.print_name_nbytes = fixed_print_name_nchars * sizeof(wchar_t);
1770         make_reparse_buffer(&rpdata, rpbuf, rpbuflen_p);
1771 }
1772
1773 /* Sets reparse data on the specified file.  This handles "fixing" the targets
1774  * of absolute symbolic links and junctions if WIMLIB_EXTRACT_FLAG_RPFIX was
1775  * specified.  */
1776 static int
1777 set_reparse_data(const struct wim_dentry *dentry,
1778                  const void *_rpbuf, u16 rpbuflen, struct win32_apply_ctx *ctx)
1779 {
1780         const struct wim_inode *inode = dentry->d_inode;
1781         const void *rpbuf = _rpbuf;
1782
1783         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX)
1784             && !inode->i_not_rpfixed
1785             && (inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
1786                 inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT))
1787         {
1788                 memcpy(&ctx->rpfixbuf, _rpbuf, rpbuflen);
1789                 try_rpfix((u8 *)&ctx->rpfixbuf, &rpbuflen, ctx);
1790                 rpbuf = &ctx->rpfixbuf;
1791         }
1792         return do_set_reparse_data(dentry, rpbuf, rpbuflen, ctx);
1793
1794 }
1795
1796 /* Import the next block of raw encrypted data  */
1797 static DWORD WINAPI
1798 import_encrypted_data(PBYTE pbData, PVOID pvCallbackContext, PULONG Length)
1799 {
1800         struct win32_apply_ctx *ctx = pvCallbackContext;
1801         ULONG copy_len;
1802
1803         copy_len = min(ctx->encrypted_size - ctx->encrypted_offset, *Length);
1804         memcpy(pbData, &ctx->data_buffer[ctx->encrypted_offset], copy_len);
1805         ctx->encrypted_offset += copy_len;
1806         *Length = copy_len;
1807         return ERROR_SUCCESS;
1808 }
1809
1810 /* Write the raw encrypted data to the already-created file corresponding to
1811  * @dentry.
1812  *
1813  * The raw encrypted data is provided in ctx->data_buffer, and its size is
1814  * ctx->encrypted_size.  */
1815 static int
1816 extract_encrypted_file(const struct wim_dentry *dentry,
1817                        struct win32_apply_ctx *ctx)
1818 {
1819         void *rawctx;
1820         DWORD err;
1821
1822         /* Temporarily build a Win32 path for OpenEncryptedFileRaw()  */
1823         build_win32_extraction_path(dentry, ctx);
1824
1825         err = OpenEncryptedFileRaw(ctx->pathbuf.Buffer,
1826                                    CREATE_FOR_IMPORT, &rawctx);
1827
1828         /* Restore the NT namespace path  */
1829         build_extraction_path(dentry, ctx);
1830
1831         if (err != ERROR_SUCCESS) {
1832                 set_errno_from_win32_error(err);
1833                 ERROR_WITH_ERRNO("Can't open \"%ls\" for encrypted import "
1834                                  "(err=%"PRIu32")", current_path(ctx), (u32)err);
1835                 return WIMLIB_ERR_OPEN;
1836         }
1837
1838         ctx->encrypted_offset = 0;
1839
1840         err = WriteEncryptedFileRaw(import_encrypted_data, ctx, rawctx);
1841
1842         CloseEncryptedFileRaw(rawctx);
1843
1844         if (err != ERROR_SUCCESS) {
1845                 set_errno_from_win32_error(err);
1846                 ERROR_WITH_ERRNO("Can't import encrypted file \"%ls\" "
1847                                  "(err=%"PRIu32")", current_path(ctx), (u32)err);
1848                 return WIMLIB_ERR_WRITE;
1849         }
1850
1851         return 0;
1852 }
1853
1854 /* Called when starting to read a stream for extraction on Windows  */
1855 static int
1856 begin_extract_stream(struct wim_lookup_table_entry *stream, void *_ctx)
1857 {
1858         struct win32_apply_ctx *ctx = _ctx;
1859         const struct stream_owner *owners = stream_owners(stream);
1860         int ret;
1861
1862         ctx->num_open_handles = 0;
1863         ctx->data_buffer_ptr = NULL;
1864         INIT_LIST_HEAD(&ctx->reparse_dentries);
1865         INIT_LIST_HEAD(&ctx->encrypted_dentries);
1866
1867         for (u32 i = 0; i < stream->out_refcnt; i++) {
1868                 const struct wim_inode *inode = owners[i].inode;
1869                 const wchar_t *stream_name = owners[i].stream_name;
1870                 struct wim_dentry *dentry;
1871
1872                 /* A copy of the stream needs to be extracted to @inode.  */
1873
1874                 if (ctx->common.supported_features.hard_links) {
1875                         dentry = inode_first_extraction_dentry(inode);
1876                         ret = begin_extract_stream_instance(stream, dentry,
1877                                                             stream_name, ctx);
1878                         if (ret)
1879                                 goto fail;
1880                 } else {
1881                         /* Hard links not supported.  Extract the stream
1882                          * separately to each alias of the inode.  */
1883                         struct list_head *next;
1884
1885                         next = inode->i_extraction_aliases.next;
1886                         do {
1887                                 dentry = list_entry(next, struct wim_dentry,
1888                                                     d_extraction_alias_node);
1889                                 ret = begin_extract_stream_instance(stream,
1890                                                                     dentry,
1891                                                                     stream_name,
1892                                                                     ctx);
1893                                 if (ret)
1894                                         goto fail;
1895                                 next = next->next;
1896                         } while (next != &inode->i_extraction_aliases);
1897                 }
1898         }
1899
1900         return 0;
1901
1902 fail:
1903         close_handles(ctx);
1904         return ret;
1905 }
1906
1907 /* Called when the next chunk of a stream has been read for extraction on
1908  * Windows  */
1909 static int
1910 extract_chunk(const void *chunk, size_t size, void *_ctx)
1911 {
1912         struct win32_apply_ctx *ctx = _ctx;
1913
1914         /* Write the data chunk to each open handle  */
1915         for (unsigned i = 0; i < ctx->num_open_handles; i++) {
1916                 u8 *bufptr = (u8 *)chunk;
1917                 size_t bytes_remaining = size;
1918                 NTSTATUS status;
1919                 while (bytes_remaining) {
1920                         ULONG count = min(0xFFFFFFFF, bytes_remaining);
1921
1922                         status = (*func_NtWriteFile)(ctx->open_handles[i],
1923                                                      NULL, NULL, NULL,
1924                                                      &ctx->iosb, bufptr, count,
1925                                                      NULL, NULL);
1926                         if (!NT_SUCCESS(status)) {
1927                                 set_errno_from_nt_status(status);
1928                                 ERROR_WITH_ERRNO("Error writing data to target "
1929                                                  "volume (status=0x%08"PRIx32")",
1930                                                  (u32)status);
1931                                 return WIMLIB_ERR_WRITE;
1932                         }
1933                         bufptr += ctx->iosb.Information;
1934                         bytes_remaining -= ctx->iosb.Information;
1935                 }
1936         }
1937
1938         /* Copy the data chunk into the buffer (if needed)  */
1939         if (ctx->data_buffer_ptr)
1940                 ctx->data_buffer_ptr = mempcpy(ctx->data_buffer_ptr,
1941                                                chunk, size);
1942         return 0;
1943 }
1944
1945 /* Called when a stream has been fully read for extraction on Windows  */
1946 static int
1947 end_extract_stream(struct wim_lookup_table_entry *stream, int status, void *_ctx)
1948 {
1949         struct win32_apply_ctx *ctx = _ctx;
1950         int ret;
1951         const struct wim_dentry *dentry;
1952
1953         close_handles(ctx);
1954
1955         if (status)
1956                 return status;
1957
1958         if (likely(!ctx->data_buffer_ptr))
1959                 return 0;
1960
1961         if (!list_empty(&ctx->reparse_dentries)) {
1962                 if (stream->size > REPARSE_DATA_MAX_SIZE) {
1963                         dentry = list_first_entry(&ctx->reparse_dentries,
1964                                                   struct wim_dentry, tmp_list);
1965                         build_extraction_path(dentry, ctx);
1966                         ERROR("Reparse data of \"%ls\" has size "
1967                               "%"PRIu64" bytes (exceeds %u bytes)",
1968                               current_path(ctx), stream->size,
1969                               REPARSE_DATA_MAX_SIZE);
1970                         return WIMLIB_ERR_INVALID_REPARSE_DATA;
1971                 }
1972                 /* In the WIM format, reparse streams are just the reparse data
1973                  * and omit the header.  But we can reconstruct the header.  */
1974                 memcpy(ctx->rpbuf.rpdata, ctx->data_buffer, stream->size);
1975                 ctx->rpbuf.rpdatalen = stream->size;
1976                 ctx->rpbuf.rpreserved = 0;
1977                 list_for_each_entry(dentry, &ctx->reparse_dentries, tmp_list) {
1978                         ctx->rpbuf.rptag = dentry->d_inode->i_reparse_tag;
1979                         ret = set_reparse_data(dentry, &ctx->rpbuf,
1980                                                stream->size + REPARSE_DATA_OFFSET,
1981                                                ctx);
1982                         if (ret)
1983                                 return ret;
1984                 }
1985         }
1986
1987         if (!list_empty(&ctx->encrypted_dentries)) {
1988                 ctx->encrypted_size = stream->size;
1989                 list_for_each_entry(dentry, &ctx->encrypted_dentries, tmp_list) {
1990                         ret = extract_encrypted_file(dentry, ctx);
1991                         if (ret)
1992                                 return ret;
1993                 }
1994         }
1995
1996         return 0;
1997 }
1998
1999 /* Attributes that can't be set directly  */
2000 #define SPECIAL_ATTRIBUTES                      \
2001         (FILE_ATTRIBUTE_REPARSE_POINT   |       \
2002          FILE_ATTRIBUTE_DIRECTORY       |       \
2003          FILE_ATTRIBUTE_ENCRYPTED       |       \
2004          FILE_ATTRIBUTE_SPARSE_FILE     |       \
2005          FILE_ATTRIBUTE_COMPRESSED)
2006
2007 /* Set the security descriptor @desc, of @desc_size bytes, on the file with open
2008  * handle @h.  */
2009 static NTSTATUS
2010 set_security_descriptor(HANDLE h, const void *_desc,
2011                         size_t desc_size, struct win32_apply_ctx *ctx)
2012 {
2013         SECURITY_INFORMATION info;
2014         NTSTATUS status;
2015         SECURITY_DESCRIPTOR_RELATIVE *desc;
2016
2017         /*
2018          * Ideally, we would just pass in the security descriptor buffer as-is.
2019          * But it turns out that Windows can mess up the security descriptor
2020          * even when using the low-level NtSetSecurityObject() function:
2021          *
2022          * - Windows will clear SE_DACL_AUTO_INHERITED if it is set in the
2023          *   passed buffer.  To actually get Windows to set
2024          *   SE_DACL_AUTO_INHERITED, the application must set the non-persistent
2025          *   flag SE_DACL_AUTO_INHERIT_REQ.  As usual, Microsoft didn't bother
2026          *   to properly document either of these flags.  It's unclear how
2027          *   important SE_DACL_AUTO_INHERITED actually is, but to be safe we use
2028          *   the SE_DACL_AUTO_INHERIT_REQ workaround to set it if needed.
2029          *
2030          * - The above also applies to the equivalent SACL flags,
2031          *   SE_SACL_AUTO_INHERITED and SE_SACL_AUTO_INHERIT_REQ.
2032          *
2033          * - If the application says that it's setting
2034          *   DACL_SECURITY_INFORMATION, then Windows sets SE_DACL_PRESENT in the
2035          *   resulting security descriptor, even if the security descriptor the
2036          *   application provided did not have a DACL.  This seems to be
2037          *   unavoidable, since omitting DACL_SECURITY_INFORMATION would cause a
2038          *   default DACL to remain.  Fortunately, this behavior seems harmless,
2039          *   since the resulting DACL will still be "null" --- but it will be
2040          *   "the other representation of null".
2041          *
2042          * - The above also applies to SACL_SECURITY_INFORMATION and
2043          *   SE_SACL_PRESENT.  Again, it's seemingly unavoidable but "harmless"
2044          *   that Windows changes the representation of a "null SACL".
2045          */
2046         if (likely(desc_size <= STACK_MAX)) {
2047                 desc = alloca(desc_size);
2048         } else {
2049                 desc = MALLOC(desc_size);
2050                 if (!desc)
2051                         return STATUS_NO_MEMORY;
2052         }
2053
2054         memcpy(desc, _desc, desc_size);
2055
2056         if (likely(desc_size >= 4)) {
2057
2058                 if (desc->Control & SE_DACL_AUTO_INHERITED)
2059                         desc->Control |= SE_DACL_AUTO_INHERIT_REQ;
2060
2061                 if (desc->Control & SE_SACL_AUTO_INHERITED)
2062                         desc->Control |= SE_SACL_AUTO_INHERIT_REQ;
2063         }
2064
2065         /*
2066          * More API insanity.  We want to set the entire security descriptor
2067          * as-is.  But all available APIs require specifying the specific parts
2068          * of the security descriptor being set.  Especially annoying is that
2069          * mandatory integrity labels are part of the SACL, but they aren't set
2070          * with SACL_SECURITY_INFORMATION.  Instead, applications must also
2071          * specify LABEL_SECURITY_INFORMATION (Windows Vista, Windows 7) or
2072          * BACKUP_SECURITY_INFORMATION (Windows 8).  But at least older versions
2073          * of Windows don't error out if you provide these newer flags...
2074          *
2075          * Also, if the process isn't running as Administrator, then it probably
2076          * doesn't have SE_RESTORE_PRIVILEGE.  In this case, it will always get
2077          * the STATUS_PRIVILEGE_NOT_HELD error by trying to set the SACL, even
2078          * if the security descriptor it provided did not have a SACL.  By
2079          * default, in this case we try to recover and set as much of the
2080          * security descriptor as possible --- potentially excluding the DACL, and
2081          * even the owner, as well as the SACL.
2082          */
2083
2084         info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
2085                DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION |
2086                LABEL_SECURITY_INFORMATION | BACKUP_SECURITY_INFORMATION;
2087
2088
2089         /*
2090          * It's also worth noting that SetFileSecurity() is unusable because it
2091          * doesn't request "backup semantics" when it opens the file internally.
2092          * NtSetSecurityObject() seems to be the best function to use in backup
2093          * applications.  (SetSecurityInfo() should also work, but it's harder
2094          * to use and must call NtSetSecurityObject() internally anyway.
2095          * BackupWrite() is theoretically usable as well, but it's inflexible
2096          * and poorly documented.)
2097          */
2098
2099 retry:
2100         status = (*func_NtSetSecurityObject)(h, info, desc);
2101         if (NT_SUCCESS(status))
2102                 goto out_maybe_free_desc;
2103
2104         /* Failed to set the requested parts of the security descriptor.  If the
2105          * error was permissions-related, try to set fewer parts of the security
2106          * descriptor, unless WIMLIB_EXTRACT_FLAG_STRICT_ACLS is enabled.  */
2107         if ((status == STATUS_PRIVILEGE_NOT_HELD ||
2108              status == STATUS_ACCESS_DENIED) &&
2109             !(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
2110         {
2111                 if (info & SACL_SECURITY_INFORMATION) {
2112                         info &= ~(SACL_SECURITY_INFORMATION |
2113                                   LABEL_SECURITY_INFORMATION |
2114                                   BACKUP_SECURITY_INFORMATION);
2115                         ctx->partial_security_descriptors++;
2116                         goto retry;
2117                 }
2118                 if (info & DACL_SECURITY_INFORMATION) {
2119                         info &= ~DACL_SECURITY_INFORMATION;
2120                         goto retry;
2121                 }
2122                 if (info & OWNER_SECURITY_INFORMATION) {
2123                         info &= ~OWNER_SECURITY_INFORMATION;
2124                         goto retry;
2125                 }
2126                 /* Nothing left except GROUP, and if we removed it we
2127                  * wouldn't have anything at all.  */
2128         }
2129
2130         /* No part of the security descriptor could be set, or
2131          * WIMLIB_EXTRACT_FLAG_STRICT_ACLS is enabled and the full security
2132          * descriptor could not be set.  */
2133         if (!(info & SACL_SECURITY_INFORMATION))
2134                 ctx->partial_security_descriptors--;
2135         ctx->no_security_descriptors++;
2136
2137 out_maybe_free_desc:
2138         if (unlikely(desc_size > STACK_MAX))
2139                 FREE(desc);
2140         return status;
2141 }
2142
2143 /* Set metadata on the open file @h from the WIM inode @inode.  */
2144 static int
2145 do_apply_metadata_to_file(HANDLE h, const struct wim_inode *inode,
2146                           struct win32_apply_ctx *ctx)
2147 {
2148         FILE_BASIC_INFORMATION info;
2149         NTSTATUS status;
2150
2151         /* Set security descriptor if present and not in NO_ACLS mode  */
2152         if (inode->i_security_id >= 0 &&
2153             !(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS))
2154         {
2155                 const struct wim_security_data *sd;
2156                 const void *desc;
2157                 size_t desc_size;
2158
2159                 sd = wim_get_current_security_data(ctx->common.wim);
2160                 desc = sd->descriptors[inode->i_security_id];
2161                 desc_size = sd->sizes[inode->i_security_id];
2162
2163                 status = set_security_descriptor(h, desc, desc_size, ctx);
2164                 if (!NT_SUCCESS(status) &&
2165                     (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
2166                 {
2167                         set_errno_from_nt_status(status);
2168                         ERROR_WITH_ERRNO("Can't set security descriptor "
2169                                          "on \"%ls\" (status=0x%08"PRIx32")",
2170                                          current_path(ctx), (u32)status);
2171                         return WIMLIB_ERR_SET_SECURITY;
2172                 }
2173         }
2174
2175         /* Set attributes and timestamps  */
2176         info.CreationTime.QuadPart = inode->i_creation_time;
2177         info.LastAccessTime.QuadPart = inode->i_last_access_time;
2178         info.LastWriteTime.QuadPart = inode->i_last_write_time;
2179         info.ChangeTime.QuadPart = 0;
2180         if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)
2181                 info.FileAttributes = 0;
2182         else
2183                 info.FileAttributes = inode->i_attributes & ~SPECIAL_ATTRIBUTES;
2184
2185         status = (*func_NtSetInformationFile)(h, &ctx->iosb,
2186                                               &info, sizeof(info),
2187                                               FileBasicInformation);
2188         /* On FAT volumes we get STATUS_INVALID_PARAMETER if we try to set
2189          * attributes on the root directory.  (Apparently because FAT doesn't
2190          * actually have a place to store those attributes!)  */
2191         if (!NT_SUCCESS(status)
2192             && !(status == STATUS_INVALID_PARAMETER &&
2193                  dentry_is_root(inode_first_extraction_dentry(inode))))
2194         {
2195                 set_errno_from_nt_status(status);
2196                 ERROR_WITH_ERRNO("Can't set basic metadata on \"%ls\" "
2197                                  "(status=0x%08"PRIx32")",
2198                                  current_path(ctx), (u32)status);
2199                 return WIMLIB_ERR_SET_ATTRIBUTES;
2200         }
2201
2202         return 0;
2203 }
2204
2205 static int
2206 apply_metadata_to_file(const struct wim_dentry *dentry,
2207                        struct win32_apply_ctx *ctx)
2208 {
2209         const struct wim_inode *inode = dentry->d_inode;
2210         DWORD perms;
2211         HANDLE h;
2212         NTSTATUS status;
2213         int ret;
2214
2215         perms = FILE_WRITE_ATTRIBUTES | WRITE_DAC |
2216                 WRITE_OWNER | ACCESS_SYSTEM_SECURITY;
2217
2218         build_extraction_path(dentry, ctx);
2219
2220         /* Open a handle with as many relevant permissions as possible.  */
2221         while (!NT_SUCCESS(status = do_create_file(&h, perms, NULL,
2222                                                    0, FILE_OPEN, 0, ctx)))
2223         {
2224                 if (status == STATUS_PRIVILEGE_NOT_HELD ||
2225                     status == STATUS_ACCESS_DENIED)
2226                 {
2227                         if (perms & ACCESS_SYSTEM_SECURITY) {
2228                                 perms &= ~ACCESS_SYSTEM_SECURITY;
2229                                 continue;
2230                         }
2231                         if (perms & WRITE_DAC) {
2232                                 perms &= ~WRITE_DAC;
2233                                 continue;
2234                         }
2235                         if (perms & WRITE_OWNER) {
2236                                 perms &= ~WRITE_OWNER;
2237                                 continue;
2238                         }
2239                 }
2240                 set_errno_from_nt_status(status);
2241                 ERROR_WITH_ERRNO("Can't open \"%ls\" to set metadata "
2242                                  "(status=0x%08"PRIx32")",
2243                                  current_path(ctx), (u32)status);
2244                 return WIMLIB_ERR_OPEN;
2245         }
2246
2247         ret = do_apply_metadata_to_file(h, inode, ctx);
2248
2249         (*func_NtClose)(h);
2250
2251         return ret;
2252 }
2253
2254 static int
2255 apply_metadata(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
2256 {
2257         const struct wim_dentry *dentry;
2258         int ret;
2259
2260         /* We go in reverse so that metadata is set on all a directory's
2261          * children before the directory itself.  This avoids any potential
2262          * problems with attributes, timestamps, or security descriptors.  */
2263         list_for_each_entry_reverse(dentry, dentry_list, d_extraction_list_node)
2264         {
2265                 ret = apply_metadata_to_file(dentry, ctx);
2266                 if (ret)
2267                         return ret;
2268                 ret = report_file_metadata_applied(&ctx->common);
2269                 if (ret)
2270                         return ret;
2271         }
2272         return 0;
2273 }
2274
2275 /* Issue warnings about problems during the extraction for which warnings were
2276  * not already issued (due to the high number of potential warnings if we issued
2277  * them per-file).  */
2278 static void
2279 do_warnings(const struct win32_apply_ctx *ctx)
2280 {
2281         if (ctx->partial_security_descriptors == 0 &&
2282             ctx->no_security_descriptors == 0 &&
2283             ctx->num_short_name_failures == 0)
2284                 return;
2285
2286         WARNING("Extraction to \"%ls\" complete, but with one or more warnings:",
2287                 ctx->common.target);
2288         if (ctx->num_short_name_failures) {
2289                 WARNING("- Could not set short names on %lu files or directories",
2290                         ctx->num_short_name_failures);
2291         }
2292         if (ctx->partial_security_descriptors) {
2293                 WARNING("- Could only partially set the security descriptor\n"
2294                         "            on %lu files or directories.",
2295                         ctx->partial_security_descriptors);
2296         }
2297         if (ctx->no_security_descriptors) {
2298                 WARNING("- Could not set security descriptor at all\n"
2299                         "            on %lu files or directories.",
2300                         ctx->no_security_descriptors);
2301         }
2302         if (ctx->partial_security_descriptors || ctx->no_security_descriptors) {
2303                 WARNING("To fully restore all security descriptors, run the program\n"
2304                         "          with Administrator rights.");
2305         }
2306 }
2307
2308 static uint64_t
2309 count_dentries(const struct list_head *dentry_list)
2310 {
2311         const struct list_head *cur;
2312         uint64_t count = 0;
2313
2314         list_for_each(cur, dentry_list)
2315                 count++;
2316
2317         return count;
2318 }
2319
2320 /* Extract files from a WIM image to a directory on Windows  */
2321 static int
2322 win32_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
2323 {
2324         int ret;
2325         struct win32_apply_ctx *ctx = (struct win32_apply_ctx *)_ctx;
2326         uint64_t dentry_count;
2327
2328         ret = prepare_target(dentry_list, ctx);
2329         if (ret)
2330                 goto out;
2331
2332         if (unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT)) {
2333                 ret = start_wimboot_extraction(ctx);
2334                 if (ret)
2335                         goto out;
2336         }
2337
2338         dentry_count = count_dentries(dentry_list);
2339
2340         ret = start_file_structure_phase(&ctx->common, dentry_count);
2341         if (ret)
2342                 goto out;
2343
2344         ret = create_directories(dentry_list, ctx);
2345         if (ret)
2346                 goto out;
2347
2348         ret = create_nondirectories(dentry_list, ctx);
2349         if (ret)
2350                 goto out;
2351
2352         ret = end_file_structure_phase(&ctx->common);
2353         if (ret)
2354                 goto out;
2355
2356         struct read_stream_list_callbacks cbs = {
2357                 .begin_stream      = begin_extract_stream,
2358                 .begin_stream_ctx  = ctx,
2359                 .consume_chunk     = extract_chunk,
2360                 .consume_chunk_ctx = ctx,
2361                 .end_stream        = end_extract_stream,
2362                 .end_stream_ctx    = ctx,
2363         };
2364         ret = extract_stream_list(&ctx->common, &cbs);
2365         if (ret)
2366                 goto out;
2367
2368         ret = start_file_metadata_phase(&ctx->common, dentry_count);
2369         if (ret)
2370                 goto out;
2371
2372         ret = apply_metadata(dentry_list, ctx);
2373         if (ret)
2374                 goto out;
2375
2376         ret = end_file_metadata_phase(&ctx->common);
2377         if (ret)
2378                 goto out;
2379
2380         if (unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT)) {
2381                 ret = end_wimboot_extraction(ctx);
2382                 if (ret)
2383                         goto out;
2384         }
2385
2386         do_warnings(ctx);
2387 out:
2388         if (ctx->h_target)
2389                 (*func_NtClose)(ctx->h_target);
2390         if (ctx->target_ntpath.Buffer)
2391                 HeapFree(GetProcessHeap(), 0, ctx->target_ntpath.Buffer);
2392         FREE(ctx->pathbuf.Buffer);
2393         FREE(ctx->print_buffer);
2394         if (ctx->wimboot.prepopulate_pats) {
2395                 FREE(ctx->wimboot.prepopulate_pats->strings);
2396                 FREE(ctx->wimboot.prepopulate_pats);
2397         }
2398         FREE(ctx->wimboot.mem_prepopulate_pats);
2399         FREE(ctx->data_buffer);
2400         return ret;
2401 }
2402
2403 const struct apply_operations win32_apply_ops = {
2404         .name                   = "Windows",
2405         .get_supported_features = win32_get_supported_features,
2406         .extract                = win32_extract,
2407         .will_externally_back   = win32_will_externally_back,
2408         .context_size           = sizeof(struct win32_apply_ctx),
2409 };
2410
2411 #endif /* __WIN32__ */