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