Standardize comment headers. Patch by Trevor McCort
[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 #ifdef ACPI
86 if (Fdo->DeviceType == FILE_DEVICE_ACPI)
87 {
88 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
89
90 /* There can be only one system power device */
91 if (!SystemPowerDeviceNodeCreated)
92 {
93 PopSystemPowerDeviceNode = DeviceNode;
94 SystemPowerDeviceNodeCreated = TRUE;
95 }
96 }
97 #endif /* ACPI */
98
99 if (Fdo->DeviceType == FILE_DEVICE_BUS_EXTENDER ||
100 Fdo->DeviceType == FILE_DEVICE_ACPI)
101 {
102 DPRINT("Bus extender found\n");
103
104 Status = IopInvalidateDeviceRelations(DeviceNode, BusRelations);
105 if (!NT_SUCCESS(Status))
106 {
107 ObDereferenceObject(Fdo);
108 return Status;
109 }
110 }
111
112 ObDereferenceObject(Fdo);
113 }
114
115 return STATUS_SUCCESS;
116 }
117
118 NTSTATUS STDCALL
119 IopCreateDevice(
120 PVOID ObjectBody,
121 PVOID Parent,
122 PWSTR RemainingPath,
123 POBJECT_ATTRIBUTES ObjectAttributes)
124 {
125 DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
126 ObjectBody, Parent, RemainingPath);
127
128 if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
129 return STATUS_UNSUCCESSFUL;
130
131 return STATUS_SUCCESS;
132 }
133
134 /* PUBLIC FUNCTIONS ***********************************************************/
135
136 /*
137 * IoAttachDeviceByPointer
138 *
139 * Status
140 * @implemented
141 */
142
143 NTSTATUS STDCALL
144 IoAttachDeviceByPointer(
145 IN PDEVICE_OBJECT SourceDevice,
146 IN PDEVICE_OBJECT TargetDevice)
147 {
148 PDEVICE_OBJECT AttachedDevice;
149
150 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
151 SourceDevice, TargetDevice);
152
153 AttachedDevice = IoAttachDeviceToDeviceStack(SourceDevice, TargetDevice);
154 if (AttachedDevice == NULL)
155 return STATUS_NO_SUCH_DEVICE;
156
157 return STATUS_SUCCESS;
158 }
159
160 /*
161 * @unimplemented
162 */
163 NTSTATUS
164 STDCALL
165 IoAttachDeviceToDeviceStackSafe(
166 IN PDEVICE_OBJECT SourceDevice,
167 IN PDEVICE_OBJECT TargetDevice,
168 OUT PDEVICE_OBJECT *AttachedToDeviceObject
169 )
170 {
171 UNIMPLEMENTED;
172 return STATUS_NOT_IMPLEMENTED;
173 }
174
175 /*
176 * IoDeleteDevice
177 *
178 * Status
179 * @implemented
180 */
181
182 VOID STDCALL
183 IoDeleteDevice(PDEVICE_OBJECT DeviceObject)
184 {
185 PDEVICE_OBJECT Previous;
186
187 if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED)
188 IoUnregisterShutdownNotification(DeviceObject);
189
190 /* Remove the timer if it exists */
191 if (DeviceObject->Timer)
192 {
193 IopRemoveTimerFromTimerList(DeviceObject->Timer);
194 ExFreePool(DeviceObject->Timer);
195 }
196
197 /* Free device extension */
198 if (DeviceObject->DeviceObjectExtension)
199 ExFreePool(DeviceObject->DeviceObjectExtension);
200
201 /* Remove device from driver device list */
202 Previous = DeviceObject->DriverObject->DeviceObject;
203 if (Previous == DeviceObject)
204 {
205 DeviceObject->DriverObject->DeviceObject = DeviceObject->NextDevice;
206 }
207 else
208 {
209 while (Previous->NextDevice != DeviceObject)
210 Previous = Previous->NextDevice;
211 Previous->NextDevice = DeviceObject->NextDevice;
212 }
213
214 ObDereferenceObject(DeviceObject);
215 }
216
217
218 /*
219 * @unimplemented
220 */
221 NTSTATUS
222 STDCALL
223 IoEnumerateDeviceObjectList(
224 IN PDRIVER_OBJECT DriverObject,
225 IN PDEVICE_OBJECT *DeviceObjectList,
226 IN ULONG DeviceObjectListSize,
227 OUT PULONG ActualNumberDeviceObjects
228 )
229 {
230 UNIMPLEMENTED;
231 return STATUS_NOT_IMPLEMENTED;
232 }
233
234
235 /*
236 * @unimplemented
237 */
238 PDEVICE_OBJECT
239 STDCALL
240 IoGetDeviceAttachmentBaseRef(
241 IN PDEVICE_OBJECT DeviceObject
242 )
243 {
244 UNIMPLEMENTED;
245 return 0;
246 }
247
248 /*
249 * @unimplemented
250 */
251 NTSTATUS
252 STDCALL
253 IoGetDiskDeviceObject(
254 IN PDEVICE_OBJECT FileSystemDeviceObject,
255 OUT PDEVICE_OBJECT *DiskDeviceObject
256 )
257 {
258 UNIMPLEMENTED;
259 return STATUS_NOT_IMPLEMENTED;
260 }
261
262 /*
263 * @unimplemented
264 */
265 PDEVICE_OBJECT
266 STDCALL
267 IoGetLowerDeviceObject(
268 IN PDEVICE_OBJECT DeviceObject
269 )
270 {
271 UNIMPLEMENTED;
272 return 0;
273 }
274
275 /*
276 * IoGetRelatedDeviceObject
277 *
278 * Remarks
279 * See "Windows NT File System Internals", page 633 - 634.
280 *
281 * Status
282 * @implemented
283 */
284
285 PDEVICE_OBJECT STDCALL
286 IoGetRelatedDeviceObject(
287 IN PFILE_OBJECT FileObject)
288 {
289 /*
290 * Get logical volume mounted on a physical/virtual/logical device
291 */
292
293 if (FileObject->Vpb && FileObject->Vpb->DeviceObject)
294 {
295 return IoGetAttachedDevice(FileObject->Vpb->DeviceObject);
296 }
297
298 /*
299 * Check if file object has an associated device object mounted by some
300 * other file system.
301 */
302
303 if (FileObject->DeviceObject->Vpb &&
304 FileObject->DeviceObject->Vpb->DeviceObject)
305 {
306 return IoGetAttachedDevice(FileObject->DeviceObject->Vpb->DeviceObject);
307 }
308
309 return IoGetAttachedDevice(FileObject->DeviceObject);
310 }
311
312 /*
313 * IoGetDeviceObjectPointer
314 *
315 * Status
316 * @implemented
317 */
318
319 NTSTATUS STDCALL
320 IoGetDeviceObjectPointer(
321 IN PUNICODE_STRING ObjectName,
322 IN ACCESS_MASK DesiredAccess,
323 OUT PFILE_OBJECT *FileObject,
324 OUT PDEVICE_OBJECT *DeviceObject)
325 {
326 OBJECT_ATTRIBUTES ObjectAttributes;
327 IO_STATUS_BLOCK StatusBlock;
328 PFILE_OBJECT LocalFileObject;
329 HANDLE FileHandle;
330 NTSTATUS Status;
331
332 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
333 ObjectName, DesiredAccess, FileObject, DeviceObject);
334
335 InitializeObjectAttributes(
336 &ObjectAttributes,
337 ObjectName,
338 0,
339 NULL,
340 NULL);
341
342 Status = NtOpenFile(
343 &FileHandle,
344 DesiredAccess,
345 &ObjectAttributes,
346 &StatusBlock,
347 0,
348 FILE_NON_DIRECTORY_FILE);
349
350 if (!NT_SUCCESS(Status))
351 return Status;
352
353 Status = ObReferenceObjectByHandle(
354 FileHandle,
355 0,
356 IoFileObjectType,
357 KernelMode,
358 (PVOID*)&LocalFileObject,
359 NULL);
360
361 if (NT_SUCCESS(Status))
362 {
363 *DeviceObject = IoGetRelatedDeviceObject(LocalFileObject);
364 *FileObject = LocalFileObject;
365 }
366
367 NtClose(FileHandle);
368
369 return Status;
370 }
371
372 /*
373 * IoDetachDevice
374 *
375 * Status
376 * @unimplemented
377 */
378
379 VOID STDCALL
380 IoDetachDevice(PDEVICE_OBJECT TargetDevice)
381 {
382 DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice);
383 }
384
385 /*
386 * IoGetAttachedDevice
387 *
388 * Status
389 * @implemented
390 */
391
392 PDEVICE_OBJECT STDCALL
393 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
394 {
395 PDEVICE_OBJECT Current = DeviceObject;
396
397 while (Current->AttachedDevice != NULL)
398 Current = Current->AttachedDevice;
399
400 return Current;
401 }
402
403 /*
404 * IoGetAttachedDeviceReference
405 *
406 * Status
407 * @implemented
408 */
409
410 PDEVICE_OBJECT STDCALL
411 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
412 {
413 PDEVICE_OBJECT Current = IoGetAttachedDevice(DeviceObject);
414 ObReferenceObject(Current);
415 return Current;
416 }
417
418 /*
419 * IoAttachDeviceToDeviceStack
420 *
421 * Status
422 * @implemented
423 */
424
425 PDEVICE_OBJECT STDCALL
426 IoAttachDeviceToDeviceStack(
427 PDEVICE_OBJECT SourceDevice,
428 PDEVICE_OBJECT TargetDevice)
429 {
430 PDEVICE_OBJECT AttachedDevice;
431
432 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
433 SourceDevice, TargetDevice);
434
435 AttachedDevice = IoGetAttachedDevice(TargetDevice);
436 AttachedDevice->AttachedDevice = SourceDevice;
437 SourceDevice->AttachedDevice = NULL;
438 SourceDevice->StackSize = AttachedDevice->StackSize + 1;
439 SourceDevice->AlignmentRequirement = AttachedDevice->AlignmentRequirement;
440 SourceDevice->SectorSize = AttachedDevice->SectorSize;
441 SourceDevice->Vpb = AttachedDevice->Vpb;
442 return AttachedDevice;
443 }
444
445 /*
446 * IoAttachDevice
447 *
448 * Layers a device over the highest device in a device stack.
449 *
450 * Parameters
451 * SourceDevice
452 * Device to be attached.
453 *
454 * TargetDevice
455 * Name of the target device.
456 *
457 * AttachedDevice
458 * Caller storage for the device attached to.
459 *
460 * Status
461 * @implemented
462 */
463
464 NTSTATUS STDCALL
465 IoAttachDevice(
466 PDEVICE_OBJECT SourceDevice,
467 PUNICODE_STRING TargetDeviceName,
468 PDEVICE_OBJECT *AttachedDevice)
469 {
470 NTSTATUS Status;
471 PFILE_OBJECT FileObject;
472 PDEVICE_OBJECT TargetDevice;
473
474 Status = IoGetDeviceObjectPointer(
475 TargetDeviceName,
476 FILE_READ_ATTRIBUTES,
477 &FileObject,
478 &TargetDevice);
479
480 if (!NT_SUCCESS(Status))
481 {
482 return Status;
483 }
484
485 *AttachedDevice = IoAttachDeviceToDeviceStack(
486 SourceDevice,
487 TargetDevice);
488
489 ObDereferenceObject(FileObject);
490
491 return STATUS_SUCCESS;
492 }
493
494 /*
495 * IoCreateDevice
496 *
497 * Allocates memory for and intializes a device object for use for
498 * a driver.
499 *
500 * Parameters
501 * DriverObject
502 * Driver object passed by IO Manager when the driver was loaded.
503 *
504 * DeviceExtensionSize
505 * Number of bytes for the device extension.
506 *
507 * DeviceName
508 * Unicode name of device.
509 *
510 * DeviceType
511 * Device type of the new device.
512 *
513 * DeviceCharacteristics
514 * Bit mask of device characteristics.
515 *
516 * Exclusive
517 * TRUE if only one thread can access the device at a time.
518 *
519 * DeviceObject
520 * On successful return this parameter is filled by pointer to
521 * allocated device object.
522 *
523 * Status
524 * @implemented
525 */
526
527 NTSTATUS STDCALL
528 IoCreateDevice(
529 PDRIVER_OBJECT DriverObject,
530 ULONG DeviceExtensionSize,
531 PUNICODE_STRING DeviceName,
532 DEVICE_TYPE DeviceType,
533 ULONG DeviceCharacteristics,
534 BOOLEAN Exclusive,
535 PDEVICE_OBJECT *DeviceObject)
536 {
537 WCHAR AutoNameBuffer[20];
538 UNICODE_STRING AutoName;
539 PDEVICE_OBJECT CreatedDeviceObject;
540 PDEVOBJ_EXTENSION DeviceObjectExtension;
541 OBJECT_ATTRIBUTES ObjectAttributes;
542 NTSTATUS Status;
543
544 ASSERT_IRQL(PASSIVE_LEVEL);
545
546 if (DeviceName != NULL)
547 {
548 DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",
549 DriverObject, DeviceName->Buffer);
550 }
551 else
552 {
553 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
554 }
555
556 if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME)
557 {
558 swprintf(AutoNameBuffer,
559 L"\\Device\\%08lx",
560 InterlockedIncrementUL(&IopDeviceObjectNumber));
561 RtlInitUnicodeString(&AutoName,
562 AutoNameBuffer);
563 DeviceName = &AutoName;
564 }
565
566 if (DeviceName != NULL)
567 {
568 InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL);
569 Status = ObCreateObject(
570 KernelMode,
571 IoDeviceObjectType,
572 &ObjectAttributes,
573 KernelMode,
574 NULL,
575 sizeof(DEVICE_OBJECT),
576 0,
577 0,
578 (PVOID*)&CreatedDeviceObject);
579 }
580 else
581 {
582 Status = ObCreateObject(
583 KernelMode,
584 IoDeviceObjectType,
585 NULL,
586 KernelMode,
587 NULL,
588 sizeof(DEVICE_OBJECT),
589 0,
590 0,
591 (PVOID*)&CreatedDeviceObject);
592 }
593
594 *DeviceObject = NULL;
595
596 if (!NT_SUCCESS(Status))
597 {
598 DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status);
599 return Status;
600 }
601
602 if (DriverObject->DeviceObject == NULL)
603 {
604 DriverObject->DeviceObject = CreatedDeviceObject;
605 CreatedDeviceObject->NextDevice = NULL;
606 }
607 else
608 {
609 CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
610 DriverObject->DeviceObject = CreatedDeviceObject;
611 }
612
613 CreatedDeviceObject->Type = DeviceType;
614 CreatedDeviceObject->DriverObject = DriverObject;
615 CreatedDeviceObject->CurrentIrp = NULL;
616 CreatedDeviceObject->Flags = 0;
617
618 CreatedDeviceObject->DeviceExtension =
619 ExAllocatePoolWithTag(
620 NonPagedPool,
621 DeviceExtensionSize,
622 TAG_DEVICE_EXTENSION);
623
624 if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL)
625 {
626 ExFreePool(CreatedDeviceObject);
627 DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES);
628 return STATUS_INSUFFICIENT_RESOURCES;
629 }
630
631 if (DeviceExtensionSize > 0)
632 {
633 RtlZeroMemory(CreatedDeviceObject->DeviceExtension, DeviceExtensionSize);
634 }
635
636 CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + DeviceExtensionSize;
637 CreatedDeviceObject->ReferenceCount = 1;
638 CreatedDeviceObject->AttachedDevice = NULL;
639 CreatedDeviceObject->DeviceType = DeviceType;
640 CreatedDeviceObject->StackSize = 1;
641 CreatedDeviceObject->AlignmentRequirement = 1;
642 CreatedDeviceObject->Characteristics = DeviceCharacteristics;
643 CreatedDeviceObject->Timer = NULL;
644 CreatedDeviceObject->Vpb = NULL;
645 KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
646
647 KeInitializeEvent(
648 &CreatedDeviceObject->DeviceLock,
649 SynchronizationEvent,
650 TRUE);
651
652 /* FIXME: Do we need to add network drives too?! */
653 if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
654 CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
655 CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
656 {
657 IoAttachVpb(CreatedDeviceObject);
658 }
659 CreatedDeviceObject->SectorSize = 512; /* FIXME */
660
661 DeviceObjectExtension =
662 ExAllocatePoolWithTag(
663 NonPagedPool,
664 sizeof(DEVOBJ_EXTENSION),
665 TAG_DEVICE_EXTENSION);
666
667 DeviceObjectExtension->Type = 0 /* ?? */;
668 DeviceObjectExtension->Size = sizeof(DEVOBJ_EXTENSION);
669 DeviceObjectExtension->DeviceObject = CreatedDeviceObject;
670 DeviceObjectExtension->DeviceNode = NULL;
671
672 CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension;
673
674 *DeviceObject = CreatedDeviceObject;
675
676 return STATUS_SUCCESS;
677 }
678
679 /*
680 * IoOpenDeviceInstanceKey
681 *
682 * Status
683 * @unimplemented
684 */
685
686 NTSTATUS STDCALL
687 IoOpenDeviceInstanceKey(
688 DWORD Unknown0,
689 DWORD Unknown1,
690 DWORD Unknown2,
691 DWORD Unknown3,
692 DWORD Unknown4)
693 {
694 UNIMPLEMENTED;
695 return STATUS_NOT_IMPLEMENTED;
696 }
697
698 /*
699 * @unimplemented
700 */
701 VOID
702 STDCALL
703 IoRegisterBootDriverReinitialization(
704 IN PDRIVER_OBJECT DriverObject,
705 IN PDRIVER_REINITIALIZE DriverReinitializationRoutine,
706 IN PVOID Context
707 )
708 {
709 UNIMPLEMENTED;
710 }
711
712
713 /*
714 * @unimplemented
715 */
716 NTSTATUS
717 STDCALL
718 IoRegisterLastChanceShutdownNotification(
719 IN PDEVICE_OBJECT DeviceObject
720 )
721 {
722 UNIMPLEMENTED;
723 return STATUS_NOT_IMPLEMENTED;
724 }
725
726 /*
727 * IoQueryDeviceEnumInfo
728 *
729 * Status
730 * @unimplemented
731 */
732
733 DWORD STDCALL
734 IoQueryDeviceEnumInfo(
735 DWORD Unknown0,
736 DWORD Unknown1)
737 {
738 UNIMPLEMENTED;
739 return 0;
740 }
741
742 /*
743 * @unimplemented
744 */
745 VOID
746 STDCALL
747 IoSetStartIoAttributes(
748 IN PDEVICE_OBJECT DeviceObject,
749 IN BOOLEAN DeferredStartIo,
750 IN BOOLEAN NonCancelable
751 )
752 {
753 UNIMPLEMENTED;
754 }
755
756 /*
757 * @unimplemented
758 */
759 VOID
760 STDCALL
761 IoSynchronousInvalidateDeviceRelations(
762 IN PDEVICE_OBJECT DeviceObject,
763 IN DEVICE_RELATION_TYPE Type
764 )
765 {
766 UNIMPLEMENTED;
767 }
768
769
770 /*
771 * @unimplemented
772 */
773 NTSTATUS
774 STDCALL
775 IoValidateDeviceIoControlAccess(
776 IN PIRP Irp,
777 IN ULONG RequiredAccess
778 )
779 {
780 UNIMPLEMENTED;
781 return STATUS_NOT_IMPLEMENTED;
782 }
783
784 /* EOF */