- RtlGetFullPathName_U: rewritten so that the source & destination
buffer can be the same - GetFullPathName[AW]: now call RtlGetFullPathName_U - GetShortPathNameW: fixed regression introduced in last patch
This commit is contained in:
parent
eae9444bc8
commit
6c8ee62340
|
@ -42,6 +42,76 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
|
||||||
|
|
||||||
#define MAX_PATHNAME_LEN 1024
|
#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 )
|
||||||
|
{
|
||||||
|
return RtlGetFullPathName_U(name, len * sizeof(WCHAR), buffer, lastpart) / sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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.@)
|
* GetLongPathNameW (KERNEL32.@)
|
||||||
|
@ -266,20 +336,21 @@ DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortl
|
||||||
for (p = longpath + lp; *p && *p != '/' && *p != '\\'; p++);
|
for (p = longpath + lp; *p && *p != '/' && *p != '\\'; p++);
|
||||||
tmplen = p - (longpath + lp);
|
tmplen = p - (longpath + lp);
|
||||||
lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
|
lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
|
||||||
|
/* Check, if the current element is a valid dos name */
|
||||||
if (tmplen <= 8+1+3+1)
|
if (tmplen <= 8+1+3+1)
|
||||||
{
|
{
|
||||||
memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR));
|
memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR));
|
||||||
ustr_buf[tmplen] = '\0';
|
ustr_buf[tmplen] = '\0';
|
||||||
ustr.Length = tmplen * sizeof(WCHAR);
|
ustr.Length = tmplen * sizeof(WCHAR);
|
||||||
/* Check, if the current element is a valid dos name */
|
if (RtlIsNameLegalDOS8Dot3(&ustr, NULL, NULL))
|
||||||
if (!RtlIsNameLegalDOS8Dot3(&ustr, NULL, NULL))
|
{
|
||||||
goto notfound;
|
sp += tmplen;
|
||||||
sp += tmplen;
|
lp += tmplen;
|
||||||
lp += tmplen;
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the file exists and use the existing file name */
|
/* Check if the file exists and use the existing short file name */
|
||||||
goit = FindFirstFileW(tmpshortpath, &wfd);
|
goit = FindFirstFileW(tmpshortpath, &wfd);
|
||||||
if (goit == INVALID_HANDLE_VALUE) goto notfound;
|
if (goit == INVALID_HANDLE_VALUE) goto notfound;
|
||||||
FindClose(goit);
|
FindClose(goit);
|
||||||
|
|
|
@ -320,54 +320,49 @@ ULONG WINAPI RtlDosSearchPath_U(LPCWSTR paths, LPCWSTR search, LPCWSTR ext,
|
||||||
* get_full_path_helper
|
* get_full_path_helper
|
||||||
*
|
*
|
||||||
* Helper for RtlGetFullPathName_U
|
* Helper for RtlGetFullPathName_U
|
||||||
|
* Note: name and buffer are allowed to point to the same memory spot
|
||||||
*/
|
*/
|
||||||
static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
||||||
{
|
{
|
||||||
ULONG reqsize, mark = 0;
|
ULONG reqsize = 0, mark = 0, dep = 0, deplen;
|
||||||
DOS_PATHNAME_TYPE type;
|
DOS_PATHNAME_TYPE type;
|
||||||
LPWSTR ptr;
|
LPWSTR ptr, ins_str = NULL;
|
||||||
UNICODE_STRING* cd;
|
const UNICODE_STRING* cd;
|
||||||
|
WCHAR tmp[4];
|
||||||
reqsize = sizeof(WCHAR); /* '\0' at the end */
|
|
||||||
|
|
||||||
RtlAcquirePebLock();
|
RtlAcquirePebLock();
|
||||||
|
|
||||||
cd = &ntdll_get_process_pmts()->CurrentDirectoryName;
|
cd = &ntdll_get_process_pmts()->CurrentDirectoryName;
|
||||||
|
|
||||||
switch (type = RtlDetermineDosPathNameType_U(name))
|
switch (type = RtlDetermineDosPathNameType_U(name))
|
||||||
{
|
{
|
||||||
case UNC_PATH: /* \\foo */
|
case UNC_PATH: /* \\foo */
|
||||||
case DEVICE_PATH: /* \\.\foo */
|
case DEVICE_PATH: /* \\.\foo */
|
||||||
if (reqsize <= size) buffer[0] = '\0';
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ABSOLUTE_DRIVE_PATH: /* c:\foo */
|
case ABSOLUTE_DRIVE_PATH: /* c:\foo */
|
||||||
reqsize += sizeof(WCHAR);
|
reqsize = sizeof(WCHAR);
|
||||||
if (reqsize <= size)
|
tmp[0] = toupperW(name[0]);
|
||||||
{
|
ins_str = tmp;
|
||||||
buffer[0] = toupperW(name[0]);
|
dep = 1;
|
||||||
buffer[1] = '\0';
|
|
||||||
}
|
|
||||||
name++;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RELATIVE_DRIVE_PATH: /* c:foo */
|
case RELATIVE_DRIVE_PATH: /* c:foo */
|
||||||
|
dep = 2;
|
||||||
if (toupperW(name[0]) != toupperW(cd->Buffer[0]) || cd->Buffer[1] != ':')
|
if (toupperW(name[0]) != toupperW(cd->Buffer[0]) || cd->Buffer[1] != ':')
|
||||||
{
|
{
|
||||||
WCHAR drive[4];
|
|
||||||
UNICODE_STRING var, val;
|
UNICODE_STRING var, val;
|
||||||
|
|
||||||
drive[0] = '=';
|
tmp[0] = '=';
|
||||||
drive[1] = name[0];
|
tmp[1] = name[0];
|
||||||
drive[2] = ':';
|
tmp[2] = ':';
|
||||||
drive[3] = '\0';
|
tmp[3] = '\0';
|
||||||
var.Length = 6;
|
var.Length = 3 * sizeof(WCHAR);
|
||||||
var.MaximumLength = 8;
|
var.MaximumLength = 4 * sizeof(WCHAR);
|
||||||
var.Buffer = drive;
|
var.Buffer = tmp;
|
||||||
val.Length = 0;
|
val.Length = 0;
|
||||||
val.MaximumLength = size;
|
val.MaximumLength = size;
|
||||||
val.Buffer = buffer;
|
val.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, size);
|
||||||
|
|
||||||
name += 2;
|
|
||||||
|
|
||||||
switch (RtlQueryEnvironmentVariable_U(NULL, &var, &val))
|
switch (RtlQueryEnvironmentVariable_U(NULL, &var, &val))
|
||||||
{
|
{
|
||||||
|
@ -379,24 +374,16 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
||||||
*/
|
*/
|
||||||
/* fall thru */
|
/* fall thru */
|
||||||
case STATUS_BUFFER_TOO_SMALL:
|
case STATUS_BUFFER_TOO_SMALL:
|
||||||
reqsize += val.Length;
|
reqsize = val.Length + sizeof(WCHAR); /* append trailing '\\' */
|
||||||
/* append trailing \\ */
|
val.Buffer[val.Length / sizeof(WCHAR)] = '\\';
|
||||||
reqsize += sizeof(WCHAR);
|
ins_str = val.Buffer;
|
||||||
if (reqsize <= size)
|
|
||||||
{
|
|
||||||
buffer[reqsize / sizeof(WCHAR) - 2] = '\\';
|
|
||||||
buffer[reqsize / sizeof(WCHAR) - 1] = '\0';
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case STATUS_VARIABLE_NOT_FOUND:
|
case STATUS_VARIABLE_NOT_FOUND:
|
||||||
reqsize += 3 * sizeof(WCHAR);
|
reqsize = 3 * sizeof(WCHAR);
|
||||||
if (reqsize <= size)
|
tmp[0] = name[0];
|
||||||
{
|
tmp[1] = ':';
|
||||||
buffer[0] = drive[1];
|
tmp[2] = '\\';
|
||||||
buffer[1] = ':';
|
ins_str = tmp;
|
||||||
buffer[2] = '\\';
|
|
||||||
buffer[3] = '\0';
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERR("Unsupported status code\n");
|
ERR("Unsupported status code\n");
|
||||||
|
@ -404,16 +391,11 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
name += 2;
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case RELATIVE_PATH: /* foo */
|
case RELATIVE_PATH: /* foo */
|
||||||
reqsize += cd->Length;
|
reqsize = cd->Length;
|
||||||
if (reqsize <= size)
|
ins_str = cd->Buffer;
|
||||||
{
|
|
||||||
memcpy(buffer, cd->Buffer, cd->Length);
|
|
||||||
buffer[cd->Length / sizeof(WCHAR)] = 0;
|
|
||||||
}
|
|
||||||
if (cd->Buffer[1] != ':')
|
if (cd->Buffer[1] != ':')
|
||||||
{
|
{
|
||||||
ptr = strchrW(cd->Buffer + 2, '\\');
|
ptr = strchrW(cd->Buffer + 2, '\\');
|
||||||
|
@ -426,69 +408,62 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
||||||
case ABSOLUTE_PATH: /* \xxx */
|
case ABSOLUTE_PATH: /* \xxx */
|
||||||
if (cd->Buffer[1] == ':')
|
if (cd->Buffer[1] == ':')
|
||||||
{
|
{
|
||||||
reqsize += 2 * sizeof(WCHAR);
|
reqsize = 2 * sizeof(WCHAR);
|
||||||
if (reqsize <= size)
|
tmp[0] = cd->Buffer[0];
|
||||||
{
|
tmp[1] = ':';
|
||||||
buffer[0] = cd->Buffer[0];
|
ins_str = tmp;
|
||||||
buffer[1] = ':';
|
|
||||||
buffer[2] = '\0';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned len;
|
|
||||||
|
|
||||||
ptr = strchrW(cd->Buffer + 2, '\\');
|
ptr = strchrW(cd->Buffer + 2, '\\');
|
||||||
if (ptr) ptr = strchrW(ptr + 1, '\\');
|
if (ptr) ptr = strchrW(ptr + 1, '\\');
|
||||||
if (!ptr) ptr = cd->Buffer + strlenW(cd->Buffer);
|
if (!ptr) ptr = cd->Buffer + strlenW(cd->Buffer);
|
||||||
len = (ptr - cd->Buffer) * sizeof(WCHAR);
|
reqsize = (ptr - cd->Buffer) * sizeof(WCHAR);
|
||||||
reqsize += len;
|
mark = reqsize / sizeof(WCHAR);
|
||||||
mark = len / sizeof(WCHAR);
|
ins_str = cd->Buffer;
|
||||||
if (reqsize <= size)
|
|
||||||
{
|
|
||||||
memcpy(buffer, cd->Buffer, len);
|
|
||||||
buffer[len / sizeof(WCHAR)] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buffer[0] = '\0';
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNC_DOT_PATH: /* \\. */
|
case UNC_DOT_PATH: /* \\. */
|
||||||
reqsize += 4 * sizeof(WCHAR);
|
reqsize = 4 * sizeof(WCHAR);
|
||||||
name += 3;
|
dep = 3;
|
||||||
if (reqsize <= size)
|
tmp[0] = '\\';
|
||||||
{
|
tmp[1] = '\\';
|
||||||
buffer[0] = '\\';
|
tmp[2] = '.';
|
||||||
buffer[1] = '\\';
|
tmp[3] = '\\';
|
||||||
buffer[2] = '.';
|
ins_str = tmp;
|
||||||
buffer[3] = '\\';
|
|
||||||
buffer[4] = '\0';
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INVALID_PATH:
|
case INVALID_PATH:
|
||||||
reqsize = 0;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
reqsize += strlenW(name) * sizeof(WCHAR);
|
/* enough space ? */
|
||||||
if (reqsize > size) goto done;
|
deplen = strlenW(name + dep) * sizeof(WCHAR);
|
||||||
|
if (reqsize + deplen + sizeof(WCHAR) > size)
|
||||||
|
{
|
||||||
|
/* not enough space, return need size (including terminating '\0') */
|
||||||
|
reqsize += deplen + sizeof(WCHAR);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
strcatW(buffer, name);
|
memmove(buffer + reqsize / sizeof(WCHAR), name + dep, deplen + sizeof(WCHAR));
|
||||||
|
if (reqsize) memcpy(buffer, ins_str, reqsize);
|
||||||
|
reqsize += deplen;
|
||||||
|
|
||||||
|
if (ins_str && ins_str != tmp && ins_str != cd->Buffer)
|
||||||
|
RtlFreeHeap(GetProcessHeap(), 0, ins_str);
|
||||||
|
|
||||||
/* convert every / into a \ */
|
/* convert every / into a \ */
|
||||||
for (ptr = buffer; *ptr; ptr++)
|
for (ptr = buffer; *ptr; ptr++) if (*ptr == '/') *ptr = '\\';
|
||||||
if (*ptr == '/') *ptr = '\\';
|
|
||||||
|
|
||||||
reqsize -= sizeof(WCHAR); /* don't count trailing \0 */
|
|
||||||
|
|
||||||
/* mark is non NULL for UNC names, so start path collapsing after server & share name
|
/* mark is non NULL for UNC names, so start path collapsing after server & share name
|
||||||
* otherwise, it's a fully qualified DOS name, so start after the drive designation
|
* otherwise, it's a fully qualified DOS name, so start after the drive designation
|
||||||
*/
|
*/
|
||||||
for (ptr = buffer + (mark ? mark : 2); ptr < buffer + reqsize / sizeof(WCHAR); )
|
for (ptr = buffer + (mark ? mark : 2); ptr < buffer + reqsize / sizeof(WCHAR); )
|
||||||
{
|
{
|
||||||
WCHAR* p = strchrW(ptr, '\\');
|
LPWSTR prev, p = strchrW(ptr, '\\');
|
||||||
|
|
||||||
if (!p) break;
|
if (!p) break;
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
|
@ -500,15 +475,13 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
||||||
switch (p[2])
|
switch (p[2])
|
||||||
{
|
{
|
||||||
case '\\':
|
case '\\':
|
||||||
{
|
prev = p - 2;
|
||||||
WCHAR* prev = p - 2;
|
while (prev >= buffer + mark && *prev != '\\') prev--;
|
||||||
while (prev >= buffer + mark && *prev != '\\') prev--;
|
/* either collapse \foo\.. into \ or \.. into \ */
|
||||||
/* either collapse \foo\.. into \ or \.. into \ */
|
if (prev < buffer + mark) prev = p - 1;
|
||||||
if (prev < buffer + mark) prev = p - 1;
|
reqsize -= (p + 2 - prev) * sizeof(WCHAR);
|
||||||
reqsize -= (p + 2 - prev) * sizeof(WCHAR);
|
memmove(prev, p + 2, reqsize + sizeof(WCHAR) - (prev - buffer) * sizeof(WCHAR));
|
||||||
memmove(prev, p + 2, reqsize + sizeof(WCHAR) - (prev - buffer) * sizeof(WCHAR));
|
p = prev;
|
||||||
p = prev;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case '\0':
|
case '\0':
|
||||||
reqsize -= 2 * sizeof(WCHAR);
|
reqsize -= 2 * sizeof(WCHAR);
|
||||||
|
|
246
files/dos_fs.c
246
files/dos_fs.c
|
@ -1172,252 +1172,6 @@ BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last, DOS_FULL_NAME *full )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* 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
|
* wine_get_unix_file_name (KERNEL32.@) Not a Windows API
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue