Author: weiden Date: Thu Jul 12 14:56:00 2007 New Revision: 27612
URL: http://svn.reactos.org/svn/reactos?rev=27612&view=rev Log: Fix the semantics of SetFilePointer as described by Raymond Chen on http://blogs.msdn.com/oldnewthing/archive/2007/07/11/3805135.aspx
Modified: trunk/reactos/dll/win32/kernel32/file/file.c
Modified: trunk/reactos/dll/win32/kernel32/file/file.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/file/fil... ============================================================================== --- trunk/reactos/dll/win32/kernel32/file/file.c (original) +++ trunk/reactos/dll/win32/kernel32/file/file.c Thu Jul 12 14:56:00 2007 @@ -394,18 +394,14 @@ return -1; }
- Distance.u.LowPart = lDistanceToMove; if (lpDistanceToMoveHigh) { Distance.u.HighPart = *lpDistanceToMoveHigh; - } - else if (lDistanceToMove >= 0) - { - Distance.u.HighPart = 0; + Distance.u.LowPart = lDistanceToMove; } else { - Distance.u.HighPart = -1; + Distance.QuadPart = lDistanceToMove; }
switch(dwMoveMethod) @@ -441,6 +437,14 @@ return -1; }
+ if (lpDistanceToMoveHigh == NULL && FilePosition.CurrentByteOffset.HighPart != 0) + { + /* If we're moving the pointer outside of the 32 bit boundaries but + the application only passed a 32 bit value we need to bail out! */ + SetLastError(ERROR_INVALID_PARAMETER); + return -1; + } + errCode = NtSetInformationFile(hFile, &IoStatusBlock, &FilePosition, @@ -448,14 +452,28 @@ FilePositionInformation); if (!NT_SUCCESS(errCode)) { - SetLastErrorByStatus(errCode); - return -1; + if (lpDistanceToMoveHigh != NULL) + *lpDistanceToMoveHigh = -1; + + SetLastErrorByStatus(errCode); + return -1; }
if (lpDistanceToMoveHigh != NULL) { *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart; } + + if (FilePosition.CurrentByteOffset.u.LowPart == -1) + { + /* The value of -1 is valid here, especially when the new + file position is greater than 4 GB. Since NtSetInformationFile + succeeded we never set an error code and we explicitly need + to clear a previously set error code in this case, which + an application will check if INVALID_SET_FILE_POINTER is returned! */ + SetLastError(ERROR_SUCCESS); + } + return FilePosition.CurrentByteOffset.u.LowPart; }