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 /* DATA ********************************************************************/
20 POBJECT_TYPE IoDeviceObjectType
= NULL
;
21 POBJECT_TYPE IoFileObjectType
= NULL
;
22 extern POBJECT_TYPE IoControllerObjectType
;
23 BOOLEAN IoCountOperations
;
24 ULONG IoReadOperationCount
= 0;
25 LARGE_INTEGER IoReadTransferCount
= {{0, 0}};
26 ULONG IoWriteOperationCount
= 0;
27 LARGE_INTEGER IoWriteTransferCount
= {{0, 0}};
28 ULONG IoOtherOperationCount
= 0;
29 LARGE_INTEGER IoOtherTransferCount
= {{0, 0}};
30 KSPIN_LOCK IoStatisticsLock
= 0;
32 GENERIC_MAPPING IopFileMapping
= {
38 extern LIST_ENTRY ShutdownListHead
;
39 extern KSPIN_LOCK ShutdownListLock
;
40 extern NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside
;
41 extern POBJECT_TYPE IoAdapterObjectType
;
42 NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside
;
43 NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside
;
44 NPAGED_LOOKASIDE_LIST IopMdlLookasideList
;
46 VOID INIT_FUNCTION
IopInitLookasideLists(VOID
);
48 #if defined (ALLOC_PRAGMA)
49 #pragma alloc_text(INIT, IoInitCancelHandling)
50 #pragma alloc_text(INIT, IoInitShutdownNotification)
51 #pragma alloc_text(INIT, IopInitLookasideLists)
52 #pragma alloc_text(INIT, IoInit)
53 #pragma alloc_text(INIT, IoInit2)
54 #pragma alloc_text(INIT, IoInit3)
57 /* INIT FUNCTIONS ************************************************************/
61 IoInitCancelHandling(VOID
)
63 extern KSPIN_LOCK CancelSpinLock
;
64 KeInitializeSpinLock(&CancelSpinLock
);
69 IoInitShutdownNotification (VOID
)
71 InitializeListHead(&ShutdownListHead
);
72 KeInitializeSpinLock(&ShutdownListLock
);
77 IopInitLookasideLists(VOID
)
79 ULONG LargeIrpSize
, SmallIrpSize
, MdlSize
;
82 PNPAGED_LOOKASIDE_LIST CurrentList
= NULL
;
84 /* Calculate the sizes */
85 LargeIrpSize
= sizeof(IRP
) + (8 * sizeof(IO_STACK_LOCATION
));
86 SmallIrpSize
= sizeof(IRP
) + sizeof(IO_STACK_LOCATION
);
87 MdlSize
= sizeof(MDL
) + (23 * sizeof(PFN_NUMBER
));
89 /* Initialize the Lookaside List for Large IRPs */
90 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside
,
98 /* Initialize the Lookaside List for Small IRPs */
99 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside
,
107 /* Initialize the Lookaside List for I\O Completion */
108 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside
,
112 sizeof(IO_COMPLETION_PACKET
),
116 /* Initialize the Lookaside List for MDLs */
117 ExInitializeNPagedLookasideList(&IopMdlLookasideList
,
125 /* Now allocate the per-processor lists */
126 for (i
= 0; i
< KeNumberProcessors
; i
++)
128 /* Get the PRCB for this CPU */
129 Prcb
= ((PKPCR
)(KPCR_BASE
+ i
* PAGE_SIZE
))->Prcb
;
130 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i
, Prcb
);
132 /* Set the Large IRP List */
133 Prcb
->PPLookasideList
[LookasideLargeIrpList
].L
= &IoLargeIrpLookaside
.L
;
134 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
135 sizeof(NPAGED_LOOKASIDE_LIST
),
139 /* Initialize the Lookaside List for Large IRPs */
140 ExInitializeNPagedLookasideList(CurrentList
,
150 CurrentList
= &IoLargeIrpLookaside
;
152 Prcb
->PPLookasideList
[LookasideLargeIrpList
].P
= &CurrentList
->L
;
154 /* Set the Small IRP List */
155 Prcb
->PPLookasideList
[LookasideSmallIrpList
].L
= &IoSmallIrpLookaside
.L
;
156 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
157 sizeof(NPAGED_LOOKASIDE_LIST
),
161 /* Initialize the Lookaside List for Small IRPs */
162 ExInitializeNPagedLookasideList(CurrentList
,
172 CurrentList
= &IoSmallIrpLookaside
;
174 Prcb
->PPLookasideList
[LookasideSmallIrpList
].P
= &CurrentList
->L
;
176 /* Set the I/O Completion List */
177 Prcb
->PPLookasideList
[LookasideCompletionList
].L
= &IoCompletionPacketLookaside
.L
;
178 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
179 sizeof(NPAGED_LOOKASIDE_LIST
),
183 /* Initialize the Lookaside List for Large IRPs */
184 ExInitializeNPagedLookasideList(CurrentList
,
188 sizeof(IO_COMPLETION_PACKET
),
194 CurrentList
= &IoCompletionPacketLookaside
;
196 Prcb
->PPLookasideList
[LookasideCompletionList
].P
= &CurrentList
->L
;
198 /* Set the MDL Completion List */
199 Prcb
->PPLookasideList
[LookasideMdlList
].L
= &IopMdlLookasideList
.L
;
200 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
201 sizeof(NPAGED_LOOKASIDE_LIST
),
205 /* Initialize the Lookaside List for MDLs */
206 ExInitializeNPagedLookasideList(CurrentList
,
216 CurrentList
= &IopMdlLookasideList
;
218 Prcb
->PPLookasideList
[LookasideMdlList
].P
= &CurrentList
->L
;
221 DPRINT("Done allocation\n");
228 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
230 OBJECT_ATTRIBUTES ObjectAttributes
;
231 UNICODE_STRING DirName
;
232 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices");
235 /* Initialize default settings */
236 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
237 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
238 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
239 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
240 ObjectTypeInitializer
.ValidAccessMask
= FILE_ALL_ACCESS
;
241 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
242 ObjectTypeInitializer
.GenericMapping
= IopFileMapping
;
244 /* Do the Adapter Type */
245 RtlInitUnicodeString(&Name
, L
"Adapter");
246 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoAdapterObjectType
);
248 /* Do the Controller Type */
249 RtlInitUnicodeString(&Name
, L
"Controller");
250 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(CONTROLLER_OBJECT
);
251 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoControllerObjectType
);
253 /* Do the Device Type */
254 RtlInitUnicodeString(&Name
, L
"Device");
255 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DEVICE_OBJECT
);
256 ObjectTypeInitializer
.ParseProcedure
= IopParseDevice
;
257 ObjectTypeInitializer
.SecurityProcedure
= IopSecurityFile
;
258 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoDeviceObjectType
);
260 /* Initialize the Driver object type */
261 RtlInitUnicodeString(&Name
, L
"Driver");
262 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DRIVER_OBJECT
);
263 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteDriver
;
264 ObjectTypeInitializer
.ParseProcedure
= NULL
;
265 ObjectTypeInitializer
.SecurityProcedure
= NULL
;
266 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoDriverObjectType
);
268 /* Initialize the I/O Completion object type */
269 RtlInitUnicodeString(&Name
, L
"IoCompletion");
270 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KQUEUE
);
271 ObjectTypeInitializer
.ValidAccessMask
= IO_COMPLETION_ALL_ACCESS
;
272 ObjectTypeInitializer
.InvalidAttributes
|= OBJ_PERMANENT
;
273 ObjectTypeInitializer
.GenericMapping
= IopCompletionMapping
;
274 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteIoCompletion
;
275 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoCompletionType
);
277 /* Initialize the File object type */
278 RtlInitUnicodeString(&Name
, L
"File");
279 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(FILE_OBJECT
);
280 ObjectTypeInitializer
.InvalidAttributes
|= OBJ_EXCLUSIVE
;
281 ObjectTypeInitializer
.MaintainHandleCount
= TRUE
;
282 ObjectTypeInitializer
.ValidAccessMask
= FILE_ALL_ACCESS
;
283 ObjectTypeInitializer
.GenericMapping
= IopFileMapping
;
284 ObjectTypeInitializer
.CloseProcedure
= IopCloseFile
;
285 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteFile
;
286 ObjectTypeInitializer
.SecurityProcedure
= IopSecurityFile
;
287 ObjectTypeInitializer
.QueryNameProcedure
= IopQueryNameFile
;
288 ObjectTypeInitializer
.ParseProcedure
= IopParseFile
;
289 ObjectTypeInitializer
.UseDefaultObject
= FALSE
;
290 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &IoFileObjectType
);
293 * Create the '\Driver' object directory
295 RtlInitUnicodeString(&DirName
, L
"\\Driver");
296 InitializeObjectAttributes(&ObjectAttributes
,
301 ZwCreateDirectoryObject(&Handle
,
306 * Create the '\FileSystem' object directory
308 RtlInitUnicodeString(&DirName
,
310 InitializeObjectAttributes(&ObjectAttributes
,
315 ZwCreateDirectoryObject(&Handle
,
320 * Create the '\Device' directory
322 RtlInitUnicodeString(&DirName
,
324 InitializeObjectAttributes(&ObjectAttributes
,
329 ZwCreateDirectoryObject(&Handle
,
334 * Create the '\??' directory
336 RtlInitUnicodeString(&DirName
,
338 InitializeObjectAttributes(&ObjectAttributes
,
343 ZwCreateDirectoryObject(&Handle
,
348 * Create the '\ArcName' directory
350 RtlInitUnicodeString(&DirName
,
352 InitializeObjectAttributes(&ObjectAttributes
,
357 ZwCreateDirectoryObject(&Handle
,
362 * Initialize remaining subsubsystem
364 IopInitDriverImplementation();
365 IoInitCancelHandling();
366 IoInitFileSystemImplementation();
367 IoInitVpbImplementation();
368 IoInitShutdownNotification();
369 IopInitPnpNotificationImplementation();
371 IopInitTimerImplementation();
372 IopInitLookasideLists();
375 * Create link from '\DosDevices' to '\??' directory
377 RtlInitUnicodeString(&DirName
,
379 IoCreateSymbolicLink(&LinkName
,
383 * Initialize PnP manager
390 IoInit2(BOOLEAN BootLog
)
392 PDEVICE_NODE DeviceNode
;
393 PDRIVER_OBJECT DriverObject
;
394 LDR_DATA_TABLE_ENTRY ModuleObject
;
399 IoCreateDriverList();
401 KeInitializeSpinLock (&IoStatisticsLock
);
403 /* Initialize raw filesystem driver */
405 /* Use IopRootDeviceNode for now */
406 Status
= IopCreateDeviceNode(IopRootDeviceNode
,
409 if (!NT_SUCCESS(Status
))
411 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status
);
415 ModuleObject
.DllBase
= NULL
;
416 ModuleObject
.SizeOfImage
= 0;
417 ModuleObject
.EntryPoint
= RawFsDriverEntry
;
419 Status
= IopInitializeDriverModule(
422 &DeviceNode
->ServiceName
,
425 if (!NT_SUCCESS(Status
))
427 IopFreeDeviceNode(DeviceNode
);
428 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status
);
432 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
433 if (!NT_SUCCESS(Status
))
435 IopFreeDeviceNode(DeviceNode
);
436 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
440 Status
= IopStartDevice(DeviceNode
);
441 if (!NT_SUCCESS(Status
))
443 IopFreeDeviceNode(DeviceNode
);
444 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
449 * Initialize PnP root releations
451 IoInvalidateDeviceRelations(
452 IopRootDeviceNode
->PhysicalDeviceObject
,
455 /* Start boot logging */
456 IopInitBootLog(BootLog
);
458 /* Load boot start drivers */
459 IopInitializeBootDrivers();
461 /* Call back drivers that asked for */
462 IopReinitializeBootDrivers();
472 /* Create ARC names for boot devices */
475 /* Create the SystemRoot symbolic link */
476 DPRINT("CommandLine: %s\n", (PCHAR
)KeLoaderBlock
.CommandLine
);
477 Status
= IoCreateSystemRootLink((PCHAR
)KeLoaderBlock
.CommandLine
);
478 if (!NT_SUCCESS(Status
)) {
479 CPRINT("IoCreateSystemRootLink FAILED: (0x%x) - ", Status
);
480 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE
);
486 /* I/O is now setup for disk access, so phase 3 */
487 KdInitSystem(3, (PROS_LOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
489 /* Load services for devices found by PnP manager */
490 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
492 /* Load system start drivers */
493 IopInitializeSystemDrivers();
494 IoDestroyDriverList();
496 /* Reinitialize drivers that requested it */
497 IopReinitializeDrivers();
499 /* Stop boot logging */
502 /* Assign drive letters */
503 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,