Commit 0acd98f1 authored by Akihiro Sagawa's avatar Akihiro Sagawa Committed by Alexandre Julliard

ntdll: Validate directory path when the path name ends with a dos device name.

parent 64c4582a
...@@ -129,6 +129,40 @@ ULONG WINAPI RtlIsDosDeviceName_U( PCWSTR dos_name ) ...@@ -129,6 +129,40 @@ ULONG WINAPI RtlIsDosDeviceName_U( PCWSTR dos_name )
return 0; 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.@] * RtlDosPathNameToNtPathName_U_WithStatus [NTDLL.@]
* *
...@@ -146,9 +180,10 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U ...@@ -146,9 +180,10 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U
{ {
static const WCHAR global_prefix[] = {'\\','\\','?','\\'}; static const WCHAR global_prefix[] = {'\\','\\','?','\\'};
static const WCHAR global_prefix2[] = {'\\','?','?','\\'}; static const WCHAR global_prefix2[] = {'\\','?','?','\\'};
ULONG sz, offset; NTSTATUS nts = STATUS_SUCCESS;
ULONG sz, offset, dosdev;
WCHAR local[MAX_PATH]; WCHAR local[MAX_PATH];
LPWSTR ptr; LPWSTR ptr = local;
TRACE("(%s,%p,%p,%p)\n", debugstr_w(dos_path), ntpath, file_part, cd); 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 ...@@ -178,28 +213,57 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
ptr = local; dosdev = RtlIsDosDeviceName_U(dos_path);
sz = RtlGetFullPathName_U(dos_path, sizeof(local), ptr, file_part); if ((offset = HIWORD(dosdev)))
if (sz == 0) return STATUS_OBJECT_NAME_INVALID; {
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;
if (sz > sizeof(local)) 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
{ {
if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, sz))) return STATUS_NO_MEMORY; sz = RtlGetFullPathName_U(dos_path, sizeof(local), ptr, file_part);
sz = RtlGetFullPathName_U(dos_path, sz, 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); sz += (1 /* NUL */ + 4 /* unc\ */ + 4 /* \??\ */) * sizeof(WCHAR);
if (sz > MAXWORD) if (sz > MAXWORD)
{ {
if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr); nts = STATUS_OBJECT_NAME_INVALID;
return STATUS_OBJECT_NAME_INVALID; goto out;
} }
ntpath->MaximumLength = sz; ntpath->MaximumLength = sz;
ntpath->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, ntpath->MaximumLength); ntpath->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, ntpath->MaximumLength);
if (!ntpath->Buffer) if (!ntpath->Buffer)
{ {
if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr); nts = STATUS_NO_MEMORY;
return STATUS_NO_MEMORY; goto out;
} }
wcscpy(ntpath->Buffer, L"\\??\\"); wcscpy(ntpath->Buffer, L"\\??\\");
...@@ -225,8 +289,9 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U ...@@ -225,8 +289,9 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U
/* FIXME: cd filling */ /* FIXME: cd filling */
out:
if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr); if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr);
return STATUS_SUCCESS; return nts;
} }
/************************************************************************** /**************************************************************************
......
...@@ -571,13 +571,11 @@ static void test_RtlDosPathNameToNtPathName_U(void) ...@@ -571,13 +571,11 @@ static void test_RtlDosPathNameToNtPathName_U(void)
winetest_push_context("%s", debugstr_w(error_paths[i])); winetest_push_context("%s", debugstr_w(error_paths[i]));
ret = pRtlDosPathNameToNtPathName_U(error_paths[i], &nameW, &file_part, NULL); ret = pRtlDosPathNameToNtPathName_U(error_paths[i], &nameW, &file_part, NULL);
todo_wine_if(i == 3 || i == 4)
ok(!ret, "Got %d.\n", ret); ok(!ret, "Got %d.\n", ret);
if (pRtlDosPathNameToNtPathName_U_WithStatus) if (pRtlDosPathNameToNtPathName_U_WithStatus)
{ {
status = pRtlDosPathNameToNtPathName_U_WithStatus(error_paths[i], &nameW, &file_part, NULL); 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 */), ok(status == STATUS_OBJECT_NAME_INVALID || broken(status == STATUS_OBJECT_PATH_NOT_FOUND /* 2003 */),
"Got status %#x.\n", status); "Got status %#x.\n", status);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment