- 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
|
||||
|
||||
/***********************************************************************
|
||||
* 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.@)
|
||||
|
@ -266,20 +336,21 @@ DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortl
|
|||
for (p = longpath + lp; *p && *p != '/' && *p != '\\'; p++);
|
||||
tmplen = p - (longpath + lp);
|
||||
lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
|
||||
/* Check, if the current element is a valid dos name */
|
||||
if (tmplen <= 8+1+3+1)
|
||||
{
|
||||
memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR));
|
||||
ustr_buf[tmplen] = '\0';
|
||||
ustr.Length = tmplen * sizeof(WCHAR);
|
||||
/* Check, if the current element is a valid dos name */
|
||||
if (!RtlIsNameLegalDOS8Dot3(&ustr, NULL, NULL))
|
||||
goto notfound;
|
||||
sp += tmplen;
|
||||
lp += tmplen;
|
||||
continue;
|
||||
if (RtlIsNameLegalDOS8Dot3(&ustr, NULL, NULL))
|
||||
{
|
||||
sp += tmplen;
|
||||
lp += tmplen;
|
||||
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);
|
||||
if (goit == INVALID_HANDLE_VALUE) goto notfound;
|
||||
FindClose(goit);
|
||||
|
|
|
@ -320,54 +320,49 @@ ULONG WINAPI RtlDosSearchPath_U(LPCWSTR paths, LPCWSTR search, LPCWSTR ext,
|
|||
* get_full_path_helper
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
ULONG reqsize, mark = 0;
|
||||
DOS_PATHNAME_TYPE type;
|
||||
LPWSTR ptr;
|
||||
UNICODE_STRING* cd;
|
||||
|
||||
reqsize = sizeof(WCHAR); /* '\0' at the end */
|
||||
|
||||
ULONG reqsize = 0, mark = 0, dep = 0, deplen;
|
||||
DOS_PATHNAME_TYPE type;
|
||||
LPWSTR ptr, ins_str = NULL;
|
||||
const UNICODE_STRING* cd;
|
||||
WCHAR tmp[4];
|
||||
|
||||
RtlAcquirePebLock();
|
||||
|
||||
cd = &ntdll_get_process_pmts()->CurrentDirectoryName;
|
||||
|
||||
switch (type = RtlDetermineDosPathNameType_U(name))
|
||||
{
|
||||
case UNC_PATH: /* \\foo */
|
||||
case DEVICE_PATH: /* \\.\foo */
|
||||
if (reqsize <= size) buffer[0] = '\0';
|
||||
break;
|
||||
|
||||
case ABSOLUTE_DRIVE_PATH: /* c:\foo */
|
||||
reqsize += sizeof(WCHAR);
|
||||
if (reqsize <= size)
|
||||
{
|
||||
buffer[0] = toupperW(name[0]);
|
||||
buffer[1] = '\0';
|
||||
}
|
||||
name++;
|
||||
reqsize = sizeof(WCHAR);
|
||||
tmp[0] = toupperW(name[0]);
|
||||
ins_str = tmp;
|
||||
dep = 1;
|
||||
break;
|
||||
|
||||
case RELATIVE_DRIVE_PATH: /* c:foo */
|
||||
dep = 2;
|
||||
if (toupperW(name[0]) != toupperW(cd->Buffer[0]) || cd->Buffer[1] != ':')
|
||||
{
|
||||
WCHAR drive[4];
|
||||
UNICODE_STRING var, val;
|
||||
|
||||
drive[0] = '=';
|
||||
drive[1] = name[0];
|
||||
drive[2] = ':';
|
||||
drive[3] = '\0';
|
||||
var.Length = 6;
|
||||
var.MaximumLength = 8;
|
||||
var.Buffer = drive;
|
||||
tmp[0] = '=';
|
||||
tmp[1] = name[0];
|
||||
tmp[2] = ':';
|
||||
tmp[3] = '\0';
|
||||
var.Length = 3 * sizeof(WCHAR);
|
||||
var.MaximumLength = 4 * sizeof(WCHAR);
|
||||
var.Buffer = tmp;
|
||||
val.Length = 0;
|
||||
val.MaximumLength = size;
|
||||
val.Buffer = buffer;
|
||||
|
||||
name += 2;
|
||||
val.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, size);
|
||||
|
||||
switch (RtlQueryEnvironmentVariable_U(NULL, &var, &val))
|
||||
{
|
||||
|
@ -379,24 +374,16 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
|||
*/
|
||||
/* fall thru */
|
||||
case STATUS_BUFFER_TOO_SMALL:
|
||||
reqsize += val.Length;
|
||||
/* append trailing \\ */
|
||||
reqsize += sizeof(WCHAR);
|
||||
if (reqsize <= size)
|
||||
{
|
||||
buffer[reqsize / sizeof(WCHAR) - 2] = '\\';
|
||||
buffer[reqsize / sizeof(WCHAR) - 1] = '\0';
|
||||
}
|
||||
reqsize = val.Length + sizeof(WCHAR); /* append trailing '\\' */
|
||||
val.Buffer[val.Length / sizeof(WCHAR)] = '\\';
|
||||
ins_str = val.Buffer;
|
||||
break;
|
||||
case STATUS_VARIABLE_NOT_FOUND:
|
||||
reqsize += 3 * sizeof(WCHAR);
|
||||
if (reqsize <= size)
|
||||
{
|
||||
buffer[0] = drive[1];
|
||||
buffer[1] = ':';
|
||||
buffer[2] = '\\';
|
||||
buffer[3] = '\0';
|
||||
}
|
||||
reqsize = 3 * sizeof(WCHAR);
|
||||
tmp[0] = name[0];
|
||||
tmp[1] = ':';
|
||||
tmp[2] = '\\';
|
||||
ins_str = tmp;
|
||||
break;
|
||||
default:
|
||||
ERR("Unsupported status code\n");
|
||||
|
@ -404,16 +391,11 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
|||
}
|
||||
break;
|
||||
}
|
||||
name += 2;
|
||||
/* fall through */
|
||||
|
||||
case RELATIVE_PATH: /* foo */
|
||||
reqsize += cd->Length;
|
||||
if (reqsize <= size)
|
||||
{
|
||||
memcpy(buffer, cd->Buffer, cd->Length);
|
||||
buffer[cd->Length / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
reqsize = cd->Length;
|
||||
ins_str = cd->Buffer;
|
||||
if (cd->Buffer[1] != ':')
|
||||
{
|
||||
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 */
|
||||
if (cd->Buffer[1] == ':')
|
||||
{
|
||||
reqsize += 2 * sizeof(WCHAR);
|
||||
if (reqsize <= size)
|
||||
{
|
||||
buffer[0] = cd->Buffer[0];
|
||||
buffer[1] = ':';
|
||||
buffer[2] = '\0';
|
||||
}
|
||||
reqsize = 2 * sizeof(WCHAR);
|
||||
tmp[0] = cd->Buffer[0];
|
||||
tmp[1] = ':';
|
||||
ins_str = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
ptr = strchrW(cd->Buffer + 2, '\\');
|
||||
if (ptr) ptr = strchrW(ptr + 1, '\\');
|
||||
if (!ptr) ptr = cd->Buffer + strlenW(cd->Buffer);
|
||||
len = (ptr - cd->Buffer) * sizeof(WCHAR);
|
||||
reqsize += len;
|
||||
mark = len / sizeof(WCHAR);
|
||||
if (reqsize <= size)
|
||||
{
|
||||
memcpy(buffer, cd->Buffer, len);
|
||||
buffer[len / sizeof(WCHAR)] = '\0';
|
||||
}
|
||||
else
|
||||
buffer[0] = '\0';
|
||||
reqsize = (ptr - cd->Buffer) * sizeof(WCHAR);
|
||||
mark = reqsize / sizeof(WCHAR);
|
||||
ins_str = cd->Buffer;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNC_DOT_PATH: /* \\. */
|
||||
reqsize += 4 * sizeof(WCHAR);
|
||||
name += 3;
|
||||
if (reqsize <= size)
|
||||
{
|
||||
buffer[0] = '\\';
|
||||
buffer[1] = '\\';
|
||||
buffer[2] = '.';
|
||||
buffer[3] = '\\';
|
||||
buffer[4] = '\0';
|
||||
}
|
||||
reqsize = 4 * sizeof(WCHAR);
|
||||
dep = 3;
|
||||
tmp[0] = '\\';
|
||||
tmp[1] = '\\';
|
||||
tmp[2] = '.';
|
||||
tmp[3] = '\\';
|
||||
ins_str = tmp;
|
||||
break;
|
||||
|
||||
case INVALID_PATH:
|
||||
reqsize = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
reqsize += strlenW(name) * sizeof(WCHAR);
|
||||
if (reqsize > size) goto done;
|
||||
/* enough space ? */
|
||||
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 \ */
|
||||
for (ptr = buffer; *ptr; ptr++)
|
||||
if (*ptr == '/') *ptr = '\\';
|
||||
|
||||
reqsize -= sizeof(WCHAR); /* don't count trailing \0 */
|
||||
for (ptr = buffer; *ptr; ptr++) if (*ptr == '/') *ptr = '\\';
|
||||
|
||||
/* 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
|
||||
*/
|
||||
for (ptr = buffer + (mark ? mark : 2); ptr < buffer + reqsize / sizeof(WCHAR); )
|
||||
{
|
||||
WCHAR* p = strchrW(ptr, '\\');
|
||||
LPWSTR prev, p = strchrW(ptr, '\\');
|
||||
|
||||
if (!p) break;
|
||||
|
||||
p++;
|
||||
|
@ -500,15 +475,13 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
|||
switch (p[2])
|
||||
{
|
||||
case '\\':
|
||||
{
|
||||
WCHAR* prev = p - 2;
|
||||
while (prev >= buffer + mark && *prev != '\\') prev--;
|
||||
/* either collapse \foo\.. into \ or \.. into \ */
|
||||
if (prev < buffer + mark) prev = p - 1;
|
||||
reqsize -= (p + 2 - prev) * sizeof(WCHAR);
|
||||
memmove(prev, p + 2, reqsize + sizeof(WCHAR) - (prev - buffer) * sizeof(WCHAR));
|
||||
p = prev;
|
||||
}
|
||||
prev = p - 2;
|
||||
while (prev >= buffer + mark && *prev != '\\') prev--;
|
||||
/* either collapse \foo\.. into \ or \.. into \ */
|
||||
if (prev < buffer + mark) prev = p - 1;
|
||||
reqsize -= (p + 2 - prev) * sizeof(WCHAR);
|
||||
memmove(prev, p + 2, reqsize + sizeof(WCHAR) - (prev - buffer) * sizeof(WCHAR));
|
||||
p = prev;
|
||||
break;
|
||||
case '\0':
|
||||
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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue