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