test: pnpirp.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# pnpirp.c File Reference

`#include "iop.h"`

Go to the source code of this file.

## Classes

struct | _DEVICE_COMPLETION_CONTEXT
struct | _LOCK_MOUNTABLE_DEVICE_CONTEXT

## Defines

#define | PnpIrpStatusTracking(Status, IrpCode, Device)
#define | HASH_UNICODE_STRING(_pustr, _phash)
#define | MAX_PARENT_PREFIX (8 + 8 + 8 + 2)

## Typedefs

typedef _DEVICE_COMPLETION_CONTEXT | DEVICE_COMPLETION_CONTEXT
typedef _DEVICE_COMPLETION_CONTEXT * | PDEVICE_COMPLETION_CONTEXT
typedef _LOCK_MOUNTABLE_DEVICE_CONTEXT | LOCK_MOUNTABLE_DEVICE_CONTEXT
typedef _LOCK_MOUNTABLE_DEVICE_CONTEXT * | PLOCK_MOUNTABLE_DEVICE_CONTEXT

## Functions

NTSTATUS | IopAsynchronousCall (IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION TopStackLocation, IN PDEVICE_COMPLETION_CONTEXT CompletionContext, IN PVOID CompletionRoutine)
NTSTATUS | IopDeviceEjectComplete (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS | IopDeviceStartComplete (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS | IopDeviceRelationsComplete (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
PDEVICE_OBJECT | IopFindMountableDevice (IN PDEVICE_OBJECT DeviceObject)
PDEVICE_OBJECT | IopLockMountedDeviceForRemove (IN PDEVICE_OBJECT DeviceObject, IN ULONG IrpMinorCode, OUT PLOCK_MOUNTABLE_DEVICE_CONTEXT Context)
VOID | IopUnlockMountedDeviceForRemove (IN PDEVICE_OBJECT DeviceObject, IN ULONG IrpMinorCode, IN PLOCK_MOUNTABLE_DEVICE_CONTEXT Context)
NTSTATUS | IopFilterResourceRequirementsCall (IN PDEVICE_OBJECT DeviceObject, IN PIO_RESOURCE_REQUIREMENTS_LIST ResReqList, OUT PVOID *Information)
VOID | IopUncacheInterfaceInformation (IN PDEVICE_OBJECT DeviceObject)
NTSTATUS | IopSynchronousCall (IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION TopStackLocation, OUT PVOID *Information)
VOID | IopStartDevice (IN PDEVICE_OBJECT DeviceObject)
NTSTATUS | IopEjectDevice (IN PDEVICE_OBJECT DeviceObject, IN OUT PPENDING_RELATIONS_LIST_ENTRY PendingEntry)
NTSTATUS | IopRemoveDevice (IN PDEVICE_OBJECT TargetDevice, IN ULONG IrpMinorCode)
NTSTATUS | IopQueryDeviceRelations (IN DEVICE_RELATION_TYPE Relations, IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN AsyncOk, OUT PDEVICE_RELATIONS *DeviceRelations)
NTSTATUS | IopQueryDeviceId (IN PDEVICE_OBJECT DeviceObject, OUT PWCHAR *DeviceId)
NTSTATUS | IopQueryUniqueId (IN PDEVICE_OBJECT DeviceObject, OUT PWCHAR *UniqueId)
NTSTATUS | IopMakeGloballyUniqueId (IN PDEVICE_OBJECT DeviceObject, IN PWCHAR UniqueId, OUT PWCHAR *GloballyUniqueId)
NTSTATUS | IopQueryCompatibleIds (IN PDEVICE_OBJECT DeviceObject, IN BUS_QUERY_ID_TYPE IdType, OUT PWCHAR *CompatibleIds, OUT ULONG *Length)
NTSTATUS | IopQueryDeviceResources (IN PDEVICE_OBJECT DeviceObject, IN ULONG ResourceType, OUT PVOID *Resource, OUT ULONG *Length)
NTSTATUS | IopQueryResourceHandlerInterface (IN RESOURCE_HANDLER_TYPE HandlerType, IN PDEVICE_OBJECT DeviceObject, IN UCHAR ResourceType, IN OUT PVOID *Interface)
NTSTATUS | IopQueryReconfiguration (IN UCHAR Request, IN PDEVICE_OBJECT DeviceObject)
NTSTATUS | IopQueryLegacyBusInformation (IN PDEVICE_OBJECT DeviceObject, OUT LPGUID InterfaceGuid, OPTIONAL OUT INTERFACE_TYPE *InterfaceType, OPTIONAL OUT ULONG *BusNumber OPTIONAL)
NTSTATUS | IopQueryPnpBusInformation (IN PDEVICE_OBJECT DeviceObject, OUT LPGUID InterfaceGuid, OPTIONAL OUT INTERFACE_TYPE *InterfaceType, OPTIONAL OUT ULONG *BusNumber OPTIONAL)
NTSTATUS | IopQueryDeviceState (IN PDEVICE_OBJECT DeviceObject)
VOID | IopIncDisableableDepends (IN OUT PDEVICE_NODE DeviceNode)
VOID | IopDecDisableableDepends (IN OUT PDEVICE_NODE DeviceNode)
NTSTATUS | IopQueryDeviceSerialNumber (IN PDEVICE_OBJECT DeviceObject, OUT PWCHAR *SerialNumber)
NTSTATUS | IopQueryDockRemovalInterface (IN PDEVICE_OBJECT DeviceObject, IN OUT PDOCK_INTERFACE *DockInterface)

## Variables

ULONG | PnpIrpMask
PCHAR | IrpName []

## Define Documentation

#define HASH_UNICODE_STRING | ( | _pustr,
|  | _phash |  | ) |

Value:

    {                             \
        PWCHAR _p = (_pustr)->Buffer;                                           \
        PWCHAR _ep = _p + ((_pustr)->Length/sizeof(WCHAR));                     \
        ULONG _chHolder =0;                                                     \
                                                                                \
        while( _p < _ep ) {                                                     \
            _chHolder = 37 * _chHolder + (unsigned int) (*_p++);                \
        }                                                                       \
                                                                                \
        *(_phash) = abs(314159269 * _chHolder) % 1000000007;                    \
    }

Definition at line 72 of file pnpirp.c.

Referenced by IopMakeGloballyUniqueId().

#define MAX_PARENT_PREFIX (8 + 8 + 8 + 2)

| Definition at line 85 of file pnpirp.c. Referenced by IopMakeGloballyUniqueId().

#define PnpIrpStatusTracking | ( | Status,
|  | IrpCode,
|  | Device |  | ) |

Value:

    if (PnpIrpMask & (1 << IrpCode)) {                                   \
            if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) {           \
                DbgPrint(" ++ %s Driver ( %wZ ) return status %08lx\n",      \
                         IrpName[IrpCode],                                   \
                         &Device->DriverObject->DriverName,                  \
                         Status);                                            \
            }                                                                \
        }

Definition at line 26 of file pnpirp.c.

Referenced by IopDeviceRelationsComplete(), IopDeviceStartComplete(), IopFilterResourceRequirementsCall(), and IopSynchronousCall().

## Typedef Documentation

typedef struct _DEVICE_COMPLETION_CONTEXT DEVICE_COMPLETION_CONTEXT

typedef struct _LOCK_MOUNTABLE_DEVICE_CONTEXT LOCK_MOUNTABLE_DEVICE_CONTEXT

typedef struct _DEVICE_COMPLETION_CONTEXT * PDEVICE_COMPLETION_CONTEXT

| Referenced by IopDeviceRelationsComplete(), IopDeviceStartComplete(), IopQueryDeviceRelations(), and IopStartDevice().

typedef struct _LOCK_MOUNTABLE_DEVICE_CONTEXT * PLOCK_MOUNTABLE_DEVICE_CONTEXT

## Function Documentation

NTSTATUS IopAsynchronousCall | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIO_STACK_LOCATION | TopStackLocation,
|  | IN PDEVICE_COMPLETION_CONTEXT | CompletionContext,
|  | IN PVOID | CompletionRoutine
| ) |

Definition at line 262 of file pnpirp.c.

References ASSERT, _VPB::DeviceObject, FALSE, IoAllocateIrp(), IoCallDriver, IoGetAttachedDevice(), IoGetNextIrpStackLocation, IoSetCompletionRoutine, _IRP::IoStatus, IRP_SYSTEM_RESTRICTED, KernelMode, NTSTATUS(), NULL, PAGED_CODE, PsGetCurrentThread, _IRP::RequestorMode, SPECIALIRP_WATERMARK_IRP, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, _IRP::UserIosb, _DEVICE_OBJECT::Vpb, and VPB_MOUNTED.

Referenced by IopQueryDeviceRelations(), and IopStartDevice().

    00271                    :
    00272
    00273     This function sends an  Asynchronous irp to the top level device
    00274     object which roots on DeviceObject.
    00275
    00276 Parameters:
    00277
    00278     DeviceObject - Supplies the device object of the device being removed.
    00279
    00280     TopStackLocation - Supplies a pointer to the parameter block for the irp.
    00281
    00282     CompletionContext -
    00283
    00284     CompletionRoutine -
    00285
    00286 Return Value:
    00287
    00288     NTSTATUS code.
    00289
    00290 --*/
    00291
    00292 {
    00293     PDEVICE_OBJECT deviceObject;
    00294     PIRP irp;
    00295     PIO_STACK_LOCATION irpSp;
    00296     NTSTATUS status;
    00297
    00298     PAGED_CODE();
    00299
    00300     //
    00301     // If the target device object has a VPB associated with it and a file
    00302     // system is mounted, make the filesystem's volume device object the
    00303     // irp target.
    00304     //
    00305     // BUGBUG - I don't think we need to do this.  The filesystem
    00306     // driver should attach to the PDO chain or registered for device
    00307     // change registration.
    00308     //
    00309
    00310     if ((TargetDevice->Vpb != NULL) && (TargetDevice->Vpb->Flags & VPB_MOUNTED)) {
    00311         deviceObject = TargetDevice->Vpb->DeviceObject;
    00312     } else {
    00313         deviceObject = TargetDevice;
    00314     }
    00315
    00316     ASSERT(deviceObject != NULL);
    00317
    00318     //
    00319     // Get a pointer to the topmost device object in the stack of devices,
    00320     // beginning with the deviceObject.
    00321     //
    00322
    00323     deviceObject = IoGetAttachedDevice(deviceObject);
    00324
    00325     //
    00326     // Allocate an I/O Request Packet (IRP) for this device removal operation.
    00327     //
    00328
    00329     irp = IoAllocateIrp( (CCHAR) (deviceObject->StackSize), FALSE );
    00330     if (!irp) {
    00331         return STATUS_INSUFFICIENT_RESOURCES;
    00332     }
    00333
    00334     SPECIALIRP_WATERMARK_IRP(irp, IRP_SYSTEM_RESTRICTED);
    00335
    00336     //
    00337     // Initialize it to failure.
    00338     //
    00339
    00340     irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
    00341     irp->IoStatus.Information = 0;
    00342
    00343     //
    00344     // Get a pointer to the next stack location in the packet.  This location
    00345     // will be used to pass the function codes and parameters to the first
    00346     // driver.
    00347     //
    00348
    00349     irpSp = IoGetNextIrpStackLocation (irp);
    00350
    00351     //
    00352     // Fill in the IRP according to this request.
    00353     //
    00354
    00355     irp->Tail.Overlay.Thread = PsGetCurrentThread();
    00356     irp->RequestorMode = KernelMode;
    00357     irp->UserIosb = NULL;
    00358     irp->UserEvent = NULL;
    00359
    00360     //
    00361     // Copy in the caller-supplied stack location contents
    00362     //
    00363
    00364     *irpSp = *TopStackLocation;
    00365 #if DBG
    00366     CompletionContext->Id = irp;
    00367 #endif
    00368     IoSetCompletionRoutine(irp,
    00369                            CompletionRoutine,
    00370                            CompletionContext,  /* Completion context */
    00371                            TRUE,               /* Invoke on success  */
    00372                            TRUE,               /* Invoke on error    */
    00373                            TRUE                /* Invoke on cancel   */
    00374                            );
    00375
    00376     status = IoCallDriver( deviceObject, irp );
    00377     return status;
    00378 }

VOID IopDecDisableableDepends | ( | IN OUT PDEVICE_NODE | DeviceNode | ) |

Definition at line 3152 of file pnpirp.c.

References NULL.

Referenced by IopQueryDeviceState(), and IopRemoveDevice().

    03157                    :
    03158
    03159     Decrements the DisableableDepends field of this devicenode
    03160     and potentially every parent device node up the tree
    03161     A parent devicenode is only decremented if the child in question
    03162     is decremented from 1 to 0
    03163
    03164 Parameters:
    03165
    03166     DeviceNode - Supplies the device node where the depends is to be decremented
    03167
    03168 Return Value:
    03169
    03170     none.
    03171
    03172 --*/
    03173 {
    03174
    03175     while (DeviceNode != NULL) {
    03176
    03177         LONG newval;
    03178
    03179         newval = InterlockedDecrement(& DeviceNode->DisableableDepends);
    03180         if (newval != 0) {
    03181             //
    03182             // we are still non-disableable, so we don't have to bother parent
    03183             //
    03184             break;
    03185         }
    03186
    03187         DeviceNode = DeviceNode ->Parent;
    03188
    03189     }
    03190
    03191 }

NTSTATUS IopDeviceEjectComplete | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp,
|  | IN PVOID | Context
| ) |

Definition at line 896 of file pnpirp.c.

References ASSERT, DelayedWorkQueue, _PENDING_RELATIONS_LIST_ENTRY::EjectIrp, ExInitializeWorkItem, ExQueueWorkItem(), IoFreeIrp(), IopProcessCompletedEject(), Irp, NULL, and _PENDING_RELATIONS_LIST_ENTRY::WorkItem.

Referenced by IopEjectDevice().

    00901 {
    00902     PPENDING_RELATIONS_LIST_ENTRY entry = (PPENDING_RELATIONS_LIST_ENTRY)Context;
    00903     PIRP ejectIrp;
    00904
    00905     ejectIrp = InterlockedExchangePointer(&entry->EjectIrp, NULL);
    00906
    00907     ASSERT(ejectIrp == NULL || ejectIrp == Irp);
    00908
    00909     //
    00910     // Queue a work item to finish up the eject.  We queue a work item because
    00911     // we are probably running at dispatch level in some random context.
    00912     //
    00913
    00914     ExInitializeWorkItem( &entry->WorkItem,
    00915                           IopProcessCompletedEject,
    00916                           entry);
    00917
    00918     ExQueueWorkItem( &entry->WorkItem, DelayedWorkQueue );
    00919
    00920     IoFreeIrp( Irp );
    00921
    00922     return STATUS_MORE_PROCESSING_REQUIRED;
    00923
    00924 }

NTSTATUS IopDeviceRelationsComplete | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp,
|  | IN PVOID | Context
| ) |

Definition at line 1496 of file pnpirp.c.

References ASSERT, DNF_BEING_ENUMERATED, DNF_ENUMERATION_REQUEST_PENDING, DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING, ERESOURCE_THREAD, ExFreePool(), FALSE, _DEVICE_NODE::Flags, IoFreeIrp(), IopPnPSpinLock, IopReleaseEnumerationLockForThread, IopRequestDeviceAction(), _IRP::IoStatus, Irp, IRP_MN_QUERY_DEVICE_RELATIONS, NT_SUCCESS, NULL, _DEVICE_NODE::OverUsed1, PDEVICE_COMPLETION_CONTEXT, _DEVICE_NODE::PhysicalDeviceObject, PnpIrpStatusTracking, ReenumerateDeviceTree, RestartEnumeration, and TRUE.

Referenced by IopQueryDeviceRelations().

    01504                    :
    01505
    01506     Completion function for a QueryDeviceRelations IRP. T
    01507
    01508 Arguments:
    01509
    01510     DeviceObject - NULL.
    01511     Irp          - SetPower irp which has completed
    01512     Context      - a pointer to the DEVICE_CHANGE_COMPLETION_CONTEXT.
    01513
    01514 Return Value:
    01515
    01516     STATUS_MORE_PROCESSING_REQUIRED is returned to IoCompleteRequest
    01517     to signify that IoCompleteRequest should not continue processing
    01518     the IRP.
    01519
    01520 --*/
    01521 {
    01522     PDEVICE_NODE deviceNode = ((PDEVICE_COMPLETION_CONTEXT)Context)->DeviceNode;
    01523     ERESOURCE_THREAD LockingThread = ((PDEVICE_COMPLETION_CONTEXT)Context)->Thread;
    01524     KIRQL oldIrql;
    01525     BOOLEAN requestEnumeration = FALSE;
    01526
    01527 #if DBG
    01528     if (((PDEVICE_COMPLETION_CONTEXT)Context)->Id != (PVOID)Irp) {
    01529         ASSERT(0);
    01530         IoFreeIrp (Irp);
    01531         ExFreePool(Context);
    01532         return STATUS_MORE_PROCESSING_REQUIRED;
    01533     }
    01534 #endif
    01535
    01536     PnpIrpStatusTracking(Irp->IoStatus.Status, IRP_MN_QUERY_DEVICE_RELATIONS, deviceNode->PhysicalDeviceObject);
    01537     ExAcquireSpinLock(&IopPnPSpinLock, &oldIrql);
    01538     deviceNode->Flags  &= ~DNF_BEING_ENUMERATED;
    01539
    01540     //
    01541     // Read state from Irp.
    01542     //
    01543
    01544     if (NT_SUCCESS(Irp->IoStatus.Status) && (Irp->IoStatus.Information)) {
    01545
    01546         //
    01547         // It is VERY important that we set PendingDeviceRealtions field before
    01548         // checking DNF_ENUMERATION_REQUEST_PENDING.
    01549         //
    01550
    01551         ASSERT(deviceNode->OverUsed1.PendingDeviceRelations == NULL);
    01552         deviceNode->OverUsed1.PendingDeviceRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
    01553     }
    01554
    01555     if (deviceNode->Flags & DNF_ENUMERATION_REQUEST_PENDING) {
    01556         ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01557
    01558         if (deviceNode->OverUsed1.PendingDeviceRelations) {
    01559
    01560             //
    01561             // If the query_device_relations irp returns something, we will
    01562             // make a request to process the childrens.
    01563             //
    01564
    01565             IopRequestDeviceAction( deviceNode->PhysicalDeviceObject,
    01566                                     RestartEnumeration,
    01567                                     NULL,
    01568                                     NULL );
    01569         } else {
    01570             deviceNode->Flags &= ~DNF_ENUMERATION_REQUEST_PENDING;
    01571         }
    01572     } else {
    01573         deviceNode->Flags |= DNF_ENUMERATION_REQUEST_PENDING;
    01574         ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01575     }
    01576
    01577     IopReleaseEnumerationLockForThread(NULL, LockingThread);
    01578
    01579     //
    01580     // Irp processing is complete, free the irp and then return
    01581     // more_processing_required which causes IoCompleteRequest to
    01582     // stop "completing" this irp any future.
    01583     //
    01584
    01585     IoFreeIrp (Irp);
    01586     ExFreePool(Context);
    01587
    01588     ExAcquireSpinLock(&IopPnPSpinLock, &oldIrql);
    01589     if (deviceNode->Flags & DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING) {
    01590         deviceNode->Flags &= ~DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING;
    01591         requestEnumeration = TRUE;
    01592     }
    01593     ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01594     if (requestEnumeration) {
    01595         IopRequestDeviceAction( DeviceObject,
    01596                                 ReenumerateDeviceTree,
    01597                                 NULL,
    01598                                 NULL );
    01599     }
    01600     return STATUS_MORE_PROCESSING_REQUIRED;
    01601 }

NTSTATUS IopDeviceStartComplete | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp,
|  | IN PVOID | Context
| ) |

Definition at line 1370 of file pnpirp.c.

References ASSERT, DNF_NEED_ENUMERATION_ONLY, DNF_START_REQUEST_PENDING, DNF_STARTED, DNF_STOPPED, DOCK_ARRIVING, DOCK_NOTDOCKDEVICE, _DEVICE_NODE::DockInfo, ERESOURCE_THREAD, ExFreePool(), _DEVICE_NODE::Flags, IoFreeIrp(), IopPnPSpinLock, IopReleaseEnumerationLockForThread, IopRequestDeviceAction(), IopRequestDeviceRemoval(), IopSetDevNodeProblem, IoRequestDeviceEject(), _IRP::IoStatus, Irp, IRP_MN_START_DEVICE, NT_SUCCESS, NULL, PDEVICE_COMPLETION_CONTEXT, _DEVICE_NODE::PhysicalDeviceObject, PnpIrpStatusTracking, ReenumerateDeviceTree, and SAVE_FAILURE_INFO.

Referenced by IopStartDevice().

    01378                    :
    01379
    01380     Completion function for an Async Start IRP.
    01381
    01382 Arguments:
    01383
    01384     DeviceObject - NULL.
    01385     Irp          - SetPower irp which has completed
    01386     Context      - a pointer to the DEVICE_CHANGE_COMPLETION_CONTEXT.
    01387
    01388 Return Value:
    01389
    01390     STATUS_MORE_PROCESSING_REQUIRED is returned to IoCompleteRequest
    01391     to signify that IoCompleteRequest should not continue processing
    01392     the IRP.
    01393
    01394 --*/
    01395 {
    01396     PDEVICE_NODE deviceNode = ((PDEVICE_COMPLETION_CONTEXT)Context)->DeviceNode;
    01397     ERESOURCE_THREAD LockingThread = ((PDEVICE_COMPLETION_CONTEXT)Context)->Thread;
    01398     ULONG oldFlags;
    01399     KIRQL oldIrql;
    01400
    01401     //
    01402     // Read state from Irp.
    01403     //
    01404
    01405 #if DBG
    01406     if (((PDEVICE_COMPLETION_CONTEXT)Context)->Id != (PVOID)Irp) {
    01407         ASSERT(0);
    01408         IoFreeIrp (Irp);
    01409         ExFreePool(Context);
    01410
    01411         return STATUS_MORE_PROCESSING_REQUIRED;
    01412     }
    01413 #endif
    01414
    01415     PnpIrpStatusTracking(Irp->IoStatus.Status, IRP_MN_START_DEVICE, deviceNode->PhysicalDeviceObject);
    01416     ExAcquireSpinLock(&IopPnPSpinLock, &oldIrql);
    01417
    01418     oldFlags = deviceNode->Flags;
    01419     deviceNode->Flags &= ~DNF_START_REQUEST_PENDING;
    01420     if (NT_SUCCESS(Irp->IoStatus.Status)) {
    01421
    01422         if (deviceNode->Flags & DNF_STOPPED) {
    01423
    01424             //
    01425             // If the start is initiated by rebalancing, do NOT do enumeration
    01426             //
    01427
    01428             deviceNode->Flags &= ~DNF_STOPPED;
    01429             deviceNode->Flags |= DNF_STARTED;
    01430
    01431             ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01432         } else {
    01433
    01434             //
    01435             // Otherwise, we need to queue a request to enumerate the device if DNF_START_REQUEST_PENDING
    01436             // is set.  (IopStartDevice sets the flag if status of start irp returns pending.)
    01437             //
    01438             //
    01439
    01440             deviceNode->Flags |= DNF_NEED_ENUMERATION_ONLY + DNF_STARTED;
    01441
    01442             ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01443
    01444             if (oldFlags & DNF_START_REQUEST_PENDING) {
    01445                 IopRequestDeviceAction( deviceNode->PhysicalDeviceObject,
    01446                                         ReenumerateDeviceTree,
    01447                                         NULL,
    01448                                         NULL );
    01449             }
    01450         }
    01451
    01452     } else {
    01453
    01454         //
    01455         // The start failed.  We will remove the device
    01456         //
    01457
    01458         deviceNode->Flags &= ~(DNF_STOPPED | DNF_STARTED);
    01459
    01460         ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01461         SAVE_FAILURE_INFO(deviceNode, Irp->IoStatus.Status);
    01462
    01463         IopSetDevNodeProblem(deviceNode, CM_PROB_FAILED_START);
    01464
    01465         if (deviceNode->DockInfo.DockStatus == DOCK_NOTDOCKDEVICE) {
    01466
    01467             IopRequestDeviceRemoval(deviceNode->PhysicalDeviceObject, CM_PROB_FAILED_START);
    01468         } else {
    01469
    01470             ASSERT(deviceNode->DockInfo.DockStatus == DOCK_ARRIVING);
    01471
    01472             //
    01473             // ADRIAO BUGBUG 05/12/1999 -
    01474             //     We never go down this path, but if we fix it a function
    01475             // similar to IopRequestDeviceEjectWorker needs to be queued, one
    01476             // that passes in "FALSE" for the kernel initiated parameter.
    01477             //
    01478             ASSERT(0);
    01479             IoRequestDeviceEject(deviceNode->PhysicalDeviceObject);
    01480         }
    01481     }
    01482     IopReleaseEnumerationLockForThread(NULL, LockingThread);
    01483
    01484     //
    01485     // Irp processing is complete, free the irp and then return
    01486     // more_processing_required which causes IoCompleteRequest to
    01487     // stop "completing" this irp any future.
    01488     //
    01489
    01490     IoFreeIrp (Irp);
    01491     ExFreePool(Context);
    01492     return STATUS_MORE_PROCESSING_REQUIRED;
    01493 }

NTSTATUS IopEjectDevice | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN OUT PPENDING_RELATIONS_LIST_ENTRY | PendingEntry
| ) |

Definition at line 730 of file pnpirp.c.

References DelayedWorkQueue, ExInitializeWorkItem, ExQueueWorkItem(), FALSE, IoAllocateIrp(), IoCallDriver, IoGetAttachedDevice(), IoGetNextIrpStackLocation, IopDeviceEjectComplete(), IopProcessCompletedEject(), IopQueuePendingEject(), IoSetCompletionRoutine, _IRP::IoStatus, IRP_MJ_PNP, IRP_MN_EJECT, IRP_SYSTEM_RESTRICTED, KernelMode, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), NULL, PAGED_CODE, PpNotifyUserModeRemovalSafe(), PsGetCurrentThread, _IRP::RequestorMode, SPECIALIRP_WATERMARK_IRP, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, and _IRP::UserIosb.

    00737                    :
    00738
    00739     This function sends an eject device irp to the top level device
    00740     object which roots on DeviceObject.
    00741
    00742 Parameters:
    00743
    00744     DeviceObject - Supplies a pointer to the device object of the device being
    00745                    removed.
    00746
    00747 Return Value:
    00748
    00749     NTSTATUS code.
    00750
    00751 --*/
    00752
    00753 {
    00754     PIO_STACK_LOCATION irpSp;
    00755     NTSTATUS status;
    00756     PDEVICE_NODE deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    00757     PDEVICE_OBJECT deviceObject;
    00758     PIRP irp;
    00759
    00760     PAGED_CODE();
    00761
    00762     if (PendingEntry->LightestSleepState != PowerSystemWorking) {
    00763
    00764         //
    00765         // We have to warm eject.
    00766         //
    00767         if (PendingEntry->DockInterface) {
    00768
    00769             PendingEntry->DockInterface->ProfileDepartureSetMode(
    00770                 PendingEntry->DockInterface->Context,
    00771                 PDS_UPDATE_ON_EJECT
    00772                 );
    00773         }
    00774
    00775         PendingEntry->EjectIrp = NULL;
    00776
    00777         InitializeListHead( &PendingEntry->Link );
    00778
    00779         IopQueuePendingEject(PendingEntry);
    00780
    00781         ExInitializeWorkItem( &PendingEntry->WorkItem,
    00782                               IopProcessCompletedEject,
    00783                               PendingEntry);
    00784
    00785         ExQueueWorkItem( &PendingEntry->WorkItem, DelayedWorkQueue );
    00786         return STATUS_SUCCESS;
    00787     }
    00788
    00789     if (PendingEntry->DockInterface) {
    00790
    00791         //
    00792         // Notify dock that now is a good time to update it's hardware profile.
    00793         //
    00794         PendingEntry->DockInterface->ProfileDepartureSetMode(
    00795             PendingEntry->DockInterface->Context,
    00796             PDS_UPDATE_ON_INTERFACE
    00797             );
    00798
    00799         PendingEntry->DockInterface->ProfileDepartureUpdate(
    00800             PendingEntry->DockInterface->Context
    00801             );
    00802
    00803         if (PendingEntry->DisplaySafeRemovalDialog) {
    00804
    00805             PpNotifyUserModeRemovalSafe(DeviceObject);
    00806             PendingEntry->DisplaySafeRemovalDialog = FALSE;
    00807         }
    00808     }
    00809
    00810     //
    00811     // Get a pointer to the topmost device object in the stack of devices,
    00812     // beginning with the deviceObject.
    00813     //
    00814
    00815     deviceObject = IoGetAttachedDevice(DeviceObject);
    00816
    00817     //
    00818     // Allocate an I/O Request Packet (IRP) for this device removal operation.
    00819     //
    00820
    00821     irp = IoAllocateIrp( (CCHAR) (deviceObject->StackSize), FALSE );
    00822     if (!irp) {
    00823
    00824         PendingEntry->EjectIrp = NULL;
    00825
    00826         InitializeListHead( &PendingEntry->Link );
    00827
    00828         IopQueuePendingEject(PendingEntry);
    00829
    00830         ExInitializeWorkItem( &PendingEntry->WorkItem,
    00831                               IopProcessCompletedEject,
    00832                               PendingEntry);
    00833
    00834         ExQueueWorkItem( &PendingEntry->WorkItem, DelayedWorkQueue );
    00835
    00836         return STATUS_INSUFFICIENT_RESOURCES;
    00837     }
    00838
    00839     SPECIALIRP_WATERMARK_IRP(irp, IRP_SYSTEM_RESTRICTED);
    00840
    00841     //
    00842     // Initialize it to failure.
    00843     //
    00844
    00845     irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
    00846     irp->IoStatus.Information = 0;
    00847
    00848     //
    00849     // Get a pointer to the next stack location in the packet.  This location
    00850     // will be used to pass the function codes and parameters to the first
    00851     // driver.
    00852     //
    00853
    00854     irpSp = IoGetNextIrpStackLocation(irp);
    00855
    00856     //
    00857     // Initialize the stack location to pass to IopSynchronousCall()
    00858     //
    00859
    00860     RtlZeroMemory(irpSp, sizeof(IO_STACK_LOCATION));
    00861
    00862     //
    00863     // Set the function codes.
    00864     //
    00865
    00866     irpSp->MajorFunction = IRP_MJ_PNP;
    00867     irpSp->MinorFunction = IRP_MN_EJECT;
    00868
    00869     //
    00870     // Fill in the IRP according to this request.
    00871     //
    00872
    00873     irp->Tail.Overlay.Thread = PsGetCurrentThread();
    00874     irp->RequestorMode = KernelMode;
    00875     irp->UserIosb = NULL;
    00876     irp->UserEvent = NULL;
    00877
    00878     PendingEntry->EjectIrp = irp;
    00879
    00880     IopQueuePendingEject(PendingEntry);
    00881
    00882     IoSetCompletionRoutine(irp,
    00883                            IopDeviceEjectComplete,
    00884                            PendingEntry,       /* Completion context */
    00885                            TRUE,               /* Invoke on success  */
    00886                            TRUE,               /* Invoke on error    */
    00887                            TRUE                /* Invoke on cancel   */
    00888                            );
    00889
    00890     status = IoCallDriver( deviceObject, irp );
    00891
    00892     return status;
    00893 }

NTSTATUS IopFilterResourceRequirementsCall | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIO_RESOURCE_REQUIREMENTS_LIST | ResReqList,
|  | OUT PVOID * | Information
| ) |

Definition at line 3255 of file pnpirp.c.

References Executive, FALSE, IoAllocateIrp(), IoCallDriver, IoGetAttachedDevice(), IoGetNextIrpStackLocation, IopQueueThreadIrp, _IRP::IoStatus, IRP_MJ_PNP, IRP_MN_FILTER_RESOURCE_REQUIREMENTS, IRP_SYSTEM_RESTRICTED, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PnpIrpStatusTracking, PsGetCurrentThread, SPECIALIRP_WATERMARK_IRP, _DEVICE_OBJECT::StackSize, _IRP::Tail, _IRP::UserEvent, _IRP::UserIosb, and VOID().

Referenced by IopQueryDeviceResources().

    03263                    :
    03264
    03265     This function sends a synchronous filter resource requirements irp to the
    03266     top level device object which roots on DeviceObject.
    03267
    03268 Parameters:
    03269
    03270     DeviceObject - Supplies the device object of the device being removed.
    03271
    03272     ResReqList   - Supplies a pointer to the resource requirements requiring
    03273                    filtering.
    03274
    03275     Information  - Supplies a pointer to a variable that receives the returned
    03276                    information of the irp.
    03277
    03278 Return Value:
    03279
    03280     NTSTATUS code.
    03281
    03282 --*/
    03283
    03284 {
    03285     PIRP irp;
    03286     PIO_STACK_LOCATION irpSp;
    03287     IO_STATUS_BLOCK statusBlock;
    03288     KEVENT event;
    03289     NTSTATUS status;
    03290     PULONG_PTR returnInfo = (PULONG_PTR)Information;
    03291     PDEVICE_OBJECT deviceObject;
    03292
    03293     PAGED_CODE();
    03294
    03295     //
    03296     // Get a pointer to the topmost device object in the stack of devices,
    03297     // beginning with the deviceObject.
    03298     //
    03299
    03300     deviceObject = IoGetAttachedDevice(DeviceObject);
    03301
    03302     //
    03303     // Begin by allocating the IRP for this request.  Do not charge quota to
    03304     // the current process for this IRP.
    03305     //
    03306
    03307     irp = IoAllocateIrp(deviceObject->StackSize, FALSE);
    03308     if (irp == NULL){
    03309
    03310         return STATUS_INSUFFICIENT_RESOURCES;
    03311     }
    03312
    03313     SPECIALIRP_WATERMARK_IRP(irp, IRP_SYSTEM_RESTRICTED);
    03314
    03315     //
    03316     // Initialize it to success. This is a special hack for WDM (ie 9x)
    03317     // compatibility. The driver verifier is in on this one.
    03318     //
    03319
    03320     if (ResReqList) {
    03321
    03322         irp->IoStatus.Status = statusBlock.Status = STATUS_SUCCESS;
    03323         irp->IoStatus.Information = statusBlock.Information = (ULONG_PTR) ResReqList;
    03324
    03325     } else {
    03326
    03327         irp->IoStatus.Status = statusBlock.Status = STATUS_NOT_SUPPORTED;
    03328     }
    03329
    03330     //
    03331     // Set the pointer to the status block and initialized event.
    03332     //
    03333
    03334     KeInitializeEvent( &event,
    03335                        SynchronizationEvent,
    03336                        FALSE );
    03337
    03338     irp->UserIosb = &statusBlock;
    03339     irp->UserEvent = &event;
    03340
    03341     //
    03342     // Set the address of the current thread
    03343     //
    03344
    03345     irp->Tail.Overlay.Thread = PsGetCurrentThread();
    03346
    03347     //
    03348     // Queue this irp onto the current thread
    03349     //
    03350
    03351     IopQueueThreadIrp(irp);
    03352
    03353     //
    03354     // Get a pointer to the stack location of the first driver which will be
    03355     // invoked.  This is where the function codes and parameters are set.
    03356     //
    03357
    03358     irpSp = IoGetNextIrpStackLocation(irp);
    03359
    03360     //
    03361     // Setup the stack location contents
    03362     //
    03363
    03364     irpSp->MinorFunction = IRP_MN_FILTER_RESOURCE_REQUIREMENTS;
    03365     irpSp->MajorFunction = IRP_MJ_PNP;
    03366     irpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList = ResReqList;
    03367
    03368     //
    03369     // Call the driver
    03370     //
    03371
    03372     status = IoCallDriver(deviceObject, irp);
    03373
    03374     PnpIrpStatusTracking(status, IRP_MN_FILTER_RESOURCE_REQUIREMENTS, deviceObject);
    03375
    03376     //
    03377     // If a driver returns STATUS_PENDING, we will wait for it to complete
    03378     //
    03379
    03380     if (status == STATUS_PENDING) {
    03381         (VOID) KeWaitForSingleObject( &event,
    03382                                       Executive,
    03383                                       KernelMode,
    03384                                       FALSE,
    03385                                       (PLARGE_INTEGER) NULL );
    03386         status = statusBlock.Status;
    03387     }
    03388
    03389     *returnInfo = (ULONG_PTR) statusBlock.Information;
    03390
    03391     return status;
    03392 }

PDEVICE_OBJECT IopFindMountableDevice | ( | IN PDEVICE_OBJECT | DeviceObject | ) |

Definition at line 1316 of file pnpirp.c.

References _DEVICE_OBJECT::AttachedDevice, DO_DEVICE_HAS_NAME, _DEVICE_OBJECT::Flags, NULL, and _DEVICE_OBJECT::Vpb.

Referenced by IopRemoveDevice().

    01321                    :
    01322
    01323     This routine will scan up the device stack and find a device which could
    01324     finds with the VPB_REMOVE_PENDING bit (or clear it in the case of cancel)
    01325     and increment (or decrement in the case of cancel) the reference count
    01326     in the VPB.  This is to ensure that no new file system can get mounted on
    01327     the device stack while the remove operation is in place.
    01328
    01329     The search will terminate once all the attached device objects have been
    01330     marked, or once a mounted device object has been marked.
    01331
    01332 Arguments:
    01333
    01334     DeviceObject - the PDO we are attempting to remove
    01335
    01336     IrpMinorCode - the remove-type operation we are going to perform
    01337
    01338     Context - a context block which must be passed in to the unlock operation
    01339
    01340 Return Value:
    01341
    01342     A pointer to the device object stack which the remove request should be
    01343     sent to.  If a mounted file system was found, this will be the lowest
    01344     file system device object in the mounted stack.  Otherwise this will be
    01345     the PDO which was passed in.
    01346
    01347 --*/
    01348
    01349 {
    01350     PVPB vpb;
    01351
    01352     PDEVICE_OBJECT mountableDevice = DeviceObject;
    01353
    01354     while (mountableDevice != NULL) {
    01355
    01356         if ((mountableDevice->Flags & DO_DEVICE_HAS_NAME) &&
    01357            (mountableDevice->Vpb != NULL)) {
    01358
    01359             return mountableDevice;
    01360         }
    01361
    01362         mountableDevice = mountableDevice->AttachedDevice;
    01363     }
    01364
    01365     return NULL;
    01366 }

VOID IopIncDisableableDepends | ( | IN OUT PDEVICE_NODE | DeviceNode | ) |

Definition at line 3109 of file pnpirp.c.

References NULL.

Referenced by IopQueryDeviceState().

    03114                    :
    03115
    03116     Increments the DisableableDepends field of this devicenode
    03117     and potentially every parent device node up the tree
    03118     A parent devicenode is only incremented if the child in question
    03119     is incremented from 0 to 1
    03120
    03121 Parameters:
    03122
    03123     DeviceNode - Supplies the device node where the depends is to be incremented
    03124
    03125 Return Value:
    03126
    03127     none.
    03128
    03129 --*/
    03130 {
    03131
    03132     while (DeviceNode != NULL) {
    03133
    03134         LONG newval;
    03135
    03136         newval = InterlockedIncrement(& DeviceNode->DisableableDepends);
    03137         if (newval != 1) {
    03138             //
    03139             // we were already non-disableable, so we don't have to bother parent
    03140             //
    03141             break;
    03142         }
    03143
    03144         DeviceNode = DeviceNode ->Parent;
    03145
    03146     }
    03147
    03148 }

PDEVICE_OBJECT IopLockMountedDeviceForRemove | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN ULONG | IrpMinorCode,
|  | OUT PLOCK_MOUNTABLE_DEVICE_CONTEXT | Context
| ) |

Definition at line 1080 of file pnpirp.c.

References ASSERT, _DEVICE_OBJECT::AttachedDevice, _DEVICE_OBJECT::DeviceLock, _VPB::DeviceObject, Executive, FALSE, _VPB::Flags, IO_NO_INCREMENT, IoAcquireVpbSpinLock(), IopDatabaseLock, IoReleaseVpbSpinLock(), IRP_MN_CANCEL_REMOVE_DEVICE, IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_REMOVE_DEVICE, IRP_MN_SURPRISE_REMOVAL, KernelMode, KeSetEvent(), KeWaitForSingleObject(), NULL, _DEVICE_OBJECT::Vpb, VPB_MOUNTED, and VPB_REMOVE_PENDING.

Referenced by IopRemoveDevice().

    01088                    :
    01089
    01090     This routine will scan up the device stack and mark each unmounted VPB it
    01091     finds with the VPB_REMOVE_PENDING bit (or clear it in the case of cancel)
    01092     and increment (or decrement in the case of cancel) the reference count
    01093     in the VPB.  This is to ensure that no new file system can get mounted on
    01094     the device stack while the remove operation is in place.
    01095
    01096     The search will terminate once all the attached device objects have been
    01097     marked, or once a mounted device object has been marked.
    01098
    01099 Arguments:
    01100
    01101     DeviceObject - the PDO we are attempting to remove
    01102
    01103     IrpMinorCode - the remove-type operation we are going to perform
    01104
    01105     Context - a context block which must be passed in to the unlock operation
    01106
    01107 Return Value:
    01108
    01109     A pointer to the device object stack which the remove request should be
    01110     sent to.  If a mounted file system was found, this will be the lowest
    01111     file system device object in the mounted stack.  Otherwise this will be
    01112     the PDO which was passed in.
    01113
    01114 --*/
    01115
    01116 {
    01117     PVPB vpb;
    01118
    01119     PDEVICE_OBJECT device = DeviceObject;
    01120     PDEVICE_OBJECT fsDevice = NULL;
    01121
    01122     BOOLEAN isRemovePendingSet;
    01123     KIRQL oldIrql;
    01124
    01125     RtlZeroMemory(Context, sizeof(LOCK_MOUNTABLE_DEVICE_CONTEXT));
    01126     Context->MountedDevice = DeviceObject;
    01127
    01128     do {
    01129
    01130         //
    01131         // Walk up each device object in the stack.  For each one, if a VPB
    01132         // exists, grab the database resource exclusive followed by the
    01133         // device lock.  Then acquire the Vpb spinlock and perform the
    01134         // appropriate magic on the device object.
    01135         //
    01136
    01137         //
    01138         // NOTE - Its unfortunate that the locking order includes grabbing
    01139         // the device specific lock first followed by the global lock.
    01140         //
    01141
    01142         if(device->Vpb != NULL) {
    01143
    01144             //
    01145             // Grab the device lock.  This will ensure that there are no mount
    01146             // or verify operations in progress.
    01147             //
    01148
    01149             KeWaitForSingleObject(&(device->DeviceLock),
    01150                                   Executive,
    01151                                   KernelMode,
    01152                                   FALSE,
    01153                                   NULL);
    01154
    01155             //
    01156             // Now set the remove pending flag, which will prevent new mounts
    01157             // from occuring on this stack once the current (if existant)
    01158             // filesystem dismounts. Filesystems will preserve the flag across
    01159             // vpb swaps.
    01160             //
    01161
    01162             IoAcquireVpbSpinLock(&oldIrql);
    01163
    01164             vpb = device->Vpb;
    01165
    01166             ASSERT(vpb != NULL);
    01167
    01168             switch(IrpMinorCode) {
    01169
    01170                 case IRP_MN_QUERY_REMOVE_DEVICE:
    01171                 case IRP_MN_SURPRISE_REMOVAL:
    01172                 case IRP_MN_REMOVE_DEVICE: {
    01173
    01174                     vpb->Flags |= VPB_REMOVE_PENDING;
    01175                     break;
    01176                 }
    01177
    01178                 case IRP_MN_CANCEL_REMOVE_DEVICE: {
    01179
    01180                     vpb->Flags &= ~VPB_REMOVE_PENDING;
    01181                     break;
    01182                 }
    01183
    01184                 default:
    01185                     break;
    01186             }
    01187
    01188             //
    01189             // Note the device object that has the filesystem stack attached.
    01190             // We must remember the vpb we referenced that had the fs because
    01191             // it may be swapped off of the storage device during a dismount
    01192             // operation.
    01193             //
    01194
    01195             if(vpb->Flags & VPB_MOUNTED) {
    01196
    01197                 Context->MountedDevice = device;
    01198                 fsDevice = vpb->DeviceObject;
    01199             }
    01200
    01201             IoReleaseVpbSpinLock(oldIrql);
    01202             KeSetEvent(&(device->DeviceLock), IO_NO_INCREMENT, FALSE);
    01203
    01204             //
    01205             // Stop if we hit a device with a mounted filesystem.
    01206             //
    01207
    01208             if (Context->MountedDevice != NULL) {
    01209
    01210                 //
    01211                 // We found and setup a mounted device.  Time to return.
    01212                 //
    01213
    01214                 break;
    01215             }
    01216         }
    01217
    01218         ExAcquireFastLock( &IopDatabaseLock, &oldIrql );
    01219         device = device->AttachedDevice;
    01220         ExReleaseFastLock( &IopDatabaseLock, oldIrql );
    01221
    01222     } while (device != NULL);
    01223
    01224     if(fsDevice != NULL) {
    01225
    01226         return fsDevice;
    01227     }
    01228
    01229     return Context->MountedDevice;
    01230 }

NTSTATUS IopMakeGloballyUniqueId | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PWCHAR | UniqueId,
|  | OUT PWCHAR * | GloballyUniqueId
| ) |

Definition at line 1891 of file pnpirp.c.

References ASSERT, CmRegistryMachineSystemCurrentControlSetEnumName, DbgPrint, ExAcquireResourceShared, ExAllocatePool, ExFreePool(), ExReleaseResource, HASH_UNICODE_STRING, _DEVICE_NODE::InstancePath, IopOpenRegistryKeyEx(), KeEnterCriticalRegion, KeLeaveCriticalRegion, L, _DEVICE_NODE::Level, max, MAX_PARENT_PREFIX, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, _DEVICE_NODE::Parent, PpRegistryDeviceResource, RtlFreeUnicodeString(), RtlInitUnicodeString(), RtlUpcaseUnicodeString(), TITLE_INDEX_VALUE, and TRUE.

Referenced by IopProcessNewDeviceNode().

    01896 {
    01897     NTSTATUS status;
    01898     ULONG length;
    01899     PWSTR id, Prefix = NULL;
    01900     HANDLE enumKey;
    01901     HANDLE instanceKey;
    01902     UCHAR keyBuffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
    01903     PKEY_VALUE_PARTIAL_INFORMATION keyValue, stringValueBuffer = NULL;
    01904     UNICODE_STRING valueName;
    01905     ULONG uniqueIdValue, Hash, hashInstance;
    01906     PDEVICE_NODE parentNode;
    01907
    01908     PAGED_CODE();
    01909
    01910     //
    01911     // We need to build an instance id to uniquely identify this
    01912     // device.  We will accomplish this by producing a prefix that will be
    01913     // prepended to the non-unique device id supplied.
    01914     //
    01915
    01916     //
    01917     // To 'unique-ify' the child's instance ID, we will retrieve
    01918     // the unique "UniqueParentID" number that has been assigned
    01919     // to the parent and use it to construct a prefix.  This is
    01920     // the legacy mechanism supported here so that existing device
    01921     // settings are not lost on upgrade.
    01922     //
    01923
    01924     KeEnterCriticalRegion();
    01925     ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
    01926
    01927     parentNode = ((PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode)->Parent;
    01928
    01929     status = IopOpenRegistryKeyEx( &enumKey,
    01930                                    NULL,
    01931                                    &CmRegistryMachineSystemCurrentControlSetEnumName,
    01932                                    KEY_READ | KEY_WRITE
    01933                                    );
    01934
    01935     if (!NT_SUCCESS(status)) {
    01936         DbgPrint("IopQueryUniqueId:\tUnable to open HKLM\\SYSTEM\\CCS\\ENUM (status %08lx)\n",
    01937                  status
    01938                 );
    01939         goto clean0;
    01940     }
    01941
    01942     //
    01943     // Open the instance key for this devnode
    01944     //
    01945     status = IopOpenRegistryKeyEx( &instanceKey,
    01946                                    enumKey,
    01947                                    &parentNode->InstancePath,
    01948                                    KEY_READ | KEY_WRITE
    01949                                    );
    01950
    01951     if (!NT_SUCCESS(status)) {
    01952         DbgPrint("IopQueryUniqueId:\tUnable to open registry key for %wZ (status %08lx)\n",
    01953                  &parentNode->InstancePath,
    01954                  status
    01955                 );
    01956         goto clean1;
    01957     }
    01958
    01959     //
    01960     // Attempt to retrieve the "UniqueParentID" value from the device
    01961     // instance key.
    01962     //
    01963     keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyBuffer;
    01964     PiWstrToUnicodeString(&valueName, REGSTR_VALUE_UNIQUE_PARENT_ID);
    01965
    01966     status = ZwQueryValueKey(instanceKey,
    01967                              &valueName,
    01968                              KeyValuePartialInformation,
    01969                              keyValue,
    01970                              sizeof(keyBuffer),
    01971                              &length
    01972                              );
    01973
    01974     if (NT_SUCCESS(status)) {
    01975         ASSERT(keyValue->Type == REG_DWORD);
    01976         ASSERT(keyValue->DataLength == sizeof(ULONG));
    01977         if ((keyValue->Type != REG_DWORD) ||
    01978             (keyValue->DataLength != sizeof(ULONG))) {
    01979             status = STATUS_INVALID_PARAMETER;
    01980             goto clean2;
    01981         }
    01982
    01983         uniqueIdValue = *(PULONG)(keyValue->Data);
    01984
    01985         //
    01986         // OK, we have a unique parent ID number to prefix to the
    01987         // instance ID.
    01988         Prefix = (PWSTR)ExAllocatePool(PagedPool, 9 * sizeof(WCHAR));
    01989         if (!Prefix) {
    01990             status = STATUS_INSUFFICIENT_RESOURCES;
    01991             goto clean2;
    01992         }
    01993         swprintf(Prefix, L"%x", uniqueIdValue);
    01994     } else {
    01995
    01996         //
    01997         // This is the current mechanism for finding existing
    01998         // device instance prefixes and calculating new ones if
    01999         // required.
    02000         //
    02001
    02002         //
    02003         // Attempt to retrieve the "ParentIdPrefix" value from the device
    02004         // instance key.
    02005         //
    02006
    02007         PiWstrToUnicodeString(&valueName, REGSTR_VALUE_PARENT_ID_PREFIX);
    02008         length = (MAX_PARENT_PREFIX + 1) * sizeof(WCHAR) +
    02009             FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
    02010         stringValueBuffer = ExAllocatePool(PagedPool,
    02011                                            length);
    02012         if (stringValueBuffer) {
    02013             status = ZwQueryValueKey(instanceKey,
    02014                                      &valueName,
    02015                                      KeyValuePartialInformation,
    02016                                      stringValueBuffer,
    02017                                      length,
    02018                                      &length);
    02019         }
    02020         else {
    02021             status = STATUS_INSUFFICIENT_RESOURCES;
    02022             goto clean2;
    02023         }
    02024
    02025         if (NT_SUCCESS(status)) {
    02026
    02027             ASSERT(stringValueBuffer->Type == REG_SZ);
    02028             if (stringValueBuffer->Type != REG_SZ) {
    02029                 status = STATUS_INVALID_PARAMETER;
    02030                 goto clean2;
    02031             }
    02032
    02033             //
    02034             // Parent has already been assigned a "ParentIdPrefix".
    02035             //
    02036
    02037             Prefix = (PWSTR) ExAllocatePool(PagedPool,
    02038                                             stringValueBuffer->DataLength);
    02039             if (!Prefix)
    02040             {
    02041                 status = STATUS_INSUFFICIENT_RESOURCES;
    02042                 goto clean2;
    02043             }
    02044             wcscpy(Prefix, (PWSTR) stringValueBuffer->Data);
    02045         }
    02046         else
    02047         {
    02048             //
    02049             // Parent has not been assigned a "ParentIdPrefix".
    02050             // Compute the prefix:
    02051             //    * Compute Hash
    02052             //    * Look for value of the form:
    02053             //        NextParentId.<level>.<hash>:REG_DWORD: <NextInstance>
    02054             //      under CCS\Enum.  If not present, create it.
    02055             //    * Assign the new "ParentIdPrefix" which will be of
    02056             //      of the form:
    02057             //        <level>&<hash>&<instance>
    02058             //
    02059
    02060             // Allocate a buffer once for the NextParentId... value
    02061             // and for the prefix.
    02062             length = max(wcslen(REGSTR_VALUE_NEXT_PARENT_ID) + 2 + 8 + 8,
    02063                          MAX_PARENT_PREFIX) + 1;
    02064
    02065             // Device instances are case in-sensitive.  Upcase before
    02066             // performing hash to ensure that the hash is case-insensitve.
    02067             status = RtlUpcaseUnicodeString(&valueName,
    02068                                             &parentNode->InstancePath,
    02069                                             TRUE);
    02070             if (!NT_SUCCESS(status))
    02071             {
    02072                 goto clean2;
    02073             }
    02074             HASH_UNICODE_STRING(&valueName, &Hash);
    02075             RtlFreeUnicodeString(&valueName);
    02076
    02077             Prefix = (PWSTR) ExAllocatePool(PagedPool,
    02078                                             length * sizeof(WCHAR));
    02079             if (!Prefix) {
    02080                 status = STATUS_INSUFFICIENT_RESOURCES;
    02081                 goto clean2;
    02082             }
    02083
    02084             // Check for existence of "NextParentId...." value and update.
    02085             swprintf(Prefix, L"%s.%x.%x", REGSTR_VALUE_NEXT_PARENT_ID,
    02086                      Hash, parentNode->Level);
    02087             RtlInitUnicodeString(&valueName, Prefix);
    02088             keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyBuffer;
    02089             status = ZwQueryValueKey(enumKey,
    02090                                      &valueName,
    02091                                      KeyValuePartialInformation,
    02092                                      keyValue,
    02093                                      sizeof(keyBuffer),
    02094                                      &length
    02095                                      );
    02096             if (NT_SUCCESS(status) && (keyValue->Type == REG_DWORD) &&
    02097                 (keyValue->DataLength == sizeof(ULONG))) {
    02098                 hashInstance = *(PULONG)(keyValue->Data);
    02099             }
    02100             else {
    02101                 hashInstance = 0;
    02102             }
    02103
    02104             hashInstance++;
    02105
    02106             status = ZwSetValueKey(enumKey,
    02107                                    &valueName,
    02108                                    TITLE_INDEX_VALUE,
    02109                                    REG_DWORD,
    02110                                    &hashInstance,
    02111                                    sizeof(hashInstance)
    02112                                    );
    02113
    02114             if (!NT_SUCCESS(status)) {
    02115                 goto clean2;
    02116             }
    02117
    02118             hashInstance--;
    02119
    02120             // Create actual ParentIdPrefix string
    02121             PiWstrToUnicodeString(&valueName, REGSTR_VALUE_PARENT_ID_PREFIX);
    02122             length = swprintf(Prefix, L"%x&%x&%x", parentNode->Level,
    02123                      Hash, hashInstance) + 1;
    02124             status = ZwSetValueKey(instanceKey,
    02125                                    &valueName,
    02126                                    TITLE_INDEX_VALUE,
    02127                                    REG_SZ,
    02128                                    Prefix,
    02129                                    length * sizeof(WCHAR)
    02130                                    );
    02131             if (!NT_SUCCESS(status))
    02132             {
    02133                 goto clean2;
    02134             }
    02135         }
    02136     }
    02137
    02138     // Construct the instance id from the non-unique id (if any)
    02139     // provided by the child and the prefix we've constructed.
    02140     length = wcslen(Prefix) + (UniqueId ? wcslen(UniqueId) : 0) + 2;
    02141     id = (PWSTR)ExAllocatePool(PagedPool, length * sizeof(WCHAR));
    02142     if (!id) {
    02143         status = STATUS_INSUFFICIENT_RESOURCES;
    02144     } else if (UniqueId) {
    02145         swprintf(id, L"%s&%s", Prefix, UniqueId);
    02146     } else {
    02147         wcscpy(id, Prefix);
    02148     }
    02149
    02150 clean2:
    02151     ZwClose(instanceKey);
    02152
    02153 clean1:
    02154     ZwClose(enumKey);
    02155
    02156 clean0:
    02157     ExReleaseResource(&PpRegistryDeviceResource);
    02158     KeLeaveCriticalRegion();
    02159
    02160     if (stringValueBuffer) {
    02161         ExFreePool(stringValueBuffer);
    02162     }
    02163
    02164     if (Prefix) {
    02165         ExFreePool(Prefix);
    02166     }
    02167
    02168     *GloballyUniqueId = id;
    02169     return status;
    02170 }

NTSTATUS IopQueryCompatibleIds | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN BUS_QUERY_ID_TYPE | IdType,
|  | OUT PWCHAR * | CompatibleIds,
|  | OUT ULONG * | Length
| ) |

Definition at line 2173 of file pnpirp.c.

References BusQueryCompatibleIDs, BusQueryHardwareIDs, IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_ID, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), PAGED_CODE, and _IO_STACK_LOCATION::Parameters.

Referenced by IopProcessNewDeviceNode(), and IopStartAndEnumerateDevice().

    02182                    :
    02183
    02184     This routine sends irp to query HardwareIds or CompatibleIds.  This rotine
    02185     queries MULTISZ Ids.
    02186
    02187 Parameters:
    02188
    02189     DeviceObject - Supplies the device object of the device being queried/
    02190
    02191     IdType - Specifies the Id type interested.  Only HardwareIDs and CompatibleIDs
    02192              are supported by this routine.
    02193
    02194     CompatibleId - Supplies a pointer to a variable to receive the returned Ids.
    02195                    This must be freed by the caller.
    02196
    02197     Length - Supplies a pointer to a variable to receive the length of the IDs.
    02198
    02199 Return Value:
    02200
    02201     NTSTATUS code.
    02202
    02203 --*/
    02204 {
    02205     IO_STACK_LOCATION irpSp;
    02206     NTSTATUS status;
    02207
    02208     PAGED_CODE();
    02209
    02210     *Length = 0;
    02211     if ((IdType != BusQueryHardwareIDs) && (IdType != BusQueryCompatibleIDs)) {
    02212         return STATUS_INVALID_PARAMETER_2;
    02213     }
    02214
    02215     //
    02216     // Initialize the stack location to pass to IopSynchronousCall()
    02217     //
    02218
    02219     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    02220
    02221     //
    02222     // Set the function codes.
    02223     //
    02224
    02225     irpSp.MajorFunction = IRP_MJ_PNP;
    02226     irpSp.MinorFunction = IRP_MN_QUERY_ID;
    02227
    02228     //
    02229     // Set the pointer to the resource list
    02230     //
    02231
    02232     irpSp.Parameters.QueryId.IdType = IdType;
    02233
    02234     //
    02235     // Make the call and return.
    02236     //
    02237
    02238     status = IopSynchronousCall(DeviceObject, &irpSp, CompatibleIds);
    02239
    02240     if (NT_SUCCESS(status) && *CompatibleIds) {
    02241
    02242         //
    02243         // The Compatible IDs and Hardware IDs are multi_sz,
    02244         // try to determine its size.
    02245         //
    02246
    02247         PWCHAR wp;
    02248
    02249         for (wp = *CompatibleIds;
    02250              (*wp != UNICODE_NULL) || (*(wp + 1) != UNICODE_NULL);
    02251              wp++) {
    02252
    02253             *Length += 2;
    02254         }
    02255         *Length += 4;
    02256     }
    02257
    02258     return status;
    02259 }

NTSTATUS IopQueryDeviceId | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | OUT PWCHAR * | DeviceId
| ) |

Definition at line 1762 of file pnpirp.c.

References BusQueryDeviceID, IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_ID, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), PAGED_CODE, and _IO_STACK_LOCATION::Parameters.

Referenced by IopProcessNewDeviceNode().

    01769                    :
    01770
    01771     This routine sends a query device id irp to the specified device object.
    01772
    01773 Parameters:
    01774
    01775     DeviceObject - Supplies the device object of the device being queried/
    01776
    01777     DeviceId - Supplies a pointer to a variable to receive the returned Id.
    01778                This must be freed by the caller.
    01779
    01780 Return Value:
    01781
    01782     NTSTATUS code.
    01783
    01784 --*/
    01785 {
    01786     IO_STACK_LOCATION irpSp;
    01787     NTSTATUS status;
    01788
    01789     PAGED_CODE();
    01790
    01791     //
    01792     // Initialize the stack location to pass to IopSynchronousCall()
    01793     //
    01794
    01795     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    01796
    01797     //
    01798     // Set the function codes.
    01799     //
    01800
    01801     irpSp.MajorFunction = IRP_MJ_PNP;
    01802     irpSp.MinorFunction = IRP_MN_QUERY_ID;
    01803
    01804     //
    01805     // Set the pointer to the resource list
    01806     //
    01807
    01808     irpSp.Parameters.QueryId.IdType = BusQueryDeviceID;
    01809
    01810     //
    01811     // Make the call and return.
    01812     //
    01813
    01814     status = IopSynchronousCall(DeviceObject, &irpSp, DeviceId);
    01815
    01816     return status;
    01817 }

NTSTATUS IopQueryDeviceRelations | ( | IN DEVICE_RELATION_TYPE | Relations,
|  | IN PDEVICE_OBJECT | DeviceObject,
|  | IN BOOLEAN | AsyncOk,
|  | OUT PDEVICE_RELATIONS * | DeviceRelations
| ) |

Definition at line 1604 of file pnpirp.c.

References BusRelations, _DEVICE_COMPLETION_CONTEXT::DeviceNode, DNF_BEING_ENUMERATED, DNF_ENUMERATION_REQUEST_PENDING, DNF_ENUMERATION_REQUEST_QUEUED, DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING, ExAllocatePool, ExGetCurrentResourceThread, FALSE, _DEVICE_NODE::Flags, IopAcquireEnumerationLock, IopAsynchronousCall(), IopDeviceRelationsComplete(), IopPnPSpinLock, IopRequestDeviceAction(), IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_RELATIONS, _DEVICE_COMPLETION_CONTEXT::IrpMinorCode, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NonPagedPool, NTSTATUS(), NULL, _DEVICE_NODE::OverUsed1, _IO_STACK_LOCATION::Parameters, PDEVICE_COMPLETION_CONTEXT, ReenumerateDeviceTree, _DEVICE_COMPLETION_CONTEXT::Thread, and TRUE.

Referenced by IopEnumerateDevice(), and IopProcessRelation().

    01613                    :
    01614
    01615     This routine sends query device relation irp to the specified device object.
    01616
    01617 Parameters:
    01618
    01619     Relations - specifies the type of relation interested.
    01620
    01621     DeviceObjet - Supplies the device object of the device being queried.
    01622
    01623     AsyncOk - Specifies if we can perform Async QueryDeviceRelations
    01624
    01625     DeviceRelations - Supplies a pointer to a variable to receive the returned
    01626                       relation information. This must be freed by the caller.
    01627
    01628 Return Value:
    01629
    01630     NTSTATUS code.
    01631
    01632 --*/
    01633
    01634 {
    01635     IO_STACK_LOCATION irpSp;
    01636     NTSTATUS status;
    01637     PDEVICE_RELATIONS deviceRelations;
    01638     PDEVICE_NODE deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    01639     PDEVICE_COMPLETION_CONTEXT completionContext;
    01640     BOOLEAN requestEnumeration = FALSE;
    01641     KIRQL oldIrql;
    01642
    01643     //
    01644     // Do not allow two bus relations at the same time
    01645     //
    01646
    01647     if (Relations == BusRelations) {
    01648         ExAcquireSpinLock(&IopPnPSpinLock, &oldIrql);
    01649         if (deviceNode->Flags & DNF_BEING_ENUMERATED) {
    01650             ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01651             return STATUS_UNSUCCESSFUL;
    01652         }
    01653         deviceNode->Flags &= ~DNF_ENUMERATION_REQUEST_QUEUED;
    01654         deviceNode->Flags  |= DNF_BEING_ENUMERATED;
    01655         ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01656     }
    01657
    01658     //
    01659     // Initialize the stack location to pass to IopSynchronousCall()
    01660     //
    01661
    01662     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    01663
    01664     //
    01665     // Set the function codes.
    01666     //
    01667
    01668     irpSp.MajorFunction = IRP_MJ_PNP;
    01669     irpSp.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
    01670
    01671     //
    01672     // Set the pointer to the resource list
    01673     //
    01674
    01675     irpSp.Parameters.QueryDeviceRelations.Type = Relations;
    01676
    01677     //
    01678     // Make the call and return.
    01679     //
    01680
    01681     if (AsyncOk && Relations == BusRelations) {
    01682         completionContext = (PDEVICE_COMPLETION_CONTEXT) ExAllocatePool(
    01683                               NonPagedPool,
    01684                               sizeof(DEVICE_COMPLETION_CONTEXT));
    01685         if (completionContext == NULL) {
    01686             return STATUS_INSUFFICIENT_RESOURCES;   // BUGBUG - Should try it again.
    01687         }
    01688
    01689         completionContext->DeviceNode = deviceNode;
    01690         completionContext->IrpMinorCode = IRP_MN_QUERY_DEVICE_RELATIONS;
    01691         completionContext->Thread = ExGetCurrentResourceThread();
    01692
    01693         //
    01694         // Make the call and return.
    01695         //
    01696
    01697         IopAcquireEnumerationLock(NULL);  // To block IopAcquireTreeLock();
    01698         status = IopAsynchronousCall(DeviceObject, &irpSp, completionContext, IopDeviceRelationsComplete);
    01699         if (status == STATUS_PENDING) {
    01700             KIRQL oldIrql;
    01701
    01702             ExAcquireSpinLock(&IopPnPSpinLock, &oldIrql);
    01703
    01704             //
    01705             // Check if the completion routine completes before we setting
    01706             // the DNF_ENUMERATION_REQUEST_PENDING flags.
    01707             //
    01708
    01709             if (deviceNode->Flags & DNF_ENUMERATION_REQUEST_PENDING) {
    01710                 deviceNode->Flags &= ~DNF_ENUMERATION_REQUEST_PENDING;
    01711                 *DeviceRelations = deviceNode->OverUsed1.PendingDeviceRelations;
    01712                 deviceNode->OverUsed1.PendingDeviceRelations = NULL;
    01713                 status = STATUS_SUCCESS;
    01714             } else {
    01715
    01716                 //
    01717                 // Set DNF_ENUMERATION_REQUEST_PENDING such that the completion routine knows it
    01718                 // needs to request enumeration when the Q_bus_relations completed successfully.
    01719                 //
    01720
    01721                 deviceNode->Flags |= DNF_ENUMERATION_REQUEST_PENDING;
    01722             }
    01723
    01724             ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01725         } else {
    01726             deviceNode->Flags &= ~DNF_ENUMERATION_REQUEST_PENDING;
    01727             *DeviceRelations = deviceNode->OverUsed1.PendingDeviceRelations;
    01728             deviceNode->OverUsed1.PendingDeviceRelations = NULL;
    01729         }
    01730         return status;
    01731     } else {
    01732         status = IopSynchronousCall(DeviceObject, &irpSp, DeviceRelations);
    01733
    01734         //
    01735         // To prevent the scenario that a driver calls IoInvalidateDeviceRelations while servicing
    01736         // an Async Q-D-R irp, and receives another q-d-r irp before first one completed, we will
    01737         // set a flag when it calls IoInvalidateDeviceRelations and delay queuing the request till
    01738         // the original one is completed.
    01739         //
    01740
    01741         if (Relations == BusRelations) {
    01742             ExAcquireSpinLock(&IopPnPSpinLock, &oldIrql);
    01743             deviceNode->Flags  &= ~DNF_BEING_ENUMERATED;
    01744             if (deviceNode->Flags & DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING) {
    01745                 deviceNode->Flags &= ~DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING;
    01746                 requestEnumeration = TRUE;
    01747             }
    01748             ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    01749             if (requestEnumeration) {
    01750                 IopRequestDeviceAction( DeviceObject,
    01751                                         ReenumerateDeviceTree,
    01752                                         NULL,
    01753                                         NULL );
    01754             }
    01755         }
    01756     }
    01757
    01758     return status;
    01759 }

NTSTATUS IopQueryDeviceResources | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN ULONG | ResourceType,
|  | OUT PVOID * | Resource,
|  | OUT ULONG * | Length
| ) |

Definition at line 2262 of file pnpirp.c.

References ASSERT, DbgPrint, DNF_MADEUP, DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED, ExAllocatePool, ExFreePool(), FALSE, _DEVICE_NODE::Flags, IopCmResourcesToIoResources(), IopDetermineResourceListSize(), IopDeviceObjectToDeviceInstance(), IopFilterResourceRequirementsCall(), IopFilterResourceRequirementsList(), IopGetDeviceResourcesFromRegistry(), IopMergeFilteredResourceRequirementsList(), IopOpenRegistryKeyEx(), IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_RESOURCE_REQUIREMENTS, IRP_MN_QUERY_RESOURCES, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, QUERY_RESOURCE_LIST, QUERY_RESOURCE_REQUIREMENTS, REGISTRY_ALLOC_CONFIG, REGISTRY_BASIC_CONFIGVECTOR, REGISTRY_BOOT_CONFIG, REGISTRY_FORCED_CONFIG, REGISTRY_OVERRIDE_CONFIGVECTOR, Resource, _DEVICE_NODE::ResourceRequirements, and TITLE_INDEX_VALUE.

Referenced by IopGetResourceRequirementsForAssignTable(), IopProcessNewDeviceNode(), and IopReleaseDeviceResources().

    02271                    :
    02272
    02273     This routine sends irp to queries resources or resource requirements list
    02274     of the specified device object.
    02275
    02276     If the device object is a detected device, its resources will be read from
    02277     registry.  Otherwise, an irp is sent to the bus driver to query its resources.
    02278
    02279 Parameters:
    02280
    02281     DeviceObject - Supplies the device object of the device being queries.
    02282
    02283     ResourceType - 0 for device resources and 1 for resource requirements list.
    02284
    02285     Resource - Supplies a pointer to a variable to receive the returned resources
    02286
    02287     Length - Supplies a pointer to a variable to receive the length of the returned
    02288              resources or resource requirements list.
    02289
    02290 Return Value:
    02291
    02292     NTSTATUS code.
    02293
    02294 --*/
    02295 {
    02296     IO_STACK_LOCATION irpSp;
    02297     PDEVICE_NODE deviceNode;
    02298     NTSTATUS status;
    02299     PIO_RESOURCE_REQUIREMENTS_LIST resReqList, newResources;
    02300     ULONG junk;
    02301     PCM_RESOURCE_LIST cmList;
    02302     PIO_RESOURCE_REQUIREMENTS_LIST filteredList, mergedList;
    02303     BOOLEAN exactMatch;
    02304
    02305     PAGED_CODE();
    02306
    02307 #if DBG
    02308
    02309     if ((ResourceType != QUERY_RESOURCE_LIST) &&
    02310         (ResourceType != QUERY_RESOURCE_REQUIREMENTS)) {
    02311         return STATUS_INVALID_PARAMETER_2;
    02312     }
    02313 #endif
    02314
    02315     *Resource = NULL;
    02316     *Length = 0;
    02317
    02318     //
    02319     // Initialize the stack location to pass to IopSynchronousCall()
    02320     //
    02321
    02322     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    02323
    02324     deviceNode = (PDEVICE_NODE) DeviceObject->DeviceObjectExtension->DeviceNode;
    02325
    02326     if (ResourceType == QUERY_RESOURCE_LIST) {
    02327
    02328         //
    02329         // caller is asked for RESOURCE_LIST.  If this is a madeup device, we will
    02330         // read it from registry.  Otherwise, we ask drivers.
    02331         //
    02332
    02333         if (deviceNode->Flags & DNF_MADEUP) {
    02334
    02335             status = IopGetDeviceResourcesFromRegistry(
    02336                              DeviceObject,
    02337                              ResourceType,
    02338                              REGISTRY_ALLOC_CONFIG + REGISTRY_FORCED_CONFIG + REGISTRY_BOOT_CONFIG,
    02339                              Resource,
    02340                              Length);
    02341             if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
    02342                 status = STATUS_SUCCESS;
    02343             }
    02344             return status;
    02345         } else {
    02346             irpSp.MinorFunction = IRP_MN_QUERY_RESOURCES;
    02347             irpSp.MajorFunction = IRP_MJ_PNP;
    02348             status = IopSynchronousCall(DeviceObject, &irpSp, Resource);
    02349             if (status == STATUS_NOT_SUPPORTED) {
    02350
    02351                 //
    02352                 // If driver doesn't implement this request, it
    02353                 // doesn't consume any resources.
    02354                 //
    02355
    02356                 *Resource = NULL;
    02357                 status = STATUS_SUCCESS;
    02358             }
    02359             if (NT_SUCCESS(status)) {
    02360                 *Length = IopDetermineResourceListSize((PCM_RESOURCE_LIST)*Resource);
    02361             }
    02362             return status;
    02363         }
    02364     } else {
    02365
    02366         //
    02367         // Caller is asked for resource requirements list.  We will check:
    02368         // if there is a ForcedConfig, it will be converted to resource requirements
    02369         //     list and return.  Otherwise,
    02370         // If there is an OVerrideConfigVector, we will use it as our
    02371         //     FilterConfigVector.  Otherwise we ask driver for the config vector and
    02372         //     use it as our FilterConfigVector.
    02373         //     Finaly, we pass the FilterConfigVector to driver stack to let drivers
    02374         //     filter the requirements.
    02375         //
    02376
    02377         status = IopGetDeviceResourcesFromRegistry(
    02378                          DeviceObject,
    02379                          QUERY_RESOURCE_LIST,
    02380                          REGISTRY_FORCED_CONFIG,
    02381                          Resource,
    02382                          &junk);
    02383         if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
    02384             status = IopGetDeviceResourcesFromRegistry(
    02385                              DeviceObject,
    02386                              QUERY_RESOURCE_REQUIREMENTS,
    02387                              REGISTRY_OVERRIDE_CONFIGVECTOR,
    02388                              &resReqList,
    02389                              &junk);
    02390             if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
    02391                 if (deviceNode->Flags & DNF_MADEUP) {
    02392                     status = IopGetDeviceResourcesFromRegistry(
    02393                                      DeviceObject,
    02394                                      QUERY_RESOURCE_REQUIREMENTS,
    02395                                      REGISTRY_BASIC_CONFIGVECTOR,
    02396                                      &resReqList,
    02397                                      &junk);
    02398                     if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
    02399                         status = STATUS_SUCCESS;
    02400                         resReqList = NULL;
    02401                     }
    02402                 } else {
    02403
    02404                     //
    02405                     // We are going to ask the bus driver ...
    02406                     //
    02407
    02408                     if (deviceNode->ResourceRequirements) {
    02409                         ASSERT(deviceNode->Flags & DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED);
    02410                         resReqList = ExAllocatePool(PagedPool, deviceNode->ResourceRequirements->ListSize);
    02411                         if (resReqList) {
    02412                             RtlMoveMemory(resReqList,
    02413                                          deviceNode->ResourceRequirements,
    02414                                          deviceNode->ResourceRequirements->ListSize
    02415                                          );
    02416                             status = STATUS_SUCCESS;
    02417                         } else {
    02418                             return STATUS_NO_MEMORY;
    02419                         }
    02420                     } else {
    02421                         irpSp.MinorFunction = IRP_MN_QUERY_RESOURCE_REQUIREMENTS;
    02422                         irpSp.MajorFunction = IRP_MJ_PNP;
    02423                         status = IopSynchronousCall(DeviceObject, &irpSp, &resReqList);
    02424                         if (status == STATUS_NOT_SUPPORTED) {
    02425
    02426                             //
    02427                             // If driver doesn't implement this request, it
    02428                             // doesn't require any resources.
    02429                             //
    02430
    02431                             status = STATUS_SUCCESS;
    02432                             resReqList = NULL;
    02433
    02434                         }
    02435                     }
    02436                 }
    02437                 if (!NT_SUCCESS(status)) {
    02438                     return status;
    02439                 }
    02440             }
    02441
    02442             //
    02443             // For devices with boot config, we need to filter the resource requirements
    02444             // list against boot config.
    02445             //
    02446
    02447             status = IopGetDeviceResourcesFromRegistry(
    02448                              DeviceObject,
    02449                              QUERY_RESOURCE_LIST,
    02450                              REGISTRY_BOOT_CONFIG,
    02451                              &cmList,
    02452                              &junk);
    02453             if (NT_SUCCESS(status) &&
    02454                 (!cmList || cmList->Count == 0 || cmList->List[0].InterfaceType != PCIBus)) {
    02455                 status = IopFilterResourceRequirementsList (
    02456                              resReqList,
    02457                              cmList,
    02458                              &filteredList,
    02459                              &exactMatch);
    02460                 if (cmList) {
    02461                     ExFreePool(cmList);
    02462                 }
    02463                 if (!NT_SUCCESS(status)) {
    02464                     if (resReqList) {
    02465                         ExFreePool(resReqList);
    02466                     }
    02467                     return status;
    02468                 } else {
    02469
    02470                     //
    02471                     // For non-root-enumerated devices, we merge filtered config with basic config
    02472                     // vectors to form a new res req list.  For root-enumerated devices, we don't
    02473                     // consider Basic config vector.
    02474                     //
    02475
    02476                     if (!(deviceNode->Flags & DNF_MADEUP) &&
    02477                         (exactMatch == FALSE || resReqList->AlternativeLists > 1)) {
    02478                         status = IopMergeFilteredResourceRequirementsList (
    02479                                  filteredList,
    02480                                  resReqList,
    02481                                  &mergedList
    02482                                  );
    02483                         if (resReqList) {
    02484                             ExFreePool(resReqList);
    02485                         }
    02486                         if (filteredList) {
    02487                             ExFreePool(filteredList);
    02488                         }
    02489                         if (NT_SUCCESS(status)) {
    02490                             resReqList = mergedList;
    02491                         } else {
    02492                             return status;
    02493                         }
    02494                     } else {
    02495                         if (resReqList) {
    02496                             ExFreePool(resReqList);
    02497                         }
    02498                         resReqList = filteredList;
    02499                     }
    02500                 }
    02501             }
    02502
    02503         } else {
    02504             ASSERT(NT_SUCCESS(status));
    02505
    02506             //
    02507             // We have Forced Config.  Convert it to resource requirements and return it.
    02508             //
    02509
    02510             if (*Resource) {
    02511                 resReqList = IopCmResourcesToIoResources (0, (PCM_RESOURCE_LIST)*Resource, LCPRI_FORCECONFIG);
    02512                 ExFreePool(*Resource);
    02513                 if (resReqList) {
    02514                     *Resource = (PVOID)resReqList;
    02515                     *Length = resReqList->ListSize;
    02516                 } else {
    02517                     *Resource = NULL;
    02518                     *Length = 0;
    02519                     status = STATUS_INSUFFICIENT_RESOURCES;
    02520                     return status;
    02521                 }
    02522             } else {
    02523                 resReqList = NULL;
    02524             }
    02525         }
    02526
    02527         //
    02528         // If we are here, we have a resource requirements list for drivers to examine ...
    02529         // NOTE: Per Lonny's request, we let drivers filter ForcedConfig
    02530         //
    02531
    02532         status = IopFilterResourceRequirementsCall(
    02533             DeviceObject,
    02534             resReqList,
    02535             &newResources
    02536             );
    02537
    02538         if (NT_SUCCESS(status)) {
    02539             UNICODE_STRING unicodeName;
    02540             HANDLE handle, handlex;
    02541
    02542 #if DBG
    02543             if (newResources == NULL && resReqList) {
    02544                 DbgPrint("PnpMgr: Non-NULL resource requirements list filtered to NULL\n");
    02545             }
    02546 #endif
    02547             if (newResources) {
    02548
    02549                 *Length = newResources->ListSize;
    02550                 ASSERT(*Length);
    02551
    02552                 //
    02553                 // Make our own copy of the allocation. We do this so that the
    02554                 // verifier doesn't believe the driver has leaked memory if
    02555                 // unloaded.
    02556                 //
    02557
    02558                 *Resource = (PVOID) ExAllocatePool(PagedPool, *Length);
    02559                 if (*Resource == NULL) {
    02560
    02561                     ExFreePool(newResources);
    02562                     return STATUS_INSUFFICIENT_RESOURCES;
    02563                 }
    02564
    02565                 RtlCopyMemory(*Resource, newResources, *Length);
    02566                 ExFreePool(newResources);
    02567
    02568             } else {
    02569                 *Length = 0;
    02570                 *Resource = NULL;
    02571             }
    02572
    02573             //
    02574             // Write filtered res req to registry
    02575             //
    02576
    02577             status = IopDeviceObjectToDeviceInstance(DeviceObject, &handlex, KEY_ALL_ACCESS);
    02578             if (NT_SUCCESS(status)) {
    02579                 PiWstrToUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
    02580                 status = IopOpenRegistryKeyEx( &handle,
    02581                                                handlex,
    02582                                                &unicodeName,
    02583                                                KEY_READ
    02584                                                );
    02585                 if (NT_SUCCESS(status)) {
    02586                     PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_FILTERED_CONFIG_VECTOR);
    02587                     ZwSetValueKey(handle,
    02588                                   &unicodeName,
    02589                                   TITLE_INDEX_VALUE,
    02590                                   REG_RESOURCE_REQUIREMENTS_LIST,
    02591                                   *Resource,
    02592                                   *Length
    02593                                   );
    02594                     ZwClose(handle);
    02595                     ZwClose(handlex);
    02596                 }
    02597             }
    02598         } else {
    02599
    02600             //
    02601             // ADRIAO BUGBUG 05/26/1999 -
    02602             //     Why do we not bubble up non-STATUS_NOT_SUPPORTED failure
    02603             // codes?
    02604             //
    02605             *Resource = resReqList;
    02606             if (resReqList) {
    02607                 *Length = resReqList->ListSize;
    02608             } else {
    02609                 *Length = 0;
    02610             }
    02611         }
    02612         return STATUS_SUCCESS;
    02613     }
    02614 }

NTSTATUS IopQueryDeviceSerialNumber | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | OUT PWCHAR * | SerialNumber
| ) |

Definition at line 3195 of file pnpirp.c.

References ASSERT, BusQueryDeviceSerialNumber, IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_ID, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and _IO_STACK_LOCATION::Parameters.

Referenced by IopHardwareProfileCommitStartedDock(), and IopHardwareProfileMarkDock().

    03202                    :
    03203
    03204     This routine retrieves a hardware serial number for the specified device object.
    03205     If the routine fails, SerialNumber is guarenteed to be to NULL.
    03206
    03207 Parameters:
    03208
    03209     DeviceObject - Supplies the device object of the device being queried
    03210
    03211     SerialNumber - Supplies a pointer to a variable to receive the returned Id.
    03212                    This must be freed by the caller.
    03213
    03214 Return Value:
    03215
    03216     NTSTATUS code.
    03217
    03218 --*/
    03219 {
    03220     IO_STACK_LOCATION irpSp;
    03221     NTSTATUS status;
    03222
    03223     PAGED_CODE();
    03224
    03225     *SerialNumber = NULL;
    03226
    03227     //
    03228     // Initialize the stack location to pass to IopSynchronousCall()
    03229     //
    03230
    03231     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    03232
    03233     //
    03234     // Set the function codes.
    03235     //
    03236
    03237     irpSp.MajorFunction = IRP_MJ_PNP;
    03238     irpSp.MinorFunction = IRP_MN_QUERY_ID;
    03239     irpSp.Parameters.QueryId.IdType = BusQueryDeviceSerialNumber;
    03240
    03241     //
    03242     // Make the call and return.
    03243     //
    03244
    03245     status = IopSynchronousCall(DeviceObject, &irpSp, SerialNumber);
    03246
    03247     ASSERT(NT_SUCCESS(status) || (*SerialNumber == NULL));
    03248     if (!NT_SUCCESS(status)) {
    03249         *SerialNumber = NULL;
    03250     }
    03251     return status;
    03252 }

NTSTATUS IopQueryDeviceState | ( | IN PDEVICE_OBJECT | DeviceObject | ) |

Definition at line 2976 of file pnpirp.c.

References DNF_HAS_PRIVATE_PROBLEM, DNUF_DONT_SHOW_IN_UI, DNUF_NOT_DISABLEABLE, FALSE, _DEVICE_NODE::Flags, IopDecDisableableDepends(), IopIncDisableableDepends(), IopRequestDeviceRemoval(), IopResourceRequirementsChanged(), IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_PNP_DEVICE_STATE, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), PAGED_CODE, PNP_DEVICE_DISABLED, PNP_DEVICE_DONT_DISPLAY_IN_UI, PNP_DEVICE_FAILED, PNP_DEVICE_NOT_DISABLEABLE, PNP_DEVICE_REMOVED, PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED, PNP_DEVICE_STATE, TRUE, and _DEVICE_NODE::UserFlags.

Referenced by IopInvalidateDeviceStateWorker(), and IopStartAndEnumerateDevice().

    02982                    :
    02983
    02984     This routine sends query device state irp to the specified device object.
    02985
    02986 Parameters:
    02987
    02988     DeviceObjet - Supplies the device object of the device being queried.
    02989
    02990 Return Value:
    02991
    02992     NTSTATUS code.
    02993
    02994 --*/
    02995
    02996 {
    02997     IO_STACK_LOCATION irpSp;
    02998     PDEVICE_NODE deviceNode;
    02999     PNP_DEVICE_STATE deviceState;
    03000     PDEVICE_RELATIONS deviceRelations;
    03001     KEVENT userEvent;
    03002     ULONG eventResult;
    03003     NTSTATUS status;
    03004
    03005     PAGED_CODE();
    03006
    03007     //
    03008     // Initialize the stack location to pass to IopSynchronousCall()
    03009     //
    03010
    03011     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    03012
    03013     //
    03014     // Set the function codes.
    03015     //
    03016
    03017     irpSp.MajorFunction = IRP_MJ_PNP;
    03018     irpSp.MinorFunction = IRP_MN_QUERY_PNP_DEVICE_STATE;
    03019
    03020     //
    03021     // Make the call.
    03022     //
    03023
    03024     status = IopSynchronousCall(DeviceObject, &irpSp, (PVOID *)&deviceState);
    03025
    03026     //
    03027     // Now perform the appropriate action based on the returned state
    03028     //
    03029
    03030     if (NT_SUCCESS(status)) {
    03031
    03032         deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode;
    03033
    03034         if (deviceState != 0) {
    03035
    03036             //
    03037             // everything here can only be turned on (state set)
    03038             //
    03039
    03040             if (deviceState & PNP_DEVICE_DONT_DISPLAY_IN_UI) {
    03041
    03042                 deviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
    03043             }
    03044
    03045             if (deviceState & PNP_DEVICE_NOT_DISABLEABLE) {
    03046
    03047                 if ((deviceNode->UserFlags & DNUF_NOT_DISABLEABLE)==0) {
    03048                     //
    03049                     // this node itself is not disableable
    03050                     //
    03051                     deviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
    03052                     //
    03053                     // propagate up tree
    03054                     //
    03055                     IopIncDisableableDepends(deviceNode);
    03056
    03057                 }
    03058             }
    03059
    03060             if (deviceState & (PNP_DEVICE_DISABLED | PNP_DEVICE_REMOVED)) {
    03061
    03062                 IopRequestDeviceRemoval( DeviceObject,
    03063                                          (deviceState & PNP_DEVICE_DISABLED) ?
    03064                                             CM_PROB_HARDWARE_DISABLED : CM_PROB_DEVICE_NOT_THERE
    03065                                          );
    03066
    03067             } else if (deviceState & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED) {
    03068
    03069                 if (deviceState & PNP_DEVICE_FAILED) {
    03070
    03071                     IopResourceRequirementsChanged(DeviceObject, TRUE);
    03072
    03073                 } else {
    03074
    03075                     IopResourceRequirementsChanged(DeviceObject, FALSE);
    03076
    03077                 }
    03078             } else if (deviceState & PNP_DEVICE_FAILED) {
    03079
    03080                 deviceNode->Flags |= DNF_HAS_PRIVATE_PROBLEM;
    03081
    03082                 IopRequestDeviceRemoval(DeviceObject, 0);
    03083             }
    03084         } else {
    03085
    03086             //
    03087             // handle things that can be turned off (state cleared)
    03088             //
    03089
    03090             if (deviceNode->UserFlags & DNUF_NOT_DISABLEABLE) {
    03091                 //
    03092                 // this node itself is now disableable
    03093                 //
    03094                 //
    03095                 // check tree
    03096                 //
    03097                 IopDecDisableableDepends(deviceNode);
    03098             }
    03099
    03100             deviceNode->UserFlags &= ~(DNUF_DONT_SHOW_IN_UI | DNUF_NOT_DISABLEABLE);
    03101         }
    03102     }
    03103
    03104     return status;
    03105 }

NTSTATUS IopQueryDockRemovalInterface | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN OUT PDOCK_INTERFACE * | DockInterface
| ) |

Definition at line 3395 of file pnpirp.c.

References dummy(), ExAllocatePool, ExFreePool(), IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_INTERFACE, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, _IO_STACK_LOCATION::Parameters, _INTERFACE::Size, USHORT, and _INTERFACE::Version.

    03402                    :
    03403
    03404     This routine queries the specified DeviceObject for the dock removal
    03405     interface. We use this interface to send pseudo-remove's. We use this
    03406     to solve the removal orderings problem.
    03407
    03408 Parameters:
    03409
    03410     DeviceObject - Supplies a pointer to the Device object to be queried.
    03411
    03412     Interface - supplies a variable to receive the desired interface.
    03413
    03414 Return Value:
    03415
    03416     Status code that indicates whether or not the function was successful.
    03417
    03418 --*/
    03419 {
    03420     IO_STACK_LOCATION irpSp;
    03421     NTSTATUS status;
    03422     PVOID dummy;
    03423     PINTERFACE interface;
    03424     USHORT size;
    03425     GUID interfaceType;
    03426
    03427     PAGED_CODE();
    03428
    03429     size = sizeof(DOCK_INTERFACE);
    03430     interfaceType = GUID_DOCK_INTERFACE;
    03431     interface = (PINTERFACE) ExAllocatePool(PagedPool, size);
    03432     if (interface == NULL) {
    03433         return STATUS_INSUFFICIENT_RESOURCES;
    03434     }
    03435
    03436     RtlZeroMemory(interface, size);
    03437     interface->Size = size;
    03438
    03439     //
    03440     // Initialize the stack location to pass to IopSynchronousCall()
    03441     //
    03442
    03443     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    03444
    03445     //
    03446     // Set the function codes.
    03447     //
    03448
    03449     irpSp.MajorFunction = IRP_MJ_PNP;
    03450     irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
    03451
    03452     //
    03453     // Set the pointer to the resource list
    03454     //
    03455
    03456     irpSp.Parameters.QueryInterface.InterfaceType = &interfaceType;
    03457     irpSp.Parameters.QueryInterface.Size = interface->Size;
    03458     irpSp.Parameters.QueryInterface.Version = interface->Version = 0;
    03459     irpSp.Parameters.QueryInterface.Interface = interface;
    03460     irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
    03461
    03462     //
    03463     // Make the call and return.
    03464     //
    03465
    03466     status = IopSynchronousCall(DeviceObject, &irpSp, &dummy);
    03467     if (NT_SUCCESS(status)) {
    03468         *DockInterface = (PDOCK_INTERFACE) interface;
    03469     } else {
    03470         ExFreePool(interface);
    03471     }
    03472     return status;
    03473 }

NTSTATUS IopQueryLegacyBusInformation | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | OUT LPGUID | InterfaceGuid,
|  | OPTIONAL OUT INTERFACE_TYPE * | InterfaceType,
|  | OPTIONAL OUT ULONG *BusNumber | OPTIONAL
| ) |

Definition at line 2793 of file pnpirp.c.

References ASSERT, _LEGACY_BUS_INFORMATION::BusNumber, BusNumber, _LEGACY_BUS_INFORMATION::BusTypeGuid, DbgPrint, ExFreePool(), InterfaceType, IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_LEGACY_BUS_INFORMATION, _LEGACY_BUS_INFORMATION::LegacyBusType, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and _DEVICE_NODE::ServiceName.

Referenced by IopCallDriverAddDevice().

    02802                    :
    02803
    02804     This routine queries the specified DeviceObject for its legacy bus
    02805     information.
    02806
    02807 Parameters:
    02808
    02809     DeviceObject - The device object to be queried.
    02810
    02811     InterfaceGuid = Supplies a pointer to receive the device's interface type
    02812         GUID.
    02813
    02814     Interface = Supplies a pointer to receive the device's interface type.
    02815
    02816     BusNumber = Supplies a pointer to receive the device's bus number.
    02817
    02818 Return Value:
    02819
    02820     Returns NTSTATUS.
    02821
    02822 --*/
    02823 {
    02824     IO_STACK_LOCATION irpSp;
    02825     NTSTATUS status;
    02826     PLEGACY_BUS_INFORMATION busInfo;
    02827
    02828     PAGED_CODE();
    02829
    02830     //
    02831     // Initialize the stack location to pass to IopSynchronousCall()
    02832     //
    02833
    02834     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    02835
    02836     //
    02837     // Set the function codes.
    02838     //
    02839
    02840     irpSp.MajorFunction = IRP_MJ_PNP;
    02841     irpSp.MinorFunction = IRP_MN_QUERY_LEGACY_BUS_INFORMATION;
    02842
    02843     //
    02844     // Make the call and return.
    02845     //
    02846
    02847     status = IopSynchronousCall(DeviceObject, &irpSp, &busInfo);
    02848     if (NT_SUCCESS(status)) {
    02849
    02850         if (busInfo == NULL) {
    02851
    02852             //
    02853             // The device driver LIED to us.  Bad, bad, bad device driver.
    02854             //
    02855
    02856             PDEVICE_NODE deviceNode;
    02857
    02858             deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode;
    02859
    02860             if (deviceNode && deviceNode->ServiceName.Buffer) {
    02861
    02862                 DbgPrint("*** IopQueryLegacyBusInformation - Driver %wZ returned STATUS_SUCCESS\n", &deviceNode->ServiceName);
    02863                 DbgPrint("    for IRP_MN_QUERY_LEGACY_BUS_INFORMATION, and a NULL POINTER.\n");
    02864             }
    02865
    02866             ASSERT(busInfo != NULL);
    02867
    02868         } else {
    02869             if (ARGUMENT_PRESENT(InterfaceGuid)) {
    02870                 *InterfaceGuid = busInfo->BusTypeGuid;
    02871             }
    02872             if (ARGUMENT_PRESENT(InterfaceType)) {
    02873                 *InterfaceType = busInfo->LegacyBusType;
    02874             }
    02875             if (ARGUMENT_PRESENT(BusNumber)) {
    02876                 *BusNumber = busInfo->BusNumber;
    02877             }
    02878             ExFreePool(busInfo);
    02879         }
    02880     }
    02881     return status;
    02882 }

NTSTATUS IopQueryPnpBusInformation | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | OUT LPGUID | InterfaceGuid,
|  | OPTIONAL OUT INTERFACE_TYPE * | InterfaceType,
|  | OPTIONAL OUT ULONG *BusNumber | OPTIONAL
| ) |

Definition at line 2885 of file pnpirp.c.

References ASSERT, _PNP_BUS_INFORMATION::BusNumber, BusNumber, _PNP_BUS_INFORMATION::BusTypeGuid, DbgPrint, ExFreePool(), InterfaceType, IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_BUS_INFORMATION, _PNP_BUS_INFORMATION::LegacyBusType, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and _DEVICE_NODE::ServiceName.

Referenced by IopProcessNewDeviceNode().

    02894                    :
    02895
    02896     This routine queries the specified DeviceObject for the specified ResourceType
    02897     resource translator.
    02898
    02899 Parameters:
    02900
    02901     HandlerType - specifies Arbiter or Translator
    02902
    02903     DeviceObject - Supplies a pointer to the Device object to be queried.
    02904
    02905     ResourceType - Specifies the desired type of translator.
    02906
    02907     Interface - supplies a variable to receive the desired interface.
    02908
    02909 Return Value:
    02910
    02911     Status code that indicates whether or not the function was successful.
    02912
    02913 --*/
    02914 {
    02915     IO_STACK_LOCATION irpSp;
    02916     NTSTATUS status;
    02917     PPNP_BUS_INFORMATION busInfo;
    02918
    02919     PAGED_CODE();
    02920
    02921     //
    02922     // Initialize the stack location to pass to IopSynchronousCall()
    02923     //
    02924
    02925     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    02926
    02927     //
    02928     // Set the function codes.
    02929     //
    02930
    02931     irpSp.MajorFunction = IRP_MJ_PNP;
    02932     irpSp.MinorFunction = IRP_MN_QUERY_BUS_INFORMATION;
    02933
    02934     //
    02935     // Make the call and return.
    02936     //
    02937
    02938     status = IopSynchronousCall(DeviceObject, &irpSp, &busInfo);
    02939     if (NT_SUCCESS(status)) {
    02940
    02941         if (busInfo == NULL) {
    02942
    02943             //
    02944             // The device driver LIED to us.  Bad, bad, bad device driver.
    02945             //
    02946
    02947             PDEVICE_NODE deviceNode;
    02948
    02949             deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode;
    02950
    02951             if (deviceNode && deviceNode->ServiceName.Buffer) {
    02952
    02953                 DbgPrint("*** IopQueryPnpBusInformation - Driver %wZ returned STATUS_SUCCESS\n", &deviceNode->ServiceName);
    02954                 DbgPrint("    for IRP_MN_QUERY_BUS_INFORMATION, and a NULL POINTER.\n");
    02955             }
    02956
    02957             ASSERT(busInfo != NULL);
    02958
    02959         } else {
    02960             if (ARGUMENT_PRESENT(InterfaceGuid)) {
    02961                 *InterfaceGuid = busInfo->BusTypeGuid;
    02962             }
    02963             if (ARGUMENT_PRESENT(InterfaceType)) {
    02964                 *InterfaceType = busInfo->LegacyBusType;
    02965             }
    02966             if (ARGUMENT_PRESENT(BusNumber)) {
    02967                 *BusNumber = busInfo->BusNumber;
    02968             }
    02969             ExFreePool(busInfo);
    02970         }
    02971     }
    02972     return status;
    02973 }

NTSTATUS IopQueryReconfiguration | ( | IN UCHAR | Request,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 2733 of file pnpirp.c.

References ASSERT, dummy(), IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_QUERY_STOP_DEVICE, IRP_MN_STOP_DEVICE, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), PAGED_CODE, and Request().

Referenced by IopRebalance(), and IopTestForReconfiguration().

    02740                    :
    02741
    02742     This routine queries the specified DeviceObject for the specified ResourceType
    02743     resource translator.
    02744
    02745 Parameters:
    02746
    02747     HandlerType - specifies Arbiter or Translator
    02748
    02749     DeviceObject - Supplies a pointer to the Device object to be queried.
    02750
    02751     ResourceType - Specifies the desired type of translator.
    02752
    02753     Interface - supplies a variable to receive the desired interface.
    02754
    02755 Return Value:
    02756
    02757     Status code that indicates whether or not the function was successful.
    02758
    02759 --*/
    02760 {
    02761     IO_STACK_LOCATION irpSp;
    02762     NTSTATUS status;
    02763     PVOID dummy;
    02764
    02765     PAGED_CODE();
    02766
    02767     ASSERT (Request == IRP_MN_QUERY_STOP_DEVICE ||
    02768             Request == IRP_MN_STOP_DEVICE ||
    02769             Request == IRP_MN_CANCEL_STOP_DEVICE);
    02770
    02771     //
    02772     // Initialize the stack location to pass to IopSynchronousCall()
    02773     //
    02774
    02775     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    02776
    02777     //
    02778     // Set the function codes.
    02779     //
    02780
    02781     irpSp.MajorFunction = IRP_MJ_PNP;
    02782     irpSp.MinorFunction = Request;
    02783
    02784     //
    02785     // Make the call and return.
    02786     //
    02787
    02788     status = IopSynchronousCall(DeviceObject, &irpSp, &dummy);
    02789     return status;
    02790 }

NTSTATUS IopQueryResourceHandlerInterface | ( | IN RESOURCE_HANDLER_TYPE | HandlerType,
|  | IN PDEVICE_OBJECT | DeviceObject,
|  | IN UCHAR | ResourceType,
|  | IN OUT PVOID * | Interface
| ) |

Definition at line 2617 of file pnpirp.c.

References DO_BUS_ENUMERATED_DEVICE, _DEVICE_OBJECT::DriverObject, dummy(), _DEVICE_NODE::DuplicatePDO, ExAllocatePool, ExFreePool(), IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_INTERFACE, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, _IO_STACK_LOCATION::Parameters, ResourceArbiter, ResourceLegacyDeviceDetection, ResourceTranslator, _INTERFACE::Size, USHORT, and _INTERFACE::Version.

Referenced by IopDuplicateDetection(), and IopSetupArbiterAndTranslators().

    02626                    :
    02627
    02628     This routine queries the specified DeviceObject for the specified ResourceType
    02629     resource translator.
    02630
    02631 Parameters:
    02632
    02633     HandlerType - specifies Arbiter or Translator
    02634
    02635     DeviceObject - Supplies a pointer to the Device object to be queried.
    02636
    02637     ResourceType - Specifies the desired type of translator.
    02638
    02639     Interface - supplies a variable to receive the desired interface.
    02640
    02641 Return Value:
    02642
    02643     Status code that indicates whether or not the function was successful.
    02644
    02645 --*/
    02646 {
    02647     IO_STACK_LOCATION irpSp;
    02648     NTSTATUS status;
    02649     PVOID dummy;
    02650     PINTERFACE interface;
    02651     USHORT size;
    02652     GUID interfaceType;
    02653     PDEVICE_NODE deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    02654
    02655     PAGED_CODE();
    02656
    02657     //
    02658     // If this device object is created by pnp mgr for legacy resource allocation,
    02659     // skip it.
    02660     //
    02661
    02662     if ((deviceNode->DuplicatePDO == (PDEVICE_OBJECT) DeviceObject->DriverObject) ||
    02663         !(DeviceObject->Flags & DO_BUS_ENUMERATED_DEVICE)) {
    02664         return STATUS_NOT_SUPPORTED;
    02665     }
    02666
    02667     switch (HandlerType) {
    02668     case ResourceTranslator:
    02669         size = sizeof(TRANSLATOR_INTERFACE) + 4;  // Pnptest
    02670         //size = sizeof(TRANSLATOR_INTERFACE);
    02671         interfaceType = GUID_TRANSLATOR_INTERFACE_STANDARD;
    02672         break;
    02673
    02674     case ResourceArbiter:
    02675         size = sizeof(ARBITER_INTERFACE);
    02676         interfaceType = GUID_ARBITER_INTERFACE_STANDARD;
    02677         break;
    02678
    02679     case ResourceLegacyDeviceDetection:
    02680         size = sizeof(LEGACY_DEVICE_DETECTION_INTERFACE);
    02681         interfaceType = GUID_LEGACY_DEVICE_DETECTION_STANDARD;
    02682         break;
    02683
    02684     default:
    02685         return STATUS_INVALID_PARAMETER;
    02686     }
    02687
    02688     interface = (PINTERFACE) ExAllocatePool(PagedPool, size);
    02689     if (interface == NULL) {
    02690         return STATUS_INSUFFICIENT_RESOURCES;
    02691     }
    02692
    02693     RtlZeroMemory(interface, size);
    02694     interface->Size = size;
    02695
    02696     //
    02697     // Initialize the stack location to pass to IopSynchronousCall()
    02698     //
    02699
    02700     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    02701
    02702     //
    02703     // Set the function codes.
    02704     //
    02705
    02706     irpSp.MajorFunction = IRP_MJ_PNP;
    02707     irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
    02708
    02709     //
    02710     // Set the pointer to the resource list
    02711     //
    02712
    02713     irpSp.Parameters.QueryInterface.InterfaceType = &interfaceType;
    02714     irpSp.Parameters.QueryInterface.Size = interface->Size;
    02715     irpSp.Parameters.QueryInterface.Version = interface->Version = 0;
    02716     irpSp.Parameters.QueryInterface.Interface = interface;
    02717     irpSp.Parameters.QueryInterface.InterfaceSpecificData = (PVOID) ResourceType;
    02718
    02719     //
    02720     // Make the call and return.
    02721     //
    02722
    02723     status = IopSynchronousCall(DeviceObject, &irpSp, &dummy);
    02724     if (NT_SUCCESS(status)) {
    02725         *Interface = interface;
    02726     } else {
    02727         ExFreePool(interface);
    02728     }
    02729     return status;
    02730 }

NTSTATUS IopQueryUniqueId | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | OUT PWCHAR * | UniqueId
| ) |

Definition at line 1820 of file pnpirp.c.

References BusQueryInstanceID, IopSynchronousCall(), IRP_MJ_PNP, IRP_MN_QUERY_ID, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and _IO_STACK_LOCATION::Parameters.

Referenced by IopProcessNewDeviceNode().

    01827                    :
    01828
    01829
    01830     This routine generates a unique id for the specified device object.
    01831
    01832 Parameters:
    01833
    01834     DeviceObject - Supplies the device object of the device being queried
    01835
    01836     UniqueId - Supplies a pointer to a variable to receive the returned Id.
    01837                This must be freed by the caller.
    01838
    01839     GloballyUnique - Indicates (from a previous call to query capabilities
    01840                      whether the id is globally unique.
    01841 Return Value:
    01842
    01843     NTSTATUS code.
    01844
    01845 --*/
    01846 {
    01847     IO_STACK_LOCATION irpSp;
    01848     NTSTATUS status;
    01849
    01850     PAGED_CODE();
    01851
    01852     *UniqueId = NULL;
    01853
    01854     //
    01855     // First ask for for InstanceId.
    01856     //
    01857
    01858     // Initialize the stack location to pass to IopSynchronousCall()
    01859     //
    01860
    01861     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    01862
    01863     //
    01864     // Set the function codes.
    01865     //
    01866
    01867     irpSp.MajorFunction = IRP_MJ_PNP;
    01868     irpSp.MinorFunction = IRP_MN_QUERY_ID;
    01869
    01870     //
    01871     // Set the pointer to the resource list
    01872     //
    01873
    01874     irpSp.Parameters.QueryId.IdType = BusQueryInstanceID;
    01875
    01876     //
    01877     // Make the call and return.
    01878     //
    01879
    01880     status = IopSynchronousCall(DeviceObject, &irpSp, UniqueId);
    01881
    01882     if (!NT_SUCCESS(status)) {
    01883         *UniqueId = NULL;
    01884     }
    01885
    01886     return status;
    01887
    01888 }

NTSTATUS IopRemoveDevice | ( | IN PDEVICE_OBJECT | TargetDevice,
|  | IN ULONG | IrpMinorCode
| ) |

Definition at line 927 of file pnpirp.c.

References ASSERT, ASSERTMSG, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, DNF_ADDED, DNF_LEGACY_DRIVER, DNF_NEED_ENUMERATION_ONLY, DNF_NEED_QUERY_IDS, DNF_STARTED, DNUF_NOT_DISABLEABLE, dummy(), FALSE, IopDecDisableableDepends(), IopFindMountableDevice(), IopInvalidateVolumesForDevice(), IopLockMountedDeviceForRemove(), IopSynchronousCall(), IopUncacheInterfaceInformation(), IopUnlockMountedDeviceForRemove(), IRP_MJ_PNP, IRP_MN_CANCEL_REMOVE_DEVICE, IRP_MN_EJECT, IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_REMOVE_DEVICE, IRP_MN_SURPRISE_REMOVAL, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, TRUE, and _DEVICE_NODE::UserFlags.

Referenced by IopDeleteLockedDeviceNode(), IopDisableDevice(), and IopProcessNewDeviceNode().

    00934                    :
    00935
    00936     This function sends a requested DeviceRemoval related irp to the top level device
    00937     object which roots on TargetDevice.  If there is a VPB associated with the
    00938     TargetDevice, the corresponding filesystem's VDO will be used.  Otherwise
    00939     the irp will be sent directly to the target device/ or its assocated device
    00940     object.
    00941
    00942 Parameters:
    00943
    00944     TargetDevice - Supplies the device object of the device being removed.
    00945
    00946     Operation - Specifies the operation requested.
    00947         The following IRP codes are used with IRP_MJ_DEVICE_CHANGE for removing
    00948         devices:
    00949             IRP_MN_QUERY_REMOVE_DEVICE
    00950             IRP_MN_CANCEL_REMOVE_DEVICE
    00951             IRP_MN_REMOVE_DEVICE
    00952             IRP_MN_EJECT
    00953 Return Value:
    00954
    00955     NTSTATUS code.
    00956
    00957 --*/
    00958 {
    00959     PDEVICE_OBJECT deviceObject;
    00960     PIRP irp;
    00961     IO_STACK_LOCATION irpSp;
    00962     NTSTATUS status;
    00963
    00964     BOOLEAN isMountable = FALSE;
    00965     PDEVICE_OBJECT mountedDevice;
    00966
    00967     PVOID dummy;
    00968     LOCK_MOUNTABLE_DEVICE_CONTEXT lockContext;
    00969
    00970     PAGED_CODE();
    00971
    00972     ASSERT(IrpMinorCode == IRP_MN_QUERY_REMOVE_DEVICE ||
    00973            IrpMinorCode == IRP_MN_CANCEL_REMOVE_DEVICE ||
    00974            IrpMinorCode == IRP_MN_REMOVE_DEVICE ||
    00975            IrpMinorCode == IRP_MN_SURPRISE_REMOVAL ||
    00976            IrpMinorCode == IRP_MN_EJECT);
    00977
    00978     if (IrpMinorCode == IRP_MN_REMOVE_DEVICE ||
    00979         IrpMinorCode == IRP_MN_QUERY_REMOVE_DEVICE) {
    00980         IopUncacheInterfaceInformation(TargetDevice);
    00981     }
    00982
    00983     //
    00984     // Initialize the stack location to pass to IopSynchronousCall()
    00985     //
    00986
    00987     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    00988
    00989     irpSp.MajorFunction = IRP_MJ_PNP;
    00990     irpSp.MinorFunction = (UCHAR)IrpMinorCode;
    00991
    00992     //
    00993     // BUGBUG - this should probably go at a higher level but then it goes
    00994     // in way too many places.  The only thing we do to the VPB is make sure
    00995     // that it won't go away while the operation is in the file system and
    00996     // that no one new can mount on the device if the FS decides to bail out.
    00997     //
    00998
    00999     //
    01000     // Check to see if there's a VPB anywhere in the device stack.  If there
    01001     // is then we'll have to lock the stack.
    01002     //
    01003
    01004     mountedDevice = IopFindMountableDevice(TargetDevice);
    01005
    01006     if (mountedDevice != NULL) {
    01007
    01008         //
    01009         // This routine will cause any mount operations on the VPB to fail.
    01010         // It will also release the VPB spinlock.
    01011         //
    01012
    01013         mountedDevice = IopLockMountedDeviceForRemove(TargetDevice,
    01014                                                       IrpMinorCode,
    01015                                                       &lockContext);
    01016
    01017         isMountable = TRUE;
    01018
    01019     } else {
    01020         ASSERTMSG("Mass storage device does not have VPB - this is odd",
    01021                   !((TargetDevice->Type == FILE_DEVICE_DISK) ||
    01022                     (TargetDevice->Type == FILE_DEVICE_CD_ROM) ||
    01023                     (TargetDevice->Type == FILE_DEVICE_TAPE) ||
    01024                     (TargetDevice->Type == FILE_DEVICE_VIRTUAL_DISK)));
    01025
    01026         mountedDevice = TargetDevice;
    01027     }
    01028
    01029     //
    01030     // Make the call and return.
    01031     //
    01032
    01033     if (IrpMinorCode == IRP_MN_SURPRISE_REMOVAL || IrpMinorCode == IRP_MN_REMOVE_DEVICE) {
    01034         //
    01035         // if device was not disableable, we cleanup the tree
    01036         // and debug-trace that we surprise-removed a non-disableable device
    01037         //
    01038         PDEVICE_NODE deviceNode = TargetDevice->DeviceObjectExtension->DeviceNode;
    01039
    01040         if (deviceNode->UserFlags & DNUF_NOT_DISABLEABLE) {
    01041             //
    01042             // this device was marked as disableable, update the depends
    01043             // before this device disappears
    01044             // (by momentarily marking this node as disableable)
    01045             //
    01046             deviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
    01047             IopDecDisableableDepends(deviceNode);
    01048         }
    01049     }
    01050
    01051     status = IopSynchronousCall(mountedDevice, &irpSp, &dummy);
    01052
    01053     if (isMountable) {
    01054
    01055         IopUnlockMountedDeviceForRemove(TargetDevice,
    01056                                         IrpMinorCode,
    01057                                         &lockContext);
    01058
    01059         //
    01060         // Succesful query should follow up with invalidation of all volumes
    01061         // which have been on this device but which are not currently mounted.
    01062         //
    01063
    01064         if (IrpMinorCode == IRP_MN_QUERY_REMOVE_DEVICE && NT_SUCCESS( status )) {
    01065
    01066             status = IopInvalidateVolumesForDevice( TargetDevice );
    01067         }
    01068     }
    01069
    01070     if (IrpMinorCode == IRP_MN_REMOVE_DEVICE) {
    01071         ((PDEVICE_NODE)TargetDevice->DeviceObjectExtension->DeviceNode)->Flags &=
    01072             ~(DNF_ADDED | DNF_STARTED | DNF_LEGACY_DRIVER | DNF_NEED_QUERY_IDS | DNF_NEED_ENUMERATION_ONLY);
    01073     }
    01074
    01075     return status;
    01076 }

VOID IopStartDevice | ( | IN PDEVICE_OBJECT | DeviceObject | ) |

Definition at line 510 of file pnpirp.c.

References ASSERT, _DEVICE_COMPLETION_CONTEXT::DeviceNode, DNF_NEED_ENUMERATION_ONLY, DNF_RESOURCE_REPORTED, DNF_START_REQUEST_PENDING, DNF_STARTED, DNF_STOPPED, DOCK_ARRIVING, DOCK_NOTDOCKDEVICE, DOCK_QUIESCENT, _DEVICE_NODE::DockInfo, dummy(), ExAllocatePool, ExGetCurrentResourceThread, FALSE, _DEVICE_NODE::Flags, IopAcquireEnumerationLock, IopAsynchronousCall(), IopDeviceStartComplete(), IopDoDeferredSetInterfaceState(), IopDoesDevNodeHaveProblem, IopHardwareProfileBeginTransition(), IopHardwareProfileCancelTransition(), IopHardwareProfileCommitStartedDock(), IopHardwareProfileMarkDock(), IopHardwareProfileQueryChange(), IopPnPSpinLock, IopRequestDeviceRemoval(), IopSetDevNodeProblem, IopSynchronousCall(), IopUncacheInterfaceInformation(), IRP_MJ_PNP, IRP_MN_START_DEVICE, _DEVICE_COMPLETION_CONTEXT::IrpMinorCode, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, _IO_STACK_LOCATION::Parameters, PDEVICE_COMPLETION_CONTEXT, _DEVICE_NODE::PhysicalDeviceObject, PnpAsyncOk, PpSetTargetDeviceRemove(), PROFILE_PERHAPS_IN_PNPEVENT, _DEVICE_NODE::ResourceList, _DEVICE_NODE::ResourceListTranslated, SAVE_FAILURE_INFO, _DEVICE_COMPLETION_CONTEXT::Thread, and TRUE.

Referenced by IopReallocateResources(), IopRebalance(), and IopStartAndEnumerateDevice().

    00516                    :
    00517
    00518     This function sends a start device irp to the top level device
    00519     object which roots on DeviceObject.
    00520
    00521 Parameters:
    00522
    00523     DeviceObject - Supplies the pointer to the device object of the device
    00524                    being removed.
    00525
    00526 Return Value:
    00527
    00528     NTSTATUS code.
    00529
    00530 --*/
    00531
    00532 {
    00533     IO_STACK_LOCATION irpSp;
    00534     PVOID dummy;
    00535     PDEVICE_NODE deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    00536     PDEVICE_COMPLETION_CONTEXT completionContext;
    00537     NTSTATUS status;
    00538     PNP_VETO_TYPE  vetoType;
    00539
    00540 //    PAGED_CODE();
    00541
    00542     //
    00543     // Initialize the stack location to pass to IopSynchronousCall()
    00544     //
    00545
    00546     RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
    00547
    00548     //
    00549     // Set the function codes.
    00550     //
    00551
    00552     irpSp.MajorFunction = IRP_MJ_PNP;
    00553     irpSp.MinorFunction = IRP_MN_START_DEVICE;
    00554
    00555     //
    00556     // Set the pointers for the raw and translated resource lists
    00557     //
    00558
    00559     if (!(deviceNode->Flags & DNF_RESOURCE_REPORTED)) {
    00560         irpSp.Parameters.StartDevice.AllocatedResources = deviceNode->ResourceList;
    00561         irpSp.Parameters.StartDevice.AllocatedResourcesTranslated = deviceNode->ResourceListTranslated;
    00562     }
    00563
    00564     if (!(deviceNode->Flags & DNF_STOPPED)) {
    00565         IopUncacheInterfaceInformation(DeviceObject);
    00566     }
    00567
    00568     if (PnpAsyncOk) {
    00569
    00570         //
    00571         // ADRIAO BUGBUG 11/18/98 -
    00572         //     The dock code has not been duplicated in the async case, but as
    00573         // PnpAsync support is totally broken and disabled anyway, this should
    00574         // not matter right now.
    00575         //
    00576         ASSERT(0);
    00577         completionContext = (PDEVICE_COMPLETION_CONTEXT) ExAllocatePool(
    00578                               NonPagedPool,
    00579                               sizeof(DEVICE_COMPLETION_CONTEXT));
    00580         if (completionContext == NULL) {
    00581             return;   // BUGBUG - Should try it again *explicitly*
    00582         }
    00583
    00584         completionContext->DeviceNode = deviceNode;
    00585         completionContext->IrpMinorCode = IRP_MN_START_DEVICE;
    00586         completionContext->Thread = ExGetCurrentResourceThread();
    00587
    00588         //
    00589         // Make the call and return.
    00590         //
    00591
    00592         IopAcquireEnumerationLock(NULL);  // To block IopAcquireTreeLock();
    00593         status = IopAsynchronousCall(DeviceObject, &irpSp, completionContext, IopDeviceStartComplete);
    00594         if (status == STATUS_PENDING) {
    00595
    00596             KIRQL oldIrql;
    00597
    00598             //
    00599             // Set DNF_START_REQUEST_PENDING flag such that the completion routine knows it
    00600             // needs to request enumeration when the start completed successfully.
    00601             //
    00602
    00603             ExAcquireSpinLock(&IopPnPSpinLock, &oldIrql);
    00604
    00605             if (!(IopDoesDevNodeHaveProblem(deviceNode) || (deviceNode->Flags & DNF_STARTED))) {
    00606                 deviceNode->Flags |= DNF_START_REQUEST_PENDING;
    00607             }
    00608             ExReleaseSpinLock(&IopPnPSpinLock, oldIrql);
    00609         }
    00610     } else {
    00611
    00612         if ((deviceNode->Flags & DNF_STOPPED)||
    00613             (deviceNode->DockInfo.DockStatus == DOCK_NOTDOCKDEVICE)) {
    00614
    00615
    00616             //
    00617             // This is either the rebalance case in which we are restarting a
    00618             // temporarily stopped device, or we are starting a non-dock device,
    00619             // and it was previously off.
    00620             //
    00621             status = IopSynchronousCall(DeviceObject, &irpSp, &dummy);
    00622
    00623         } else {
    00624
    00625             //
    00626             // This is a dock so we a little bit of work before starting it.
    00627             // Take the profile change semaphore. We do this whenever a dock
    00628             // is in our list, even if no query is going to occur.
    00629             //
    00630             IopHardwareProfileBeginTransition(FALSE);
    00631
    00632             //
    00633             // Tell the profile code what dock device object may be bringing the
    00634             // new hardware profile online.
    00635             //
    00636             IopHardwareProfileMarkDock(deviceNode, DOCK_ARRIVING);
    00637
    00638             //
    00639             // Ask everyone if this is really a good idea right now. Note that
    00640             // PiProcessStart calls IopNewDevice calls IopStartAndEnumerateDevice
    00641             // who calls this function on that thread. Therefore we may indded be
    00642             // in an event, although this would probably be a fairly rare event
    00643             // for a dock.
    00644             //
    00645             status = IopHardwareProfileQueryChange(
    00646                 FALSE,
    00647                 PROFILE_PERHAPS_IN_PNPEVENT,
    00648                 &vetoType,
    00649                 NULL
    00650                 );
    00651
    00652             if (NT_SUCCESS(status)) {
    00653
    00654                 status = IopSynchronousCall(DeviceObject, &irpSp, &dummy);
    00655             }
    00656
    00657             if (NT_SUCCESS(status)) {
    00658
    00659                 //
    00660                 // Commit the current Hardware Profile as necessary.
    00661                 //
    00662                 IopHardwareProfileCommitStartedDock(deviceNode);
    00663
    00664             } else {
    00665
    00666                 IopHardwareProfileCancelTransition();
    00667             }
    00668         }
    00669
    00670         if (!NT_SUCCESS(status)) {
    00671             ULONG Problem = CM_PROB_FAILED_START;
    00672
    00673             SAVE_FAILURE_INFO(deviceNode, status);
    00674
    00675             //
    00676             // Handle certain problems determined by the status code
    00677             //
    00678             switch (status) {
    00679                 case STATUS_PNP_REBOOT_REQUIRED:
    00680                     Problem = CM_PROB_NEED_RESTART;
    00681                     break;
    00682
    00683                 default:
    00684                     Problem = CM_PROB_FAILED_START;
    00685             }
    00686             IopSetDevNodeProblem(deviceNode, Problem);
    00687
    00688             if (deviceNode->DockInfo.DockStatus == DOCK_NOTDOCKDEVICE) {
    00689
    00690                 IopRequestDeviceRemoval(deviceNode->PhysicalDeviceObject, CM_PROB_FAILED_START);
    00691             } else {
    00692
    00693                 ASSERT(deviceNode->DockInfo.DockStatus == DOCK_QUIESCENT);
    00694
    00695                 PpSetTargetDeviceRemove( deviceNode->PhysicalDeviceObject,
    00696                                          FALSE,
    00697                                          TRUE,
    00698                                          TRUE,
    00699                                          CM_PROB_DEVICE_NOT_THERE,
    00700                                          NULL,
    00701                                          NULL,
    00702                                          NULL,
    00703                                          NULL);
    00704             }
    00705
    00706         } else {
    00707
    00708             IopDoDeferredSetInterfaceState(deviceNode);
    00709
    00710             deviceNode->Flags |= DNF_STARTED;
    00711
    00712             if (deviceNode->Flags & DNF_STOPPED) {
    00713
    00714                 //
    00715                 // If the start is initiated by rebalancing, do NOT do enumeration
    00716                 //
    00717
    00718                 deviceNode->Flags &= ~DNF_STOPPED;
    00719
    00720             } else {
    00721
    00722                 deviceNode->Flags |= DNF_NEED_ENUMERATION_ONLY;
    00723
    00724             }
    00725         }
    00726     }
    00727 }

NTSTATUS IopSynchronousCall | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIO_STACK_LOCATION | TopStackLocation,
|  | OUT PVOID * | Information
| ) |

Definition at line 381 of file pnpirp.c.

References Executive, FALSE, IoAllocateIrp(), IoCallDriver, IoGetAttachedDevice(), IoGetNextIrpStackLocation, IopQueueThreadIrp, _IRP::IoStatus, IRP_SYSTEM_RESTRICTED, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NTSTATUS(), NULL, PAGED_CODE, PnpIrpStatusTracking, PsGetCurrentThread, SPECIALIRP_WATERMARK_IRP, _DEVICE_OBJECT::StackSize, _IRP::Tail, _IRP::UserEvent, _IRP::UserIosb, and VOID().

Referenced by IoFreeDumpStack(), IopEnumerateDevice(), IopGetDumpStack(), IopGetRelatedTargetDevice(), IopProcessNewDeviceNode(), IopQueryCompatibleIds(), IopQueryDeviceCapabilities(), IopQueryDeviceId(), IopQueryDeviceRelations(), IopQueryDeviceResources(), IopQueryDeviceSerialNumber(), IopQueryDeviceState(), IopQueryDockRemovalInterface(), IopQueryLegacyBusInformation(), IopQueryPnpBusInformation(), IopQueryReconfiguration(), IopQueryResourceHandlerInterface(), IopQueryUniqueId(), IopRemoveDevice(), and IopStartDevice().

    00389                    :
    00390
    00391     This function sends a synchronous irp to the top level device
    00392     object which roots on DeviceObject.
    00393
    00394 Parameters:
    00395
    00396     DeviceObject - Supplies the device object of the device being removed.
    00397
    00398     TopStackLocation - Supplies a pointer to the parameter block for the irp.
    00399
    00400     Information - Supplies a pointer to a variable to receive the returned
    00401                   information of the irp.
    00402
    00403 Return Value:
    00404
    00405     NTSTATUS code.
    00406
    00407 --*/
    00408
    00409 {
    00410     PIRP irp;
    00411     PIO_STACK_LOCATION irpSp;
    00412     IO_STATUS_BLOCK statusBlock;
    00413     KEVENT event;
    00414     NTSTATUS status;
    00415     PULONG_PTR returnInfo = (PULONG_PTR)Information;
    00416     PDEVICE_OBJECT deviceObject;
    00417
    00418     PAGED_CODE();
    00419
    00420     //
    00421     // Get a pointer to the topmost device object in the stack of devices,
    00422     // beginning with the deviceObject.
    00423     //
    00424
    00425     deviceObject = IoGetAttachedDevice(DeviceObject);
    00426
    00427     //
    00428     // Begin by allocating the IRP for this request.  Do not charge quota to
    00429     // the current process for this IRP.
    00430     //
    00431
    00432     irp = IoAllocateIrp(deviceObject->StackSize, FALSE);
    00433     if (irp == NULL){
    00434
    00435         return STATUS_INSUFFICIENT_RESOURCES;
    00436     }
    00437
    00438     SPECIALIRP_WATERMARK_IRP(irp, IRP_SYSTEM_RESTRICTED);
    00439
    00440     //
    00441     // Initialize it to failure.
    00442     //
    00443
    00444     irp->IoStatus.Status = statusBlock.Status = STATUS_NOT_SUPPORTED;
    00445     irp->IoStatus.Information = statusBlock.Information = 0;
    00446
    00447     //
    00448     // Set the pointer to the status block and initialized event.
    00449     //
    00450
    00451     KeInitializeEvent( &event,
    00452                        SynchronizationEvent,
    00453                        FALSE );
    00454
    00455     irp->UserIosb = &statusBlock;
    00456     irp->UserEvent = &event;
    00457
    00458     //
    00459     // Set the address of the current thread
    00460     //
    00461
    00462     irp->Tail.Overlay.Thread = PsGetCurrentThread();
    00463
    00464     //
    00465     // Queue this irp onto the current thread
    00466     //
    00467
    00468     IopQueueThreadIrp(irp);
    00469
    00470     //
    00471     // Get a pointer to the stack location of the first driver which will be
    00472     // invoked.  This is where the function codes and parameters are set.
    00473     //
    00474
    00475     irpSp = IoGetNextIrpStackLocation(irp);
    00476
    00477     //
    00478     // Copy in the caller-supplied stack location contents
    00479     //
    00480
    00481     *irpSp = *TopStackLocation;
    00482
    00483     //
    00484     // Call the driver
    00485     //
    00486
    00487     status = IoCallDriver(deviceObject, irp);
    00488
    00489     PnpIrpStatusTracking(status, TopStackLocation->MinorFunction, deviceObject);
    00490
    00491     //
    00492     // If a driver returns STATUS_PENDING, we will wait for it to complete
    00493     //
    00494
    00495     if (status == STATUS_PENDING) {
    00496         (VOID) KeWaitForSingleObject( &event,
    00497                                       Executive,
    00498                                       KernelMode,
    00499                                       FALSE,
    00500                                       (PLARGE_INTEGER) NULL );
    00501         status = statusBlock.Status;
    00502     }
    00503
    00504     *returnInfo = (ULONG_PTR) statusBlock.Information;
    00505
    00506     return status;
    00507 }

VOID IopUncacheInterfaceInformation | ( | IN PDEVICE_OBJECT | DeviceObject | ) |

Definition at line 191 of file pnpirp.c.

References _INTERFACE::Context, _DEVICE_NODE::DeviceArbiterList, _DEVICE_NODE::DeviceTranslatorList, ExFreePool(), _INTERFACE::InterfaceDereference, _DEVICE_NODE::NoArbiterMask, _DEVICE_NODE::NoTranslatorMask, _DEVICE_NODE::QueryArbiterMask, _DEVICE_NODE::QueryTranslatorMask, and _PI_RESOURCE_TRANSLATOR_ENTRY::TranslatorInterface.

Referenced by IopDestroyDeviceNode(), IopInvalidateDeviceStateWorker(), IopRemoveDevice(), and IopStartDevice().

    00197                    :
    00198
    00199     This function removes all the cached translators and arbiters information
    00200     from the device object.
    00201
    00202 Parameters:
    00203
    00204     DeviceObject - Supplies the device object of the device being removed.
    00205
    00206 Return Value:
    00207
    00208     NTSTATUS code.
    00209
    00210 --*/
    00211
    00212 {
    00213     PDEVICE_NODE deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    00214     PLIST_ENTRY listHead, nextEntry, entry;
    00215     PPI_RESOURCE_TRANSLATOR_ENTRY handlerEntry;
    00216     PINTERFACE interface;
    00217
    00218     //
    00219     // Dereference all the arbiters on this PDO.
    00220     //
    00221
    00222     listHead = &deviceNode->DeviceArbiterList;
    00223     nextEntry = listHead->Flink;
    00224     while (nextEntry != listHead) {
    00225         entry = nextEntry;
    00226         nextEntry = nextEntry->Flink;
    00227         handlerEntry = CONTAINING_RECORD(entry, PI_RESOURCE_TRANSLATOR_ENTRY, DeviceTranslatorList);
    00228         if (interface = (PINTERFACE)handlerEntry->TranslatorInterface) {
    00229             (interface->InterfaceDereference)(interface->Context);
    00230             ExFreePool(interface);
    00231         }
    00232         ExFreePool(entry);
    00233     }
    00234     InitializeListHead(&deviceNode->DeviceArbiterList);
    00235
    00236     //
    00237     // Dereference all the translators on this PDO.
    00238     //
    00239
    00240     listHead = &deviceNode->DeviceTranslatorList;
    00241     nextEntry = listHead->Flink;
    00242     while (nextEntry != listHead) {
    00243         entry = nextEntry;
    00244         nextEntry = nextEntry->Flink;
    00245         handlerEntry = CONTAINING_RECORD(entry, PI_RESOURCE_TRANSLATOR_ENTRY, DeviceTranslatorList);
    00246         if (interface = (PINTERFACE)handlerEntry->TranslatorInterface) {
    00247             (interface->InterfaceDereference)(interface->Context);
    00248             ExFreePool(interface);
    00249         }
    00250         ExFreePool(entry);
    00251     }
    00252
    00253     InitializeListHead(&deviceNode->DeviceTranslatorList);
    00254
    00255     deviceNode->NoArbiterMask = 0;
    00256     deviceNode->QueryArbiterMask = 0;
    00257     deviceNode->NoTranslatorMask = 0;
    00258     deviceNode->QueryTranslatorMask = 0;
    00259 }

VOID IopUnlockMountedDeviceForRemove | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN ULONG | IrpMinorCode,
|  | IN PLOCK_MOUNTABLE_DEVICE_CONTEXT | Context
| ) |

Definition at line 1233 of file pnpirp.c.

References _DEVICE_OBJECT::AttachedDevice, _DEVICE_OBJECT::DeviceLock, Executive, FALSE, _VPB::Flags, IO_NO_INCREMENT, IoAcquireVpbSpinLock(), IopDatabaseLock, IoReleaseVpbSpinLock(), IRP_MN_REMOVE_DEVICE, KernelMode, KeSetEvent(), KeWaitForSingleObject(), NULL, _DEVICE_OBJECT::Vpb, and VPB_REMOVE_PENDING.

Referenced by IopRemoveDevice().

    01238 {
    01239     PVPB vpb;
    01240     BOOLEAN removePendingSet;
    01241
    01242     PDEVICE_OBJECT device = DeviceObject;
    01243
    01244     do {
    01245
    01246         KIRQL oldIrql;
    01247
    01248         //
    01249         // Walk up each device object in the stack.  For each one, if a VPB
    01250         // exists, grab the database resource exclusive followed by the
    01251         // device lock.  Then acquire the Vpb spinlock and perform the
    01252         // appropriate magic on the device object.
    01253         //
    01254
    01255         //
    01256         // NOTE - It's unfortunate that the locking order includes grabing
    01257         // the device specific lock first followed by the global lock.
    01258         //
    01259
    01260         if (device->Vpb != NULL) {
    01261
    01262             //
    01263             // Grab the device lock.  This will ensure that there are no mount
    01264             // or verify operations in progress, which in turn will ensure
    01265             // that any mounted file system won't go away.
    01266             //
    01267
    01268             KeWaitForSingleObject(&(device->DeviceLock),
    01269                                   Executive,
    01270                                   KernelMode,
    01271                                   FALSE,
    01272                                   NULL);
    01273
    01274             //
    01275             // Now decrement the reference count in the VPB.  If the remove
    01276             // pending flag has been set in the VPB (if this is a QUERY or a
    01277             // REMOVE) then even on a dismount no new file system will be
    01278             // allowed onto the device.
    01279             //
    01280
    01281             IoAcquireVpbSpinLock(&oldIrql);
    01282
    01283             if (IrpMinorCode == IRP_MN_REMOVE_DEVICE) {
    01284
    01285                 device->Vpb->Flags &= ~VPB_REMOVE_PENDING;
    01286             }
    01287
    01288             IoReleaseVpbSpinLock(oldIrql);
    01289
    01290             KeSetEvent(&(device->DeviceLock), IO_NO_INCREMENT, FALSE);
    01291         }
    01292
    01293         //
    01294         // Continue up the chain until we know we hit the device the fs
    01295         // mounted on, if any.
    01296         //
    01297
    01298         if (Context->MountedDevice == device) {
    01299
    01300             break;
    01301
    01302         } else {
    01303
    01304             ExAcquireFastLock( &IopDatabaseLock, &oldIrql );
    01305             device = device->AttachedDevice;
    01306             ExReleaseFastLock( &IopDatabaseLock, oldIrql );
    01307         }
    01308
    01309     } while (device != NULL);
    01310
    01311     return;
    01312 }

## Variable Documentation

PCHAR IrpName[]

Initial value:

     {
        "IRP_MN_START_DEVICE - ",
        "IRP_MN_QUERY_REMOVE_DEVICE - ",
        "IRP_MN_REMOVE_DEVICE - ",
        "IRP_MN_CANCEL_REMOVE_DEVICE - ",
        "IRP_MN_STOP_DEVICE - ",
        "IRP_MN_QUERY_STOP_DEVICE - ",
        "IRP_MN_CANCEL_STOP_DEVICE - ",
        "IRP_MN_QUERY_DEVICE_RELATIONS - ",
        "IRP_MN_QUERY_INTERFACE - ",
        "IRP_MN_QUERY_CAPABILITIES - ",
        "IRP_MN_QUERY_RESOURCES - ",
        "IRP_MN_QUERY_RESOURCE_REQUIREMENTS - ",
        "IRP_MN_QUERY_DEVICE_TEXT - ",
        "IRP_MN_FILTER_RESOURCE_REQUIREMENTS - ",
        "INVALID_IRP_CODE - ",
        "IRP_MN_READ_CONFIG - ",
        "IRP_MN_WRITE_CONFIG - ",
        "IRP_MN_EJECT - ",
        "IRP_MN_SET_LOCK - ",
        "IRP_MN_QUERY_ID - ",
        "IRP_MN_QUERY_PNP_DEVICE_STATE - ",
        "IRP_MN_QUERY_BUS_INFORMATION - ",
        "IRP_MN_DEVICE_USAGE_NOTIFICATION - ",
        NULL
    }

Definition at line 37 of file pnpirp.c.

ULONG PnpIrpMask

| Definition at line 36 of file pnpirp.c.