Пример #1
0
// user assinged bigger buffer that is enough to return WriteEventContext
NTSTATUS
DokanEventWrite(__in PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) {
  KIRQL oldIrql;
  PLIST_ENTRY thisEntry, nextEntry, listHead;
  PIRP_ENTRY irpEntry;
  PDokanVCB vcb;
  PEVENT_INFORMATION eventInfo;
  PIRP writeIrp;

  eventInfo = (PEVENT_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  ASSERT(eventInfo != NULL);

  DDbgPrint("==> DokanEventWrite [EventInfo #%X]\n", eventInfo->SerialNumber);

  vcb = DeviceObject->DeviceExtension;

  if (GetIdentifierType(vcb) != VCB) {
    return STATUS_INVALID_PARAMETER;
  }

  ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  KeAcquireSpinLock(&vcb->Dcb->PendingIrp.ListLock, &oldIrql);

  // search corresponding write IRP through pending IRP list
  listHead = &vcb->Dcb->PendingIrp.ListHead;

  for (thisEntry = listHead->Flink; thisEntry != listHead;
       thisEntry = nextEntry) {

    PIO_STACK_LOCATION writeIrpSp, eventIrpSp;
    PEVENT_CONTEXT eventContext;
    ULONG info = 0;
    NTSTATUS status;

    nextEntry = thisEntry->Flink;
    irpEntry = CONTAINING_RECORD(thisEntry, IRP_ENTRY, ListEntry);

    // check whehter this is corresponding IRP

    // DDbgPrint("SerialNumber irpEntry %X eventInfo %X\n",
    // irpEntry->SerialNumber, eventInfo->SerialNumber);

    if (irpEntry->SerialNumber != eventInfo->SerialNumber) {
      continue;
    }

    // do NOT free irpEntry here
    writeIrp = irpEntry->Irp;
    if (writeIrp == NULL) {
      // this IRP has already been canceled
      ASSERT(irpEntry->CancelRoutineFreeMemory == FALSE);
      DokanFreeIrpEntry(irpEntry);
      continue;
    }

    if (IoSetCancelRoutine(writeIrp, DokanIrpCancelRoutine) == NULL) {
      // if (IoSetCancelRoutine(writeIrp, NULL) != NULL) {
      // Cancel routine will run as soon as we release the lock
      InitializeListHead(&irpEntry->ListEntry);
      irpEntry->CancelRoutineFreeMemory = TRUE;
      continue;
    }

    writeIrpSp = irpEntry->IrpSp;
    eventIrpSp = IoGetCurrentIrpStackLocation(Irp);

    ASSERT(writeIrpSp != NULL);
    ASSERT(eventIrpSp != NULL);

    eventContext =
        (PEVENT_CONTEXT)
            writeIrp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT];
    ASSERT(eventContext != NULL);

    // short of buffer length
    if (eventIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        eventContext->Length) {
      DDbgPrint("  EventWrite: STATUS_INSUFFICIENT_RESOURCE\n");
      status = STATUS_INSUFFICIENT_RESOURCES;
    } else {
      PVOID buffer;
      // DDbgPrint("  EventWrite CopyMemory\n");
      // DDbgPrint("  EventLength %d, BufLength %d\n", eventContext->Length,
      //            eventIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
      if (Irp->MdlAddress)
        buffer = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress);
      else
        buffer = Irp->AssociatedIrp.SystemBuffer;

      ASSERT(buffer != NULL);
      RtlCopyMemory(buffer, eventContext, eventContext->Length);

      info = eventContext->Length;
      status = STATUS_SUCCESS;
    }

    DokanFreeEventContext(eventContext);
    writeIrp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;

    KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql);

    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = info;

    // this IRP will be completed by caller function
    return Irp->IoStatus.Status;
  }

  KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql);

  return STATUS_SUCCESS;
}
Пример #2
0
NTSTATUS
DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {
  PIO_STACK_LOCATION irpSp;
  PFILE_OBJECT fileObject;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  PVOID buffer;
  BOOLEAN writeToEoF = FALSE;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN isNonCached = FALSE;
  BOOLEAN isSynchronousIo = FALSE;
  BOOLEAN fcbLocked = FALSE;

  __try {

    DDbgPrint("==> DokanWrite\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    //
    //  If this is a zero length write then return SUCCESS immediately.
    //

    if (irpSp->Parameters.Write.Length == 0) {
      DDbgPrint("  Parameters.Write.Length == 0\n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;

    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);

    ccb = fileObject->FsContext2;
    ASSERT(ccb != NULL);

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (Irp->MdlAddress) {
      DDbgPrint("  use MdlAddress\n");
      buffer = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress);
    } else {
      DDbgPrint("  use UserBuffer\n");
      buffer = Irp->UserBuffer;
    }

    if (buffer == NULL) {
      DDbgPrint("  buffer == NULL\n");
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (irpSp->Parameters.Write.ByteOffset.LowPart ==
            FILE_WRITE_TO_END_OF_FILE &&
        irpSp->Parameters.Write.ByteOffset.HighPart == -1) {
      writeToEoF = TRUE;
    }

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }

    if (Irp->Flags & IRP_NOCACHE) {
      isNonCached = TRUE;
    }

    if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
      isSynchronousIo = TRUE;
    }

    if (!isPagingIo && (fileObject->SectionObjectPointer != NULL) &&
        (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {
      ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
      CcFlushCache(&fcb->SectionObjectPointers,
                   writeToEoF ? NULL : &irpSp->Parameters.Write.ByteOffset,
                   irpSp->Parameters.Write.Length, NULL);
      CcPurgeCacheSection(&fcb->SectionObjectPointers,
                          writeToEoF ? NULL
                                     : &irpSp->Parameters.Write.ByteOffset,
                          irpSp->Parameters.Write.Length, FALSE);
      ExReleaseResourceLite(&fcb->PagingIoResource);
    }

    // Cannot write at end of the file when using paging IO
    if (writeToEoF && isPagingIo) {
      DDbgPrint("  writeToEoF & isPagingIo\n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    // the length of EventContext is sum of length to write and length of file
    // name
    DokanFCBLockRO(fcb);
    fcbLocked = TRUE;
    eventLength = sizeof(EVENT_CONTEXT) + irpSp->Parameters.Write.Length +
                  fcb->FileName.Length;

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

    // no more memory!
    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;
    // DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

    // When the length is bigger than usual event notitfication buffer,
    // saves pointer in DiverContext to copy EventContext after allocating
    // more bigger memory.
    Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = eventContext;

    if (isPagingIo) {
      DDbgPrint("  Paging IO\n");
      eventContext->FileFlags |= DOKAN_PAGING_IO;
    }
    if (isSynchronousIo) {
      DDbgPrint("  Synchronous IO\n");
      eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
    }
    if (isNonCached) {
      DDbgPrint("  Nocache\n");
      eventContext->FileFlags |= DOKAN_NOCACHE;
    }

    // offset of file to write
    eventContext->Operation.Write.ByteOffset =
        irpSp->Parameters.Write.ByteOffset;

    if (writeToEoF) {
      eventContext->FileFlags |= DOKAN_WRITE_TO_END_OF_FILE;
      DDbgPrint("  WriteOffset = end of file\n");
    }

    if (isSynchronousIo &&
        ((irpSp->Parameters.Write.ByteOffset.LowPart ==
          FILE_USE_FILE_POINTER_POSITION) &&
         (irpSp->Parameters.Write.ByteOffset.HighPart == -1))) {
      // NOTE:
      // http://msdn.microsoft.com/en-us/library/ms795960.aspx
      // Do not check IrpSp->Parameters.Write.ByteOffset.QuadPart == 0
      // Probably the document is wrong.
      eventContext->Operation.Write.ByteOffset.QuadPart =
          fileObject->CurrentByteOffset.QuadPart;
    }

    // the size of buffer to write
    eventContext->Operation.Write.BufferLength = irpSp->Parameters.Write.Length;

    // the offset from the begining of structure
    // the contents to write will be copyed to this offset
    eventContext->Operation.Write.BufferOffset =
        FIELD_OFFSET(EVENT_CONTEXT, Operation.Write.FileName[0]) +
        fcb->FileName.Length + sizeof(WCHAR); // adds last null char

    // copies the content to write to EventContext
    RtlCopyMemory((PCHAR)eventContext +
                      eventContext->Operation.Write.BufferOffset,
                  buffer, irpSp->Parameters.Write.Length);

    // copies file name
    eventContext->Operation.Write.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.Write.FileName, fcb->FileName.Buffer,
                  fcb->FileName.Length);

    // When eventlength is less than event notification buffer,
    // returns it to user-mode using pending event.
    if (eventLength <= EVENT_CONTEXT_MAX_SIZE) {

      DDbgPrint("   Offset %d:%d, Length %d\n",
                irpSp->Parameters.Write.ByteOffset.HighPart,
                irpSp->Parameters.Write.ByteOffset.LowPart,
                irpSp->Parameters.Write.Length);

      // EventContext is no longer needed, clear it
      Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;

      //
      //  We now check whether we can proceed based on the state of
      //  the file oplocks.
      //
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
        status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext,
                                  DokanOplockComplete, DokanPrePostIrp);

        //
        //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
        //  to service an oplock break and we need to leave now.
        //
        if (status != STATUS_SUCCESS) {
          if (status == STATUS_PENDING) {
            DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
          } else {
            DokanFreeEventContext(eventContext);
          }
          __leave;
        }
      }

      // register this IRP to IRP waiting list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

      // Resuests bigger memory
      // eventContext will be freed later using
      // Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT]
    } else {
      // the length at lest file name can be stored
      ULONG requestContextLength = max(
          sizeof(EVENT_CONTEXT), eventContext->Operation.Write.BufferOffset);
      PEVENT_CONTEXT requestContext =
          AllocateEventContext(vcb->Dcb, Irp, requestContextLength, ccb);

      // no more memory!
      if (requestContext == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;
        DokanFreeEventContext(eventContext);
        __leave;
      }

      DDbgPrint("   Offset %d:%d, Length %d (request)\n",
                irpSp->Parameters.Write.ByteOffset.HighPart,
                irpSp->Parameters.Write.ByteOffset.LowPart,
                irpSp->Parameters.Write.Length);

      // copies from begining of EventContext to the end of file name
      RtlCopyMemory(requestContext, eventContext,
                    eventContext->Operation.Write.BufferOffset);
      // puts actual size of RequestContext
      requestContext->Length = requestContextLength;
      // requsts enough size to copy EventContext
      requestContext->Operation.Write.RequestLength = eventLength;

      //
      //  We now check whether we can proceed based on the state of
      //  the file oplocks.
      //
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
        status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, requestContext,
                                  DokanOplockComplete, DokanPrePostIrp);

        //
        //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
        //  to service an oplock break and we need to leave now.
        //
        if (status != STATUS_SUCCESS) {
          if (status == STATUS_PENDING) {
            DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
          } else {
            DokanFreeEventContext(requestContext);
            Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;
            DokanFreeEventContext(eventContext);
          }
          __leave;
        }
      }

      // regiters this IRP to IRP wainting list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, requestContext, 0);
    }

  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, 0);

    DDbgPrint("<== DokanWrite\n");
  }

  return status;
}
Пример #3
0
NTSTATUS
DokanDispatchRead(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

/*++

Routine Description:

        This device control dispatcher handles read IRPs.

Arguments:

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

Return Value:

        NTSTATUS

--*/
{
  PIO_STACK_LOCATION irpSp;
  PFILE_OBJECT fileObject;
  ULONG bufferLength;
  LARGE_INTEGER byteOffset;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  ULONG readLength = 0;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  PVOID currentAddress = NULL;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;
  BOOLEAN fcbLocked = FALSE;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN isSynchronousIo = FALSE;
  BOOLEAN noCache = FALSE;

  __try {

    DDbgPrint("==> DokanRead\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    //
    //  If this is a zero length read then return SUCCESS immediately.
    //
    if (irpSp->Parameters.Read.Length == 0) {
      DDbgPrint("  Parameters.Read.Length == 0 \n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (irpSp->MinorFunction == IRP_MN_COMPLETE) {
      Irp->MdlAddress = NULL;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL && Irp->MdlAddress != NULL) {
      DDbgPrint("  Reads by File System Recognizers\n");

      currentAddress = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress);
      if (currentAddress == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        __leave;
      }

      // here we could return the bootsector. If we don't have one
      // the requested read lenght must be returned as requested
      readLength = irpSp->Parameters.Read.Length;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;
    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    bufferLength = irpSp->Parameters.Read.Length;
    if (irpSp->Parameters.Read.ByteOffset.LowPart ==
            FILE_USE_FILE_POINTER_POSITION &&
        irpSp->Parameters.Read.ByteOffset.HighPart == -1) {

      // irpSp->Parameters.Read.ByteOffset == NULL don't need check?

      DDbgPrint("use FileObject ByteOffset\n");

      byteOffset = fileObject->CurrentByteOffset;

    } else {
      byteOffset = irpSp->Parameters.Read.ByteOffset;
    }

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);
    DDbgPrint("  ByteCount:%lu ByteOffset:%I64d\n", bufferLength,
              byteOffset.QuadPart);

    if (bufferLength == 0) {
      status = STATUS_SUCCESS;
      readLength = 0;
      __leave;
    }

    // make a MDL for UserBuffer that can be used later on another thread
    // context
    if (Irp->MdlAddress == NULL) {
      status = DokanAllocateMdl(Irp, irpSp->Parameters.Read.Length);
      if (!NT_SUCCESS(status)) {
        __leave;
      }
    }

    ccb = fileObject->FsContext2;
    ASSERT(ccb != NULL);

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) {
      DDbgPrint("   DOKAN_FILE_DIRECTORY %p\n", fcb);
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }
    if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
      isSynchronousIo = TRUE;
    }

    if (Irp->Flags & IRP_NOCACHE) {
      noCache = TRUE;
    }

    if (!isPagingIo && (fileObject->SectionObjectPointer != NULL) &&
        (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {
      ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
      CcFlushCache(&fcb->SectionObjectPointers,
                   &irpSp->Parameters.Read.ByteOffset,
                   irpSp->Parameters.Read.Length, NULL);
      ExReleaseResourceLite(&fcb->PagingIoResource);
    }

    DokanFCBLockRO(fcb);
    fcbLocked = TRUE;
    // length of EventContext is sum of file name length and itself
    eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);
    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;
    // DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

    if (isPagingIo) {
      DDbgPrint("  Paging IO\n");
      eventContext->FileFlags |= DOKAN_PAGING_IO;
    }
    if (isSynchronousIo) {
      DDbgPrint("  Synchronous IO\n");
      eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
    }

    if (noCache) {
      DDbgPrint("  Nocache\n");
      eventContext->FileFlags |= DOKAN_NOCACHE;
    }

    // offset of file to read
    eventContext->Operation.Read.ByteOffset = byteOffset;

    // buffer size for read
    // user-mode file system application can return this size
    eventContext->Operation.Read.BufferLength = irpSp->Parameters.Read.Length;

    // copy the accessed file name
    eventContext->Operation.Read.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.Read.FileName, fcb->FileName.Buffer,
                  fcb->FileName.Length);

    //
    //  We now check whether we can proceed based on the state of
    //  the file oplocks.
    //
    if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext,
                                DokanOplockComplete, DokanPrePostIrp);

      //
      //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
      //  to service an oplock break and we need to leave now.
      //
      if (status != STATUS_SUCCESS) {
        if (status == STATUS_PENDING) {
          DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
        } else {
          DokanFreeEventContext(eventContext);
        }
        __leave;
      }

      //
      // We have to check for read access according to the current
      // state of the file locks, and set FileSize from the Fcb.
      //
      // FsRtlCheckLockForReadAccess does not block.
      if (!FsRtlCheckLockForReadAccess(&fcb->FileLock, Irp)) {
        status = STATUS_FILE_LOCK_CONFLICT;
        __leave;
      }
    }

    // register this IRP to pending IPR list and make it pending status
    status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);
  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, readLength);

    DDbgPrint("<== DokanRead\n");
  }

  return status;
}
Пример #4
0
VOID DokanCompleteRead(__in PIRP_ENTRY IrpEntry,
                       __in PEVENT_INFORMATION EventInfo) {
  PIRP irp;
  PIO_STACK_LOCATION irpSp;
  NTSTATUS status = STATUS_SUCCESS;
  ULONG readLength = 0;
  ULONG bufferLen = 0;
  PVOID buffer = NULL;
  PDokanCCB ccb;
  PFILE_OBJECT fileObject;

  fileObject = IrpEntry->FileObject;
  ASSERT(fileObject != NULL);

  DDbgPrint("==> DokanCompleteRead %wZ\n", &fileObject->FileName);

  irp = IrpEntry->Irp;
  irpSp = IrpEntry->IrpSp;

  ccb = fileObject->FsContext2;
  ASSERT(ccb != NULL);

  ccb->UserContext = EventInfo->Context;
  // DDbgPrint("   set Context %X\n", (ULONG)ccb->UserContext);

  // buffer which is used to copy Read info
  if (irp->MdlAddress) {
    // DDbgPrint("   use MDL Address\n");
    buffer = MmGetSystemAddressForMdlNormalSafe(irp->MdlAddress);
  } else {
    // DDbgPrint("   use UserBuffer\n");
    buffer = irp->UserBuffer;
  }

  // available buffer size
  bufferLen = irpSp->Parameters.Read.Length;

  DDbgPrint("  bufferLen %d, Event.BufferLen %d\n", bufferLen,
            EventInfo->BufferLength);

  // buffer is not specified or short of length
  if (bufferLen == 0 || buffer == NULL || bufferLen < EventInfo->BufferLength) {

    readLength = 0;
    status = STATUS_INSUFFICIENT_RESOURCES;

  } else {
    RtlZeroMemory(buffer, bufferLen);
    RtlCopyMemory(buffer, EventInfo->Buffer, EventInfo->BufferLength);

    // read length which is actually read
    readLength = EventInfo->BufferLength;
    status = EventInfo->Status;

    if (NT_SUCCESS(status) && EventInfo->BufferLength > 0 &&
        (fileObject->Flags & FO_SYNCHRONOUS_IO) &&
        !(irp->Flags & IRP_PAGING_IO)) {
      // update current byte offset only when synchronous IO and not pagind IO
      fileObject->CurrentByteOffset.QuadPart =
          EventInfo->Operation.Read.CurrentByteOffset.QuadPart;
      DDbgPrint("  Updated CurrentByteOffset %I64d\n",
                fileObject->CurrentByteOffset.QuadPart);
    }
  }

  if (NT_SUCCESS(status)) {
    DDbgPrint("  STATUS_SUCCESS\n");
  } else if (status == STATUS_INSUFFICIENT_RESOURCES) {
    DDbgPrint("  STATUS_INSUFFICIENT_RESOURCES\n");
  } else if (status == STATUS_END_OF_FILE) {
    DDbgPrint("  STATUS_END_OF_FILE\n");
  } else {
    DDbgPrint("  status = 0x%X\n", status);
  }

  DokanCompleteIrpRequest(irp, status, readLength);

  DDbgPrint("<== DokanCompleteRead\n");
}
Пример #5
0
VOID DokanCompleteDirectoryControl(__in PIRP_ENTRY IrpEntry,
                                   __in PEVENT_INFORMATION EventInfo) {
  PIRP irp;
  PIO_STACK_LOCATION irpSp;
  NTSTATUS status = STATUS_SUCCESS;
  ULONG info = 0;
  ULONG bufferLen = 0;
  PVOID buffer = NULL;

  DDbgPrint("==> DokanCompleteDirectoryControl\n");

  irp = IrpEntry->Irp;
  irpSp = IrpEntry->IrpSp;

  // buffer pointer which points DirecotryInfo
  if (irp->MdlAddress) {
    // DDbgPrint("   use MDL Address\n");
    buffer = MmGetSystemAddressForMdlNormalSafe(irp->MdlAddress);
  } else {
    // DDbgPrint("   use UserBuffer\n");
    buffer = irp->UserBuffer;
  }
  // usable buffer size
  bufferLen = irpSp->Parameters.QueryDirectory.Length;

  // DDbgPrint("  !!Returning DirecotyInfo!!\n");

  // buffer is not specified or short of length
  if (bufferLen == 0 || buffer == NULL || bufferLen < EventInfo->BufferLength) {
    info = 0;
    status = STATUS_INSUFFICIENT_RESOURCES;

  } else {

    PDokanCCB ccb = IrpEntry->FileObject->FsContext2;
    // ULONG     orgLen = irpSp->Parameters.QueryDirectory.Length;

    //
    // set the information recieved from user mode
    //
    ASSERT(buffer != NULL);

    RtlZeroMemory(buffer, bufferLen);

    // DDbgPrint("   copy DirectoryInfo\n");
    RtlCopyMemory(buffer, EventInfo->Buffer, EventInfo->BufferLength);

    DDbgPrint("    eventInfo->Directory.Index = %lu\n",
              EventInfo->Operation.Directory.Index);
    DDbgPrint("    eventInfo->BufferLength    = %lu\n",
              EventInfo->BufferLength);
    DDbgPrint("    eventInfo->Status = %x (%lu)\n", EventInfo->Status,
              EventInfo->Status);

    // update index which specified n-th directory entry is returned
    // this should be locked before writing?
    ccb->Context = EventInfo->Operation.Directory.Index;

    ccb->UserContext = EventInfo->Context;
    // DDbgPrint("   set Context %X\n", (ULONG)ccb->UserContext);

    // written bytes
    // irpSp->Parameters.QueryDirectory.Length = EventInfo->BufferLength;

    status = EventInfo->Status;

    info = EventInfo->BufferLength;
  }

  if (IrpEntry->Flags & DOKAN_MDL_ALLOCATED) {
    DokanFreeMdl(irp);
    IrpEntry->Flags &= ~DOKAN_MDL_ALLOCATED;
  }

  DokanCompleteIrpRequest(irp, status, info);

  DDbgPrint("<== DokanCompleteDirectoryControl\n");
}