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