mirror of
https://github.com/reactos/reactos.git
synced 2025-05-21 10:05:35 +00:00
- Reverted to previous version of RtlGetFullPathName_U
- Fixed GetFullPathNameA svn path=/trunk/; revision=6373
This commit is contained in:
parent
0802d5a7f3
commit
b73b1eaf89
2 changed files with 312 additions and 303 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: dir.c,v 1.37 2003/07/10 18:50:51 chorns Exp $
|
/* $Id: dir.c,v 1.38 2003/10/19 16:17:50 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -336,67 +336,67 @@ GetFullPathNameA (
|
||||||
LPSTR *lpFilePart
|
LPSTR *lpFilePart
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UNICODE_STRING FileNameU;
|
UNICODE_STRING nameW;
|
||||||
UNICODE_STRING FullNameU;
|
WCHAR bufferW[MAX_PATH];
|
||||||
ANSI_STRING FileName;
|
DWORD ret, retW;
|
||||||
ANSI_STRING FullName;
|
|
||||||
PWSTR FilePartU;
|
|
||||||
ULONG BufferLength;
|
|
||||||
ULONG Offset;
|
|
||||||
DWORD FullNameLen;
|
|
||||||
|
|
||||||
DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
|
DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
|
||||||
"lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
|
"lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
|
||||||
|
|
||||||
RtlInitAnsiString (&FileName,
|
if (!lpFileName)
|
||||||
(LPSTR)lpFileName);
|
|
||||||
|
|
||||||
RtlAnsiStringToUnicodeString (&FileNameU,
|
|
||||||
&FileName,
|
|
||||||
TRUE);
|
|
||||||
|
|
||||||
BufferLength = nBufferLength * sizeof(WCHAR);
|
|
||||||
|
|
||||||
FullNameU.MaximumLength = BufferLength;
|
|
||||||
FullNameU.Length = 0;
|
|
||||||
FullNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
|
|
||||||
0,
|
|
||||||
BufferLength);
|
|
||||||
|
|
||||||
FullNameU.Length = RtlGetFullPathName_U (FileNameU.Buffer,
|
|
||||||
BufferLength,
|
|
||||||
FullNameU.Buffer,
|
|
||||||
&FilePartU);
|
|
||||||
|
|
||||||
RtlFreeUnicodeString (&FileNameU);
|
|
||||||
|
|
||||||
FullName.MaximumLength = nBufferLength;
|
|
||||||
FullName.Length = 0;
|
|
||||||
FullName.Buffer = lpBuffer;
|
|
||||||
|
|
||||||
if (lpBuffer != NULL )
|
|
||||||
{
|
{
|
||||||
RtlUnicodeStringToAnsiString (&FullName,
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
&FullNameU,
|
return 0;
|
||||||
FALSE);
|
}
|
||||||
|
|
||||||
if (lpFilePart != NULL)
|
if (!RtlCreateUnicodeStringFromAsciiz(&nameW, (LPSTR)lpFileName))
|
||||||
|
{
|
||||||
|
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 <= nBufferLength)
|
||||||
{
|
{
|
||||||
Offset = (ULONG)(FilePartU - FullNameU.Buffer);
|
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpBuffer, nBufferLength, NULL, NULL);
|
||||||
*lpFilePart = FullName.Buffer + Offset;
|
ret--; /* length without 0 */
|
||||||
|
|
||||||
|
if (lpFilePart)
|
||||||
|
{
|
||||||
|
LPSTR p = lpBuffer + strlen(lpBuffer);
|
||||||
|
|
||||||
|
if (*p != '\\')
|
||||||
|
{
|
||||||
|
while ((p > lpBuffer + 2) && (*p != '\\')) p--;
|
||||||
|
*lpFilePart = p + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*lpFilePart = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FullNameLen = FullNameU.Length / sizeof(WCHAR);
|
RtlFreeUnicodeString(&nameW);
|
||||||
|
|
||||||
RtlFreeHeap (RtlGetProcessHeap (),
|
|
||||||
0,
|
|
||||||
FullNameU.Buffer);
|
|
||||||
|
|
||||||
DPRINT("lpBuffer %s lpFilePart %s Length %ld\n",
|
DPRINT("lpBuffer %s lpFilePart %s Length %ld\n",
|
||||||
lpBuffer, lpFilePart, FullName.Length);
|
lpBuffer, lpFilePart, nameW.Length);
|
||||||
|
|
||||||
return FullNameLen;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: path.c,v 1.22 2003/10/18 20:32:58 navaraf Exp $
|
/* $Id: path.c,v 1.23 2003/10/19 16:17:50 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -16,7 +16,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <ddk/obfuncs.h>
|
#include <ddk/obfuncs.h>
|
||||||
#include <ntos/rtl.h>
|
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <ntdll/ntdll.h>
|
#include <ntdll/ntdll.h>
|
||||||
|
@ -80,6 +79,89 @@ static const UNICODE_STRING _nul =
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
static ULONG RtlpGetDotSequence (PWSTR p)
|
||||||
|
{
|
||||||
|
ULONG Count = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (*p == '.')
|
||||||
|
Count++;
|
||||||
|
else if ((*p == '\\' || *p == '\0') && Count)
|
||||||
|
return Count;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VOID RtlpEatPath (PWSTR Path)
|
||||||
|
{
|
||||||
|
PWSTR p, prev;
|
||||||
|
|
||||||
|
p = Path + 2;
|
||||||
|
prev = p;
|
||||||
|
|
||||||
|
while ((*p) != 0 || ((*p) == L'\\' && (*(p+1)) == 0))
|
||||||
|
{
|
||||||
|
ULONG DotLen;
|
||||||
|
|
||||||
|
DotLen = RtlpGetDotSequence (p+1);
|
||||||
|
DPRINT("DotSequenceLength %u\n", DotLen);
|
||||||
|
DPRINT("prev '%S' p '%S'\n",prev,p);
|
||||||
|
|
||||||
|
if (DotLen == 0)
|
||||||
|
{
|
||||||
|
prev = p;
|
||||||
|
p = wcschr(p + 1, L'\\');
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DotLen == 1)
|
||||||
|
{
|
||||||
|
wcscpy (p, p+2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (DotLen > 2)
|
||||||
|
{
|
||||||
|
int n = DotLen - 2;
|
||||||
|
|
||||||
|
while (n > 0 && prev > (Path + 2))
|
||||||
|
{
|
||||||
|
prev--;
|
||||||
|
if ((*prev) == L'\\')
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*(p + DotLen + 1) == 0)
|
||||||
|
*(prev + 1) = 0;
|
||||||
|
else
|
||||||
|
wcscpy (prev, p + DotLen + 1);
|
||||||
|
p = prev;
|
||||||
|
if (prev > (Path + 2))
|
||||||
|
{
|
||||||
|
prev--;
|
||||||
|
while ((*prev) != L'\\')
|
||||||
|
{
|
||||||
|
prev--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Path[2] == 0)
|
||||||
|
{
|
||||||
|
Path[2] = L'\\';
|
||||||
|
Path[3] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -452,272 +534,199 @@ RtlSetCurrentDirectory_U(PUNICODE_STRING name)
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* get_full_path_helper
|
|
||||||
*
|
|
||||||
* Helper for RtlGetFullPathName_U
|
|
||||||
*/
|
|
||||||
static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
|
|
||||||
{
|
|
||||||
ULONG reqsize, mark = 0;
|
|
||||||
/*DOS_PATHNAME_TYPE*/INT type;
|
|
||||||
LPWSTR ptr;
|
|
||||||
UNICODE_STRING* cd;
|
|
||||||
|
|
||||||
reqsize = sizeof(WCHAR); /* '\0' at the end */
|
|
||||||
|
|
||||||
RtlAcquirePebLock();
|
|
||||||
cd = &NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName;
|
|
||||||
|
|
||||||
switch (type = RtlDetermineDosPathNameType_U((LPWSTR)name))
|
|
||||||
{
|
|
||||||
case 1 /*UNC_PATH*/: /* \\foo */
|
|
||||||
case 6 /*DEVICE_PATH*/: /* \\.\foo */
|
|
||||||
if (reqsize <= size) buffer[0] = '\0';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2 /*ABSOLUTE_DRIVE_PATH*/: /* c:\foo */
|
|
||||||
reqsize += sizeof(WCHAR);
|
|
||||||
if (reqsize <= size)
|
|
||||||
{
|
|
||||||
buffer[0] = RtlUpcaseUnicodeChar(name[0]);
|
|
||||||
buffer[1] = '\0';
|
|
||||||
}
|
|
||||||
name++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3 /*RELATIVE_DRIVE_PATH*/: /* c:foo */
|
|
||||||
if (RtlUpcaseUnicodeChar(name[0]) != RtlUpcaseUnicodeChar(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;
|
|
||||||
val.Length = 0;
|
|
||||||
val.MaximumLength = size;
|
|
||||||
val.Buffer = buffer;
|
|
||||||
|
|
||||||
name += 2;
|
|
||||||
|
|
||||||
switch (RtlQueryEnvironmentVariable_U(NULL, &var, &val))
|
|
||||||
{
|
|
||||||
case STATUS_SUCCESS:
|
|
||||||
/* FIXME: Win2k seems to check that the environment variable actually points
|
|
||||||
* to an existing directory. If not, root of the drive is used
|
|
||||||
* (this seems also to be the only spot in RtlGetFullPathName that the
|
|
||||||
* existence of a part of a path is checked)
|
|
||||||
*/
|
|
||||||
/* 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';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATUS_VARIABLE_NOT_FOUND:
|
|
||||||
reqsize += 3 * sizeof(WCHAR);
|
|
||||||
if (reqsize <= size)
|
|
||||||
{
|
|
||||||
buffer[0] = drive[1];
|
|
||||||
buffer[1] = ':';
|
|
||||||
buffer[2] = '\\';
|
|
||||||
buffer[3] = '\0';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DPRINT("Unsupported status code\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
name += 2;
|
|
||||||
/* fall through */
|
|
||||||
|
|
||||||
case 5 /*RELATIVE_PATH*/: /* foo */
|
|
||||||
reqsize += cd->Length;
|
|
||||||
if (reqsize <= size)
|
|
||||||
{
|
|
||||||
memcpy(buffer, cd->Buffer, cd->Length);
|
|
||||||
buffer[cd->Length / sizeof(WCHAR)] = 0;
|
|
||||||
}
|
|
||||||
if (cd->Buffer[1] != ':')
|
|
||||||
{
|
|
||||||
ptr = wcsrchr(cd->Buffer + 2, '\\');
|
|
||||||
if (ptr) ptr = wcsrchr(ptr + 1, '\\');
|
|
||||||
if (!ptr) ptr = cd->Buffer + wcslen(cd->Buffer);
|
|
||||||
mark = ptr - cd->Buffer;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4 /*ABSOLUTE_PATH*/: /* \xxx */
|
|
||||||
if (cd->Buffer[1] == ':')
|
|
||||||
{
|
|
||||||
reqsize += 2 * sizeof(WCHAR);
|
|
||||||
if (reqsize <= size)
|
|
||||||
{
|
|
||||||
buffer[0] = cd->Buffer[0];
|
|
||||||
buffer[1] = ':';
|
|
||||||
buffer[2] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned len;
|
|
||||||
|
|
||||||
ptr = wcsrchr(cd->Buffer + 2, '\\');
|
|
||||||
if (ptr) ptr = wcsrchr(ptr + 1, '\\');
|
|
||||||
if (!ptr) ptr = cd->Buffer + wcslen(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';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 7 /*UNC_DOT_PATH*/: /* \\. */
|
|
||||||
reqsize += 4 * sizeof(WCHAR);
|
|
||||||
name += 3;
|
|
||||||
if (reqsize <= size)
|
|
||||||
{
|
|
||||||
buffer[0] = '\\';
|
|
||||||
buffer[1] = '\\';
|
|
||||||
buffer[2] = '.';
|
|
||||||
buffer[3] = '\\';
|
|
||||||
buffer[4] = '\0';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0 /*INVALID_PATH*/:
|
|
||||||
reqsize = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
reqsize += wcslen(name) * sizeof(WCHAR);
|
|
||||||
if (reqsize > size) goto done;
|
|
||||||
|
|
||||||
wcscat(buffer, name);
|
|
||||||
|
|
||||||
/* convert every / into a \ */
|
|
||||||
for (ptr = buffer; ptr < buffer + size / sizeof(WCHAR); 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
|
|
||||||
* 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 = wcsrchr(ptr, '\\');
|
|
||||||
if (!p) break;
|
|
||||||
|
|
||||||
p++;
|
|
||||||
if (p[0] == '.')
|
|
||||||
{
|
|
||||||
switch (p[1])
|
|
||||||
{
|
|
||||||
case '.':
|
|
||||||
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, buffer + reqsize - prev + sizeof(WCHAR));
|
|
||||||
p = prev;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '\0':
|
|
||||||
reqsize -= 2 * sizeof(WCHAR);
|
|
||||||
*p = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
reqsize -= 2 * sizeof(WCHAR);
|
|
||||||
memmove(ptr, ptr + 2, buffer + reqsize - ptr + sizeof(WCHAR));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ptr = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
RtlReleasePebLock();
|
|
||||||
return reqsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL RtlGetFullPathName_U(WCHAR* name, ULONG size, WCHAR* buffer,
|
ULONG STDCALL
|
||||||
WCHAR** file_part)
|
RtlGetFullPathName_U(PWSTR DosName,
|
||||||
|
ULONG size,
|
||||||
|
PWSTR buf,
|
||||||
|
PWSTR *FilePart)
|
||||||
{
|
{
|
||||||
WCHAR* ptr;
|
WCHAR *wcs, var[4], drive;
|
||||||
DWORD dosdev;
|
ULONG len;
|
||||||
DWORD reqsize;
|
ULONG templen = 0;
|
||||||
|
DWORD offs, sz, type;
|
||||||
|
UNICODE_STRING usvar, pfx;
|
||||||
|
PCURDIR cd;
|
||||||
|
NTSTATUS Status;
|
||||||
|
WCHAR TempFullPathName[MAX_PATH] = L"";
|
||||||
|
|
||||||
DPRINT("(%s %lu %p %p)\n", name, size, buffer, file_part);
|
DPRINT("RtlGetFullPathName_U %S %ld %p %p\n",
|
||||||
|
DosName, size, buf, FilePart);
|
||||||
|
|
||||||
if (!name || !*name) return 0;
|
if (!DosName || !*DosName)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (file_part) *file_part = NULL;
|
len = wcslen (DosName);
|
||||||
|
|
||||||
/* check for DOS device name */
|
/* strip trailing spaces */
|
||||||
dosdev = RtlIsDosDeviceName_U((WCHAR *)name);
|
while (len && DosName[len - 1] == L' ')
|
||||||
if (dosdev)
|
len--;
|
||||||
{
|
if (!len)
|
||||||
DWORD offset = ((dosdev & 0xffff0000) >> 16) / sizeof(WCHAR); /* get it in WCHARs, not bytes */
|
return 0;
|
||||||
DWORD sz = dosdev & 0xffff; /* in bytes */
|
|
||||||
|
/* strip trailing path separator (but don't change '\') */
|
||||||
|
if ((len > 1) &&
|
||||||
|
IS_PATH_SEPARATOR(DosName[len - 1]))
|
||||||
|
len--;
|
||||||
|
if (FilePart)
|
||||||
|
*FilePart = NULL;
|
||||||
|
*buf = 0;
|
||||||
|
|
||||||
if (8 + sz + 2 > size) return sz + 10;
|
CHECKPOINT;
|
||||||
wcscpy(buffer, L"\\\\.\\");
|
/* check for DOS device name */
|
||||||
memmove(buffer + 4, name + offset, sz);
|
sz = RtlIsDosDeviceName_U (DosName);
|
||||||
buffer[4 + sz / sizeof(WCHAR)] = '\0';
|
if (sz)
|
||||||
/* file_part isn't set in this case */
|
{
|
||||||
return sz + 8;
|
offs = sz >> 17;
|
||||||
}
|
sz &= 0x0000FFFF;
|
||||||
|
if (sz + 8 >= size)
|
||||||
|
return sz + 10;
|
||||||
|
wcscpy (buf, L"\\\\.\\");
|
||||||
|
wcsncat (buf, DosName + offs, sz / sizeof(WCHAR));
|
||||||
|
return sz + 8;
|
||||||
|
}
|
||||||
|
|
||||||
reqsize = get_full_path_helper(name, buffer, size);
|
CHECKPOINT;
|
||||||
if (reqsize > size)
|
type = RtlDetermineDosPathNameType_U (DosName);
|
||||||
{
|
|
||||||
LPWSTR tmp = RtlAllocateHeap(RtlGetProcessHeap(), 0, reqsize);
|
RtlAcquirePebLock();
|
||||||
reqsize = get_full_path_helper(name, tmp, reqsize);
|
|
||||||
if (reqsize > size) /* it may have worked the second time */
|
cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName);
|
||||||
{
|
DPRINT("type %ld\n", type);
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, tmp);
|
switch (type)
|
||||||
return reqsize + sizeof(WCHAR);
|
{
|
||||||
|
case 1: /* \\xxx or \\.xxx */
|
||||||
|
case 6: /* \\.\xxx */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* x:\xxx */
|
||||||
|
*DosName = RtlUpcaseUnicodeChar (*DosName);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: /* x:xxx */
|
||||||
|
drive = RtlUpcaseUnicodeChar (*DosName);
|
||||||
|
DosName += 2;
|
||||||
|
len -= 2;
|
||||||
|
CHECKPOINT;
|
||||||
|
if (drive == RtlUpcaseUnicodeChar (cd->DosPath.Buffer[0]))
|
||||||
|
{
|
||||||
|
CHECKPOINT;
|
||||||
|
memcpy (TempFullPathName, cd->DosPath.Buffer, cd->DosPath.Length);
|
||||||
|
templen = cd->DosPath.Length / sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECKPOINT;
|
||||||
|
var[0] = L'=';
|
||||||
|
var[1] = drive;
|
||||||
|
var[2] = L':';
|
||||||
|
var[3] = 0;
|
||||||
|
usvar.Length = 3 * sizeof(WCHAR);
|
||||||
|
usvar.MaximumLength = 4 * sizeof(WCHAR);
|
||||||
|
usvar.Buffer = var;
|
||||||
|
pfx.Length = 0;
|
||||||
|
pfx.MaximumLength = MAX_PATH;
|
||||||
|
pfx.Buffer = TempFullPathName;
|
||||||
|
Status = RtlQueryEnvironmentVariable_U (NULL,
|
||||||
|
&usvar,
|
||||||
|
&pfx);
|
||||||
|
CHECKPOINT;
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
CHECKPOINT;
|
||||||
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||||
|
return pfx.Length + len * 2 + 2;
|
||||||
|
CHECKPOINT;
|
||||||
|
TempFullPathName[0] = drive;
|
||||||
|
TempFullPathName[1] = L':';
|
||||||
|
TempFullPathName[2] = L'\\';
|
||||||
|
TempFullPathName[3] = 0;
|
||||||
|
templen = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECKPOINT;
|
||||||
|
templen = pfx.Length / sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: /* \xxx */
|
||||||
|
wcsncpy (TempFullPathName, cd->DosPath.Buffer, 2);
|
||||||
|
TempFullPathName[2] = 0;
|
||||||
|
templen = wcslen(TempFullPathName);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: /* xxx */
|
||||||
|
memcpy (TempFullPathName, cd->DosPath.Buffer, cd->DosPath.Length);
|
||||||
|
templen = cd->DosPath.Length / sizeof(WCHAR);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: /* \\. */
|
||||||
|
memcpy (TempFullPathName, L"\\\\.\\", 8);
|
||||||
|
templen = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlReleasePebLock();
|
||||||
|
|
||||||
|
DPRINT("TempFullPathName \'%S\' DosName \'%S\' len %ld\n", TempFullPathName, DosName, len);
|
||||||
|
/* add dosname to prefix */
|
||||||
|
memcpy (TempFullPathName + templen, DosName, len * sizeof(WCHAR));
|
||||||
|
len += templen;
|
||||||
|
TempFullPathName[len] = 0;
|
||||||
|
|
||||||
|
CHECKPOINT;
|
||||||
|
/* replace slashes */
|
||||||
|
wcs = wcschr(TempFullPathName, L'/');
|
||||||
|
while(wcs)
|
||||||
|
{
|
||||||
|
*wcs = L'\\';
|
||||||
|
wcs = wcschr(wcs + 1, L'/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 2 && TempFullPathName[1] == L':')
|
||||||
|
{
|
||||||
|
TempFullPathName[len++] = L'\\';
|
||||||
|
TempFullPathName[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DPRINT("TempFullPathName \'%S\'\n", TempFullPathName);
|
||||||
|
RtlpEatPath (TempFullPathName);
|
||||||
|
DPRINT("TempFullPathName \'%S\'\n", TempFullPathName);
|
||||||
|
|
||||||
|
len = wcslen (TempFullPathName);
|
||||||
|
|
||||||
|
if (len < (size / sizeof(WCHAR)))
|
||||||
|
{
|
||||||
|
memcpy (buf, TempFullPathName, (len + 1) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
/* find file part */
|
||||||
|
if (FilePart)
|
||||||
|
{
|
||||||
|
*FilePart = wcsrchr(buf, L'\\');
|
||||||
|
if (*FilePart)
|
||||||
|
{
|
||||||
|
(*FilePart)++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*FilePart = buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
memcpy( buffer, tmp, reqsize + sizeof(WCHAR) );
|
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find file part */
|
return len * sizeof(WCHAR);
|
||||||
if (file_part && (ptr = wcsrchr(buffer, '\\')) != NULL && ptr >= buffer + 2 && *++ptr)
|
|
||||||
*file_part = ptr;
|
|
||||||
return reqsize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue