Fix the semantics of SetFilePointer as described by Raymond Chen on http://blogs.msdn.com/oldnewthing/archive/2007/07/11/3805135.aspx

svn path=/trunk/; revision=27612
This commit is contained in:
Thomas Bluemel 2007-07-12 10:56:00 +00:00
parent 87d4c1e2b4
commit e0bf78bad7

View file

@ -394,18 +394,14 @@ SetFilePointer(HANDLE hFile,
return -1; return -1;
} }
Distance.u.LowPart = lDistanceToMove;
if (lpDistanceToMoveHigh) if (lpDistanceToMoveHigh)
{ {
Distance.u.HighPart = *lpDistanceToMoveHigh; Distance.u.HighPart = *lpDistanceToMoveHigh;
} Distance.u.LowPart = lDistanceToMove;
else if (lDistanceToMove >= 0)
{
Distance.u.HighPart = 0;
} }
else else
{ {
Distance.u.HighPart = -1; Distance.QuadPart = lDistanceToMove;
} }
switch(dwMoveMethod) switch(dwMoveMethod)
@ -441,6 +437,14 @@ SetFilePointer(HANDLE hFile,
return -1; 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, errCode = NtSetInformationFile(hFile,
&IoStatusBlock, &IoStatusBlock,
&FilePosition, &FilePosition,
@ -448,6 +452,9 @@ SetFilePointer(HANDLE hFile,
FilePositionInformation); FilePositionInformation);
if (!NT_SUCCESS(errCode)) if (!NT_SUCCESS(errCode))
{ {
if (lpDistanceToMoveHigh != NULL)
*lpDistanceToMoveHigh = -1;
SetLastErrorByStatus(errCode); SetLastErrorByStatus(errCode);
return -1; return -1;
} }
@ -456,6 +463,17 @@ SetFilePointer(HANDLE hFile,
{ {
*lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart; *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; return FilePosition.CurrentByteOffset.u.LowPart;
} }