+static int
+do_win32_extract_encrypted_stream(const wchar_t *path,
+ const struct wim_lookup_table_entry *lte)
+{
+ ERROR("Extrat encryted streams not implemented");
+ return WIMLIB_ERR_INVALID_PARAM;
+}
+
+static bool
+path_is_root_of_drive(const wchar_t *path)
+{
+ if (!*path)
+ return false;
+
+ if (*path != L'/' && *path != L'\\') {
+ if (*(path + 1) == L':')
+ path += 2;
+ else
+ return false;
+ }
+ while (*path == L'/' || *path == L'\\')
+ path++;
+ return (*path == L'\0');
+}
+
+static DWORD
+win32_get_create_flags_and_attributes(DWORD i_attributes)
+{
+ DWORD attributes;
+
+ /*
+ * Some attributes cannot be set by passing them to CreateFile(). In
+ * particular:
+ *
+ * FILE_ATTRIBUTE_DIRECTORY:
+ * CreateDirectory() must be called instead of CreateFile().
+ *
+ * FILE_ATTRIBUTE_SPARSE_FILE:
+ * Needs an ioctl.
+ * See: win32_set_sparse().
+ *
+ * FILE_ATTRIBUTE_COMPRESSED:
+ * Not clear from the documentation, but apparently this needs an
+ * ioctl as well.
+ * See: win32_set_compressed().
+ *
+ * FILE_ATTRIBUTE_REPARSE_POINT:
+ * Needs an ioctl, with the reparse data specified.
+ * See: win32_set_reparse_data().
+ *
+ * In addition, clear any file flags in the attributes that we don't
+ * want, but also specify FILE_FLAG_OPEN_REPARSE_POINT and
+ * FILE_FLAG_BACKUP_SEMANTICS as we are a backup application.
+ */
+ attributes = i_attributes & ~(FILE_ATTRIBUTE_SPARSE_FILE |
+ FILE_ATTRIBUTE_COMPRESSED |
+ FILE_ATTRIBUTE_REPARSE_POINT |
+ FILE_ATTRIBUTE_DIRECTORY |
+ FILE_FLAG_DELETE_ON_CLOSE |
+ FILE_FLAG_NO_BUFFERING |
+ FILE_FLAG_OPEN_NO_RECALL |
+ FILE_FLAG_OVERLAPPED |
+ FILE_FLAG_RANDOM_ACCESS |
+ /*FILE_FLAG_SESSION_AWARE |*/
+ FILE_FLAG_SEQUENTIAL_SCAN |
+ FILE_FLAG_WRITE_THROUGH);
+ return attributes |
+ FILE_FLAG_OPEN_REPARSE_POINT |
+ FILE_FLAG_BACKUP_SEMANTICS;
+}
+
+static bool
+inode_has_special_attributes(const struct wim_inode *inode)
+{
+ return (inode->i_attributes & (FILE_ATTRIBUTE_COMPRESSED |
+ FILE_ATTRIBUTE_REPARSE_POINT |
+ FILE_ATTRIBUTE_SPARSE_FILE)) != 0;
+}
+
+/* Set compression or sparse attributes, and reparse data, if supported by the
+ * volume. */
+static int
+win32_set_special_attributes(HANDLE hFile, const struct wim_inode *inode,
+ struct wim_lookup_table_entry *unnamed_stream_lte,
+ const wchar_t *path, unsigned vol_flags)
+{
+ int ret;
+
+ if (inode->i_attributes & FILE_ATTRIBUTE_COMPRESSED) {
+ if (vol_flags & FILE_FILE_COMPRESSION) {
+ DEBUG("Setting compression flag on \"%ls\"", path);
+ ret = win32_set_compressed(hFile, path);
+ if (ret)
+ return ret;
+ } else {
+ DEBUG("Cannot set compression attribute on \"%ls\": "
+ "volume does not support transparent compression",
+ path);
+ }
+ }
+
+ if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) {
+ if (vol_flags & FILE_SUPPORTS_SPARSE_FILES) {
+ DEBUG("Setting sparse flag on \"%ls\"", path);
+ ret = win32_set_sparse(hFile, path);
+ if (ret)
+ return ret;
+ } else {
+ DEBUG("Cannot set sparse attribute on \"%ls\": "
+ "volume does not support sparse files",
+ path);
+ }
+ }
+
+ if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+ if (vol_flags & FILE_SUPPORTS_REPARSE_POINTS) {
+ DEBUG("Setting reparse data on \"%ls\"", path);
+ ret = win32_set_reparse_data(hFile, inode->i_reparse_tag,
+ unnamed_stream_lte, path);
+ if (ret)
+ return ret;
+ } else {
+ DEBUG("Cannot set reparse data on \"%ls\": volume "
+ "does not support reparse points", path);
+ }
+ }
+
+ return 0;
+}
+