Ejemplo n.º 1
0
// Switchs the current log buffer, saves the contents of old buffer to the log
// file, and prints them out as necessary. This function does not flush the log
// file, so code should call LogpWriteMessageToFile() or ZwFlushBuffersFile()
// later.
_Use_decl_annotations_ static NTSTATUS LogpFlushLogBuffer(LogBufferInfo *info) {
  NT_ASSERT(info);
  NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

  auto status = STATUS_SUCCESS;

  // Enter a critical section and acquire a reader lock for info in order to
  // write a log file safely.
  ExEnterCriticalRegionAndAcquireResourceExclusive(&info->resource);

  // Acquire a spin lock for info.log_buffer(s) in order to switch its head
  // safely.
  KLOCK_QUEUE_HANDLE lock_handle = {};
  KeAcquireInStackQueuedSpinLock(&info->spin_lock, &lock_handle);
  const auto old_log_buffer = const_cast<char *>(info->log_buffer_head);
  if (old_log_buffer[0]) {
    info->log_buffer_head = (old_log_buffer == info->log_buffer1)
                                ? info->log_buffer2
                                : info->log_buffer1;
    info->log_buffer_head[0] = '\0';
    info->log_buffer_tail = info->log_buffer_head;
  }
  KeReleaseInStackQueuedSpinLock(&lock_handle);

  // Write all log entries in old log buffer.
  IO_STATUS_BLOCK io_status = {};
  for (auto current_log_entry = old_log_buffer; current_log_entry[0]; /**/) {
    // Check the printed bit and clear it
    const auto printed_out = LogpIsPrinted(current_log_entry);
    LogpSetPrintedBit(current_log_entry, false);

    const auto current_log_entry_length = strlen(current_log_entry);
    status = ZwWriteFile(info->log_file_handle, nullptr, nullptr, nullptr,
                         &io_status, current_log_entry,
                         static_cast<ULONG>(current_log_entry_length), nullptr,
                         nullptr);
    if (!NT_SUCCESS(status)) {
      // It could happen when you did not register IRP_SHUTDOWN and call
      // LogIrpShutdownHandler() and the system tried to log to a file after
      // a file system was unmounted.
      LogpDbgBreak();
    }

    // Print it out if requested and the message is not already printed out
    if (!printed_out) {
      LogpDoDbgPrint(current_log_entry);
    }

    current_log_entry += current_log_entry_length + 1;
  }
  old_log_buffer[0] = '\0';

  ExReleaseResourceAndLeaveCriticalRegion(&info->resource);
  return status;
}
Ejemplo n.º 2
0
// Switch the current log buffer and save the contents of old buffer to the log
// file. This function does not flush the log file, so code should call
// LogpWriteMessageToFile() or ZwFlushBuffersFile() later.
EXTERN_C static NTSTATUS LogpWriteLogBufferToFile(
    _In_opt_ LogBufferInfo *Info) {
  NT_ASSERT(Info);
  NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

  auto status = STATUS_SUCCESS;

  // Enter a critical section and acquire a reader lock for Info in order to
  // write a log file safely.
  ExEnterCriticalRegionAndAcquireResourceExclusive(&Info->Resource);

  // Acquire a spin lock for Info.LogBuffer(s) in order to switch its head
  // safely.
  const auto irql = KeAcquireSpinLockRaiseToDpc(&Info->SpinLock);
  auto oldLogBuffer = const_cast<char *>(Info->LogBufferHead);
  if (oldLogBuffer[0]) {
    Info->LogBufferHead = (oldLogBuffer == Info->LogBuffer1) ? Info->LogBuffer2
                                                             : Info->LogBuffer1;
    Info->LogBufferHead[0] = '\0';
    Info->LogBufferTail = Info->LogBufferHead;
  }
  KeReleaseSpinLock(&Info->SpinLock, irql);

  // Write all log entries in old log buffer.
  IO_STATUS_BLOCK ioStatus = {};
  for (auto currentLogEntry = oldLogBuffer; currentLogEntry[0]; /**/) {
    const auto currentLogEntryLength = strlen(currentLogEntry);
    status =
        ZwWriteFile(Info->LogFileHandle, nullptr, nullptr, nullptr, &ioStatus,
                    currentLogEntry, static_cast<ULONG>(currentLogEntryLength),
                    nullptr, nullptr);
    if (!NT_SUCCESS(status)) {
      // It could happen when you did not register IRP_SHUTDOWN and call
      // LogIrpShutdownHandler() and the system tried to log to a file after
      // a filesystem was unmounted.
      DBG_BREAK();
    }

    currentLogEntry += currentLogEntryLength + 1;
  }
  oldLogBuffer[0] = '\0';

  ExReleaseResourceAndLeaveCriticalRegion(&Info->Resource);
  return status;
}
Ejemplo n.º 3
0
NTSTATUS
DokanDispatchDeviceControl(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

/*++

Routine Description:

        This device control dispatcher handles IOCTLs.

Arguments:

        DeviceObject - Context for the activity.
        Irp          - The device control argument block.

Return Value:

        NTSTATUS

--*/

{
  PDokanVCB vcb;
  PDokanDCB dcb;
  PIO_STACK_LOCATION irpSp;
  NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  ULONG controlCode = 0;
  ULONG outputLength = 0;
  // {DCA0E0A5-D2CA-4f0f-8416-A6414657A77A}
  // GUID dokanGUID = { 0xdca0e0a5, 0xd2ca, 0x4f0f, { 0x84, 0x16, 0xa6, 0x41,
  // 0x46, 0x57, 0xa7, 0x7a } };

  __try {
    Irp->IoStatus.Information = 0;

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    outputLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

    controlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;

    if (controlCode != IOCTL_EVENT_WAIT && controlCode != IOCTL_EVENT_INFO &&
        controlCode != IOCTL_KEEPALIVE) {

      DDbgPrint("==> DokanDispatchIoControl\n");
      DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    }

    if (DeviceObject->DriverObject == NULL ||
        DeviceObject->ReferenceCount < 0) {
      status = STATUS_DEVICE_DOES_NOT_EXIST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;
    PrintIdType(vcb);
    if (GetIdentifierType(vcb) == DGL) {
      status = GlobalDeviceControl(DeviceObject, Irp);
      __leave;
    } else if (GetIdentifierType(vcb) == DCB) {
      status = DiskDeviceControlWithLock(DeviceObject, Irp);
      __leave;
    } else if (GetIdentifierType(vcb) != VCB) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }
    dcb = vcb->Dcb;

    switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
    case IOCTL_EVENT_WAIT:
      DDbgPrint("  IOCTL_EVENT_WAIT\n");
      status = DokanRegisterPendingIrpForEvent(DeviceObject, Irp);
      break;

    case IOCTL_EVENT_INFO:
      // DDbgPrint("  IOCTL_EVENT_INFO\n");
      status = DokanCompleteIrp(DeviceObject, Irp);
      break;

    case IOCTL_EVENT_RELEASE:
      DDbgPrint("  IOCTL_EVENT_RELEASE\n");
      status = DokanEventRelease(DeviceObject, Irp);
      break;

    case IOCTL_EVENT_WRITE:
      DDbgPrint("  IOCTL_EVENT_WRITE\n");
      status = DokanEventWrite(DeviceObject, Irp);
      break;

    case IOCTL_KEEPALIVE:
      DDbgPrint("  IOCTL_KEEPALIVE\n");
      if (IsFlagOn(vcb->Flags, VCB_MOUNTED)) {
        ExEnterCriticalRegionAndAcquireResourceExclusive(&dcb->Resource);
        DokanUpdateTimeout(&dcb->TickCount, DOKAN_KEEPALIVE_TIMEOUT);
        ExReleaseResourceAndLeaveCriticalRegion(&dcb->Resource);
        status = STATUS_SUCCESS;
      } else {
        DDbgPrint(" device is not mounted\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
      }
      break;

    case IOCTL_RESET_TIMEOUT:
      status = DokanResetPendingIrpTimeout(DeviceObject, Irp);
      break;

    case IOCTL_GET_ACCESS_TOKEN:
      status = DokanGetAccessToken(DeviceObject, Irp);
      break;

    default: {
      ULONG baseCode = DEVICE_TYPE_FROM_CTL_CODE(
          irpSp->Parameters.DeviceIoControl.IoControlCode);
      status = STATUS_NOT_IMPLEMENTED;
      // In case of IOCTL_STORAGE_BASE or IOCTL_DISK_BASE OR
      // FILE_DEVICE_NETWORK_FILE_SYSTEM or MOUNTDEVCONTROLTYPE ioctl type, pass
      // to DiskDeviceControl to avoid code duplication
      // TODO: probably not the best way to pass down Irp...
      if (baseCode == IOCTL_STORAGE_BASE || baseCode == IOCTL_DISK_BASE ||
          baseCode == FILE_DEVICE_NETWORK_FILE_SYSTEM ||
          baseCode == MOUNTDEVCONTROLTYPE) {
        status = DiskDeviceControlWithLock(dcb->DeviceObject, Irp);
      }

      if (status == STATUS_NOT_IMPLEMENTED) {
        PrintUnknownDeviceIoctlCode(
            irpSp->Parameters.DeviceIoControl.IoControlCode);
      }
    } break;
    } // switch IoControlCode

  } __finally {

    if (status != STATUS_PENDING) {
      if (IsDeletePending(DeviceObject)) {
        DDbgPrint("  DeviceObject is invalid, so prevent BSOD");
        status = STATUS_DEVICE_REMOVED;
      }
      DokanCompleteIrpRequest(Irp, status, Irp->IoStatus.Information);
    }

    if (controlCode != IOCTL_EVENT_WAIT && controlCode != IOCTL_EVENT_INFO &&
        controlCode != IOCTL_KEEPALIVE) {

      DokanPrintNTStatus(status);
      DDbgPrint("<== DokanDispatchIoControl\n");
    }
  }

  return status;
}
Ejemplo n.º 4
0
static
VOID
TestResourceUndocumentedShortcuts(
    IN PERESOURCE Res,
    IN BOOLEAN AreApcsDisabled)
{
    PVOID Ret;
    LONG Count = 0;

    ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_uint(KeAreAllApcsDisabled(), AreApcsDisabled);

    /* ExEnterCriticalRegionAndAcquireResourceShared, ExEnterCriticalRegionAndAcquireSharedWaitForExclusive */
    Count = 0;
    Ret = ExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count;
    ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
    ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
    CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);

    Ret = ExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count;
    ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
    ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
    CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);

    ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(Res); ++Count;
    ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
    ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
    CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);

    while (Count-- > 1)
    {
        ExReleaseResourceAndLeaveCriticalRegion(Res);
        ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
        ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
        CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
    }

    ExReleaseResourceAndLeaveCriticalRegion(Res);
    ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
    CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);

    /* ExEnterCriticalRegionAndAcquireResourceExclusive */
    Count = 0;
    ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
    Ret = ExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count;
    ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
    ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
    CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);

    Ret = ExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count;
    ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
    ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
    CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);

    ExReleaseResourceAndLeaveCriticalRegion(Res); --Count;
    ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
    CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);

    ExReleaseResourceAndLeaveCriticalRegion(Res); --Count;
    ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
    ok_eq_uint(KeAreAllApcsDisabled(), AreApcsDisabled);
    CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
}