update for HEAD-2003091401
[reactos.git] / ntoskrnl / io / device.c
1 /* $Id$
2  *
3  * COPYRIGHT:      See COPYING in the top level directory
4  * PROJECT:        ReactOS kernel
5  * FILE:           ntoskrnl/io/device.c
6  * PURPOSE:        Manage devices
7  * PROGRAMMER:     David Welch (welch@cwcom.net)
8  * UPDATE HISTORY:
9  *                 15/05/98: Created
10  */
11
12 /* INCLUDES ****************************************************************/
13
14 #define NTOS_MODE_KERNEL
15 #include <ntos.h>
16 #include <internal/io.h>
17 #include <internal/po.h>
18 #include <internal/ldr.h>
19 #include <internal/id.h>
20 #include <internal/pool.h>
21 #include <internal/registry.h>
22
23 #include <roscfg.h>
24
25 #define NDEBUG
26 //#define DBG
27 #include <internal/debug.h>
28
29 /* GLOBALS *******************************************************************/
30
31 #define TAG_DRIVER             TAG('D', 'R', 'V', 'R')
32 #define TAG_DRIVER_EXTENSION   TAG('D', 'R', 'V', 'E')
33 #define TAG_DEVICE_EXTENSION   TAG('D', 'E', 'X', 'T')
34
35 #define DRIVER_REGISTRY_KEY_BASENAME  L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
36
37 /* FUNCTIONS ***************************************************************/
38
39 /*
40  * @implemented
41  */
42 NTSTATUS STDCALL
43 IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice,
44                         IN PDEVICE_OBJECT TargetDevice)
45 {
46         PDEVICE_OBJECT AttachedDevice;
47
48         DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
49                SourceDevice,
50                TargetDevice);
51
52         AttachedDevice = IoAttachDeviceToDeviceStack (SourceDevice,
53                                                       TargetDevice);
54         if (AttachedDevice == NULL)
55                 return STATUS_NO_SUCH_DEVICE;
56
57         return STATUS_SUCCESS;
58 }
59
60
61 /*
62  * @implemented
63  */
64 VOID STDCALL
65 IoDeleteDevice(PDEVICE_OBJECT DeviceObject)
66 {
67         PDEVICE_OBJECT Previous;
68
69         if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED)
70                 IoUnregisterShutdownNotification(DeviceObject);
71
72         /* remove the timer if it exists */
73         if (DeviceObject->Timer)
74         {
75                 IoStopTimer(DeviceObject);
76                 ExFreePool(DeviceObject->Timer);
77         }
78
79         /* free device extension */
80         if (DeviceObject->DeviceObjectExtension)
81                 ExFreePool (DeviceObject->DeviceObjectExtension);
82
83         /* remove device from driver device list */
84         Previous = DeviceObject->DriverObject->DeviceObject;
85         if (Previous == DeviceObject)
86         {
87                 DeviceObject->DriverObject->DeviceObject = DeviceObject->NextDevice;
88         }
89         else
90         {
91                 while (Previous->NextDevice != DeviceObject)
92                         Previous = Previous->NextDevice;
93                 Previous->NextDevice = DeviceObject->NextDevice;
94         }
95
96         ObDereferenceObject (DeviceObject);
97 }
98
99
100 /*
101  * @implemented
102  */
103 PDEVICE_OBJECT
104 STDCALL
105 IoGetRelatedDeviceObject (
106         IN      PFILE_OBJECT    FileObject
107         )
108 {
109    /*Win NT File System Internals, page 633-634*/
110
111    /*get logical volume mounted on a physical/virtual/logical device*/
112    if (FileObject->Vpb && FileObject->Vpb->DeviceObject)
113    {
114       return IoGetAttachedDevice(FileObject->Vpb->DeviceObject);
115    }
116
117    /*check if fileobject has an associated device object mounted by some other file system*/
118    if (FileObject->DeviceObject->Vpb && FileObject->DeviceObject->Vpb->DeviceObject)
119    {
120       return IoGetAttachedDevice(FileObject->DeviceObject->Vpb->DeviceObject);
121    }
122
123    return IoGetAttachedDevice(FileObject->DeviceObject);
124 }
125
126
127 /*
128  * @implemented
129  */
130 NTSTATUS
131 STDCALL
132 IoGetDeviceObjectPointer (
133         IN      PUNICODE_STRING ObjectName,
134         IN      ACCESS_MASK     DesiredAccess,
135         OUT     PFILE_OBJECT    * FileObject,
136         OUT     PDEVICE_OBJECT  * DeviceObject)
137 {
138         OBJECT_ATTRIBUTES ObjectAttributes;
139         IO_STATUS_BLOCK StatusBlock;
140         PFILE_OBJECT LocalFileObject;
141         HANDLE FileHandle;
142         NTSTATUS Status;
143
144         DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
145                ObjectName,
146                DesiredAccess,
147                FileObject,
148                DeviceObject);
149
150         InitializeObjectAttributes (&ObjectAttributes,
151                                     ObjectName,
152                                     0,
153                                     NULL,
154                                     NULL);
155
156         Status = NtOpenFile (&FileHandle,
157                              DesiredAccess,
158                              &ObjectAttributes,
159                              &StatusBlock,
160                              0,
161                              FILE_NON_DIRECTORY_FILE);
162         if (!NT_SUCCESS(Status))
163                 return Status;
164
165         Status = ObReferenceObjectByHandle (FileHandle,
166                                             0,
167                                             IoFileObjectType,
168                                             KernelMode,
169                                             (PVOID*)&LocalFileObject,
170                                             NULL);
171         if (NT_SUCCESS(Status))
172         {
173                 *DeviceObject = IoGetRelatedDeviceObject (LocalFileObject);
174                 *FileObject = LocalFileObject;
175         }
176         NtClose (FileHandle);
177
178         return Status;
179 }
180
181
182 /*
183  * @unimplemented
184  */
185 VOID
186 STDCALL
187 IoDetachDevice(PDEVICE_OBJECT TargetDevice)
188 {
189 //   UNIMPLEMENTED;
190    DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice);
191 }
192
193
194 /*
195  * @implemented
196  */
197 PDEVICE_OBJECT
198 STDCALL
199 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
200 {
201    PDEVICE_OBJECT Current = DeviceObject;
202    
203 //   DPRINT("IoGetAttachedDevice(DeviceObject %x)\n",DeviceObject);
204    
205    while (Current->AttachedDevice!=NULL)
206      {
207         Current = Current->AttachedDevice;
208 //      DPRINT("Current %x\n",Current);
209      }
210
211 //   DPRINT("IoGetAttachedDevice() = %x\n",DeviceObject);
212    return(Current);
213 }
214
215 /*
216  * @implemented
217  */
218 PDEVICE_OBJECT
219 STDCALL
220 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
221 {
222    PDEVICE_OBJECT Current = DeviceObject;
223
224    while (Current->AttachedDevice!=NULL)
225      {
226         Current = Current->AttachedDevice;
227      }
228
229    ObReferenceObject(Current);
230    return(Current);
231 }
232
233 /*
234  * @implemented
235  */
236 PDEVICE_OBJECT STDCALL
237 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice,
238                             PDEVICE_OBJECT TargetDevice)
239 {
240    PDEVICE_OBJECT AttachedDevice;
241    
242    DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
243           SourceDevice,TargetDevice);
244
245    AttachedDevice = IoGetAttachedDevice(TargetDevice);
246    AttachedDevice->AttachedDevice = SourceDevice;
247    SourceDevice->AttachedDevice = NULL;
248    SourceDevice->StackSize = AttachedDevice->StackSize + 1;
249    SourceDevice->Vpb = AttachedDevice->Vpb;
250    return(AttachedDevice);
251 }
252
253 /*
254  * @unimplemented
255  */
256 VOID STDCALL
257 IoRegisterDriverReinitialization(PDRIVER_OBJECT DriverObject,
258                                  PDRIVER_REINITIALIZE ReinitRoutine,
259                                  PVOID Context)
260 {
261    UNIMPLEMENTED;
262 }
263
264 NTSTATUS STDCALL
265 IopDefaultDispatchFunction(PDEVICE_OBJECT DeviceObject,
266                            PIRP Irp)
267 {
268   Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
269   Irp->IoStatus.Information = 0;
270
271   IoCompleteRequest(Irp, IO_NO_INCREMENT);
272   return(STATUS_NOT_IMPLEMENTED);
273 }
274
275
276 NTSTATUS
277 IopCreateDriverObject(PDRIVER_OBJECT *DriverObject,
278                       PUNICODE_STRING ServiceName,
279                       BOOLEAN FileSystem,
280                       PVOID DriverImageStart,
281                       ULONG DriverImageSize)
282 {
283   PDRIVER_OBJECT Object;
284   HANDLE DriverHandle = 0;
285   ULONG i;
286   WCHAR NameBuffer[MAX_PATH];
287   UNICODE_STRING DriverName;
288   OBJECT_ATTRIBUTES ObjectAttributes;
289   NTSTATUS Status;
290
291   DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n", DriverObject, ServiceName, FileSystem,
292          DriverImageStart, DriverImageSize);
293
294   *DriverObject = NULL;
295
296   /*  Create ModuleName string  */
297   if ((ServiceName != NULL) && (ServiceName->Buffer != NULL))
298     {
299       if (FileSystem == TRUE)
300         wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
301       else
302         wcscpy(NameBuffer, DRIVER_ROOT_NAME);
303       wcscat(NameBuffer, ServiceName->Buffer);
304
305       RtlInitUnicodeString(&DriverName,
306                            NameBuffer);
307       DPRINT("Driver name: '%wZ'\n", &DriverName);
308     }
309
310   /* Initialize ObjectAttributes for driver object */
311   InitializeObjectAttributes(&ObjectAttributes,
312                              ((ServiceName != NULL) && (ServiceName->Buffer != NULL))? &DriverName : NULL,
313                              OBJ_PERMANENT,
314                              NULL,
315                              NULL);
316
317   /* Create module object */
318   Status = ObRosCreateObject(&DriverHandle,
319                           STANDARD_RIGHTS_REQUIRED,
320                           &ObjectAttributes,
321                           IoDriverObjectType,
322                           (PVOID*)&Object);
323   if (!NT_SUCCESS(Status))
324     {
325       return(Status);
326     }
327
328   NtClose(DriverHandle);
329
330   /* Create driver extension */
331   Object->DriverExtension = (PDRIVER_EXTENSION)
332     ExAllocatePoolWithTag(NonPagedPool,
333        sizeof(DRIVER_EXTENSION),
334        TAG_DRIVER_EXTENSION);
335   if (Object->DriverExtension == NULL)
336     {
337       ExFreePool(Object);
338       return(STATUS_INSUFFICIENT_RESOURCES);
339     }
340
341   RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
342
343   Object->Type = InternalDriverType;
344
345   Object->DriverStart = DriverImageStart;
346   Object->DriverSize = DriverImageSize;
347
348   for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
349     {
350        Object->MajorFunction[i] = (PDRIVER_DISPATCH) IopDefaultDispatchFunction;
351     }
352
353   *DriverObject = Object;
354
355   return STATUS_SUCCESS;
356 }
357
358 NTSTATUS
359 IopAttachFilterDrivers(PDEVICE_NODE DeviceNode,
360                        BOOLEAN Lower)
361 {
362   return STATUS_SUCCESS;
363 }
364
365 NTSTATUS 
366 IopInitializeDevice(PDEVICE_NODE DeviceNode,
367                     BOOLEAN BootDriversOnly)
368 {
369   IO_STATUS_BLOCK       IoStatusBlock;
370   PDRIVER_OBJECT DriverObject;
371   IO_STACK_LOCATION Stack;
372   PDEVICE_OBJECT Fdo;
373   NTSTATUS Status;
374
375   DriverObject = DeviceNode->DriverObject;
376
377   if (DriverObject->DriverExtension->AddDevice)
378     {
379       /* This is a Plug and Play driver */
380       DPRINT("Plug and Play driver found\n");
381
382       assert(DeviceNode->Pdo);
383
384       DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
385         DriverObject->DriverExtension->AddDevice);
386       Status = DriverObject->DriverExtension->AddDevice(
387         DriverObject, DeviceNode->Pdo);
388       if (!NT_SUCCESS(Status))
389         {
390                 return(Status);
391         }
392
393       IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
394
395       DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
396
397       Fdo = IoGetAttachedDeviceReference(DeviceNode->Pdo);
398
399       if (Fdo == DeviceNode->Pdo)
400         {
401           /* FIXME: What do we do? Unload the driver or just disable the device? */
402           DbgPrint("An FDO was not attached\n");
403           KEBUGCHECK(0);
404         }
405
406       /* FIXME: Put some resources in the IRP for the device */
407       Stack.Parameters.StartDevice.AllocatedResources = NULL;
408       Stack.Parameters.StartDevice.AllocatedResourcesTranslated = NULL;
409
410       Status = IopInitiatePnpIrp(
411         Fdo,
412         &IoStatusBlock,
413         IRP_MN_START_DEVICE,
414         &Stack);
415       if (!NT_SUCCESS(Status))
416         {
417           DPRINT("IopInitiatePnpIrp() failed\n");
418           ObDereferenceObject(Fdo);
419                 return(Status);
420         }
421
422       if (Fdo->DeviceType == FILE_DEVICE_BUS_EXTENDER)
423         {
424           DPRINT("Bus extender found\n");
425
426           Status = IopInterrogateBusExtender(
427             DeviceNode, Fdo, BootDriversOnly);
428           if (!NT_SUCCESS(Status))
429             {
430               ObDereferenceObject(Fdo);
431                     return(Status);
432             }
433         }
434       else if (Fdo->DeviceType == FILE_DEVICE_ACPI)
435         {
436 #ifdef ACPI
437           static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
438
439           /* There can be only one system power device */
440           if (!SystemPowerDeviceNodeCreated)
441             {
442               PopSystemPowerDeviceNode = DeviceNode;
443               SystemPowerDeviceNodeCreated = TRUE;
444             }
445 #endif /* ACPI */
446         }
447       ObDereferenceObject(Fdo);
448     }
449
450   return STATUS_SUCCESS;
451 }
452
453 NTSTATUS
454 IopInitializeService(
455   PDEVICE_NODE DeviceNode,
456   PUNICODE_STRING ImagePath)
457 {
458   PMODULE_OBJECT ModuleObject;
459   NTSTATUS Status;
460
461   ModuleObject = LdrGetModuleObject(&DeviceNode->ServiceName);
462   if (ModuleObject == NULL)
463   {
464     /* The module is currently not loaded, so load it now */
465
466     Status = LdrLoadModule(ImagePath, &ModuleObject);
467     if (!NT_SUCCESS(Status))
468     {
469       /* FIXME: Log the error */
470       CPRINT("Driver load failed\n");
471       return(Status);
472     }
473
474     Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, FALSE,
475                                  ModuleObject->Base, ModuleObject->Length);
476     if (!NT_SUCCESS(Status))
477     {
478       LdrUnloadModule(ModuleObject);
479
480       /* FIXME: Log the error */
481       CPRINT("A driver failed to initialize\n");
482       return(Status);
483     }
484   }
485
486   Status = IopInitializeDevice(DeviceNode, TRUE);
487
488   return(Status);
489 }
490
491 NTSTATUS
492 IopInitializeDeviceNodeService(PDEVICE_NODE DeviceNode)
493 {
494   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
495   UNICODE_STRING ImagePath;
496   HANDLE KeyHandle;
497   NTSTATUS Status;
498
499   Status = RtlpGetRegistryHandle(
500     RTL_REGISTRY_SERVICES,
501           DeviceNode->ServiceName.Buffer,
502                 TRUE,
503                 &KeyHandle);
504   if (!NT_SUCCESS(Status))
505     {
506       DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
507       return(Status);
508     }
509
510   RtlZeroMemory(QueryTable, sizeof(QueryTable));
511
512   RtlInitUnicodeString(&ImagePath, NULL);
513
514   QueryTable[0].Name = L"ImagePath";
515   QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
516   QueryTable[0].EntryContext = &ImagePath;
517
518   Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
519                                   (PWSTR)KeyHandle,
520                                   QueryTable,
521                                   NULL,
522                                   NULL);
523   NtClose(KeyHandle);
524
525   DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
526
527   if (NT_SUCCESS(Status))
528     {
529       DPRINT("Got ImagePath %S\n", ImagePath.Buffer);
530
531       Status = IopInitializeService(DeviceNode, &ImagePath);
532
533       RtlFreeUnicodeString(&ImagePath);
534     }
535
536   return(Status);
537 }
538
539 NTSTATUS
540 IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
541                     PDEVICE_NODE DeviceNode,
542                     BOOLEAN FileSystemDriver,
543                     PVOID DriverImageStart,
544                     ULONG DriverImageSize)
545 /*
546  * FUNCTION: Called to initalize a loaded driver
547  * ARGUMENTS:
548  *   DriverEntry = Pointer to driver entry routine
549  *   DeviceNode  = Pointer to device node
550  */
551 {
552   WCHAR RegistryKeyBuffer[MAX_PATH];
553   PDRIVER_OBJECT DriverObject;
554   UNICODE_STRING RegistryKey;
555   NTSTATUS Status;
556
557   DPRINT("IopInitializeDriver(DriverEntry %08lx, DeviceNode %08lx)\n",
558     DriverEntry, DeviceNode);
559
560   Status = IopCreateDriverObject(&DriverObject,
561                                  &DeviceNode->ServiceName,
562                                  FileSystemDriver,
563                                  DriverImageStart,
564                                  DriverImageSize);
565   if (!NT_SUCCESS(Status))
566     {
567       return(Status);
568     }
569
570   DeviceNode->DriverObject = DriverObject;
571
572   if (DeviceNode->ServiceName.Buffer)
573     {
574       wcscpy(RegistryKeyBuffer, DRIVER_REGISTRY_KEY_BASENAME);
575       wcscat(RegistryKeyBuffer, DeviceNode->ServiceName.Buffer);
576       RtlInitUnicodeString(&RegistryKey, RegistryKeyBuffer);
577     }
578   else
579     {
580       RtlInitUnicodeString(&RegistryKey, NULL);
581     }
582
583   DPRINT("RegistryKey: %wZ\n", &RegistryKey);
584   DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
585
586   Status = DriverEntry(DriverObject, &RegistryKey);
587   if (!NT_SUCCESS(Status))
588     {
589       DeviceNode->DriverObject = NULL;
590       ExFreePool(DriverObject->DriverExtension);
591       ObMakeTemporaryObject(DriverObject);
592       ObDereferenceObject(DriverObject);
593       return(Status);
594     }
595
596   Status = IopInitializeDevice(DeviceNode, TRUE);
597
598   return(Status);
599 }
600
601
602 /*
603  * @implemented
604  */
605 NTSTATUS STDCALL
606 IoAttachDevice(PDEVICE_OBJECT SourceDevice,
607           PUNICODE_STRING TargetDeviceName,
608                PDEVICE_OBJECT* AttachedDevice)
609 /*
610  * FUNCTION: Layers a device over the highest device in a device stack
611  * ARGUMENTS:
612  *       SourceDevice = Device to attached
613  *       TargetDevice = Name of the target device
614  *       AttachedDevice (OUT) = Caller storage for the device attached to
615  */
616 {
617    NTSTATUS       Status;
618    PFILE_OBJECT   FileObject;
619    PDEVICE_OBJECT TargetDevice;
620      
621    Status = IoGetDeviceObjectPointer(TargetDeviceName,
622                                      FILE_READ_ATTRIBUTES,
623                                      &FileObject,
624                                      &TargetDevice);
625    
626    if (!NT_SUCCESS(Status))
627    {
628       return Status;
629    }
630
631    *AttachedDevice = IoAttachDeviceToDeviceStack(SourceDevice,
632                                                  TargetDevice);
633
634    ObDereferenceObject(FileObject);
635    return STATUS_SUCCESS;
636 }
637
638
639 NTSTATUS STDCALL
640 IopCreateDevice(PVOID ObjectBody,
641                 PVOID Parent,
642                 PWSTR RemainingPath,
643                 POBJECT_ATTRIBUTES ObjectAttributes)
644 {
645    
646    DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
647           ObjectBody, Parent, RemainingPath);
648    
649    if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
650      {
651         return(STATUS_UNSUCCESSFUL);
652      }
653    
654    return(STATUS_SUCCESS);
655 }
656
657
658 /*
659  * @implemented
660  */
661 NTSTATUS STDCALL
662 IoCreateDevice(PDRIVER_OBJECT DriverObject,
663                ULONG DeviceExtensionSize,
664                PUNICODE_STRING DeviceName,
665                DEVICE_TYPE DeviceType,
666                ULONG DeviceCharacteristics,
667                BOOLEAN Exclusive,
668                PDEVICE_OBJECT* DeviceObject)
669 /*
670  * FUNCTION: Allocates memory for and intializes a device object for use for
671  * a driver
672  * ARGUMENTS:
673  *         DriverObject : Driver object passed by iomgr when the driver was
674  *                        loaded
675  *         DeviceExtensionSize : Number of bytes for the device extension
676  *         DeviceName : Unicode name of device
677  *         DeviceType : Device type
678  *         DeviceCharacteristics : Bit mask of device characteristics
679  *         Exclusive : True if only one thread can access the device at a
680  *                     time
681  * RETURNS:
682  *         Success or failure
683  *         DeviceObject : Contains a pointer to allocated device object
684  *                        if the call succeeded
685  * NOTES: See the DDK documentation for more information
686  */
687 {
688    PDEVICE_OBJECT CreatedDeviceObject;
689    OBJECT_ATTRIBUTES ObjectAttributes;
690    NTSTATUS Status;
691    
692    assert_irql(PASSIVE_LEVEL);
693    
694    if (DeviceName != NULL)
695      {
696         DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",DriverObject,
697                DeviceName->Buffer);
698      }
699    else
700      {
701         DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
702      }
703    
704    if (DeviceName != NULL)
705      {
706         InitializeObjectAttributes(&ObjectAttributes,DeviceName,0,NULL,NULL);
707         Status = ObRosCreateObject(NULL,
708                                 0,
709                                 &ObjectAttributes,
710                                 IoDeviceObjectType,
711                                 (PVOID*)&CreatedDeviceObject);
712      }
713    else
714      {
715         Status = ObRosCreateObject(NULL,
716                                 0,
717                                 NULL,
718                                 IoDeviceObjectType,
719                                 (PVOID*)&CreatedDeviceObject);
720      }
721    
722    *DeviceObject = NULL;
723    
724    if (!NT_SUCCESS(Status))
725      {
726         DPRINT("IoCreateDevice() ObRosCreateObject failed, status: 0x%08X\n", Status);
727         return(Status);
728      }
729   
730    if (DriverObject->DeviceObject == NULL)
731      {
732         DriverObject->DeviceObject = CreatedDeviceObject;
733         CreatedDeviceObject->NextDevice = NULL;
734      }
735    else
736      {
737         CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
738         DriverObject->DeviceObject = CreatedDeviceObject;
739      }
740   
741   CreatedDeviceObject->Type = DeviceType;
742   CreatedDeviceObject->DriverObject = DriverObject;
743   CreatedDeviceObject->CurrentIrp = NULL;
744   CreatedDeviceObject->Flags = 0;
745
746   CreatedDeviceObject->DeviceExtension = 
747     ExAllocatePoolWithTag(NonPagedPool, DeviceExtensionSize,
748                           TAG_DEVICE_EXTENSION);
749   if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL)
750     {
751       ExFreePool(CreatedDeviceObject);
752       DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES);
753       return(STATUS_INSUFFICIENT_RESOURCES);
754     }
755
756   if (DeviceExtensionSize > 0)
757     {
758       RtlZeroMemory(CreatedDeviceObject->DeviceExtension,
759                     DeviceExtensionSize);
760     }
761
762   CreatedDeviceObject->AttachedDevice = NULL;
763   CreatedDeviceObject->DeviceType = DeviceType;
764   CreatedDeviceObject->StackSize = 1;
765   CreatedDeviceObject->AlignmentRequirement = 1;
766   KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
767   
768   KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
769                     SynchronizationEvent,
770                     TRUE);
771   
772   /* FIXME: Do we need to add network drives too?! */
773   if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
774       CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
775       CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
776     {
777       IoAttachVpb(CreatedDeviceObject);
778     }
779   
780   *DeviceObject = CreatedDeviceObject;
781   
782   return(STATUS_SUCCESS);
783 }
784
785
786 NTSTATUS
787 STDCALL
788 IoOpenDeviceInstanceKey (
789         DWORD   Unknown0,
790         DWORD   Unknown1,
791         DWORD   Unknown2,
792         DWORD   Unknown3,
793         DWORD   Unknown4
794         )
795 {
796   UNIMPLEMENTED;
797   return(STATUS_NOT_IMPLEMENTED);
798 }
799
800
801 DWORD
802 STDCALL
803 IoQueryDeviceEnumInfo (
804         DWORD   Unknown0,
805         DWORD   Unknown1
806         )
807 {
808   UNIMPLEMENTED;
809   return 0;
810 }
811
812
813 /* EOF */