This part of #39 hasn't been applied, so resending for clarification. A+
Index: dlls/kernel39/path.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/kernel/path.c,v retrieving revision 1.1 diff -u -r1.1 path.c --- dlls/kernel39/path.c 15 Jan 2004 00:20:46 -0000 1.1 +++ dlls/kernel39/path.c 17 Jan 2004 20:15:57 -0000 @@ -42,6 +42,87 @@ #define MAX_PATHNAME_LEN 1024 +/*********************************************************************** + * GetFullPathNameW (KERNEL32.@) + * NOTES + * if the path closed with '\', *lastpart is 0 + */ +DWORD WINAPI GetFullPathNameW( LPCWSTR name, DWORD len, LPWSTR buffer, + LPWSTR *lastpart ) +{ + LPWSTR dst = HeapAlloc(GetProcessHeap(), 0, len * sizeof(buffer)); + DWORD ret; + + if (!dst) return 0; + ret = RtlGetFullPathName_U(name, len * sizeof(WCHAR), dst, lastpart) / sizeof(WCHAR); + if (ret < len) + { + strcpyW(buffer, dst); + if (lastpart && *lastpart) *lastpart = buffer + (*lastpart - dst); + } + HeapFree(GetProcessHeap(), 0, dst); + return ret; +} + +/*********************************************************************** + * GetFullPathNameA (KERNEL32.@) + * NOTES + * if the path closed with '\', *lastpart is 0 + */ +DWORD WINAPI GetFullPathNameA( LPCSTR name, DWORD len, LPSTR buffer, + LPSTR *lastpart ) +{ + UNICODE_STRING nameW; + WCHAR bufferW[MAX_PATH]; + DWORD ret, retW; + + if (!name) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (!RtlCreateUnicodeStringFromAsciiz(&nameW, name)) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + retW = GetFullPathNameW( nameW.Buffer, MAX_PATH, bufferW, NULL); + + if (!retW) + ret = 0; + else if (retW > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + ret = 0; + } + else + { + ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL); + if (ret && ret <= len) + { + WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, len, NULL, NULL); + ret--; /* length without 0 */ + + if (lastpart) + { + LPSTR p = buffer + strlen(buffer) - 1; + + if (*p != '\\') + { + while ((p > buffer + 2) && (*p != '\\')) p--; + *lastpart = p + 1; + } + else *lastpart = NULL; + } + } + } + + RtlFreeUnicodeString(&nameW); + return ret; +} + /*********************************************************************** * GetLongPathNameW (KERNEL32.@) Index: files39/dos_fs.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/files/dos_fs.c,v retrieving revision 1.146 diff -u -r1.146 dos_fs.c --- files39/dos_fs.c 15 Jan 2004 01:48:44 -0000 1.146 +++ files39/dos_fs.c 16 Jan 2004 19:54:59 -0000 @@ -1173,252 +1173,6 @@ /*********************************************************************** - * DOSFS_DoGetFullPathName - * - * Implementation of GetFullPathNameA/W. - * - * bon@elektron 000331: - * A test for GetFullPathName with many pathological cases - * now gives identical output for Wine and OSR2 - */ -static DWORD DOSFS_DoGetFullPathName( LPCWSTR name, DWORD len, LPWSTR result ) -{ - DWORD ret; - DOS_FULL_NAME full_name; - LPWSTR p, q; - char *p_l; - const char * root; - WCHAR drivecur[] = {'C',':','.',0}; - WCHAR driveletter=0; - int namelen,drive=0; - static const WCHAR bkslashW[] = {'\\',0}; - static const WCHAR dotW[] = {'.',0}; - static const WCHAR updir_slashW[] = {'\\','.','.','\\',0}; - static const WCHAR curdirW[] = {'\\','.','\\',0}; - static const WCHAR updirW[] = {'\\','.','.',0}; - - if (!name[0]) - { - SetLastError(ERROR_BAD_PATHNAME); - return 0; - } - - TRACE("passed %s\n", debugstr_w(name)); - - if (name[1]==':') - /*drive letter given */ - { - driveletter = name[0]; - } - if ((name[1]==':') && ((name[2]=='\\') || (name[2]=='/'))) - /*absolute path given */ - { - strncpyW(full_name.short_name, name, MAX_PATHNAME_LEN); - full_name.short_name[MAX_PATHNAME_LEN - 1] = 0; /* ensure 0 termination */ - drive = toupperW(name[0]) - 'A'; - } - else - { - if (driveletter) - drivecur[0]=driveletter; - else if ((name[0]=='\\') || (name[0]=='/')) - strcpyW(drivecur, bkslashW); - else - strcpyW(drivecur, dotW); - - if (!DOSFS_GetFullName( drivecur, FALSE, &full_name )) - { - FIXME("internal: error getting drive/path\n"); - return 0; - } - /* find path that drive letter substitutes*/ - drive = toupperW(full_name.short_name[0]) - 'A'; - root= DRIVE_GetRoot(drive); - if (!root) - { - FIXME("internal: error getting DOS Drive Root\n"); - return 0; - } - if (!strcmp(root,"/")) - { - /* we have just the last / and we need it. */ - p_l = full_name.long_name; - } - else - { - p_l = full_name.long_name + strlen(root); - } - /* append long name (= unix name) to drive */ - MultiByteToWideChar(CP_UNIXCP, 0, p_l, -1, full_name.short_name + 2, MAX_PATHNAME_LEN - 3); - /* append name to treat */ - namelen= strlenW(full_name.short_name); - p = (LPWSTR)name; - if (driveletter) - p += 2; /* skip drive name when appending */ - if (namelen + 2 + strlenW(p) > MAX_PATHNAME_LEN) - { - FIXME("internal error: buffer too small\n"); - return 0; - } - full_name.short_name[namelen++] ='\\'; - full_name.short_name[namelen] = 0; - strncpyW(full_name.short_name + namelen, p, MAX_PATHNAME_LEN - namelen); - full_name.short_name[MAX_PATHNAME_LEN - 1] = 0; /* ensure 0 termination */ - } - /* reverse all slashes */ - for (p=full_name.short_name; - p < full_name.short_name + strlenW(full_name.short_name); - p++) - { - if ( *p == '/' ) - *p = '\\'; - } - /* Use memmove, as areas overlap */ - /* Delete .. */ - while ((p = strstrW(full_name.short_name, updir_slashW))) - { - if (p > full_name.short_name+2) - { - *p = 0; - q = strrchrW(full_name.short_name, '\\'); - memmove(q+1, p+4, (strlenW(p+4)+1) * sizeof(WCHAR)); - } - else - { - memmove(full_name.short_name+3, p+4, (strlenW(p+4)+1) * sizeof(WCHAR)); - } - } - if ((full_name.short_name[2]=='.')&&(full_name.short_name[3]=='.')) - { - /* This case istn't treated yet : c:..\test */ - memmove(full_name.short_name+2,full_name.short_name+4, - (strlenW(full_name.short_name+4)+1) * sizeof(WCHAR)); - } - /* Delete . */ - while ((p = strstrW(full_name.short_name, curdirW))) - { - *(p+1) = 0; - memmove(p+1, p+3, (strlenW(p+3)+1) * sizeof(WCHAR)); - } - if (!(DRIVE_GetFlags(drive) & DRIVE_CASE_PRESERVING)) - for (p = full_name.short_name; *p; p++) *p = toupperW(*p); - namelen = strlenW(full_name.short_name); - if (!strcmpW(full_name.short_name+namelen-3, updirW)) - { - /* one more strange case: "c:\test\test1\.." - return "c:\test" */ - *(full_name.short_name+namelen-3)=0; - q = strrchrW(full_name.short_name, '\\'); - *q =0; - } - if (full_name.short_name[namelen-1]=='.') - full_name.short_name[(namelen--)-1] =0; - TRACE("got %s\n", debugstr_w(full_name.short_name)); - - /* If the lpBuffer buffer is too small, the return value is the - size of the buffer, in characters, required to hold the path - plus the terminating \0 (tested against win95osr2, bon 001118) - . */ - ret = strlenW(full_name.short_name); - if (ret >= len ) - { - /* don't touch anything when the buffer is not large enough */ - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return ret+1; - } - if (result) - { - strncpyW( result, full_name.short_name, len ); - result[len - 1] = 0; /* ensure 0 termination */ - } - - TRACE("returning %s\n", debugstr_w(full_name.short_name) ); - return ret; -} - - -/*********************************************************************** - * GetFullPathNameA (KERNEL32.@) - * NOTES - * if the path closed with '\', *lastpart is 0 - */ -DWORD WINAPI GetFullPathNameA( LPCSTR name, DWORD len, LPSTR buffer, - LPSTR *lastpart ) -{ - UNICODE_STRING nameW; - WCHAR bufferW[MAX_PATH]; - DWORD ret, retW; - - if (!name) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - if (!RtlCreateUnicodeStringFromAsciiz(&nameW, name)) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - retW = GetFullPathNameW( nameW.Buffer, MAX_PATH, bufferW, NULL); - - if (!retW) - ret = 0; - else if (retW > MAX_PATH) - { - SetLastError(ERROR_FILENAME_EXCED_RANGE); - ret = 0; - } - else - { - ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL); - if (ret <= len) - { - WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, len, NULL, NULL); - ret--; /* length without 0 */ - - if (lastpart) - { - LPSTR p = buffer + strlen(buffer) - 1; - - if (*p != '\\') - { - while ((p > buffer + 2) && (*p != '\\')) p--; - *lastpart = p + 1; - } - else *lastpart = NULL; - } - } - } - - RtlFreeUnicodeString(&nameW); - return ret; -} - - -/*********************************************************************** - * GetFullPathNameW (KERNEL32.@) - */ -DWORD WINAPI GetFullPathNameW( LPCWSTR name, DWORD len, LPWSTR buffer, - LPWSTR *lastpart ) -{ - DWORD ret = DOSFS_DoGetFullPathName( name, len, buffer ); - if (ret && (ret<=len) && buffer && lastpart) - { - LPWSTR p = buffer + strlenW(buffer) - 1; - if (*p != (WCHAR)'\\') - { - while ((p > buffer + 2) && (*p != (WCHAR)'\\')) p--; - *lastpart = p + 1; - } - else *lastpart = NULL; - } - return ret; -} - - -/*********************************************************************** * wine_get_unix_file_name (KERNEL32.@) Not a Windows API * * Return the full Unix file name for a given path.