Put in alphabetical order, remove IopCreateDevice, and remove incorrect implementatio...
[reactos.git] / reactos / 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 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ********************************************************************/
18
19 #define TAG_DEVICE_EXTENSION TAG('D', 'E', 'X', 'T')
20
21 static ULONG IopDeviceObjectNumber = 0;
22
23 /* PRIVATE FUNCTIONS **********************************************************/
24
25 NTSTATUS FASTCALL
26 IopInitializeDevice(
27 PDEVICE_NODE DeviceNode,
28 PDRIVER_OBJECT DriverObject)
29 {
30 IO_STATUS_BLOCK IoStatusBlock;
31 IO_STACK_LOCATION Stack;
32 PDEVICE_OBJECT Fdo;
33 NTSTATUS Status;
34
35 if (DriverObject->DriverExtension->AddDevice)
36 {
37 /* This is a Plug and Play driver */
38 DPRINT("Plug and Play driver found\n");
39
40 ASSERT(DeviceNode->PhysicalDeviceObject);
41
42 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
43 DriverObject->DriverExtension->AddDevice);
44
45 Status = DriverObject->DriverExtension->AddDevice(
46 DriverObject, DeviceNode->PhysicalDeviceObject);
47
48 if (!NT_SUCCESS(Status))
49 {
50 return Status;
51 }
52
53 Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
54
55 if (Fdo == DeviceNode->PhysicalDeviceObject)
56 {
57 /* FIXME: What do we do? Unload the driver or just disable the device? */
58 DbgPrint("An FDO was not attached\n");
59 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
60 return STATUS_UNSUCCESSFUL;
61 }
62
63 IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
64
65 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
66
67 /* FIXME: Should be DeviceNode->ResourceList */
68 Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->BootResources;
69 /* FIXME: Should be DeviceNode->ResourceListTranslated */
70 Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->BootResources;
71
72 Status = IopInitiatePnpIrp(
73 Fdo,
74 &IoStatusBlock,
75 IRP_MN_START_DEVICE,
76 &Stack);
77
78 if (!NT_SUCCESS(Status))
79 {
80 DPRINT("IopInitiatePnpIrp() failed\n");
81 ObDereferenceObject(Fdo);
82 return Status;
83 }
84
85 if (Fdo->DeviceType == FILE_DEVICE_ACPI)
86 {
87 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
88
89 /* There can be only one system power device */
90 if (!SystemPowerDeviceNodeCreated)
91 {
92 PopSystemPowerDeviceNode = DeviceNode;
93 SystemPowerDeviceNodeCreated = TRUE;
94 }
95 }
96
97 if (Fdo->DeviceType == FILE_DEVICE_BUS_EXTENDER ||
98 Fdo->DeviceType == FILE_DEVICE_ACPI)
99 {
100 DPRINT("Bus extender found\n");
101
102 Status = IopInvalidateDeviceRelations(DeviceNode, BusRelations);
103 if (!NT_SUCCESS(Status))
104 {
105 ObDereferenceObject(Fdo);
106 return Status;
107 }
108 }
109
110 ObDereferenceObject(Fdo);
111 }
112
113 return STATUS_SUCCESS;
114 }
115
116 NTSTATUS
117 STDCALL
118 IopGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName,
119 IN ACCESS_MASK DesiredAccess,
120 OUT PFILE_OBJECT *FileObject,
121 OUT PDEVICE_OBJECT *DeviceObject,
122 IN ULONG AttachFlag)
123 {
124 OBJECT_ATTRIBUTES ObjectAttributes;
125 IO_STATUS_BLOCK StatusBlock;
126 PFILE_OBJECT LocalFileObject;
127 HANDLE FileHandle;
128 NTSTATUS Status;
129
130 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x,"
131 "FileObject %p DeviceObject %p)\n",
132 ObjectName, DesiredAccess, FileObject, DeviceObject);
133
134 /* Open the Device */
135 InitializeObjectAttributes(&ObjectAttributes,
136 ObjectName,
137 0,
138 NULL,
139 NULL);
140 Status = ZwOpenFile(&FileHandle,
141 DesiredAccess,
142 &ObjectAttributes,
143 &StatusBlock,
144 0,
145 FILE_NON_DIRECTORY_FILE | AttachFlag);
146
147 if (!NT_SUCCESS(Status))
148 {
149 DPRINT1("NtOpenFile failed, Status: 0x%x\n", Status);
150 return Status;
151 }
152
153 /* Get File Object */
154 Status = ObReferenceObjectByHandle(FileHandle,
155 0,
156 IoFileObjectType,
157 KernelMode,
158 (PVOID*)&LocalFileObject,
159 NULL);
160 if (NT_SUCCESS(Status))
161 {
162 /* Return the requested data */
163 *DeviceObject = IoGetRelatedDeviceObject(LocalFileObject);
164 *FileObject = LocalFileObject;
165 }
166
167 /* Close the handle */
168 ZwClose(FileHandle);
169 return Status;
170 }
171
172 /* PUBLIC FUNCTIONS ***********************************************************/
173
174 /*
175 * IoAttachDevice
176 *
177 * Layers a device over the highest device in a device stack.
178 *
179 * Parameters
180 * SourceDevice
181 * Device to be attached.
182 *
183 * TargetDevice
184 * Name of the target device.
185 *
186 * AttachedDevice
187 * Caller storage for the device attached to.
188 *
189 * Status
190 * @implemented
191 */
192 NTSTATUS
193 STDCALL
194 IoAttachDevice(PDEVICE_OBJECT SourceDevice,
195 PUNICODE_STRING TargetDeviceName,
196 PDEVICE_OBJECT *AttachedDevice)
197 {
198 NTSTATUS Status;
199 PFILE_OBJECT FileObject;
200 PDEVICE_OBJECT TargetDevice;
201
202 /* Call the helper routine for an attach operation */
203 DPRINT("IoAttachDevice\n");
204 Status = IopGetDeviceObjectPointer(TargetDeviceName,
205 FILE_READ_ATTRIBUTES,
206 &FileObject,
207 &TargetDevice,
208 IO_ATTACH_DEVICE_API);
209
210 if (!NT_SUCCESS(Status))
211 {
212 DPRINT1("Failed to get Device Object\n");
213 return Status;
214 }
215
216 /* Attach the device */
217 IoAttachDeviceToDeviceStackSafe(SourceDevice, TargetDevice, AttachedDevice);
218
219 /* Derference it */
220 ObDereferenceObject(FileObject);
221 return STATUS_SUCCESS;
222 }
223
224 /*
225 * IoAttachDeviceByPointer
226 *
227 * Status
228 * @implemented
229 */
230 NTSTATUS
231 STDCALL
232 IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice,
233 IN PDEVICE_OBJECT TargetDevice)
234 {
235 PDEVICE_OBJECT AttachedDevice;
236 NTSTATUS Status = STATUS_SUCCESS;
237
238 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
239 SourceDevice, TargetDevice);
240
241 /* Do the Attach */
242 AttachedDevice = IoAttachDeviceToDeviceStack(SourceDevice, TargetDevice);
243 if (AttachedDevice == NULL) Status = STATUS_NO_SUCH_DEVICE;
244
245 /* Return the status */
246 return Status;
247 }
248
249 /*
250 * IoAttachDeviceToDeviceStack
251 *
252 * Status
253 * @implemented
254 */
255 PDEVICE_OBJECT
256 STDCALL
257 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice,
258 PDEVICE_OBJECT TargetDevice)
259 {
260 NTSTATUS Status;
261 PDEVICE_OBJECT LocalAttach;
262
263 /* Attach it safely */
264 DPRINT("IoAttachDeviceToDeviceStack\n");
265 Status = IoAttachDeviceToDeviceStackSafe(SourceDevice,
266 TargetDevice,
267 &LocalAttach);
268
269 /* Return it */
270 DPRINT("IoAttachDeviceToDeviceStack DONE: %x\n", LocalAttach);
271 return LocalAttach;
272 }
273
274 /*
275 * @implemented
276 */
277 NTSTATUS
278 STDCALL
279 IoAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice,
280 IN PDEVICE_OBJECT TargetDevice,
281 OUT PDEVICE_OBJECT *AttachedToDeviceObject)
282 {
283 PDEVICE_OBJECT AttachedDevice;
284 PDEVOBJ_EXTENSION SourceDeviceExtension;
285
286 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
287 SourceDevice, TargetDevice);
288
289 /* Get the Attached Device and source extension */
290 AttachedDevice = IoGetAttachedDevice(TargetDevice);
291 SourceDeviceExtension = SourceDevice->DeviceObjectExtension;
292
293 /* Make sure that it's in a correct state */
294 if (!(AttachedDevice->DeviceObjectExtension->ExtensionFlags &
295 (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING |
296 DOE_REMOVE_PENDING | DOE_REMOVE_PROCESSED)))
297 {
298 /* Update fields */
299 AttachedDevice->AttachedDevice = SourceDevice;
300 SourceDevice->AttachedDevice = NULL;
301 SourceDevice->StackSize = AttachedDevice->StackSize + 1;
302 SourceDevice->AlignmentRequirement = AttachedDevice->AlignmentRequirement;
303 SourceDevice->SectorSize = AttachedDevice->SectorSize;
304 SourceDevice->Vpb = AttachedDevice->Vpb;
305
306 /* Set the attachment in the device extension */
307 SourceDeviceExtension->AttachedTo = AttachedDevice;
308 }
309 else
310 {
311 /* Device was unloading or being removed */
312 AttachedDevice = NULL;
313 }
314
315 /* Return the attached device */
316 *AttachedToDeviceObject = AttachedDevice;
317 return STATUS_SUCCESS;
318 }
319
320 /*
321 * IoCreateDevice
322 *
323 * Allocates memory for and intializes a device object for use for
324 * a driver.
325 *
326 * Parameters
327 * DriverObject
328 * Driver object passed by IO Manager when the driver was loaded.
329 *
330 * DeviceExtensionSize
331 * Number of bytes for the device extension.
332 *
333 * DeviceName
334 * Unicode name of device.
335 *
336 * DeviceType
337 * Device type of the new device.
338 *
339 * DeviceCharacteristics
340 * Bit mask of device characteristics.
341 *
342 * Exclusive
343 * TRUE if only one thread can access the device at a time.
344 *
345 * DeviceObject
346 * On successful return this parameter is filled by pointer to
347 * allocated device object.
348 *
349 * Status
350 * @implemented
351 */
352 NTSTATUS
353 STDCALL
354 IoCreateDevice(PDRIVER_OBJECT DriverObject,
355 ULONG DeviceExtensionSize,
356 PUNICODE_STRING DeviceName,
357 DEVICE_TYPE DeviceType,
358 ULONG DeviceCharacteristics,
359 BOOLEAN Exclusive,
360 PDEVICE_OBJECT *DeviceObject)
361 {
362 WCHAR AutoNameBuffer[20];
363 UNICODE_STRING AutoName;
364 PDEVICE_OBJECT CreatedDeviceObject;
365 PDEVOBJ_EXTENSION DeviceObjectExtension;
366 OBJECT_ATTRIBUTES ObjectAttributes;
367 NTSTATUS Status;
368 ULONG AlignedDeviceExtensionSize;
369 ULONG TotalSize;
370 HANDLE TempHandle;
371
372 ASSERT_IRQL(PASSIVE_LEVEL);
373 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
374
375 /* Generate a name if we have to */
376 if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME)
377 {
378 swprintf(AutoNameBuffer,
379 L"\\Device\\%08lx",
380 InterlockedIncrementUL(&IopDeviceObjectNumber));
381 RtlInitUnicodeString(&AutoName, AutoNameBuffer);
382 DeviceName = &AutoName;
383 }
384
385 /* Initialize the Object Attributes */
386 InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL);
387
388 /* Honour exclusive flag */
389 ObjectAttributes.Attributes |= OBJ_EXCLUSIVE;
390
391 /* Align the Extension Size to 8-bytes */
392 AlignedDeviceExtensionSize = (DeviceExtensionSize + 7) &~ 7;
393 DPRINT("AlignedDeviceExtensionSize %x\n", AlignedDeviceExtensionSize);
394
395 /* Total Size */
396 TotalSize = AlignedDeviceExtensionSize +
397 sizeof(DEVICE_OBJECT) + sizeof(DEVOBJ_EXTENSION);
398 DPRINT("TotalSize %x\n", TotalSize);
399
400 /* Create the Device Object */
401 Status = ObCreateObject(KernelMode,
402 IoDeviceObjectType,
403 &ObjectAttributes,
404 KernelMode,
405 NULL,
406 TotalSize,
407 0,
408 0,
409 (PVOID*)&CreatedDeviceObject);
410
411 if (!NT_SUCCESS(Status))
412 {
413 DPRINT1("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status);
414 return Status;
415 }
416
417 /* Clear the whole Object and extension so we don't null stuff manually */
418 RtlZeroMemory(CreatedDeviceObject, TotalSize);
419 DPRINT("CreatedDeviceObject %x\n", CreatedDeviceObject);
420
421 /*
422 * Setup the Type and Size. Note that we don't use the aligned size,
423 * because that's only padding for the DevObjExt and not part of the Object.
424 */
425 CreatedDeviceObject->Type = IO_TYPE_DEVICE;
426 CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + DeviceExtensionSize;
427
428 /* The kernel extension is after the driver internal extension */
429 DeviceObjectExtension = (PDEVOBJ_EXTENSION)
430 ((ULONG_PTR)(CreatedDeviceObject + 1) +
431 AlignedDeviceExtensionSize);
432
433 /* Set the Type and Size. Question: why is Size 0 on Windows? */
434 DPRINT("DeviceObjectExtension %x\n", DeviceObjectExtension);
435 DeviceObjectExtension->Type = IO_TYPE_DEVICE_OBJECT_EXTENSION;
436 DeviceObjectExtension->Size = 0;
437
438 /* Link the Object and Extension */
439 DeviceObjectExtension->DeviceObject = CreatedDeviceObject;
440 CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension;
441
442 /* Set Device Object Data */
443 CreatedDeviceObject->DeviceType = DeviceType;
444 CreatedDeviceObject->Characteristics = DeviceCharacteristics;
445 CreatedDeviceObject->DeviceExtension = CreatedDeviceObject + 1;
446 CreatedDeviceObject->StackSize = 1;
447 CreatedDeviceObject->AlignmentRequirement = 1; /* FIXME */
448
449 /* Set the Flags */
450 /* FIXME: After the Driver is Loaded, the flag below should be removed */
451 CreatedDeviceObject->Flags = DO_DEVICE_INITIALIZING;
452 if (Exclusive) CreatedDeviceObject->Flags |= DO_EXCLUSIVE;
453 if (DeviceName) CreatedDeviceObject->Flags |= DO_DEVICE_HAS_NAME;
454
455 /* Attach a Vpb for Disks and Tapes, and create the Device Lock */
456 if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
457 CreatedDeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
458 CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
459 CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
460 {
461 /* Create Vpb */
462 IopAttachVpb(CreatedDeviceObject);
463
464 /* Initialize Lock Event */
465 KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
466 SynchronizationEvent,
467 TRUE);
468 }
469
470 /* Set the right Sector Size */
471 switch (DeviceType)
472 {
473 case FILE_DEVICE_DISK_FILE_SYSTEM:
474 case FILE_DEVICE_DISK:
475 case FILE_DEVICE_VIRTUAL_DISK:
476 CreatedDeviceObject->SectorSize = 512;
477 break;
478
479 case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
480 CreatedDeviceObject->SectorSize = 2048;
481 break;
482 }
483
484 /* Create the Device Queue */
485 KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
486
487 /* Insert the Object */
488 Status = ObInsertObject(CreatedDeviceObject,
489 NULL,
490 FILE_READ_DATA | FILE_WRITE_DATA,
491 0,
492 NULL,
493 &TempHandle);
494
495 if (!NT_SUCCESS(Status))
496 {
497 DPRINT1("Cannot insert Device Object into Handle Table\n");
498 *DeviceObject = NULL;
499 return Status;
500 }
501
502 /* Now do the final linking */
503 ObReferenceObject(DriverObject);
504 CreatedDeviceObject->DriverObject = DriverObject;
505 CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
506 DriverObject->DeviceObject = CreatedDeviceObject;
507
508 /* Close the temporary handle, but do an extra reference first so it doesn't die */
509 ObReferenceObject(CreatedDeviceObject);
510 NtClose(TempHandle);
511
512 /* Return to caller */
513 *DeviceObject = CreatedDeviceObject;
514 return STATUS_SUCCESS;
515 }
516
517 /*
518 * IoDeleteDevice
519 *
520 * Status
521 * @implemented
522 */
523 VOID
524 STDCALL
525 IoDeleteDevice(PDEVICE_OBJECT DeviceObject)
526 {
527 PDEVICE_OBJECT Previous;
528
529 if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED)
530 IoUnregisterShutdownNotification(DeviceObject);
531
532 /* Remove the timer if it exists */
533 if (DeviceObject->Timer)
534 {
535 IopRemoveTimerFromTimerList(DeviceObject->Timer);
536 ExFreePool(DeviceObject->Timer);
537 }
538
539 /* Remove device from driver device list */
540 Previous = DeviceObject->DriverObject->DeviceObject;
541 if (Previous == DeviceObject)
542 {
543 DeviceObject->DriverObject->DeviceObject = DeviceObject->NextDevice;
544 }
545 else
546 {
547 while (Previous->NextDevice != DeviceObject)
548 Previous = Previous->NextDevice;
549 Previous->NextDevice = DeviceObject->NextDevice;
550 }
551
552 /* I guess this should be removed later... but it shouldn't cause problems */
553 DeviceObject->DeviceObjectExtension->ExtensionFlags |= DOE_DELETE_PENDING;
554 ObDereferenceObject(DeviceObject);
555 }
556
557 /*
558 * IoDetachDevice
559 *
560 * Status
561 * @implemented
562 */
563 VOID
564 STDCALL
565 IoDetachDevice(PDEVICE_OBJECT TargetDevice)
566 {
567 DPRINT("IoDetachDevice(TargetDevice %x)\n", TargetDevice);
568
569 /* Remove the attachment */
570 TargetDevice->AttachedDevice->DeviceObjectExtension->AttachedTo = NULL;
571 TargetDevice->AttachedDevice = NULL;
572 }
573
574 /*
575 * @implemented
576 */
577 NTSTATUS
578 STDCALL
579 IoEnumerateDeviceObjectList(IN PDRIVER_OBJECT DriverObject,
580 IN PDEVICE_OBJECT *DeviceObjectList,
581 IN ULONG DeviceObjectListSize,
582 OUT PULONG ActualNumberDeviceObjects)
583 {
584 ULONG ActualDevices = 1;
585 PDEVICE_OBJECT CurrentDevice = DriverObject->DeviceObject;
586
587 DPRINT1("IoEnumerateDeviceObjectList\n");
588
589 /* Find out how many devices we'll enumerate */
590 while ((CurrentDevice = CurrentDevice->NextDevice))
591 {
592 ActualDevices++;
593 }
594
595 /* Go back to the first */
596 CurrentDevice = DriverObject->DeviceObject;
597
598 /* Start by at least returning this */
599 *ActualNumberDeviceObjects = ActualDevices;
600
601 /* Check if we can support so many */
602 if ((ActualDevices * 4) > DeviceObjectListSize)
603 {
604 /* Fail because the buffer was too small */
605 return STATUS_BUFFER_TOO_SMALL;
606 }
607
608 /* Check if the caller only wanted the size */
609 if (DeviceObjectList)
610 {
611 /* Loop through all the devices */
612 while (ActualDevices)
613 {
614 /* Reference each Device */
615 ObReferenceObject(CurrentDevice);
616
617 /* Add it to the list */
618 *DeviceObjectList = CurrentDevice;
619
620 /* Go to the next one */
621 CurrentDevice = CurrentDevice->NextDevice;
622 ActualDevices--;
623 DeviceObjectList++;
624 }
625 }
626
627 /* Return the status */
628 return STATUS_SUCCESS;
629 }
630
631 /*
632 * IoGetAttachedDevice
633 *
634 * Status
635 * @implemented
636 */
637 PDEVICE_OBJECT
638 STDCALL
639 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
640 {
641 PDEVICE_OBJECT Current = DeviceObject;
642
643 /* Get the last attached device */
644 while (Current->AttachedDevice)
645 {
646 Current = Current->AttachedDevice;
647 }
648
649 /* Return it */
650 return Current;
651 }
652
653 /*
654 * IoGetAttachedDeviceReference
655 *
656 * Status
657 * @implemented
658 */
659 PDEVICE_OBJECT
660 STDCALL
661 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
662 {
663 PDEVICE_OBJECT Current = IoGetAttachedDevice(DeviceObject);
664
665 /* Reference the ATtached Device */
666 ObReferenceObject(Current);
667 return Current;
668 }
669
670 /*
671 * @implemented
672 */
673 PDEVICE_OBJECT
674 STDCALL
675 IoGetDeviceAttachmentBaseRef(IN PDEVICE_OBJECT DeviceObject)
676 {
677 /* Return the attached Device */
678 return (DeviceObject->DeviceObjectExtension->AttachedTo);
679 }
680
681 /*
682 * IoGetDeviceObjectPointer
683 *
684 * Status
685 * @implemented
686 */
687 NTSTATUS
688 STDCALL
689 IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName,
690 IN ACCESS_MASK DesiredAccess,
691 OUT PFILE_OBJECT *FileObject,
692 OUT PDEVICE_OBJECT *DeviceObject)
693 {
694 /* Call the helper routine for a normal operation */
695 return IopGetDeviceObjectPointer(ObjectName,
696 DesiredAccess,
697 FileObject,
698 DeviceObject,
699 0);
700 }
701
702 /*
703 * @implemented
704 */
705 NTSTATUS
706 STDCALL
707 IoGetDiskDeviceObject(IN PDEVICE_OBJECT FileSystemDeviceObject,
708 OUT PDEVICE_OBJECT *DiskDeviceObject)
709 {
710 PDEVOBJ_EXTENSION DeviceExtension;
711 PVPB Vpb;
712 KIRQL OldIrql;
713
714 /* Make sure there's a VPB */
715 if (!FileSystemDeviceObject->Vpb) return STATUS_INVALID_PARAMETER;
716
717 /* Acquire it */
718 IoAcquireVpbSpinLock(&OldIrql);
719
720 /* Get the Device Extension */
721 DeviceExtension = FileSystemDeviceObject->DeviceObjectExtension;
722
723 /* Make sure this one has a VPB too */
724 Vpb = DeviceExtension->Vpb;
725 if (!Vpb) return STATUS_INVALID_PARAMETER;
726
727 /* Make sure someone it's mounted */
728 if ((!Vpb->ReferenceCount) || (Vpb->Flags & VPB_MOUNTED)) return STATUS_VOLUME_DISMOUNTED;
729
730 /* Return the Disk Device Object */
731 *DiskDeviceObject = Vpb->RealDevice;
732
733 /* Release the lock */
734 IoReleaseVpbSpinLock(OldIrql);
735 return STATUS_SUCCESS;
736 }
737
738 /*
739 * @implemented
740 */
741 PDEVICE_OBJECT
742 STDCALL
743 IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject)
744 {
745 PDEVOBJ_EXTENSION DeviceExtension = DeviceObject->DeviceObjectExtension;
746 PDEVICE_OBJECT LowerDeviceObject = NULL;
747
748 /* Make sure it's not getting deleted */
749 if (DeviceExtension->ExtensionFlags & (DOE_UNLOAD_PENDING |
750 DOE_DELETE_PENDING |
751 DOE_REMOVE_PENDING |
752 DOE_REMOVE_PROCESSED))
753 {
754 /* Get the Lower Device Object */
755 LowerDeviceObject = DeviceExtension->AttachedTo;
756
757 /* Reference it */
758 ObReferenceObject(LowerDeviceObject);
759 }
760
761 /* Return it */
762 return LowerDeviceObject;
763 }
764
765 /*
766 * IoGetRelatedDeviceObject
767 *
768 * Remarks
769 * See "Windows NT File System Internals", page 633 - 634.
770 *
771 * Status
772 * @implemented
773 */
774 PDEVICE_OBJECT
775 STDCALL
776 IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject)
777 {
778 PDEVICE_OBJECT DeviceObject = FileObject->DeviceObject;
779
780 /* Get logical volume mounted on a physical/virtual/logical device */
781 if (FileObject->Vpb && FileObject->Vpb->DeviceObject)
782 {
783 DeviceObject = FileObject->Vpb->DeviceObject;
784 }
785
786 /*
787 * Check if file object has an associated device object mounted by some
788 * other file system.
789 */
790 if (FileObject->DeviceObject->Vpb &&
791 FileObject->DeviceObject->Vpb->DeviceObject)
792 {
793 DeviceObject = FileObject->DeviceObject->Vpb->DeviceObject;
794 }
795
796 /* Return the highest attached device */
797 return IoGetAttachedDevice(DeviceObject);
798 }
799
800 /*
801 * @unimplemented
802 */
803 NTSTATUS
804 STDCALL
805 IoRegisterLastChanceShutdownNotification(
806 IN PDEVICE_OBJECT DeviceObject
807 )
808 {
809 UNIMPLEMENTED;
810 return STATUS_NOT_IMPLEMENTED;
811 }
812
813 /*
814 * @unimplemented
815 */
816 VOID
817 STDCALL
818 IoSetStartIoAttributes(
819 IN PDEVICE_OBJECT DeviceObject,
820 IN BOOLEAN DeferredStartIo,
821 IN BOOLEAN NonCancelable
822 )
823 {
824 UNIMPLEMENTED;
825 }
826
827 /*
828 * @unimplemented
829 */
830 VOID
831 STDCALL
832 IoSynchronousInvalidateDeviceRelations(
833 IN PDEVICE_OBJECT DeviceObject,
834 IN DEVICE_RELATION_TYPE Type
835 )
836 {
837 UNIMPLEMENTED;
838 }
839
840 /*
841 * @unimplemented
842 */
843 NTSTATUS
844 STDCALL
845 IoValidateDeviceIoControlAccess(
846 IN PIRP Irp,
847 IN ULONG RequiredAccess
848 )
849 {
850 UNIMPLEMENTED;
851 return STATUS_NOT_IMPLEMENTED;
852 }
853
854 /* EOF */