static int OnSendAsynchronousFsctl( HWND hDlg, ULONG IoctlCode, PVOID InputBuffer = NULL, ULONG InputBufferSize = 0, PVOID OutputBuffer = NULL, ULONG OutputBufferSize = 0) { TFileTestData * pData = GetDialogData(hDlg); TApcEntry * pApc; NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; // Create new APC entry pApc = (TApcEntry *)CreateApcEntry(pData, APC_TYPE_FSCTL, sizeof(TApcEntry) + OutputBufferSize); if(pApc != NULL) { // If there's an output buffer, move it to the APC structure if(OutputBuffer && OutputBufferSize) { memcpy(pApc + 1, OutputBuffer, OutputBufferSize); OutputBuffer = (pApc + 1); } // Send the FSCTL Status = NtFsControlFile(pData->hFile, pApc->hEvent, NULL, NULL, &pApc->IoStatus, IoctlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize); // If the IOCTL returned STATUS_PENDING, it means that the oplock is active. // If the oplock breaks, the event becomes signalled, and we get the APC message if(Status == STATUS_PENDING) { pApc->UserParam = IoctlCode; InsertApcEntry(pData, pApc); } else { FreeApcEntry(pApc); } } SetResultInfo(hDlg, RtlNtStatusToDosError(Status)); 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; }
static int OnReadWriteFile(HWND hDlg, int nIDCtrl) { IO_STATUS_BLOCK IoStatus = {0}; TFileTestData * pData = GetDialogData(hDlg); TApcReadWrite * pApc; LARGE_INTEGER ByteOffset = {0}; NTREADWRITE NtReadWrite; READWRITE ReadWrite; NTSTATUS Status; DWORD dwTransferred = 0; DWORD Length = 0; int nError = ERROR_SUCCESS; // Get the start position DlgText2Hex64(hDlg, IDC_BYTE_OFFSET, &ByteOffset.QuadPart); DlgText2Hex32(hDlg, IDC_LENGTH, &Length); assert(pData->cbFileData >= Length); // Create new APC entry pApc = (TApcReadWrite *)CreateApcEntry(pData, APC_TYPE_READ_WRITE, sizeof(TApcReadWrite)); if(pApc != NULL) { // Remember the state of "Increment position" pApc->ByteOffset = ByteOffset; pApc->bIncrementPosition = (IsDlgButtonChecked(hDlg, IDC_INCREASE_FILEPOS) == BST_CHECKED); // Perform the appropriate API switch(nIDCtrl) { case IDC_READ_FILE: case IDC_WRITE_FILE: // Get the pointer to the appropriate API ReadWrite = (nIDCtrl == IDC_READ_FILE) ? ReadFile : (READWRITE)WriteFile; pApc->bUpdateData = (nIDCtrl == IDC_READ_FILE); pApc->bNativeCall = false; // Prepare the OVERLAPPED structure in the APC pApc->Overlapped.OffsetHigh = ByteOffset.HighPart; pApc->Overlapped.Offset = ByteOffset.LowPart; // Perform the read operation using ReadFile if(!ReadWrite(pData->hFile, pData->pbFileData, Length, &dwTransferred, &pApc->Overlapped)) nError = GetLastError(); // If the read operation ended with ERROR_IO_PENDING, queue the APC if(nError == ERROR_IO_PENDING) { SetResultInfo(hDlg, ERROR_IO_PENDING); InsertApcEntry(pData, pApc); return TRUE; } break; case IDC_NTREAD_FILE: case IDC_NTWRITE_FILE: // Get the pointer to the appropriate API NtReadWrite = (nIDCtrl == IDC_NTREAD_FILE) ? NtReadFile : NtWriteFile; pApc->bUpdateData = (nIDCtrl == IDC_NTREAD_FILE); pApc->bNativeCall = true; // Perform the read/write operation Status = NtReadWrite(pData->hFile, pApc->hEvent, NULL, NULL, &pApc->IoStatus, pData->pbFileData, Length, &ByteOffset, NULL); // If the read operation ended with STATUS_PENDING, queue the APC if(Status == STATUS_PENDING) { SetResultInfo(hDlg, ERROR_IO_PENDING); InsertApcEntry(pData, pApc); return TRUE; } // Fill the number of bytes transferred dwTransferred = (DWORD)IoStatus.Information; nError = RtlNtStatusToDosError(Status); break; } // Complete the read/write operation CompleteReadWriteOperation(hDlg, pApc, nError, dwTransferred); FreeApcEntry(pApc); } else { SetResultInfo(hDlg, GetLastError()); } return TRUE; }