2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/io/iomgr.c
5 * PURPOSE: I/O Manager Initialization and Misc Utility Functions
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
10 /* INCLUDES ****************************************************************/
14 #include <internal/debug.h>
16 ULONG IopTraceLevel
= IO_IRP_DEBUG
;
18 // should go into a proper header
21 IoSynchronousInvalidateDeviceRelations(
22 IN PDEVICE_OBJECT DeviceObject
,
23 IN DEVICE_RELATION_TYPE Type
30 IN PVOID DeferredContext
,
31 IN PVOID SystemArgument1
,
32 IN PVOID SystemArgument2
35 /* DATA ********************************************************************/
37 POBJECT_TYPE IoDeviceObjectType
= NULL
;
38 POBJECT_TYPE IoFileObjectType
= NULL
;
39 extern POBJECT_TYPE IoControllerObjectType
;
40 extern UNICODE_STRING NtSystemRoot
;
41 BOOLEAN IoCountOperations
;
42 ULONG IoReadOperationCount
= 0;
43 LARGE_INTEGER IoReadTransferCount
= {{0, 0}};
44 ULONG IoWriteOperationCount
= 0;
45 LARGE_INTEGER IoWriteTransferCount
= {{0, 0}};
46 ULONG IoOtherOperationCount
= 0;
47 LARGE_INTEGER IoOtherTransferCount
= {{0, 0}};
48 KSPIN_LOCK IoStatisticsLock
= 0;
50 GENERIC_MAPPING IopFileMapping
= {
56 extern LIST_ENTRY ShutdownListHead
;
57 extern KSPIN_LOCK ShutdownListLock
;
58 extern NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside
;
59 extern POBJECT_TYPE IoAdapterObjectType
;
60 ERESOURCE IopDatabaseResource
;
61 extern ERESOURCE FileSystemListLock
;
62 ERESOURCE IopSecurityResource
;
63 extern KGUARDED_MUTEX FsChangeNotifyListLock
;
64 extern KGUARDED_MUTEX PnpNotifyListLock
;
65 extern LIST_ENTRY IopDiskFsListHead
;
66 extern LIST_ENTRY IopCdRomFsListHead
;
67 extern LIST_ENTRY IopTapeFsListHead
;
68 extern LIST_ENTRY IopNetworkFsListHead
;
69 extern LIST_ENTRY DriverBootReinitListHead
;
70 extern LIST_ENTRY DriverReinitListHead
;
71 extern LIST_ENTRY PnpNotifyListHead
;
72 extern LIST_ENTRY FsChangeNotifyListHead
;
73 extern LIST_ENTRY IopLogListHead
;
74 extern LIST_ENTRY IopTimerQueueHead
;
75 extern KDPC IopTimerDpc
;
76 extern KTIMER IopTimer
;
77 extern KSPIN_LOCK CancelSpinLock
;
78 extern KSPIN_LOCK IoVpbLock
;
79 extern KSPIN_LOCK IoStatisticsLock
;
80 extern KSPIN_LOCK DriverReinitListLock
;
81 extern KSPIN_LOCK DriverBootReinitListLock
;
82 extern KSPIN_LOCK IopLogListLock
;
83 extern KSPIN_LOCK IopTimerLock
;
85 extern PDEVICE_OBJECT IopErrorLogObject
;
87 NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside
;
88 NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside
;
89 NPAGED_LOOKASIDE_LIST IopMdlLookasideList
;
91 #if defined (ALLOC_PRAGMA)
92 #pragma alloc_text(INIT, IoInitSystem)
95 /* INIT FUNCTIONS ************************************************************/
100 IopInitLookasideLists(VOID
)
102 ULONG LargeIrpSize
, SmallIrpSize
, MdlSize
;
105 PNPAGED_LOOKASIDE_LIST CurrentList
= NULL
;
107 /* Calculate the sizes */
108 LargeIrpSize
= sizeof(IRP
) + (8 * sizeof(IO_STACK_LOCATION
));
109 SmallIrpSize
= sizeof(IRP
) + sizeof(IO_STACK_LOCATION
);
110 MdlSize
= sizeof(MDL
) + (23 * sizeof(PFN_NUMBER
));
112 /* Initialize the Lookaside List for Large IRPs */
113 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside
,
121 /* Initialize the Lookaside List for Small IRPs */
122 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside
,
130 /* Initialize the Lookaside List for I\O Completion */
131 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside
,
135 sizeof(IO_COMPLETION_PACKET
),
139 /* Initialize the Lookaside List for MDLs */
140 ExInitializeNPagedLookasideList(&IopMdlLookasideList
,
148 /* Now allocate the per-processor lists */
149 for (i
= 0; i
< KeNumberProcessors
; i
++)
151 /* Get the PRCB for this CPU */
152 Prcb
= ((PKPCR
)(KPCR_BASE
+ i
* PAGE_SIZE
))->Prcb
;
153 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i
, Prcb
);
155 /* Set the Large IRP List */
156 Prcb
->PPLookasideList
[LookasideLargeIrpList
].L
= &IoLargeIrpLookaside
.L
;
157 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
158 sizeof(NPAGED_LOOKASIDE_LIST
),
162 /* Initialize the Lookaside List for Large IRPs */
163 ExInitializeNPagedLookasideList(CurrentList
,
173 CurrentList
= &IoLargeIrpLookaside
;
175 Prcb
->PPLookasideList
[LookasideLargeIrpList
].P
= &CurrentList
->L
;
177 /* Set the Small IRP List */
178 Prcb
->PPLookasideList
[LookasideSmallIrpList
].L
= &IoSmallIrpLookaside
.L
;
179 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
180 sizeof(NPAGED_LOOKASIDE_LIST
),
184 /* Initialize the Lookaside List for Small IRPs */
185 ExInitializeNPagedLookasideList(CurrentList
,
195 CurrentList
= &IoSmallIrpLookaside
;
197 Prcb
->PPLookasideList
[LookasideSmallIrpList
].P
= &CurrentList
->L
;
199 /* Set the I/O Completion List */
200 Prcb
->PPLookasideList
[LookasideCompletionList
].L
= &IoCompletionPacketLookaside
.L
;
201 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
202 sizeof(NPAGED_LOOKASIDE_LIST
),
206 /* Initialize the Lookaside List for Large IRPs */
207 ExInitializeNPagedLookasideList(CurrentList
,
211 sizeof(IO_COMPLETION_PACKET
),
217 CurrentList
= &IoCompletionPacketLookaside
;
219 Prcb
->PPLookasideList
[LookasideCompletionList
].P
= &CurrentList
->L
;
221 /* Set the MDL Completion List */
222 Prcb
->PPLookasideList
[LookasideMdlList
].L
= &IopMdlLookasideList
.L
;
223 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
224 sizeof(NPAGED_LOOKASIDE_LIST
),
228 /* Initialize the Lookaside List for MDLs */
229 ExInitializeNPagedLookasideList(CurrentList
,
239 CurrentList
= &IopMdlLookasideList
;
241 Prcb
->PPLookasideList
[LookasideMdlList
].P
= &CurrentList
->L
;
248 IopCreateObjectTypes(VOID
)
250 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
253 /* Initialize default settings */
254 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
255 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
256 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
257 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
258 ObjectTypeInitializer
.ValidAccessMask
= FILE_ALL_ACCESS
;
259 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
260 ObjectTypeInitializer
.GenericMapping
= IopFileMapping
;
262 /* Do the Adapter Type */
263 RtlInitUnicodeString(&Name
, L
"Adapter");
264 if (!NT_SUCCESS(ObCreateObjectType(&Name
,
265 &ObjectTypeInitializer
,
267 &IoAdapterObjectType
))) return FALSE
;
269 /* Do the Controller Type */
270 RtlInitUnicodeString(&Name
, L
"Controller");
271 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(CONTROLLER_OBJECT
);
272 if (!NT_SUCCESS(ObCreateObjectType(&Name
,
273 &ObjectTypeInitializer
,
275 &IoControllerObjectType
))) return FALSE
;
277 /* Do the Device Type. FIXME: Needs Delete Routine! */
278 RtlInitUnicodeString(&Name
, L
"Device");
279 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DEVICE_OBJECT
);
280 ObjectTypeInitializer
.ParseProcedure
= IopParseDevice
;
281 ObjectTypeInitializer
.SecurityProcedure
= IopSecurityFile
;
282 if (!NT_SUCCESS(ObCreateObjectType(&Name
,
283 &ObjectTypeInitializer
,
285 &IoDeviceObjectType
))) return FALSE
;
287 /* Initialize the Driver object type */
288 RtlInitUnicodeString(&Name
, L
"Driver");
289 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DRIVER_OBJECT
);
290 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteDriver
;
291 ObjectTypeInitializer
.ParseProcedure
= NULL
;
292 ObjectTypeInitializer
.SecurityProcedure
= NULL
;
293 if (!NT_SUCCESS(ObCreateObjectType(&Name
,
294 &ObjectTypeInitializer
,
296 &IoDriverObjectType
))) return FALSE
;
298 /* Initialize the I/O Completion object type */
299 RtlInitUnicodeString(&Name
, L
"IoCompletion");
300 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KQUEUE
);
301 ObjectTypeInitializer
.ValidAccessMask
= IO_COMPLETION_ALL_ACCESS
;
302 ObjectTypeInitializer
.InvalidAttributes
|= OBJ_PERMANENT
;
303 ObjectTypeInitializer
.GenericMapping
= IopCompletionMapping
;
304 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteIoCompletion
;
305 if (!NT_SUCCESS(ObCreateObjectType(&Name
,
306 &ObjectTypeInitializer
,
308 &IoCompletionType
))) return FALSE
;
310 /* Initialize the File object type */
311 RtlInitUnicodeString(&Name
, L
"File");
312 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(FILE_OBJECT
);
313 ObjectTypeInitializer
.InvalidAttributes
|= OBJ_EXCLUSIVE
;
314 ObjectTypeInitializer
.MaintainHandleCount
= TRUE
;
315 ObjectTypeInitializer
.ValidAccessMask
= FILE_ALL_ACCESS
;
316 ObjectTypeInitializer
.GenericMapping
= IopFileMapping
;
317 ObjectTypeInitializer
.CloseProcedure
= IopCloseFile
;
318 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteFile
;
319 ObjectTypeInitializer
.SecurityProcedure
= IopSecurityFile
;
320 ObjectTypeInitializer
.QueryNameProcedure
= IopQueryNameFile
;
321 ObjectTypeInitializer
.ParseProcedure
= IopParseFile
;
322 ObjectTypeInitializer
.UseDefaultObject
= FALSE
;
323 if (!NT_SUCCESS(ObCreateObjectType(&Name
,
324 &ObjectTypeInitializer
,
326 &IoFileObjectType
))) return FALSE
;
335 IopCreateRootDirectories()
337 OBJECT_ATTRIBUTES ObjectAttributes
;
338 UNICODE_STRING DirName
;
341 /* Create the '\Driver' object directory */
342 RtlInitUnicodeString(&DirName
, L
"\\Driver");
343 InitializeObjectAttributes(&ObjectAttributes
,
348 if (!NT_SUCCESS(NtCreateDirectoryObject(&Handle
,
349 DIRECTORY_ALL_ACCESS
,
350 &ObjectAttributes
))) return FALSE
;
353 /* Create the '\FileSystem' object directory */
354 RtlInitUnicodeString(&DirName
, L
"\\FileSystem");
355 InitializeObjectAttributes(&ObjectAttributes
,
360 if (!NT_SUCCESS(NtCreateDirectoryObject(&Handle
,
361 DIRECTORY_ALL_ACCESS
,
362 &ObjectAttributes
))) return FALSE
;
372 IopMarkBootPartition(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
374 OBJECT_ATTRIBUTES ObjectAttributes
;
377 UNICODE_STRING DeviceName
;
380 IO_STATUS_BLOCK IoStatusBlock
;
381 PFILE_OBJECT FileObject
;
383 /* Build the ARC device name */
384 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
385 RtlInitAnsiString(&DeviceString
, Buffer
);
386 Status
= RtlAnsiStringToUnicodeString(&DeviceName
, &DeviceString
, TRUE
);
387 if (!NT_SUCCESS(Status
)) return FALSE
;
390 InitializeObjectAttributes(&ObjectAttributes
,
392 OBJ_CASE_INSENSITIVE
,
395 Status
= ZwOpenFile(&FileHandle
,
396 FILE_READ_ATTRIBUTES
,
400 FILE_NON_DIRECTORY_FILE
);
401 if (!NT_SUCCESS(Status
))
404 KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE
,
405 (ULONG_PTR
)&DeviceName
,
412 Status
= ObReferenceObjectByHandle(FileHandle
,
416 (PVOID
*)&FileObject
,
418 if (!NT_SUCCESS(Status
))
421 RtlFreeUnicodeString(&DeviceName
);
425 /* Mark it as the boot partition */
426 FileObject
->DeviceObject
->Flags
|= DO_SYSTEM_BOOT_PARTITION
;
428 /* Save a copy of the DO for the I/O Error Logger */
429 ObReferenceObject(FileObject
->DeviceObject
);
430 IopErrorLogObject
= FileObject
->DeviceObject
;
432 /* Cleanup and return success */
433 RtlFreeUnicodeString(&DeviceName
);
435 ObDereferenceObject(FileObject
);
442 IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
444 LARGE_INTEGER ExpireTime
;
445 PDEVICE_NODE DeviceNode
;
446 PDRIVER_OBJECT DriverObject
;
447 LDR_DATA_TABLE_ENTRY ModuleObject
;
450 ANSI_STRING NtBootPath
, RootString
;
452 /* Initialize empty NT Boot Path */
453 RtlInitEmptyAnsiString(&NtBootPath
, Buffer
, sizeof(Buffer
));
455 /* Initialize the lookaside lists */
456 IopInitLookasideLists();
458 /* Initialize all locks and lists */
459 ExInitializeResource(&IopDatabaseResource
);
460 ExInitializeResource(&FileSystemListLock
);
461 ExInitializeResource(&IopSecurityResource
);
462 KeInitializeGuardedMutex(&FsChangeNotifyListLock
);
463 KeInitializeGuardedMutex(&PnpNotifyListLock
);
464 InitializeListHead(&IopDiskFsListHead
);
465 InitializeListHead(&IopCdRomFsListHead
);
466 InitializeListHead(&IopTapeFsListHead
);
467 InitializeListHead(&IopNetworkFsListHead
);
468 InitializeListHead(&DriverBootReinitListHead
);
469 InitializeListHead(&DriverReinitListHead
);
470 InitializeListHead(&PnpNotifyListHead
);
471 InitializeListHead(&ShutdownListHead
);
472 InitializeListHead(&FsChangeNotifyListHead
);
473 InitializeListHead(&IopLogListHead
);
474 KeInitializeSpinLock(&CancelSpinLock
);
475 KeInitializeSpinLock(&IoVpbLock
);
476 KeInitializeSpinLock(&IoStatisticsLock
);
477 KeInitializeSpinLock(&DriverReinitListLock
);
478 KeInitializeSpinLock(&DriverBootReinitListLock
);
479 KeInitializeSpinLock(&ShutdownListLock
);
480 KeInitializeSpinLock(&IopLogListLock
);
482 /* Initialize Timer List Lock */
483 KeInitializeSpinLock(&IopTimerLock
);
485 /* Initialize Timer List */
486 InitializeListHead(&IopTimerQueueHead
);
488 /* Initialize the DPC/Timer which will call the other Timer Routines */
489 ExpireTime
.QuadPart
= -10000000;
490 KeInitializeDpc(&IopTimerDpc
, IopTimerDispatch
, NULL
);
491 KeInitializeTimerEx(&IopTimer
, SynchronizationTimer
);
492 KeSetTimerEx(&IopTimer
, ExpireTime
, 1000, &IopTimerDpc
);
494 /* Create Object Types */
495 if (!IopCreateObjectTypes()) return FALSE
;
497 /* Create Object Directories */
498 if (!IopCreateRootDirectories()) return FALSE
;
501 * Initialize PnP manager
507 IoCreateDriverList();
509 KeInitializeSpinLock (&IoStatisticsLock
);
511 /* Initialize raw filesystem driver */
513 /* Use IopRootDeviceNode for now */
514 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
515 if (!NT_SUCCESS(Status
))
517 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status
);
521 ModuleObject
.DllBase
= NULL
;
522 ModuleObject
.SizeOfImage
= 0;
523 ModuleObject
.EntryPoint
= RawFsDriverEntry
;
525 Status
= IopInitializeDriverModule(DeviceNode
,
527 &DeviceNode
->ServiceName
,
530 if (!NT_SUCCESS(Status
))
532 IopFreeDeviceNode(DeviceNode
);
533 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status
);
537 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
538 if (!NT_SUCCESS(Status
))
540 IopFreeDeviceNode(DeviceNode
);
541 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
545 Status
= IopStartDevice(DeviceNode
);
546 if (!NT_SUCCESS(Status
))
548 IopFreeDeviceNode(DeviceNode
);
549 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
554 * Initialize PnP root releations
556 IoSynchronousInvalidateDeviceRelations(IopRootDeviceNode
->
557 PhysicalDeviceObject
,
560 /* Load boot start drivers */
561 IopInitializeBootDrivers();
563 /* Call back drivers that asked for */
564 IopReinitializeBootDrivers();
566 /* Create ARC names for boot devices */
567 IopCreateArcNames(LoaderBlock
);
569 /* Mark the system boot partition */
570 if (!IopMarkBootPartition(LoaderBlock
)) return FALSE
;
575 /* I/O is now setup for disk access, so phase 3 */
576 KdInitSystem(3, LoaderBlock
);
578 /* Load services for devices found by PnP manager */
579 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
581 /* Load system start drivers */
582 IopInitializeSystemDrivers();
584 /* Destroy the group driver list */
585 IoDestroyDriverList();
587 /* Reinitialize drivers that requested it */
588 IopReinitializeDrivers();
590 /* Convert SystemRoot from ARC to NT path */
591 Status
= IopReassignSystemRoot(LoaderBlock
, &NtBootPath
);
592 if (!NT_SUCCESS(Status
)) return FALSE
;
594 /* Set the ANSI_STRING for the root path */
595 RootString
.MaximumLength
= NtSystemRoot
.MaximumLength
/ sizeof(WCHAR
);
596 RootString
.Length
= 0;
597 RootString
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
598 RootString
.MaximumLength
,
601 /* Convert the path into the ANSI_STRING */
602 Status
= RtlUnicodeStringToAnsiString(&RootString
, &NtSystemRoot
, FALSE
);
603 if (!NT_SUCCESS(Status
)) return FALSE
;
605 /* Assign drive letters */
606 IoAssignDriveLetters(LoaderBlock
,
608 (PUCHAR
)RootString
.Buffer
,
611 /* Update system root */
612 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &RootString
, FALSE
);
613 if (!NT_SUCCESS(Status
)) return FALSE
;
615 /* Load the System DLL and its Entrypoints */
616 if (!NT_SUCCESS(PsLocateSystemDll())) return FALSE
;