Пример #1
0
NTSTATUS
DriverEntry (
    IN  PDRIVER_OBJECT  DriverObject,
    IN  PUNICODE_STRING UniRegistryPath
    )
/*++
Routine Description:

    Initialize the entry points of the driver.

--*/
{
    ULONG i;

    UNREFERENCED_PARAMETER (UniRegistryPath);

    Serenum_KdPrint_Def (SER_DBG_SS_TRACE, ("Driver Entry\n"));
    Serenum_KdPrint_Def (SER_DBG_SS_TRACE, ("RegPath: %p\n", UniRegistryPath));

    //
    // Set ever slot to initially pass the request through to the lower
    // device object
    //
    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
       DriverObject->MajorFunction[i] = Serenum_DispatchPassThrough;
    }

    //
    // Fill in the Dispatch slots intercepted by the filter driver.
    //
    DriverObject->MajorFunction [IRP_MJ_CREATE] =
    DriverObject->MajorFunction [IRP_MJ_CLOSE] = Serenum_CreateClose;
    DriverObject->MajorFunction [IRP_MJ_PNP] = Serenum_PnP;
    DriverObject->MajorFunction [IRP_MJ_POWER] = Serenum_Power;
    DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Serenum_IoCtl;
    DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL]
        = Serenum_InternIoCtl;
    DriverObject->DriverUnload = Serenum_DriverUnload;
    DriverObject->DriverExtension->AddDevice = Serenum_AddDevice;


#if DBG
   SerenumLogInit();
#endif

    return STATUS_SUCCESS;
}
Пример #2
0
NTSTATUS
Serenum_CreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
/*++
Routine Description:
    Some outside source is trying to create a file against us.

    If this is for the FDO (the bus itself) then the caller is trying to
    open the propriatary conection to tell us which serial port to enumerate.

    If this is for the PDO (an object on the bus) then this is a client that
    wishes to use the serial port.
--*/
{
    PIO_STACK_LOCATION irpStack;
    NTSTATUS status = STATUS_SUCCESS;
    KEVENT completionEvent;
    PDEVICE_OBJECT pNextDevice;
    PCOMMON_DEVICE_DATA commonData=(PCOMMON_DEVICE_DATA)DeviceObject->DeviceExtension;


    UNREFERENCED_PARAMETER(DeviceObject);
    status=IoAcquireRemoveLock(&commonData->RemoveLock,Irp);
    if(!NT_SUCCESS(status)){
        Irp->IoStatus.Information=0;
        Irp->IoStatus.Status=status;
        IoCompleteRequest(Irp,IO_NO_INCREMENT);
        return status;
    }


   irpStack = IoGetCurrentIrpStackLocation(Irp);

   if (commonData->IsFDO) {
      pNextDevice = ((PFDO_DEVICE_DATA)DeviceObject->DeviceExtension)
                    ->TopOfStack;
   } else {
      pNextDevice = ((PFDO_DEVICE_DATA)((PPDO_DEVICE_DATA)DeviceObject->
                                        DeviceExtension)->ParentFdo->
                     DeviceExtension)->TopOfStack;
   }

   switch (irpStack->MajorFunction) {
   case IRP_MJ_CREATE:
      Serenum_KdPrint_Def(SER_DBG_SS_TRACE, ("Create"));

      //
      // Pass on the create and the close
      //

      status = Serenum_DispatchPassThroughWithoutAcquire(DeviceObject, Irp);
      break;

   case IRP_MJ_CLOSE:
      Serenum_KdPrint_Def (SER_DBG_SS_TRACE, ("Close \n"));

      //
      // Send the close down; after it finishes we can open and take
      // over the port
      //

      IoCopyCurrentIrpStackLocationToNext(Irp);

      KeInitializeEvent(&completionEvent, SynchronizationEvent, FALSE);

      IoSetCompletionRoutine(Irp, SerenumSyncCompletion, &completionEvent,
                             TRUE, TRUE, TRUE);

      status = IoCallDriver(pNextDevice, Irp);


      if (status == STATUS_PENDING) {
         KeWaitForSingleObject(&completionEvent, Executive, KernelMode, FALSE,
                               NULL);
      }

      status = Irp->IoStatus.Status;

      IoCompleteRequest(Irp, IO_NO_INCREMENT);
      IoReleaseRemoveLock(&commonData->RemoveLock, Irp); 

      break;
   }

   return status;
}
Пример #3
0
NTSTATUS
Serenum_IoCtl (
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
/*++
Routine Description:

--*/
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    PCOMMON_DEVICE_DATA     commonData;
    PFDO_DEVICE_DATA        fdoData;
    HANDLE                  keyHandle;
    ULONG                   actualLength;


	
    status = STATUS_SUCCESS;
    irpStack = IoGetCurrentIrpStackLocation (Irp);
    ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction);

    commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;

    status = IoAcquireRemoveLock(&commonData->RemoveLock, Irp);
    if (!NT_SUCCESS(status)){
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }


    //buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    // We only take Device Control requests for the FDO.
    // That is the bus itself.
    //
    // The request is one of the propriatary Ioctls for
    //
    // NB We ARE a filter driver, so we DO pass on the irp if we don't handle it
    //

    //inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    //outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    if (!commonData->IsFDO) {
        //
        // These commands are only allowed to go to the FDO.  Since they came
        // into the PDO, we need to fire them down to the serenum Fdo.
        //
        return Serenum_Generic_FireAndRelease_RemoveLock(((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension)->ParentFdo,Irp);
    }

    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
    case IOCTL_SERENUM_GET_PORT_NAME:
        //
        // Get the port name from the registry.
        // This IOCTL is used by the modem cpl.
        //

        status = IoOpenDeviceRegistryKey(fdoData->UnderlyingPDO,
                                         PLUGPLAY_REGKEY_DEVICE,
                                         STANDARD_RIGHTS_READ,
                                         &keyHandle);

        if (!NT_SUCCESS(status)) {
           //
           // This is a fatal error.  If we can't get to our registry key,
           // we are sunk.
           //
           Serenum_KdPrint_Def (SER_DBG_PNP_ERROR,
                ("IoOpenDeviceRegistryKey failed - %x \n", status));
           Irp->IoStatus.Information = 0;
        } else {
            status = Serenum_GetRegistryKeyValue(
                keyHandle,
                L"PortName",
                sizeof(L"PortName"),
                Irp->AssociatedIrp.SystemBuffer,
                irpStack->Parameters.DeviceIoControl.OutputBufferLength,
                &actualLength);
            if ( STATUS_OBJECT_NAME_NOT_FOUND == status ||
                 STATUS_INVALID_PARAMETER  == status ) {
                status = Serenum_GetRegistryKeyValue(
                    keyHandle,
                    L"Identifier",
                    sizeof(L"Identifier"),
                    Irp->AssociatedIrp.SystemBuffer,
                    irpStack->Parameters.DeviceIoControl.OutputBufferLength,
                    &actualLength);
            }
            Irp->IoStatus.Information = actualLength;
            ZwClose (keyHandle);
        }
        break;
    default:
        //
        // This is not intended for us - fire and Protect!
        //
        return Serenum_DispatchPassThroughWithoutAcquire(
            DeviceObject,
            Irp);
    }

    IoReleaseRemoveLock(&commonData->RemoveLock, Irp);
    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    return status;
}
Пример #4
0
NTSTATUS
Serenum_AddDevice(IN PDRIVER_OBJECT DriverObject,
                  IN PDEVICE_OBJECT BusPhysicalDeviceObject)
/*++
Routine Description.
    A bus has been found.  Attach our FDO to it.
    Allocate any required resources.  Set things up.  And be prepared for the
    first ``start device.''

Arguments:
    BusPhysicalDeviceObject - Device object representing the bus.  That to which
        we attach a new FDO.

    DriverObject - This very self referenced driver.

--*/
{
    NTSTATUS status;
    PDEVICE_OBJECT deviceObject;
    PFDO_DEVICE_DATA pDeviceData;
    HANDLE keyHandle;
    ULONG actualLength;

    PAGED_CODE();

    Serenum_KdPrint_Def(SER_DBG_PNP_TRACE, ("Add Device: 0x%x\n",
                                            BusPhysicalDeviceObject));
    //
    // Create our FDO
    //

    status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_DATA), NULL,
                            FILE_DEVICE_BUS_EXTENDER, 0, TRUE, &deviceObject);

    if (NT_SUCCESS(status)) {
        pDeviceData = (PFDO_DEVICE_DATA)deviceObject->DeviceExtension;
        RtlFillMemory (pDeviceData, sizeof (FDO_DEVICE_DATA), 0);

        pDeviceData->IsFDO = TRUE;
        pDeviceData->DebugLevel = SER_DEFAULT_DEBUG_OUTPUT_LEVEL;
        pDeviceData->Self = deviceObject;
        pDeviceData->AttachedPDO = NULL;
        pDeviceData->NumPDOs = 0;
        pDeviceData->DeviceState = PowerDeviceD0;
        pDeviceData->SystemState = PowerSystemWorking;
        pDeviceData->PDOForcedRemove = FALSE;

        pDeviceData->SystemWake=PowerSystemUnspecified;
        pDeviceData->DeviceWake=PowerDeviceUnspecified;

        pDeviceData->Removed = FALSE;

        //
        // Set the PDO for use with PlugPlay functions
        //

        pDeviceData->UnderlyingPDO = BusPhysicalDeviceObject;


        //
        // Attach our filter driver to the device stack.
        // the return value of IoAttachDeviceToDeviceStack is the top of the
        // attachment chain.  This is where all the IRPs should be routed.
        //
        // Our filter will send IRPs to the top of the stack and use the PDO
        // for all PlugPlay functions.
        //

        pDeviceData->TopOfStack
            = IoAttachDeviceToDeviceStack(deviceObject, BusPhysicalDeviceObject);

        if (!pDeviceData->TopOfStack) {
            Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR,
                            ("AddDevice: IoAttach failed (%x)", status));
            IoDeleteDevice(deviceObject);
            return STATUS_UNSUCCESSFUL;
        }

        //
        // Set the type of IO we do
        //

        if (pDeviceData->TopOfStack->Flags & DO_BUFFERED_IO) {
            deviceObject->Flags |= DO_BUFFERED_IO;
        } else if (pDeviceData->TopOfStack->Flags & DO_DIRECT_IO) {
            deviceObject->Flags |= DO_DIRECT_IO;
        }

        //
        // Bias outstanding request to 1 so that we can look for a
        // transition to zero when processing the remove device PlugPlay IRP.
        //

        pDeviceData->OutstandingIO = 1;

        KeInitializeEvent(&pDeviceData->RemoveEvent, SynchronizationEvent,
                          FALSE);
        KeInitializeSemaphore(&pDeviceData->CreateSemaphore, 1, 1);
        KeInitializeSpinLock(&pDeviceData->EnumerationLock);



        //
        // Tell the PlugPlay system that this device will need an interface
        // device class shingle.
        //
        // It may be that the driver cannot hang the shingle until it starts
        // the device itself, so that it can query some of its properties.
        // (Aka the shingles guid (or ref string) is based on the properties
        // of the device.)
        //

        status = IoRegisterDeviceInterface(BusPhysicalDeviceObject,
                                           (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR,
                                           NULL,
                                           &pDeviceData->DevClassAssocName);

        if (!NT_SUCCESS(status)) {
            Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR,
                            ("AddDevice: IoRegisterDCA failed (%x)", status));
            IoDetachDevice(pDeviceData->TopOfStack);
            IoDeleteDevice(deviceObject);
            return status;
        }

        //
        // If for any reason you need to save values in a safe location that
        // clients of this DeviceClassAssociate might be interested in reading
        // here is the time to do so, with the function
        // IoOpenDeviceClassRegistryKey
        // the symbolic link name used is was returned in
        // pDeviceData->DevClassAssocName (the same name which is returned by
        // IoGetDeviceClassAssociations and the SetupAPI equivs.
        //

#if DBG
        {
            PWCHAR deviceName = NULL;
            ULONG nameLength = 0;

            status = IoGetDeviceProperty(BusPhysicalDeviceObject,
                                         DevicePropertyPhysicalDeviceObjectName, 0,
                                         NULL, &nameLength);

            if ((nameLength != 0) && (status == STATUS_BUFFER_TOO_SMALL)) {
                deviceName = ExAllocatePool(NonPagedPool, nameLength);

                if (NULL == deviceName) {
                    goto someDebugStuffExit;
                }

                IoGetDeviceProperty(BusPhysicalDeviceObject,
                                    DevicePropertyPhysicalDeviceObjectName,
                                    nameLength, deviceName, &nameLength);

                Serenum_KdPrint(pDeviceData, SER_DBG_PNP_TRACE,
                                ("AddDevice: %x to %x->%x (%ws) \n", deviceObject,
                                 pDeviceData->TopOfStack, BusPhysicalDeviceObject,
                                 deviceName));
            }

someDebugStuffExit:
            ;
            if (deviceName != NULL) {
                ExFreePool(deviceName);
            }
        }
#endif // DBG

        //
        // Turn on the shingle and point it to the given device object.
        //
        status = IoSetDeviceInterfaceState(&pDeviceData->DevClassAssocName,
                                           TRUE);

        if (!NT_SUCCESS(status)) {
            Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR,
                            ("AddDevice: IoSetDeviceClass failed (%x)", status));
            return status;
        }

        //
        // Open the registry and read in our settings
        //

        status = IoOpenDeviceRegistryKey(pDeviceData->UnderlyingPDO,
                                         PLUGPLAY_REGKEY_DEVICE,
                                         STANDARD_RIGHTS_READ, &keyHandle);

        if (status == STATUS_SUCCESS) {
            status
                = Serenum_GetRegistryKeyValue(keyHandle, L"SkipEnumerations",
                                              sizeof(L"SkipEnumerations"),
                                              &pDeviceData->SkipEnumerations,
                                              sizeof(pDeviceData->SkipEnumerations),
                                              &actualLength);

            if ((status != STATUS_SUCCESS)
                    || (actualLength != sizeof(pDeviceData->SkipEnumerations))) {
                pDeviceData->SkipEnumerations = 0;
                status = STATUS_SUCCESS;

            }

            ZwClose(keyHandle);
        }
    }

    if (NT_SUCCESS(status)) {
        deviceObject->Flags |= DO_POWER_PAGABLE;
        deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    }

    return status;
}