mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 22:13:06 +00:00
[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:
parent
1c15cfffb4
commit
7c480c24b8
1 changed files with 169 additions and 129 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue