ntdll: Validate directory path when the path name ends with a dos device name.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51291 Signed-off-by: Akihiro Sagawa <sagawa.aki@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
64c4582a40
commit
0acd98f135
|
@ -129,6 +129,40 @@ ULONG WINAPI RtlIsDosDeviceName_U( PCWSTR dos_name )
|
|||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* is_valid_directory
|
||||
*
|
||||
* Helper for RtlDosPathNameToNtPathName_U_WithStatus.
|
||||
* Test if the path is an exisiting directory.
|
||||
*/
|
||||
static BOOL is_valid_directory(LPCWSTR path)
|
||||
{
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING ntpath;
|
||||
IO_STATUS_BLOCK io;
|
||||
HANDLE handle;
|
||||
NTSTATUS nts;
|
||||
|
||||
if (!RtlDosPathNameToNtPathName_U(path, &ntpath, NULL, NULL))
|
||||
return FALSE;
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.ObjectName = &ntpath;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
nts = NtOpenFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &io,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
|
||||
RtlFreeUnicodeString(&ntpath);
|
||||
if (nts != STATUS_SUCCESS)
|
||||
return FALSE;
|
||||
NtClose(handle);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* RtlDosPathNameToNtPathName_U_WithStatus [NTDLL.@]
|
||||
*
|
||||
|
@ -146,9 +180,10 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U
|
|||
{
|
||||
static const WCHAR global_prefix[] = {'\\','\\','?','\\'};
|
||||
static const WCHAR global_prefix2[] = {'\\','?','?','\\'};
|
||||
ULONG sz, offset;
|
||||
NTSTATUS nts = STATUS_SUCCESS;
|
||||
ULONG sz, offset, dosdev;
|
||||
WCHAR local[MAX_PATH];
|
||||
LPWSTR ptr;
|
||||
LPWSTR ptr = local;
|
||||
|
||||
TRACE("(%s,%p,%p,%p)\n", debugstr_w(dos_path), ntpath, file_part, cd);
|
||||
|
||||
|
@ -178,28 +213,57 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ptr = local;
|
||||
sz = RtlGetFullPathName_U(dos_path, sizeof(local), ptr, file_part);
|
||||
if (sz == 0) return STATUS_OBJECT_NAME_INVALID;
|
||||
|
||||
if (sz > sizeof(local))
|
||||
dosdev = RtlIsDosDeviceName_U(dos_path);
|
||||
if ((offset = HIWORD(dosdev)))
|
||||
{
|
||||
if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, sz))) return STATUS_NO_MEMORY;
|
||||
sz = RtlGetFullPathName_U(dos_path, sz, ptr, file_part);
|
||||
sz = offset + sizeof(WCHAR);
|
||||
|
||||
if (sz > sizeof(local) &&
|
||||
(!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, sz))))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
memcpy(ptr, dos_path, offset);
|
||||
ptr[offset/sizeof(WCHAR)] = '\0';
|
||||
|
||||
if (!is_valid_directory(ptr))
|
||||
{
|
||||
nts = STATUS_OBJECT_NAME_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*file_part) *file_part = NULL;
|
||||
|
||||
sz = LOWORD(dosdev);
|
||||
|
||||
wcscpy(ptr, L"\\\\.\\");
|
||||
memcpy(ptr + 4, dos_path + offset / sizeof(WCHAR), sz);
|
||||
ptr[4 + sz / sizeof(WCHAR)] = '\0';
|
||||
sz += 4 * sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = RtlGetFullPathName_U(dos_path, sizeof(local), ptr, file_part);
|
||||
if (sz == 0) return STATUS_OBJECT_NAME_INVALID;
|
||||
|
||||
if (sz > sizeof(local))
|
||||
{
|
||||
if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, sz))) return STATUS_NO_MEMORY;
|
||||
sz = RtlGetFullPathName_U(dos_path, sz, ptr, file_part);
|
||||
}
|
||||
}
|
||||
sz += (1 /* NUL */ + 4 /* unc\ */ + 4 /* \??\ */) * sizeof(WCHAR);
|
||||
if (sz > MAXWORD)
|
||||
{
|
||||
if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr);
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
nts = STATUS_OBJECT_NAME_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ntpath->MaximumLength = sz;
|
||||
ntpath->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, ntpath->MaximumLength);
|
||||
if (!ntpath->Buffer)
|
||||
{
|
||||
if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr);
|
||||
return STATUS_NO_MEMORY;
|
||||
nts = STATUS_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
wcscpy(ntpath->Buffer, L"\\??\\");
|
||||
|
@ -225,8 +289,9 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U
|
|||
|
||||
/* FIXME: cd filling */
|
||||
|
||||
out:
|
||||
if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr);
|
||||
return STATUS_SUCCESS;
|
||||
return nts;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
|
|
@ -571,13 +571,11 @@ static void test_RtlDosPathNameToNtPathName_U(void)
|
|||
winetest_push_context("%s", debugstr_w(error_paths[i]));
|
||||
|
||||
ret = pRtlDosPathNameToNtPathName_U(error_paths[i], &nameW, &file_part, NULL);
|
||||
todo_wine_if(i == 3 || i == 4)
|
||||
ok(!ret, "Got %d.\n", ret);
|
||||
|
||||
if (pRtlDosPathNameToNtPathName_U_WithStatus)
|
||||
{
|
||||
status = pRtlDosPathNameToNtPathName_U_WithStatus(error_paths[i], &nameW, &file_part, NULL);
|
||||
todo_wine_if(i == 3 || i == 4)
|
||||
ok(status == STATUS_OBJECT_NAME_INVALID || broken(status == STATUS_OBJECT_PATH_NOT_FOUND /* 2003 */),
|
||||
"Got status %#x.\n", status);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue