starting with the file APIs... this patch implements a few helper functions A+ -- Eric Pouech
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; +} + +