[KERNEL32]: Lock/UnlockFile APIs should not allow console handles. Also remove superflous parameter check.

[KERNEL32]: Lock/UnlockFile APIs should handle STATUS_PENDING/ERROR_IO_PENDING situations instead of always assuming the Nt functions return synchronously.
[KERNEL32]: Other stylying changes + commenting/annotations.

svn path=/trunk/; revision=55795
This commit is contained in:
Alex Ionescu 2012-02-21 21:38:08 +00:00
parent 1c15cfffb4
commit 7c480c24b8

View file

@ -9,14 +9,12 @@
* Created 01/11/98 * Created 01/11/98
*/ */
/* FIXME: the large integer manipulations in this file dont handle overflow */
/* INCLUDES ****************************************************************/ /* INCLUDES ****************************************************************/
#include <k32.h> #include <k32.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
DEBUG_CHANNEL(kernel32file);
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
@ -25,77 +23,98 @@ DEBUG_CHANNEL(kernel32file);
*/ */
BOOL BOOL
WINAPI WINAPI
LockFile(HANDLE hFile, LockFile(IN HANDLE hFile,
DWORD dwFileOffsetLow, IN DWORD dwFileOffsetLow,
DWORD dwFileOffsetHigh, IN DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToLockLow, IN DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh) IN DWORD nNumberOfBytesToLockHigh)
{ {
DWORD dwReserved; IO_STATUS_BLOCK IoStatusBlock;
OVERLAPPED Overlapped; NTSTATUS Status;
LARGE_INTEGER BytesToLock, Offset;
Overlapped.Offset = dwFileOffsetLow; /* Is this a console handle? */
Overlapped.OffsetHigh = dwFileOffsetHigh; if (IsConsoleHandle(hFile))
Overlapped.hEvent = NULL; {
dwReserved = 0; /* Can't "lock" a console! */
BaseSetLastNTError(STATUS_INVALID_HANDLE);
return FALSE;
}
return LockFileEx(hFile, /* Setup the parameters in NT style and call the native API */
LOCKFILE_FAIL_IMMEDIATELY | BytesToLock.u.LowPart = nNumberOfBytesToLockLow;
LOCKFILE_EXCLUSIVE_LOCK, BytesToLock.u.HighPart = nNumberOfBytesToLockHigh;
dwReserved, Offset.u.LowPart = dwFileOffsetLow;
nNumberOfBytesToLockLow, Offset.u.HighPart = dwFileOffsetHigh;
nNumberOfBytesToLockHigh, Status = NtLockFile(hFile,
&Overlapped ) ; NULL,
NULL,
NULL,
&IoStatusBlock,
&Offset,
&BytesToLock,
0,
TRUE,
TRUE);
if (Status == STATUS_PENDING)
{
/* Wait for completion if needed */
Status = NtWaitForSingleObject(hFile, FALSE, NULL);
if (NT_SUCCESS(Status)) Status = IoStatusBlock.Status;
}
/* Check if we failed */
if (!NT_SUCCESS(Status))
{
/* Convert the error code and fail */
BaseSetLastNTError(Status);
return FALSE;
}
/* Success! */
return TRUE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
LockFileEx(HANDLE hFile, LockFileEx(IN HANDLE hFile,
DWORD dwFlags, IN DWORD dwFlags,
DWORD dwReserved, IN DWORD dwReserved,
DWORD nNumberOfBytesToLockLow, IN DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh, IN DWORD nNumberOfBytesToLockHigh,
LPOVERLAPPED lpOverlapped /* required! */) IN LPOVERLAPPED lpOverlapped)
{ {
LARGE_INTEGER BytesToLock; LARGE_INTEGER BytesToLock, Offset;
BOOL LockImmediate; NTSTATUS Status;
BOOL LockExclusive;
NTSTATUS errCode;
LARGE_INTEGER Offset;
if(dwReserved != 0 || lpOverlapped==NULL) /* Is this a console handle? */
if (IsConsoleHandle(hFile))
{ {
/* Can't "lock" a console! */
BaseSetLastNTError(STATUS_INVALID_HANDLE);
return FALSE;
}
/* This parameter should be zero */
if (dwReserved)
{
/* Fail since it isn't */
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
TRACE( "%p %x%08x %x%08x flags %x\n", /* Set the initial status in the IO_STATUS_BLOCK to pending... */
hFile, lpOverlapped->OffsetHigh, lpOverlapped->Offset,
nNumberOfBytesToLockHigh, nNumberOfBytesToLockLow, dwFlags );
lpOverlapped->Internal = STATUS_PENDING; lpOverlapped->Internal = STATUS_PENDING;
/* Convert the parameters to NT format and call the native API */
Offset.u.LowPart = lpOverlapped->Offset; Offset.u.LowPart = lpOverlapped->Offset;
Offset.u.HighPart = lpOverlapped->OffsetHigh; Offset.u.HighPart = lpOverlapped->OffsetHigh;
if ( (dwFlags & LOCKFILE_FAIL_IMMEDIATELY) == LOCKFILE_FAIL_IMMEDIATELY )
LockImmediate = TRUE;
else
LockImmediate = FALSE;
if ( (dwFlags & LOCKFILE_EXCLUSIVE_LOCK) == LOCKFILE_EXCLUSIVE_LOCK )
LockExclusive = TRUE;
else
LockExclusive = FALSE;
BytesToLock.u.LowPart = nNumberOfBytesToLockLow; BytesToLock.u.LowPart = nNumberOfBytesToLockLow;
BytesToLock.u.HighPart = nNumberOfBytesToLockHigh; BytesToLock.u.HighPart = nNumberOfBytesToLockHigh;
Status = NtLockFile(hFile,
errCode = NtLockFile(hFile,
lpOverlapped->hEvent, lpOverlapped->hEvent,
NULL, NULL,
NULL, NULL,
@ -103,87 +122,108 @@ LockFileEx(HANDLE hFile,
&Offset, &Offset,
&BytesToLock, &BytesToLock,
0, 0,
(BOOLEAN)LockImmediate, dwFlags & LOCKFILE_FAIL_IMMEDIATELY ? TRUE : FALSE,
(BOOLEAN)LockExclusive); dwFlags & LOCKFILE_EXCLUSIVE_LOCK ? TRUE: FALSE);
if ((NT_SUCCESS(Status)) && (Status != STATUS_PENDING))
if ( !NT_SUCCESS(errCode) )
{ {
BaseSetLastNTError(errCode); /* Pending status is *not* allowed in the Ex API */
return FALSE; return TRUE;
} }
return TRUE; /* Convert the error code and fail */
BaseSetLastNTError(Status);
return FALSE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
UnlockFile(HANDLE hFile, UnlockFile(IN HANDLE hFile,
DWORD dwFileOffsetLow, IN DWORD dwFileOffsetLow,
DWORD dwFileOffsetHigh, IN DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToUnlockLow, IN DWORD nNumberOfBytesToUnlockLow,
DWORD nNumberOfBytesToUnlockHigh) IN DWORD nNumberOfBytesToUnlockHigh)
{ {
OVERLAPPED Overlapped; OVERLAPPED Overlapped;
DWORD dwReserved; NTSTATUS Status;
BOOLEAN Result;
/* Convert parameters to Ex format and call the new API */
Overlapped.Offset = dwFileOffsetLow; Overlapped.Offset = dwFileOffsetLow;
Overlapped.OffsetHigh = dwFileOffsetHigh; Overlapped.OffsetHigh = dwFileOffsetHigh;
dwReserved = 0; Result = UnlockFileEx(hFile,
0,
return UnlockFileEx(hFile,
dwReserved,
nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockLow,
nNumberOfBytesToUnlockHigh, nNumberOfBytesToUnlockHigh,
&Overlapped); &Overlapped);
} if (!(Result) && (GetLastError() == ERROR_IO_PENDING))
{
/* Ex fails during STATUS_PENDING, handle that here by waiting */
Status = NtWaitForSingleObject(hFile, FALSE, NULL);
if (NT_SUCCESS(Status)) Status = Overlapped.Internal;
/* Now if the status is successful, return */
if (!NT_SUCCESS(Status)) return TRUE;
/* Otherwise the asynchronous operation had a failure, so fail */
BaseSetLastNTError(Status);
return FALSE;
}
/* Success or error case -- Ex took care of the rest, just return */
return Result;
}
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
UnlockFileEx(HANDLE hFile, UnlockFileEx(IN HANDLE hFile,
DWORD dwReserved, IN DWORD dwReserved,
DWORD nNumberOfBytesToUnLockLow, IN DWORD nNumberOfBytesToUnLockLow,
DWORD nNumberOfBytesToUnLockHigh, IN DWORD nNumberOfBytesToUnLockHigh,
LPOVERLAPPED lpOverlapped /* required! */) IN LPOVERLAPPED lpOverlapped)
{ {
LARGE_INTEGER BytesToUnLock; LARGE_INTEGER BytesToUnLock, StartAddress;
LARGE_INTEGER StartAddress; NTSTATUS Status;
NTSTATUS errCode;
if(dwReserved != 0 || lpOverlapped == NULL) /* Is this a console handle? */
if (IsConsoleHandle(hFile))
{ {
/* Can't "unlock" a console! */
BaseSetLastNTError(STATUS_INVALID_HANDLE);
return FALSE;
}
/* This parameter should be zero */
if (dwReserved)
{
/* Fail since it isn't */
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
TRACE( "%p %x%08x %x%08x\n", /* Convert to NT format and call the native function */
hFile, lpOverlapped->OffsetHigh, lpOverlapped->Offset,
nNumberOfBytesToUnLockHigh, nNumberOfBytesToUnLockLow);
BytesToUnLock.u.LowPart = nNumberOfBytesToUnLockLow; BytesToUnLock.u.LowPart = nNumberOfBytesToUnLockLow;
BytesToUnLock.u.HighPart = nNumberOfBytesToUnLockHigh; BytesToUnLock.u.HighPart = nNumberOfBytesToUnLockHigh;
StartAddress.u.LowPart = lpOverlapped->Offset; StartAddress.u.LowPart = lpOverlapped->Offset;
StartAddress.u.HighPart = lpOverlapped->OffsetHigh; StartAddress.u.HighPart = lpOverlapped->OffsetHigh;
Status = NtUnlockFile(hFile,
errCode = NtUnlockFile(hFile,
(PIO_STATUS_BLOCK)lpOverlapped, (PIO_STATUS_BLOCK)lpOverlapped,
&StartAddress, &StartAddress,
&BytesToUnLock, &BytesToUnLock,
0); 0);
if (!NT_SUCCESS(Status))
if ( !NT_SUCCESS(errCode) )
{ {
BaseSetLastNTError(errCode); /* Convert the error and fail */
BaseSetLastNTError(Status);
return FALSE; return FALSE;
} }
/* All good */
return TRUE; return TRUE;
} }