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