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/p... ============================================================================== --- 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,