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