]> wimlib.net Git - wimlib/blob - src/win32_apply.c
c1fbc491bfe116482d2a9f85fa491c50bdb28b7f
[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          * FileName seemingly does not, however, need to be null-terminated in
957          * any case.
958          */
959
960         size_t bufsize = offsetof(FILE_NAME_INFORMATION, FileName) +
961                          max(dentry->short_name_nbytes, 2 * sizeof(wchar_t));
962         u8 buf[bufsize] _aligned_attribute(8);
963         FILE_NAME_INFORMATION *info = (FILE_NAME_INFORMATION *)buf;
964         NTSTATUS status;
965
966         info->FileNameLength = dentry->short_name_nbytes;
967         memcpy(info->FileName, dentry->short_name, dentry->short_name_nbytes);
968
969
970 retry:
971         status = (*func_NtSetInformationFile)(h, &ctx->iosb, info, bufsize,
972                                               FileShortNameInformation);
973         if (NT_SUCCESS(status))
974                 return 0;
975
976         if (status == STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME) {
977                 if (dentry->short_name_nbytes == 0)
978                         return 0;
979                 if (!ctx->tried_to_enable_short_names) {
980                         wchar_t volume[7];
981                         int ret;
982
983                         ctx->tried_to_enable_short_names = true;
984
985                         ret = win32_get_drive_path(ctx->common.target,
986                                                    volume);
987                         if (ret)
988                                 return ret;
989                         if (try_to_enable_short_names(volume))
990                                 goto retry;
991                 }
992         }
993
994         /* By default, failure to set short names is not an error (since short
995          * names aren't too important anymore...).  */
996         if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES)) {
997                 ctx->num_short_name_failures++;
998                 return 0;
999         }
1000
1001         if (status == STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME) {
1002                 ERROR("Can't set short name when short "
1003                       "names are not enabled on the volume!");
1004         } else {
1005                 ERROR("Can't set short name on \"%ls\" (status=0x%08"PRIx32")",
1006                       current_path(ctx), (u32)status);
1007         }
1008         return WIMLIB_ERR_SET_SHORT_NAME;
1009 }
1010
1011 /*
1012  * A wrapper around NtCreateFile() to make it slightly more usable...
1013  * This uses the path currently constructed in ctx->pathbuf.
1014  *
1015  * Also, we always specify FILE_OPEN_FOR_BACKUP_INTENT and
1016  * FILE_OPEN_REPARSE_POINT.
1017  */
1018 static NTSTATUS
1019 do_create_file(PHANDLE FileHandle,
1020                ACCESS_MASK DesiredAccess,
1021                PLARGE_INTEGER AllocationSize,
1022                ULONG FileAttributes,
1023                ULONG CreateDisposition,
1024                ULONG CreateOptions,
1025                struct win32_apply_ctx *ctx)
1026 {
1027         return (*func_NtCreateFile)(FileHandle,
1028                                     DesiredAccess,
1029                                     &ctx->attr,
1030                                     &ctx->iosb,
1031                                     AllocationSize,
1032                                     FileAttributes,
1033                                     FILE_SHARE_VALID_FLAGS,
1034                                     CreateDisposition,
1035                                     CreateOptions |
1036                                         FILE_OPEN_FOR_BACKUP_INTENT |
1037                                         FILE_OPEN_REPARSE_POINT,
1038                                     NULL,
1039                                     0);
1040 }
1041
1042 /* Like do_create_file(), but builds the extraction path of the @dentry first.
1043  */
1044 static NTSTATUS
1045 create_file(PHANDLE FileHandle,
1046             ACCESS_MASK DesiredAccess,
1047             PLARGE_INTEGER AllocationSize,
1048             ULONG FileAttributes,
1049             ULONG CreateDisposition,
1050             ULONG CreateOptions,
1051             const struct wim_dentry *dentry,
1052             struct win32_apply_ctx *ctx)
1053 {
1054         build_extraction_path(dentry, ctx);
1055         return do_create_file(FileHandle,
1056                               DesiredAccess,
1057                               AllocationSize,
1058                               FileAttributes,
1059                               CreateDisposition,
1060                               CreateOptions,
1061                               ctx);
1062 }
1063
1064 /* Create empty named data streams.
1065  *
1066  * Since these won't have 'struct wim_lookup_table_entry's, they won't show up
1067  * in the call to extract_stream_list().  Hence the need for the special case.
1068  */
1069 static int
1070 create_any_empty_ads(const struct wim_dentry *dentry,
1071                      struct win32_apply_ctx *ctx)
1072 {
1073         const struct wim_inode *inode = dentry->d_inode;
1074         LARGE_INTEGER allocation_size;
1075         bool path_modified = false;
1076         int ret = 0;
1077
1078         if (!ctx->common.supported_features.named_data_streams)
1079                 return 0;
1080
1081         for (u16 i = 0; i < inode->i_num_ads; i++) {
1082                 const struct wim_ads_entry *entry;
1083                 NTSTATUS status;
1084                 HANDLE h;
1085
1086                 entry = &inode->i_ads_entries[i];
1087
1088                 /* Not named?  */
1089                 if (!entry->stream_name_nbytes)
1090                         continue;
1091
1092                 /* Not empty?  */
1093                 if (entry->lte)
1094                         continue;
1095
1096                 /* Probably setting the allocation size to 0 has no effect, but
1097                  * we might as well try.  */
1098                 allocation_size.QuadPart = 0;
1099
1100                 build_extraction_path_with_ads(dentry, ctx,
1101                                                entry->stream_name,
1102                                                entry->stream_name_nbytes /
1103                                                         sizeof(wchar_t));
1104                 path_modified = true;
1105                 status = do_create_file(&h, FILE_WRITE_DATA, &allocation_size,
1106                                         0, FILE_SUPERSEDE, 0, ctx);
1107                 if (!NT_SUCCESS(status)) {
1108                         set_errno_from_nt_status(status);
1109                         ERROR_WITH_ERRNO("Can't create \"%ls\" "
1110                                          "(status=0x%08"PRIx32")",
1111                                          current_path(ctx), (u32)status);
1112                         ret = WIMLIB_ERR_OPEN;
1113                         break;
1114                 }
1115                 (*func_NtClose)(h);
1116         }
1117         /* Restore the path to the dentry itself  */
1118         if (path_modified)
1119                 build_extraction_path(dentry, ctx);
1120         return ret;
1121 }
1122
1123 /*
1124  * Creates the directory named by @dentry, or uses an existing directory at that
1125  * location.  If necessary, sets the short name and/or fixes compression and
1126  * encryption attributes.
1127  *
1128  * Returns 0, WIMLIB_ERR_MKDIR, or WIMLIB_ERR_SET_SHORT_NAME.
1129  */
1130 static int
1131 create_directory(const struct wim_dentry *dentry,
1132                  struct win32_apply_ctx *ctx)
1133 {
1134         HANDLE h;
1135         NTSTATUS status;
1136         int ret;
1137         ULONG attrib;
1138
1139         /* Special attributes:
1140          *
1141          * Use FILE_ATTRIBUTE_ENCRYPTED if the directory needs to have it set.
1142          * This doesn't work for FILE_ATTRIBUTE_COMPRESSED (unfortunately).
1143          *
1144          * Don't specify FILE_ATTRIBUTE_DIRECTORY; it gets set anyway as a
1145          * result of the FILE_DIRECTORY_FILE option.  */
1146         attrib = (dentry->d_inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED);
1147
1148         /* DELETE is needed for set_short_name().
1149          * GENERIC_READ and GENERIC_WRITE are needed for
1150          * adjust_compression_attribute().  */
1151         status = create_file(&h, GENERIC_READ | GENERIC_WRITE | DELETE, NULL,
1152                              attrib, FILE_OPEN_IF, FILE_DIRECTORY_FILE,
1153                              dentry, ctx);
1154         if (!NT_SUCCESS(status)) {
1155                 set_errno_from_nt_status(status);
1156                 ERROR_WITH_ERRNO("Can't create directory \"%ls\" "
1157                                  "(status=0x%08"PRIx32")",
1158                                  current_path(ctx), (u32)status);
1159                 return WIMLIB_ERR_MKDIR;
1160         }
1161
1162         ret = set_short_name(h, dentry, ctx);
1163
1164         if (!ret)
1165                 ret = adjust_compression_attribute(h, dentry, ctx);
1166
1167         if (!ret)
1168                 ret = maybe_clear_encryption_attribute(&h, dentry, ctx);
1169                 /* May close the handle!!! */
1170
1171         if (h)
1172                 (*func_NtClose)(h);
1173         return ret;
1174 }
1175
1176 /*
1177  * Create all the directories being extracted, other than the target directory
1178  * itself.
1179  *
1180  * Note: we don't honor directory hard links.  However, we don't allow them to
1181  * exist in WIM images anyway (see inode_fixup.c).
1182  */
1183 static int
1184 create_directories(struct list_head *dentry_list,
1185                    struct win32_apply_ctx *ctx)
1186 {
1187         const struct wim_dentry *dentry;
1188         int ret;
1189
1190         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
1191
1192                 if (!(dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY))
1193                         continue;
1194
1195                 /* Note: Here we include files with
1196                  * FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT, but we
1197                  * wait until later to actually set the reparse data.  */
1198
1199                 /* If the root dentry is being extracted, it was already done so
1200                  * in prepare_target().  */
1201                 if (!dentry_is_root(dentry)) {
1202                         ret = create_directory(dentry, ctx);
1203                         if (ret)
1204                                 return ret;
1205
1206                         ret = create_any_empty_ads(dentry, ctx);
1207                         if (ret)
1208                                 return ret;
1209                 }
1210
1211                 ret = report_file_created(&ctx->common);
1212                 if (ret)
1213                         return ret;
1214         }
1215         return 0;
1216 }
1217
1218 /*
1219  * Creates the nondirectory file named by @dentry.
1220  *
1221  * On success, returns an open handle to the file in @h_ret, with GENERIC_READ,
1222  * GENERIC_WRITE, and DELETE access.  Also, the path to the file will be saved
1223  * in ctx->pathbuf.  On failure, returns WIMLIB_ERR_OPEN.
1224  */
1225 static int
1226 create_nondirectory_inode(HANDLE *h_ret, const struct wim_dentry *dentry,
1227                           struct win32_apply_ctx *ctx)
1228 {
1229         const struct wim_inode *inode;
1230         ULONG attrib;
1231         NTSTATUS status;
1232         bool retried = false;
1233
1234         inode = dentry->d_inode;
1235
1236         /* If the file already exists and has FILE_ATTRIBUTE_SYSTEM and/or
1237          * FILE_ATTRIBUTE_HIDDEN, these must be specified in order to supersede
1238          * the file.
1239          *
1240          * Normally the user shouldn't be trying to overwrite such files anyway,
1241          * but we at least provide FILE_ATTRIBUTE_SYSTEM and
1242          * FILE_ATTRIBUTE_HIDDEN if the WIM inode has those attributes so that
1243          * we catch the case where the user extracts the same files to the same
1244          * location more than one time.
1245          *
1246          * Also specify FILE_ATTRIBUTE_ENCRYPTED if the file needs to be
1247          * encrypted.
1248          *
1249          * In NO_ATTRIBUTES mode just don't specify any attributes at all.
1250          */
1251         if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES) {
1252                 attrib = 0;
1253         } else {
1254                 attrib = (inode->i_attributes & (FILE_ATTRIBUTE_SYSTEM |
1255                                                  FILE_ATTRIBUTE_HIDDEN |
1256                                                  FILE_ATTRIBUTE_ENCRYPTED));
1257         }
1258         build_extraction_path(dentry, ctx);
1259 retry:
1260         status = do_create_file(h_ret, GENERIC_READ | GENERIC_WRITE | DELETE,
1261                                 NULL, attrib, FILE_SUPERSEDE,
1262                                 FILE_NON_DIRECTORY_FILE, ctx);
1263         if (NT_SUCCESS(status)) {
1264                 int ret;
1265
1266                 ret = adjust_compression_attribute(*h_ret, dentry, ctx);
1267                 if (ret) {
1268                         (*func_NtClose)(*h_ret);
1269                         return ret;
1270                 }
1271
1272                 ret = maybe_clear_encryption_attribute(h_ret, dentry, ctx);
1273                 /* May close the handle!!! */
1274
1275                 if (ret) {
1276                         if (*h_ret)
1277                                 (*func_NtClose)(*h_ret);
1278                         return ret;
1279                 }
1280
1281                 if (!*h_ret) {
1282                         /* Re-open the handle so that we can return it on
1283                          * success.  */
1284                         status = do_create_file(h_ret,
1285                                                 GENERIC_READ |
1286                                                         GENERIC_WRITE | DELETE,
1287                                                 NULL, 0, FILE_OPEN,
1288                                                 FILE_NON_DIRECTORY_FILE, ctx);
1289                         if (!NT_SUCCESS(status))
1290                                 goto fail;
1291                 }
1292
1293                 ret = create_any_empty_ads(dentry, ctx);
1294                 if (ret) {
1295                         (*func_NtClose)(*h_ret);
1296                         return ret;
1297                 }
1298                 return 0;
1299         }
1300
1301         if (status == STATUS_ACCESS_DENIED && !retried) {
1302                 /* We also can't supersede an existing file that has
1303                  * FILE_ATTRIBUTE_READONLY set; doing so causes NtCreateFile()
1304                  * to return STATUS_ACCESS_DENIED .  The only workaround seems
1305                  * to be to explicitly remove FILE_ATTRIBUTE_READONLY on the
1306                  * existing file, then try again.  */
1307
1308                 FILE_BASIC_INFORMATION info;
1309                 HANDLE h;
1310
1311                 status = do_create_file(&h, FILE_WRITE_ATTRIBUTES, NULL, 0,
1312                                         FILE_OPEN, FILE_NON_DIRECTORY_FILE, ctx);
1313                 if (!NT_SUCCESS(status))
1314                         goto fail;
1315
1316                 memset(&info, 0, sizeof(info));
1317                 info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1318
1319                 status = (*func_NtSetInformationFile)(h, &ctx->iosb,
1320                                                       &info, sizeof(info),
1321                                                       FileBasicInformation);
1322                 (*func_NtClose)(h);
1323                 if (!NT_SUCCESS(status))
1324                         goto fail;
1325                 retried = true;
1326                 goto retry;
1327         }
1328 fail:
1329         set_errno_from_nt_status(status);
1330         ERROR_WITH_ERRNO("Can't create file \"%ls\" (status=0x%08"PRIx32")",
1331                          current_path(ctx), (u32)status);
1332         return WIMLIB_ERR_OPEN;
1333 }
1334
1335 /* Creates a hard link at the location named by @dentry to the file represented
1336  * by the open handle @h.  Or, if the target volume does not support hard links,
1337  * create a separate file instead.  */
1338 static int
1339 create_link(HANDLE h, const struct wim_dentry *dentry,
1340             struct win32_apply_ctx *ctx)
1341 {
1342         if (ctx->common.supported_features.hard_links) {
1343
1344                 build_extraction_path(dentry, ctx);
1345
1346                 size_t bufsize = offsetof(FILE_LINK_INFORMATION, FileName) +
1347                                  ctx->pathbuf.Length + sizeof(wchar_t);
1348                 u8 buf[bufsize] _aligned_attribute(8);
1349                 FILE_LINK_INFORMATION *info = (FILE_LINK_INFORMATION *)buf;
1350                 NTSTATUS status;
1351
1352                 info->ReplaceIfExists = TRUE;
1353                 info->RootDirectory = ctx->attr.RootDirectory;
1354                 info->FileNameLength = ctx->pathbuf.Length;
1355                 memcpy(info->FileName, ctx->pathbuf.Buffer, ctx->pathbuf.Length);
1356                 info->FileName[info->FileNameLength / 2] = L'\0';
1357
1358                 /* Note: the null terminator isn't actually necessary,
1359                  * but if you don't add the extra character, you get
1360                  * STATUS_INFO_LENGTH_MISMATCH when FileNameLength
1361                  * happens to be 2  */
1362
1363                 status = (*func_NtSetInformationFile)(h, &ctx->iosb,
1364                                                       info, bufsize,
1365                                                       FileLinkInformation);
1366                 if (NT_SUCCESS(status))
1367                         return 0;
1368                 ERROR("Failed to create link \"%ls\" (status=0x%08"PRIx32")",
1369                       current_path(ctx), (u32)status);
1370                 return WIMLIB_ERR_LINK;
1371         } else {
1372                 HANDLE h2;
1373                 int ret;
1374
1375                 ret = create_nondirectory_inode(&h2, dentry, ctx);
1376                 if (ret)
1377                         return ret;
1378
1379                 (*func_NtClose)(h2);
1380                 return 0;
1381         }
1382 }
1383
1384 /* Given an inode (represented by the open handle @h) for which one link has
1385  * been created (named by @first_dentry), create the other links.
1386  *
1387  * Or, if the target volume does not support hard links, create separate files.
1388  *
1389  * Note: This uses ctx->pathbuf and does not reset it.
1390  */
1391 static int
1392 create_links(HANDLE h, const struct wim_dentry *first_dentry,
1393              struct win32_apply_ctx *ctx)
1394 {
1395         const struct wim_inode *inode;
1396         const struct list_head *next;
1397         const struct wim_dentry *dentry;
1398         int ret;
1399
1400         inode = first_dentry->d_inode;
1401         next = inode->i_extraction_aliases.next;
1402         do {
1403                 dentry = list_entry(next, struct wim_dentry,
1404                                     d_extraction_alias_node);
1405                 if (dentry != first_dentry) {
1406                         ret = create_link(h, dentry, ctx);
1407                         if (ret)
1408                                 return ret;
1409                 }
1410                 next = next->next;
1411         } while (next != &inode->i_extraction_aliases);
1412         return 0;
1413 }
1414
1415 /* Create a nondirectory file, including all links.  */
1416 static int
1417 create_nondirectory(const struct wim_inode *inode, struct win32_apply_ctx *ctx)
1418 {
1419         struct wim_dentry *first_dentry;
1420         HANDLE h;
1421         int ret;
1422
1423         first_dentry = first_extraction_alias(inode);
1424
1425         /* Create first link.  */
1426         ret = create_nondirectory_inode(&h, first_dentry, ctx);
1427         if (ret)
1428                 return ret;
1429
1430         /* Set short name.  */
1431         ret = set_short_name(h, first_dentry, ctx);
1432
1433         /* Create additional links, OR if hard links are not supported just
1434          * create more files.  */
1435         if (!ret)
1436                 ret = create_links(h, first_dentry, ctx);
1437
1438         /* "WIMBoot" extraction: set external backing by the WIM file if needed.  */
1439         if (!ret && unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT))
1440                 ret = set_external_backing(h, first_dentry, ctx);
1441
1442         (*func_NtClose)(h);
1443         return ret;
1444 }
1445
1446 /* Create all the nondirectory files being extracted, including all aliases
1447  * (hard links).  */
1448 static int
1449 create_nondirectories(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
1450 {
1451         const struct wim_dentry *dentry;
1452         const struct wim_inode *inode;
1453         int ret;
1454
1455         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
1456                 inode = dentry->d_inode;
1457                 if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
1458                         continue;
1459                 /* Call create_nondirectory() only once per inode  */
1460                 if (dentry == inode_first_extraction_dentry(inode)) {
1461                         ret = create_nondirectory(inode, ctx);
1462                         if (ret)
1463                                 return ret;
1464                 }
1465                 ret = report_file_created(&ctx->common);
1466                 if (ret)
1467                         return ret;
1468         }
1469         return 0;
1470 }
1471
1472 static void
1473 close_handles(struct win32_apply_ctx *ctx)
1474 {
1475         for (unsigned i = 0; i < ctx->num_open_handles; i++)
1476                 (*func_NtClose)(ctx->open_handles[i]);
1477 }
1478
1479 /* Prepare to read the next stream, which has size @stream_size, into an
1480  * in-memory buffer.  */
1481 static int
1482 prepare_data_buffer(struct win32_apply_ctx *ctx, u64 stream_size)
1483 {
1484         if (stream_size > ctx->data_buffer_size) {
1485                 /* Larger buffer needed.  */
1486                 void *new_buffer;
1487                 if ((size_t)stream_size != stream_size)
1488                         return WIMLIB_ERR_NOMEM;
1489                 new_buffer = REALLOC(ctx->data_buffer, stream_size);
1490                 if (!new_buffer)
1491                         return WIMLIB_ERR_NOMEM;
1492                 ctx->data_buffer = new_buffer;
1493                 ctx->data_buffer_size = stream_size;
1494         }
1495         /* On the first call this changes data_buffer_ptr from NULL, which tells
1496          * extract_chunk() that the data buffer needs to be filled while reading
1497          * the stream data.  */
1498         ctx->data_buffer_ptr = ctx->data_buffer;
1499         return 0;
1500 }
1501
1502 static int
1503 begin_extract_stream_instance(const struct wim_lookup_table_entry *stream,
1504                               struct wim_dentry *dentry,
1505                               const wchar_t *stream_name,
1506                               struct win32_apply_ctx *ctx)
1507 {
1508         const struct wim_inode *inode = dentry->d_inode;
1509         size_t stream_name_nchars = 0;
1510         FILE_ALLOCATION_INFORMATION alloc_info;
1511         HANDLE h;
1512         NTSTATUS status;
1513
1514         if (unlikely(stream_name))
1515                 stream_name_nchars = wcslen(stream_name);
1516
1517         if (unlikely(stream_name_nchars)) {
1518                 build_extraction_path_with_ads(dentry, ctx,
1519                                                stream_name, stream_name_nchars);
1520         } else {
1521                 build_extraction_path(dentry, ctx);
1522         }
1523
1524         /* Reparse point?  */
1525         if (unlikely(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)
1526             && (stream_name_nchars == 0))
1527         {
1528                 if (!ctx->common.supported_features.reparse_points)
1529                         return 0;
1530
1531                 /* We can't write the reparse stream directly; we must set it
1532                  * with FSCTL_SET_REPARSE_POINT, which requires that all the
1533                  * data be available.  So, stage the data in a buffer.  */
1534
1535                 list_add_tail(&dentry->tmp_list, &ctx->reparse_dentries);
1536                 return prepare_data_buffer(ctx, stream->size);
1537         }
1538
1539         /* Encrypted file?  */
1540         if (unlikely(inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED)
1541             && (stream_name_nchars == 0))
1542         {
1543                 if (!ctx->common.supported_features.encrypted_files)
1544                         return 0;
1545
1546                 /* We can't write encrypted file streams directly; we must use
1547                  * WriteEncryptedFileRaw(), which requires providing the data
1548                  * through a callback function.  This can't easily be combined
1549                  * with our own callback-based approach.
1550                  *
1551                  * The current workaround is to simply read the stream into
1552                  * memory and write the encrypted file from that.
1553                  *
1554                  * TODO: This isn't sufficient for extremely large encrypted
1555                  * files.  Perhaps we should create an extra thread to write
1556                  * such files...  */
1557                 list_add_tail(&dentry->tmp_list, &ctx->encrypted_dentries);
1558                 return prepare_data_buffer(ctx, stream->size);
1559         }
1560
1561         if (ctx->num_open_handles == MAX_OPEN_STREAMS) {
1562                 /* XXX: Fix this.  But because of the checks in
1563                  * extract_stream_list(), this can now only happen on a
1564                  * filesystem that does not support hard links.  */
1565                 ERROR("Can't extract data: too many open files!");
1566                 return WIMLIB_ERR_UNSUPPORTED;
1567         }
1568
1569         /* Open a new handle  */
1570         status = do_create_file(&h,
1571                                 FILE_WRITE_DATA | SYNCHRONIZE,
1572                                 NULL, 0, FILE_OPEN_IF,
1573                                 FILE_SEQUENTIAL_ONLY |
1574                                         FILE_SYNCHRONOUS_IO_NONALERT,
1575                                 ctx);
1576         if (!NT_SUCCESS(status)) {
1577                 set_errno_from_nt_status(status);
1578                 ERROR_WITH_ERRNO("Can't open \"%ls\" for writing "
1579                                  "(status=0x%08"PRIx32")",
1580                                  current_path(ctx), (u32)status);
1581                 return WIMLIB_ERR_OPEN;
1582         }
1583
1584         ctx->open_handles[ctx->num_open_handles++] = h;
1585
1586         /* Allocate space for the data.  */
1587         alloc_info.AllocationSize.QuadPart = stream->size;
1588         (*func_NtSetInformationFile)(h, &ctx->iosb,
1589                                      &alloc_info, sizeof(alloc_info),
1590                                      FileAllocationInformation);
1591         return 0;
1592 }
1593
1594 /* Set the reparse data @rpbuf of length @rpbuflen on the extracted file
1595  * corresponding to the WIM dentry @dentry.  */
1596 static int
1597 do_set_reparse_data(const struct wim_dentry *dentry,
1598                     const void *rpbuf, u16 rpbuflen,
1599                     struct win32_apply_ctx *ctx)
1600 {
1601         NTSTATUS status;
1602         HANDLE h;
1603
1604         status = create_file(&h, GENERIC_WRITE, NULL,
1605                              0, FILE_OPEN, 0, dentry, ctx);
1606         if (!NT_SUCCESS(status))
1607                 goto fail;
1608
1609         status = (*func_NtFsControlFile)(h, NULL, NULL, NULL,
1610                                          &ctx->iosb, FSCTL_SET_REPARSE_POINT,
1611                                          (void *)rpbuf, rpbuflen,
1612                                          NULL, 0);
1613         (*func_NtClose)(h);
1614
1615         if (NT_SUCCESS(status))
1616                 return 0;
1617
1618         /* On Windows, by default only the Administrator can create symbolic
1619          * links for some reason.  By default we just issue a warning if this
1620          * appears to be the problem.  Use WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS
1621          * to get a hard error.  */
1622         if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS)
1623             && (status == STATUS_PRIVILEGE_NOT_HELD ||
1624                 status == STATUS_ACCESS_DENIED)
1625             && (dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
1626                 dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT))
1627         {
1628                 WARNING("Can't create symbolic link \"%ls\"!              \n"
1629                         "          (Need Administrator rights, or at least "
1630                         "the\n"
1631                         "          SeCreateSymbolicLink privilege.)",
1632                         current_path(ctx));
1633                 return 0;
1634         }
1635
1636 fail:
1637         set_errno_from_nt_status(status);
1638         ERROR_WITH_ERRNO("Can't set reparse data on \"%ls\" "
1639                          "(status=0x%08"PRIx32")",
1640                          current_path(ctx), (u32)status);
1641         return WIMLIB_ERR_SET_REPARSE_DATA;
1642 }
1643
1644 /* Given a Windows NT namespace path, such as \??\e:\Windows\System32, return a
1645  * pointer to the suffix of the path that begins with the device directly, such
1646  * as e:\Windows\System32.  */
1647 static const wchar_t *
1648 skip_nt_toplevel_component(const wchar_t *path, size_t path_nchars)
1649 {
1650         static const wchar_t * const dirs[] = {
1651                 L"\\??\\",
1652                 L"\\DosDevices\\",
1653                 L"\\Device\\",
1654         };
1655         size_t first_dir_len = 0;
1656         const wchar_t * const end = path + path_nchars;
1657
1658         for (size_t i = 0; i < ARRAY_LEN(dirs); i++) {
1659                 size_t len = wcslen(dirs[i]);
1660                 if (len <= (end - path) && !wcsnicmp(path, dirs[i], len)) {
1661                         first_dir_len = len;
1662                         break;
1663                 }
1664         }
1665         if (first_dir_len == 0)
1666                 return path;
1667         path += first_dir_len;
1668         while (path != end && *path == L'\\')
1669                 path++;
1670         return path;
1671 }
1672
1673 /* Given a Windows NT namespace path, such as \??\e:\Windows\System32, return a
1674  * pointer to the suffix of the path that is device-relative, such as
1675  * Windows\System32.
1676  *
1677  * The path has an explicit length and is not necessarily null terminated.
1678  *
1679  * If the path just something like \??\e: then the returned pointer will point
1680  * just past the colon.  In this case the length of the result will be 0
1681  * characters.  */
1682 static const wchar_t *
1683 get_device_relative_path(const wchar_t *path, size_t path_nchars)
1684 {
1685         const wchar_t * const orig_path = path;
1686         const wchar_t * const end = path + path_nchars;
1687
1688         path = skip_nt_toplevel_component(path, path_nchars);
1689         if (path == orig_path)
1690                 return orig_path;
1691
1692         path = wmemchr(path, L'\\', (end - path));
1693         if (!path)
1694                 return end;
1695         do {
1696                 path++;
1697         } while (path != end && *path == L'\\');
1698         return path;
1699 }
1700
1701 /*
1702  * Given a reparse point buffer for a symbolic link or junction, adjust its
1703  * contents so that the target of the link is consistent with the new location
1704  * of the files.
1705  */
1706 static void
1707 try_rpfix(u8 *rpbuf, u16 *rpbuflen_p, struct win32_apply_ctx *ctx)
1708 {
1709         struct reparse_data rpdata;
1710         size_t orig_subst_name_nchars;
1711         const wchar_t *relpath;
1712         size_t relpath_nchars;
1713         size_t target_ntpath_nchars;
1714         size_t fixed_subst_name_nchars;
1715         const wchar_t *fixed_print_name;
1716         size_t fixed_print_name_nchars;
1717
1718         if (parse_reparse_data(rpbuf, *rpbuflen_p, &rpdata)) {
1719                 /* Do nothing if the reparse data is invalid.  */
1720                 return;
1721         }
1722
1723         if (rpdata.rptag == WIM_IO_REPARSE_TAG_SYMLINK &&
1724             (rpdata.rpflags & SYMBOLIC_LINK_RELATIVE))
1725         {
1726                 /* Do nothing if it's a relative symbolic link.  */
1727                 return;
1728         }
1729
1730         /* Build the new substitute name from the NT namespace path to the
1731          * target directory, then a path separator, then the "device relative"
1732          * part of the old substitute name.  */
1733
1734         orig_subst_name_nchars = rpdata.substitute_name_nbytes / sizeof(wchar_t);
1735
1736         relpath = get_device_relative_path(rpdata.substitute_name,
1737                                            orig_subst_name_nchars);
1738         relpath_nchars = orig_subst_name_nchars -
1739                          (relpath - rpdata.substitute_name);
1740
1741         target_ntpath_nchars = ctx->target_ntpath.Length / sizeof(wchar_t);
1742
1743         fixed_subst_name_nchars = target_ntpath_nchars;
1744         if (relpath_nchars)
1745                 fixed_subst_name_nchars += 1 + relpath_nchars;
1746         wchar_t fixed_subst_name[fixed_subst_name_nchars];
1747
1748         wmemcpy(fixed_subst_name, ctx->target_ntpath.Buffer,
1749                 target_ntpath_nchars);
1750         if (relpath_nchars) {
1751                 fixed_subst_name[target_ntpath_nchars] = L'\\';
1752                 wmemcpy(&fixed_subst_name[target_ntpath_nchars + 1],
1753                         relpath, relpath_nchars);
1754         }
1755         /* Doesn't need to be null-terminated.  */
1756
1757         /* Print name should be Win32, but not all NT names can even be
1758          * translated to Win32 names.  But we can at least delete the top-level
1759          * directory, such as \??\, and this will have the expected result in
1760          * the usual case.  */
1761         fixed_print_name = skip_nt_toplevel_component(fixed_subst_name,
1762                                                       fixed_subst_name_nchars);
1763         fixed_print_name_nchars = fixed_subst_name_nchars - (fixed_print_name -
1764                                                              fixed_subst_name);
1765
1766         rpdata.substitute_name = fixed_subst_name;
1767         rpdata.substitute_name_nbytes = fixed_subst_name_nchars * sizeof(wchar_t);
1768         rpdata.print_name = (wchar_t *)fixed_print_name;
1769         rpdata.print_name_nbytes = fixed_print_name_nchars * sizeof(wchar_t);
1770         make_reparse_buffer(&rpdata, rpbuf, rpbuflen_p);
1771 }
1772
1773 /* Sets reparse data on the specified file.  This handles "fixing" the targets
1774  * of absolute symbolic links and junctions if WIMLIB_EXTRACT_FLAG_RPFIX was
1775  * specified.  */
1776 static int
1777 set_reparse_data(const struct wim_dentry *dentry,
1778                  const void *_rpbuf, u16 rpbuflen, struct win32_apply_ctx *ctx)
1779 {
1780         const struct wim_inode *inode = dentry->d_inode;
1781         const void *rpbuf = _rpbuf;
1782
1783         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX)
1784             && !inode->i_not_rpfixed
1785             && (inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
1786                 inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT))
1787         {
1788                 memcpy(&ctx->rpfixbuf, _rpbuf, rpbuflen);
1789                 try_rpfix((u8 *)&ctx->rpfixbuf, &rpbuflen, ctx);
1790                 rpbuf = &ctx->rpfixbuf;
1791         }
1792         return do_set_reparse_data(dentry, rpbuf, rpbuflen, ctx);
1793
1794 }
1795
1796 /* Import the next block of raw encrypted data  */
1797 static DWORD WINAPI
1798 import_encrypted_data(PBYTE pbData, PVOID pvCallbackContext, PULONG Length)
1799 {
1800         struct win32_apply_ctx *ctx = pvCallbackContext;
1801         ULONG copy_len;
1802
1803         copy_len = min(ctx->encrypted_size - ctx->encrypted_offset, *Length);
1804         memcpy(pbData, &ctx->data_buffer[ctx->encrypted_offset], copy_len);
1805         ctx->encrypted_offset += copy_len;
1806         *Length = copy_len;
1807         return ERROR_SUCCESS;
1808 }
1809
1810 /* Write the raw encrypted data to the already-created file corresponding to
1811  * @dentry.
1812  *
1813  * The raw encrypted data is provided in ctx->data_buffer, and its size is
1814  * ctx->encrypted_size.  */
1815 static int
1816 extract_encrypted_file(const struct wim_dentry *dentry,
1817                        struct win32_apply_ctx *ctx)
1818 {
1819         void *rawctx;
1820         DWORD err;
1821
1822         /* Temporarily build a Win32 path for OpenEncryptedFileRaw()  */
1823         build_win32_extraction_path(dentry, ctx);
1824
1825         err = OpenEncryptedFileRaw(ctx->pathbuf.Buffer,
1826                                    CREATE_FOR_IMPORT, &rawctx);
1827
1828         /* Restore the NT namespace path  */
1829         build_extraction_path(dentry, ctx);
1830
1831         if (err != ERROR_SUCCESS) {
1832                 set_errno_from_win32_error(err);
1833                 ERROR_WITH_ERRNO("Can't open \"%ls\" for encrypted import "
1834                                  "(err=%"PRIu32")", current_path(ctx), (u32)err);
1835                 return WIMLIB_ERR_OPEN;
1836         }
1837
1838         ctx->encrypted_offset = 0;
1839
1840         err = WriteEncryptedFileRaw(import_encrypted_data, ctx, rawctx);
1841
1842         CloseEncryptedFileRaw(rawctx);
1843
1844         if (err != ERROR_SUCCESS) {
1845                 set_errno_from_win32_error(err);
1846                 ERROR_WITH_ERRNO("Can't import encrypted file \"%ls\" "
1847                                  "(err=%"PRIu32")", current_path(ctx), (u32)err);
1848                 return WIMLIB_ERR_WRITE;
1849         }
1850
1851         return 0;
1852 }
1853
1854 /* Called when starting to read a stream for extraction on Windows  */
1855 static int
1856 begin_extract_stream(struct wim_lookup_table_entry *stream, void *_ctx)
1857 {
1858         struct win32_apply_ctx *ctx = _ctx;
1859         const struct stream_owner *owners = stream_owners(stream);
1860         int ret;
1861
1862         ctx->num_open_handles = 0;
1863         ctx->data_buffer_ptr = NULL;
1864         INIT_LIST_HEAD(&ctx->reparse_dentries);
1865         INIT_LIST_HEAD(&ctx->encrypted_dentries);
1866
1867         for (u32 i = 0; i < stream->out_refcnt; i++) {
1868                 const struct wim_inode *inode = owners[i].inode;
1869                 const wchar_t *stream_name = owners[i].stream_name;
1870                 struct wim_dentry *dentry;
1871
1872                 /* A copy of the stream needs to be extracted to @inode.  */
1873
1874                 if (ctx->common.supported_features.hard_links) {
1875                         dentry = inode_first_extraction_dentry(inode);
1876                         ret = begin_extract_stream_instance(stream, dentry,
1877                                                             stream_name, ctx);
1878                         if (ret)
1879                                 goto fail;
1880                 } else {
1881                         /* Hard links not supported.  Extract the stream
1882                          * separately to each alias of the inode.  */
1883                         struct list_head *next;
1884
1885                         next = inode->i_extraction_aliases.next;
1886                         do {
1887                                 dentry = list_entry(next, struct wim_dentry,
1888                                                     d_extraction_alias_node);
1889                                 ret = begin_extract_stream_instance(stream,
1890                                                                     dentry,
1891                                                                     stream_name,
1892                                                                     ctx);
1893                                 if (ret)
1894                                         goto fail;
1895                                 next = next->next;
1896                         } while (next != &inode->i_extraction_aliases);
1897                 }
1898         }
1899
1900         return 0;
1901
1902 fail:
1903         close_handles(ctx);
1904         return ret;
1905 }
1906
1907 /* Called when the next chunk of a stream has been read for extraction on
1908  * Windows  */
1909 static int
1910 extract_chunk(const void *chunk, size_t size, void *_ctx)
1911 {
1912         struct win32_apply_ctx *ctx = _ctx;
1913
1914         /* Write the data chunk to each open handle  */
1915         for (unsigned i = 0; i < ctx->num_open_handles; i++) {
1916                 u8 *bufptr = (u8 *)chunk;
1917                 size_t bytes_remaining = size;
1918                 NTSTATUS status;
1919                 while (bytes_remaining) {
1920                         ULONG count = min(0xFFFFFFFF, bytes_remaining);
1921
1922                         status = (*func_NtWriteFile)(ctx->open_handles[i],
1923                                                      NULL, NULL, NULL,
1924                                                      &ctx->iosb, bufptr, count,
1925                                                      NULL, NULL);
1926                         if (!NT_SUCCESS(status)) {
1927                                 set_errno_from_nt_status(status);
1928                                 ERROR_WITH_ERRNO("Error writing data to target "
1929                                                  "volume (status=0x%08"PRIx32")",
1930                                                  (u32)status);
1931                                 return WIMLIB_ERR_WRITE;
1932                         }
1933                         bufptr += ctx->iosb.Information;
1934                         bytes_remaining -= ctx->iosb.Information;
1935                 }
1936         }
1937
1938         /* Copy the data chunk into the buffer (if needed)  */
1939         if (ctx->data_buffer_ptr)
1940                 ctx->data_buffer_ptr = mempcpy(ctx->data_buffer_ptr,
1941                                                chunk, size);
1942         return 0;
1943 }
1944
1945 /* Called when a stream has been fully read for extraction on Windows  */
1946 static int
1947 end_extract_stream(struct wim_lookup_table_entry *stream, int status, void *_ctx)
1948 {
1949         struct win32_apply_ctx *ctx = _ctx;
1950         int ret;
1951         const struct wim_dentry *dentry;
1952
1953         close_handles(ctx);
1954
1955         if (status)
1956                 return status;
1957
1958         if (likely(!ctx->data_buffer_ptr))
1959                 return 0;
1960
1961         if (!list_empty(&ctx->reparse_dentries)) {
1962                 if (stream->size > REPARSE_DATA_MAX_SIZE) {
1963                         dentry = list_first_entry(&ctx->reparse_dentries,
1964                                                   struct wim_dentry, tmp_list);
1965                         build_extraction_path(dentry, ctx);
1966                         ERROR("Reparse data of \"%ls\" has size "
1967                               "%"PRIu64" bytes (exceeds %u bytes)",
1968                               current_path(ctx), stream->size,
1969                               REPARSE_DATA_MAX_SIZE);
1970                         return WIMLIB_ERR_INVALID_REPARSE_DATA;
1971                 }
1972                 /* In the WIM format, reparse streams are just the reparse data
1973                  * and omit the header.  But we can reconstruct the header.  */
1974                 memcpy(ctx->rpbuf.rpdata, ctx->data_buffer, stream->size);
1975                 ctx->rpbuf.rpdatalen = stream->size;
1976                 ctx->rpbuf.rpreserved = 0;
1977                 list_for_each_entry(dentry, &ctx->reparse_dentries, tmp_list) {
1978                         ctx->rpbuf.rptag = dentry->d_inode->i_reparse_tag;
1979                         ret = set_reparse_data(dentry, &ctx->rpbuf,
1980                                                stream->size + REPARSE_DATA_OFFSET,
1981                                                ctx);
1982                         if (ret)
1983                                 return ret;
1984                 }
1985         }
1986
1987         if (!list_empty(&ctx->encrypted_dentries)) {
1988                 ctx->encrypted_size = stream->size;
1989                 list_for_each_entry(dentry, &ctx->encrypted_dentries, tmp_list) {
1990                         ret = extract_encrypted_file(dentry, ctx);
1991                         if (ret)
1992                                 return ret;
1993                 }
1994         }
1995
1996         return 0;
1997 }
1998
1999 /* Attributes that can't be set directly  */
2000 #define SPECIAL_ATTRIBUTES                      \
2001         (FILE_ATTRIBUTE_REPARSE_POINT   |       \
2002          FILE_ATTRIBUTE_DIRECTORY       |       \
2003          FILE_ATTRIBUTE_ENCRYPTED       |       \
2004          FILE_ATTRIBUTE_SPARSE_FILE     |       \
2005          FILE_ATTRIBUTE_COMPRESSED)
2006
2007 /* Set the security descriptor @desc, of @desc_size bytes, on the file with open
2008  * handle @h.  */
2009 static NTSTATUS
2010 set_security_descriptor(HANDLE h, const void *desc,
2011                         size_t desc_size, struct win32_apply_ctx *ctx)
2012 {
2013         SECURITY_INFORMATION info;
2014         NTSTATUS status;
2015
2016         /* We really just want to set entire the security descriptor as-is, but
2017          * all available APIs require specifying the specific parts of the
2018          * descriptor being set.  Start out by requesting all parts be set.  If
2019          * permissions problems are encountered, fall back to omitting some
2020          * parts (first the SACL, then the DACL, then the owner), unless the
2021          * WIMLIB_EXTRACT_FLAG_STRICT_ACLS flag has been enabled.  */
2022         info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
2023                DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
2024
2025         /* Prefer NtSetSecurityObject() to SetFileSecurity().  SetFileSecurity()
2026          * itself necessarily uses NtSetSecurityObject() as the latter is the
2027          * underlying system call for setting security information, but
2028          * SetFileSecurity() opens the handle with NtCreateFile() without
2029          * FILE_OPEN_FILE_BACKUP_INTENT.  Hence, access checks are done and due
2030          * to the Windows security model, even a process running as the
2031          * Administrator can have access denied.  (Of course, this not mentioned
2032          * in the MS "documentation".)  */
2033 retry:
2034         status = (*func_NtSetSecurityObject)(h, info, (PSECURITY_DESCRIPTOR)desc);
2035         if (NT_SUCCESS(status))
2036                 return status;
2037         /* Failed to set the requested parts of the security descriptor.  If the
2038          * error was permissions-related, try to set fewer parts of the security
2039          * descriptor, unless WIMLIB_EXTRACT_FLAG_STRICT_ACLS is enabled.  */
2040         if ((status == STATUS_PRIVILEGE_NOT_HELD ||
2041              status == STATUS_ACCESS_DENIED) &&
2042             !(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
2043         {
2044                 if (info & SACL_SECURITY_INFORMATION) {
2045                         info &= ~SACL_SECURITY_INFORMATION;
2046                         ctx->partial_security_descriptors++;
2047                         goto retry;
2048                 }
2049                 if (info & DACL_SECURITY_INFORMATION) {
2050                         info &= ~DACL_SECURITY_INFORMATION;
2051                         goto retry;
2052                 }
2053                 if (info & OWNER_SECURITY_INFORMATION) {
2054                         info &= ~OWNER_SECURITY_INFORMATION;
2055                         goto retry;
2056                 }
2057                 /* Nothing left except GROUP, and if we removed it we
2058                  * wouldn't have anything at all.  */
2059         }
2060
2061         /* No part of the security descriptor could be set, or
2062          * WIMLIB_EXTRACT_FLAG_STRICT_ACLS is enabled and the full security
2063          * descriptor could not be set.  */
2064         if (!(info & SACL_SECURITY_INFORMATION))
2065                 ctx->partial_security_descriptors--;
2066         ctx->no_security_descriptors++;
2067         return status;
2068 }
2069
2070 /* Set metadata on the open file @h from the WIM inode @inode.  */
2071 static int
2072 do_apply_metadata_to_file(HANDLE h, const struct wim_inode *inode,
2073                           struct win32_apply_ctx *ctx)
2074 {
2075         FILE_BASIC_INFORMATION info;
2076         NTSTATUS status;
2077
2078         /* Set security descriptor if present and not in NO_ACLS mode  */
2079         if (inode->i_security_id >= 0 &&
2080             !(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS))
2081         {
2082                 const struct wim_security_data *sd;
2083                 const void *desc;
2084                 size_t desc_size;
2085
2086                 sd = wim_get_current_security_data(ctx->common.wim);
2087                 desc = sd->descriptors[inode->i_security_id];
2088                 desc_size = sd->sizes[inode->i_security_id];
2089
2090                 status = set_security_descriptor(h, desc, desc_size, ctx);
2091                 if (!NT_SUCCESS(status) &&
2092                     (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
2093                 {
2094                         set_errno_from_nt_status(status);
2095                         ERROR_WITH_ERRNO("Can't set security descriptor "
2096                                          "on \"%ls\" (status=0x%08"PRIx32")",
2097                                          current_path(ctx), (u32)status);
2098                         return WIMLIB_ERR_SET_SECURITY;
2099                 }
2100         }
2101
2102         /* Set attributes and timestamps  */
2103         info.CreationTime.QuadPart = inode->i_creation_time;
2104         info.LastAccessTime.QuadPart = inode->i_last_access_time;
2105         info.LastWriteTime.QuadPart = inode->i_last_write_time;
2106         info.ChangeTime.QuadPart = 0;
2107         if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)
2108                 info.FileAttributes = 0;
2109         else
2110                 info.FileAttributes = inode->i_attributes & ~SPECIAL_ATTRIBUTES;
2111
2112         status = (*func_NtSetInformationFile)(h, &ctx->iosb,
2113                                               &info, sizeof(info),
2114                                               FileBasicInformation);
2115         /* On FAT volumes we get STATUS_INVALID_PARAMETER if we try to set
2116          * attributes on the root directory.  (Apparently because FAT doesn't
2117          * actually have a place to store those attributes!)  */
2118         if (!NT_SUCCESS(status)
2119             && !(status == STATUS_INVALID_PARAMETER &&
2120                  dentry_is_root(inode_first_extraction_dentry(inode))))
2121         {
2122                 set_errno_from_nt_status(status);
2123                 ERROR_WITH_ERRNO("Can't set basic metadata on \"%ls\" "
2124                                  "(status=0x%08"PRIx32")",
2125                                  current_path(ctx), (u32)status);
2126                 return WIMLIB_ERR_SET_ATTRIBUTES;
2127         }
2128
2129         return 0;
2130 }
2131
2132 static int
2133 apply_metadata_to_file(const struct wim_dentry *dentry,
2134                        struct win32_apply_ctx *ctx)
2135 {
2136         const struct wim_inode *inode = dentry->d_inode;
2137         DWORD perms;
2138         HANDLE h;
2139         NTSTATUS status;
2140         int ret;
2141
2142         perms = FILE_WRITE_ATTRIBUTES | WRITE_DAC |
2143                 WRITE_OWNER | ACCESS_SYSTEM_SECURITY;
2144
2145         build_extraction_path(dentry, ctx);
2146
2147         /* Open a handle with as many relevant permissions as possible.  */
2148         while (!NT_SUCCESS(status = do_create_file(&h, perms, NULL,
2149                                                    0, FILE_OPEN, 0, ctx)))
2150         {
2151                 if (status == STATUS_PRIVILEGE_NOT_HELD ||
2152                     status == STATUS_ACCESS_DENIED)
2153                 {
2154                         if (perms & ACCESS_SYSTEM_SECURITY) {
2155                                 perms &= ~ACCESS_SYSTEM_SECURITY;
2156                                 continue;
2157                         }
2158                         if (perms & WRITE_DAC) {
2159                                 perms &= ~WRITE_DAC;
2160                                 continue;
2161                         }
2162                         if (perms & WRITE_OWNER) {
2163                                 perms &= ~WRITE_OWNER;
2164                                 continue;
2165                         }
2166                 }
2167                 set_errno_from_nt_status(status);
2168                 ERROR_WITH_ERRNO("Can't open \"%ls\" to set metadata "
2169                                  "(status=0x%08"PRIx32")",
2170                                  current_path(ctx), (u32)status);
2171                 return WIMLIB_ERR_OPEN;
2172         }
2173
2174         ret = do_apply_metadata_to_file(h, inode, ctx);
2175
2176         (*func_NtClose)(h);
2177
2178         return ret;
2179 }
2180
2181 static int
2182 apply_metadata(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
2183 {
2184         const struct wim_dentry *dentry;
2185         int ret;
2186
2187         /* We go in reverse so that metadata is set on all a directory's
2188          * children before the directory itself.  This avoids any potential
2189          * problems with attributes, timestamps, or security descriptors.  */
2190         list_for_each_entry_reverse(dentry, dentry_list, d_extraction_list_node)
2191         {
2192                 ret = apply_metadata_to_file(dentry, ctx);
2193                 if (ret)
2194                         return ret;
2195                 ret = report_file_metadata_applied(&ctx->common);
2196                 if (ret)
2197                         return ret;
2198         }
2199         return 0;
2200 }
2201
2202 /* Issue warnings about problems during the extraction for which warnings were
2203  * not already issued (due to the high number of potential warnings if we issued
2204  * them per-file).  */
2205 static void
2206 do_warnings(const struct win32_apply_ctx *ctx)
2207 {
2208         if (ctx->partial_security_descriptors == 0 &&
2209             ctx->no_security_descriptors == 0 &&
2210             ctx->num_short_name_failures == 0)
2211                 return;
2212
2213         WARNING("Extraction to \"%ls\" complete, but with one or more warnings:",
2214                 ctx->common.target);
2215         if (ctx->num_short_name_failures) {
2216                 WARNING("- Could not set short names on %lu files or directories",
2217                         ctx->num_short_name_failures);
2218         }
2219         if (ctx->partial_security_descriptors) {
2220                 WARNING("- Could only partially set the security descriptor\n"
2221                         "            on %lu files or directories.",
2222                         ctx->partial_security_descriptors);
2223         }
2224         if (ctx->no_security_descriptors) {
2225                 WARNING("- Could not set security descriptor at all\n"
2226                         "            on %lu files or directories.",
2227                         ctx->no_security_descriptors);
2228         }
2229         if (ctx->partial_security_descriptors || ctx->no_security_descriptors) {
2230                 WARNING("To fully restore all security descriptors, run the program\n"
2231                         "          with Administrator rights.");
2232         }
2233 }
2234
2235 static uint64_t
2236 count_dentries(const struct list_head *dentry_list)
2237 {
2238         const struct list_head *cur;
2239         uint64_t count = 0;
2240
2241         list_for_each(cur, dentry_list)
2242                 count++;
2243
2244         return count;
2245 }
2246
2247 /* Extract files from a WIM image to a directory on Windows  */
2248 static int
2249 win32_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
2250 {
2251         int ret;
2252         struct win32_apply_ctx *ctx = (struct win32_apply_ctx *)_ctx;
2253         uint64_t dentry_count;
2254
2255         ret = prepare_target(dentry_list, ctx);
2256         if (ret)
2257                 goto out;
2258
2259         if (unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT)) {
2260                 ret = start_wimboot_extraction(ctx);
2261                 if (ret)
2262                         goto out;
2263         }
2264
2265         dentry_count = count_dentries(dentry_list);
2266
2267         ret = start_file_structure_phase(&ctx->common, dentry_count);
2268         if (ret)
2269                 goto out;
2270
2271         ret = create_directories(dentry_list, ctx);
2272         if (ret)
2273                 goto out;
2274
2275         ret = create_nondirectories(dentry_list, ctx);
2276         if (ret)
2277                 goto out;
2278
2279         ret = end_file_structure_phase(&ctx->common);
2280         if (ret)
2281                 goto out;
2282
2283         struct read_stream_list_callbacks cbs = {
2284                 .begin_stream      = begin_extract_stream,
2285                 .begin_stream_ctx  = ctx,
2286                 .consume_chunk     = extract_chunk,
2287                 .consume_chunk_ctx = ctx,
2288                 .end_stream        = end_extract_stream,
2289                 .end_stream_ctx    = ctx,
2290         };
2291         ret = extract_stream_list(&ctx->common, &cbs);
2292         if (ret)
2293                 goto out;
2294
2295         ret = start_file_metadata_phase(&ctx->common, dentry_count);
2296         if (ret)
2297                 goto out;
2298
2299         ret = apply_metadata(dentry_list, ctx);
2300         if (ret)
2301                 goto out;
2302
2303         ret = end_file_metadata_phase(&ctx->common);
2304         if (ret)
2305                 goto out;
2306
2307         if (unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT)) {
2308                 ret = end_wimboot_extraction(ctx);
2309                 if (ret)
2310                         goto out;
2311         }
2312
2313         do_warnings(ctx);
2314 out:
2315         if (ctx->h_target)
2316                 (*func_NtClose)(ctx->h_target);
2317         if (ctx->target_ntpath.Buffer)
2318                 HeapFree(GetProcessHeap(), 0, ctx->target_ntpath.Buffer);
2319         FREE(ctx->pathbuf.Buffer);
2320         FREE(ctx->print_buffer);
2321         if (ctx->wimboot.prepopulate_pats) {
2322                 FREE(ctx->wimboot.prepopulate_pats->strings);
2323                 FREE(ctx->wimboot.prepopulate_pats);
2324         }
2325         FREE(ctx->wimboot.mem_prepopulate_pats);
2326         FREE(ctx->data_buffer);
2327         return ret;
2328 }
2329
2330 const struct apply_operations win32_apply_ops = {
2331         .name                   = "Windows",
2332         .get_supported_features = win32_get_supported_features,
2333         .extract                = win32_extract,
2334         .will_externally_back   = win32_will_externally_back,
2335         .context_size           = sizeof(struct win32_apply_ctx),
2336 };
2337
2338 #endif /* __WIN32__ */