/* * @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; }
static int OnLockUnlockFile(HWND hDlg, int nReadWriteType) { TFileTestData * pData = GetDialogData(hDlg); TApcReadWrite * pApc; LARGE_INTEGER ByteOffset = {0}; LARGE_INTEGER LockLength = {0}; NTSTATUS Status; int nError = ERROR_SUCCESS; // Get the start position DlgText2Hex64(hDlg, IDC_BYTE_OFFSET, &ByteOffset.QuadPart); DlgText2Hex32(hDlg, IDC_LENGTH, &LockLength.LowPart); assert((LONGLONG)pData->cbFileData >= LockLength.QuadPart); // Create new APC entry pApc = (TApcReadWrite *)CreateApcEntry(pData, APC_TYPE_READ_WRITE, sizeof(TApcReadWrite)); if(pApc != NULL) { // Perform the I/O operation switch(nReadWriteType) { case IDC_LOCK_FILE: // Perform the lock operation using LockFile if(!LockFile(pData->hFile, ByteOffset.LowPart, ByteOffset.HighPart, LockLength.LowPart, LockLength.HighPart)) nError = GetLastError(); break; case IDC_UNLOCK_FILE: // Perform the unlock operation using UnlockFile if(!UnlockFile(pData->hFile, ByteOffset.LowPart, ByteOffset.HighPart, LockLength.LowPart, LockLength.HighPart)) nError = GetLastError(); break; case IDC_NTLOCK_FILE: // Remember that this is a native call pApc->bNativeCall = false; // Perform the lock operation using NtLockFile Status = NtLockFile(pData->hFile, pApc->hEvent, NULL, NULL, &pApc->IoStatus, &ByteOffset, &LockLength, 0, TRUE, TRUE); // If the lock operation ended with STATUS_PENDING, queue the APC if(Status == STATUS_PENDING) { SetResultInfo(hDlg, ERROR_IO_PENDING); InsertApcEntry(pData, pApc); return TRUE; } // Save the error nError = RtlNtStatusToDosError(Status); break; case IDC_NTUNLOCK_FILE: // Perform the unlock operation using NtUnlockFile Status = NtUnlockFile(pData->hFile, &pApc->IoStatus, &ByteOffset, &LockLength, 0); // Save the error assert(Status != STATUS_PENDING); nError = RtlNtStatusToDosError(Status); break; } // Set the information about the operation SetResultInfo(hDlg, nError); FreeApcEntry(pApc); } else { SetResultInfo(hDlg, GetLastError()); } return TRUE; }