From: Jiajin Cui cuijiajin@uniontech.com
see "https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-lim...".
Signed-off-by: Jiajin Cui cuijiajin@uniontech.com --- dlls/ntdll/path.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+)
diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c index 37ad4bbcea2..b844b19ba72 100644 --- a/dlls/ntdll/path.c +++ b/dlls/ntdll/path.c @@ -33,6 +33,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
#define IS_SEPARATOR(ch) ((ch) == '\' || (ch) == '/')
+#define LONGPATH_INIT 0 +#define LONGPATH_ENABLE 1 +#define LONGPATH_DISABLE -1 +static DWORD longpathenable = LONGPATH_INIT; + /*********************************************************************** * RtlDetermineDosPathNameType_U (NTDLL.@) */ @@ -163,6 +168,79 @@ static BOOL is_valid_directory(LPCWSTR path) return TRUE; }
+static NTSTATUS query_dword_option( HANDLE hkey, LPCWSTR name, LONG *value ) +{ + NTSTATUS status; + UNICODE_STRING str; + ULONG size; + WCHAR buffer[64]; + KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + + RtlInitUnicodeString( &str, name ); + + size = sizeof(buffer) - sizeof(WCHAR); + if ((status = NtQueryValueKey( hkey, &str, KeyValuePartialInformation, buffer, size, &size ))) + return status; + + if (info->Type != REG_DWORD) + { + buffer[size / sizeof(WCHAR)] = 0; + *value = wcstoul( (WCHAR *)info->Data, 0, 16 ); + } + else memcpy( value, info->Data, sizeof(*value) ); + return status; +} + +static DWORD getLongPathsEnabled() +{ + OBJECT_ATTRIBUTES attr = { sizeof(attr) }; + UNICODE_STRING name; + HANDLE mutex; + static HKEY hklm; + + static WCHAR longpath_mutexW[] = + {'\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s', + '\','_','_','L','O','N','G','_','P','A','T','H','_','M','U','T','E','X','_','_'}; + + attr.Attributes = OBJ_OPENIF; + attr.ObjectName = &name; + name.Buffer = longpath_mutexW; + name.Length = name.MaximumLength = sizeof(longpath_mutexW); + + if (NtCreateMutant( &mutex, MUTEX_ALL_ACCESS, &attr, FALSE ) < 0) return 0; + NtWaitForSingleObject( mutex, FALSE, NULL ); + + if(LONGPATH_INIT == longpathenable) + { + static const WCHAR filesystemW[] = {'\','R','e','g','i','s','t','r','y', + '\','M','a','c','h','i','n','e', + '\','S','y','s','t','e','m', + '\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t', + '\','C','o','n','t','r','o','l', + '\','F','i','l','e','S','y','s','t','e','m',0}; + static const WCHAR longpathenableW[] = {'L','o','n','g','P','a','t','h','s','E','n','a','b','l','e','d',0}; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + HANDLE key; + + InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL ); + nameW.Buffer = filesystemW; + nameW.Length = sizeof(filesystemW); + nameW.MaximumLength = nameW.Length; + if (!NtOpenKey( &key, KEY_READ, &attr )) + { + query_dword_option( key, longpathenableW, &longpathenable ); + NtClose( key ); + } + } + + if(LONGPATH_ENABLE != longpathenable) longpathenable = LONGPATH_DISABLE; + + NtReleaseMutant( mutex, NULL ); + + return longpathenable; +} + /************************************************************************** * RtlDosPathNameToNtPathName_U_WithStatus [NTDLL.@] * @@ -196,6 +274,13 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U if (!dos_path || !*dos_path) return STATUS_OBJECT_NAME_INVALID;
+ if( LONGPATH_ENABLE != getLongPathsEnabled() + && memcmp(dos_path, global_prefix, sizeof(global_prefix)) + && wcslen(dos_path) > MAX_PATH ) + { + return STATUS_OBJECT_NAME_INVALID; + } + if (!memcmp(dos_path, global_prefix, sizeof(global_prefix)) || (!memcmp(dos_path, global_prefix2, sizeof(global_prefix2)) && dos_path[4]) || !wcsicmp( dos_path, L"\\.\CON" ))