Author: ion Date: Tue Feb 21 21:38:08 2012 New Revision: 55795
URL: http://svn.reactos.org/svn/reactos?rev=55795&view=rev Log: [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.
Modified: trunk/reactos/dll/win32/kernel32/client/file/lock.c
Modified: trunk/reactos/dll/win32/kernel32/client/file/lock.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/f... ============================================================================== --- trunk/reactos/dll/win32/kernel32/client/file/lock.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/client/file/lock.c [iso-8859-1] Tue Feb 21 21:38:08 2012 @@ -9,14 +9,12 @@ * Created 01/11/98 */
-/* FIXME: the large integer manipulations in this file dont handle overflow */
/* INCLUDES ****************************************************************/
#include <k32.h> #define NDEBUG #include <debug.h> -DEBUG_CHANNEL(kernel32file);
/* FUNCTIONS ****************************************************************/
@@ -25,165 +23,207 @@ */ BOOL WINAPI -LockFile(HANDLE hFile, - DWORD dwFileOffsetLow, - DWORD dwFileOffsetHigh, - DWORD nNumberOfBytesToLockLow, - DWORD nNumberOfBytesToLockHigh) -{ - DWORD dwReserved; +LockFile(IN HANDLE hFile, + IN DWORD dwFileOffsetLow, + IN DWORD dwFileOffsetHigh, + IN DWORD nNumberOfBytesToLockLow, + IN DWORD nNumberOfBytesToLockHigh) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + LARGE_INTEGER BytesToLock, Offset; + + /* Is this a console handle? */ + if (IsConsoleHandle(hFile)) + { + /* Can't "lock" a console! */ + BaseSetLastNTError(STATUS_INVALID_HANDLE); + return FALSE; + } + + /* Setup the parameters in NT style and call the native API */ + BytesToLock.u.LowPart = nNumberOfBytesToLockLow; + BytesToLock.u.HighPart = nNumberOfBytesToLockHigh; + Offset.u.LowPart = dwFileOffsetLow; + Offset.u.HighPart = dwFileOffsetHigh; + Status = NtLockFile(hFile, + 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 + */ +BOOL +WINAPI +LockFileEx(IN HANDLE hFile, + IN DWORD dwFlags, + IN DWORD dwReserved, + IN DWORD nNumberOfBytesToLockLow, + IN DWORD nNumberOfBytesToLockHigh, + IN LPOVERLAPPED lpOverlapped) +{ + LARGE_INTEGER BytesToLock, Offset; + NTSTATUS Status; + + /* 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); + return FALSE; + } + + /* Set the initial status in the IO_STATUS_BLOCK to pending... */ + lpOverlapped->Internal = STATUS_PENDING; + + /* Convert the parameters to NT format and call the native API */ + Offset.u.LowPart = lpOverlapped->Offset; + Offset.u.HighPart = lpOverlapped->OffsetHigh; + BytesToLock.u.LowPart = nNumberOfBytesToLockLow; + BytesToLock.u.HighPart = nNumberOfBytesToLockHigh; + Status = NtLockFile(hFile, + lpOverlapped->hEvent, + NULL, + NULL, + (PIO_STATUS_BLOCK)lpOverlapped, + &Offset, + &BytesToLock, + 0, + dwFlags & LOCKFILE_FAIL_IMMEDIATELY ? TRUE : FALSE, + dwFlags & LOCKFILE_EXCLUSIVE_LOCK ? TRUE: FALSE); + if ((NT_SUCCESS(Status)) && (Status != STATUS_PENDING)) + { + /* 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; - 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) - { + 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; + } + + /* 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; }
- TRACE( "%p %x%08x %x%08x flags %x\n", - 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.HighPart = nNumberOfBytesToLockHigh; - - errCode = NtLockFile(hFile, - lpOverlapped->hEvent, - NULL, - NULL, - (PIO_STATUS_BLOCK)lpOverlapped, - &Offset, - &BytesToLock, - 0, - (BOOLEAN)LockImmediate, - (BOOLEAN)LockExclusive); - - if ( !NT_SUCCESS(errCode) ) - { - BaseSetLastNTError(errCode); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -UnlockFile(HANDLE hFile, - DWORD dwFileOffsetLow, - DWORD dwFileOffsetHigh, - DWORD nNumberOfBytesToUnlockLow, - DWORD nNumberOfBytesToUnlockHigh) -{ - OVERLAPPED Overlapped; - DWORD dwReserved; - Overlapped.Offset = dwFileOffsetLow; - Overlapped.OffsetHigh = dwFileOffsetHigh; - dwReserved = 0; - - return UnlockFileEx(hFile, - dwReserved, - 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) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - TRACE( "%p %x%08x %x%08x\n", - hFile, lpOverlapped->OffsetHigh, lpOverlapped->Offset, - nNumberOfBytesToUnLockHigh, nNumberOfBytesToUnLockLow); - + /* 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; - - errCode = NtUnlockFile(hFile, - (PIO_STATUS_BLOCK)lpOverlapped, - &StartAddress, - &BytesToUnLock, - 0); - - if ( !NT_SUCCESS(errCode) ) - { - BaseSetLastNTError(errCode); - return FALSE; - } - + 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; }