[RTL/PATH]

- Update path.c code to Wine 1.3.14. Fixes a buffer overwrite happening in RtlDosSearchPath_U() when invoked by "shell32_winetest.exe shlexec".
- RtlDosPathNameToNtPathName_U remains unsynced.
- Author names added to the header of the file.
See issue #5964 for more details.

svn path=/trunk/; revision=50954
This commit is contained in:
Aleksey Bragin 2011-03-02 11:42:30 +00:00
parent 92654a7e4e
commit 97d2212a19

View file

@ -3,7 +3,9 @@
* PROJECT: ReactOS system libraries
* FILE: lib/rtl/path.c
* PURPOSE: Path and current directory functions
* PROGRAMMERS:
* PROGRAMMERS: Wine team
* Thomas Weidenmueller
* Gunnar Dalsnes
*/
/* INCLUDES *****************************************************************/
@ -112,30 +114,24 @@ RtlIsDosDeviceName_U(PWSTR dos_name)
if (!_wcsicmp( dos_name, consoleW ))
return MAKELONG( sizeof(conW), 4 * sizeof(WCHAR) ); /* 4 is length of \\.\ prefix */
return 0;
case RtlPathTypeDriveAbsolute:
case RtlPathTypeDriveRelative:
start = dos_name + 2; /* skip drive letter */
break;
default:
start = dos_name;
break;
}
end = dos_name + wcslen(dos_name) - 1;
while (end >= dos_name && *end == ':') end--; /* remove all trailing ':' */
/* find start of file name */
for (start = end; start >= dos_name; start--)
{
if (IS_PATH_SEPARATOR(start[0])) break;
/* check for ':' but ignore if before extension (for things like NUL:.txt) */
if (start[0] == ':' && start[1] != '.') break;
}
start++;
for (p = start; *p; p++) if (IS_PATH_SEPARATOR(*p)) start = p + 1;
/* truncate at extension and ':' */
for (end = start; *end; end++) if (*end == '.' || *end == ':') break;
end--;
/* remove extension */
if ((p = wcschr( start, '.' )))
{
end = p - 1;
if (end >= dos_name && *end == ':') end--; /* remove trailing ':' before extension */
}
/* remove trailing spaces */
while (end >= dos_name && *end == ' ') end--;
while (end >= start && *end == ' ') end--;
/* now we have a potential device name between start and end, check it */
switch(end - start + 1)
@ -218,6 +214,8 @@ RtlSetCurrentDirectory_U(PUNICODE_STRING dir)
DPRINT("RtlSetCurrentDirectory %wZ\n", dir);
full.Buffer = NULL;
RtlAcquirePebLock ();
cd = (PCURDIR)&NtCurrentPeb ()->ProcessParameters->CurrentDirectory.DosPath;
@ -287,16 +285,13 @@ RtlSetCurrentDirectory_U(PUNICODE_STRING dir)
}
/******************************************************************
* collapse_path
* collapse_path
*
* Helper for RtlGetFullPathName_U.
* 1) Convert slashes into backslashes
* 2) Get rid of duplicate backslashes
* 3) Get rid of . and .. components in the path.
* Get rid of . and .. components in the path.
*/
static __inline void collapse_path( WCHAR *path, UINT mark )
void FORCEINLINE collapse_path( WCHAR *path, UINT mark )
{
WCHAR *p, *next;
@ -469,9 +464,11 @@ static ULONG get_full_path_helper(
tmp[1] = ':';
tmp[2] = '\\';
ins_str = tmp;
RtlFreeHeap(RtlGetProcessHeap(), 0, val.Buffer);
break;
default:
DPRINT1("Unsupported status code\n");
RtlFreeHeap(RtlGetProcessHeap(), 0, val.Buffer);
break;
}
mark = 3;
@ -554,7 +551,7 @@ static ULONG get_full_path_helper(
if (reqsize) memcpy(buffer, ins_str, reqsize);
reqsize += deplen;
if (ins_str && ins_str != tmp && ins_str != cd->Buffer)
if (ins_str != tmp && ins_str != cd->Buffer)
RtlFreeHeap(RtlGetProcessHeap(), 0, ins_str);
collapse_path( buffer, mark );
@ -614,10 +611,9 @@ ULONG NTAPI RtlGetFullPathName_U(
if (reqsize > size)
{
LPWSTR tmp = RtlAllocateHeap(RtlGetProcessHeap(), 0, reqsize);
if (tmp == NULL)
return 0;
if (tmp == NULL) return 0;
reqsize = get_full_path_helper(name, tmp, reqsize);
if (reqsize > size) /* it may have worked the second time */
if (reqsize + sizeof(WCHAR) > size) /* it may have worked the second time */
{
RtlFreeHeap(RtlGetProcessHeap(), 0, tmp);
return reqsize + sizeof(WCHAR);
@ -799,77 +795,79 @@ RtlDosPathNameToNtPathName_U(IN PCWSTR DosPathName,
/*
* @implemented
*/
/******************************************************************
* RtlDosSearchPath_U
*
* Searches a file of name 'name' into a ';' separated list of paths
* (stored in paths)
* Doesn't seem to search elsewhere than the paths list
* Stores the result in buffer (file_part will point to the position
* of the file name in the buffer)
* FIXME:
* - how long shall the paths be ??? (MAX_PATH or larger with \\?\ constructs ???)
*/
ULONG
NTAPI
RtlDosSearchPath_U (
PCWSTR sp,
PCWSTR name,
PCWSTR ext,
ULONG buf_sz,
WCHAR *buffer,
PWSTR *FilePart
)
RtlDosSearchPath_U(PCWSTR paths,
PCWSTR search,
PCWSTR ext,
ULONG buffer_size,
PWSTR buffer,
PWSTR* file_part)
{
ULONG Type;
ULONG Length = 0;
PWSTR full_name;
PWSTR wcs;
PCWSTR path;
RTL_PATH_TYPE type = RtlDetermineDosPathNameType_U(search);
ULONG len = 0;
Type = RtlDetermineDosPathNameType_U (name);
if (type == RtlPathTypeRelative)
{
ULONG allocated = 0, needed, filelen;
WCHAR *name = NULL;
if (Type == 5)
{
Length = wcslen (sp);
Length += wcslen (name);
if (wcschr (name, L'.'))
ext = NULL;
if (ext != NULL)
Length += wcslen (ext);
filelen = 1 /* for \ */ + wcslen(search) + 1 /* \0 */;
full_name = (WCHAR*)RtlAllocateHeap (RtlGetProcessHeap (),
0,
(Length + 1) * sizeof(WCHAR));
Length = 0;
if (full_name != NULL)
{
path = sp;
while (*path)
{
wcs = full_name;
while (*path && *path != L';')
*wcs++ = *path++;
if (*path)
path++;
if (wcs != full_name && *(wcs - 1) != L'\\')
*wcs++ = L'\\';
wcscpy (wcs, name);
if (ext)
wcscat (wcs, ext);
if (RtlDoesFileExists_U (full_name))
{
Length = RtlGetFullPathName_U (full_name,
buf_sz,
buffer,
FilePart);
break;
}
}
/* Windows only checks for '.' without worrying about path components */
if (wcschr( search, '.' )) ext = NULL;
if (ext != NULL) filelen += wcslen(ext);
RtlFreeHeap (RtlGetProcessHeap (),
0,
full_name);
}
}
else if (RtlDoesFileExists_U (name))
{
Length = RtlGetFullPathName_U (name,
buf_sz,
buffer,
FilePart);
}
while (*paths)
{
LPCWSTR ptr;
return Length;
for (needed = 0, ptr = paths; *ptr != 0 && *ptr++ != ';'; needed++);
if (needed + filelen > allocated)
{
if (!name) name = RtlAllocateHeap(RtlGetProcessHeap(), 0,
(needed + filelen) * sizeof(WCHAR));
else
{
WCHAR *newname = RtlReAllocateHeap(RtlGetProcessHeap(), 0, name,
(needed + filelen) * sizeof(WCHAR));
if (!newname) RtlFreeHeap(RtlGetProcessHeap(), 0, name);
name = newname;
}
if (!name) return 0;
allocated = needed + filelen;
}
memmove(name, paths, needed * sizeof(WCHAR));
/* append '\\' if none is present */
if (needed > 0 && name[needed - 1] != '\\') name[needed++] = '\\';
wcscpy(&name[needed], search);
if (ext) wcscat(&name[needed], ext);
if (RtlDoesFileExists_U(name))
{
len = RtlGetFullPathName_U(name, buffer_size, buffer, file_part);
break;
}
paths = ptr;
}
RtlFreeHeap(RtlGetProcessHeap(), 0, name);
}
else if (RtlDoesFileExists_U(search))
{
len = RtlGetFullPathName_U(search, buffer_size, buffer, file_part);
}
return len;
}
@ -881,11 +879,10 @@ RtlDoesFileExists_U(IN PCWSTR FileName)
{
UNICODE_STRING NtFileName;
OBJECT_ATTRIBUTES Attr;
FILE_BASIC_INFORMATION Info;
FILE_BASIC_INFORMATION Info;
NTSTATUS Status;
CURDIR CurDir;
if (!RtlDosPathNameToNtPathName_U (FileName,
&NtFileName,
NULL,
@ -905,7 +902,7 @@ RtlDoesFileExists_U(IN PCWSTR FileName)
Status = ZwQueryAttributesFile (&Attr, &Info);
RtlFreeUnicodeString(&NtFileName);
RtlFreeUnicodeString(&NtFileName);
if (NT_SUCCESS(Status) ||