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

📄 pnp.c

📁 串口Windows驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
    IRP_MJ_PNP major code (plug-and-play IRPs).

Arguments:

    PDevObj - Pointer to the device object for this device

    PIrp - Pointer to the IRP for the current request

Return Value:

    The function value is the final status of the call


--*/

{
   PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
   PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
   PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
   NTSTATUS status;
   PDEVICE_CAPABILITIES pDevCaps;

   PAGED_CODE();

   if ((status = SerialIRPPrologue(PIrp, pDevExt)) != STATUS_SUCCESS) {
      SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
      return status;
   }

   switch (pIrpStack->MinorFunction) {
   case IRP_MN_QUERY_CAPABILITIES: {
      PKEVENT pQueryCapsEvent;
      SYSTEM_POWER_STATE cap;

      SerialDbgPrintEx(SERPNPPOWER,
                       "Got IRP_MN_QUERY_DEVICE_CAPABILITIES IRP\n");

      pQueryCapsEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));

      if (pQueryCapsEvent == NULL) {
         PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
         SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
         return STATUS_INSUFFICIENT_RESOURCES;
      }

      KeInitializeEvent(pQueryCapsEvent, SynchronizationEvent, FALSE);

      IoCopyCurrentIrpStackLocationToNext(PIrp);
      IoSetCompletionRoutine(PIrp, SerialSyncCompletion, pQueryCapsEvent,
                             TRUE, TRUE, TRUE);

      status = IoCallDriver(pLowerDevObj, PIrp);


      //
      // Wait for lower drivers to be done with the Irp
      //

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

      ExFreePool(pQueryCapsEvent);

      status = PIrp->IoStatus.Status;

      if (pIrpStack->Parameters.DeviceCapabilities.Capabilities == NULL) {
         goto errQueryCaps;
      }

      //
      // Save off their power capabilities
      //

      SerialDbgPrintEx(SERPNPPOWER, "Mapping power capabilities\n");

      pIrpStack = IoGetCurrentIrpStackLocation(PIrp);

      pDevCaps = pIrpStack->Parameters.DeviceCapabilities.Capabilities;

      for (cap = PowerSystemSleeping1; cap < PowerSystemMaximum;
           cap++) {
#if DBG
         SerialDbgPrintEx(SERPNPPOWER, "  %d: %s <--> %s\n",
                          cap, SerSystemCapString[cap],
                          SerDeviceCapString[pDevCaps->DeviceState[cap]]);
#endif // DBG
         pDevExt->DeviceStateMap[cap] = pDevCaps->DeviceState[cap];
      }

      pDevExt->DeviceStateMap[PowerSystemUnspecified]
         = PowerDeviceUnspecified;

      pDevExt->DeviceStateMap[PowerSystemWorking]
        = PowerDeviceD0;

      pDevExt->SystemWake = pDevCaps->SystemWake;
      pDevExt->DeviceWake = pDevCaps->DeviceWake;

      errQueryCaps:;

      SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
      return status;
   }

   case IRP_MN_QUERY_DEVICE_RELATIONS:
      //
      // We just pass this down -- serenum enumerates our bus for us.
      //

      SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_DEVICE_RELATIONS Irp\n");

      switch (pIrpStack->Parameters.QueryDeviceRelations.Type) {
      case BusRelations:
         SerialDbgPrintEx(SERPNPPOWER, "------- BusRelations Query\n");
         break;

      case EjectionRelations:
         SerialDbgPrintEx(SERPNPPOWER, "------- EjectionRelations Query\n");
         break;

      case PowerRelations:
         SerialDbgPrintEx(SERPNPPOWER, "------- PowerRelations Query\n");
         break;

      case RemovalRelations:
         SerialDbgPrintEx(SERPNPPOWER, "------- RemovalRelations Query\n");
         break;

      case TargetDeviceRelation:
         SerialDbgPrintEx(SERPNPPOWER, "------- TargetDeviceRelation Query\n");
         break;

      default:
         SerialDbgPrintEx(SERPNPPOWER, "------- Unknown Query\n");
         break;
      }

      IoSkipCurrentIrpStackLocation(PIrp);
      status = SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
      return status;


   case IRP_MN_QUERY_INTERFACE:
      SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_INTERFACE Irp\n");
      break;


   case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
      SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp"
                       "\n");
      break;


   case IRP_MN_START_DEVICE: {
      PVOID startLockPtr;

      SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_START_DEVICE Irp\n");

      //
      // SerialStartDevice will pass this Irp to the next driver,
      // and process it as completion so just complete it here.
      //

      SerialLockPagableSectionByHandle(SerialGlobals.PAGESER_Handle);

      //
      // We used to make sure the stack was powered up, but now it
      // is supposed to be done implicitly by start_device.
      // If that wasn't the case we would just make this call:
      //
      //   status = SerialGotoPowerState(PDevObj, pDevExt, PowerDeviceD0);
      //

      pDevExt->PowerState = PowerDeviceD0;

      status = SerialStartDevice(PDevObj, PIrp);

      if(!pDevExt->RetainPowerOnClose) {
         (void)SerialGotoPowerState(PDevObj, pDevExt, PowerDeviceD3);
      }

      SerialUnlockPagableImageSection(SerialGlobals.PAGESER_Handle);


      PIrp->IoStatus.Status = status;

      SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
      return status;
   }


   case IRP_MN_READ_CONFIG:
      SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_READ_CONFIG Irp\n");
      break;


   case IRP_MN_WRITE_CONFIG:
      SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_WRITE_CONFIG Irp\n");
      break;


   case IRP_MN_EJECT:
      SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_EJECT Irp\n");
      break;


   case IRP_MN_SET_LOCK:
      SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_SET_LOCK Irp\n");
      break;


   case IRP_MN_QUERY_ID: {
         UNICODE_STRING pIdBuf;
         PWCHAR pPnpIdStr;
         ULONG pnpIdStrLen;
         ULONG isMulti = 0;
         HANDLE pnpKey;

         SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_ID Irp\n");

         if (((pIrpStack->Parameters.QueryId.IdType != BusQueryHardwareIDs)
             && (pIrpStack->Parameters.QueryId.IdType != BusQueryCompatibleIDs))
             || ((pDevExt->Flags & SERIAL_FLAGS_LEGACY_ENUMED) == 0)) {
            IoSkipCurrentIrpStackLocation(PIrp);
            return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
         }

         if (pIrpStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs) {
            PIrp->IoStatus.Status = STATUS_SUCCESS;
            IoSkipCurrentIrpStackLocation(PIrp);
            return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
         }

         status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
                                          STANDARD_RIGHTS_WRITE, &pnpKey);

         if (!NT_SUCCESS(status)) {
            PIrp->IoStatus.Status = status;

            SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
            return status;

         }

         isMulti = 0;

         status = SerialGetRegistryKeyValue(pnpKey, L"MultiportDevice",
                                            sizeof(L"MultiportDevice"),
                                            &isMulti, sizeof(ULONG));

         ZwClose(pnpKey);

         pPnpIdStr = isMulti ? SERIAL_PNP_MULTI_ID_STR : SERIAL_PNP_ID_STR;
         pnpIdStrLen = isMulti ? sizeof(SERIAL_PNP_MULTI_ID_STR)
            : sizeof(SERIAL_PNP_ID_STR);

         if (PIrp->IoStatus.Information != 0) {
            ULONG curStrLen;
            ULONG allocLen = 0;
            PWSTR curStr = (PWSTR)PIrp->IoStatus.Information;

            //
            // We have to walk the strings to count the amount of space to
            // reallocate
            //

            while ((curStrLen = wcslen(curStr)) != 0) {
               allocLen += curStrLen * sizeof(WCHAR) + sizeof(UNICODE_NULL);
               curStr += curStrLen + 1;
            }

            allocLen += sizeof(UNICODE_NULL);

            pIdBuf.Buffer = ExAllocatePool(PagedPool, allocLen
                                           + pnpIdStrLen
                                           + sizeof(WCHAR));

            if (pIdBuf.Buffer == NULL) {
               //
               // Clean up after other drivers since we are
               // sending the irp back up.
               //

               ExFreePool((PWSTR)PIrp->IoStatus.Information);


               PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
               PIrp->IoStatus.Information = 0;
               SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
               return STATUS_INSUFFICIENT_RESOURCES;
            }

            pIdBuf.MaximumLength = (USHORT)(allocLen + pnpIdStrLen);
            pIdBuf.Length = (USHORT)allocLen - sizeof(UNICODE_NULL);

            RtlZeroMemory(pIdBuf.Buffer, pIdBuf.MaximumLength + sizeof(WCHAR));
            RtlCopyMemory(pIdBuf.Buffer, (PWSTR)PIrp->IoStatus.Information,
                          allocLen);
            RtlAppendUnicodeToString(&pIdBuf, pPnpIdStr);

            //
            // Free what the previous driver allocated
            //

            ExFreePool((PWSTR)PIrp->IoStatus.Information);


         } else {

            SerialDbgPrintEx(SERPNPPOWER, "ID is sole ID\n");

            pIdBuf.Buffer = ExAllocatePool(PagedPool, pnpIdStrLen
                                           + sizeof(WCHAR) * 2);

            if (pIdBuf.Buffer == NULL) {
               PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
               PIrp->IoStatus.Information = 0;
               SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
               return STATUS_INSUFFICIENT_RESOURCES;
            }

            pIdBuf.MaximumLength  = (USHORT)pnpIdStrLen;
            pIdBuf.Length = 0;

            RtlZeroMemory(pIdBuf.Buffer, pIdBuf.MaximumLength + sizeof(WCHAR)
                          * 2);

            RtlAppendUnicodeToString(&pIdBuf, pPnpIdStr);
         }

         PIrp->IoStatus.Information = (ULONG_PTR)pIdBuf.Buffer;
         PIrp->IoStatus.Status = STATUS_SUCCESS;

         IoCopyCurrentIrpStackLocationToNext(PIrp);
         return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
      }

      case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: {
         HANDLE pnpKey;
         PKEVENT pResFiltEvent;
         ULONG isMulti = 0;
         PIO_RESOURCE_REQUIREMENTS_LIST pReqList;
         PIO_RESOURCE_LIST pResList;
         PIO_RESOURCE_DESCRIPTOR pResDesc;
         ULONG i, j;
         ULONG reqCnt;
         ULONG gotISR;
         ULONG gotInt;
         ULONG listNum;

         SerialDbgPrintEx(SERPNPPOWER, "Got "
                          "IRP_MN_FILTER_RESOURCE_REQUIREMENTS Irp\n");
         SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);


         pResFiltEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));

         if (pResFiltEvent == NULL) {
            PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
            return STATUS_INSUFFICIENT_RESOURCES;
         }

         KeInitializeEvent(pResFiltEvent, SynchronizationEvent, FALSE);

         IoCopyCurrentIrpStackLocationToNext(PIrp);
         IoSetCompletionRoutine(PIrp, SerialSyncCompletion, pResFiltEvent,
                                TRUE, TRUE, TRUE);

         status = IoCallDriver(pLowerDevObj, PIrp);


         //
         // Wait for lower drivers to be done with the Irp
         //

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

         ExFreePool(pResFiltEvent);

         if (PIrp->IoStatus.Information == 0) {
            if (pIrpStack->Parameters.FilterResourceRequirements
                .IoResourceRequirementList == 0) {
               SerialDbgPrintEx(SERPNPPOWER, "Can't filter NULL resources!\n");
               status = PIrp->IoStatus.Status;
               SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
               return status;
            }

            PIrp->IoStatus.Information = (ULONG_PTR)pIrpStack->Parameters
                                        .FilterResourceRequirements
                                        .IoResourceRequirementList;

         }

         status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
                                          STANDARD_RIGHTS_WRITE, &pnpKey);

         if (!NT_SUCCESS(status)) {
            PIrp->IoStatus.Status = status;

            SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
            return status;

         }

         //
         // No matter what we add our filter if we can and return success.
         //

         status = SerialGetRegistryKeyValue (pnpKey, L"MultiportDevice",
                                             sizeof(L"MultiportDevice"),
                                             &isMulti,
                                             sizeof (ULONG));

         ZwClose(pnpKey);


         //
         // Force ISR ports in IO_RES_REQ_LIST to shared status
         // Force interrupts to shared status
         //

         //
         // We will only process the first list -- multiport boards
         // should not have alternative resources
         //

         pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)PIrp->IoStatus.Information;
         pResList = &pReqList->List[0];

         SerialDbgPrintEx(SERPNPPOWER, "List has %x lists (including "
                          "alternatives)\n", pReqList->AlternativeLists);

         for (listNum = 0; listNum < (pReqList->AlternativeLists);
              listNum++) {
            gotISR = 0;
            gotInt = 0;

            SerialDbgPrintEx(SERPNPPOWER, "List has %x resources in it\n",
                                  pResList->Count);

            for (j = 0; (j < pResList->Count); j++) {
               pResDesc = &pResList->Descriptors[j];

               switch (pResDesc->Type) {
               case CmResourceTypePort:
                  if (isMulti
                      && (pResDesc->u.Port.Length == SERIAL_STATUS_LENGTH)
                      && !gotISR) {
                     gotISR = 1;

⌨️ 快捷键说明

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