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&a…
==============================================================================
--- 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) ||