From eabff1b67733ea6d4fce35512e2f0a896497d582 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 14 Aug 2016 08:56:58 -0700 Subject: [PATCH] win32_apply.c: detect case-sensitive filename support --- NEWS | 4 ++++ doc/man1/wimlib-imagex-apply.1 | 17 +++++++++++------ doc/man1/wimlib-imagex-capture.1 | 5 +++-- include/wimlib/win32_common.h | 7 +++++++ src/win32_apply.c | 24 ++++++++++++++++++++++-- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 2d21c49e..88522aac 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,10 @@ Version 1.10.0-BETA: been removed. Users are advised to upgrade to a later version of libntfs-3g. + On Windows, wimlib now supports case-sensitive filename extraction when + supported by the underlying operating system and filesystem (operating + system support requires a registry setting). + Version 1.9.2: On UNIX, wimlib can now overwrite readonly files when extracting. diff --git a/doc/man1/wimlib-imagex-apply.1 b/doc/man1/wimlib-imagex-apply.1 index a046ef7f..688d74f0 100644 --- a/doc/man1/wimlib-imagex-apply.1 +++ b/doc/man1/wimlib-imagex-apply.1 @@ -337,15 +337,20 @@ byte except '\\0' and \'/', so on a POSIX-compliant system this option will only have an effect in the unlikely case that the WIM image for some reason has a filename containing one of these characters. .IP "" -On Windows, filenames are case-insensitive, cannot include the characters '/', -\'\\0', '\\', ':', '*', '?', '"', '<', '>', or '|', and cannot end with a space -or period. Ordinarily, files in WIM images should meet these conditions as -well. However, it is not guaranteed, and in particular a WIM image captured with -\fBwimlib-imagex\fR on a POSIX-compliant system could contain such files. By -default, invalid names will be ignored, and if there are multiple names +On Windows, filenames are case-insensitive(*), cannot include the characters +'/', \'\\0', '\\', ':', '*', '?', '"', '<', '>', or '|', and cannot end with a +space or period. Ordinarily, files in WIM images should meet these conditions +as well. However, it is not guaranteed, and in particular a WIM image captured +with \fBwimlib-imagex\fR on a POSIX-compliant system could contain such files. +By default, invalid names will be ignored, and if there are multiple names differing only in case, one will be chosen to extract arbitrarily; however, with \fB--include-invalid-names\fR, all names will be sanitized and extracted in some form. +.IP "" +(*) Unless the ObCaseInsensitive setting has been set to 0 in the Windows +registry, in which case certain software, including the Windows version of +\fBwimlib-imagex\fR, will honor case-sensitive filenames on NTFS and other +compatible filesystems. .TP \fB--wimboot\fR Windows only: Instead of extracting the files themselves, extract "pointer diff --git a/doc/man1/wimlib-imagex-capture.1 b/doc/man1/wimlib-imagex-capture.1 index 226441c6..3b0db0ad 100644 --- a/doc/man1/wimlib-imagex-capture.1 +++ b/doc/man1/wimlib-imagex-capture.1 @@ -174,8 +174,9 @@ information, at least to the extent supported by the destination filesystem. Pedantic note: since Windows is not fully compatible with its own filesystem (NTFS), on Windows wimlib cannot archive certain files that may exist on a valid NTFS filesystem but are inaccessible to the Windows API, for example two files -with names differing only in case in the same directory, or a file whose name -contains certain characters considered invalid by Windows. If you run into +with names differing only in case in the same directory (unless +ObCaseInsensitive has been set to 0 in the Windows registry), or a file whose +name contains certain characters considered invalid by Windows. If you run into problems archiving such files consider using the \fBNTFS VOLUME CAPTURE (UNIX)\fR mode from Linux. .SH OPTIONS diff --git a/include/wimlib/win32_common.h b/include/wimlib/win32_common.h index df8b0cb7..cbdacd32 100644 --- a/include/wimlib/win32_common.h +++ b/include/wimlib/win32_common.h @@ -95,6 +95,13 @@ NtSetSecurityObject(IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor); +NTSTATUS +NTAPI +NtOpenSymbolicLinkObject(PHANDLE LinkHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes); + + /* Dynamically loaded ntdll functions */ extern NTSTATUS (WINAPI *func_RtlDosPathNameToNtPathName_U_WithStatus) diff --git a/src/win32_apply.c b/src/win32_apply.c index 33c1a5dd..a4f81751 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -308,8 +308,28 @@ win32_get_supported_features(const wchar_t *target, supported_features->timestamps = 1; - /* Note: Windows does not support case sensitive filenames! At least - * not without changing the registry and rebooting... */ + if (vol_flags & FILE_CASE_SENSITIVE_SEARCH) { + /* + * The filesystem supports case-sensitive filenames. But does + * the operating system as well? This normally requires the + * registry setting ObCaseInsensitive=0. We can test it + * indirectly by attempting to open the "\SystemRoot" symbolic + * link using a name with the wrong case. If we get + * STATUS_OBJECT_NAME_NOT_FOUND instead of STATUS_ACCESS_DENIED, + * then case-sensitive names must be enabled. + */ + UNICODE_STRING path; + OBJECT_ATTRIBUTES attr; + HANDLE h; + NTSTATUS status; + + RtlInitUnicodeString(&path, L"\\systemroot"); + InitializeObjectAttributes(&attr, &path, 0, NULL, NULL); + + status = NtOpenSymbolicLinkObject(&h, 0, &attr); + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + supported_features->case_sensitive_filenames = 1; + } return 0; } -- 2.43.0