ntdll/kernel32: #17
Eric Pouech
pouech-eric at wanadoo.fr
Sun Apr 6 11:33:07 CDT 2003
starting with the file APIs...
this patch implements a few helper functions
A+
--
Eric Pouech
-------------- next part --------------
Name: ntkrnl_17
ChangeLog: added RtlDetermineDosPathNameType_U RtlDoesFileExists_U RtlDosPathNameToNtPathName_U
RtlDosSearchPath_U RtlGetFullPathName_U RtlIsDosDeviceName_U RtlIsNameLegalDOS8Dot3
License: X11
GenDate: 2003/04/06 16:27:11 UTC
ModifiedFiles: dlls/ntdll/Makefile.in dlls/ntdll/ntdll.spec dlls/ntdll/rtl.c include/winternl.h
AddedFiles: dlls/ntdll/dos.c dlls/ntdll/path.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/Makefile.in,v
retrieving revision 1.54
diff -u -u -r1.54 Makefile.in
--- dlls/ntdll/Makefile.in 4 Apr 2003 22:26:34 -0000 1.54
+++ dlls/ntdll/Makefile.in 5 Apr 2003 08:09:13 -0000
@@ -74,6 +74,7 @@
cdrom.c \
critsection.c \
debugtools.c \
+ dos.c \
exception.c \
error.c \
file.c \
@@ -83,6 +84,7 @@
misc.c \
nt.c \
om.c \
+ path.c \
reg.c \
rtl.c \
rtlstr.c \
Index: dlls/ntdll/ntdll.spec
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/ntdll.spec,v
retrieving revision 1.103
diff -u -u -r1.103 ntdll.spec
--- dlls/ntdll/ntdll.spec 4 Apr 2003 22:26:34 -0000 1.103
+++ dlls/ntdll/ntdll.spec 5 Apr 2003 08:09:14 -0000
@@ -347,10 +347,10 @@
@ stdcall RtlDestroyHeap(long)
@ stub RtlDestroyProcessParameters
@ stub RtlDestroyQueryDebugBuffer
-@ stub RtlDetermineDosPathNameType_U
-@ stub RtlDoesFileExists_U
-@ stdcall RtlDosPathNameToNtPathName_U(ptr ptr long long)
-@ stub RtlDosSearchPath_U
+@ stdcall RtlDetermineDosPathNameType_U(wstr)
+@ stdcall RtlDoesFileExists_U(wstr)
+@ stdcall RtlDosPathNameToNtPathName_U(wstr ptr ptr ptr)
+@ stdcall RtlDosSearchPath_U(wstr wstr wstr long ptr ptr)
@ stdcall RtlDowncaseUnicodeChar(long)
@ stdcall RtlDowncaseUnicodeString(ptr ptr long)
@ stdcall RtlDumpResource(ptr)
@@ -409,7 +409,7 @@
@ stub RtlGetCurrentDirectory_U
@ stdcall RtlGetDaclSecurityDescriptor(ptr ptr ptr ptr)
@ stub RtlGetElementGenericTable
-@ stub RtlGetFullPathName_U
+@ stdcall RtlGetFullPathName_U(wstr long ptr ptr)
@ stdcall RtlGetGroupSecurityDescriptor(ptr ptr ptr)
@ stdcall RtlGetLongestNtPathLength()
@ stub RtlGetNtGlobalFlags
@@ -441,9 +441,9 @@
@ stdcall RtlInt64ToUnicodeString(long long long ptr)
@ stdcall RtlIntegerToChar(long long long ptr)
@ stdcall RtlIntegerToUnicodeString(long long ptr)
-@ stub RtlIsDosDeviceName_U
+@ stdcall RtlIsDosDeviceName_U(wstr)
@ stub RtlIsGenericTableEmpty
-@ stub RtlIsNameLegalDOS8Dot3
+@ stdcall RtlIsNameLegalDOS8Dot3(ptr ptr ptr)
@ stdcall RtlIsTextUnicode(ptr long ptr)
@ stdcall -ret64 RtlLargeIntegerAdd(long long long long)
@ stdcall -ret64 RtlLargeIntegerArithmeticShift(long long long)
Index: dlls/ntdll/rtl.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/rtl.c,v
retrieving revision 1.59
diff -u -u -r1.59 rtl.c
--- dlls/ntdll/rtl.c 3 Apr 2003 23:57:11 -0000 1.59
+++ dlls/ntdll/rtl.c 5 Apr 2003 08:09:14 -0000
@@ -378,55 +378,6 @@
context->Esp -= context->Eax;
}
-/**************************************************************************
- * RtlDosPathNameToNtPathName_U [NTDLL.@]
- *
- * szwDosPath: a fully qualified DOS path name
- * ntpath: pointer to a UNICODE_STRING to hold the converted
- * path name
- *
- * FIXME: Should we not allocate the ntpath buffer under some
- * circumstances?
- * Are the conversions static? (always prepend '\??\' ?)
- * Not really sure about the last two arguments.
- */
-BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(
- LPWSTR szwDosPath,PUNICODE_STRING ntpath,
- DWORD x2,DWORD x3)
-{
- ULONG length;
- UNICODE_STRING pathprefix;
- WCHAR szPrefix[] = { '\\', '?', '?', '\\', 0 };
-
- FIXME("(%s,%p,%08lx,%08lx) partial stub\n",
- debugstr_w(szwDosPath),ntpath,x2,x3);
-
- if ( !szwDosPath )
- return FALSE;
-
- if ( !szwDosPath[0] )
- return FALSE;
-
- if ( szwDosPath[1]!= ':' )
- return FALSE;
-
- length = strlenW(szwDosPath) * sizeof (WCHAR) + sizeof szPrefix;
-
- ntpath->Buffer = RtlAllocateHeap(ntdll_get_process_heap(), 0, length);
- ntpath->Length = 0;
- ntpath->MaximumLength = length;
-
- if ( !ntpath->Buffer )
- return FALSE;
-
- RtlInitUnicodeString( &pathprefix, szPrefix );
- RtlCopyUnicodeString( ntpath, &pathprefix );
- RtlAppendUnicodeToString( ntpath, szwDosPath );
-
- return TRUE;
-}
-
-
/******************************************************************************
* RtlCreateEnvironment [NTDLL.@]
*/
@@ -637,23 +588,6 @@
ulCount /= sizeof(ULONG);
while(ulCount--)
*lpDest++ = ulValue;
-}
-
-/*************************************************************************
- * RtlGetLongestNtPathLength [NTDLL.@]
- *
- * Get the longest allowed path length
- *
- * PARAMS
- * None.
- *
- * RETURNS
- * The longest allowed path length (277 characters under Win2k).
- */
-DWORD WINAPI RtlGetLongestNtPathLength(void)
-{
- TRACE("()\n");
- return 277;
}
/*********************************************************************
Index: include/winternl.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/include/winternl.h,v
retrieving revision 1.23
diff -u -u -r1.23 winternl.h
--- include/winternl.h 4 Apr 2003 22:26:34 -0000 1.23
+++ include/winternl.h 5 Apr 2003 08:09:28 -0000
@@ -931,7 +931,7 @@
DWORD WINAPI RtlDeleteSecurityObject(DWORD);
DWORD WINAPI RtlDestroyEnvironment(DWORD);
HANDLE WINAPI RtlDestroyHeap(HANDLE);
-BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(LPWSTR,PUNICODE_STRING,DWORD,DWORD);
+BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(LPWSTR,PUNICODE_STRING,LPWSTR*,void*);
WCHAR WINAPI RtlDowncaseUnicodeChar(WCHAR);
NTSTATUS WINAPI RtlDowncaseUnicodeString(UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
void WINAPI RtlDumpResource(LPRTL_RWLOCK);
@@ -1248,6 +1248,18 @@
NTSTATUS WINAPI LdrShutdownThread(void);
NTSTATUS WINAPI LdrUnloadDll(HMODULE);
NTSTATUS WINAPI LdrUnlockLoaderLock(ULONG,ULONG);
+
+/*************************************************************************
+ * Some more file & path functions and structures.
+ *
+ * Those are not part of standard Winternl.h
+ */
+DWORD WINAPI RtlDetermineDosPathNameType_U(LPCWSTR path);
+DWORD WINAPI RtlIsDosDeviceName_U(LPCWSTR);
+ULONG WINAPI RtlDosSearchPath_U(LPCWSTR, LPCWSTR, LPCWSTR, ULONG, LPWSTR, LPWSTR*);
+
+ULONG WINAPI RtlGetFullPathName_U(LPCWSTR, ULONG, LPWSTR, LPWSTR*);
+BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR);
#ifdef __cplusplus
} /* extern "C" */
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/ntdll/dos.c 2003-04-06 18:08:20.000000000 +0200
@@ -0,0 +1,321 @@
+/*
+ * NTDLL's dos filenames/devices related functions
+ *
+ * Copyright 2003, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "winternl.h"
+
+#include "wine/port.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+#include "ntdll_misc.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
+
+static const WCHAR DOS_Con[] = {'C','O','N'};
+static const WCHAR DOS_Prn[] = {'P','R','N'};
+static const WCHAR DOS_Nul[] = {'N','U','L'};
+static const WCHAR DOS_Aux[] = {'A','U','X'};
+static const WCHAR DOS_Lpt[] = {'L','P','T'};
+static const WCHAR DOS_Com[] = {'C','O','M'};
+
+static const WCHAR NTDosPrefixW[] = {'\\','?','?','\\',0};
+static const WCHAR NTLongFileNameW[] = {'\\','\\','?','\\',0};
+static const WCHAR NT_UNCW[] = {'U','N','C','\\',0};
+
+#define IS_SEPARATOR(c) ((c) == '/' || (c) == '\\')
+#define INVALID_DOS_CHARS "*?<>|\"+=,;[] \345"
+
+/******************************************************************
+ * RtlIsDosDeviceName_U
+ *
+ * Returns 0 if device_name is not a standard DOS device
+ * Returns otherwise:
+ * high word: offset (in bytes) to DOS device in device_name
+ * low word: length (in bytes) of DOS device in device_name
+ */
+DWORD WINAPI RtlIsDosDeviceName_U(const WCHAR* device_name)
+{
+ DWORD len;
+ const WCHAR*ptr;
+
+ TRACE("(%s)\n", debugstr_w(device_name));
+
+ if (!device_name || !*device_name) return 0;
+
+ len = strlenW(device_name);
+ ptr = device_name + len - 1;
+ while (len > 0 && *ptr == ' ') ptr--, len--;
+ while (len > 0 && *ptr == '.') ptr--, len--;
+ if (len > 0 && *ptr == ':') ptr--,len--;
+
+ while (ptr > device_name && !IS_SEPARATOR(ptr[-1]))
+ ptr--;
+ len -= ptr - device_name;
+ if (len == 3 && (strncmpW(ptr, DOS_Con, 3) == 0 ||
+ strncmpW(ptr, DOS_Prn, 3) == 0 ||
+ strncmpW(ptr, DOS_Nul, 3) == 0 ||
+ strncmpW(ptr, DOS_Aux, 3) == 0))
+ return ((ptr - device_name) << 17) | 6;
+ if (len == 4 &&
+ (strncmpW(ptr, DOS_Com, 3) == 0 || strncmpW(ptr, DOS_Lpt, 3) == 0) &&
+ ptr[3] >= '1' && ptr[3] <= '9')
+ return ((ptr - device_name) << 17) | 8;
+
+ return 0;
+}
+
+/******************************************************************
+ * RtlDetermineDosPathNameType_U
+ *
+ * Returns:
+ * 1: NT name space (\\foo)
+ * 2: DOS: drive + absolute path (c:\foo)
+ * 3: DOS: drive + relative path (c:foo)
+ * 4: DOS: absolute path (\foo)
+ * 5: DOS: relative path (foo)
+ * 6: NT device \\.\foo
+ * 7: NT device root \\.
+ */
+DWORD WINAPI RtlDetermineDosPathNameType_U(const WCHAR* path)
+{
+ /* Win 2k actually segv:s on a NULL path */
+ if (IS_SEPARATOR(path[0]))
+ {
+ if (IS_SEPARATOR(path[1]))
+ {
+ if (path[2] == '.')
+ {
+ if (IS_SEPARATOR(path[3])) return 6; /* \\.\foo */
+ if (path[3]) return 1; /* \\.foo */
+ return 7; /* \\. */
+ }
+ return 1; /* \\foo */
+ }
+ return 4; /* \foo */
+ }
+ if (path[1] == ':')
+ {
+ if (IS_SEPARATOR(path[2])) return 2; /* c:\foo */
+ return 3; /* c:xxx */
+ }
+ return 5; /* xxx */
+}
+
+/**************************************************************************
+ * RtlDosPathNameToNtPathName_U [NTDLL.@]
+ *
+ * dos_path: a DOS path name (fully qualified or not)
+ * ntpath: pointer to a UNICODE_STRING to hold the converted
+ * path name
+ * file_part:will point (in ntpath) to the file part in the path
+ * cd: directory reference (optional)
+ *
+ * FIXME:
+ * + Not really sure about the last arguments (it's a pointer to
+ * a structure describing a directory, likely the current one)
+ */
+BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PWSTR dos_path,
+ PUNICODE_STRING ntpath,
+ PWSTR* file_part,
+ void* cd)
+{
+ ULONG sz, ptr_sz, offset, type;
+ WCHAR local[MAX_PATH];
+ LPWSTR ptr;
+
+ TRACE("(%s,%p,%p,%p)\n",
+ debugstr_w(dos_path), ntpath, file_part, cd);
+ if (cd) FIXME("Unsupported parameter\n");
+
+ if (!dos_path || !*dos_path) return FALSE;
+
+ if (!strcmpW(dos_path, NTLongFileNameW))
+ {
+ dos_path += 4;
+ ptr = NULL;
+ ptr_sz = 0;
+ }
+ else
+ {
+ ptr = local;
+ ptr_sz = sizeof(local);
+ }
+ sz = RtlGetFullPathName_U(dos_path, ptr_sz, ptr, file_part);
+ if (sz == 0) return FALSE;
+ if (sz > ptr_sz)
+ {
+ ptr = RtlAllocateHeap(ntdll_get_process_heap(), 0, sz);
+ sz = RtlGetFullPathName_U(dos_path, sz, ptr, file_part);
+ }
+
+ ntpath->MaximumLength = sz + (4 /* unc\ */ + 4 /* \??\ */) * sizeof(WCHAR);
+ ntpath->Buffer = RtlAllocateHeap(ntdll_get_process_heap(), 0, ntpath->MaximumLength);
+ if (!ntpath->Buffer)
+ {
+ if (ptr != local) RtlFreeHeap(ntdll_get_process_heap(), 0, ptr);
+ return FALSE;
+ }
+
+ strcpyW(ntpath->Buffer, NTDosPrefixW);
+ offset = 0;
+ switch (type = RtlDetermineDosPathNameType_U(ptr))
+ {
+ case 1: /* \\foo */
+ if (ptr[2] != '?')
+ {
+ offset = 2;
+ strcatW(ntpath->Buffer, NT_UNCW);
+ }
+ break;
+ case 6: /* \\.\foo */
+ offset = 4;
+ break;
+ }
+
+ strcatW(ntpath->Buffer, ptr + offset);
+ ntpath->Length = strlenW(ntpath->Buffer) * sizeof(WCHAR);
+
+ if (file_part && *file_part)
+ *file_part = ntpath->Buffer + ntpath->Length / sizeof(WCHAR) - lstrlenW(*file_part);
+
+ /* FIXME: cd filling */
+
+ if (ptr != local) RtlFreeHeap(ntdll_get_process_heap(), 0, ptr);
+ return TRUE;
+}
+
+/******************************************************************
+ * RtlIsNameLegalDOS8Dot3
+ *
+ * Returns TRUE iff unicode is a valid DOS (8+3) name.
+ * If the name is valid, ansi gets filled with the corresponding ANSI string
+ * spaces is set to TRUE if unicode contains spaces
+ */
+BOOLEAN WINAPI RtlIsNameLegalDOS8Dot3(PUNICODE_STRING unicode,
+ PANSI_STRING ansi,
+ BOOLEAN* spaces)
+{
+ unsigned len, i;
+ int dot = -1;
+
+ if (unicode->Length > 24) return FALSE;
+
+ len = unicode->Length / sizeof(WCHAR);
+ if (spaces) *spaces = FALSE;
+ if (unicode->Buffer[0] == '.')
+ {
+ /* a starting . is invalid, except for . and .. */
+ switch (len)
+ {
+ case 1: break;
+ case 2: if (unicode->Buffer[1] != '.') return FALSE; break;
+ default: return FALSE;
+ }
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ {
+ switch (unicode->Buffer[i])
+ {
+ case ' ': if (spaces) *spaces = TRUE; break;
+ case '.': if (dot != -1) return FALSE; dot = i; break;
+ }
+ }
+ }
+ /* check file part is shorter than 8, extension shorter than 3
+ * dot cannot be last in string
+ */
+ if (dot == -1)
+ {
+ if (len > 8) return FALSE;
+ }
+ else
+ {
+ if (dot > 8 || (len - dot > 4) || dot == len - 1) return FALSE;
+ }
+
+ RtlUnicodeStringToAnsiString(ansi, unicode, TRUE);
+
+ return TRUE;
+}
+
+/******************************************************************
+ * RtlDosSearchPath_U
+ *
+ * Searchs 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 WINAPI RtlDosSearchPath_U(LPCWSTR paths, LPCWSTR search, LPCWSTR ext,
+ ULONG buffer_size, LPWSTR buffer,
+ LPWSTR* file_part)
+{
+ ULONG type = RtlDetermineDosPathNameType_U(search);
+ ULONG len = 0;
+
+ if (type == 5) /* relative DOS pathname */
+ {
+ ULONG allocated = 0, needed, filelen;
+ WCHAR* name = NULL;
+
+ filelen = 1 /* for \ */ + strlenW(search) + 1 /* \0 */;
+
+ if (strchrW(search, '.') != NULL) ext = NULL;
+ if (ext != NULL) filelen += strlenW(ext);
+
+ while (*paths)
+ {
+ LPCWSTR ptr;
+
+ for (needed = 0, ptr = paths; *ptr != 0 && *ptr++ != ';'; needed++);
+ if (needed + filelen > allocated)
+ {
+ name = (WCHAR*)RtlReAllocateHeap(ntdll_get_process_heap(), 0,
+ name, (needed + filelen) * sizeof(WCHAR));
+ 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++] = '\\';
+ strcpyW(&name[needed], search);
+ if (ext) strcatW(&name[needed], ext);
+ if (RtlDoesFileExists_U(name))
+ {
+ len = RtlGetFullPathName_U(name, buffer_size, buffer, file_part);
+ break;
+ }
+ paths = ptr;
+ }
+ RtlFreeHeap(ntdll_get_process_heap(), 0, name);
+ }
+ else if (RtlDoesFileExists_U(search))
+ {
+ len = RtlGetFullPathName_U(search, buffer_size, buffer, file_part);
+ }
+
+ return len;
+}
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/ntdll/path.c 2003-04-06 18:22:56.000000000 +0200
@@ -0,0 +1,274 @@
+/*
+ * NTDLL's paths related functions
+ *
+ * Copyright 2003, Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "winternl.h"
+
+#include "wine/port.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+#include "drive.h"
+#include "file.h"
+#include "ntdll_misc.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
+
+static WCHAR DeviceRootW[] = {'\\','\\','.','\\',0};
+
+/******************************************************************
+ * RtlDoesFileExists_U
+ *
+ *
+ */
+BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR file_name)
+{
+ DOS_FULL_NAME dos;
+
+ TRACE("%s\n", debugstr_w(file_name));
+ return DOSFS_GetFullName(file_name, TRUE, &dos);
+}
+
+/******************************************************************
+ * get_full_path_helper
+ *
+ * Helper for RtlGetFullPathName_U
+ */
+static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
+{
+ ULONG reqsize;
+ DWORD type;
+ LPWSTR ptr;
+
+ reqsize = sizeof(WCHAR); /* '\0' at the end */
+
+ switch (type = RtlDetermineDosPathNameType_U(name))
+ {
+ case 1: /* \\foo */
+ case 6: /* \\.\foo */
+ if (reqsize <= size) buffer[0] = '\0';
+ break;
+
+ case 2: /* c:\foo */
+ reqsize += sizeof(WCHAR);
+ if (reqsize <= size)
+ {
+ buffer[0] = toupperW(name[0]);
+ buffer[1] = '\0';
+ }
+ name++;
+ break;
+
+ case 3: /* c:foo */
+ case 5: /* foo */
+ {
+ WCHAR drive;
+ LPCSTR cwd;
+
+ if (type == 3)
+ {
+ drive = toupperW(name[0]) - 'A';
+ name += 2;
+ }
+ else
+ drive = DRIVE_GetCurrentDrive();
+ reqsize += 3 * sizeof(WCHAR);
+ if (reqsize <= size)
+ {
+ buffer[0] = drive + 'A';
+ buffer[1] = ':';
+ buffer[2] = '\\';
+ }
+ cwd = DRIVE_GetUnixCwd(drive);
+ if (!cwd || !*cwd)
+ {
+ if (reqsize <= size) buffer[3] = '\0';
+ }
+ else
+ {
+ DWORD clen = strlen(cwd);
+
+ ptr = buffer + 3;
+ reqsize += (clen + 1) * sizeof(WCHAR);
+ if (reqsize <= size)
+ {
+ /* FIXME: this comes from kernel32...
+ * but ntdll's equivalent aren't fully available yet
+ */
+ MultiByteToWideChar(DRIVE_GetCodepage(drive), 0, cwd, -1,
+ ptr, clen);
+ ptr += clen;
+ *ptr++ = '\\';
+ }
+
+ *ptr = '\0';
+ }
+ }
+ break;
+
+ case 4: /* \xxx */
+ reqsize += 2 * sizeof(WCHAR);
+ if (reqsize <= size)
+ {
+ buffer[0] = DRIVE_GetCurrentDrive() + 'A';
+ buffer[1] = ':';
+ buffer[2] = '\0';
+ }
+ break;
+ case 7: /* \\. */
+ reqsize += 4 * sizeof(WCHAR);
+ name += 3;
+ if (reqsize <= size)
+ {
+ buffer[0] = '\\';
+ buffer[1] = '\\';
+ buffer[2] = '.';
+ buffer[3] = '\\';
+ buffer[4] = '\0';
+ }
+ break;
+
+ default:
+ ERR("Unrecognized type: %ld\n", type);
+ return 0;
+ }
+
+ reqsize += strlenW(name) * sizeof(WCHAR);
+ if (reqsize > size) return reqsize;
+
+ strcatW(buffer, name);
+
+ for (ptr = buffer; ptr < buffer + size / sizeof(WCHAR); ptr++)
+ if (*ptr == '/') *ptr = '\\';
+
+ reqsize -= sizeof(WCHAR); /* don't count trailing \0 */
+
+ for (ptr = buffer + 2; ptr < buffer + reqsize / sizeof(WCHAR); )
+ {
+ WCHAR* p = strchrW(ptr, '\\');
+ if (!p) break;
+
+ p++;
+ if (p[0] == '.')
+ {
+ switch (p[1])
+ {
+ case '.':
+ switch (p[2])
+ {
+ case '\\':
+ {
+ WCHAR* prev = p - 2;
+ while (prev >= buffer && *prev != '\\') prev--;
+ /* either collapse \foo\.. into \ or \.. into \ */
+ if (prev < buffer) prev = p - 1;
+ reqsize -= (p + 2 - prev) * sizeof(WCHAR);
+ memmove(prev, p + 2, buffer + reqsize - prev + sizeof(WCHAR));
+ }
+ break;
+ case '\0':
+ reqsize -= 2 * sizeof(WCHAR);
+ *p = 0;
+ break;
+ }
+ break;
+ case '\\':
+ reqsize -= 2 * sizeof(WCHAR);
+ memmove(ptr + 2, ptr, buffer + reqsize - ptr + sizeof(WCHAR));
+ break;
+ }
+ }
+ ptr = p;
+ }
+ return reqsize;
+}
+
+/******************************************************************
+ * RtlGetFullPathName_U
+ *
+ * Returns the number of bytes written to buffer (not including the
+ * terminating NULL) if the function succeeds, or the required number of bytes
+ * (including the terminating NULL) if the buffer is to small.
+ *
+ * file_part will point to the filename part inside buffer (except if we use
+ * DOS device name, in which case file_in_buf is NULL)
+ *
+ */
+DWORD WINAPI RtlGetFullPathName_U(const WCHAR* name, ULONG size, WCHAR* buffer,
+ WCHAR** file_part)
+{
+ DWORD dosdev;
+ DWORD reqsize;
+
+ TRACE("(%s %lu %p %p)\n", debugstr_w(name), size, buffer, file_part);
+
+ if (!name || !*name) return 0;
+
+ if (file_part) *file_part = NULL;
+
+ /* check for DOS device name */
+ dosdev = RtlIsDosDeviceName_U(name);
+ if (dosdev)
+ {
+ DWORD offset = dosdev >> 17; /* get it in WCHARs, not bytes */
+ DWORD sz = dosdev & 0xFFFF; /* in bytes */
+
+ if (8 + sz + 2 > size) return sz + 10;
+ strcpyW(buffer, DeviceRootW);
+ memmove(buffer + 4, name + offset, sz);
+ buffer[4 + sz / sizeof(WCHAR)] = '\0';
+ /* file_part isn't set in this case */
+ return sz + 8;
+ }
+
+ reqsize = get_full_path_helper(name, buffer, size);
+ if (reqsize > size)
+ {
+ LPWSTR tmp = RtlAllocateHeap(ntdll_get_process_heap(), 0, reqsize);
+ reqsize = get_full_path_helper(name, tmp, reqsize) + sizeof(WCHAR);
+ RtlFreeHeap(ntdll_get_process_heap(), 0, tmp);
+ }
+ else
+ {
+ WCHAR* ptr;
+ /* find file part */
+ if (file_part && (ptr = strrchrW(buffer, '\\')) != NULL && ptr >= buffer + 2 && *++ptr)
+ *file_part = ptr;
+ }
+ return reqsize;
+}
+
+/*************************************************************************
+ * RtlGetLongestNtPathLength [NTDLL.@]
+ *
+ * Get the longest allowed path length
+ *
+ * PARAMS
+ * None.
+ *
+ * RETURNS
+ * The longest allowed path length (277 characters under Win2k).
+ */
+DWORD WINAPI RtlGetLongestNtPathLength(void)
+{
+ TRACE("()\n");
+ return 277;
+}
+
+
More information about the wine-patches
mailing list