Beispiel #1
0
NTSTATUS
TapeGetDriveParameters(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++
Routine Description:


    This routine returns the default fixed-block size, the maximum block size,
    the minimum block size, the maximum number of partitions, and the device
    features flag.

Arguments:

    DeviceObject
    Irp

Return Value:

    NTSTATUS

--*/

{
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
    PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer;
    PNINE_TRACKSENSE_DATA buffer;
    PREAD_BLOCK_LIMITS_DATA blockLimits;
    SCSI_REQUEST_BLOCK  srb;
    PCDB                cdb = (PCDB)srb.Cdb;
    NTSTATUS            status;

    DebugPrint((3,"TapeGetDriveParameters: Get Tape Drive Parameters\n"));

    //
    // Zero CDB in SRB on stack.
    //

    RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);

    srb.CdbLength = CDB6GENERIC_LENGTH;

    cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;

    //
    // Set timeout value.
    //

    srb.TimeOutValue = deviceExtension->TimeOutValue;

    cdb->MODE_SENSE.AllocationLength = sizeof(NINE_TRACKSENSE_DATA);
    cdb->MODE_SENSE.PageCode = MODE_SENSE_CURRENT_VALUES;
    cdb->MODE_SENSE.Pc = 0x0B;

    buffer = ExAllocatePool(NonPagedPoolCacheAligned,
        sizeof(NINE_TRACKSENSE_DATA));

    if (!buffer) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = ScsiClassSendSrbSynchronous(DeviceObject,
                                &srb,
                                buffer,
                                sizeof(NINE_TRACKSENSE_DATA),
                                FALSE);

    if (NT_SUCCESS(status)) {
        Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);

        //
        // Indicate support of following:
        //

        tapeGetDriveParams->ECC = FALSE;
        tapeGetDriveParams->Compression = FALSE;
        tapeGetDriveParams->DataPadding = FALSE;
        tapeGetDriveParams->ReportSetmarks = FALSE;

        tapeGetDriveParams->FeaturesLow =
            TAPE_DRIVE_ERASE_SHORT |
            TAPE_DRIVE_FIXED_BLOCK |
            TAPE_DRIVE_VARIABLE_BLOCK |
            TAPE_DRIVE_WRITE_PROTECT |
            TAPE_DRIVE_GET_ABSOLUTE_BLK |
            TAPE_DRIVE_GET_LOGICAL_BLK;

        tapeGetDriveParams->FeaturesHigh =
            TAPE_DRIVE_LOAD_UNLOAD |
            TAPE_DRIVE_LOCK_UNLOCK |
            TAPE_DRIVE_SET_BLOCK_SIZE |
            TAPE_DRIVE_ABSOLUTE_BLK |
            TAPE_DRIVE_ABS_BLK_IMMED |
            TAPE_DRIVE_LOGICAL_BLK |
            TAPE_DRIVE_END_OF_DATA |
            TAPE_DRIVE_FILEMARKS |
            TAPE_DRIVE_SEQUENTIAL_FMKS |
            TAPE_DRIVE_REVERSE_POSITION |
            TAPE_DRIVE_WRITE_FILEMARKS;
    }

    ExFreePool(buffer);

    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Zero CDB in SRB on stack.
    //

    RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);

    srb.CdbLength = CDB6GENERIC_LENGTH;

    cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS;

    //
    // Set timeout value.
    //

    srb.TimeOutValue = deviceExtension->TimeOutValue;

    blockLimits = ExAllocatePool(NonPagedPoolCacheAligned,
        sizeof(READ_BLOCK_LIMITS_DATA));

    if (!blockLimits) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA));

    status = ScsiClassSendSrbSynchronous(DeviceObject,
                                &srb,
                                blockLimits,
                                sizeof(READ_BLOCK_LIMITS_DATA),
                                FALSE);

    if (NT_SUCCESS(status)) {
        tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2];
        tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8);
        tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16);

        tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1];
        tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8);
    }

    ExFreePool(blockLimits);

    return status;

} // end TapeGetDriveParameters()
Beispiel #2
0
/* Creates the client side */
NTSTATUS DEFAULTAPI
MsfsCreate(PDEVICE_OBJECT DeviceObject,
           PIRP Irp)
{
    PIO_STACK_LOCATION IoStack;
    PFILE_OBJECT FileObject;
    PMSFS_DEVICE_EXTENSION DeviceExtension;
    PMSFS_FCB Fcb;
    PMSFS_CCB Ccb;
    PMSFS_FCB current = NULL;
    PLIST_ENTRY current_entry;
    KIRQL oldIrql;

    DPRINT("MsfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);

    IoStack = IoGetCurrentIrpStackLocation(Irp);
    DeviceExtension = DeviceObject->DeviceExtension;
    FileObject = IoStack->FileObject;

    DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);

    Ccb = ExAllocatePool(NonPagedPool, sizeof(MSFS_CCB));
    if (Ccb == NULL)
    {
        Irp->IoStatus.Status = STATUS_NO_MEMORY;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_NO_MEMORY;
    }

    KeLockMutex(&DeviceExtension->FcbListLock);
    current_entry = DeviceExtension->FcbListHead.Flink;
    while (current_entry != &DeviceExtension->FcbListHead)
    {
        current = CONTAINING_RECORD(current_entry,
                                    MSFS_FCB,
                                    FcbListEntry);

        if (!RtlCompareUnicodeString(&FileObject->FileName, &current->Name, TRUE))
            break;

        current_entry = current_entry->Flink;
    }

    if (current_entry == &DeviceExtension->FcbListHead)
    {
        ExFreePool(Ccb);
        KeUnlockMutex(&DeviceExtension->FcbListLock);

        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return STATUS_UNSUCCESSFUL;
    }

    Fcb = current;

    KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
    InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
    KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);

    Fcb->ReferenceCount++;

    Ccb->Fcb = Fcb;

    KeUnlockMutex(&DeviceExtension->FcbListLock);

    FileObject->FsContext = Fcb;
    FileObject->FsContext2 = Ccb;
    FileObject->Flags |= FO_MAILSLOT;

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}
Beispiel #3
0
NTSTATUS
NTAPI
SeLocateProcessImageName(IN PEPROCESS Process,
                         OUT PUNICODE_STRING *ProcessImageName)
{
    POBJECT_NAME_INFORMATION AuditName;
    PUNICODE_STRING ImageName;
    PFILE_OBJECT FileObject;
    NTSTATUS Status = STATUS_SUCCESS;

    PAGED_CODE();

    /* Assume failure */
    *ProcessImageName = NULL;

    /* Check if we have audit info */
    AuditName = Process->SeAuditProcessCreationInfo.ImageFileName;
    if (!AuditName)
    {
        /* Get the file object */
        Status = PsReferenceProcessFilePointer(Process, &FileObject);
        if (!NT_SUCCESS(Status)) return Status;

        /* Initialize the audit structure */
        Status = SeInitializeProcessAuditName(FileObject, TRUE, &AuditName);
        if (NT_SUCCESS(Status))
        {
            /* Set it */
            if (InterlockedCompareExchangePointer((PVOID*)&Process->
                                                  SeAuditProcessCreationInfo.ImageFileName,
                                                  AuditName,
                                                  NULL))
            {
                /* Someone beat us to it, deallocate our copy */
                ExFreePool(AuditName);
            }
        }

        /* Dereference the file object */
        ObDereferenceObject(FileObject);
        if (!NT_SUCCESS(Status)) return Status;
    }

    /* Get audit info again, now we have it for sure */
    AuditName = Process->SeAuditProcessCreationInfo.ImageFileName;

    /* Allocate the output string */
    ImageName = ExAllocatePoolWithTag(NonPagedPool,
                                      AuditName->Name.MaximumLength +
                                      sizeof(UNICODE_STRING),
                                      TAG_SEPA);
    if (!ImageName) return STATUS_NO_MEMORY;

    /* Make a copy of it */
    RtlCopyMemory(ImageName,
                  &AuditName->Name,
                  AuditName->Name.MaximumLength + sizeof(UNICODE_STRING));

    /* Fix up the buffer */
    ImageName->Buffer = (PWSTR)(ImageName + 1);

    /* Return it */
    *ProcessImageName = ImageName;

    /* Return status */
    return Status;
}
Beispiel #4
0
NTSTATUS
FsRtlGetTunnelParameterValue (
    IN PUNICODE_STRING ValueName,
    IN OUT PULONG Value
    )

/*++

Routine Description:

    Given a unicode value name this routine will go into the registry
    location for the Tunnel parameter information and get the
    value.

Arguments:

    ValueName - the unicode name for the registry value located in the
                double space configuration location of the registry.
    Value   - a pointer to the ULONG for the result.

Return Value:

    NTSTATUS

    If STATUS_SUCCESSFUL is returned, the location *Value will be
    updated with the DWORD value from the registry.  If any failing
    status is returned, this value is untouched.

--*/

{
    HANDLE Handle;
    NTSTATUS Status;
    ULONG RequestLength;
    ULONG ResultLength;
    UCHAR Buffer[KEY_WORK_AREA];
    UNICODE_STRING KeyName;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PKEY_VALUE_FULL_INFORMATION KeyValueInformation;

    KeyName.Buffer = TUNNEL_KEY_NAME;
    KeyName.Length = sizeof(TUNNEL_KEY_NAME) - sizeof(WCHAR);
    KeyName.MaximumLength = sizeof(TUNNEL_KEY_NAME);

    InitializeObjectAttributes(&ObjectAttributes,
                               &KeyName,
                               OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);

    Status = ZwOpenKey(&Handle,
                       KEY_READ,
                       &ObjectAttributes);

    if (!NT_SUCCESS(Status)) {

        return Status;
    }

    RequestLength = KEY_WORK_AREA;

    KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;

    while (1) {

        Status = ZwQueryValueKey(Handle,
                                 ValueName,
                                 KeyValueFullInformation,
                                 KeyValueInformation,
                                 RequestLength,
                                 &ResultLength);

        ASSERT( Status != STATUS_BUFFER_OVERFLOW );

        if (Status == STATUS_BUFFER_OVERFLOW) {

            //
            // Try to get a buffer big enough.
            //

            if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {

                ExFreePool(KeyValueInformation);
            }

            RequestLength += 256;

            KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)
                                  ExAllocatePoolWithTag(PagedPool,
                                                        RequestLength,
                                                        'KnuT');

            if (!KeyValueInformation) {
                return STATUS_NO_MEMORY;
            }

        } else {

            break;
        }
    }

    ZwClose(Handle);

    if (NT_SUCCESS(Status)) {

        if (KeyValueInformation->DataLength != 0) {

            PULONG DataPtr;

            //
            // Return contents to the caller.
            //

            DataPtr = (PULONG)
              ((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
            *Value = *DataPtr;

        } else {

            //
            // Treat as if no value was found
            //

            Status = STATUS_OBJECT_NAME_NOT_FOUND;
        }
    }

    if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {

        ExFreePool(KeyValueInformation);
    }

    return Status;
}
Beispiel #5
0
NTSTATUS
DiskDeviceControl(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {
  PIO_STACK_LOCATION irpSp;
  PDokanDCB dcb;
  PDokanVCB vcb;
  NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  ULONG outputLength = 0;
  ULONG inputLength = 0;

  DDbgPrint("   => DokanDiskDeviceControl\n");
  irpSp = IoGetCurrentIrpStackLocation(Irp);
  dcb = DeviceObject->DeviceExtension;
  outputLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  inputLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;

  if (GetIdentifierType(dcb) != DCB) {
    PrintIdType(dcb);
    DDbgPrint("   Device is not dcb so go out here\n");
    return STATUS_INVALID_PARAMETER;
  }

  if (IsDeletePending(DeviceObject)) {
    DDbgPrint("   Device object is pending for delete valid anymore\n");
    return STATUS_DEVICE_REMOVED;
  }

  vcb = dcb->Vcb;
  if (IsUnmountPendingVcb(vcb)) {
    DDbgPrint("   Volume is unmounted so ignore dcb requests\n");
    return STATUS_NO_SUCH_DEVICE;
  }

  DDbgPrint("   DiskDeviceControl Device name %wZ \n", dcb->DiskDeviceName);

  switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
    PDISK_GEOMETRY diskGeometry;

    DDbgPrint("  IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
    if (outputLength < sizeof(DISK_GEOMETRY)) {
      Irp->IoStatus.Information = 0;
      status = STATUS_BUFFER_TOO_SMALL;
      break;
    }

    diskGeometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(diskGeometry != NULL);

    DokanPopulateDiskGeometry(diskGeometry);

    Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
    status = STATUS_SUCCESS;
  } break;

  case IOCTL_DISK_GET_LENGTH_INFO: {
    PGET_LENGTH_INFORMATION getLengthInfo;

    DDbgPrint("  IOCTL_DISK_GET_LENGTH_INFO\n");

    if (outputLength < sizeof(GET_LENGTH_INFORMATION)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }

    getLengthInfo = (PGET_LENGTH_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(getLengthInfo != NULL);

    getLengthInfo->Length.QuadPart = 1024 * 1024 * 500;
    status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
  } break;

  case IOCTL_DISK_GET_DRIVE_LAYOUT:
  case IOCTL_DISK_GET_DRIVE_LAYOUT_EX:
  case IOCTL_DISK_GET_PARTITION_INFO:
  case IOCTL_DISK_GET_PARTITION_INFO_EX: {
    // Fake drive layout/partition information

    VOID *outputBuffer = Irp->AssociatedIrp.SystemBuffer;
    ULONG ioctl = irpSp->Parameters.DeviceIoControl.IoControlCode;

    switch (ioctl) {
    case IOCTL_DISK_GET_DRIVE_LAYOUT:
      DDbgPrint("  IOCTL_DISK_GET_DRIVE_LAYOUT\n");
      Irp->IoStatus.Information =
          FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]);
      break;
    case IOCTL_DISK_GET_DRIVE_LAYOUT_EX:
      DDbgPrint("  IOCTL_DISK_GET_DRIVE_LAYOUT_EX\n");
      Irp->IoStatus.Information =
          FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]);
      break;
    case IOCTL_DISK_GET_PARTITION_INFO:
      DDbgPrint("  IOCTL_DISK_GET_PARTITION_INFO\n");
      Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
      break;
    case IOCTL_DISK_GET_PARTITION_INFO_EX:
      DDbgPrint("  IOCTL_DISK_GET_PARTITION_INFO_EX\n");
      Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX);
      break;
    }

    if (outputLength < Irp->IoStatus.Information) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }
    RtlZeroMemory(outputBuffer, Irp->IoStatus.Information);

    // if we are getting the drive layout, then we need to start by
    // adding some of the non-partition stuff that says we have
    // exactly one partition available.
    if (ioctl == IOCTL_DISK_GET_DRIVE_LAYOUT) {
      PDRIVE_LAYOUT_INFORMATION layout;
      layout = (PDRIVE_LAYOUT_INFORMATION)outputBuffer;
      layout->PartitionCount = 1;
      layout->Signature = 1;
      outputBuffer = (PVOID)(layout->PartitionEntry);
      ioctl = IOCTL_DISK_GET_PARTITION_INFO;
    } else if (ioctl == IOCTL_DISK_GET_DRIVE_LAYOUT_EX) {
      PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
      layoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)outputBuffer;
      layoutEx->PartitionStyle = PARTITION_STYLE_MBR;
      layoutEx->PartitionCount = 1;
      layoutEx->Mbr.Signature = 1;
      outputBuffer = (PVOID)(layoutEx->PartitionEntry);
      ioctl = IOCTL_DISK_GET_PARTITION_INFO_EX;
    }

    // NOTE: the local var 'ioctl' is now modified to either EX or
    // non-EX version. the local var 'systemBuffer' is now pointing
    // to the partition information structure.
    if (ioctl == IOCTL_DISK_GET_PARTITION_INFO) {
      PPARTITION_INFORMATION partitionInfo;
      partitionInfo = (PPARTITION_INFORMATION)outputBuffer;
      partitionInfo->RewritePartition = FALSE;
      partitionInfo->RecognizedPartition = FALSE;
      partitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
      partitionInfo->BootIndicator = FALSE;
      partitionInfo->HiddenSectors = 0;
      partitionInfo->StartingOffset.QuadPart = 0;
      partitionInfo->PartitionLength.QuadPart =
          DOKAN_DEFAULT_DISK_SIZE; // Partition size equels disk size here
      partitionInfo->PartitionNumber = 0;
    } else {
      PPARTITION_INFORMATION_EX partitionInfo;
      partitionInfo = (PPARTITION_INFORMATION_EX)outputBuffer;
      partitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
      partitionInfo->RewritePartition = FALSE;
      partitionInfo->Mbr.RecognizedPartition = FALSE;
      partitionInfo->Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
      partitionInfo->Mbr.BootIndicator = FALSE;
      partitionInfo->Mbr.HiddenSectors = 0;
      partitionInfo->StartingOffset.QuadPart = 0;
      partitionInfo->PartitionLength.QuadPart =
          DOKAN_DEFAULT_DISK_SIZE; // Partition size equels disk size here
      partitionInfo->PartitionNumber = 0;
    }

    status = STATUS_SUCCESS;
  } break;

  case IOCTL_DISK_IS_WRITABLE:
    DDbgPrint("  IOCTL_DISK_IS_WRITABLE\n");
    status = IS_DEVICE_READ_ONLY(DeviceObject) ? STATUS_MEDIA_WRITE_PROTECTED
                                               : STATUS_SUCCESS;
    break;

  case IOCTL_DISK_MEDIA_REMOVAL:
    DDbgPrint("  IOCTL_DISK_MEDIA_REMOVAL\n");
    status = STATUS_SUCCESS;
    break;

  case IOCTL_STORAGE_MEDIA_REMOVAL:
    DDbgPrint("  IOCTL_STORAGE_MEDIA_REMOVAL\n");
    status = STATUS_SUCCESS;
    break;

  case IOCTL_DISK_SET_PARTITION_INFO:
    DDbgPrint("  IOCTL_DISK_SET_PARTITION_INFO\n");
    break;

  case IOCTL_DISK_VERIFY:
    DDbgPrint("  IOCTL_DISK_VERIFY\n");
    break;

  case IOCTL_STORAGE_GET_HOTPLUG_INFO: {
    PSTORAGE_HOTPLUG_INFO hotplugInfo;
    DDbgPrint("  IOCTL_STORAGE_GET_HOTPLUG_INFO\n");
    if (outputLength < sizeof(STORAGE_HOTPLUG_INFO)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }
    hotplugInfo = Irp->AssociatedIrp.SystemBuffer;
    hotplugInfo->Size = sizeof(STORAGE_HOTPLUG_INFO);
    hotplugInfo->MediaRemovable = 1;
    hotplugInfo->MediaHotplug = 1;
    hotplugInfo->DeviceHotplug = 1;
    hotplugInfo->WriteCacheEnableOverride = 0;
    status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO);
  } break;

  case IOCTL_VOLUME_GET_GPT_ATTRIBUTES: {
    DDbgPrint("   IOCTL_VOLUME_GET_GPT_ATTRIBUTES\n");
    PVOLUME_GET_GPT_ATTRIBUTES_INFORMATION gptAttrInfo;
    if (outputLength < sizeof(VOLUME_GET_GPT_ATTRIBUTES_INFORMATION)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }
    // Set GPT read-only flag if device is not writable
    gptAttrInfo = Irp->AssociatedIrp.SystemBuffer;
    if (IS_DEVICE_READ_ONLY(DeviceObject))
      gptAttrInfo->GptAttributes = GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY;
    Irp->IoStatus.Information = sizeof(VOLUME_GET_GPT_ATTRIBUTES_INFORMATION);
    status = STATUS_SUCCESS;
  } break;

  case IOCTL_STORAGE_CHECK_VERIFY:
  case IOCTL_DISK_CHECK_VERIFY:
    DDbgPrint("  IOCTL_STORAGE_CHECK_VERIFY\n");
    status = STATUS_SUCCESS;
    break;

  case IOCTL_STORAGE_CHECK_VERIFY2:
    DDbgPrint("  IOCTL_STORAGE_CHECK_VERIFY2\n");
    status = STATUS_SUCCESS;
    break;
  case IOCTL_STORAGE_QUERY_PROPERTY:
    DDbgPrint("  IOCTL_STORAGE_QUERY_PROPERTY\n");
    PSTORAGE_PROPERTY_QUERY query = NULL;
    query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(query != NULL);
    if (query->QueryType == PropertyExistsQuery) {
      if (query->PropertyId == StorageDeviceUniqueIdProperty) {
        PSTORAGE_DEVICE_UNIQUE_IDENTIFIER storage;
        DDbgPrint("    PropertyExistsQuery StorageDeviceUniqueIdProperty\n");
        if (outputLength < sizeof(STORAGE_DEVICE_UNIQUE_IDENTIFIER)) {
          status = STATUS_BUFFER_TOO_SMALL;
          Irp->IoStatus.Information = 0;
          break;
        }
        storage = Irp->AssociatedIrp.SystemBuffer;

        status = STATUS_SUCCESS;
      } else if (query->PropertyId == StorageDeviceWriteCacheProperty) {
        DDbgPrint("    PropertyExistsQuery StorageDeviceWriteCacheProperty\n");
        status = STATUS_NOT_IMPLEMENTED;
      } else {
        DDbgPrint("    PropertyExistsQuery Unknown %d\n", query->PropertyId);
        status = STATUS_NOT_IMPLEMENTED;
      }
    } else if (query->QueryType == PropertyStandardQuery) {
      if (query->PropertyId == StorageDeviceProperty) {
        PSTORAGE_DEVICE_DESCRIPTOR storage;
        DDbgPrint("    PropertyStandardQuery StorageDeviceProperty\n");
        if (outputLength < sizeof(STORAGE_DEVICE_DESCRIPTOR)) {
          status = STATUS_BUFFER_TOO_SMALL;
          Irp->IoStatus.Information = 0;
          break;
        }
        storage = Irp->AssociatedIrp.SystemBuffer;

        status = STATUS_SUCCESS;
      } else if (query->PropertyId == StorageAdapterProperty) {
        DDbgPrint("    PropertyStandardQuery StorageAdapterProperty\n");
        status = STATUS_NOT_IMPLEMENTED;
      } else {
        DDbgPrint("    PropertyStandardQuery Unknown %d\n", query->PropertyId);
        status = STATUS_ACCESS_DENIED;
      }
    } else {
      DDbgPrint("    Unknown query type %d\n", query->QueryType);
      status = STATUS_ACCESS_DENIED;
    }
    break;
  case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: {
    PMOUNTDEV_NAME mountdevName;
    PUNICODE_STRING deviceName = dcb->DiskDeviceName;

    DDbgPrint("   IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n");

    if (outputLength < sizeof(MOUNTDEV_NAME)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
      break;
    }

    mountdevName = (PMOUNTDEV_NAME)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(mountdevName != NULL);
    /* NOTE: When Windows API GetVolumeNameForVolumeMountPoint is called, this
       IO control is called.
       Even if status = STATUS_SUCCESS, GetVolumeNameForVolumeMountPoint can
       returns error
       if it doesn't match cached data from mount manager (looks like).
    */
    RtlZeroMemory(mountdevName, outputLength);
    mountdevName->NameLength = deviceName->Length;

    if (sizeof(USHORT) + mountdevName->NameLength < outputLength) {
      RtlCopyMemory((PCHAR)mountdevName->Name, deviceName->Buffer,
                    mountdevName->NameLength);
      Irp->IoStatus.Information = sizeof(USHORT) + mountdevName->NameLength;
      status = STATUS_SUCCESS;
      DDbgPrint("  DeviceName %wZ\n", deviceName);
    } else {
      Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
      status = STATUS_BUFFER_OVERFLOW;
    }
  } break;
  case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: {
    PMOUNTDEV_UNIQUE_ID uniqueId;

    DDbgPrint("   IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n");
    if (outputLength < sizeof(MOUNTDEV_UNIQUE_ID)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
      break;
    }

    uniqueId = (PMOUNTDEV_UNIQUE_ID)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(uniqueId != NULL);

    uniqueId->UniqueIdLength = dcb->DiskDeviceName->Length;

    if (sizeof(USHORT) + uniqueId->UniqueIdLength < outputLength) {
      RtlCopyMemory((PCHAR)uniqueId->UniqueId, dcb->DiskDeviceName->Buffer,
                    uniqueId->UniqueIdLength);
      Irp->IoStatus.Information =
          FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId[0]) +
          uniqueId->UniqueIdLength;
      status = STATUS_SUCCESS;
      DDbgPrint("  UniqueName %wZ\n", dcb->DiskDeviceName);
      break;
    } else {
      Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
      status = STATUS_BUFFER_OVERFLOW;
    }
  } break;
  case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: {
    PMOUNTDEV_SUGGESTED_LINK_NAME linkName;
    DDbgPrint("   IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME\n");

    if (outputLength < sizeof(MOUNTDEV_SUGGESTED_LINK_NAME)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
      break;
    }

    linkName = (PMOUNTDEV_SUGGESTED_LINK_NAME)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(linkName != NULL);

    if (dcb->MountPoint != NULL && dcb->MountPoint->Length > 0) {
      if (IsMountPointDriveLetter(dcb->MountPoint) == STATUS_SUCCESS) {
        linkName->UseOnlyIfThereAreNoOtherLinks = FALSE;
        linkName->NameLength = dcb->MountPoint->Length;

        if (sizeof(USHORT) + linkName->NameLength < outputLength) {
          RtlCopyMemory((PCHAR)linkName->Name, dcb->MountPoint->Buffer,
                        linkName->NameLength);
          Irp->IoStatus.Information =
              FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME, Name[0]) +
              linkName->NameLength;
          status = STATUS_SUCCESS;
          DDbgPrint("  LinkName %wZ (%d)\n", dcb->MountPoint,
                    dcb->MountPoint->Length);
          break;
        } else {
          Irp->IoStatus.Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
          status = STATUS_BUFFER_OVERFLOW;
        }
      } else {
        DDbgPrint("   MountPoint %wZ is not a drive\n", dcb->MountPoint);
        status = STATUS_NOT_FOUND;
      }
    } else {
      DDbgPrint("   MountPoint is NULL or undefined\n");
      status = STATUS_NOT_FOUND;
    }
  } break;
  case IOCTL_MOUNTDEV_LINK_CREATED: {
    PMOUNTDEV_NAME mountdevName = Irp->AssociatedIrp.SystemBuffer;
    DDbgPrint("   IOCTL_MOUNTDEV_LINK_CREATED\n");

    status = STATUS_SUCCESS;
    if (!IsUnmountPending(DeviceObject) && mountdevName != NULL &&
        mountdevName->NameLength > 0) {
      WCHAR *symbolicLinkNameBuf =
          ExAllocatePool((mountdevName->NameLength + 1) * sizeof(WCHAR));
      if (symbolicLinkNameBuf == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        break;
      }

      RtlZeroMemory(symbolicLinkNameBuf,
                    (mountdevName->NameLength + 1) * sizeof(WCHAR));
      RtlCopyMemory(symbolicLinkNameBuf, mountdevName->Name,
                    mountdevName->NameLength);
      DDbgPrint("   MountDev Name: %ws\n", symbolicLinkNameBuf);

      if (wcsncmp(symbolicLinkNameBuf, L"\\DosDevices\\", 12) == 0) {
        if (dcb->MountPoint != NULL && dcb->MountPoint->Length == 0) {
          ExFreePool(dcb->MountPoint);
          dcb->MountPoint = NULL;
        }
        if (dcb->MountPoint == NULL) {
          DDbgPrint("   Not current MountPoint. MountDev set as MountPoint\n");
          dcb->MountPoint = DokanAllocateUnicodeString(symbolicLinkNameBuf);
          if (dcb->DiskDeviceName != NULL) {
            PMOUNT_ENTRY mountEntry;
            PDOKAN_CONTROL dokanControl = ExAllocatePool(sizeof(DOKAN_CONTROL));
            if (dokanControl == NULL) {
              ExFreePool(symbolicLinkNameBuf);
              status = STATUS_INSUFFICIENT_RESOURCES;
              break;
            }
            RtlZeroMemory(dokanControl, sizeof(*dokanControl));
            RtlCopyMemory(dokanControl->DeviceName, dcb->DiskDeviceName->Buffer,
                          dcb->DiskDeviceName->Length);
            if (dcb->UNCName->Buffer != NULL && dcb->UNCName->Length > 0) {
              RtlCopyMemory(dokanControl->UNCName, dcb->UNCName->Buffer,
                            dcb->UNCName->Length);
            }
            mountEntry = FindMountEntry(dcb->Global, dokanControl, TRUE);
            ExFreePool(dokanControl);
            if (mountEntry != NULL) {
              RtlStringCchCopyW(mountEntry->MountControl.MountPoint,
                                MAXIMUM_FILENAME_LENGTH, symbolicLinkNameBuf);
            } else {
              DDbgPrint("   Cannot found associated MountEntry.\n");
            }
          } else {
            DDbgPrint(
                "   DiskDeviceName is null. Is device currently unmounted?\n");
          }
        } else {
          DDbgPrint("   Mount Point already assigned to the device. New mount "
                    "point ignored.\n");
        }
      } else {
        DDbgPrint("   Mount Point is not DosDevices, ignored.\n");
      }
      ExFreePool(symbolicLinkNameBuf);
    } else {
      DDbgPrint("   MountDev Name is undefined or unmounting in progress.\n");
    }
  } break;
  case IOCTL_MOUNTDEV_LINK_DELETED: {
    PMOUNTDEV_NAME mountdevName = Irp->AssociatedIrp.SystemBuffer;
    DDbgPrint("   IOCTL_MOUNTDEV_LINK_DELETED\n");
    status = STATUS_SUCCESS;
    if (dcb->UseMountManager) {
      if (mountdevName != NULL && mountdevName->NameLength > 0) {
        WCHAR *symbolicLinkNameBuf =
            ExAllocatePool((mountdevName->NameLength + 1) * sizeof(WCHAR));
        if (symbolicLinkNameBuf == NULL) {
          status = STATUS_INSUFFICIENT_RESOURCES;
          break;
        }

        RtlZeroMemory(symbolicLinkNameBuf,
                      (mountdevName->NameLength + 1) * sizeof(WCHAR));
        RtlCopyMemory(symbolicLinkNameBuf, mountdevName->Name,
                      mountdevName->NameLength);
        DDbgPrint("   MountDev Name: %ws\n", symbolicLinkNameBuf);

        if (dcb->MountPoint != NULL && dcb->MountPoint->Length > 0) {
          // If deleted mount point match user requested mount point, release
          // devices
          if (dcb->MountPoint->Length == mountdevName->NameLength &&
              RtlCompareMemory(mountdevName->Name, dcb->MountPoint->Buffer,
                               mountdevName->NameLength) ==
                  mountdevName->NameLength) {
            status = DokanEventRelease(vcb->DeviceObject, Irp);
          } else {
            DDbgPrint("   Deleted Mount Point doesn't match device excepted "
                      "mount point.\n");
          }
        }
        // Or, if no requested mount point, we assume the first deleted one
        // release devices
        else {
          status = DokanEventRelease(vcb->DeviceObject, Irp);
        }
        ExFreePool(symbolicLinkNameBuf);
      } else {
        DDbgPrint("   MountDev Name is undefined.\n");
      }
    } else {
      DDbgPrint("   Mount Manager is not enabled for this device. Ignored.\n");
    }
  } break;
  // case IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY:
  //    DDbgPrint("   IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY\n");
  //    break;
  case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
    DDbgPrint("   IOCTL_MOUNTDEV_QUERY_STABLE_GUID\n");
    break;
  case IOCTL_VOLUME_ONLINE:
    DDbgPrint("   IOCTL_VOLUME_ONLINE\n");
    status = STATUS_SUCCESS;
    break;
  case IOCTL_VOLUME_OFFLINE:
    DDbgPrint("   IOCTL_VOLUME_OFFLINE\n");
    status = STATUS_SUCCESS;
    break;
  case IOCTL_VOLUME_READ_PLEX:
    DDbgPrint("   IOCTL_VOLUME_READ_PLEX\n");
    break;
  case IOCTL_VOLUME_PHYSICAL_TO_LOGICAL:
    DDbgPrint("   IOCTL_VOLUME_PHYSICAL_TO_LOGICAL\n");
    break;
  case IOCTL_VOLUME_IS_CLUSTERED:
    DDbgPrint("   IOCTL_VOLUME_IS_CLUSTERED\n");
    break;
  case IOCTL_VOLUME_PREPARE_FOR_CRITICAL_IO:
    DDbgPrint("   IOCTL_VOLUME_PREPARE_FOR_CRITICAL_IO\n");
    break;
  case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: {
    PVOLUME_DISK_EXTENTS volume;
    ULONG bufferLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

    DDbgPrint("   IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS\n");
    if (bufferLength < sizeof(VOLUME_DISK_EXTENTS)) {
      status = STATUS_INVALID_PARAMETER;
      Irp->IoStatus.Information = 0;
      break;
    }
    volume = Irp->AssociatedIrp.SystemBuffer;
    RtlZeroMemory(volume, sizeof(VOLUME_DISK_EXTENTS));
    volume->NumberOfDiskExtents = 1;
    Irp->IoStatus.Information = sizeof(VOLUME_DISK_EXTENTS);
    status = STATUS_SUCCESS;
  } break;
  case IOCTL_STORAGE_EJECT_MEDIA: {
    DDbgPrint("   IOCTL_STORAGE_EJECT_MEDIA\n");
    DokanUnmount(dcb);
    status = STATUS_SUCCESS;
  } break;
  case IOCTL_REDIR_QUERY_PATH_EX:
  case IOCTL_REDIR_QUERY_PATH: {
    PQUERY_PATH_RESPONSE pathResp;
    BOOLEAN prefixOk = FALSE;

    if (dcb->UNCName != NULL && dcb->UNCName->Length > 0) {
      if (Irp->RequestorMode != KernelMode) {
        break;
      }

      WCHAR *lpPath = NULL;
      ULONG ulPath = 0;

      if (irpSp->Parameters.DeviceIoControl.IoControlCode ==
          IOCTL_REDIR_QUERY_PATH) {
        PQUERY_PATH_REQUEST pathReq;
        DDbgPrint("  IOCTL_REDIR_QUERY_PATH\n");

        if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
            sizeof(QUERY_PATH_REQUEST)) {
          status = STATUS_BUFFER_OVERFLOW;
          break;
        }

        // Always a METHOD_NEITHER IOCTL
        pathReq = (PQUERY_PATH_REQUEST)
                      irpSp->Parameters.DeviceIoControl.Type3InputBuffer;

        DDbgPrint("   PathNameLength = %d\n", pathReq->PathNameLength);
        DDbgPrint("   SecurityContext = %p\n", pathReq->SecurityContext);
        DDbgPrint("   FilePathName = %.*ls\n",
                  (unsigned int)(pathReq->PathNameLength / sizeof(WCHAR)),
                  pathReq->FilePathName);

        lpPath = pathReq->FilePathName;
        ulPath = pathReq->PathNameLength / sizeof(WCHAR);

        if (pathReq->PathNameLength >= dcb->UNCName->Length / sizeof(WCHAR)) {
          prefixOk = (_wcsnicmp(pathReq->FilePathName, dcb->UNCName->Buffer,
                                dcb->UNCName->Length / sizeof(WCHAR)) == 0);
        }
      } else {
        PQUERY_PATH_REQUEST_EX pathReqEx;
        DDbgPrint("  IOCTL_REDIR_QUERY_PATH_EX\n");

        if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
            sizeof(QUERY_PATH_REQUEST_EX)) {
          status = STATUS_BUFFER_OVERFLOW;
          break;
        }

        // Always a METHOD_NEITHER IOCTL
        pathReqEx = (PQUERY_PATH_REQUEST_EX)
                        irpSp->Parameters.DeviceIoControl.Type3InputBuffer;

        DDbgPrint("   pSecurityContext = %p\n", pathReqEx->pSecurityContext);
        DDbgPrint("   EaLength = %d\n", pathReqEx->EaLength);
        DDbgPrint("   pEaBuffer = %p\n", pathReqEx->pEaBuffer);
        DDbgPrint("   PathNameLength = %d\n", pathReqEx->PathName.Length);
        DDbgPrint("   FilePathName = %*ls\n",
                  (unsigned int)(pathReqEx->PathName.Length / sizeof(WCHAR)),
                  pathReqEx->PathName.Buffer);

        lpPath = pathReqEx->PathName.Buffer;
        ulPath = pathReqEx->PathName.Length / sizeof(WCHAR);

        if (pathReqEx->PathName.Length >= dcb->UNCName->Length) {
          prefixOk =
              (_wcsnicmp(pathReqEx->PathName.Buffer, dcb->UNCName->Buffer,
                         dcb->UNCName->Length / sizeof(WCHAR)) == 0);
        }
      }

      unsigned int i = 1;
      for (;
           i < ulPath && i * sizeof(WCHAR) < dcb->UNCName->Length && !prefixOk;
           ++i) {
        if (_wcsnicmp(&lpPath[i], &dcb->UNCName->Buffer[i], 1) != 0) {
          break;
        }

        if ((i + 1) * sizeof(WCHAR) < dcb->UNCName->Length) {
          prefixOk = (dcb->UNCName->Buffer[i + 1] == L'\\');
        }
      }

      if (!prefixOk) {
        status = STATUS_BAD_NETWORK_PATH;
        break;
      }

      for (; i < ulPath && i * sizeof(WCHAR) < dcb->UNCName->Length && prefixOk;
           ++i) {
        if (_wcsnicmp(&lpPath[i], &dcb->UNCName->Buffer[i], 1) != 0) {
          prefixOk = FALSE;
        }
      }

      if (!prefixOk) {
        status = STATUS_BAD_NETWORK_NAME;
        break;
      }

      pathResp = (PQUERY_PATH_RESPONSE)Irp->UserBuffer;
      pathResp->LengthAccepted = dcb->UNCName->Length;
      status = STATUS_SUCCESS;
    }
  } break;
  case IOCTL_STORAGE_GET_MEDIA_TYPES_EX: {
    PGET_MEDIA_TYPES mediaTypes = NULL;
    PDEVICE_MEDIA_INFO mediaInfo = NULL; //&mediaTypes->MediaInfo[0];

    // We alway return only one media type
    DDbgPrint("  IOCTL_STORAGE_GET_MEDIA_TYPES_EX\n");
    if (outputLength < sizeof(GET_MEDIA_TYPES)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }

    mediaTypes = (PGET_MEDIA_TYPES)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(mediaTypes != NULL);

    mediaInfo = &mediaTypes->MediaInfo[0];

    mediaTypes->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
    mediaTypes->MediaInfoCount = 1;

    PDISK_GEOMETRY diskGeometry = ExAllocatePool(sizeof(DISK_GEOMETRY));
    if (diskGeometry == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      break;
    }
    RtlZeroMemory(diskGeometry, sizeof(*diskGeometry));
    DokanPopulateDiskGeometry(diskGeometry);
    mediaInfo->DeviceSpecific.DiskInfo.MediaType = diskGeometry->MediaType;
    mediaInfo->DeviceSpecific.DiskInfo.NumberMediaSides = 1;
    mediaInfo->DeviceSpecific.DiskInfo.MediaCharacteristics =
        (MEDIA_CURRENTLY_MOUNTED | MEDIA_READ_WRITE);
    mediaInfo->DeviceSpecific.DiskInfo.Cylinders.QuadPart =
        diskGeometry->Cylinders.QuadPart;
    mediaInfo->DeviceSpecific.DiskInfo.TracksPerCylinder =
        diskGeometry->TracksPerCylinder;
    mediaInfo->DeviceSpecific.DiskInfo.SectorsPerTrack =
        diskGeometry->SectorsPerTrack;
    mediaInfo->DeviceSpecific.DiskInfo.BytesPerSector =
        diskGeometry->BytesPerSector;
    ExFreePool(diskGeometry);

    status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(GET_MEDIA_TYPES);
  } break;
  case IOCTL_STORAGE_GET_DEVICE_NUMBER: {
    PSTORAGE_DEVICE_NUMBER deviceNumber;

    DDbgPrint("  IOCTL_STORAGE_GET_DEVICE_NUMBER\n");

    if (outputLength < sizeof(STORAGE_DEVICE_NUMBER)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
      break;
    }

    deviceNumber = (PSTORAGE_DEVICE_NUMBER)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(deviceNumber != NULL);

    deviceNumber->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
    if (vcb) {
      deviceNumber->DeviceType = vcb->DeviceObject->DeviceType;
    }

    deviceNumber->DeviceNumber = 0; // Always one volume only per disk device
    deviceNumber->PartitionNumber = (ULONG)-1; // Not partitionable

    Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
    status = STATUS_SUCCESS;
  } break;

  default:
    PrintUnknownDeviceIoctlCode(
        irpSp->Parameters.DeviceIoControl.IoControlCode);
    status = STATUS_INVALID_DEVICE_REQUEST;
    break;
  }
  DDbgPrint("   <= DokanDiskDeviceControl\n");
  return status;
}
NTSTATUS KDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS              status = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION    irpStack  = IoGetCurrentIrpStackLocation(Irp);
    PPROCESS_EVENT        pProcessEvent;
	PCHAR pOutputBuffer;
	PPROCESS_INFORMATION pInputBuffer;
	UINT dwDataWritten = 0;
	PCAPTURE_PROCESS_MANAGER pProcessManager;

	/* Get the process manager from the device extension */
    pProcessManager = gpDeviceObject->DeviceExtension;

    switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
    {
        case IOCTL_CAPTURE_GET_PROCINFO:
			/* Update the time the user space program last sent an IOCTL */
			//UpdateLastContactTime();
			/* Return some of the process events that are queued */
            if(irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(PROCESS_EVENT))
            {
				ULONG left = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
				ULONG done = 0;
				pOutputBuffer = Irp->UserBuffer;
				__try {
					ProbeForWrite(pOutputBuffer, 
								irpStack->Parameters.DeviceIoControl.OutputBufferLength,
								__alignof (PROCESS_EVENT));
					//ExAcquireFastMutex(&pProcessManager->mProcessWaitingSpinLock);
					//if(pProcessManager->pCurrentProcessEvent != NULL)
					//{
					//	RtlCopyMemory(pOutputBuffer+done, pProcessManager->pCurrentProcessEvent, sizeof(PROCESS_EVENT));
					//	done += sizeof(PROCESS_EVENT);
					//	ExFreePoolWithTag(pProcessManager->pCurrentProcessEvent, PROCESS_POOL_TAG);
					//	pProcessManager->pCurrentProcessEvent = NULL;
					//}
					//ExReleaseFastMutex(&pProcessManager->mProcessWaitingSpinLock);
					
					if(!IsListEmpty(&pProcessManager->lQueuedProcessEvents))
					{
						PLIST_ENTRY head;
						PPROCESS_EVENT_PACKET pProcessEventPacket;
						head = ExInterlockedRemoveHeadList(&pProcessManager->lQueuedProcessEvents, &pProcessManager->lQueuedProcessEventsSpinLock);
						pProcessManager->nQueuedProcessEvents--;
						pProcessEventPacket = CONTAINING_RECORD(head, PROCESS_EVENT_PACKET, Link);
						
						RtlCopyMemory(pOutputBuffer, &pProcessEventPacket->processEvent, sizeof(PROCESS_EVENT));
						done = sizeof(PROCESS_EVENT);

						ExFreePool(pProcessEventPacket);

						// Notify that we still have process events queued
						if( pProcessManager->nQueuedProcessEvents )
						{
							KeSetEvent(pProcessManager->eNewProcessEvent, 0, FALSE);
							KeClearEvent(pProcessManager->eNewProcessEvent);
						}
					}
					
					dwDataWritten = done;
					status = STATUS_SUCCESS;
				} __except( EXCEPTION_EXECUTE_HANDLER ) {
					DbgPrint("CaptureProcessMonitor: EXCEPTION IOCTL_CAPTURE_GET_PROCINFO - %08x\n", GetExceptionCode());
					status = GetExceptionCode();     
				}        
            }
            break;
        default:
            break;
    }
Beispiel #7
0
BOOLEAN
LfsReadNextLogRecord (
    IN LFS_LOG_HANDLE LogHandle,
    IN OUT LFS_LOG_CONTEXT Context,
    OUT PLFS_RECORD_TYPE RecordType,
    OUT TRANSACTION_ID *TransactionId,
    OUT PLSN UndoNextLsn,
    OUT PLSN PreviousLsn,
    OUT PLSN Lsn,
    OUT PULONG BufferLength,
    OUT PVOID *Buffer
    )

/*++

Routine Description:

    This routine is called to continue a query operation.  The Lfs uses
    private information stored in the context structure to determine the
    next log record to return to the caller.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

    Context - Supplies the address to store a pointer to the Lfs created
              context structure.

    Lsn - Lsn for this log record.

    RecordType - Supplies the address to store the record type of this
                 log record.

    TransactionId - Supplies the address to store the transaction Id of
                    this log record.

    UndoNextLsn - Supplies the address to store the Undo Next Lsn for this
                  log record.

    PreviousLsn - Supplies the address to store the Previous Lsn for this
                  log record.

    BufferLength - This is the length of the log data.

    Buffer - This is a pointer to the start of the log data.

Return Value:

    None

--*/

{
    volatile NTSTATUS Status = STATUS_SUCCESS;

    PLCH Lch;

    PLFCB Lfcb;

    PLfsLCB Lcb;

    BOOLEAN FoundNextLsn;

    BOOLEAN UnwindRememberLcbFields;
    PBCB UnwindRecordHeaderBcb;
    PLFS_RECORD_HEADER UnwindRecordHeader;
    PVOID UnwindCurrentLogRecord;
    BOOLEAN UnwindAuxilaryBuffer;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsReadNextLogRecord:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle    -> %08lx\n", LogHandle );
    LfsDebugTrace(  0, Dbg, "Context       -> %08lx\n", Context );

    FoundNextLsn = FALSE;

    UnwindRememberLcbFields = FALSE;

    Lch = (PLCH) LogHandle;
    Lcb = (PLfsLCB) Context;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-except to catch errors.
    //

    __try {

        //
        //  Use a try-finally to facilitate cleanup.
        //

        __try {

            //
            //  Acquire the log file control block for this log file.
            //

            LfsAcquireLch( Lch );
            Lfcb = Lch->Lfcb;

            //
            //  If the Log file has been closed then refuse access.
            //

            if (Lfcb == NULL) {

                ExRaiseStatus( STATUS_ACCESS_DENIED );
            }

            //
            //  Check that the client Id is valid.
            //

            LfsValidateClientId( Lfcb, Lch );

            //
            //  Check that the context structure is valid.
            //

            LfsValidateLcb( Lcb, Lch );

            //
            //  Remember any context fields to be overwritten.
            //

            UnwindRememberLcbFields = TRUE;

            UnwindRecordHeaderBcb = Lcb->RecordHeaderBcb;
            Lcb->RecordHeaderBcb = NULL;

            UnwindRecordHeader = Lcb->RecordHeader;
            UnwindCurrentLogRecord = Lcb->CurrentLogRecord;

            UnwindAuxilaryBuffer = Lcb->AuxilaryBuffer;
            Lcb->AuxilaryBuffer = FALSE;

            //
            //  Find the next Lsn number based on the current Lsn number in
            //  the context block.
            //

            if (LfsFindClientNextLsn( Lfcb, Lcb, Lsn )) {

                //
                //  We can give up the Lfcb as we know the Lsn is within the file.
                //

                LfsReleaseLfcb( Lfcb );

                //
                //  Cleanup the context block so we can do the next search.
                //

                Lcb->CurrentLogRecord = NULL;
                Lcb->AuxilaryBuffer = FALSE;

                //
                //  Perform the work of getting the log record.
                //

                LfsFindLogRecord( Lfcb,
                                  Lcb,
                                  *Lsn,
                                  RecordType,
                                  TransactionId,
                                  UndoNextLsn,
                                  PreviousLsn,
                                  BufferLength,
                                  Buffer );

                FoundNextLsn = TRUE;
            }

        } __finally {

            DebugUnwind( LfsReadNextLogRecord );

            //
            //  If we exited due to an error, we have to restore the context
            //  block.
            //

            if (UnwindRememberLcbFields) {

                if (AbnormalTermination()) {

                    //
                    //  If the record header in the context block is not
                    //  the same as we started with.  Then we unpin that
                    //  data.
                    //

                    if (Lcb->RecordHeaderBcb != NULL) {

                        CcUnpinData( Lcb->RecordHeaderBcb );

                    }

                    if (Lcb->CurrentLogRecord != NULL
                        && Lcb->AuxilaryBuffer == TRUE) {

                        ExFreePool( Lcb->CurrentLogRecord );
                    }

                    Lcb->RecordHeaderBcb = UnwindRecordHeaderBcb;
                    Lcb->RecordHeader = UnwindRecordHeader;
                    Lcb->CurrentLogRecord = UnwindCurrentLogRecord;
                    Lcb->AuxilaryBuffer = UnwindAuxilaryBuffer;

                //
                //  Otherwise, if we have successfully found the next Lsn,
                //  we free up any resources being held from the previous search.
                //

                } else if (FoundNextLsn ) {

                    if (UnwindRecordHeaderBcb != NULL) {

                        CcUnpinData( UnwindRecordHeaderBcb );
                    }

                    if (UnwindCurrentLogRecord != NULL
                        && UnwindAuxilaryBuffer == TRUE) {

                        ExFreePool( UnwindCurrentLogRecord );
                    }

                //
                //  Restore the Bcb and auxilary buffer field for the final
                //  cleanup.
                //

                } else {

                    if (UnwindRecordHeaderBcb != NULL) {

                        if (Lcb->RecordHeaderBcb != NULL) {

                            CcUnpinData( UnwindRecordHeaderBcb );

                        } else {

                            Lcb->RecordHeaderBcb = UnwindRecordHeaderBcb;
                        }
                    }

                    if (UnwindAuxilaryBuffer) {

                        if (Lcb->CurrentLogRecord == UnwindCurrentLogRecord) {

                            Lcb->AuxilaryBuffer = TRUE;

                        } else {

                            ExFreePool( UnwindCurrentLogRecord );
                        }
                    }
                }
            }

            //
            //  Release the log file control block if held.
            //

            LfsReleaseLch( Lch );

            LfsDebugTrace(  0, Dbg, "Lsn (Low)     -> %08lx\n", Lsn->LowPart );
            LfsDebugTrace(  0, Dbg, "Lsn (High)    -> %08lx\n", Lsn->HighPart );
            LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", *BufferLength );
            LfsDebugTrace(  0, Dbg, "Buffer        -> %08lx\n", *Buffer );
            LfsDebugTrace( -1, Dbg, "LfsReadNextLogRecord:  Exit\n", 0 );
        }

    } __except (LfsExceptionFilter( GetExceptionInformation() )) {

        Status = GetExceptionCode();
    }

    if (Status != STATUS_SUCCESS) {

        ExRaiseStatus( Status );
    }

    return FoundNextLsn;
}
Beispiel #8
0
NTSTATUS
ReleaseTimeoutPendingIrp(
   PDEVICE_EXTENSION	DeviceExtension
   )
{
	KIRQL				oldIrql;
    PLIST_ENTRY			thisEntry, nextEntry, listHead;
	PIRP_ENTRY			irpEntry;
	LARGE_INTEGER		tickCount;
	LIST_ENTRY			completeList;
	PIRP				irp;

	DDbgPrint("==> ReleaseTimeoutPendingIRP\n");
	InitializeListHead(&completeList);

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

	// when IRP queue is empty, there is nothing to do
	if (IsListEmpty(&DeviceExtension->PendingIrp.ListHead)) {
		KeReleaseSpinLock(&DeviceExtension->PendingIrp.ListLock, oldIrql);
		DDbgPrint("  IrpQueue is Empty\n");
		return STATUS_SUCCESS;
	}

	KeQueryTickCount(&tickCount);

	// search timeout IRP through pending IRP list
	listHead = &DeviceExtension->PendingIrp.ListHead;

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

        nextEntry = thisEntry->Flink;

        irpEntry = CONTAINING_RECORD(thisEntry, IRP_ENTRY, ListEntry);

		// this IRP is NOT timeout yet
		if ( (tickCount.QuadPart - irpEntry->TickCount.QuadPart) * KeQueryTimeIncrement()
			< DOKAN_IPR_PENDING_TIMEOUT * 10000 * 1000) {
			break;
		}

		RemoveEntryList(thisEntry);

		DDbgPrint(" timeout Irp #%X\n", irpEntry->SerialNumber);

		irp = irpEntry->Irp;

		if (irp == NULL) {
			// this IRP has already been canceled
			ASSERT(irpEntry->CancelRoutineFreeMemory == FALSE);
			ExFreePool(irpEntry);
			continue;
		}

		// this IRP is not canceled yet
		if (IoSetCancelRoutine(irp, NULL) == NULL) {
			// Cancel routine will run as soon as we release the lock
			InitializeListHead(&irpEntry->ListEntry);
			irpEntry->CancelRoutineFreeMemory = TRUE;
			continue;
		}
		// IrpEntry is saved here for CancelRoutine
		// Clear it to prevent to be completed by CancelRoutine twice
		irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_IRP_ENTRY] = NULL;
		InsertTailList(&completeList, &irpEntry->ListEntry);
	}

	if (IsListEmpty(&DeviceExtension->PendingIrp.ListHead)) {
		KeClearEvent(&DeviceExtension->PendingIrp.NotEmpty);
	}
	KeReleaseSpinLock(&DeviceExtension->PendingIrp.ListLock, oldIrql);
	
	while (!IsListEmpty(&completeList)) {
		listHead = RemoveHeadList(&completeList);
		irpEntry = CONTAINING_RECORD(listHead, IRP_ENTRY, ListEntry);
		irp = irpEntry->Irp;
		irp->IoStatus.Information = 0;
		irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		ExFreePool(irpEntry);
		IoCompleteRequest(irp, IO_NO_INCREMENT);
	}

	DDbgPrint("<== ReleaseTimeoutPendingIRP\n");
	return STATUS_SUCCESS;
}
Beispiel #9
0
NTSTATUS
NTAPI
NduDispatchRead(PDEVICE_OBJECT DeviceObject,
                PIRP Irp)
{
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
    PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
    PNDISUIO_OPEN_ENTRY OpenEntry = IrpSp->FileObject->FsContext2;
    KIRQL OldIrql, OldCancelIrql;
    NTSTATUS Status;
    PLIST_ENTRY ListEntry;
    PNDISUIO_PACKET_ENTRY PacketEntry = NULL;
    ULONG BytesCopied = 0;

    ASSERT(DeviceObject == GlobalDeviceObject);

    if (OpenEntry->WriteOnly)
    {
        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        
        return STATUS_INVALID_PARAMETER;
    }

    /* Make the read cancellable */
    IoAcquireCancelSpinLock(&OldCancelIrql);
    IoSetCancelRoutine(Irp, ReadIrpCancel);
    if (Irp->Cancel)
    {
        IoReleaseCancelSpinLock(OldCancelIrql);

        /* Indicate a 0 byte read */
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        
        return STATUS_SUCCESS;
    }
    IoReleaseCancelSpinLock(OldCancelIrql);

    while (TRUE)
    {
        KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);

        /* Check if we have a packet */
        if (IsListEmpty(&AdapterContext->PacketList))
        {
            KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);

            /* Wait for a packet (in the context of the calling user thread) */
            Status = KeWaitForSingleObject(&AdapterContext->PacketReadEvent,
                                           UserRequest,
                                           UserMode,
                                           TRUE,
                                           NULL);
            if (Status != STATUS_SUCCESS)
            {
                /* Remove the cancel routine */
                IoAcquireCancelSpinLock(&OldCancelIrql);
                IoSetCancelRoutine(Irp, NULL);
                IoReleaseCancelSpinLock(OldCancelIrql);

                break;
            }
        }
        else
        {
            /* Remove the cancel routine */
            IoAcquireCancelSpinLock(&OldCancelIrql);
            IoSetCancelRoutine(Irp, NULL);
            IoReleaseCancelSpinLock(OldCancelIrql);
            
            /* Remove the first packet in the list */
            ListEntry = RemoveHeadList(&AdapterContext->PacketList);
            PacketEntry = CONTAINING_RECORD(ListEntry, NDISUIO_PACKET_ENTRY, ListEntry);

            /* Release the adapter lock */
            KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
            
            /* And we're done with this loop */
            Status = STATUS_SUCCESS;
            break;
        }
    }
    
    /* Check if we got a packet */
    if (PacketEntry != NULL)
    {
        /* Find the right amount of bytes to copy */
        BytesCopied = PacketEntry->PacketLength;
        if (BytesCopied > IrpSp->Parameters.Read.Length)
            BytesCopied = IrpSp->Parameters.Read.Length;

        /* Copy the packet */
        RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
                      &PacketEntry->PacketData[0],
                      BytesCopied);
        
        /* Free the packet entry */
        ExFreePool(PacketEntry);
    }
    else
    {
        /* Something failed */
        BytesCopied = 0;
    }

    /* Complete the IRP */
    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = BytesCopied;
    IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
    
    return Status;
}
Beispiel #10
0
EXTERN_C VOID EnumProcessModuleByVM( PEPROCESS pEProcess, PALL_PROCESS_MODULE_INFO pAllModuleInf )
{

	ULONG dwStartAddr = 0x00000000;
	HANDLE hProcess;
	MEMORY_BASIC_INFORMATION mbi;
	PUNICODE_STRING pSectionNam = NULL;
	OBJECT_ATTRIBUTES ObjectAttributes;
	CLIENT_ID ClientId={0};
	NTSTATUS status;
	int i=0;
	int count = -1;
	ULONG ulDllSize;
	//BOOL bInit = FALSE;



	//WinVer = GetWindowsVersion();
	//switch(WinVer)
	//{
	//case WINDOWS_VERSION_XP:
	//	if (!MmIsAddressValidEx(ZwQueryVirtualMemory)){
	//		ZwQueryVirtualMemory = GetZwQueryVirtualMemoryAddress();
	//	}
	//	break;
	//case WINDOWS_VERSION_7_7600_UP:
	//case WINDOWS_VERSION_7_7000:
	//	ReLoadNtosCALL((PVOID)(&ZwQueryVirtualMemory),L"ZwQueryVirtualMemory",SystemKernelModuleBase,(ULONG)ImageModuleBase); //win7导出了,可以直接用
	//	break;
	//case WINDOWS_VERSION_2K3_SP1_SP2:
	//	if (!MmIsAddressValidEx(ZwQueryVirtualMemory)){
	//		ZwQueryVirtualMemory = GetZwQueryVirtualMemoryAddress();
	//	}
	//	break;
	//}
	//ReLoadNtosCALL((PVOID)(&RObOpenObjectByPointer),L"ObOpenObjectByPointer",SystemKernelModuleBase,(ULONG)ImageModuleBase);
	//ReLoadNtosCALL((PVOID)(&RExAllocatePool),L"ExAllocatePool",SystemKernelModuleBase,(ULONG)ImageModuleBase);
	//ReLoadNtosCALL((PVOID)(&RExFreePool),L"ExFreePool",SystemKernelModuleBase,(ULONG)ImageModuleBase);
	//ReLoadNtosCALL((PVOID)(&RZwClose),L"ZwClose",SystemKernelModuleBase,(ULONG)ImageModuleBase);
	//if (ZwQueryVirtualMemory &&
	//	RObOpenObjectByPointer &&
	//	RExAllocatePool &&
	//	RExFreePool &&
	//	RZwClose)
	//{
	//	bInit = TRUE;
	//}
	//if (!bInit)
	//	return ;

	////进程已经退出鸟
	//if (!IsExitProcess((PEPROCESS)EProcess)){
	//	return ;
	//}
	status = ObOpenObjectByPointer(
		(PVOID)pEProcess,          // Object    
		OBJ_KERNEL_HANDLE,  // HandleAttributes    
		NULL,               // PassedAccessState OPTIONAL    
		(ACCESS_MASK)0,       // DesiredAccess    
		*PsProcessType,     // ObjectType    
		KernelMode,         // AccessMode    
		&hProcess);    
	if (!NT_SUCCESS(status))
	{
		//if (DebugOn)
		//KdPrint(("ObOpenObjectByPointer failed:%d",RtlNtStatusToDosError(status)));
		return ;
	}
	pSectionNam = (PUNICODE_STRING)ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR));
	if (!pSectionNam)
	{
		ZwClose(hProcess);
		return;
	}
	RtlZeroMemory(pSectionNam->Buffer, MAX_PATH * sizeof(WCHAR));
	pSectionNam->MaximumLength = MAX_PATH;

	__try
	{
		for (dwStartAddr = 0; dwStartAddr < 0x7fffffff; dwStartAddr = dwStartAddr + 0x10000)
		{
			status = ZwQueryVirtualMemory(
				hProcess,
				(PVOID)dwStartAddr,
				MemoryBasicInformation,
				&mbi,
				sizeof(MEMORY_BASIC_INFORMATION),
				0
				);
			if (NT_SUCCESS(status) && mbi.Type == MEM_IMAGE)
			{
				status = ZwQueryVirtualMemory(
					hProcess,
					(PVOID)dwStartAddr,
					MemorySectionName,
					pSectionNam,
					MAX_PATH*sizeof(WCHAR),
					0
					);
				if (NT_SUCCESS(status) && !MmIsAddressValid(pSectionNam->Buffer))
				{
					//如果当前的DLL模块路径 不等于前一个,则说明是开始了下一个DLL的枚举了,首先判断第一个字节是否是'\'
					if (((PCHAR)pSectionNam->Buffer)[0] == 0x5c)
					{ 
						if (count == -1 ||\
							RtlCompareMemory(pAllModuleInf->vModuleInf[count].ImagePathName, pSectionNam->Buffer, pSectionNam->Length)\
							!= pSectionNam->Length)
						{
							RtlCopyMemory(pAllModuleInf->vModuleInf[++count].ImagePathName, pSectionNam->Buffer, pSectionNam->Length);
							for (ulDllSize = dwStartAddr+mbi.RegionSize; ulDllSize < 0x7fffffff; ulDllSize += mbi.RegionSize)
							{
								status = ZwQueryVirtualMemory(
									hProcess,
									(PVOID)ulDllSize,
									MemoryBasicInformation,
									&mbi,
									sizeof(MEMORY_BASIC_INFORMATION),
									0
									);
								if (NT_SUCCESS(status) && mbi.Type != MEM_IMAGE)
								{
									pAllModuleInf->vModuleInf[count].size = ulDllSize - dwStartAddr;
								}
							}
						}
					}
				}
			}
		}

	}__except(EXCEPTION_EXECUTE_HANDLER){}
_FunctionRet:
	pAllModuleInf->uCount = count;
	ExFreePool(pSectionNam);
	ZwClose(hProcess);
}
Beispiel #11
0
NTSTATUS
CreateSdpRecord(
    _In_ PBTHDDI_SDP_NODE_INTERFACE SdpNodeInterface,
    _In_ PBTHDDI_SDP_PARSE_INTERFACE SdpParseInterface,
    _In_ const GUID * ClassId,
    _In_ LPWSTR Name,
    _In_ USHORT Psm,
    _Out_ PUCHAR * Stream,
    _Out_ ULONG * Size
    )
/*++

Description:

    Create server SDP record

Arguments:

    SdpNodeInterface - Node interface that we obtained from bth stack
    SdpParseInterface - Parse interface that we obtained from bth stack
    ClassId - Service Class ID to publish
    Name - Service name to publish
    Psm - Server PSM
    Stream - receives the sdp record stream
    Size - receives size of sdp record stream

Return Value:

    NTSTATUS Status code.

--*/
{
    NTSTATUS status;
    PSDP_TREE_ROOT_NODE tree = NULL;
    PSDP_NODE seqClsIdList, seqProto, seqLang; 
    PSDP_NODE nodeName = NULL, nodeDesc = NULL, nodeProto; 
    UNICODE_STRING unicodeStrName;
    ANSI_STRING ansiStrName;
    PUCHAR stream = NULL;
    ULONG size;
    ULONG_PTR errorByte = 0;

    RtlInitUnicodeString(&unicodeStrName, Name);
    RtlInitAnsiString(&ansiStrName, NULL);

    status = RtlUnicodeStringToAnsiString(&ansiStrName, &unicodeStrName, TRUE);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "Creating ANSI string for service name failed, Status code %!STATUS!\n", status);

        ansiStrName.Length = 0;
        goto exit;
    }
        
    tree = SdpNodeInterface->SdpCreateNodeTree(
        POOLTAG_BTHECHOSAMPLE
        );

    if (NULL == tree)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "SdpCreateNodeTree failed, returning Status code %!STATUS!\n", status);
        
        goto exit;
    }

    //
    // Add ClassIdList attribute
    //

    status = AddSeqAttribute(SdpNodeInterface, tree, SDP_ATTRIB_CLASS_ID_LIST, &seqClsIdList);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    status = AppendNodeUuid128(SdpNodeInterface, seqClsIdList, ClassId);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    //
    // Add protocols
    //

    //
    // L2CAP
    //
    status = AddSeqAttribute(SdpNodeInterface, tree, SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST, &seqProto);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    status = AppendSeqNode(SdpNodeInterface, seqProto, &nodeProto);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }
    
    status = AppendNodeUuid16(SdpNodeInterface, nodeProto, L2CAP_PROTOCOL_UUID16);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    status = AppendNodeUint16(SdpNodeInterface, nodeProto, Psm);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    //
    // SDP
    //

    status = AppendSeqNode(SdpNodeInterface, seqProto, &nodeProto);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    status = AppendNodeUuid16(SdpNodeInterface, nodeProto, SDP_PROTOCOL_UUID16);            
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    //
    // Add lang attributes
    //
    status = AddSeqAttribute(SdpNodeInterface, tree, SDP_ATTRIB_LANG_BASE_ATTRIB_ID_LIST, &seqLang);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    status = AppendNodeUint16(SdpNodeInterface, seqLang, 0x656e); //TODO: find constants for these           
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    status = AppendNodeUint16(SdpNodeInterface, seqLang, 0x006A);            
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }
    
    status = AppendNodeUint16(SdpNodeInterface, seqLang, 0x0100);            
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }
    
    //
    // Add service name
    //

    nodeName = SdpNodeInterface->SdpCreateNodeString(
        ansiStrName.Buffer, 
        ansiStrName.Length, 
        POOLTAG_BTHECHOSAMPLE
        );
    if(NULL == nodeName)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "Creating node for service name failed, Status code %!STATUS!\n", status);

        goto exit;
    }
    
    status = SdpNodeInterface->SdpAddAttributeToTree(
        tree, 
        LANG_DEFAULT_ID+STRING_NAME_OFFSET, 
        nodeName, 
        POOLTAG_BTHECHOSAMPLE
        );
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "SdpAddAttributeToTree for service name failed, Status code %!STATUS!\n", status);

        goto exit;
    }

    nodeName = NULL; //transferred owenership to tree
    
    nodeDesc = SdpNodeInterface->SdpCreateNodeString(
        ansiStrName.Buffer, 
        ansiStrName.Length, 
        POOLTAG_BTHECHOSAMPLE
        );
    if(NULL == nodeDesc)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "Creating node for service desc failed, Status code %!STATUS!\n", status);

        goto exit;
    }
    
    status = SdpNodeInterface->SdpAddAttributeToTree(
        tree, 
        LANG_DEFAULT_ID+STRING_DESCRIPTION_OFFSET, 
        nodeDesc, 
        POOLTAG_BTHECHOSAMPLE
        );
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "SdpAddAttributeToTree for service desc failed, Status code %!STATUS!\n", status);
        
        goto exit;
    }

    nodeDesc = NULL;

    //
    // Create stream from tree
    //

    status = SdpParseInterface->SdpConvertTreeToStream(tree, &stream, &size, POOLTAG_BTHECHOSAMPLE);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "Failed to get stream from tree for SDP record, Status code %!STATUS!\n", status);
        
        goto exit;
    }

    status = SdpParseInterface->SdpValidateStream(
        stream,
        size,
        &errorByte
        );

    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "Validate stream failed for SDP record, first failure at address %p\n", (PVOID)errorByte);
        
        goto exit;
    }

    *Stream = stream;
    *Size = size;
    
exit:
    if (NULL != tree)
    {
        SdpNodeInterface->SdpFreeTree(tree);
    }

    if (NULL != nodeName)
    {
        //
        // If we failed to add attribute to tree use ExFreePool to free it
        //
        ExFreePool(nodeName);
    }
    
    if (NULL != nodeDesc)
    {
        //
        // If we failed to add attribute to tree use ExFreePool to free it
        //
        ExFreePool(nodeDesc);
    }
    
    RtlFreeAnsiString(&ansiStrName);

    if (!NT_SUCCESS(status))
    {
        if (stream != NULL)
        {
            ExFreePoolWithTag(stream, POOLTAG_BTHECHOSAMPLE);
        }
    }
    
    return status;
}
Beispiel #12
0
void STDCALL free_cache() {
    ExFreePool(cache_callbacks);
}
Beispiel #13
0
NTSTATUS
TapeSetMediaParameters(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++
Routine Description:

    This routine sets the fixed-length logical block size or variable-length
    block mode (if the block size is 0).

Arguments:

    DeviceObject
    Irp

Return Value:

    NTSTATUS

--*/

{
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
    PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer;
    PMODE_PARM_READ_WRITE_DATA buffer;
    SCSI_REQUEST_BLOCK  srb;
    PCDB                cdb = (PCDB)srb.Cdb;
    NTSTATUS            status;

    DebugPrint((3,"TapeIoControl: Set Tape Media Parameters \n"));

    //
    // Zero CDB in SRB on stack.
    //

    RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);

    srb.CdbLength = CDB6GENERIC_LENGTH;

    cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;

    //
    // Set timeout value.
    //

    srb.TimeOutValue = deviceExtension->TimeOutValue;

    cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA);
    cdb->MODE_SELECT.Reserved1 = MODE_SELECT_PFBIT;

    buffer = ExAllocatePool(NonPagedPoolCacheAligned,
        sizeof(MODE_PARM_READ_WRITE_DATA));

    if (!buffer) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(buffer, sizeof(MODE_PARM_READ_WRITE_DATA));

    buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
    buffer->ParameterListHeader.BlockDescriptorLength = MODE_BLOCK_DESC_LENGTH;

    buffer->ParameterListBlock.BlockLength[0] =
        (UCHAR)((tapeSetMediaParams->BlockSize >> 16) & 0xFF);
    buffer->ParameterListBlock.BlockLength[1] =
        (UCHAR)((tapeSetMediaParams->BlockSize >> 8) & 0xFF);
    buffer->ParameterListBlock.BlockLength[2] =
        (UCHAR)(tapeSetMediaParams->BlockSize & 0xFF);

    status = ScsiClassSendSrbSynchronous(DeviceObject,
                                &srb,
                                buffer,
                                sizeof( MODE_PARM_READ_WRITE_DATA ),
                                TRUE);

    ExFreePool(buffer);

    return status;

} // end TapeSetMediaParameters()
Beispiel #14
0
NTSTATUS
TapeGetMediaParameters(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++
Routine Description:

    The OVERLAND 9-track tape device can return whether media is
    write-protected.

Arguments:

    DeviceObject
    Irp

Return Value:

    NTSTATUS

--*/

{
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
    PTAPE_GET_MEDIA_PARAMETERS tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer;
    PNINE_TRACKSENSE_DATA  buffer;
    SCSI_REQUEST_BLOCK  srb;
    PCDB                cdb = (PCDB)srb.Cdb;
    NTSTATUS            status;

    DebugPrint((3,"TapeGetMediaParameters: Get Tape Media Parameters\n"));

    //
    // Zero SRB on stack.
    //

    RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));

    srb.CdbLength = CDB6GENERIC_LENGTH;

    cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;

    //
    // Set timeout value.
    //

    srb.TimeOutValue = deviceExtension->TimeOutValue;

    cdb->MODE_SENSE.AllocationLength = sizeof(NINE_TRACKSENSE_DATA);
    cdb->MODE_SENSE.PageCode = MODE_SENSE_CURRENT_VALUES;
    cdb->MODE_SENSE.Pc = 0x0B;

    buffer = ExAllocatePool(NonPagedPoolCacheAligned,
        sizeof(NINE_TRACKSENSE_DATA));

    if (!buffer) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = ScsiClassSendSrbSynchronous(DeviceObject,
                                &srb,
                                buffer,
                                sizeof(NINE_TRACKSENSE_DATA),
                                FALSE);

    if (status == STATUS_DATA_OVERRUN) {
        status = STATUS_SUCCESS;
    }

    if (NT_SUCCESS(status)) {
        Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);

        tapeGetMediaParams->BlockSize = buffer->BlockLength[2];
        tapeGetMediaParams->BlockSize += buffer->BlockLength[1] << 8;
        tapeGetMediaParams->BlockSize += buffer->BlockLength[0] << 16;

        tapeGetMediaParams->WriteProtected = buffer->WriteProtected;
        tapeGetMediaParams->PartitionCount = 0;
    }

    ExFreePool(buffer);

    return status;
    return status;

} // end TapeGetMediaParameters()
Beispiel #15
0
NTSTATUS
FatPostStackOverflowRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN PFCB Fcb
)

/*++

Routine Description:

    This routine posts a read request that could not be processed by
    the fsp thread because of stack overflow potential.

Arguments:

    Irp - Supplies the request to process.

    Fcb - Supplies the file.

Return Value:

    STATUS_PENDING.

--*/

{
    PKEVENT Event;
    PERESOURCE Resource;

    DebugTrace(0, Dbg, "Getting too close to stack limit pass request to Fsp\n", 0 );

    //
    //  Allocate an event and get shared on the resource we will
    //  be later using the common read.
    //

    Event = FsRtlAllocatePool( NonPagedPool, sizeof(KEVENT) );
    KeInitializeEvent( Event, NotificationEvent, FALSE );

    if (FlagOn(Irp->Flags, IRP_PAGING_IO) && (Fcb->Header.PagingIoResource != NULL)) {

        Resource = Fcb->Header.PagingIoResource;

    } else {

        Resource = Fcb->Header.Resource;
    }

    ExAcquireResourceShared( Resource, TRUE );

    try {

        //
        //  Make the Irp just like a regular post request and
        //  then send the Irp to the special overflow thread.
        //  After the post we will wait for the stack overflow
        //  read routine to set the event that indicates we can
        //  now release the scb resource and return.
        //

        FatPrePostIrp( IrpContext, Irp );

        //
        //  If this read is the result of a verify, we have to
        //  tell the overflow read routne to temporarily
        //  hijack the Vcb->VerifyThread field so that reads
        //  can go through.
        //

        if (Fcb->Vcb->VerifyThread == KeGetCurrentThread()) {

            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ);
        }

        FsRtlPostStackOverflow( IrpContext, Event, FatStackOverflowRead );

        //
        //  And wait for the worker thread to complete the item
        //

        (VOID) KeWaitForSingleObject( Event, Executive, KernelMode, FALSE, NULL );

    }
    finally {

        ExReleaseResource( Resource );

        ExFreePool( Event );
    }

    return STATUS_PENDING;
}
Beispiel #16
0
VOID
NTAPI
LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
                     IN BOOLEAN Destroy)
{
    PLIST_ENTRY ListHead, NextEntry;
    PETHREAD Thread;
    PLPCP_MESSAGE Message;
    PLPCP_PORT_OBJECT ConnectionPort = NULL;
    PLPCP_CONNECTION_MESSAGE ConnectMessage;
    PAGED_CODE();
    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);

    /* Hold the lock */
    KeAcquireGuardedMutex(&LpcpLock);

    /* Check if we have a connected port */
    if (((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_UNCONNECTED_PORT) &&
        (Port->ConnectedPort))
    {
        /* Disconnect it */
        Port->ConnectedPort->ConnectedPort = NULL;
        ConnectionPort = Port->ConnectedPort->ConnectionPort;
        if (ConnectionPort)
        {
            /* Clear connection port */
            Port->ConnectedPort->ConnectionPort = NULL;
        }
    }

    /* Check if this is a connection port */
    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT)
    {
        /* Delete the name */
        Port->Flags |= LPCP_NAME_DELETED;
    }

    /* Walk all the threads waiting and signal them */
    ListHead = &Port->LpcReplyChainHead;
    NextEntry = ListHead->Flink;
    while ((NextEntry) && (NextEntry != ListHead))
    {
        /* Get the Thread */
        Thread = CONTAINING_RECORD(NextEntry, ETHREAD, LpcReplyChain);

        /* Make sure we're not in exit */
        if (Thread->LpcExitThreadCalled) break;

        /* Move to the next entry */
        NextEntry = NextEntry->Flink;

        /* Remove and reinitialize the List */
        RemoveEntryList(&Thread->LpcReplyChain);
        InitializeListHead(&Thread->LpcReplyChain);

        /* Check if someone is waiting */
        if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore))
        {
            /* Get the message */
            Message = LpcpGetMessageFromThread(Thread);
            if (Message)
            {
                /* Check if it's a connection request */
                if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
                {
                    /* Get the connection message */
                    ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);

                    /* Check if it had a section */
                    if (ConnectMessage->SectionToMap)
                    {
                        /* Dereference it */
                        ObDereferenceObject(ConnectMessage->SectionToMap);
                    }
                }

                /* Clear the reply message */
                Thread->LpcReplyMessage = NULL;

                /* And remove the message from the port zone */
                LpcpFreeToPortZone(Message, 1);
                NextEntry = Port->LpcReplyChainHead.Flink;
            }

            /* Release the semaphore and reset message id count */
            Thread->LpcReplyMessageId = 0;
            KeReleaseSemaphore(&Thread->LpcReplySemaphore, 0, 1, FALSE);
        }
    }

    /* Reinitialize the list head */
    InitializeListHead(&Port->LpcReplyChainHead);

    /* Loop queued messages */
    while ((Port->MsgQueue.ReceiveHead.Flink) &&
           !(IsListEmpty(&Port->MsgQueue.ReceiveHead)))
    {
        /* Get the message */
        Message = CONTAINING_RECORD(Port->MsgQueue.ReceiveHead.Flink,
                                    LPCP_MESSAGE,
                                    Entry);

        /* Free and reinitialize it's list head */
        RemoveEntryList(&Message->Entry);
        InitializeListHead(&Message->Entry);

        /* Remove it from the port zone */
        LpcpFreeToPortZone(Message, 1);
    }

    /* Release the lock */
    KeReleaseGuardedMutex(&LpcpLock);

    /* Dereference the connection port */
    if (ConnectionPort) ObDereferenceObject(ConnectionPort);

    /* Check if we have to free the port entirely */
    if (Destroy)
    {
        /* Check if the semaphore exists */
        if (Port->MsgQueue.Semaphore)
        {
            /* Use the semaphore to find the port queue and free it */
            ExFreePool(CONTAINING_RECORD(Port->MsgQueue.Semaphore,
                                         LPCP_NONPAGED_PORT_QUEUE,
                                         Semaphore));
        }
    }
}
Beispiel #17
0
NTSTATUS
	IrpCreateFile(
	IN PUNICODE_STRING FileName,
	IN ACCESS_MASK DesiredAccess,
	__out PIO_STATUS_BLOCK IoStatusBlock,
	IN ULONG FileAttributes,
	IN ULONG ShareAccess,
	IN ULONG CreateDisposition,
	IN ULONG CreateOptions,
	IN PDEVICE_OBJECT DeviceObject,
	IN PDEVICE_OBJECT RealDevice,
	OUT PFILE_OBJECT *Object
	)
{
	NTSTATUS status;
	KEVENT event;
	PIRP irp;
	PIO_STACK_LOCATION irpSp;
	IO_SECURITY_CONTEXT securityContext;
	ACCESS_STATE accessState;
	OBJECT_ATTRIBUTES objectAttributes;
	PFILE_OBJECT fileObject;
	AUX_ACCESS_DATA auxData;

	PAGED_CODE();

	RtlZeroMemory(&auxData, sizeof(AUX_ACCESS_DATA));
	
	InitializeObjectAttributes(&objectAttributes, NULL, OBJ_CASE_INSENSITIVE| OBJ_KERNEL_HANDLE, 0, NULL);

	status = ObCreateObject(KernelMode,
		*IoFileObjectType,
		&objectAttributes,
		KernelMode,
		NULL,
		sizeof(FILE_OBJECT),
		0,
		0,
		(PVOID *)&fileObject);

	if (!NT_SUCCESS(status)) {
		return status;
	}

	RtlZeroMemory(fileObject, sizeof(FILE_OBJECT));
	fileObject->Type = IO_TYPE_FILE;
	fileObject->Size = sizeof(FILE_OBJECT);
	fileObject->DeviceObject = RealDevice;
	//	fileObject->RelatedFileObject = NULL;
	fileObject->Flags = FO_SYNCHRONOUS_IO;
	fileObject->FileName.MaximumLength = FileName->MaximumLength;
	fileObject->FileName.Buffer = (PWCH)ExAllocatePoolWithTag(NonPagedPool, FileName->MaximumLength, 'File');
	//fileObject->FileObjectExtension
	if (fileObject->FileName.Buffer == NULL) {
		ObDereferenceObject(fileObject);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	RtlCopyUnicodeString(&fileObject->FileName, FileName);
	KeInitializeEvent(&fileObject->Lock, SynchronizationEvent, FALSE);
	KeInitializeEvent(&fileObject->Event, NotificationEvent, FALSE);

	irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
	
	if (irp == NULL) {
		ObDereferenceObject(fileObject);
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	KeInitializeEvent(&event, SynchronizationEvent, FALSE);

	irp->MdlAddress = NULL;
	irp->Flags |= IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API;
	irp->RequestorMode = KernelMode;
	irp->UserIosb = IoStatusBlock;
	////LCXL:CHANGE
	irp->UserEvent = &event;
	//irp->UserEvent = NULL;
	irp->PendingReturned = FALSE;
	irp->Cancel = FALSE;
	irp->CancelRoutine = NULL;
	irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
	irp->Tail.Overlay.AuxiliaryBuffer = NULL;
	irp->Tail.Overlay.OriginalFileObject = fileObject;

	status = SeCreateAccessState(&accessState,
		&auxData,
		DesiredAccess,
		IoGetFileObjectGenericMapping());

	if (!NT_SUCCESS(status)) {
		IoFreeIrp(irp);
		ExFreePool(fileObject->FileName.Buffer);
		ObDereferenceObject(fileObject);
		return status;
	}

	securityContext.SecurityQos = NULL;
	securityContext.AccessState = &accessState;
	securityContext.DesiredAccess = DesiredAccess;
	securityContext.FullCreateOptions = 0;

	irpSp = IoGetNextIrpStackLocation(irp);
	irpSp->MajorFunction = IRP_MJ_CREATE;
	irpSp->DeviceObject = DeviceObject;
	irpSp->FileObject = fileObject;
	irpSp->Parameters.Create.SecurityContext = &securityContext;
	irpSp->Parameters.Create.Options = (CreateDisposition << 24) | CreateOptions;
	irpSp->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
	irpSp->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
	irpSp->Parameters.Create.EaLength = 0;

	IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE);
	status = IoCallDriver(DeviceObject, irp);

	if (status == STATUS_PENDING) {
		KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);
	}

	status = IoStatusBlock->Status;

	if (!NT_SUCCESS(status)) {
		ExFreePool(fileObject->FileName.Buffer);
		fileObject->FileName.Length = 0;
		fileObject->DeviceObject = NULL;
		ObDereferenceObject(fileObject);
	} else {
		InterlockedIncrement(&fileObject->DeviceObject->ReferenceCount);
		if (fileObject->Vpb) {
			InterlockedIncrement((PLONG)&fileObject->Vpb->ReferenceCount);
		}
		*Object = fileObject;
		KdPrint(("IrpCreateFile:Open file success! object = %x\n", fileObject));
	}

	return status;
}
NTSTATUS UpdateDeviceInformation( PDEVICE_OBJECT fdo )
{
    PUSB_STRING_DESCRIPTOR desc;
    UNICODE_STRING         dummy;
    URB                    urb;    
    int                    id;      
    NTSTATUS               status;
    
    KdPrint((DRIVERNAME " - UpdateDeviceInformation\n"));

    status = STATUS_SUCCESS;

    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

    // initialize buffers
    pdx->manufacturer.Buffer = NULL;
    pdx->product     .Buffer = NULL;
    pdx->serialNumber.Buffer = NULL;
    pdx->displayName .Buffer = NULL;
    desc                     = NULL;
    
    // allocate buffers for all strings
    pdx->manufacturer.Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG );
    pdx->product     .Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG );
    pdx->serialNumber.Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG );
    pdx->displayName .Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG );

    if( 
        (pdx->manufacturer.Buffer == NULL) ||
        (pdx->product     .Buffer == NULL) ||
        (pdx->serialNumber.Buffer == NULL) ||
        (pdx->displayName .Buffer == NULL)   
      )
    {
        KdPrint((DRIVERNAME " - Unable to allocate memory for device info\n"));        
        status =  STATUS_INSUFFICIENT_RESOURCES;
        goto cleanup;
    }
    
    pdx->manufacturer.Length        = 0;
    pdx->manufacturer.MaximumLength = StringDescriptorBytes;    
    pdx->product     .Length        = 0;
    pdx->product     .MaximumLength = StringDescriptorBytes;    
    pdx->serialNumber.Length        = 0;
    pdx->serialNumber.MaximumLength = StringDescriptorBytes;    
    pdx->displayName .Length        = 0;
    pdx->displayName .MaximumLength = StringDescriptorBytes;
    
    // allocate buffer for device string descriptor requests
    desc = (PUSB_STRING_DESCRIPTOR)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, SPOT_TAG );
    
    if(!desc)
    {
        KdPrint((DRIVERNAME " - Unable to allocate %X bytes for string descriptor\n", sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes));
        status =  STATUS_INSUFFICIENT_RESOURCES;
        goto cleanup;
    }

    
    if(0 != pdx->dd.iManufacturer)
    {
        // Manufacturer
        UsbBuildGetDescriptorRequest(&urb, 
                                 sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), 
                                 USB_STRING_DESCRIPTOR_TYPE,
                                 pdx->dd.iManufacturer,
                                 LangId, 
                                 desc, 
                                 NULL, 
                                 sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes,
                                 NULL);
        
        status = SendAwaitUrb(fdo, &urb);

        if(NT_SUCCESS(status))
        {            
            desc->bString[ (desc->bLength / 2) - 1 ] = L'\0';

            RtlInitUnicodeString( &dummy            , desc->bString );
            RtlCopyUnicodeString( &pdx->manufacturer, &dummy        );
        }
        else
        {
            RtlInitUnicodeString( &dummy            , EmptyString );
            RtlCopyUnicodeString( &pdx->manufacturer, &dummy      );
            KdPrint(( DRIVERNAME " - could not retrieve manufacturer %08x\n", status ));                
        }
    }

    if(0 != pdx->dd.iProduct)
    {
        // Product
        UsbBuildGetDescriptorRequest(&urb, 
                                 sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), 
                                 USB_STRING_DESCRIPTOR_TYPE,
                                 pdx->dd.iProduct,
                                 LangId, 
                                 desc, 
                                 NULL, 
                                 sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes,
                                 NULL);
        
        status = SendAwaitUrb(fdo, &urb);

        if(NT_SUCCESS(status))
        {            
            desc->bString[ (desc->bLength / 2) - 1 ] = L'\0';

            RtlInitUnicodeString( &dummy       , desc->bString );
            RtlCopyUnicodeString( &pdx->product, &dummy        );
            
        }
        else
        {
            RtlInitUnicodeString( &dummy       , EmptyString );
            RtlCopyUnicodeString( &pdx->product, &dummy      );       
            KdPrint(( DRIVERNAME " - could not retrieve product %08x\n", status ));          
        }
    }

    if(0 != pdx->dd.iSerialNumber)
    {
        // Serial Number
        UsbBuildGetDescriptorRequest(&urb, 
                                 sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), 
                                 USB_STRING_DESCRIPTOR_TYPE,
                                 pdx->dd.iSerialNumber,
                                 LangId, 
                                 desc, 
                                 NULL, 
                                 sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes,
                                 NULL);
        
        status = SendAwaitUrb(fdo, &urb);

        if(NT_SUCCESS(status))
        {            
            desc->bString[ (desc->bLength / 2) - 1 ] = L'\0';
            
            RtlInitUnicodeString( &dummy            , desc->bString );
            RtlCopyUnicodeString( &pdx->serialNumber, &dummy        );
            
        }
        else
        {          
            RtlInitUnicodeString( &dummy            , EmptyString );
            RtlCopyUnicodeString( &pdx->serialNumber, &dummy      );
            KdPrint(( DRIVERNAME " - could not retrieve serial number %08x\n", status ));            
        }
    }
    
    // DisplayName
    UsbBuildGetDescriptorRequest(&urb, 
                             sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), 
                             USB_STRING_DESCRIPTOR_TYPE,
                             DisplayNameId,
                             LangId, 
                             desc, 
                             NULL, 
                             sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes,
                             NULL);
    
    status = SendAwaitUrb(fdo, &urb);

    if(NT_SUCCESS(status))
    {            
        desc->bString[ (desc->bLength / 2) - 1 ] = L'\0';
        

        RtlInitUnicodeString( &dummy           , desc->bString );
        RtlCopyUnicodeString( &pdx->displayName, &dummy        );
        
    }
    else
    {
        RtlInitUnicodeString( &dummy            , EmptyString );
        RtlCopyUnicodeString( &pdx->displayName, &dummy      );
        KdPrint(( DRIVERNAME " - could not retrieve display name %08x\n", status ));    
    }

cleanup:
    
    if(desc) ExFreePool( desc );
    
    if(!NT_SUCCESS(status))
    {
        if(pdx->manufacturer.Buffer) ExFreePool( pdx->manufacturer.Buffer );
        if(pdx->product     .Buffer) ExFreePool( pdx->product     .Buffer );
        if(pdx->serialNumber.Buffer) ExFreePool( pdx->serialNumber.Buffer );
        if(pdx->displayName .Buffer) ExFreePool( pdx->displayName .Buffer );

        pdx->manufacturer.Buffer = NULL;
        pdx->product     .Buffer = NULL;
        pdx->serialNumber.Buffer = NULL;
        pdx->displayName .Buffer = NULL;       
    }
    
    return status;
}
Beispiel #19
0
NTSTATUS transfer(libusb_device_t *dev, IRP *irp,
                  int direction, int urb_function, int endpoint, 
                  int packet_size, MDL *buffer, int size)
{
  IO_STACK_LOCATION *stack_location = NULL;
  context_t *context;
  NTSTATUS status = STATUS_SUCCESS;
 
  DEBUG_PRINT_NL();

  if(urb_function == URB_FUNCTION_ISOCH_TRANSFER)
    DEBUG_MESSAGE("transfer(): isochronous transfer");
  else
    DEBUG_MESSAGE("transfer(): bulk or interrupt transfer");

  if(direction == USBD_TRANSFER_DIRECTION_IN)
    DEBUG_MESSAGE("transfer(): direction in");
  else
    DEBUG_MESSAGE("transfer(): direction out");

  DEBUG_MESSAGE("transfer(): endpoint 0x%02x", endpoint);

  if(urb_function == URB_FUNCTION_ISOCH_TRANSFER)
    DEBUG_MESSAGE("transfer(): packet_size 0x%x", packet_size);

  DEBUG_MESSAGE("transfer(): size %d", size);
  DEBUG_MESSAGE("transfer(): sequence %d", sequence);
  DEBUG_PRINT_NL();

  if(!dev->config.value)
    {
      DEBUG_ERROR("transfer(): invalid configuration 0");
      remove_lock_release(dev);
      return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0);
    }
  
  context = ExAllocatePool(NonPagedPool, sizeof(context_t));

  if(!context)
    {
      remove_lock_release(dev);
      return complete_irp(irp, STATUS_NO_MEMORY, 0);
    }

  status = create_urb(dev, &context->urb, direction, urb_function, 
                      endpoint, packet_size, buffer, size);
    
  if(!NT_SUCCESS(status))
    {
      ExFreePool(context);
      remove_lock_release(dev);
      return complete_irp(irp, status, 0);
    }

  context->sequence = sequence++;

  stack_location = IoGetNextIrpStackLocation(irp);
    
  stack_location->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  stack_location->Parameters.Others.Argument1 = context->urb;
  stack_location->Parameters.DeviceIoControl.IoControlCode 
    = IOCTL_INTERNAL_USB_SUBMIT_URB;
    
  IoSetCompletionRoutine(irp, transfer_complete, context,
                         TRUE, TRUE, TRUE);
    
  return IoCallDriver(dev->target_device, irp);
}
NTSTATUS StartDevice( PDEVICE_OBJECT fdo, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PARTIAL_RESOURCE_LIST translated )
{
    USB_CONFIGURATION_DESCRIPTOR  tcd;
    PUSB_CONFIGURATION_DESCRIPTOR pcd;
    PUSB_STRING_DESCRIPTOR        desc;            
    HANDLE                        RecoveryHandle;
    PURB                          selurb;
    URB                           urb;     
    NTSTATUS                      status;

    status = STATUS_SUCCESS; 
    
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

    selurb = NULL;
    pcd    = NULL;

    // Read our device descriptor. The only real purpose to this would be to find out how many
    // configurations there are so we can read their descriptors. In this simplest of examples,
    // there's only one configuration.
    
    KdPrint((DRIVERNAME " - Start device\n"));

    UsbBuildGetDescriptorRequest(
                                  &urb, 
                                  sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), 
                                  USB_DEVICE_DESCRIPTOR_TYPE,
                                  0, 
                                  LangId, 
                                  &pdx->dd, 
                                  NULL, 
                                  sizeof(pdx->dd), 
                                  NULL
                                );
 
    status = SendAwaitUrb( fdo, &urb );
    
    if(!NT_SUCCESS(status))
    {
        KdPrint((DRIVERNAME " - Error %X trying to retrieve device descriptor\n", status));
        goto cleanup;
    }

    // allocate the buffer for the descriptor; take extra space to null terminate the bString member
    desc = (PUSB_STRING_DESCRIPTOR)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, SPOT_TAG );

    if(!desc)
    {
        KdPrint((DRIVERNAME " - Unable to allocate %X bytes for string descriptor\n", sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto cleanup;
    }
    
    pdx->devHash = desc;

    UsbBuildGetDescriptorRequest(&urb, 
                                 sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), 
                                 USB_STRING_DESCRIPTOR_TYPE,
                                 DeviceId, 
                                 LangId, 
                                 desc, 
                                 NULL, 
                                 sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes,
                                 NULL);
    
    status = SendAwaitUrb(fdo, &urb);
    
    if(!NT_SUCCESS(status))
    {
        KdPrint((DRIVERNAME " - Error %X trying to retrieve string descriptor for DeviceId\n", status));
        goto cleanup;
    }
        
    // null terminate the buffer; we allocated one more wchar_t for the purpose 
    desc->bString[ (desc->bLength / 2) - 1 ] = L'\0';

    UpdateDeviceInformation( fdo );

    // Read the descriptor of the first configuration. This requires two steps. The first step
    // reads the fixed-size configuration descriptor alone. The second step reads the
    // configuration descriptor plus all imbedded interface and endpoint descriptors.

    UsbBuildGetDescriptorRequest(&urb, 
                                 sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), 
                                 USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                 0, 
                                 LangId, 
                                 &tcd, 
                                 NULL, 
                                 sizeof(tcd), 
                                 NULL);

    status = SendAwaitUrb(fdo, &urb);
    
    if(!NT_SUCCESS(status))
    {
        KdPrint((DRIVERNAME " - Error %X trying to read configuration descriptor 1\n", status));
        goto cleanup;
    }

    ULONG size = tcd.wTotalLength;
    
    pcd = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePoolWithTag(NonPagedPool, size, SPOT_TAG);
    
    if(!pcd)
    {
        KdPrint((DRIVERNAME " - Unable to allocate %X bytes for configuration descriptor\n", size));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto cleanup;
    }

    UsbBuildGetDescriptorRequest(&urb, 
                                 sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), 
                                 USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                 0, 
                                 LangId, 
                                 pcd, 
                                 NULL, 
                                 size, 
                                 NULL);

    status = SendAwaitUrb(fdo, &urb);
    if(!NT_SUCCESS(status))
    {
        KdPrint((DRIVERNAME " - Error %X trying to read configuration descriptor 1\n", status));
        goto cleanup;
    }
                           
    // Locate the descriptor for the one and only interface we expect to find

    PUSB_INTERFACE_DESCRIPTOR pid = USBD_ParseConfigurationDescriptorEx(pcd, 
                                                                        pcd,
                                                                        -1, 
                                                                        -1, 
                                                                        -1, 
                                                                        -1, 
                                                                        -1);

    ASSERT(pid);
                           
    // Create a URB to use in selecting a configuration.

    USBD_INTERFACE_LIST_ENTRY interfaces[2] = {
        {pid, NULL},
        {NULL, NULL},        // fence to terminate the array
    };

    selurb = USBD_CreateConfigurationRequestEx(pcd, interfaces);
    if(!selurb)
    {
        KdPrint((DRIVERNAME " - Unable to create configuration request\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto cleanup;
    }

    // Verify that the interface describes exactly the endpoints we expect
    if(pid->bNumEndpoints != 2)
    {
        KdPrint((DRIVERNAME " - %d is the wrong number of endpoints\n", pid->bNumEndpoints));
        status = STATUS_DEVICE_CONFIGURATION_ERROR;
        goto cleanup;
    }

    PUSB_ENDPOINT_DESCRIPTOR ped = (PUSB_ENDPOINT_DESCRIPTOR) pid;
    ped = (PUSB_ENDPOINT_DESCRIPTOR) USBD_ParseDescriptors(pcd, tcd.wTotalLength, ped, USB_ENDPOINT_DESCRIPTOR_TYPE);
    if(!ped || 0 == (ped->bEndpointAddress & 0x80) || ped->bmAttributes != USB_ENDPOINT_TYPE_BULK || ped->wMaxPacketSize > 64)
    {
        KdPrint((DRIVERNAME " - Endpoint has wrong attributes\n"));
        status = STATUS_DEVICE_CONFIGURATION_ERROR;
        goto cleanup;
    }
    ++ped;
    if(!ped || 0 != (ped->bEndpointAddress & 0x80) || ped->bmAttributes != USB_ENDPOINT_TYPE_BULK || ped->wMaxPacketSize > 64)
    {
        KdPrint((DRIVERNAME " - Endpoint has wrong attributes\n"));
        status = STATUS_DEVICE_CONFIGURATION_ERROR;
        goto cleanup;
    }
    ++ped;

    PUSBD_INTERFACE_INFORMATION pii = interfaces[0].Interface;
    ASSERT(pii->NumberOfPipes == pid->bNumEndpoints);

    // Initialize the maximum transfer size for each of the endpoints. The
    // default would be PAGE_SIZE. The firmware itself only has a 4096-byte
    // ring buffer, though. We need to restrict the test applet to that many
    // bytes. In order to exercise the multi-segment aspect of the transfer code,
    // therefore, reduce the maximum transfer size to 1024 bytes.

    pii->Pipes[0].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
    pii->Pipes[1].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
    pdx->maxtransfer = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;

    // Submit the set-configuration request

    status = SendAwaitUrb(fdo, selurb);
    if(!NT_SUCCESS(status))
    {
        KdPrint((DRIVERNAME " - Error %X trying to select configuration\n", status));
        goto cleanup;
    }

    // Save the configuration and pipe handles
    pdx->hconfig = selurb->UrbSelectConfiguration.ConfigurationHandle;
    pdx->hinpipe = pii->Pipes[0].PipeHandle;
    pdx->houtpipe = pii->Pipes[1].PipeHandle;

    // Transfer ownership of the configuration descriptor to the device extension

    pdx->pcd = pcd;
    pcd = NULL;

    // Enable the interface
    IoSetDeviceInterfaceState(&pdx->operationsInterfaceName, TRUE);        

    // Enable the interface
    IoSetDeviceInterfaceState(&pdx->inquiriesInterfaceName, TRUE);                    

    // create recovery thread                     
    status = PsCreateSystemThread(&RecoveryHandle, 0, NULL, NULL, NULL, RecoveryThread, (PVOID)pdx);

    if(!NT_SUCCESS(status))
    {
        KdPrint((DRIVERNAME " - PsCreateSystemThread failed with error %08x\n", status));
        goto cleanup;
    }
    
    status = ObReferenceObjectByHandle( RecoveryHandle,
                                        SYNCHRONIZE,
                                        NULL,
                                        KernelMode,
                                        (PVOID*)&pdx->RecoveryThread,
                                        NULL );

    ASSERT(NT_SUCCESS(status));

    ZwClose(RecoveryHandle);
    
    // Start polling
    status = StartPolling(pdx);
    
    if(!NT_SUCCESS(status))
    {   
        KdPrint((DRIVERNAME " - StartPolling failed 0x%08x\n", status));

        if(pdx->RecoveryThread)
        {
            // shutdown recovery thread
            pdx->RecoveryExit = TRUE; 
            KeSetEvent(&pdx->RecoveryEvent, 0, FALSE);    
            // wait for polling thread to exit 
            KeWaitForSingleObject(pdx->RecoveryThread, Executive, KernelMode, FALSE, NULL);     
            ObDereferenceObject(pdx->RecoveryThread);
            pdx->RecoveryThread = NULL;
        }
        
        goto cleanup;
    }
    
cleanup:
    if(selurb) ExFreePool(selurb);
    if(pcd   ) ExFreePool(pcd   );

    // get rid of return codes like STATUS_PENDING
    if(NT_SUCCESS(status)) 
    {
        return STATUS_SUCCESS;
    }
    
    return status;
}
Beispiel #21
0
VOID
LfsFindLogRecord (
    IN PLFCB Lfcb,
    IN OUT PLfsLCB Lcb,
    IN LSN Lsn,
    OUT PLFS_RECORD_TYPE RecordType,
    OUT TRANSACTION_ID *TransactionId,
    OUT PLSN UndoNextLsn,
    OUT PLSN PreviousLsn,
    OUT PULONG BufferLength,
    OUT PVOID *Buffer
    )

/*++

Routine Description:

    This routine is called recover a log record for a client.

Arguments:

    Lfcb - Log file control block for this file.

    Lcb - Pointer to the context block to update.

    Lsn - This is the Lsn for the log record.

    RecordType - Supplies the address to store the record type of this
                 log record.

    TransactionId - Supplies the address to store the transaction Id of
                    this log record.

    UndoNextLsn - Supplies the address to store the Undo Next Lsn for this
                  log record.

    PreviousLsn - Supplies the address to store the Previous Lsn for this
                  log record.

    BufferLength - Pointer to address to store the length in bytes of the
                   log record.

    Buffer - Pointer to store the address where the log record data begins.

Return Value:

    None

--*/

{
    PCHAR NewBuffer;
    BOOLEAN UsaError;
    LONGLONG LogRecordLength;
    ULONG PageOffset;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsFindLogRecord:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Lfcb          -> %08lx\n", Lfcb );
    LfsDebugTrace(  0, Dbg, "Context Block -> %08lx\n", Lcb );
    LfsDebugTrace(  0, Dbg, "Lsn (Low)     -> %08lx\n", Lsn.LowPart );

    NewBuffer = NULL;

    //
    //  Use a try-finally to facilitate cleanup.
    //

    __try {

        //
        //  Map the record header for this Lsn if we haven't already.
        //

        if (Lcb->RecordHeader == NULL) {

            LfsPinOrMapLogRecordHeader( Lfcb,
                                        Lsn,
                                        FALSE,
                                        FALSE,
                                        &UsaError,
                                        &Lcb->RecordHeader,
                                        &Lcb->RecordHeaderBcb );
        }

        //
        //  We now have the log record desired.  If the Lsn in the
        //  log record doesn't match the desired Lsn then the disk is
        //  corrupt.
        //

        if ( Lsn.QuadPart != Lcb->RecordHeader->ThisLsn.QuadPart ) {                                                   //**** xxNeq( Lsn, Lcb->RecordHeader->ThisLsn )

            ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
        }

        //
        //  Check that the length field isn't greater than the total available space
        //  in the log file.
        //

        LogRecordLength = Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength;                              //**** xxFromUlong( Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength );

        if ( LogRecordLength >= Lfcb->TotalAvailable ) {                                                               //**** xxGeq( LogRecordLength, Lfcb->TotalAvailable )

            ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
        }

        //
        //  If the entire log record is on this log page, put a pointer to
        //  the log record in the context block.
        //

        if (!FlagOn( Lcb->RecordHeader->Flags, LOG_RECORD_MULTI_PAGE )) {

            //
            //  If client size indicates that we have to go beyond the end of the current
            //  page, we raise an error.
            //

            PageOffset = LfsLsnToPageOffset( Lfcb, Lsn );

            if ((PageOffset + Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength)
                > (ULONG)Lfcb->LogPageSize) {

                ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
            }

            Lcb->CurrentLogRecord = LfsAdd2Ptr( Lcb->RecordHeader, LFS_RECORD_HEADER_SIZE, PVOID );
            Lcb->AuxilaryBuffer = FALSE;

        //
        //  Else we copy the data and remember that we allocated a buffer.
        //

        } else {

            NewBuffer = FsRtlAllocatePool( PagedPool, Lcb->RecordHeader->ClientDataLength );

            LfsCopyReadLogRecord( Lfcb,
                                  Lcb->RecordHeader,
                                  NewBuffer );

            Lcb->CurrentLogRecord = NewBuffer;

            Lcb->AuxilaryBuffer = TRUE;

            NewBuffer = NULL;
        }

        //
        //  We need to update the caller's parameters and the context block.
        //

        *RecordType = Lcb->RecordHeader->RecordType;
        *TransactionId = Lcb->RecordHeader->TransactionId;

        *UndoNextLsn = Lcb->RecordHeader->ClientUndoNextLsn;
        *PreviousLsn = Lcb->RecordHeader->ClientPreviousLsn;

        *Buffer = Lcb->CurrentLogRecord;
        *BufferLength = Lcb->RecordHeader->ClientDataLength;

    } __finally {

        DebugUnwind( LfsFindLogRecord );

        //
        //  If an error occurred we unpin the record header and the log
        //  We also free the buffer if allocated by us.
        //

        if (NewBuffer != NULL) {

            ExFreePool( NewBuffer );
        }

        LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", *BufferLength );
        LfsDebugTrace(  0, Dbg, "Buffer        -> %08lx\n", *Buffer );
        LfsDebugTrace( -1, Dbg, "LfsFindLogRecord:  Exit\n", 0 );
    }

    return;
}
NTSTATUS OnWriteComplete(PDEVICE_OBJECT fdo, PIRP Irp, PRWCONTEXT ctx)
{   
    PIO_STACK_LOCATION stack;
    NTSTATUS           status;
    ULONG              length;
    KIRQL              OldIrql;
    ULONG              count;
    
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

    status = Irp->IoStatus.Status;
    
    if(NT_SUCCESS(status) && ctx->remain && !Irp->Cancel)
    {
        /* we have more to transfer */
        length = ctx->remain;
        if(length > pdx->maxtransfer)
            length = pdx->maxtransfer;
        
        UsbBuildInterruptOrBulkTransferRequest(&ctx->urb,
                                               sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
                                               pdx->houtpipe,
                                               ctx->data,
                                               NULL,
                                               length,
                                               (USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK),
                                               NULL);

        ctx->data += length;
        ctx->remain -= length;
        
        stack = IoGetNextIrpStackLocation(Irp);
        stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
        stack->Parameters.Others.Argument1 = (PVOID)&ctx->urb;
        stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

        IoSetCompletionRoutine(Irp, 
                               (PIO_COMPLETION_ROUTINE)OnWriteComplete,
                               (PVOID) ctx,
                               TRUE,
                               TRUE,
                               TRUE);

        IoCallDriver(pdx->LowerDeviceObject, Irp);

        return STATUS_MORE_PROCESSING_REQUIRED;
    }
    
    if(NT_SUCCESS(status)) 
    {
        Irp->IoStatus.Information = ctx->total;
    } 
    else 
    {
        KdPrint((DRIVERNAME " - finished with error!\n"));
    }
    
    ExFreePool(ctx);

    StartNextPacket    ( &pdx->dqWrite, fdo    );
    IoReleaseRemoveLock( &pdx->RemoveLock, Irp );
    
    return STATUS_SUCCESS;
}
/* Source: WDK/src_5239/kmdf/1394/isochapi.c, line 679. */
NTSTATUS
t1394_IsochFreeResources(
    PDEVICE_EXTENSION   deviceExtension, /* added for SLAyer */
/*     IN WDFDEVICE   Device, */
/*     IN WDFREQUEST  Request, */
    /* IN */ HANDLE      hResource
    )
{
    NTSTATUS              ntStatus            = STATUS_SUCCESS;
/*     PDEVICE_EXTENSION     deviceExtension     = GetDeviceContext(Device); */
    PIRB                  pIrb                = NULL;
    PISOCH_RESOURCE_DATA  IsochResourceData   = NULL;
    PLIST_ENTRY           listHead;
    PLIST_ENTRY           thisEntry;

/*     ENTER("t1394_IsochFreeResources"); */

/*     TRACE(TL_TRACE, ("hResource = 0x%x\n", hResource)); */

    pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_1394);

    if (!pIrb) {

/*         TRACE(TL_ERROR, ("Failed to allocate pIrb!\n")); */
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit_IsochFreeResources;
    } // if

    // remove this one from our list...

	WdfSpinLockAcquire(deviceExtension->IsochResourceSpinLock);

    listHead = &deviceExtension->IsochResourceData;

    for(thisEntry = listHead->Flink;
                    thisEntry != listHead;
                    IsochResourceData = NULL, thisEntry = thisEntry->Flink)
    {
        IsochResourceData = CONTAINING_RECORD(thisEntry,
                                              ISOCH_RESOURCE_DATA,
                                              IsochResourceList);

        if (IsochResourceData->hResource == hResource) {
/*             TRACE(TL_TRACE, ("Removing hResource = 0x%x\n", hResource)); */
            RemoveEntryList(&IsochResourceData->IsochResourceList);
            ExFreePool(IsochResourceData);
            break;
        }
    }


	WdfSpinLockRelease(deviceExtension->IsochResourceSpinLock);

    RtlZeroMemory (pIrb, sizeof (IRB));
/*     pIrb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES; */
    pIrb->Flags = 0;
/*     pIrb->u.IsochFreeResources.hResource = hResource; */

/*     ntStatus = t1394_SubmitIrpSynch(deviceExtension->StackIoTarget, Request, pIrb); */

    if (!NT_SUCCESS(ntStatus)) {

/*         TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus)); */
    }

Exit_IsochFreeResources:

    if (pIrb)
    {
        ExFreePool(pIrb);
    }

/*     EXIT("t1394_IsochFreeResources", ntStatus); */
    return(ntStatus);
} // t1394_IsochFreeResources
Beispiel #24
0
NTSTATUS
LspCleanupLock(
   PLANSCSI_SESSION	LSS,
   UCHAR			LockNo
){
	NTSTATUS		status;
	LONG			i;
	LANSCSI_PDUDESC	pduDesc;
	BYTE			pduResponse;
	PLANSCSI_SESSION	tempLSS;
	LONG			maxConn;
	LARGE_INTEGER	GenericTimeOut;
	TA_LSTRANS_ADDRESS	BindingAddress, TargetAddress;
	LSSLOGIN_INFO	loginInfo;
	LSPROTO_TYPE	LSProto;
	ULONG			cleaned;

	//
	//	Parameter check
	//

	if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) {
		return STATUS_NOT_SUPPORTED;
	}

	if(LSS->HWVersion >= 1) {
		maxConn = LANSCSIIDE_MAX_CONNECTION_VER11 - 1;
	} else {
		return STATUS_NOT_SUPPORTED;
	}

	tempLSS = ExAllocatePoolWithTag(
							NonPagedPool,
							maxConn * sizeof(LANSCSI_SESSION),
							LSS_POOLTAG);
	RtlZeroMemory(tempLSS, maxConn * sizeof(LANSCSI_SESSION));

	//
	//	Init variables
	//

	status = STATUS_SUCCESS;
	RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC));
	pduDesc.Param8[3] = (UCHAR)LockNo;
	LspGetAddresses(LSS, &BindingAddress, &TargetAddress);
	GenericTimeOut.QuadPart = NANO100_PER_SEC * 5;
	cleaned = 0;


	//
	//	Try to make connections to fill up connection pool of the NDAS device.
	//	So, we can clear invalid acquisition of the locks.
	//
	KDPrintM(DBG_LURN_ERROR,("Try to clean up lock\n"));
	for (i=0 ; i < maxConn; i++) {


		//
		//	Connect and log in with read-only access.
		//

		//	connect
		LspSetTimeOut(&tempLSS[i], &GenericTimeOut);
		status = LspConnect(
					&tempLSS[i],
					&BindingAddress,
					&TargetAddress
					);
		if(!NT_SUCCESS(status)) {
			KDPrintM(DBG_LURN_ERROR, ("LspConnect(), Can't Connect to the LS node. STATUS:0x%08x\n", status));
			break;
		}
	}


	for (i=0; i < maxConn; i++) {

		if(!LspIsConnected(&tempLSS[i])) {
			continue;
		}

		KDPrintM(DBG_LURN_TRACE, ("Con#%u\n", i));
		cleaned++;

		//	extract login information from the existing LSS.
		LspBuildLoginInfo(LSS, &loginInfo);
		status = LspLookupProtocol(loginInfo.HWType, loginInfo.HWVersion, &LSProto);
		if(!NT_SUCCESS(status)) {
			LspDisconnect(&tempLSS[i]);
			KDPrintM(DBG_LURN_ERROR, ("Wrong hardware version.\n"));
			continue;
		}

		//	Log in with read-only access.
		if (loginInfo.HWVersion == LANSCSIIDE_VERSION_2_5) {
			loginInfo.UserID = MAKE_USER_ID(DEFAULT_USER_NUM, USER_PERMISSION_RO);
		} else {
			loginInfo.UserID &= 0x0000ffff;
		}
		status = LspLogin(
						&tempLSS[i],
						&loginInfo,
						LSProto,
						FALSE
					);
		if(!NT_SUCCESS(status)) {
			KDPrintM(DBG_LURN_ERROR, ("LspLogin() failed. STATUS:0x%08x\n", status));
			LspDisconnect(&tempLSS[i]);
			ASSERT(FALSE);
			continue;
		}


		//
		//	Acquire the lock on the NDAS device.
		//

		pduDesc.Command = VENDOR_OP_SET_MUTEX;
		status = LspVendorRequest(
						&tempLSS[i],
						&pduDesc,
						&pduResponse
						);
		if(pduResponse != LANSCSI_RESPONSE_SUCCESS) {
			KDPrintM(DBG_LURN_ERROR,	("Acquiring lock #%u denied by NDAS device\n", LockNo));
		}
		if(!NT_SUCCESS(status)) {
			LspDisconnect(&tempLSS[i]);
			KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status));
			continue;
		}

		//
		//	Release the lock on the NDAS device.
		//

		pduDesc.Command = VENDOR_OP_FREE_MUTEX;
		status = LspVendorRequest(
						&tempLSS[i],
						&pduDesc,
						&pduResponse
						);
		if(pduResponse != LANSCSI_RESPONSE_SUCCESS) {
			KDPrintM(DBG_LURN_ERROR,	("Releasing lock #%u denied by NDAS device\n", LockNo));
		}
		if(!NT_SUCCESS(status)) {
			LspDisconnect(&tempLSS[i]);
			KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status));
			continue;
		}


		//
		//	Log out and disconnect.
		//

		LspLogout(
			&tempLSS[i]
			);

		LspDisconnect(
			&tempLSS[i]
			);
	}

	KDPrintM(DBG_LURN_INFO, ("Cleaned #%u\n", cleaned));

	ExFreePool(tempLSS);

	return status;
}
Beispiel #25
0
/* Creates the server side */
NTSTATUS DEFAULTAPI
MsfsCreateMailslot(PDEVICE_OBJECT DeviceObject,
                   PIRP Irp)
{
    PEXTENDED_IO_STACK_LOCATION IoStack;
    PFILE_OBJECT FileObject;
    PMSFS_DEVICE_EXTENSION DeviceExtension;
    PMSFS_FCB Fcb;
    PMSFS_CCB Ccb;
    KIRQL oldIrql;
    PLIST_ENTRY current_entry;
    PMSFS_FCB current = NULL;
    PMAILSLOT_CREATE_PARAMETERS Buffer;

    DPRINT("MsfsCreateMailslot(DeviceObject %p Irp %p)\n", DeviceObject, Irp);

    IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
    DeviceExtension = DeviceObject->DeviceExtension;
    FileObject = IoStack->FileObject;
    Buffer = IoStack->Parameters.CreateMailslot.Parameters;

    DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);

    Fcb = ExAllocatePool(NonPagedPool, sizeof(MSFS_FCB));
    if (Fcb == NULL)
    {
        Irp->IoStatus.Status = STATUS_NO_MEMORY;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return STATUS_NO_MEMORY;
    }

    Fcb->Name.Length = FileObject->FileName.Length;
    Fcb->Name.MaximumLength = Fcb->Name.Length + sizeof(UNICODE_NULL);
    Fcb->Name.Buffer = ExAllocatePool(NonPagedPool, Fcb->Name.MaximumLength);
    if (Fcb->Name.Buffer == NULL)
    {
        ExFreePool(Fcb);

        Irp->IoStatus.Status = STATUS_NO_MEMORY;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return STATUS_NO_MEMORY;
    }

    RtlCopyUnicodeString(&Fcb->Name, &FileObject->FileName);

    Ccb = ExAllocatePool(NonPagedPool, sizeof(MSFS_CCB));
    if (Ccb == NULL)
    {
        ExFreePool(Fcb->Name.Buffer);
        ExFreePool(Fcb);

        Irp->IoStatus.Status = STATUS_NO_MEMORY;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return STATUS_NO_MEMORY;
    }

    Fcb->ReferenceCount = 0;
    InitializeListHead(&Fcb->CcbListHead);
    KeInitializeSpinLock(&Fcb->CcbListLock);

    Fcb->MaxMessageSize = Buffer->MaximumMessageSize;
    Fcb->MessageCount = 0;
    Fcb->TimeOut = Buffer->ReadTimeout;
    KeInitializeEvent(&Fcb->MessageEvent,
                      NotificationEvent,
                      FALSE);

    InitializeListHead(&Fcb->MessageListHead);
    KeInitializeSpinLock(&Fcb->MessageListLock);

    KeLockMutex(&DeviceExtension->FcbListLock);
    current_entry = DeviceExtension->FcbListHead.Flink;
    while (current_entry != &DeviceExtension->FcbListHead)
    {
        current = CONTAINING_RECORD(current_entry,
                                    MSFS_FCB,
                                    FcbListEntry);

        if (!RtlCompareUnicodeString(&Fcb->Name, &current->Name, TRUE))
            break;

        current_entry = current_entry->Flink;
    }

    if (current_entry != &DeviceExtension->FcbListHead)
    {
        ExFreePool(Fcb->Name.Buffer);
        ExFreePool(Fcb);
        ExFreePool(Ccb);

        KeUnlockMutex(&DeviceExtension->FcbListLock);

        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return STATUS_UNSUCCESSFUL;
    }
    else
    {
        InsertTailList(&DeviceExtension->FcbListHead,
                       &Fcb->FcbListEntry);
    }

    KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
    InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
    KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);

    Fcb->ReferenceCount++;
    Fcb->ServerCcb = Ccb;
    Ccb->Fcb = Fcb;

    KeUnlockMutex(&DeviceExtension->FcbListLock);

    FileObject->FsContext = Fcb;
    FileObject->FsContext2 = Ccb;
    FileObject->Flags |= FO_MAILSLOT;

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}
Beispiel #26
0
NTSTATUS
LspConnectEx(
		IN OUT PLANSCSI_SESSION	LSS,
		OUT PTA_LSTRANS_ADDRESS	BoundAddr,
		IN PTA_LSTRANS_ADDRESS	BindAddr,
		IN PTA_LSTRANS_ADDRESS	BindAddr2,
		IN PTA_LSTRANS_ADDRESS	DestAddr,
		IN BOOLEAN				BindAnyAddress
	) {
	NTSTATUS			status;
	PTA_LSTRANS_ADDRESS	addrList;
	ULONG				addrListLen;
	PTA_LSTRANS_ADDRESS	addrListPrioritized;
	ULONG				idx_addr;
	LSTRANS_TYPE		transport;


	ASSERT(LSS);
	ASSERT(DestAddr);


	//
	//	Parameter check
	//

	if(DestAddr->TAAddressCount != 1) {
		return STATUS_INVALID_PARAMETER;
	}

	if(DestAddr->Address[0].AddressType != TDI_ADDRESS_TYPE_LPX) {
		return STATUS_NOT_IMPLEMENTED;
	}
	if(BindAddr && DestAddr->Address[0].AddressType != BindAddr->Address[0].AddressType)
		return STATUS_INVALID_PARAMETER;
	if(BindAddr2 && DestAddr->Address[0].AddressType != BindAddr2->Address[0].AddressType)
		return STATUS_INVALID_PARAMETER;


	//
	//	Initialize variables
	//

	addrList = NULL;
	addrListPrioritized = NULL;


	do {

		//
		//	Query binding address list
		//
	
		addrList = LstranAllocateAddr(
						LSTRANS_MAX_BINDADDR,
						&addrListLen
					);
		if(!addrList) {
			status = STATUS_INSUFFICIENT_RESOURCES;
			break;
		}


		status = LstransAddrTypeToTransType(DestAddr->Address[0].AddressType, &transport);
		if(!NT_SUCCESS(status)) {
			KDPrintM(DBG_PROTO_ERROR, ("Address type not supported. STATUS=%08lx\n", status));
			break;
		}

		status = LstransQueryBindingDevices(transport, addrListLen, addrList, NULL);
		if(!NT_SUCCESS(status)) {
			KDPrintM(DBG_PROTO_ERROR, ("LstransQueryBindingDevices() failed. STATUS=%08lx\n", status));
			break;
		}


		//
		//	Validate binding address
		//

		if(BindAddr) {
			status = LstransIsInAddressList(addrList, BindAddr, TRUE);
			if(status == STATUS_OBJECT_NAME_NOT_FOUND) {
				BindAddr = NULL;
			} else if(!NT_SUCCESS(status)) {
				break;
			}
		}
		if(BindAddr2) {
			status = LstransIsInAddressList(addrList, BindAddr2, TRUE);
			if(status == STATUS_OBJECT_NAME_NOT_FOUND) {
				BindAddr2 = NULL;
			} else if(!NT_SUCCESS(status)) {
				break;
			}
		}

		//
		//	Try bind addresses in order of BindAddr, BindAddr2, and any addresses available.
		//
		addrListPrioritized = LstranAllocateAddr(
								LSTRANS_MAX_BINDADDR,
								NULL);
		if(!addrListPrioritized) {
			status = STATUS_INSUFFICIENT_RESOURCES;
			break;
		}

		idx_addr = 0;
		addrListPrioritized->TAAddressCount = 0;

		if(BindAddr) {
			RtlCopyMemory(&addrListPrioritized->Address[idx_addr], BindAddr->Address, sizeof(struct  _AddrLstrans));
			addrListPrioritized->TAAddressCount ++;
			idx_addr ++;
		}

		if(BindAddr2) {
			RtlCopyMemory(&addrListPrioritized->Address[idx_addr], BindAddr2->Address, sizeof(struct  _AddrLstrans));
			addrListPrioritized->TAAddressCount ++;
			idx_addr ++;
		}

		if(BindAnyAddress) {
			ULONG	idx_bindaddr;
			for(idx_bindaddr = 0; idx_bindaddr < (ULONG)addrList->TAAddressCount; idx_bindaddr ++) {


				//
				//	If an address has a valid length, copy into prioritized address list.
				//	Set zero legnth to the same address as BindAddr and BindAddr2 in LstransIsInAddressList().
				//

				if(addrList->Address[idx_bindaddr].AddressLength) {
					RtlCopyMemory(	&addrListPrioritized->Address[idx_addr],
									&addrList->Address[idx_bindaddr],
									sizeof(TA_LSTRANS_ADDRESS));
					addrListPrioritized->TAAddressCount ++;
					idx_addr ++;
				}
			}
		}


		//
		//	Try connecting with prioritized binding address.
		//

		status = LspConnectBindAddrList(LSS, BoundAddr, DestAddr, addrListPrioritized);

	} while(FALSE);

	if(addrListPrioritized)
		ExFreePool(addrListPrioritized);
	if(addrList)
		ExFreePool(addrList);

	return status;
}
Beispiel #27
0
NTSTATUS DEFAULTAPI
MsfsClose(PDEVICE_OBJECT DeviceObject,
          PIRP Irp)
{
    PIO_STACK_LOCATION IoStack;
    PFILE_OBJECT FileObject;
    PMSFS_DEVICE_EXTENSION DeviceExtension;
    PMSFS_FCB Fcb;
    PMSFS_CCB Ccb;
    PMSFS_MESSAGE Message;
    KIRQL oldIrql;

    DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);

    IoStack = IoGetCurrentIrpStackLocation(Irp);
    DeviceExtension = DeviceObject->DeviceExtension;
    FileObject = IoStack->FileObject;

    KeLockMutex(&DeviceExtension->FcbListLock);

    if (DeviceExtension->FcbListHead.Flink == &DeviceExtension->FcbListHead)
    {
        KeUnlockMutex(&DeviceExtension->FcbListLock);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return STATUS_SUCCESS;
    }

    Fcb = FileObject->FsContext;
    Ccb = FileObject->FsContext2;

    DPRINT("Mailslot name: %wZ\n", &Fcb->Name);

    Fcb->ReferenceCount--;
    if (Fcb->ServerCcb == Ccb)
    {
        /* delete all messages from message-list */
        KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);

        while (Fcb->MessageListHead.Flink != &Fcb->MessageListHead)
        {
            Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
                                        MSFS_MESSAGE,
                                        MessageListEntry);
            RemoveEntryList(Fcb->MessageListHead.Flink);
            ExFreePool(Message);
        }

        Fcb->MessageCount = 0;

        KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
        Fcb->ServerCcb = NULL;
    }

    KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
    RemoveEntryList(&Ccb->CcbListEntry);
    KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
    ExFreePool(Ccb);
    FileObject->FsContext2 = NULL;

    if (Fcb->ReferenceCount == 0)
    {
        DPRINT("ReferenceCount == 0: Deleting mailslot data\n");
        RemoveEntryList(&Fcb->FcbListEntry);
        ExFreePool(Fcb->Name.Buffer);
        ExFreePool(Fcb);
    }

    KeUnlockMutex(&DeviceExtension->FcbListLock);

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}
Beispiel #28
0
/**
 * Internal worker for the RTMpOn* APIs.
 *
 * @returns IPRT status code.
 * @param   pfnWorker       The callback.
 * @param   pvUser1         User argument 1.
 * @param   pvUser2         User argument 2.
 * @param   enmCpuid        What to do / is idCpu valid.
 * @param   idCpu           Used if enmCpuid RT_NT_CPUID_SPECIFIC, otherwise ignored.
 */
static int rtMpCall(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, RT_NT_CPUID enmCpuid, RTCPUID idCpu)
{
    PRTMPARGS pArgs;
    KDPC     *paExecCpuDpcs;

#if 0
    /* KeFlushQueuedDpcs must be run at IRQL PASSIVE_LEVEL according to MSDN, but the
     * driver verifier doesn't complain...
     */
    AssertMsg(KeGetCurrentIrql() == PASSIVE_LEVEL, ("%d != %d (PASSIVE_LEVEL)\n", KeGetCurrentIrql(), PASSIVE_LEVEL));
#endif

#ifdef IPRT_TARGET_NT4
    KAFFINITY Mask;
    /* g_pfnrtNt* are not present on NT anyway. */
    return VERR_NOT_SUPPORTED;
#else
    KAFFINITY Mask = KeQueryActiveProcessors();
#endif

    /* KeFlushQueuedDpcs is not present in Windows 2000; import it dynamically so we can just fail this call. */
    if (!g_pfnrtNtKeFlushQueuedDpcs)
        return VERR_NOT_SUPPORTED;

    pArgs = (PRTMPARGS)ExAllocatePoolWithTag(NonPagedPool, MAXIMUM_PROCESSORS*sizeof(KDPC) + sizeof(RTMPARGS), (ULONG)'RTMp');
    if (!pArgs)
        return VERR_NO_MEMORY;

    pArgs->pfnWorker = pfnWorker;
    pArgs->pvUser1   = pvUser1;
    pArgs->pvUser2   = pvUser2;
    pArgs->idCpu     = NIL_RTCPUID;
    pArgs->cHits     = 0;

    paExecCpuDpcs = (KDPC *)(pArgs + 1);

    if (enmCpuid == RT_NT_CPUID_SPECIFIC)
    {
        KeInitializeDpc(&paExecCpuDpcs[0], rtmpNtDPCWrapper, pArgs);
        KeSetImportanceDpc(&paExecCpuDpcs[0], HighImportance);
        KeSetTargetProcessorDpc(&paExecCpuDpcs[0], (int)idCpu);
    }
    else
    {
        for (unsigned i = 0; i < MAXIMUM_PROCESSORS; i++)
        {
            KeInitializeDpc(&paExecCpuDpcs[i], rtmpNtDPCWrapper, pArgs);
            KeSetImportanceDpc(&paExecCpuDpcs[i], HighImportance);
            KeSetTargetProcessorDpc(&paExecCpuDpcs[i], i);
        }
    }

    /* Raise the IRQL to DISPATCH_LEVEL so we can't be rescheduled to another cpu.
     * KeInsertQueueDpc must also be executed at IRQL >= DISPATCH_LEVEL.
     */
    KIRQL oldIrql;
    KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);

    /*
     * We cannot do other than assume a 1:1 relationship between the
     * affinity mask and the process despite the warnings in the docs.
     * If someone knows a better way to get this done, please let bird know.
     */
    if (enmCpuid == RT_NT_CPUID_SPECIFIC)
    {
        BOOLEAN ret = KeInsertQueueDpc(&paExecCpuDpcs[0], 0, 0);
        Assert(ret);
    }
    else
    {
        unsigned iSelf = KeGetCurrentProcessorNumber();

        for (unsigned i = 0; i < MAXIMUM_PROCESSORS; i++)
        {
            if (    (i != iSelf)
                &&  (Mask & RT_BIT_64(i)))
            {
                BOOLEAN ret = KeInsertQueueDpc(&paExecCpuDpcs[i], 0, 0);
                Assert(ret);
            }
        }
        if (enmCpuid != RT_NT_CPUID_OTHERS)
            pfnWorker(iSelf, pvUser1, pvUser2);
    }

    KeLowerIrql(oldIrql);

    /* Flush all DPCs and wait for completion. (can take long!) */
    /** @todo Consider changing this to an active wait using some atomic inc/dec
     *  stuff (and check for the current cpu above in the specific case). */
    g_pfnrtNtKeFlushQueuedDpcs();

    ExFreePool(pArgs);
    return VINF_SUCCESS;
}
Beispiel #29
0
NTSTATUS
NTAPI
SeInitializeProcessAuditName(IN PFILE_OBJECT FileObject,
                             IN BOOLEAN DoAudit,
                             OUT POBJECT_NAME_INFORMATION *AuditInfo)
{
    OBJECT_NAME_INFORMATION LocalNameInfo;
    POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
    ULONG ReturnLength = 8;
    NTSTATUS Status;

    PAGED_CODE();
    ASSERT(AuditInfo);

    /* Check if we should do auditing */
    if (DoAudit)
    {
        /* FIXME: TODO */
    }

    /* Now query the name */
    Status = ObQueryNameString(FileObject,
                               &LocalNameInfo,
                               sizeof(LocalNameInfo),
                               &ReturnLength);
    if (((Status == STATUS_BUFFER_OVERFLOW) ||
         (Status == STATUS_BUFFER_TOO_SMALL) ||
         (Status == STATUS_INFO_LENGTH_MISMATCH)) &&
        (ReturnLength != sizeof(LocalNameInfo)))
    {
        /* Allocate required size */
        ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool,
                                               ReturnLength,
                                               TAG_SEPA);
        if (ObjectNameInfo)
        {
            /* Query the name again */
            Status = ObQueryNameString(FileObject,
                                       ObjectNameInfo,
                                       ReturnLength,
                                       &ReturnLength);
        }
    }

    /* Check if we got here due to failure */
    if ((ObjectNameInfo) &&
        (!(NT_SUCCESS(Status)) || (ReturnLength == sizeof(LocalNameInfo))))
    {
        /* First, free any buffer we might've allocated */
        ASSERT(FALSE);
        if (ObjectNameInfo) ExFreePool(ObjectNameInfo);

        /* Now allocate a temporary one */
        ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
        ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool,
                                               sizeof(OBJECT_NAME_INFORMATION),
                                               TAG_SEPA);
        if (ObjectNameInfo)
        {
            /* Clear it */
            RtlZeroMemory(ObjectNameInfo, ReturnLength);
            Status = STATUS_SUCCESS;
        }
    }

    /* Check if memory allocation failed */
    if (!ObjectNameInfo) Status = STATUS_NO_MEMORY;

    /* Return the audit name */
    *AuditInfo = ObjectNameInfo;

    /* Return status */
    return Status;
}
Beispiel #30
0
VOID SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp )
{
    NTSTATUS                  ntStatus;
    POWER_STATE               powState;
    PDEVICE_EXTENSION         deviceExtension;
    PIO_STACK_LOCATION        irpStack;
    SYSTEM_POWER_STATE        systemState;
    DEVICE_POWER_STATE        devState;
    PPOWER_COMPLETION_CONTEXT powerContext;

    irpStack = IoGetCurrentIrpStackLocation(SIrp);
    systemState = irpStack->Parameters.Power.State.SystemState;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Entered\n"));

    // Read out the D-IRP out of the S->D mapping array captured in QueryCap's.
    // we can choose deeper sleep states than our mapping but never choose
    // lighter ones.
    devState = deviceExtension->DeviceCapabilities.DeviceState[systemState];
    powState.DeviceState = devState;

    powerContext = (PPOWER_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT));
    if (!powerContext)
	{
        FreeBT_DbgPrint(1, ("FBTUSB: SendDeviceIrp: Failed to alloc memory for powerContext\n"));
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;

    }

    else
	{
        powerContext->DeviceObject = DeviceObject;
        powerContext->SIrp = SIrp;

        // in win2k PoRequestPowerIrp can take fdo or pdo.
        ntStatus = PoRequestPowerIrp(
                            deviceExtension->PhysicalDeviceObject,
                            irpStack->MinorFunction,
                            powState,
                            (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine,
                            powerContext,
                            NULL);

    }

    if (!NT_SUCCESS(ntStatus))
	{
        if (powerContext)
		{
            ExFreePool(powerContext);

        }

        PoStartNextPowerIrp(SIrp);
        SIrp->IoStatus.Status = ntStatus;
        SIrp->IoStatus.Information = 0;
        IoCompleteRequest(SIrp, IO_NO_INCREMENT);

        FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp::"));
        FreeBT_IoDecrement(deviceExtension);

    }

    FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Leaving\n"));

}