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