mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[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:
parent
92654a7e4e
commit
97d2212a19
1 changed files with 91 additions and 94 deletions
|
@ -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) ||
|
||||
|
|
Loading…
Reference in a new issue