⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tlp3nt.c

📁 SmardCard Windows驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
        // a) The serial driver can't be used without opening it
        // b) The call will go through serenum first which informs
        //    it to stop looking/polling for new devices.
        //
        irp->UserIosb = &ioStatusBlock;
        IoSetNextIrpStackLocation(irp);
        irpStack = IoGetCurrentIrpStackLocation(irp);

        irpStack->MajorFunction = IRP_MJ_CREATE;
        irpStack->Parameters.Create.Options = 0;
        irpStack->Parameters.Create.ShareAccess = 0;
        irpStack->Parameters.Create.FileAttributes = 0;
        irpStack->Parameters.Create.EaLength = 0;

        status = TLP3CallSerialDriver(
            ATTACHED_DEVICE_OBJECT,
            irp
            );
       if (status != STATUS_SUCCESS) {

            leave;
        }

        KeClearEvent(&READER_EXTENSION_L(SerialCloseDone));

        status = TLP3ConfigureSerialPort(&deviceExtension->SmartcardExtension);
       if (status != STATUS_SUCCESS) {

            leave;
        }

       status = TLP3StartSerialEventTracking(
            &deviceExtension->SmartcardExtension
            );

       if (status != STATUS_SUCCESS) {

            leave;
        }

        status = IoSetDeviceInterfaceState(
            &deviceExtension->PnPDeviceName,
            TRUE
            );

        if (status != STATUS_SUCCESS) {

            leave;
        }

        KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
    }
    _finally {

        if (status == STATUS_SHARED_IRQ_BUSY) {

           SmartcardLogError(
              DeviceObject,
              TLP3_IRQ_BUSY,
              NULL,
              status
              );
        }

        if (status != STATUS_SUCCESS) {

            TLP3StopDevice(DeviceObject);
        }

        IoFreeIrp(irp);
    }

   SmartcardDebug(
      DEBUG_TRACE,
      ( "%s!TLP3StartDevice: Exit %lx\n",
        DRIVER_NAME,
        status)
      );

    return status;
}

VOID
TLP3StopDevice(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:
    Finishes card tracking requests and closes the connection to the
    serial driver.

--*/
{
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
   PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;

   SmartcardDebug(
      DEBUG_TRACE,
      ( "%s!TLP3StopDevice: Enter\n",
        DRIVER_NAME)
      );

    if (KeReadStateEvent(&READER_EXTENSION_L(SerialCloseDone)) == 0l) {

        NTSTATUS status;
        PUCHAR requestBuffer;
        PSMARTCARD_EXTENSION smartcardExtension =
            &deviceExtension->SmartcardExtension;

        // test if we ever started event tracking
        if (smartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask == 0) {

            // no, we did not
            // We 'only' need to close the serial port
            TLP3CloseSerialPort(DeviceObject, NULL);

        } else {

            //
            // We now inform the serial driver that we're not longer
            // interested in serial events. This will also free the irp
            // we use for those io-completions
            //
           smartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask = 0;

            // save the pointer
            requestBuffer = smartcardExtension->SmartcardRequest.Buffer;

           *(PULONG) smartcardExtension->SmartcardRequest.Buffer =
              smartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask;

           smartcardExtension->SmartcardRequest.BufferLength = sizeof(ULONG);

           smartcardExtension->ReaderExtension->SerialIoControlCode =
              IOCTL_SERIAL_SET_WAIT_MASK;

           // We don't expect to get bytes back
           smartcardExtension->SmartcardReply.BufferLength = 0;

           TLP3SerialIo(smartcardExtension);

            // restore the pointer
            smartcardExtension->SmartcardRequest.Buffer = requestBuffer;

            // now wait until the connetion to serial is closed
            status = KeWaitForSingleObject(
                &READER_EXTENSION_L(SerialCloseDone),
                Executive,
                KernelMode,
                FALSE,
                NULL
                );
            ASSERT(status == STATUS_SUCCESS);
        }
    }

   SmartcardDebug(
      DEBUG_TRACE,
      ( "%s!TLP3StopDevice: Exit\n",
        DRIVER_NAME)
      );
}

NTSTATUS
TLP3SystemControl(
   PDEVICE_OBJECT DeviceObject,
   PIRP        Irp
   )
/*++

--*/
{
   PDEVICE_EXTENSION DeviceExtension; 
   NTSTATUS status = STATUS_SUCCESS;

   DeviceExtension      = DeviceObject->DeviceExtension;

   IoSkipCurrentIrpStackLocation(Irp);
   status = IoCallDriver(DeviceExtension->SmartcardExtension.ReaderExtension->AttachedDeviceObject, Irp);
      
   return status;

}

NTSTATUS
TLP3DeviceControl(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )
/*++

Routine Description:
    This is our IOCTL dispatch function

--*/
{
   PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
   PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
    NTSTATUS status = STATUS_SUCCESS;
    KIRQL irql;
#ifdef SIMULATION
   RTL_QUERY_REGISTRY_TABLE parameters[2];
#endif

   SmartcardDebug(
      DEBUG_TRACE,
      ( "%s!TLP3DeviceControl: Enter\n",
        DRIVER_NAME)
      );

   if (smartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask == 0) {

      //
      // the wait mask is set to 0 whenever the device was either
      // surprise-removed or politely removed
      //
      status = STATUS_DEVICE_REMOVED;
   }

   if (status == STATUS_SUCCESS) {

      KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
      if (deviceExtension->IoCount == 0) {

         KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
         status = KeWaitForSingleObject(
            &deviceExtension->ReaderStarted,
            Executive,
            KernelMode,
            FALSE,
            NULL
            );
         ASSERT(status == STATUS_SUCCESS);

         KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
      }
      ASSERT(deviceExtension->IoCount >= 0);
      deviceExtension->IoCount++;
      KeReleaseSpinLock(&deviceExtension->SpinLock, irql);

      status = SmartcardAcquireRemoveLockWithTag(smartcardExtension, 'tcoI');
   }

    if (status != STATUS_SUCCESS) {

        // the device has been removed. Fail the call
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_DEVICE_REMOVED;
    }

#ifdef SIMULATION
   if (DriverKey) {

      ULONG oldLevel =
         smartcardExtension->ReaderExtension->SimulationLevel;

      RtlZeroMemory(parameters, sizeof(parameters));

      parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
      parameters[0].Name = L"SimulationLevel";
      parameters[0].EntryContext =
         &smartcardExtension->ReaderExtension->SimulationLevel;
      parameters[0].DefaultType = REG_DWORD;
      parameters[0].DefaultData =
         &smartcardExtension->ReaderExtension->SimulationLevel;
      parameters[0].DefaultLength = sizeof(ULONG);

      if (RtlQueryRegistryValues(
          RTL_REGISTRY_ABSOLUTE,
          DriverKey,
          parameters,
          NULL,
          NULL
          ) == STATUS_SUCCESS) {

         SmartcardDebug(
            smartcardExtension->ReaderExtension->SimulationLevel == oldLevel ? 0 : DEBUG_SIMULATION,
            ( "%s!TLP3AddDevice: SimulationLevel set to %lx\n",
            DRIVER_NAME,
            smartcardExtension->ReaderExtension->SimulationLevel)
            );
      }
   }
#endif

    ASSERT(smartcardExtension->ReaderExtension->ReaderPowerState ==
        PowerReaderWorking);

   status = SmartcardDeviceControl(
      smartcardExtension,
      Irp
      );

    SmartcardReleaseRemoveLockWithTag(smartcardExtension, 'tcoI');

    KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
    deviceExtension->IoCount--;
    ASSERT(deviceExtension->IoCount >= 0);
    KeReleaseSpinLock(&deviceExtension->SpinLock, irql);

   SmartcardDebug(
      DEBUG_TRACE,
      ( "%s!TLP3DeviceControl: Exit %lx\n",
        DRIVER_NAME,
        status)
      );

    return status;
}

VOID
TLP3CloseSerialPort(
    IN PDEVICE_OBJECT DeviceObject,
    IN PVOID Context
    )
/*++

Routine Description:
    This function closes the connection to the serial driver when the reader
    has been removed (unplugged). This function runs as a system thread at
    IRQL == PASSIVE_LEVEL. It waits for the remove event that is set by
    the IoCompletionRoutine

--*/
{
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
   PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
    NTSTATUS status;
    PIRP irp;
    PIO_STACK_LOCATION irpStack;
    IO_STATUS_BLOCK ioStatusBlock;

    UNREFERENCED_PARAMETER(Context);

   SmartcardDebug(
      DEBUG_TRACE,
      ( "%s!TLP3CloseSerialPort: Enter\n",
        DRIVER_NAME)
      );

    //
    // first mark this device as 'gone'.
    // This will prevent that someone can re-open the device
    // We intentionally ignore possible errors
    //
    IoSetDeviceInterfaceState(
        &deviceExtension->PnPDeviceName,
        FALSE
        );

    irp = IoAllocateIrp(
        (CCHAR) (DeviceObject->StackSize + 1),
        FALSE
        );

    ASSERT(irp != NULL);

    if (irp) {

       SmartcardDebug(
          DEBUG_DRIVER,
          ( "%s!TLP3CloseSerialPort: Sending IRP_MJ_CLOSE\n",
            DRIVER_NAME)
          );

        IoSetNextIrpStackLocation(irp);

        //
        // We send down a close to the serial driver. This close goes
        // through serenum first which will trigger it to start looking
        // for changes on the com-port. Since our device is gone it will
        // call the device removal event of our PnP dispatch.
        //
        irp->UserIosb = &ioStatusBlock;
        irpStack = IoGetCurrentIrpStackLocation( irp );
        irpStack->MajorFunction = IRP_MJ_CLOSE;

        status = TLP3CallSerialDriver(
            ATTACHED_DEVICE_OBJECT,
            irp
            );

        ASSERT(status == STATUS_SUCCESS);

        IoFreeIrp(irp);
    }

    // now 'signal' that we closed the serial driver
    KeSetEvent(
      &READER_EXTENSION_L(SerialCloseDone),
      0,
      FALSE
      );

   SmartcardDebug(
      DEBUG_INFO,
      ( "%s!TLP3CloseSerialPort: Exit\n",
        DRIVER_NAME)
      );
}

NTSTATUS
TLP3IoCompletion (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PKEVENT Event
    )
{
    UNREFERENCED_PARAMETER (DeviceObject);

    if (Irp->Cancel) {

        Irp->IoStatus.Status = STATUS_CANCELLED;

    } else {

        Irp->IoStatus.Status = STATUS_MORE_PROCESSING_REQUIRED;
    }

    KeSetEvent (Event, 0, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
TLP3CallSerialDriver(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:
   Send an Irp to the serial driver.

--*/
{

   NTSTATUS status = STATUS_SUCCESS;
    KEVENT Event;

    // Copy our stack location to the next.
    IoCopyCurrentIrpStackLocationToNext(Irp);

   //
   // initialize an event for process synchronization. The event is passed
   // to our completion routine and will be set when the serial driver is done
   //
    KeInitializeEvent(
        &Event,
        NotificationEvent,
        FALSE
        );

    // Our IoCompletionRoutine sets only our event
    IoSetCompletionRoutine (
        Irp,
        TLP3IoCompletion,
        &Event,
        TRUE,
        TRUE,
        TRUE
        );

    if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_POWER) {

        status = PoCallDriver(DeviceObject, Irp);

    } else {

        // Call the serial driver
        status = IoCallDriver(DeviceObject, Irp);
    }

   // Wait until the serial driver has processed the Irp
    if (status == STATUS_PENDING) {

        status = KeWaitForSingleObject(
            &Event,
            Executive,
            KernelMode,
            FALSE,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -