From 965c28d0cce2e43df3c38b47c78204b1c33c313d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 17 Aug 2014 16:58:18 -0500 Subject: [PATCH] win32_apply.c: Use volume handle when enabling short names Otherwise it doesn't work. --- include/wimlib/win32_common.h | 3 +++ src/wimboot.c | 20 ---------------- src/win32_apply.c | 43 +++++++++++++++++++++++++---------- src/win32_common.c | 21 +++++++++++++++++ 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/include/wimlib/win32_common.h b/include/wimlib/win32_common.h index 7cd991ed..e5317b61 100644 --- a/include/wimlib/win32_common.h +++ b/include/wimlib/win32_common.h @@ -157,4 +157,7 @@ typedef struct _FILE_FS_PERSISTENT_VOLUME_INFORMATION { extern int win32_path_to_nt_path(const wchar_t *win32_path, UNICODE_STRING *nt_path); +extern int +win32_get_drive_path(const wchar_t *file_path, wchar_t drive_path[7]); + #endif /* _WIMLIB_WIN32_COMMON_H */ diff --git a/src/wimboot.c b/src/wimboot.c index 35fe13a9..514ff8c5 100644 --- a/src/wimboot.c +++ b/src/wimboot.c @@ -831,26 +831,6 @@ out: return ret; } -static int -win32_get_drive_path(const wchar_t *file_path, wchar_t drive_path[7]) -{ - tchar *file_abspath; - - file_abspath = realpath(file_path, NULL); - if (!file_abspath) - return WIMLIB_ERR_NOMEM; - - if (file_abspath[0] == L'\0' || file_abspath[1] != L':') { - ERROR("\"%ls\": Path format not recognized", file_abspath); - FREE(file_abspath); - return WIMLIB_ERR_UNSUPPORTED; - } - - wsprintf(drive_path, L"\\\\.\\%lc:", file_abspath[0]); - FREE(file_abspath); - return 0; -} - /* Try to attach an instance of the Windows Overlay File System Filter Driver to * the specified drive (such as C:) */ static bool diff --git a/src/win32_apply.c b/src/win32_apply.c index 89ecd21c..1f68b69f 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -799,27 +799,38 @@ maybe_clear_encryption_attribute(HANDLE *h_ptr, const struct wim_dentry *dentry, /* Try to enable short name support on the target volume. If successful, return * true. If unsuccessful, issue a warning and return false. */ static bool -try_to_enable_short_names(struct win32_apply_ctx *ctx) +try_to_enable_short_names(const wchar_t *volume) { + HANDLE h; FILE_FS_PERSISTENT_VOLUME_INFORMATION info; - NTSTATUS status; + BOOL bret; + DWORD bytesReturned; + + h = CreateFile(volume, GENERIC_WRITE, + FILE_SHARE_VALID_FLAGS, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (h == INVALID_HANDLE_VALUE) + goto fail; info.VolumeFlags = 0; info.FlagMask = PERSISTENT_VOLUME_STATE_SHORT_NAME_CREATION_DISABLED; info.Version = 1; info.Reserved = 0; - status = (*func_NtFsControlFile)(ctx->h_target, NULL, NULL, NULL, - &ctx->iosb, - FSCTL_SET_PERSISTENT_VOLUME_STATE, - &info, sizeof(info), NULL, 0); - if (!NT_SUCCESS(status)) { - WARNING("Failed to enable short name support on target volume " - "(status=0x%08"PRIx32")", (u32)status); - return false; - } + bret = DeviceIoControl(h, FSCTL_SET_PERSISTENT_VOLUME_STATE, + &info, sizeof(info), NULL, 0, + &bytesReturned, NULL); + CloseHandle(h); + + if (!bret) + goto fail; return true; + +fail: + WARNING("Failed to enable short name support on %ls " + "(err=%"PRIu32")", volume + 4, (u32)GetLastError()); + return false; } /* Set the short name on the open file @h which has been created at the location @@ -860,8 +871,16 @@ retry: if (dentry->short_name_nbytes == 0) return 0; if (!ctx->tried_to_enable_short_names) { + wchar_t volume[7]; + int ret; + ctx->tried_to_enable_short_names = true; - if (try_to_enable_short_names(ctx)) + + ret = win32_get_drive_path(ctx->common.target, + volume); + if (ret) + return ret; + if (try_to_enable_short_names(volume)) goto retry; } } diff --git a/src/win32_common.c b/src/win32_common.c index 48e21468..d380e828 100644 --- a/src/win32_common.c +++ b/src/win32_common.c @@ -645,4 +645,25 @@ win32_path_to_nt_path(const wchar_t *win32_path, UNICODE_STRING *nt_path) return WIMLIB_ERR_INVALID_PARAM; } +int +win32_get_drive_path(const wchar_t *file_path, wchar_t drive_path[7]) +{ + tchar *file_abspath; + + file_abspath = realpath(file_path, NULL); + if (!file_abspath) + return WIMLIB_ERR_NOMEM; + + if (file_abspath[0] == L'\0' || file_abspath[1] != L':') { + ERROR("\"%ls\": Path format not recognized", file_abspath); + FREE(file_abspath); + return WIMLIB_ERR_UNSUPPORTED; + } + + wsprintf(drive_path, L"\\\\.\\%lc:", file_abspath[0]); + FREE(file_abspath); + return 0; +} + + #endif /* __WIN32__ */ -- 2.43.0