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;
}
示例#2
0
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;
}
示例#3
0
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;
}