mirror of
https://github.com/reactos/reactos.git
synced 2024-10-15 13:45:58 +00:00
[KERNEL32]: Fix infinite loop in FindLFNorSFN_U.
[KERNEL32]: Reimplement GetFullPathNameA to implement similar functionality and checks as the other reimplemented A functions, especially w.r.t ANSI/OEM and DBCS strings. svn path=/trunk/; revision=54321
This commit is contained in:
parent
3bdf1b6e8a
commit
504de2415f
|
@ -187,11 +187,10 @@ FindLFNorSFN_U(IN PWCHAR Path,
|
||||||
* Check if it is valid
|
* Check if it is valid
|
||||||
* Note that !IsShortName != IsLongName, these two functions simply help
|
* Note that !IsShortName != IsLongName, these two functions simply help
|
||||||
* us determine if a conversion is necessary or not.
|
* us determine if a conversion is necessary or not.
|
||||||
|
* "Found" really means: "Is a conversion necessary?", hence the "!"
|
||||||
*/
|
*/
|
||||||
Found = UseShort ? IsShortName_U(Path, Length) : IsLongName_U(Path, Length);
|
Found = UseShort ? !IsShortName_U(Path, Length) : !IsLongName_U(Path, Length);
|
||||||
|
if (Found)
|
||||||
/* "Found" really means: "Is a conversion necessary?", hence the ! */
|
|
||||||
if (!Found)
|
|
||||||
{
|
{
|
||||||
/* It is! did the caller request to know the markers? */
|
/* It is! did the caller request to know the markers? */
|
||||||
if ((First) && (Last))
|
if ((First) && (Last))
|
||||||
|
@ -211,7 +210,7 @@ FindLFNorSFN_U(IN PWCHAR Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return if anything was found and valid */
|
/* Return if anything was found and valid */
|
||||||
return !Found;
|
return Found;
|
||||||
}
|
}
|
||||||
|
|
||||||
PWCHAR
|
PWCHAR
|
||||||
|
@ -454,53 +453,114 @@ NeedCurrentDirectoryForExePathA(IN LPCSTR ExeName)
|
||||||
*/
|
*/
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
GetFullPathNameA (
|
GetFullPathNameA(IN LPCSTR lpFileName,
|
||||||
LPCSTR lpFileName,
|
IN DWORD nBufferLength,
|
||||||
DWORD nBufferLength,
|
IN LPSTR lpBuffer,
|
||||||
LPSTR lpBuffer,
|
IN LPSTR *lpFilePart)
|
||||||
LPSTR *lpFilePart
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
WCHAR BufferW[MAX_PATH];
|
NTSTATUS Status;
|
||||||
PWCHAR FileNameW;
|
PWCHAR Buffer;
|
||||||
DWORD ret;
|
ULONG PathSize, FilePartSize;
|
||||||
LPWSTR FilePartW = NULL;
|
ANSI_STRING AnsiString;
|
||||||
|
UNICODE_STRING FileNameString, UniString;
|
||||||
|
PWCHAR LocalFilePart;
|
||||||
|
PWCHAR* FilePart;
|
||||||
|
|
||||||
DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
|
/* If the caller wants filepart, use a local wide buffer since this is A */
|
||||||
"lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
|
FilePart = lpFilePart != NULL ? &LocalFilePart : NULL;
|
||||||
|
|
||||||
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
|
/* Initialize for Quickie */
|
||||||
return 0;
|
FilePartSize = PathSize = 0;
|
||||||
|
FileNameString.Buffer = NULL;
|
||||||
|
|
||||||
ret = GetFullPathNameW(FileNameW, MAX_PATH, BufferW, &FilePartW);
|
/* First get our string in Unicode */
|
||||||
|
Status = Basep8BitStringToDynamicUnicodeString(&FileNameString, lpFileName);
|
||||||
|
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||||
|
|
||||||
if (!ret)
|
/* Allocate a buffer to hold teh path name */
|
||||||
return 0;
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||||
|
0,
|
||||||
|
MAX_PATH * sizeof(WCHAR) + sizeof(UNICODE_NULL));
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
BaseSetLastNTError(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret > MAX_PATH)
|
/* Call into RTL to get the full Unicode path name */
|
||||||
{
|
PathSize = RtlGetFullPathName_U(FileNameString.Buffer,
|
||||||
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
MAX_PATH * sizeof(WCHAR),
|
||||||
return 0;
|
Buffer,
|
||||||
}
|
FilePart);
|
||||||
|
if (PathSize <= (MAX_PATH * sizeof(WCHAR)))
|
||||||
|
{
|
||||||
|
/* The buffer will fit, get the real ANSI string size now */
|
||||||
|
Status = RtlUnicodeToMultiByteSize(&PathSize, Buffer, PathSize);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Now check if the user wanted file part size as well */
|
||||||
|
if ((PathSize) && (lpFilePart) && (LocalFilePart))
|
||||||
|
{
|
||||||
|
/* Yep, so in this case get the length of the file part too */
|
||||||
|
Status = RtlUnicodeToMultiByteSize(&FilePartSize,
|
||||||
|
Buffer,
|
||||||
|
(LocalFilePart - Buffer) *
|
||||||
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* We failed to do that, so fail the whole call */
|
||||||
|
BaseSetLastNTError(Status);
|
||||||
|
PathSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Reset the path size since the buffer is not large enough */
|
||||||
|
PathSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
|
/* Either no path, or local buffer was too small, enter failure code */
|
||||||
|
if (!PathSize) goto Quickie;
|
||||||
|
|
||||||
if (ret < nBufferLength && lpFilePart)
|
/* If the *caller's* buffer was too small, fail, but add in space for NULL */
|
||||||
{
|
if (PathSize < nBufferLength)
|
||||||
/* if the path closed with '\', FilePart is NULL */
|
{
|
||||||
if (!FilePartW)
|
PathSize++;
|
||||||
*lpFilePart=NULL;
|
goto Quickie;
|
||||||
else
|
}
|
||||||
*lpFilePart = (FilePartW - BufferW) + lpBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n",
|
/* So far so good, initialize a unicode string to convert back to ANSI/OEM */
|
||||||
lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart);
|
RtlInitUnicodeString(&UniString, Buffer);
|
||||||
|
Status = BasepUnicodeStringTo8BitString(&AnsiString, &UniString, TRUE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Final conversion failed, fail the call */
|
||||||
|
BaseSetLastNTError(Status);
|
||||||
|
PathSize = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Conversion worked, now copy the ANSI/OEM buffer into the buffer */
|
||||||
|
RtlCopyMemory(lpBuffer, AnsiString.Buffer, PathSize + 1);
|
||||||
|
RtlFreeAnsiString(&AnsiString);
|
||||||
|
|
||||||
|
/* And finally, did the caller request file part information? */
|
||||||
|
if (lpFilePart)
|
||||||
|
{
|
||||||
|
/* Use the size we computed earlier and add it to the buffer */
|
||||||
|
*lpFilePart = LocalFilePart ? &lpBuffer[FilePartSize] : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
Quickie:
|
||||||
|
/* Cleanup and return the path size */
|
||||||
|
if (FileNameString.Buffer) RtlFreeUnicodeString(&FileNameString);
|
||||||
|
if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||||
|
return PathSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -511,6 +571,7 @@ GetFullPathNameW(IN LPCWSTR lpFileName,
|
||||||
IN LPWSTR lpBuffer,
|
IN LPWSTR lpBuffer,
|
||||||
OUT LPWSTR *lpFilePart)
|
OUT LPWSTR *lpFilePart)
|
||||||
{
|
{
|
||||||
|
/* Call Rtl to do the work */
|
||||||
return RtlGetFullPathName_U((LPWSTR)lpFileName,
|
return RtlGetFullPathName_U((LPWSTR)lpFileName,
|
||||||
nBufferLength * sizeof(WCHAR),
|
nBufferLength * sizeof(WCHAR),
|
||||||
lpBuffer,
|
lpBuffer,
|
||||||
|
|
Loading…
Reference in a new issue