[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,165 +23,207 @@ 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;
return LockFileEx(hFile,
LOCKFILE_FAIL_IMMEDIATELY |
LOCKFILE_EXCLUSIVE_LOCK,
dwReserved,
nNumberOfBytesToLockLow,
nNumberOfBytesToLockHigh,
&Overlapped ) ;
}
/*
* @implemented
*/
BOOL
WINAPI
LockFileEx(HANDLE hFile,
DWORD dwFlags,
DWORD dwReserved,
DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh,
LPOVERLAPPED lpOverlapped /* required! */)
{
LARGE_INTEGER BytesToLock;
BOOL LockImmediate;
BOOL LockExclusive;
NTSTATUS errCode;
LARGE_INTEGER Offset;
if(dwReserved != 0 || lpOverlapped==NULL)
{ {
SetLastError(ERROR_INVALID_PARAMETER); /* Can't "lock" a console! */
BaseSetLastNTError(STATUS_INVALID_HANDLE);
return FALSE; return FALSE;
} }
TRACE( "%p %x%08x %x%08x flags %x\n", /* Setup the parameters in NT style and call the native API */
hFile, lpOverlapped->OffsetHigh, lpOverlapped->Offset,
nNumberOfBytesToLockHigh, nNumberOfBytesToLockLow, dwFlags );
lpOverlapped->Internal = STATUS_PENDING;
Offset.u.LowPart = lpOverlapped->Offset;
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;
Offset.u.LowPart = dwFileOffsetLow;
errCode = NtLockFile(hFile, Offset.u.HighPart = dwFileOffsetHigh;
lpOverlapped->hEvent, Status = NtLockFile(hFile,
NULL, NULL,
NULL, NULL,
(PIO_STATUS_BLOCK)lpOverlapped, NULL,
&Offset, &IoStatusBlock,
&BytesToLock, &Offset,
0, &BytesToLock,
(BOOLEAN)LockImmediate, 0,
(BOOLEAN)LockExclusive); TRUE,
TRUE);
if ( !NT_SUCCESS(errCode) ) if (Status == STATUS_PENDING)
{ {
BaseSetLastNTError(errCode); /* 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; return FALSE;
} }
/* Success! */
return TRUE; return TRUE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
UnlockFile(HANDLE hFile, LockFileEx(IN HANDLE hFile,
DWORD dwFileOffsetLow, IN DWORD dwFlags,
DWORD dwFileOffsetHigh, IN DWORD dwReserved,
DWORD nNumberOfBytesToUnlockLow, IN DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToUnlockHigh) IN DWORD nNumberOfBytesToLockHigh,
IN LPOVERLAPPED lpOverlapped)
{ {
OVERLAPPED Overlapped; LARGE_INTEGER BytesToLock, Offset;
DWORD dwReserved; NTSTATUS Status;
Overlapped.Offset = dwFileOffsetLow;
Overlapped.OffsetHigh = dwFileOffsetHigh;
dwReserved = 0;
return UnlockFileEx(hFile, /* Is this a console handle? */
dwReserved, if (IsConsoleHandle(hFile))
nNumberOfBytesToUnlockLow,
nNumberOfBytesToUnlockHigh,
&Overlapped);
}
/*
* @implemented
*/
BOOL
WINAPI
UnlockFileEx(HANDLE hFile,
DWORD dwReserved,
DWORD nNumberOfBytesToUnLockLow,
DWORD nNumberOfBytesToUnLockHigh,
LPOVERLAPPED lpOverlapped /* required! */)
{
LARGE_INTEGER BytesToUnLock;
LARGE_INTEGER StartAddress;
NTSTATUS errCode;
if(dwReserved != 0 || lpOverlapped == NULL)
{ {
/* 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\n", /* Set the initial status in the IO_STATUS_BLOCK to pending... */
hFile, lpOverlapped->OffsetHigh, lpOverlapped->Offset, lpOverlapped->Internal = STATUS_PENDING;
nNumberOfBytesToUnLockHigh, nNumberOfBytesToUnLockLow);
BytesToUnLock.u.LowPart = nNumberOfBytesToUnLockLow; /* Convert the parameters to NT format and call the native API */
BytesToUnLock.u.HighPart = nNumberOfBytesToUnLockHigh; Offset.u.LowPart = lpOverlapped->Offset;
Offset.u.HighPart = lpOverlapped->OffsetHigh;
StartAddress.u.LowPart = lpOverlapped->Offset; BytesToLock.u.LowPart = nNumberOfBytesToLockLow;
StartAddress.u.HighPart = lpOverlapped->OffsetHigh; BytesToLock.u.HighPart = nNumberOfBytesToLockHigh;
Status = NtLockFile(hFile,
errCode = NtUnlockFile(hFile, lpOverlapped->hEvent,
(PIO_STATUS_BLOCK)lpOverlapped, NULL,
&StartAddress, NULL,
&BytesToUnLock, (PIO_STATUS_BLOCK)lpOverlapped,
0); &Offset,
&BytesToLock,
if ( !NT_SUCCESS(errCode) ) 0,
dwFlags & LOCKFILE_FAIL_IMMEDIATELY ? TRUE : FALSE,
dwFlags & LOCKFILE_EXCLUSIVE_LOCK ? TRUE: FALSE);
if ((NT_SUCCESS(Status)) && (Status != STATUS_PENDING))
{ {
BaseSetLastNTError(errCode); /* Pending status is *not* allowed in the Ex API */
return TRUE;
}
/* Convert the error code and fail */
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
UnlockFile(IN HANDLE hFile,
IN DWORD dwFileOffsetLow,
IN DWORD dwFileOffsetHigh,
IN DWORD nNumberOfBytesToUnlockLow,
IN DWORD nNumberOfBytesToUnlockHigh)
{
OVERLAPPED Overlapped;
NTSTATUS Status;
BOOLEAN Result;
/* Convert parameters to Ex format and call the new API */
Overlapped.Offset = dwFileOffsetLow;
Overlapped.OffsetHigh = dwFileOffsetHigh;
Result = UnlockFileEx(hFile,
0,
nNumberOfBytesToUnlockLow,
nNumberOfBytesToUnlockHigh,
&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; return FALSE;
} }
/* Success or error case -- Ex took care of the rest, just return */
return Result;
}
/*
* @implemented
*/
BOOL
WINAPI
UnlockFileEx(IN HANDLE hFile,
IN DWORD dwReserved,
IN DWORD nNumberOfBytesToUnLockLow,
IN DWORD nNumberOfBytesToUnLockHigh,
IN LPOVERLAPPED lpOverlapped)
{
LARGE_INTEGER BytesToUnLock, StartAddress;
NTSTATUS Status;
/* 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);
return FALSE;
}
/* Convert to NT format and call the native function */
BytesToUnLock.u.LowPart = nNumberOfBytesToUnLockLow;
BytesToUnLock.u.HighPart = nNumberOfBytesToUnLockHigh;
StartAddress.u.LowPart = lpOverlapped->Offset;
StartAddress.u.HighPart = lpOverlapped->OffsetHigh;
Status = NtUnlockFile(hFile,
(PIO_STATUS_BLOCK)lpOverlapped,
&StartAddress,
&BytesToUnLock,
0);
if (!NT_SUCCESS(Status))
{
/* Convert the error and fail */
BaseSetLastNTError(Status);
return FALSE;
}
/* All good */
return TRUE; return TRUE;
} }