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 /* DATA ********************************************************************/
18 POBJECT_TYPE EXPORTED IoDeviceObjectType
= NULL
;
19 POBJECT_TYPE EXPORTED IoFileObjectType
= NULL
;
20 extern POBJECT_TYPE IoControllerObjectType
;
21 ULONG EXPORTED IoReadOperationCount
= 0;
22 ULONGLONG EXPORTED IoReadTransferCount
= 0;
23 ULONG EXPORTED IoWriteOperationCount
= 0;
24 ULONGLONG EXPORTED IoWriteTransferCount
= 0;
25 ULONG IoOtherOperationCount
= 0;
26 ULONGLONG IoOtherTransferCount
= 0;
27 KSPIN_LOCK EXPORTED IoStatisticsLock
= 0;
29 GENERIC_MAPPING IopFileMapping
= {
35 static KSPIN_LOCK CancelSpinLock
;
36 extern LIST_ENTRY ShutdownListHead
;
37 extern KSPIN_LOCK ShutdownListLock
;
38 extern NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside
;
39 NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside
;
40 NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside
;
42 /* INIT FUNCTIONS ************************************************************/
46 IoInitCancelHandling(VOID
)
48 KeInitializeSpinLock(&CancelSpinLock
);
53 IoInitShutdownNotification (VOID
)
55 InitializeListHead(&ShutdownListHead
);
56 KeInitializeSpinLock(&ShutdownListLock
);
61 IopInitLookasideLists(VOID
)
63 ULONG LargeIrpSize
, SmallIrpSize
;
66 PNPAGED_LOOKASIDE_LIST CurrentList
= NULL
;
68 /* Calculate the sizes */
69 LargeIrpSize
= sizeof(IRP
) + (8 * sizeof(IO_STACK_LOCATION
));
70 SmallIrpSize
= sizeof(IRP
) + sizeof(IO_STACK_LOCATION
);
72 /* Initialize the Lookaside List for Large IRPs */
73 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside
,
81 /* Initialize the Lookaside List for Small IRPs */
82 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside
,
90 /* Initialize the Lookaside List for I\O Completion */
91 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside
,
95 sizeof(IO_COMPLETION_PACKET
),
99 /* Now allocate the per-processor lists */
100 for (i
= 0; i
< KeNumberProcessors
; i
++)
102 /* Get the PRCB for this CPU */
103 Prcb
= ((PKPCR
)(KPCR_BASE
+ i
* PAGE_SIZE
))->Prcb
;
104 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i
, Prcb
);
106 /* Set the Large IRP List */
107 Prcb
->PPLookasideList
[LookasideLargeIrpList
].L
= &IoLargeIrpLookaside
.L
;
108 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
109 sizeof(NPAGED_LOOKASIDE_LIST
),
113 /* Initialize the Lookaside List for Large IRPs */
114 ExInitializeNPagedLookasideList(CurrentList
,
124 CurrentList
= &IoLargeIrpLookaside
;
126 Prcb
->PPLookasideList
[LookasideLargeIrpList
].P
= &CurrentList
->L
;
128 /* Set the Small IRP List */
129 Prcb
->PPLookasideList
[LookasideSmallIrpList
].L
= &IoSmallIrpLookaside
.L
;
130 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
131 sizeof(NPAGED_LOOKASIDE_LIST
),
135 /* Initialize the Lookaside List for Large IRPs */
136 ExInitializeNPagedLookasideList(CurrentList
,
146 CurrentList
= &IoSmallIrpLookaside
;
148 Prcb
->PPLookasideList
[LookasideSmallIrpList
].P
= &CurrentList
->L
;
150 /* Set the I/O Completion List */
151 Prcb
->PPLookasideList
[LookasideCompletionList
].L
= &IoCompletionPacketLookaside
.L
;
152 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
153 sizeof(NPAGED_LOOKASIDE_LIST
),
157 /* Initialize the Lookaside List for Large IRPs */
158 ExInitializeNPagedLookasideList(CurrentList
,
168 CurrentList
= &IoCompletionPacketLookaside
;
170 Prcb
->PPLookasideList
[LookasideCompletionList
].P
= &CurrentList
->L
;
173 DPRINT("Done allocation\n");
180 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
182 OBJECT_ATTRIBUTES ObjectAttributes
;
183 UNICODE_STRING DirName
;
184 UNICODE_STRING LinkName
;
187 IopInitDriverImplementation();
189 DPRINT1("Creating Device Object Type\n");
191 /* Initialize the Driver object type */
192 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
193 RtlInitUnicodeString(&Name
, L
"Device");
194 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
195 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DEVICE_OBJECT
);
196 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
197 ObjectTypeInitializer
.ValidAccessMask
= FILE_ALL_ACCESS
;
198 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
199 ObjectTypeInitializer
.GenericMapping
= IopFileMapping
;
200 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &IoDeviceObjectType
);
202 /* Do the Adapter Type */
203 RtlInitUnicodeString(&Name
, L
"Adapter");
204 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &IoAdapterObjectType
);
206 /* Do the Controller Type */
207 RtlInitUnicodeString(&Name
, L
"Controller");
208 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(CONTROLLER_OBJECT
);
209 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &IoControllerObjectType
);
211 /* Initialize the File object type */
212 RtlInitUnicodeString(&Name
, L
"File");
213 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
214 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(FILE_OBJECT
);
215 ObjectTypeInitializer
.CloseProcedure
= IopCloseFile
;
216 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteFile
;
217 ObjectTypeInitializer
.SecurityProcedure
= IopSecurityFile
;
218 ObjectTypeInitializer
.QueryNameProcedure
= IopQueryNameFile
;
219 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &IoFileObjectType
);
222 * Create the '\Driver' object directory
224 RtlRosInitUnicodeStringFromLiteral(&DirName
, L
"\\Driver");
225 InitializeObjectAttributes(&ObjectAttributes
,
230 ZwCreateDirectoryObject(&Handle
,
235 * Create the '\FileSystem' object directory
237 RtlRosInitUnicodeStringFromLiteral(&DirName
,
239 InitializeObjectAttributes(&ObjectAttributes
,
244 ZwCreateDirectoryObject(&Handle
,
249 * Create the '\Device' directory
251 RtlRosInitUnicodeStringFromLiteral(&DirName
,
253 InitializeObjectAttributes(&ObjectAttributes
,
258 ZwCreateDirectoryObject(&Handle
,
263 * Create the '\??' directory
265 RtlRosInitUnicodeStringFromLiteral(&DirName
,
267 InitializeObjectAttributes(&ObjectAttributes
,
272 ZwCreateDirectoryObject(&Handle
,
277 * Create the '\ArcName' directory
279 RtlRosInitUnicodeStringFromLiteral(&DirName
,
281 InitializeObjectAttributes(&ObjectAttributes
,
286 ZwCreateDirectoryObject(&Handle
,
291 * Initialize remaining subsubsystem
293 IoInitCancelHandling();
294 IoInitFileSystemImplementation();
295 IoInitVpbImplementation();
296 IoInitShutdownNotification();
297 IopInitPnpNotificationImplementation();
299 IopInitTimerImplementation();
300 IopInitIoCompletionImplementation();
301 IopInitLookasideLists();
304 * Create link from '\DosDevices' to '\??' directory
306 RtlRosInitUnicodeStringFromLiteral(&LinkName
,
308 RtlRosInitUnicodeStringFromLiteral(&DirName
,
310 IoCreateSymbolicLink(&LinkName
,
314 * Initialize PnP manager
321 IoInit2(BOOLEAN BootLog
)
323 PDEVICE_NODE DeviceNode
;
324 PDRIVER_OBJECT DriverObject
;
325 MODULE_OBJECT ModuleObject
;
328 IoCreateDriverList();
330 KeInitializeSpinLock (&IoStatisticsLock
);
332 /* Initialize raw filesystem driver */
334 /* Use IopRootDeviceNode for now */
335 Status
= IopCreateDeviceNode(IopRootDeviceNode
,
338 if (!NT_SUCCESS(Status
))
340 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status
);
344 ModuleObject
.Base
= NULL
;
345 ModuleObject
.Length
= 0;
346 ModuleObject
.EntryPoint
= RawFsDriverEntry
;
348 Status
= IopInitializeDriverModule(
351 &DeviceNode
->ServiceName
,
354 if (!NT_SUCCESS(Status
))
356 IopFreeDeviceNode(DeviceNode
);
357 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status
);
361 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
362 if (!NT_SUCCESS(Status
))
364 IopFreeDeviceNode(DeviceNode
);
365 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
369 Status
= IopStartDevice(DeviceNode
);
370 if (!NT_SUCCESS(Status
))
372 IopFreeDeviceNode(DeviceNode
);
373 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
378 * Initialize PnP root releations
380 IopInvalidateDeviceRelations(
384 /* Start boot logging */
385 IopInitBootLog(BootLog
);
387 /* Load boot start drivers */
388 IopInitializeBootDrivers();
398 /* Create ARC names for boot devices */
401 /* Create the SystemRoot symbolic link */
402 DPRINT("CommandLine: %s\n", (PCHAR
)KeLoaderBlock
.CommandLine
);
403 Status
= IoCreateSystemRootLink((PCHAR
)KeLoaderBlock
.CommandLine
);
404 if (!NT_SUCCESS(Status
)) {
405 CPRINT("IoCreateSystemRootLink FAILED: (0x%x) - ", Status
);
406 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE
);
412 /* I/O is now setup for disk access, so phase 3 */
413 KdInitSystem(3, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
415 /* Load services for devices found by PnP manager */
416 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
418 /* Load system start drivers */
419 IopInitializeSystemDrivers();
420 IoDestroyDriverList();
422 /* Stop boot logging */
425 /* Assign drive letters */
426 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
432 /* FUNCTIONS *****************************************************************/
439 IoAcquireCancelSpinLock(PKIRQL Irql
)
441 KeAcquireSpinLock(&CancelSpinLock
,Irql
);
449 IoGetInitialStack(VOID
)
451 return(PsGetCurrentThread()->Tcb
.InitialStack
);
459 IoGetStackLimits(OUT PULONG LowLimit
,
460 OUT PULONG HighLimit
)
462 *LowLimit
= (ULONG
)NtCurrentTeb()->Tib
.StackLimit
;
463 *HighLimit
= (ULONG
)NtCurrentTeb()->Tib
.StackBase
;
471 IoIsSystemThread(IN PETHREAD Thread
)
473 /* Call the Ps Function */
474 return PsIsSystemThread(Thread
);
481 IoIsWdmVersionAvailable(IN UCHAR MajorVersion
,
482 IN UCHAR MinorVersion
)
484 if (MajorVersion
<= 1 && MinorVersion
<= 10)
494 IoReleaseCancelSpinLock(KIRQL Irql
)
496 KeReleaseSpinLock(&CancelSpinLock
,Irql
);
504 IoThreadToProcess(IN PETHREAD Thread
)
506 return(Thread
->ThreadsProcess
);