diff --git a/reactos/Makefile b/reactos/Makefile index 0610e2800b8..ac3f3f03637 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -11,7 +11,7 @@ include $(PATH_TO_TOP)/rules.mak # COMPONENTS = iface_native iface_additional hallib ntoskrnl HALS = halx86 -BUS = acpi isapnp +BUS = acpi isapnp pci DLLS = ntdll kernel32 advapi32 crtdll msvcrt fmifs gdi32 msafd \ user32 oleaut32 secur32 shell32 ws2_32 version SUBSYS = smss win32k csrss diff --git a/reactos/include/ddk/iofuncs.h b/reactos/include/ddk/iofuncs.h index a01600df2c9..42066d718c7 100644 --- a/reactos/include/ddk/iofuncs.h +++ b/reactos/include/ddk/iofuncs.h @@ -1,6 +1,6 @@ #ifndef _INCLUDE_DDK_IOFUNCS_H #define _INCLUDE_DDK_IOFUNCS_H -/* $Id: iofuncs.h,v 1.25 2001/09/05 09:21:09 ekohl Exp $ */ +/* $Id: iofuncs.h,v 1.26 2001/09/16 13:19:31 chorns Exp $ */ /* --- EXPORTED BY NTOSKRNL --- */ @@ -625,6 +625,10 @@ IoGetConfigurationInformation ( ((Irp)->Tail.Overlay.CurrentStackLocation) */ +#define IoSetNextIrpStackLocation(Irp) { \ + (Irp)->CurrentLocation--; \ + (Irp)->Tail.Overlay.CurrentStackLocation--; } + #define IoCopyCurrentIrpStackLocationToNext(Irp) { \ PIO_STACK_LOCATION IrpSp; \ PIO_STACK_LOCATION NextIrpSp; \ @@ -634,6 +638,10 @@ IoGetConfigurationInformation ( FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); \ NextIrpSp->Control = 0; } +#define IoSkipCurrentIrpStackLocation(Irp) \ + (Irp)->CurrentLocation++; \ + (Irp)->Tail.Overlay.CurrentStackLocation++; + struct _EPROCESS* STDCALL IoGetCurrentProcess ( diff --git a/reactos/install.bat b/reactos/install.bat index f83135dffdc..303f824866b 100644 --- a/reactos/install.bat +++ b/reactos/install.bat @@ -25,6 +25,7 @@ copy services\fs\ms\msfs.sys %ROS_INSTALL%\system32\drivers copy services\fs\np\npfs.sys %ROS_INSTALL%\system32\drivers copy services\bus\acpi\acpi.sys %ROS_INSTALL%\system32\drivers copy services\bus\isapnp\isapnp.sys %ROS_INSTALL%\system32\drivers +copy services\bus\pci\pci.sys %ROS_INSTALL%\system32\drivers copy services\dd\ide\ide.sys %ROS_INSTALL%\system32\drivers copy services\dd\floppy\floppy.sys %ROS_INSTALL%\system32\drivers copy services\input\keyboard\keyboard.sys %ROS_INSTALL%\system32\drivers diff --git a/reactos/lib/ntdll/rtl/registry.c b/reactos/lib/ntdll/rtl/registry.c index c3aed9d6628..e6d98e2591e 100644 --- a/reactos/lib/ntdll/rtl/registry.c +++ b/reactos/lib/ntdll/rtl/registry.c @@ -1,4 +1,4 @@ -/* $Id: registry.c,v 1.7 2001/09/01 15:36:43 chorns Exp $ +/* $Id: registry.c,v 1.8 2001/09/16 13:19:31 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -582,7 +582,7 @@ RtlpGetRegistryHandle(ULONG RelativeTo, } - if (Path[0] != L'\\') + if ((RelativeTo == RTL_REGISTRY_ABSOLUTE) || (Path[0] != L'\\')) { RtlAppendUnicodeToString(&KeyName, Path); diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index 0ff8574508a..9f26c597b80 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -210,6 +210,7 @@ NtEnumerateKey ( NULL); if (!NT_SUCCESS(Status)) { + DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status); return Status; } @@ -223,6 +224,7 @@ NtEnumerateKey ( if (RegistryFile == CmiVolatileFile) { ObDereferenceObject (KeyObject); + DPRINT("No more volatile entries\n"); return STATUS_NO_MORE_ENTRIES; } else @@ -241,6 +243,7 @@ NtEnumerateKey ( if(Index >= KeyBlock->NumberOfSubKeys) { ObDereferenceObject (KeyObject); + DPRINT("No more non-volatile entries\n"); return STATUS_NO_MORE_ENTRIES; } SubKeyBlock = CurKey->KeyBlock; @@ -256,6 +259,7 @@ NtEnumerateKey ( if (SubKeyBlock == NULL) { ObDereferenceObject (KeyObject); + DPRINT("No more entries\n"); return STATUS_NO_MORE_ENTRIES; } @@ -364,6 +368,8 @@ NtEnumerateKey ( CmiReleaseBlock(RegistryFile, SubKeyBlock); ObDereferenceObject (KeyObject); + DPRINT("Returning status %x\n", Status); + return Status; } diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index 1f91f99b120..9642171cead 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -126,12 +126,12 @@ CmiCreateRegistry(PWSTR Filename) DWORD FreeOffset; int i, j; BLOCK_OFFSET BlockOffset; -DPRINT1("CmiCreateRegistry() Filename '%S'\n", Filename); +DPRINT("CmiCreateRegistry() Filename '%S'\n", Filename); RegistryFile = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_FILE)); -CHECKPOINT1; + if (RegistryFile == NULL) return NULL; -CHECKPOINT1; + if (Filename != NULL) { UNICODE_STRING TmpFileName; @@ -219,7 +219,7 @@ CHECKPOINT1; if (RegistryFile->BlockList[0] == NULL) { // Status = STATUS_INSUFFICIENT_RESOURCES; - DPRINT1("error allocating %d bytes for registry\n" + DPRINT("error allocating %d bytes for registry\n" ,RegistryFile->FileSize-4096); ZwClose(FileHandle); return NULL; @@ -232,7 +232,7 @@ CHECKPOINT1; ZwClose(FileHandle); if (!NT_SUCCESS(Status)) { - DPRINT1("error %x reading registry file at offset %x\n" + DPRINT("error %x reading registry file at offset %x\n" ,Status,fileOffset.u.LowPart); return NULL; } @@ -244,7 +244,7 @@ CHECKPOINT1; tmpHeap = (PHEAP_BLOCK)(((char *)RegistryFile->BlockList [0])+BlockOffset); if (tmpHeap->BlockId != REG_HEAP_ID ) { - DPRINT1("bad BlockId %x,offset %x\n",tmpHeap->BlockId,fileOffset.u.LowPart); + DPRINT("bad BlockId %x,offset %x\n",tmpHeap->BlockId,fileOffset.u.LowPart); } RegistryFile->BlockList [i] = tmpHeap; diff --git a/reactos/ntoskrnl/cm/rtlfunc.c b/reactos/ntoskrnl/cm/rtlfunc.c index 859323de468..5376fd5d280 100644 --- a/reactos/ntoskrnl/cm/rtlfunc.c +++ b/reactos/ntoskrnl/cm/rtlfunc.c @@ -398,7 +398,7 @@ RtlpGetRegistryHandle(ULONG RelativeTo, break; } - if (Path[0] != L'\\') + if ((RelativeTo == RTL_REGISTRY_ABSOLUTE) || (Path[0] != L'\\')) { RtlAppendUnicodeToString(&KeyName, Path); diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index d7fca626a28..1b62c5f5ba9 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: io.h,v 1.13 2001/09/01 15:36:44 chorns Exp $ +/* $Id: io.h,v 1.14 2001/09/16 13:19:31 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -44,7 +44,7 @@ typedef struct _DEVICE_NODE UNICODE_STRING InstancePath; UNICODE_STRING ServiceName; //TargetDeviceNotifyList? - DEVICE_CAPABILITIES CapabilityFlags; + PDEVICE_CAPABILITIES CapabilityFlags; ULONG Flags; ULONG UserFlags; ULONG DisableableDepends; @@ -52,6 +52,14 @@ typedef struct _DEVICE_NODE PCM_RESOURCE_LIST CmResourceList; PCM_RESOURCE_LIST BootResourcesList; PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList; + /* Not NT's */ + UNICODE_STRING DeviceID; + UNICODE_STRING InstanceID; + UNICODE_STRING HardwareIDs; + UNICODE_STRING CompatibleIDs; + UNICODE_STRING DeviceText; + UNICODE_STRING DeviceTextLocation; + PPNP_BUS_INFORMATION BusInformation; } DEVICE_NODE, *PDEVICE_NODE; /* For Flags field */ @@ -103,6 +111,121 @@ typedef struct _DEVICE_NODE #define CM_PROB_FAILED_INSTALL 28 #define CM_PROB_FAILED_ADD 31 +/* + * VOID + * IopDeviceNodeSetFlag( + * PDEVICE_NODE DeviceNode, + * ULONG Flag); + */ +#define IopDeviceNodeSetFlag(DeviceNode, Flag)((DeviceNode)->Flags |= (Flag)) + +/* + * VOID + * IopDeviceNodeClearFlag( + * PDEVICE_NODE DeviceNode, + * ULONG Flag); + */ +#define IopDeviceNodeClearFlag(DeviceNode, Flag)((DeviceNode)->Flags &= ~(Flag)) + +/* + * BOOLEAN + * IopDeviceNodeHasFlag( + * PDEVICE_NODE DeviceNode, + * ULONG Flag); + */ +#define IopDeviceNodeHasFlag(DeviceNode, Flag)(((DeviceNode)->Flags & (Flag)) > 0) + +/* + * VOID + * IopDeviceNodeSetUserFlag( + * PDEVICE_NODE DeviceNode, + * ULONG UserFlag); + */ +#define IopDeviceNodeSetUserFlag(DeviceNode, UserFlag)((DeviceNode)->UserFlags |= (UserFlag)) + +/* + * VOID + * IopDeviceNodeClearUserFlag( + * PDEVICE_NODE DeviceNode, + * ULONG UserFlag); + */ +#define IopDeviceNodeClearUserFlag(DeviceNode, UserFlag)((DeviceNode)->UserFlags &= ~(UserFlag)) + +/* + * BOOLEAN + * IopDeviceNodeHasUserFlag( + * PDEVICE_NODE DeviceNode, + * ULONG UserFlag); + */ +#define IopDeviceNodeHasUserFlag(DeviceNode, UserFlag)(((DeviceNode)->UserFlags & (UserFlag)) > 0) + + /* + * VOID + * IopDeviceNodeSetProblem( + * PDEVICE_NODE DeviceNode, + * ULONG Problem); + */ +#define IopDeviceNodeSetProblem(DeviceNode, Problem)((DeviceNode)->Problem |= (Problem)) + +/* + * VOID + * IopDeviceNodeClearProblem( + * PDEVICE_NODE DeviceNode, + * ULONG Problem); + */ +#define IopDeviceNodeClearProblem(DeviceNode, Problem)((DeviceNode)->Problem &= ~(Problem)) + +/* + * BOOLEAN + * IopDeviceNodeHasProblem( + * PDEVICE_NODE DeviceNode, + * ULONG Problem); + */ +#define IopDeviceNodeHasProblem(DeviceNode, Problem)(((DeviceNode)->Problem & (Problem)) > 0) + + +/* + Called on every visit of a node during a preorder-traversal of the device + node tree. + If the routine returns STATUS_UNSUCCESSFUL the traversal will stop and + STATUS_SUCCESS is returned to the caller who initiated the tree traversal. + Any other returned status code will be returned to the caller. If a status + code that indicates an error (other than STATUS_UNSUCCESSFUL) is returned, + the traversal is stopped immediately and the status code is returned to + the caller. + */ +typedef NTSTATUS (*DEVICETREE_TRAVERSE_ROUTINE)( + PDEVICE_NODE DeviceNode, + PVOID Context); + +/* Context information for traversing the device tree */ +typedef struct _DEVICETREE_TRAVERSE_CONTEXT +{ + /* Current device node during a traversal */ + PDEVICE_NODE DeviceNode; + /* Initial device node where we start the traversal */ + PDEVICE_NODE FirstDeviceNode; + /* Action routine to be called for every device node */ + DEVICETREE_TRAVERSE_ROUTINE Action; + /* Context passed to the action routine */ + PVOID Context; +} DEVICETREE_TRAVERSE_CONTEXT, *PDEVICETREE_TRAVERSE_CONTEXT; + +/* + * VOID + * IopInitDeviceTreeTraverseContext( + * PDEVICETREE_TRAVERSE_CONTEXT DeviceTreeTraverseContext, + * PDEVICE_NODE DeviceNode, + * DEVICETREE_TRAVERSE_ROUTINE Action, + * PVOID Context); + */ +#define IopInitDeviceTreeTraverseContext( \ + _DeviceTreeTraverseContext, _DeviceNode, _Action, _Context) { \ + (_DeviceTreeTraverseContext)->FirstDeviceNode = (_DeviceNode); \ + (_DeviceTreeTraverseContext)->Action = (_Action); \ + (_DeviceTreeTraverseContext)->Context = (_Context); } + + extern PDEVICE_NODE IopRootDeviceNode; extern POBJECT_TYPE IoSymbolicLinkType; @@ -110,15 +233,6 @@ extern POBJECT_TYPE IoSymbolicLinkType; VOID PnpInit(VOID); -NTSTATUS -STDCALL -PnpRootDriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath); -NTSTATUS -PnpRootCreateDevice( - PDEVICE_OBJECT *PhysicalDeviceObject); - NTSTATUS IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject); NTSTATUS @@ -129,7 +243,7 @@ NTSTATUS IopFreeDeviceNode(PDEVICE_NODE DeviceNode); NTSTATUS IopInterrogateBusExtender(PDEVICE_NODE DeviceNode, - PDEVICE_OBJECT FunctionDeviceObject, + PDEVICE_OBJECT Pdo, BOOLEAN BootDriversOnly); VOID IopLoadBootStartDrivers(VOID); @@ -203,4 +317,23 @@ IopInitiatePnpIrp( ULONG MinorFunction, PIO_STACK_LOCATION Stack); +BOOLEAN +IopCreateUnicodeString( + PUNICODE_STRING Destination, + PWSTR Source, + POOL_TYPE PoolType); + + +/* pnproot.c */ + +NTSTATUS +STDCALL +PnpRootDriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath); + +NTSTATUS +PnpRootCreateDevice( + PDEVICE_OBJECT *PhysicalDeviceObject); + #endif diff --git a/reactos/ntoskrnl/io/device.c b/reactos/ntoskrnl/io/device.c index 06886b78718..ccaa70a2c82 100644 --- a/reactos/ntoskrnl/io/device.c +++ b/reactos/ntoskrnl/io/device.c @@ -1,4 +1,4 @@ -/* $Id: device.c,v 1.33 2001/09/01 15:36:44 chorns Exp $ +/* $Id: device.c,v 1.34 2001/09/16 13:19:32 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -358,17 +358,18 @@ IopInitializeDevice(PDEVICE_NODE DeviceNode, DriverObject, DeviceNode->Pdo); if (!NT_SUCCESS(Status)) { - ExFreePool(DriverObject->DriverExtension); - ExFreePool(DriverObject); return(Status); } + + IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED); + DPRINT("Sending IRP_MN_START_DEVICE to driver\n"); Fdo = IoGetAttachedDeviceReference(DeviceNode->Pdo); if (Fdo == DeviceNode->Pdo) { - /* FIXME: What do we do? Unload the driver? */ + /* FIXME: What do we do? Unload the driver or just disable the device? */ DbgPrint("An FDO was not attached\n"); KeBugCheck(0); } @@ -386,8 +387,6 @@ IopInitializeDevice(PDEVICE_NODE DeviceNode, { DPRINT("IopInitiatePnpIrp() failed\n"); ObDereferenceObject(Fdo); - ExFreePool(DriverObject->DriverExtension); - ExFreePool(DriverObject); return(Status); } @@ -400,8 +399,6 @@ IopInitializeDevice(PDEVICE_NODE DeviceNode, if (!NT_SUCCESS(Status)) { ObDereferenceObject(Fdo); - ExFreePool(DriverObject->DriverExtension); - ExFreePool(DriverObject); return(Status); } } @@ -456,7 +453,9 @@ IopInitializeService( ObDereferenceObject(ModuleObject); - return STATUS_SUCCESS; + Status = IopInitializeDevice(DeviceNode, TRUE); + + return Status; } NTSTATUS @@ -515,6 +514,8 @@ IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry, /* * FUNCTION: Called to initalize a loaded driver * ARGUMENTS: + * DriverEntry = Pointer to driver entry routine + * DeviceNode = Pointer to device node */ { WCHAR RegistryKeyBuffer[MAX_PATH]; diff --git a/reactos/ntoskrnl/io/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr.c index 75b28701a60..4ba7942e469 100644 --- a/reactos/ntoskrnl/io/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr.c @@ -1,4 +1,4 @@ -/* $Id: pnpmgr.c,v 1.3 2001/09/01 15:36:44 chorns Exp $ +/* $Id: pnpmgr.c,v 1.4 2001/09/16 13:19:32 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -15,6 +15,7 @@ #include #include #include +#include #include #define NDEBUG @@ -248,6 +249,38 @@ IoUnregisterPlugPlayNotification( } +BOOLEAN +IopCreateUnicodeString( + PUNICODE_STRING Destination, + PWSTR Source, + POOL_TYPE PoolType) +{ + ULONG Length; + + if (!Source) + { + RtlInitUnicodeString(Destination, NULL); + return TRUE; + } + + Length = (wcslen(Source) + 1) * sizeof(WCHAR); + + Destination->Buffer = ExAllocatePool(PoolType, Length); + + if (Destination->Buffer == NULL) + { + return FALSE; + } + + RtlCopyMemory(Destination->Buffer, Source, Length); + + Destination->MaximumLength = Length; + + Destination->Length = Length - sizeof(WCHAR); + + return TRUE; +} + NTSTATUS IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject) { @@ -304,6 +337,10 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode, ExFreePool(Node); return Status; } + + /* This is for drivers passed on the command line to ntoskrnl.exe */ + IopDeviceNodeSetFlag(Node, DNF_STARTED); + IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER); } Node->Pdo = PhysicalDeviceObject; @@ -362,7 +399,42 @@ IopFreeDeviceNode(PDEVICE_NODE DeviceNode) RtlFreeUnicodeString(&DeviceNode->ServiceName); - /* FIXME: Other fields may need to be released */ + if (DeviceNode->CapabilityFlags) + { + ExFreePool(DeviceNode->CapabilityFlags); + } + + if (DeviceNode->CmResourceList) + { + ExFreePool(DeviceNode->CmResourceList); + } + + if (DeviceNode->BootResourcesList) + { + ExFreePool(DeviceNode->BootResourcesList); + } + + if (DeviceNode->ResourceRequirementsList) + { + ExFreePool(DeviceNode->ResourceRequirementsList); + } + + RtlFreeUnicodeString(&DeviceNode->DeviceID); + + RtlFreeUnicodeString(&DeviceNode->InstanceID); + + RtlFreeUnicodeString(&DeviceNode->HardwareIDs); + + RtlFreeUnicodeString(&DeviceNode->CompatibleIDs); + + RtlFreeUnicodeString(&DeviceNode->DeviceText); + + RtlFreeUnicodeString(&DeviceNode->DeviceTextLocation); + + if (DeviceNode->BusInformation) + { + ExFreePool(DeviceNode->BusInformation); + } ExFreePool(DeviceNode); @@ -374,7 +446,7 @@ IopInitiatePnpIrp( PDEVICE_OBJECT DeviceObject, PIO_STATUS_BLOCK IoStatusBlock, ULONG MinorFunction, - PIO_STACK_LOCATION Stack) + PIO_STACK_LOCATION Stack OPTIONAL) { PDEVICE_OBJECT TopDeviceObject; PIO_STACK_LOCATION IrpSp; @@ -393,6 +465,7 @@ IopInitiatePnpIrp( /* PNP IRPs are always initialized with a status code of STATUS_NOT_IMPLEMENTED */ IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED; + IoStatusBlock->Information = 0; Irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, @@ -405,10 +478,14 @@ IopInitiatePnpIrp( IrpSp = IoGetNextIrpStackLocation(Irp); IrpSp->MinorFunction = MinorFunction; - RtlMoveMemory( - &IrpSp->Parameters, - &Stack->Parameters, - sizeof(Stack->Parameters)); + + if (Stack) + { + RtlMoveMemory( + &IrpSp->Parameters, + &Stack->Parameters, + sizeof(Stack->Parameters)); + } Status = IoCallDriver(TopDeviceObject, Irp); if (Status == STATUS_PENDING) @@ -422,166 +499,661 @@ IopInitiatePnpIrp( Status = IoStatusBlock->Status; } + ObDereferenceObject(TopDeviceObject); + return Status; } + +NTSTATUS +IopQueryCapabilities( + PDEVICE_OBJECT Pdo, + PDEVICE_CAPABILITIES *Capabilities) +{ + IO_STATUS_BLOCK IoStatusBlock; + PDEVICE_CAPABILITIES Caps; + IO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n"); + + *Capabilities = NULL; + + Caps = ExAllocatePool(PagedPool, sizeof(DEVICE_CAPABILITIES)); + if (!Caps) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(Caps, sizeof(DEVICE_CAPABILITIES)); + Caps->Size = sizeof(DEVICE_CAPABILITIES); + Caps->Version = 1; + Caps->Address = -1; + Caps->UINumber = -1; + + Stack.Parameters.DeviceCapabilities.Capabilities = Caps; + + Status = IopInitiatePnpIrp( + Pdo, + &IoStatusBlock, + IRP_MN_QUERY_CAPABILITIES, + &Stack); + if (NT_SUCCESS(Status)) + { + *Capabilities = Caps; + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + } + + return Status; +} + + +NTSTATUS +IopTraverseDeviceTreeNode( + PDEVICETREE_TRAVERSE_CONTEXT Context) +{ + PDEVICE_NODE ParentDeviceNode; + PDEVICE_NODE ChildDeviceNode; + NTSTATUS Status; + + /* Copy context data so we don't overwrite it in subsequent calls to this function */ + ParentDeviceNode = Context->DeviceNode; + + /* Call the action routine */ + Status = (Context->Action)(ParentDeviceNode, Context->Context); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Traversal of all children nodes */ + for (ChildDeviceNode = ParentDeviceNode->Child; + ChildDeviceNode != NULL; + ChildDeviceNode = ChildDeviceNode->NextSibling) + { + /* Pass the current device node to the action routine */ + Context->DeviceNode = ChildDeviceNode; + + Status = IopTraverseDeviceTreeNode(Context); + if (!NT_SUCCESS(Status)) + { + return Status; + } + } + + return Status; +} + + +NTSTATUS +IopTraverseDeviceTree( + PDEVICETREE_TRAVERSE_CONTEXT Context) +{ + NTSTATUS Status; + + DPRINT("Context %x\n", Context); + + DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n", + Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context); + + /* Start from the specified device node */ + Context->DeviceNode = Context->FirstDeviceNode; + + /* Recursively traverse the device tree */ + Status = IopTraverseDeviceTreeNode(Context); + if (Status == STATUS_UNSUCCESSFUL) + { + /* The action routine just wanted to terminate the traversal with status + code STATUS_SUCCESS */ + Status = STATUS_SUCCESS; + } + + return Status; +} + + +NTSTATUS +IopActionInterrogateDeviceStack( + PDEVICE_NODE DeviceNode, + PVOID Context) +/* + * FUNCTION: Retrieve information for all (direct) child nodes of a parent node + * ARGUMENTS: + * DeviceNode = Pointer to device node + * Context = Pointer to parent node to retrieve child node information for + * NOTES: + * We only return a status code indicating an error (STATUS_UNSUCCESSFUL) + * when we reach a device node which is not a direct child of the device node + * for which we retrieve information of child nodes for. Any errors that occur + * is logged instead so that all child services have a chance of beeing + * interrogated. + */ +{ + IO_STATUS_BLOCK IoStatusBlock; + PDEVICE_NODE ParentDeviceNode; + WCHAR InstancePath[MAX_PATH]; + IO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context); + + DPRINT("PDO %x\n", DeviceNode->Pdo); + + + ParentDeviceNode = (PDEVICE_NODE)Context; + + /* We are called for the parent too, but we don't need to do special + handling for this node */ + if (DeviceNode == ParentDeviceNode) + { + DPRINT("Success\n"); + return STATUS_SUCCESS; + } + + /* Make sure this device node is a direct child of the parent device node + that is given as an argument */ + if (DeviceNode->Parent != ParentDeviceNode) + { + /* Stop the traversal immediately and indicate successful operation */ + DPRINT("Stop\n"); + return STATUS_UNSUCCESSFUL; + } + + + /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */ + + + DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n"); + + Stack.Parameters.QueryId.IdType = BusQueryDeviceID; + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_ID, + &Stack); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString( + &DeviceNode->DeviceID, + (LPWSTR)IoStatusBlock.Information); + + /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */ + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + RtlInitUnicodeString(&DeviceNode->DeviceID, NULL); + } + + + DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n"); + + Stack.Parameters.QueryId.IdType = BusQueryInstanceID; + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_ID, + &Stack); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString( + &DeviceNode->InstanceID, + (LPWSTR)IoStatusBlock.Information); + + /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */ + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + RtlInitUnicodeString(&DeviceNode->InstanceID, NULL); + } + + + /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */ + /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */ + + + Status = IopQueryCapabilities(DeviceNode->Pdo, &DeviceNode->CapabilityFlags); + if (NT_SUCCESS(Status)) + { + } + else + { + } + + + DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n"); + + Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription; + Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_DEVICE_TEXT, + &Stack); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString( + &DeviceNode->DeviceText, + (LPWSTR)IoStatusBlock.Information); + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + RtlInitUnicodeString(&DeviceNode->DeviceText, NULL); + } + + + DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n"); + + Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation; + Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_DEVICE_TEXT, + &Stack); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString( + &DeviceNode->DeviceTextLocation, + (LPWSTR)IoStatusBlock.Information); + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + RtlInitUnicodeString(&DeviceNode->DeviceTextLocation, NULL); + } + + + DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n"); + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_BUS_INFORMATION, + NULL); + if (NT_SUCCESS(Status)) + { + DeviceNode->BusInformation = + (PPNP_BUS_INFORMATION)IoStatusBlock.Information; + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + DeviceNode->BusInformation = NULL; + } + + + DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n"); + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_RESOURCES, + NULL); + if (NT_SUCCESS(Status)) + { + DeviceNode->BootResourcesList = + (PCM_RESOURCE_LIST)IoStatusBlock.Information; + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + DeviceNode->BootResourcesList = NULL; + } + + + DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n"); + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_RESOURCE_REQUIREMENTS, + NULL); + if (NT_SUCCESS(Status)) + { + DeviceNode->ResourceRequirementsList = + (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information; + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + DeviceNode->ResourceRequirementsList = NULL; + } + + + /* Assemble the instance path for the device */ + + wcscpy(InstancePath, DeviceNode->DeviceID.Buffer); + wcscat(InstancePath, L"\\"); + wcscat(InstancePath, DeviceNode->InstanceID.Buffer); + + if (!DeviceNode->CapabilityFlags->UniqueID) + { + DPRINT("Instance ID is not unique\n"); + /* FIXME: Add information from parent bus driver to InstancePath */ + } + + if (!IopCreateUnicodeString(&DeviceNode->InstancePath, InstancePath, PagedPool)) { + DPRINT("No resources\n"); + /* FIXME: Cleanup and disable device */ + } + + DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer); + + return STATUS_SUCCESS; +} + + +NTSTATUS +IopActionConfigureChildServices( + PDEVICE_NODE DeviceNode, + PVOID Context) +/* + * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node + * ARGUMENTS: + * DeviceNode = Pointer to device node + * Context = Pointer to parent node to retrieve child node configuration for + * NOTES: + * We only return a status code indicating an error (STATUS_UNSUCCESSFUL) + * when we reach a device node which is not a direct child of the device + * node for which we configure child services for. Any errors that occur is + * logged instead so that all child services have a chance of beeing + * configured. + */ +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + PDEVICE_NODE ParentDeviceNode; + PUNICODE_STRING Service; + HANDLE KeyHandle; + NTSTATUS Status; + + DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context); + + ParentDeviceNode = (PDEVICE_NODE)Context; + + /* We are called for the parent too, but we don't need to do special + handling for this node */ + if (DeviceNode == ParentDeviceNode) + { + DPRINT("Success\n"); + return STATUS_SUCCESS; + } + + /* Make sure this device node is a direct child of the parent device node + that is given as an argument */ + if (DeviceNode->Parent != ParentDeviceNode) + { + /* Stop the traversal immediately and indicate successful operation */ + DPRINT("Stop\n"); + return STATUS_UNSUCCESSFUL; + } + + /* Retrieve configuration from Enum key */ + + Service = &DeviceNode->ServiceName; + + Status = RtlpGetRegistryHandle( + RTL_REGISTRY_ENUM, + DeviceNode->InstancePath.Buffer, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status); + return Status; + } + + RtlZeroMemory(QueryTable, sizeof(QueryTable)); + + RtlInitUnicodeString(Service, NULL); + + QueryTable[0].Name = L"Service"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = Service; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + QueryTable, + NULL, + NULL); + NtClose(KeyHandle); + + DPRINT("RtlQueryRegistryValues() returned status %x\n", Status); + + if (!NT_SUCCESS(Status)) + { + /* FIXME: Log the error */ + CPRINT("Could not retrieve configuration for device %S (Status %x)\n", + DeviceNode->InstancePath.Buffer, Status); + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + return STATUS_SUCCESS; + } + + DPRINT("Got Service %S\n", Service->Buffer); + + return STATUS_SUCCESS; +} + + +NTSTATUS +IopActionInitChildServices( + PDEVICE_NODE DeviceNode, + PVOID Context) +/* + * FUNCTION: Initialize the service for all (direct) child nodes of a parent node + * ARGUMENTS: + * DeviceNode = Pointer to device node + * Context = Pointer to parent node to initialize child node services for + * NOTES: + * If the driver image for a service is not loaded and initialized + * it is done here too. + * We only return a status code indicating an error (STATUS_UNSUCCESSFUL) + * when we reach a device node which is not a direct child of the device + * node for which we initialize child services for. Any errors that occur is + * logged instead so that all child services have a chance of beeing + * initialized. + */ +{ + PDEVICE_NODE ParentDeviceNode; + NTSTATUS Status; + + DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context); + + ParentDeviceNode = (PDEVICE_NODE)Context; + + /* We are called for the parent too, but we don't need to do special + handling for this node */ + if (DeviceNode == ParentDeviceNode) + { + DPRINT("Success\n"); + return STATUS_SUCCESS; + } + + /* Make sure this device node is a direct child of the parent device node + that is given as an argument */ + if (DeviceNode->Parent != ParentDeviceNode) + { + /* Stop the traversal immediately and indicate successful operation */ + DPRINT("Stop\n"); + return STATUS_UNSUCCESSFUL; + } + + if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) && + !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) && + !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED)) + { + Status = IopInitializeDeviceNodeService(DeviceNode); + if (NT_SUCCESS(Status)) + { + IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); + } + else + { + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + + /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */ + CPRINT("Initialization of service %S failed (Status %x)\n", + DeviceNode->ServiceName.Buffer, Status); + } + } + else + { + DPRINT("Service %S is disabled or already initialized\n", + DeviceNode->ServiceName.Buffer); + } + + return STATUS_SUCCESS; +} + + NTSTATUS IopInterrogateBusExtender( PDEVICE_NODE DeviceNode, - PDEVICE_OBJECT FunctionDeviceObject, + PDEVICE_OBJECT Pdo, BOOLEAN BootDriversOnly) { + DEVICETREE_TRAVERSE_CONTEXT Context; PDEVICE_RELATIONS DeviceRelations; IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING DriverName; + PDEVICE_NODE ChildDeviceNode; IO_STACK_LOCATION Stack; NTSTATUS Status; + ULONG i; - DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to bus driver\n"); + DPRINT("DeviceNode %x Pdo %x BootDriversOnly %d\n", DeviceNode, Pdo, BootDriversOnly); + + DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n"); Stack.Parameters.QueryDeviceRelations.Type = BusRelations; Status = IopInitiatePnpIrp( - FunctionDeviceObject, + Pdo, &IoStatusBlock, IRP_MN_QUERY_DEVICE_RELATIONS, &Stack); if (!NT_SUCCESS(Status)) - { - DPRINT("IopInitiatePnpIrp() failed\n"); - } + { + DPRINT("IopInitiatePnpIrp() failed\n"); + return Status; + } DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information; + if ((!DeviceRelations) || (DeviceRelations->Count <= 0)) + { + DPRINT("No PDOs\n"); + if (DeviceRelations) + { + ExFreePool(DeviceRelations); + } + return STATUS_SUCCESS; + } + DPRINT("Got %d PDOs\n", DeviceRelations->Count); - if (DeviceRelations->Count <= 0) - { - DPRINT("No PDOs\n"); - ExFreePool(DeviceRelations); - return STATUS_SUCCESS; - } +#ifdef DBG + { + ULONG i; - Status = IopCreateDeviceNode(DeviceNode, NULL, &DeviceNode); - if (!NT_SUCCESS(Status)) + DPRINT("DeviceRelations %x\n", DeviceRelations); + DPRINT("Count %x\n", DeviceRelations->Count); + for (i = 0; i < DeviceRelations->Count; i++) + DPRINT("Object(PDO) %x\n", DeviceRelations->Objects[i]); + } +#endif + + /* Create device nodes for all discovered devices */ + for (i = 0; i < DeviceRelations->Count; i++) + { + Status = IopCreateDeviceNode( + DeviceNode, + DeviceRelations->Objects[i], + &ChildDeviceNode); + if (!NT_SUCCESS(Status)) { DPRINT("No resources\n"); + for (i = 0; i < DeviceRelations->Count; i++) + ObDereferenceObject(DeviceRelations->Objects[i]); ExFreePool(DeviceRelations); return STATUS_INSUFFICIENT_RESOURCES; } - - /* FIXME: Use registry to find name of driver and only load driver if not - already loaded. If loaded, just call AddDevice() */ - Status = LdrLoadDriver(&DriverName, DeviceNode, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Don't free the device node, just log the error and return */ - /* FIXME: Log the error */ - CPRINT("Driver load failed, status (%x)\n", Status); - ExFreePool(DeviceRelations); - return Status; - } + } ExFreePool(DeviceRelations); + + /* Retrieve information about all discovered children from the bus driver */ + + IopInitDeviceTreeTraverseContext( + &Context, + DeviceNode, + IopActionInterrogateDeviceStack, + DeviceNode); + + Status = IopTraverseDeviceTree(&Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status); + return Status; + } + + + /* Retrieve configuration from the registry for discovered children */ + + IopInitDeviceTreeTraverseContext( + &Context, + DeviceNode, + IopActionConfigureChildServices, + DeviceNode); + + Status = IopTraverseDeviceTree(&Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status); + return Status; + } + + + /* Initialize services for discovered children */ + + IopInitDeviceTreeTraverseContext( + &Context, + DeviceNode, + IopActionInitChildServices, + DeviceNode); + + Status = IopTraverseDeviceTree(&Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status); + return Status; + } + return Status; } + VOID IopLoadBootStartDrivers(VOID) { - OBJECT_ATTRIBUTES ObjectAttributes; - PKEY_BASIC_INFORMATION KeyInfo; - PDEVICE_NODE DeviceNode; - UNICODE_STRING KeyName; - HANDLE KeyHandle; - ULONG BufferSize; - ULONG ResultSize; - NTSTATUS Status; - ULONG Index; - - DPRINT("Loading boot start drivers\n"); - - BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR); - KeyInfo = ExAllocatePool(PagedPool, BufferSize); - if (!KeyInfo) - { - return; - } - - RtlInitUnicodeString( - &KeyName, - L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - - InitializeObjectAttributes( - &ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtOpenKey() failed (Status %x)\n", Status); - ExFreePool(KeyInfo); - return; - } - - Index = 0; - do { - Status = ZwEnumerateKey( - KeyHandle, - Index, - KeyBasicInformation, - KeyInfo, - BufferSize, - &ResultSize); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwEnumerateKey() (Status %x)\n", Status); - break; - } - - /* Terminate the string */ - KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0; - - /* Use IopRootDeviceNode for now */ - Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode); - if (!NT_SUCCESS(Status)) - { - CPRINT("IopCreateDeviceNode() failed with status 0x%X\n", Status); - break; - } - - if (!RtlCreateUnicodeString(&DeviceNode->ServiceName, KeyInfo->Name)) - { - CPRINT("RtlCreateUnicodeString() failed\n"); - IopFreeDeviceNode(DeviceNode); - break; - } - - Status = IopInitializeDeviceNodeService(DeviceNode); - if (!NT_SUCCESS(Status)) - { - /* FIXME: Write an entry in the system error log */ - CPRINT("Could not load boot start driver: %wZ, status 0x%X\n", - &DeviceNode->ServiceName, Status); - - IopFreeDeviceNode(DeviceNode); - } - - Index++; - } while (TRUE); - - DPRINT("Services found: %d\n", Index); - - NtClose(KeyHandle); - - ExFreePool(KeyInfo); + IopInterrogateBusExtender( + IopRootDeviceNode, + IopRootDeviceNode->Pdo, + TRUE); } VOID PnpInit(VOID) { + PDEVICE_OBJECT Pdo; NTSTATUS Status; DPRINT("Called\n"); @@ -590,25 +1162,44 @@ VOID PnpInit(VOID) Status = IopCreateDriverObject(&IopRootDriverObject); if (!NT_SUCCESS(Status)) - { - CPRINT("IoCreateDriverObject() failed\n"); - KeBugCheck(0); - } + { + CPRINT("IoCreateDriverObject() failed\n"); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } - PnpRootDriverEntry(IopRootDriverObject, NULL); - - Status = IoCreateDevice(IopRootDriverObject, 0, NULL, - FILE_DEVICE_CONTROLLER, 0, FALSE, &IopRootDeviceNode->Pdo); + Status = IoCreateDevice( + IopRootDriverObject, + 0, + NULL, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &Pdo); if (!NT_SUCCESS(Status)) - { - CPRINT("IoCreateDevice() failed\n"); - KeBugCheck(0); - } + { + CPRINT("IoCreateDevice() failed\n"); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + Status = IopCreateDeviceNode( + NULL, + Pdo, + &IopRootDeviceNode); + if (!NT_SUCCESS(Status)) + { + CPRINT("Insufficient resources\n"); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } IopRootDeviceNode->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + IopRootDeviceNode->DriverObject = IopRootDriverObject; + + PnpRootDriverEntry(IopRootDriverObject, NULL); + IopRootDriverObject->DriverExtension->AddDevice( - IopRootDriverObject, IopRootDeviceNode->Pdo); + IopRootDriverObject, + IopRootDeviceNode->Pdo); } /* EOF */ diff --git a/reactos/ntoskrnl/io/pnproot.c b/reactos/ntoskrnl/io/pnproot.c index 9dd2e65b26b..1acb0a88432 100644 --- a/reactos/ntoskrnl/io/pnproot.c +++ b/reactos/ntoskrnl/io/pnproot.c @@ -1,4 +1,4 @@ -/* $Id: pnproot.c,v 1.5 2001/09/01 15:36:44 chorns Exp $ +/* $Id: pnproot.c,v 1.6 2001/09/16 13:19:32 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -13,55 +13,168 @@ #include #include +#include #define NDEBUG #include /* GLOBALS *******************************************************************/ +#define ENUM_NAME_ROOT L"Root" + /* DATA **********************************************************************/ typedef struct _PNPROOT_DEVICE { + // Entry on device list LIST_ENTRY ListEntry; + // Physical Device Object of device PDEVICE_OBJECT Pdo; + // Service name + UNICODE_STRING ServiceName; + // Device ID + UNICODE_STRING DeviceID; + // Instance ID + UNICODE_STRING InstanceID; + // Device description + UNICODE_STRING DeviceDescription; } PNPROOT_DEVICE, *PPNPROOT_DEVICE; +typedef enum { + dsStopped, + dsStarted, + dsPaused, + dsRemoved, + dsSurpriseRemoved +} PNPROOT_DEVICE_STATE; + + +typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION +{ + // Pointer to device object, this device extension is associated with + PDEVICE_OBJECT DeviceObject; + // Wether this device extension is for an FDO or PDO + BOOLEAN IsFDO; + // Wether the device is removed + BOOLEAN Removed; + // Current device power state for the device + DEVICE_POWER_STATE DevicePowerState; +} __attribute((packed)) PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION; + +/* Physical Device Object device extension for a child device */ +typedef struct _PNPROOT_PDO_DEVICE_EXTENSION +{ + // Common device data + PNPROOT_COMMON_DEVICE_EXTENSION; + // Device ID + UNICODE_STRING DeviceID; + // Instance ID + UNICODE_STRING InstanceID; +} __attribute((packed)) PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION; + +/* Functional Device Object device extension for the PCI driver device object */ +typedef struct _PNPROOT_FDO_DEVICE_EXTENSION +{ + // Common device data + PNPROOT_COMMON_DEVICE_EXTENSION; + // Physical Device Object + PDEVICE_OBJECT Pdo; + // Lower device object + PDEVICE_OBJECT Ldo; + // Current state of the driver + PNPROOT_DEVICE_STATE State; + // Namespace device list + LIST_ENTRY DeviceListHead; + // Number of (not removed) devices in device list + ULONG DeviceListCount; + // Lock for namespace device list + // FIXME: Use fast mutex instead? + KSPIN_LOCK DeviceListLock; +} __attribute((packed)) PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION; + + PDEVICE_OBJECT PnpRootDeviceObject; -LIST_ENTRY PnpRootDeviceListHead; -ULONG PnpRootDeviceListCount; -KSPIN_LOCK PnpRootDeviceListLock; + /* FUNCTIONS *****************************************************************/ +/* Physical Device Object routines */ + NTSTATUS PnpRootCreateDevice( PDEVICE_OBJECT *PhysicalDeviceObject) { + PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension; + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; PPNPROOT_DEVICE Device; NTSTATUS Status; + /* This function should be obsoleted soon */ + DPRINT("Called\n"); + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension; + Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE)); if (!Device) return STATUS_INSUFFICIENT_RESOURCES; - Status = IoCreateDevice(PnpRootDeviceObject->DriverObject, 0, - NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &Device->Pdo); - if (!NT_SUCCESS(Status)) - { - DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); - ExFreePool(Device); - return Status; - } + RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE)); + + Status = IoCreateDevice( + PnpRootDeviceObject->DriverObject, + sizeof(PNPROOT_PDO_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &Device->Pdo); + if (!NT_SUCCESS(Status)) { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + ExFreePool(Device); + return Status; + } Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; - ObReferenceObject(Device->Pdo); + Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; - ExInterlockedInsertTailList(&PnpRootDeviceListHead, + //Device->Pdo->Flags |= DO_POWER_PAGABLE; + + PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension; + + RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION)); + + PdoDeviceExtension->IsFDO = FALSE; + + PdoDeviceExtension->DeviceObject = Device->Pdo; + + PdoDeviceExtension->DevicePowerState = PowerDeviceD0; + + if (!IopCreateUnicodeString( + &PdoDeviceExtension->DeviceID, + ENUM_NAME_ROOT \ + L"\\LEGACY_UNKNOWN", + PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + if (!IopCreateUnicodeString( + &PdoDeviceExtension->InstanceID, + L"0000", + PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + ExInterlockedInsertTailList( + &DeviceExtension->DeviceListHead, &Device->ListEntry, - &PnpRootDeviceListLock); + &DeviceExtension->DeviceListLock); + + DeviceExtension->DeviceListCount++; *PhysicalDeviceObject = Device->Pdo; @@ -69,12 +182,405 @@ PnpRootCreateDevice( } +NTSTATUS +PdoQueryId( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension; + UNICODE_STRING String; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + +// Irp->IoStatus.Information = 0; + + Status = STATUS_SUCCESS; + + RtlInitUnicodeString(&String, NULL); + + switch (IrpSp->Parameters.QueryId.IdType) { + case BusQueryDeviceID: + Status = IopCreateUnicodeString( + &String, + DeviceExtension->DeviceID.Buffer, + PagedPool); + + DPRINT("DeviceID: %S\n", String.Buffer); + + Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; + break; + + case BusQueryHardwareIDs: + case BusQueryCompatibleIDs: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case BusQueryInstanceID: + Status = IopCreateUnicodeString( + &String, + DeviceExtension->InstanceID.Buffer, + PagedPool); + + DPRINT("InstanceID: %S\n", String.Buffer); + + Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; + break; + + case BusQueryDeviceSerialNumber: + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + return Status; +} + + +NTSTATUS +PnpRootPdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs for the child device + * ARGUMENTS: + * DeviceObject = Pointer to physical device object of the child device + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = Irp->IoStatus.Status; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { +#if 0 + case IRP_MN_CANCEL_REMOVE_DEVICE: + break; + + case IRP_MN_CANCEL_STOP_DEVICE: + break; + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + break; + + case IRP_MN_EJECT: + break; + + case IRP_MN_QUERY_BUS_INFORMATION: + break; + + case IRP_MN_QUERY_CAPABILITIES: + break; + + case IRP_MN_QUERY_DEVICE_RELATIONS: + /* FIXME: Possibly handle for RemovalRelations */ + break; + + case IRP_MN_QUERY_DEVICE_TEXT: + break; +#endif + case IRP_MN_QUERY_ID: + Status = PdoQueryId(DeviceObject, Irp, IrpSp); + break; +#if 0 + case IRP_MN_QUERY_PNP_DEVICE_STATE: + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: + break; + + case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: + break; + + case IRP_MN_QUERY_RESOURCES: + break; + + case IRP_MN_QUERY_STOP_DEVICE: + break; + + case IRP_MN_REMOVE_DEVICE: + break; + + case IRP_MN_SET_LOCK: + break; + + case IRP_MN_START_DEVICE: + break; + + case IRP_MN_STOP_DEVICE: + break; + + case IRP_MN_SURPRISE_REMOVAL: + break; +#endif + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + break; + } + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + +NTSTATUS +PnpRootPdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle power management IRPs for the child device + * ARGUMENTS: + * DeviceObject = Pointer to physical device object of the child device + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = Irp->IoStatus.Status; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + break; + } + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +/* Functional Device Object routines */ + +NTSTATUS +PnpRootFdoReadDeviceInfo( + PPNPROOT_DEVICE Device) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + PUNICODE_STRING DeviceDesc; + WCHAR KeyName[MAX_PATH]; + HANDLE KeyHandle; + NTSTATUS Status; + + DPRINT("Called\n"); + + /* Retrieve configuration from Enum key */ + + DeviceDesc = &Device->DeviceDescription; + + wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); + wcscat(KeyName, ENUM_NAME_ROOT); + wcscat(KeyName, L"\\"); + wcscat(KeyName, Device->ServiceName.Buffer); + wcscat(KeyName, L"\\"); + wcscat(KeyName, Device->InstanceID.Buffer); + + DPRINT("KeyName %S\n", KeyName); + + Status = RtlpGetRegistryHandle( + RTL_REGISTRY_ABSOLUTE, + KeyName, + FALSE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status); + return Status; + } + + RtlZeroMemory(QueryTable, sizeof(QueryTable)); + + RtlInitUnicodeString(DeviceDesc, NULL); + + QueryTable[0].Name = L"DeviceDesc"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = DeviceDesc; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + QueryTable, + NULL, + NULL); + + NtClose(KeyHandle); + + DPRINT("RtlQueryRegistryValues() returned status %x\n", Status); + + if (!NT_SUCCESS(Status)) + { + /* FIXME: */ + } + + DPRINT("Got device description: %S\n", DeviceDesc->Buffer); + + return STATUS_SUCCESS; +} + + +NTSTATUS +PnpRootFdoEnumerateDevices( + PDEVICE_OBJECT DeviceObject) +{ + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; + OBJECT_ATTRIBUTES ObjectAttributes; + PKEY_BASIC_INFORMATION KeyInfo; + UNICODE_STRING KeyName; + PPNPROOT_DEVICE Device; + WCHAR Buffer[MAX_PATH]; + HANDLE KeyHandle; + ULONG BufferSize; + ULONG ResultSize; + NTSTATUS Status; + ULONG Index; + + DPRINT("Called\n"); + + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR); + KeyInfo = ExAllocatePool(PagedPool, BufferSize); + if (!KeyInfo) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlInitUnicodeString( + &KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" \ + ENUM_NAME_ROOT); + + InitializeObjectAttributes( + &ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtOpenKey() failed (Status %x)\n", Status); + ExFreePool(KeyInfo); + return Status; + } + + /* FIXME: Disabled due to still using the old method of auto loading drivers e.g. + there are more entries in the list than found in the registry as some + drivers are passed on the command line */ +// DeviceExtension->DeviceListCount = 0; + + Index = 0; + do { + Status = ZwEnumerateKey( + KeyHandle, + Index, + KeyBasicInformation, + KeyInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwEnumerateKey() (Status %x)\n", Status); + break; + } + + /* Terminate the string */ + KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0; + + Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE)); + if (!Device) + { + /* FIXME: */ + break; + } + + RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE)); + + if (!IopCreateUnicodeString(&Device->ServiceName, KeyInfo->Name, PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + wcscpy(Buffer, ENUM_NAME_ROOT); + wcscat(Buffer, L"\\"); + wcscat(Buffer, KeyInfo->Name); + + if (!IopCreateUnicodeString(&Device->DeviceID, Buffer, PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + DPRINT("Got entry: %S\n", Device->DeviceID.Buffer); + + if (!IopCreateUnicodeString( + &Device->InstanceID, + L"0000", + PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + Status = PnpRootFdoReadDeviceInfo(Device); + if (!NT_SUCCESS(Status)) + { + DPRINT("PnpRootFdoReadDeviceInfo() failed with status %x\n", Status); + /* FIXME: */ + } + + ExInterlockedInsertTailList( + &DeviceExtension->DeviceListHead, + &Device->ListEntry, + &DeviceExtension->DeviceListLock); + + DeviceExtension->DeviceListCount++; + + Index++; + } while (TRUE); + + DPRINT("Entries found: %d\n", Index); + + NtClose(KeyHandle); + + ExFreePool(KeyInfo); + + return STATUS_SUCCESS; +} + + NTSTATUS PnpRootQueryBusRelations( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) { + PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension; + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; PDEVICE_RELATIONS Relations; PLIST_ENTRY CurrentEntry; PPNPROOT_DEVICE Device; @@ -84,33 +590,92 @@ PnpRootQueryBusRelations( DPRINT("Called\n"); + Status = PnpRootFdoEnumerateDevices(DeviceObject); + if (!NT_SUCCESS(Status)) + return Status; + + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (Irp->IoStatus.Information) + { + /* FIXME: Another bus driver has already created a DEVICE_RELATIONS + structure so we must merge this structure with our own */ + } + Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) * - (PnpRootDeviceListCount - 1); + (DeviceExtension->DeviceListCount - 1); + Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size); if (!Relations) return STATUS_INSUFFICIENT_RESOURCES; - Relations->Count = PnpRootDeviceListCount; + Relations->Count = DeviceExtension->DeviceListCount; i = 0; - CurrentEntry = PnpRootDeviceListHead.Flink; - while (CurrentEntry != &PnpRootDeviceListHead) - { - Device = CONTAINING_RECORD( - CurrentEntry, PNPROOT_DEVICE, ListEntry); + CurrentEntry = DeviceExtension->DeviceListHead.Flink; + while (CurrentEntry != &DeviceExtension->DeviceListHead) + { + Device = CONTAINING_RECORD(CurrentEntry, PNPROOT_DEVICE, ListEntry); - if (!Device->Pdo) { + if (!Device->Pdo) + { /* Create a physical device object for the device as it does not already have one */ - Status = IoCreateDevice(DeviceObject->DriverObject, 0, - NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &Device->Pdo); - if (!NT_SUCCESS(Status)) { + Status = IoCreateDevice( + DeviceObject->DriverObject, + sizeof(PNPROOT_PDO_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &Device->Pdo); + if (!NT_SUCCESS(Status)) + { DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); ExFreePool(Relations); return Status; } + DPRINT("Created PDO %x\n", Device->Pdo); + Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + + Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; + + //Device->Pdo->Flags |= DO_POWER_PAGABLE; + + PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension; + + RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION)); + + PdoDeviceExtension->IsFDO = FALSE; + + PdoDeviceExtension->DeviceObject = Device->Pdo; + + PdoDeviceExtension->DevicePowerState = PowerDeviceD0; + + if (!IopCreateUnicodeString( + &PdoDeviceExtension->DeviceID, + Device->DeviceID.Buffer, + PagedPool)) + { + DPRINT("Insufficient resources\n"); + /* FIXME: */ + } + + DPRINT("DeviceID: %S PDO %x\n", + PdoDeviceExtension->DeviceID.Buffer, + Device->Pdo); + + if (!IopCreateUnicodeString( + &PdoDeviceExtension->InstanceID, + Device->InstanceID.Buffer, + PagedPool)) + { + DPRINT("Insufficient resources\n"); + /* FIXME: */ + } + } /* Reference the physical device object. The PnP manager @@ -122,13 +687,21 @@ PnpRootQueryBusRelations( i++; CurrentEntry = CurrentEntry->Flink; - } + } - Irp->IoStatus.Information = (ULONG)Relations; + if (NT_SUCCESS(Status)) + { + Irp->IoStatus.Information = (ULONG_PTR)Relations; + } + else + { + Irp->IoStatus.Information = 0; + } return Status; } + NTSTATUS PnpRootQueryDeviceRelations( IN PDEVICE_OBJECT DeviceObject, @@ -139,42 +712,52 @@ PnpRootQueryDeviceRelations( DPRINT("Called\n"); - switch (IrpSp->Parameters.QueryDeviceRelations.Type) - { + switch (IrpSp->Parameters.QueryDeviceRelations.Type) { case BusRelations: Status = PnpRootQueryBusRelations(DeviceObject, Irp, IrpSp); break; default: Status = STATUS_NOT_IMPLEMENTED; - } + } return Status; } + NTSTATUS STDCALL -PnpRootPnpControl( +PnpRootFdoPnpControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs for the root bus device object + * ARGUMENTS: + * DeviceObject = Pointer to functional device object of the root bus driver + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ { + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; PIO_STACK_LOCATION IrpSp; NTSTATUS Status; DPRINT("Called\n"); + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + Status = Irp->IoStatus.Status; IrpSp = IoGetCurrentIrpStackLocation(Irp); - switch (IrpSp->MinorFunction) - { + switch (IrpSp->MinorFunction) { case IRP_MN_QUERY_DEVICE_RELATIONS: Status = PnpRootQueryDeviceRelations(DeviceObject, Irp, IrpSp); break; - + case IRP_MN_START_DEVICE: - PnpRootDeviceListCount = 0; + DeviceExtension->State = dsStarted; Status = STATUS_SUCCESS; break; @@ -187,24 +770,32 @@ PnpRootPnpControl( DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); Status = STATUS_NOT_IMPLEMENTED; break; - } + } - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } DPRINT("Leaving. Status 0x%X\n", Status); return Status; } + NTSTATUS STDCALL -PnpRootPowerControl( +PnpRootFdoPowerControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +/* + * FUNCTION: Handle power management IRPs for the root bus device object + * ARGUMENTS: + * DeviceObject = Pointer to functional device object of the root bus driver + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ { PIO_STACK_LOCATION IrpSp; NTSTATUS Status; @@ -212,70 +803,150 @@ PnpRootPowerControl( DPRINT("Called\n"); IrpSp = IoGetCurrentIrpStackLocation(Irp); - switch (IrpSp->MinorFunction) - { + + switch (IrpSp->MinorFunction) { default: DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); Status = STATUS_NOT_IMPLEMENTED; break; } - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } DPRINT("Leaving. Status 0x%X\n", Status); return Status; } + +NTSTATUS +STDCALL +PnpRootPnpControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs + * ARGUMENTS: + * DeviceObject = Pointer to PDO or FDO + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + DPRINT("DeviceObject %x DeviceExtension %x IsFDO %d\n", + DeviceObject, + DeviceExtension, + DeviceExtension->IsFDO); + + if (DeviceExtension->IsFDO) { + Status = PnpRootFdoPnpControl(DeviceObject, Irp); + } else { + Status = PnpRootPdoPnpControl(DeviceObject, Irp); + } + + return Status; +} + + +NTSTATUS +STDCALL +PnpRootPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle power management IRPs + * ARGUMENTS: + * DeviceObject = Pointer to PDO or FDO + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->IsFDO) { + Status = PnpRootFdoPowerControl(DeviceObject, Irp); + } else { + Status = PnpRootPdoPowerControl(DeviceObject, Irp); + } + + return Status; +} + + NTSTATUS STDCALL PnpRootAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { - PDEVICE_OBJECT Ldo; + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status; DPRINT("Called\n"); - Status = IoCreateDevice(DriverObject, 0, NULL, FILE_DEVICE_BUS_EXTENDER, - FILE_DEVICE_SECURE_OPEN, TRUE, &PnpRootDeviceObject); - if (!NT_SUCCESS(Status)) - { - DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); - KeBugCheck(0); - return Status; - } + Status = IoCreateDevice( + DriverObject, + sizeof(PNPROOT_FDO_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_BUS_EXTENDER, + FILE_DEVICE_SECURE_OPEN, + TRUE, + &PnpRootDeviceObject); + if (!NT_SUCCESS(Status)) { + CPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } - Ldo = IoAttachDeviceToDeviceStack(PnpRootDeviceObject, PhysicalDeviceObject); + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension; - if (!PnpRootDeviceObject) - { - DbgPrint("PnpRootDeviceObject 0x%X\n", PnpRootDeviceObject); - KeBugCheck(0); - } + RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION)); - if (!PhysicalDeviceObject) - { - DbgPrint("PhysicalDeviceObject 0x%X\n", PhysicalDeviceObject); - KeBugCheck(0); - } + DeviceExtension->IsFDO = TRUE; - InitializeListHead(&PnpRootDeviceListHead); - PnpRootDeviceListCount = 0; - KeInitializeSpinLock(&PnpRootDeviceListLock); + DeviceExtension->State = dsStopped; + + DeviceExtension->Ldo = IoAttachDeviceToDeviceStack( + PnpRootDeviceObject, + PhysicalDeviceObject); + + if (!PnpRootDeviceObject) { + CPRINT("PnpRootDeviceObject 0x%X\n", PnpRootDeviceObject); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + if (!PhysicalDeviceObject) { + CPRINT("PhysicalDeviceObject 0x%X\n", PhysicalDeviceObject); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + InitializeListHead(&DeviceExtension->DeviceListHead); + + DeviceExtension->DeviceListCount = 0; + + KeInitializeSpinLock(&DeviceExtension->DeviceListLock); PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - DPRINT("Done\n"); + //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE; + + DPRINT("Done AddDevice()\n"); return STATUS_SUCCESS; } + NTSTATUS STDCALL PnpRootDriverEntry( diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 4c1f4406805..438348a4495 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: main.c,v 1.105 2001/09/04 21:06:27 ekohl Exp $ +/* $Id: main.c,v 1.106 2001/09/16 13:19:32 chorns Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/main.c @@ -84,9 +84,10 @@ typedef struct } SERVICE, *PSERVICE; SERVICE Services[] = { + {L"pci", L"PCI Bus Driver", L"Boot Bus Extender", 0, 1}, {L"keyboard", L"Standard Keyboard Driver", L"Base", 0, 1}, {L"blue", L"Bluescreen Driver", L"Base", 0, 1}, - {L"vidport", L"Video Port Driver", L"Base", 0, 1}, +/* {L"vidport", L"Video Port Driver", L"Base", 0, 1}, {L"vgamp", L"VGA Miniport", L"Base", 0, 1}, {L"minixfs", L"Minix File System", L"File system", 0, 1}, {L"msfs", L"Mail Slot File System", L"File system", 0, 1}, @@ -95,22 +96,28 @@ SERVICE Services[] = { {L"mouclass", L"Mouse Class Driver", L"Pointer Class", 0, 1}, {L"ndis", L"NDIS System Driver", L"NDIS Wrapper", 0, 1}, {L"ne2000", L"Novell Eagle 2000 Driver", L"NDIS", 0, 1}, - {L"afd", L"AFD Networking Support Environment", L"TDI", 0, 1}, + {L"afd", L"AFD Networking Support Environment", L"TDI", 0, 1},*/ {NULL,} }; /* FUNCTIONS ****************************************************************/ +//#define FULLREG + VOID CreateDefaultRegistryForLegacyDriver( PSERVICE Service) { +#ifdef FULLREG WCHAR LegacyDriver[] = L"LegacyDriver"; +#endif WCHAR InstancePath[MAX_PATH]; WCHAR KeyNameBuffer[MAX_PATH]; WCHAR Name[MAX_PATH]; UNICODE_STRING KeyName; HANDLE KeyHandle; +#ifdef FULLREG DWORD DwordData; +#endif ULONG Length; NTSTATUS Status; WCHAR ImagePath[MAX_PATH]; @@ -146,7 +153,7 @@ VOID CreateDefaultRegistryForLegacyDriver( DPRINT1("RtlpGetRegistryHandle() failed (Status %x)\n", Status); return; } - +#ifdef FULLREG DwordData = 0; Length = sizeof(DWORD); Status = RtlWriteRegistryValue( @@ -177,7 +184,7 @@ VOID CreateDefaultRegistryForLegacyDriver( NtClose(KeyHandle); return; } - +#endif Length = (wcslen(Service->DeviceDesc) + 1) * sizeof(WCHAR); Status = RtlWriteRegistryValue( RTL_REGISTRY_HANDLE, @@ -192,7 +199,7 @@ VOID CreateDefaultRegistryForLegacyDriver( NtClose(KeyHandle); return; } - +#ifdef FULLREG DwordData = 0; Length = Length = sizeof(DWORD); Status = RtlWriteRegistryValue( @@ -208,7 +215,7 @@ VOID CreateDefaultRegistryForLegacyDriver( NtClose(KeyHandle); return; } - +#endif Length = (wcslen(Service->ServiceName) + 1) * sizeof(WCHAR); Status = RtlWriteRegistryValue( RTL_REGISTRY_HANDLE, @@ -226,6 +233,7 @@ VOID CreateDefaultRegistryForLegacyDriver( NtClose(KeyHandle); + /* Services section */ Status = RtlpGetRegistryHandle( @@ -238,7 +246,7 @@ VOID CreateDefaultRegistryForLegacyDriver( DPRINT1("RtlpGetRegistryHandle() failed (Status %x)\n", Status); return; } - +#ifdef FULLREG Length = (wcslen(Service->DeviceDesc) + 1) * sizeof(WCHAR); Status = RtlWriteRegistryValue( RTL_REGISTRY_HANDLE, @@ -284,7 +292,7 @@ VOID CreateDefaultRegistryForLegacyDriver( NtClose(KeyHandle); return; } - +#endif wcscpy(ImagePath, L"\\SystemRoot\\System32\\drivers\\"); wcscat(ImagePath, Service->ServiceName); wcscat(ImagePath, L".sys"); @@ -303,7 +311,7 @@ VOID CreateDefaultRegistryForLegacyDriver( NtClose(KeyHandle); return; } - +#if FULLREG DwordData = Service->Start; Length = sizeof(DWORD); Status = RtlWriteRegistryValue( @@ -335,7 +343,7 @@ VOID CreateDefaultRegistryForLegacyDriver( NtClose(KeyHandle); return; } - +#endif NtClose(KeyHandle); } @@ -347,14 +355,14 @@ VOID CreateDefaultRegistry() Status = RtlpCreateRegistryKeyPath(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); if (!NT_SUCCESS(Status)) { - DPRINT1("RtlpCreateRegistryKeyPath() (Status %x)\n", Status); + CPRINT("RtlpCreateRegistryKeyPath() (Status %x)\n", Status); return; } Status = RtlpCreateRegistryKeyPath(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); if (!NT_SUCCESS(Status)) { - DPRINT1("RtlpCreateRegistryKeyPath() (Status %x)\n", Status); + CPRINT("RtlpCreateRegistryKeyPath() (Status %x)\n", Status); return; } @@ -1051,7 +1059,7 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) * This should be done by the boot loader. */ strcpy (KeLoaderCommandLine, - "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=COM1"); + "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=SCREEN"); strcat (KeLoaderCommandLine, (PUCHAR)KeLoaderBlock.CommandLine); KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine; diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index 9037f22a07a..c9edc2ed3a1 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -1,4 +1,4 @@ -/* $Id: loader.c,v 1.89 2001/09/01 15:36:44 chorns Exp $ +/* $Id: loader.c,v 1.90 2001/09/16 13:19:32 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -882,6 +882,11 @@ VOID LdrLoadAutoConfigDrivers (VOID) #endif /* KDBG */ + /* + * PCI bus driver + */ + //LdrLoadAutoConfigDriver( L"pci.sys" ); + /* * Keyboard driver */ @@ -951,7 +956,7 @@ VOID LdrLoadAutoConfigDrivers (VOID) /* * Ancillary Function Driver */ - //LdrLoadAutoConfigDriver(L"afd.sys"); + LdrLoadAutoConfigDriver(L"afd.sys"); #endif } @@ -990,7 +995,11 @@ NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename, BOOLEAN BootDriversOnly) { PMODULE_OBJECT ModuleObject; + WCHAR Buffer[MAX_PATH]; NTSTATUS Status; + ULONG Length; + LPWSTR Start; + LPWSTR Ext; ModuleObject = LdrLoadModule(Filename); if (!ModuleObject) @@ -998,6 +1007,25 @@ NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename, return STATUS_UNSUCCESSFUL; } + /* Set a service name for the device node */ + + /* Get the service name from the module name */ + Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\'); + if (Start == NULL) + Start = ModuleObject->BaseName.Buffer; + else + Start++; + + Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.'); + if (Ext != NULL) + Length = Ext - Start; + else + Length = wcslen(Start); + + wcsncpy(Buffer, Start, Length); + RtlInitUnicodeString(&DeviceNode->ServiceName, Buffer); + + Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode); if (!NT_SUCCESS(Status)) {