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
27 /* DATA ********************************************************************/
29 POBJECT_TYPE IoDeviceObjectType
= NULL
;
30 POBJECT_TYPE IoFileObjectType
= NULL
;
31 extern POBJECT_TYPE IoControllerObjectType
;
32 extern UNICODE_STRING NtSystemRoot
;
33 BOOLEAN IoCountOperations
;
34 ULONG IoReadOperationCount
= 0;
35 LARGE_INTEGER IoReadTransferCount
= {{0, 0}};
36 ULONG IoWriteOperationCount
= 0;
37 LARGE_INTEGER IoWriteTransferCount
= {{0, 0}};
38 ULONG IoOtherOperationCount
= 0;
39 LARGE_INTEGER IoOtherTransferCount
= {{0, 0}};
40 KSPIN_LOCK IoStatisticsLock
= 0;
42 GENERIC_MAPPING IopFileMapping
= {
48 extern LIST_ENTRY ShutdownListHead
;
49 extern KSPIN_LOCK ShutdownListLock
;
50 extern NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside
;
51 extern POBJECT_TYPE IoAdapterObjectType
;
52 NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside
;
53 NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside
;
54 NPAGED_LOOKASIDE_LIST IopMdlLookasideList
;
56 VOID INIT_FUNCTION
IopInitLookasideLists(VOID
);
58 #if defined (ALLOC_PRAGMA)
59 #pragma alloc_text(INIT, IoInitCancelHandling)
60 #pragma alloc_text(INIT, IoInitShutdownNotification)
61 #pragma alloc_text(INIT, IopInitLookasideLists)
62 #pragma alloc_text(INIT, IoInitSystem)
65 /* INIT FUNCTIONS ************************************************************/
69 IoInitCancelHandling(VOID
)
71 extern KSPIN_LOCK CancelSpinLock
;
72 KeInitializeSpinLock(&CancelSpinLock
);
77 IoInitShutdownNotification (VOID
)
79 InitializeListHead(&ShutdownListHead
);
80 KeInitializeSpinLock(&ShutdownListLock
);
85 IopInitLookasideLists(VOID
)
87 ULONG LargeIrpSize
, SmallIrpSize
, MdlSize
;
90 PNPAGED_LOOKASIDE_LIST CurrentList
= NULL
;
92 /* Calculate the sizes */
93 LargeIrpSize
= sizeof(IRP
) + (8 * sizeof(IO_STACK_LOCATION
));
94 SmallIrpSize
= sizeof(IRP
) + sizeof(IO_STACK_LOCATION
);
95 MdlSize
= sizeof(MDL
) + (23 * sizeof(PFN_NUMBER
));
97 /* Initialize the Lookaside List for Large IRPs */
98 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside
,
106 /* Initialize the Lookaside List for Small IRPs */
107 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside
,
115 /* Initialize the Lookaside List for I\O Completion */
116 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside
,
120 sizeof(IO_COMPLETION_PACKET
),
124 /* Initialize the Lookaside List for MDLs */
125 ExInitializeNPagedLookasideList(&IopMdlLookasideList
,
133 /* Now allocate the per-processor lists */
134 for (i
= 0; i
< KeNumberProcessors
; i
++)
136 /* Get the PRCB for this CPU */
137 Prcb
= ((PKPCR
)(KPCR_BASE
+ i
* PAGE_SIZE
))->Prcb
;
138 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i
, Prcb
);
140 /* Set the Large IRP List */
141 Prcb
->PPLookasideList
[LookasideLargeIrpList
].L
= &IoLargeIrpLookaside
.L
;
142 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
143 sizeof(NPAGED_LOOKASIDE_LIST
),
147 /* Initialize the Lookaside List for Large IRPs */
148 ExInitializeNPagedLookasideList(CurrentList
,
158 CurrentList
= &IoLargeIrpLookaside
;
160 Prcb
->PPLookasideList
[LookasideLargeIrpList
].P
= &CurrentList
->L
;
162 /* Set the Small IRP List */
163 Prcb
->PPLookasideList
[LookasideSmallIrpList
].L
= &IoSmallIrpLookaside
.L
;
164 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
165 sizeof(NPAGED_LOOKASIDE_LIST
),
169 /* Initialize the Lookaside List for Small IRPs */
170 ExInitializeNPagedLookasideList(CurrentList
,
180 CurrentList
= &IoSmallIrpLookaside
;
182 Prcb
->PPLookasideList
[LookasideSmallIrpList
].P
= &CurrentList
->L
;
184 /* Set the I/O Completion List */
185 Prcb
->PPLookasideList
[LookasideCompletionList
].L
= &IoCompletionPacketLookaside
.L
;
186 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
187 sizeof(NPAGED_LOOKASIDE_LIST
),
191 /* Initialize the Lookaside List for Large IRPs */
192 ExInitializeNPagedLookasideList(CurrentList
,
196 sizeof(IO_COMPLETION_PACKET
),
202 CurrentList
= &IoCompletionPacketLookaside
;
204 Prcb
->PPLookasideList
[LookasideCompletionList
].P
= &CurrentList
->L
;
206 /* Set the MDL Completion List */
207 Prcb
->PPLookasideList
[LookasideMdlList
].L
= &IopMdlLookasideList
.L
;
208 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
209 sizeof(NPAGED_LOOKASIDE_LIST
),
213 /* Initialize the Lookaside List for MDLs */
214 ExInitializeNPagedLookasideList(CurrentList
,
224 CurrentList
= &IopMdlLookasideList
;
226 Prcb
->PPLookasideList
[LookasideMdlList
].P
= &CurrentList
->L
;
229 DPRINT("Done allocation\n");
236 IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
238 PDEVICE_NODE DeviceNode
;
239 PDRIVER_OBJECT DriverObject
;
240 LDR_DATA_TABLE_ENTRY ModuleObject
;
243 ANSI_STRING NtBootPath
, RootString
;
244 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
246 OBJECT_ATTRIBUTES ObjectAttributes
;
247 UNICODE_STRING DirName
;
248 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices");
251 /* Initialize default settings */
252 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
253 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
254 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
255 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
256 ObjectTypeInitializer
.ValidAccessMask
= FILE_ALL_ACCESS
;
257 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
258 ObjectTypeInitializer
.GenericMapping
= IopFileMapping
;
260 /* Do the Adapter Type */
261 RtlInitUnicodeString(&Name
, L
"Adapter");
262 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoAdapterObjectType
);
264 /* Do the Controller Type */
265 RtlInitUnicodeString(&Name
, L
"Controller");
266 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(CONTROLLER_OBJECT
);
267 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoControllerObjectType
);
269 /* Do the Device Type */
270 RtlInitUnicodeString(&Name
, L
"Device");
271 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DEVICE_OBJECT
);
272 ObjectTypeInitializer
.ParseProcedure
= IopParseDevice
;
273 ObjectTypeInitializer
.SecurityProcedure
= IopSecurityFile
;
274 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoDeviceObjectType
);
276 /* Initialize the Driver object type */
277 RtlInitUnicodeString(&Name
, L
"Driver");
278 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DRIVER_OBJECT
);
279 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteDriver
;
280 ObjectTypeInitializer
.ParseProcedure
= NULL
;
281 ObjectTypeInitializer
.SecurityProcedure
= NULL
;
282 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoDriverObjectType
);
284 /* Initialize the I/O Completion object type */
285 RtlInitUnicodeString(&Name
, L
"IoCompletion");
286 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KQUEUE
);
287 ObjectTypeInitializer
.ValidAccessMask
= IO_COMPLETION_ALL_ACCESS
;
288 ObjectTypeInitializer
.InvalidAttributes
|= OBJ_PERMANENT
;
289 ObjectTypeInitializer
.GenericMapping
= IopCompletionMapping
;
290 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteIoCompletion
;
291 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoCompletionType
);
293 /* Initialize the File object type */
294 RtlInitUnicodeString(&Name
, L
"File");
295 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(FILE_OBJECT
);
296 ObjectTypeInitializer
.InvalidAttributes
|= OBJ_EXCLUSIVE
;
297 ObjectTypeInitializer
.MaintainHandleCount
= TRUE
;
298 ObjectTypeInitializer
.ValidAccessMask
= FILE_ALL_ACCESS
;
299 ObjectTypeInitializer
.GenericMapping
= IopFileMapping
;
300 ObjectTypeInitializer
.CloseProcedure
= IopCloseFile
;
301 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteFile
;
302 ObjectTypeInitializer
.SecurityProcedure
= IopSecurityFile
;
303 ObjectTypeInitializer
.QueryNameProcedure
= IopQueryNameFile
;
304 ObjectTypeInitializer
.ParseProcedure
= IopParseFile
;
305 ObjectTypeInitializer
.UseDefaultObject
= FALSE
;
306 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoFileObjectType
);
309 * Create the '\Driver' object directory
311 RtlInitUnicodeString(&DirName
, L
"\\Driver");
312 InitializeObjectAttributes(&ObjectAttributes
,
317 ZwCreateDirectoryObject(&Handle
,
322 * Create the '\FileSystem' object directory
324 RtlInitUnicodeString(&DirName
,
326 InitializeObjectAttributes(&ObjectAttributes
,
331 ZwCreateDirectoryObject(&Handle
,
336 * Create the '\Device' directory
338 RtlInitUnicodeString(&DirName
,
340 InitializeObjectAttributes(&ObjectAttributes
,
345 ZwCreateDirectoryObject(&Handle
,
350 * Create the '\??' directory
352 RtlInitUnicodeString(&DirName
,
354 InitializeObjectAttributes(&ObjectAttributes
,
359 ZwCreateDirectoryObject(&Handle
,
364 * Create the '\ArcName' directory
366 RtlInitUnicodeString(&DirName
,
368 InitializeObjectAttributes(&ObjectAttributes
,
373 ZwCreateDirectoryObject(&Handle
,
378 * Initialize remaining subsubsystem
380 IopInitDriverImplementation();
381 IoInitCancelHandling();
382 IoInitFileSystemImplementation();
383 IoInitVpbImplementation();
384 IoInitShutdownNotification();
385 IopInitPnpNotificationImplementation();
387 IopInitTimerImplementation();
388 IopInitLookasideLists();
391 * Create link from '\DosDevices' to '\??' directory
393 RtlInitUnicodeString(&DirName
,
395 IoCreateSymbolicLink(&LinkName
,
399 * Initialize PnP manager
403 RtlInitEmptyAnsiString(&NtBootPath
, Buffer
, sizeof(Buffer
));
407 IoCreateDriverList();
409 KeInitializeSpinLock (&IoStatisticsLock
);
411 /* Initialize raw filesystem driver */
413 /* Use IopRootDeviceNode for now */
414 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
415 if (!NT_SUCCESS(Status
))
417 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status
);
421 ModuleObject
.DllBase
= NULL
;
422 ModuleObject
.SizeOfImage
= 0;
423 ModuleObject
.EntryPoint
= RawFsDriverEntry
;
425 Status
= IopInitializeDriverModule(DeviceNode
,
427 &DeviceNode
->ServiceName
,
430 if (!NT_SUCCESS(Status
))
432 IopFreeDeviceNode(DeviceNode
);
433 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status
);
437 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
438 if (!NT_SUCCESS(Status
))
440 IopFreeDeviceNode(DeviceNode
);
441 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
445 Status
= IopStartDevice(DeviceNode
);
446 if (!NT_SUCCESS(Status
))
448 IopFreeDeviceNode(DeviceNode
);
449 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
454 * Initialize PnP root releations
456 IoSynchronousInvalidateDeviceRelations(IopRootDeviceNode
->
457 PhysicalDeviceObject
,
460 /* Load boot start drivers */
461 IopInitializeBootDrivers();
463 /* Call back drivers that asked for */
464 IopReinitializeBootDrivers();
466 /* Create ARC names for boot devices */
467 IopCreateArcNames(LoaderBlock
);
472 /* I/O is now setup for disk access, so phase 3 */
473 KdInitSystem(3, LoaderBlock
);
475 /* Load services for devices found by PnP manager */
476 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
478 /* Load system start drivers */
479 IopInitializeSystemDrivers();
481 /* Destroy the group driver list */
482 IoDestroyDriverList();
484 /* Reinitialize drivers that requested it */
485 IopReinitializeDrivers();
487 /* Convert SystemRoot from ARC to NT path */
488 Status
= IopReassignSystemRoot(LoaderBlock
, &NtBootPath
);
489 if (!NT_SUCCESS(Status
)) return FALSE
;
491 /* Set the ANSI_STRING for the root path */
492 RootString
.MaximumLength
= NtSystemRoot
.MaximumLength
/ sizeof(WCHAR
);
493 RootString
.Length
= 0;
494 RootString
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
495 RootString
.MaximumLength
,
498 /* Convert the path into the ANSI_STRING */
499 Status
= RtlUnicodeStringToAnsiString(&RootString
, &NtSystemRoot
, FALSE
);
500 if (!NT_SUCCESS(Status
)) return FALSE
;
502 /* Assign drive letters */
503 IoAssignDriveLetters(LoaderBlock
,
508 /* Update system root */
509 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &RootString
, FALSE
);
510 if (!NT_SUCCESS(Status
)) return FALSE
;
512 /* Load the System DLL and its Entrypoints */
513 if (!NT_SUCCESS(PsLocateSystemDll())) return FALSE
;