+/* Pre-create directories; extract encrypted streams */
+static int
+win32_begin_extract_unnamed_stream(const struct wim_inode *inode,
+ const struct wim_lookup_table_entry *lte,
+ const wchar_t *path,
+ DWORD *creationDisposition_ret,
+ unsigned int vol_flags)
+{
+ DWORD err;
+ int ret;
+
+ /* Directories must be created with CreateDirectoryW(). Then the call
+ * to CreateFileW() will merely open the directory that was already
+ * created rather than creating a new file. */
+ if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) {
+ if (!CreateDirectoryW(path, NULL)) {
+ err = GetLastError();
+ switch (err) {
+ case ERROR_ALREADY_EXISTS:
+ break;
+ case ERROR_ACCESS_DENIED:
+ if (path_is_root_of_drive(path))
+ break;
+ /* Fall through */
+ default:
+ ERROR("Failed to create directory \"%ls\"",
+ path);
+ win32_error(err);
+ return WIMLIB_ERR_MKDIR;
+ }
+ }
+ DEBUG("Created directory \"%ls\"", path);
+ *creationDisposition_ret = OPEN_EXISTING;
+ }
+ if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED &&
+ vol_flags & FILE_SUPPORTS_ENCRYPTION)
+ {
+ if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) {
+ if (!EncryptFile(path)) {
+ err = GetLastError();
+ ERROR("Failed to encrypt directory \"%ls\"",
+ path);
+ win32_error(err);
+ return WIMLIB_ERR_WRITE;
+ }
+ } else {
+ ret = do_win32_extract_encrypted_stream(path, lte);
+ if (ret)
+ return ret;
+ DEBUG("Extracted encrypted file \"%ls\"", path);
+ }
+ *creationDisposition_ret = OPEN_EXISTING;
+ }
+
+ /* Set file attributes if we created the file. Otherwise, we haven't
+ * created the file set and we will set the attributes in the call to
+ * CreateFileW().
+ *
+ * The FAT filesystem does not let you change the attributes of the root
+ * directory, so treat that as a special case and do not set attributes.
+ * */
+ if (*creationDisposition_ret == OPEN_EXISTING &&
+ !path_is_root_of_drive(path))
+ {
+ if (!SetFileAttributesW(path,
+ win32_mask_attributes(inode->i_attributes)))
+ {
+ err = GetLastError();
+ ERROR("Failed to set attributes on \"%ls\"", path);
+ win32_error(err);
+ return WIMLIB_ERR_WRITE;
+ }
+ }
+ return 0;
+}
+
+/* Set security descriptor and extract stream data or reparse data (skip the
+ * unnamed data stream of encrypted files, which was already extracted). */
+static int
+win32_finish_extract_stream(HANDLE h, const struct wim_inode *inode,
+ const struct wim_lookup_table_entry *lte,
+ const wchar_t *stream_path,
+ const wchar_t *stream_name_utf16,
+ struct apply_args *args)
+{
+ int ret = 0;
+ if (stream_name_utf16 == NULL) {
+ /* Unnamed stream. */
+
+ /* Set security descriptor, unless the extract_flags indicate
+ * not to or the volume does not supported it. Note that this
+ * is only done when the unnamed stream is being extracted, as
+ * security descriptors are per-file and not per-stream. */
+ if (inode->i_security_id >= 0 &&
+ !(args->extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS)
+ && (args->vol_flags & FILE_PERSISTENT_ACLS))
+ {
+ ret = win32_set_security_data(inode, h, stream_path, args);