Author: fireball Date: Wed Mar 2 11:42:30 2011 New Revision: 50954
URL: http://svn.reactos.org/svn/reactos?rev=50954&view=rev Log: [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.
Modified: trunk/reactos/lib/rtl/path.c
Modified: trunk/reactos/lib/rtl/path.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/path.c?rev=50954&am... ============================================================================== --- trunk/reactos/lib/rtl/path.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/path.c [iso-8859-1] Wed Mar 2 11:42:30 2011 @@ -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 @@ 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++; - - /* remove extension */ - if ((p = wcschr( start, '.' ))) - { - end = p - 1; - if (end >= dos_name && *end == ':') end--; /* remove trailing ':' before extension */ - } + 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 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 @@
DPRINT("RtlSetCurrentDirectory %wZ\n", dir);
+ full.Buffer = NULL; + RtlAcquirePebLock ();
cd = (PCURDIR)&NtCurrentPeb ()->ProcessParameters->CurrentDirectory.DosPath; @@ -287,16 +285,13 @@ }
- /****************************************************************** - * 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. - */ -static __inline void collapse_path( WCHAR *path, UINT mark ) + * Get rid of . and .. components in the path. + */ +void FORCEINLINE collapse_path( WCHAR *path, UINT mark ) { WCHAR *p, *next;
@@ -469,9 +464,11 @@ 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 @@ 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 @@ 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 @@ /* * @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 - ) -{ - ULONG Type; - ULONG Length = 0; - PWSTR full_name; - PWSTR wcs; - PCWSTR path; - - Type = RtlDetermineDosPathNameType_U (name); - - if (Type == 5) - { - Length = wcslen (sp); - Length += wcslen (name); - if (wcschr (name, L'.')) - ext = NULL; - if (ext != NULL) - Length += wcslen (ext); - - 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; - } - } - - RtlFreeHeap (RtlGetProcessHeap (), - 0, - full_name); - } - } - else if (RtlDoesFileExists_U (name)) - { - Length = RtlGetFullPathName_U (name, - buf_sz, - buffer, - FilePart); - } - - return Length; +RtlDosSearchPath_U(PCWSTR paths, + PCWSTR search, + PCWSTR ext, + ULONG buffer_size, + PWSTR buffer, + PWSTR* file_part) +{ + RTL_PATH_TYPE type = RtlDetermineDosPathNameType_U(search); + ULONG len = 0; + + if (type == RtlPathTypeRelative) + { + ULONG allocated = 0, needed, filelen; + WCHAR *name = NULL; + + filelen = 1 /* for \ */ + wcslen(search) + 1 /* \0 */; + + /* Windows only checks for '.' without worrying about path components */ + if (wcschr( search, '.' )) ext = NULL; + if (ext != NULL) filelen += wcslen(ext); + + while (*paths) + { + LPCWSTR ptr; + + 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,10 +879,9 @@ { UNICODE_STRING NtFileName; OBJECT_ATTRIBUTES Attr; - FILE_BASIC_INFORMATION Info; + FILE_BASIC_INFORMATION Info; NTSTATUS Status; CURDIR CurDir; -
if (!RtlDosPathNameToNtPathName_U (FileName, &NtFileName, @@ -905,7 +902,7 @@
Status = ZwQueryAttributesFile (&Attr, &Info);
- RtlFreeUnicodeString(&NtFileName); + RtlFreeUnicodeString(&NtFileName);
if (NT_SUCCESS(Status) ||