Author: ion
Date: Sun Nov 6 21:00:10 2011
New Revision: 54321
URL:
http://svn.reactos.org/svn/reactos?rev=54321&view=rev
Log:
[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.
Modified:
trunk/reactos/dll/win32/kernel32/client/path.c
Modified: trunk/reactos/dll/win32/kernel32/client/path.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/path.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/path.c [iso-8859-1] Sun Nov 6 21:00:10 2011
@@ -187,11 +187,10 @@
* Check if it is valid
* Note that !IsShortName != IsLongName, these two functions simply help
* 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" really means: "Is a conversion necessary?", hence
the ! */
- if (!Found)
+ Found = UseShort ? !IsShortName_U(Path, Length) : !IsLongName_U(Path, Length);
+ if (Found)
{
/* It is! did the caller request to know the markers? */
if ((First) && (Last))
@@ -211,7 +210,7 @@
}
/* Return if anything was found and valid */
- return !Found;
+ return Found;
}
PWCHAR
@@ -454,52 +453,113 @@
*/
DWORD
WINAPI
-GetFullPathNameA (
- LPCSTR lpFileName,
- DWORD nBufferLength,
- LPSTR lpBuffer,
- LPSTR *lpFilePart
- )
-{
- WCHAR BufferW[MAX_PATH];
- PWCHAR FileNameW;
- DWORD ret;
- LPWSTR FilePartW = NULL;
-
- DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
- "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
-
- if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
- return 0;
-
- ret = GetFullPathNameW(FileNameW, MAX_PATH, BufferW, &FilePartW);
-
- if (!ret)
- return 0;
-
- if (ret > MAX_PATH)
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- return 0;
- }
-
- ret = FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
-
- if (ret < nBufferLength && lpFilePart)
- {
- /* if the path closed with '\', FilePart is NULL */
- if (!FilePartW)
- *lpFilePart=NULL;
- else
- *lpFilePart = (FilePartW - BufferW) + lpBuffer;
- }
-
- DPRINT("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n",
- lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart);
-
- return ret;
-}
-
+GetFullPathNameA(IN LPCSTR lpFileName,
+ IN DWORD nBufferLength,
+ IN LPSTR lpBuffer,
+ IN LPSTR *lpFilePart)
+{
+ NTSTATUS Status;
+ PWCHAR Buffer;
+ ULONG PathSize, FilePartSize;
+ ANSI_STRING AnsiString;
+ UNICODE_STRING FileNameString, UniString;
+ PWCHAR LocalFilePart;
+ PWCHAR* FilePart;
+
+ /* If the caller wants filepart, use a local wide buffer since this is A */
+ FilePart = lpFilePart != NULL ? &LocalFilePart : NULL;
+
+ /* Initialize for Quickie */
+ FilePartSize = PathSize = 0;
+ FileNameString.Buffer = NULL;
+
+ /* First get our string in Unicode */
+ Status = Basep8BitStringToDynamicUnicodeString(&FileNameString, lpFileName);
+ if (!NT_SUCCESS(Status)) goto Quickie;
+
+ /* Allocate a buffer to hold teh path name */
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ MAX_PATH * sizeof(WCHAR) + sizeof(UNICODE_NULL));
+ if (!Buffer)
+ {
+ BaseSetLastNTError(STATUS_INSUFFICIENT_RESOURCES);
+ goto Quickie;
+ }
+
+ /* Call into RTL to get the full Unicode path name */
+ PathSize = RtlGetFullPathName_U(FileNameString.Buffer,
+ MAX_PATH * sizeof(WCHAR),
+ 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;
+ }
+
+ /* Either no path, or local buffer was too small, enter failure code */
+ if (!PathSize) goto Quickie;
+
+ /* If the *caller's* buffer was too small, fail, but add in space for NULL */
+ if (PathSize < nBufferLength)
+ {
+ PathSize++;
+ goto Quickie;
+ }
+
+ /* So far so good, initialize a unicode string to convert back to ANSI/OEM */
+ 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;
+ }
+ }
+
+Quickie:
+ /* Cleanup and return the path size */
+ if (FileNameString.Buffer) RtlFreeUnicodeString(&FileNameString);
+ if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+ return PathSize;
+}
/*
* @implemented
@@ -511,6 +571,7 @@
IN LPWSTR lpBuffer,
OUT LPWSTR *lpFilePart)
{
+ /* Call Rtl to do the work */
return RtlGetFullPathName_U((LPWSTR)lpFileName,
nBufferLength * sizeof(WCHAR),
lpBuffer,