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 IoDeviceObjectType
= NULL
;
19 POBJECT_TYPE IoFileObjectType
= NULL
;
20 extern POBJECT_TYPE IoControllerObjectType
;
21 ULONG IoReadOperationCount
= 0;
22 LARGE_INTEGER IoReadTransferCount
= {{0, 0}};
23 ULONG IoWriteOperationCount
= 0;
24 LARGE_INTEGER IoWriteTransferCount
= {{0, 0}};
25 ULONG IoOtherOperationCount
= 0;
26 LARGE_INTEGER IoOtherTransferCount
= {{0, 0}};
27 KSPIN_LOCK 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 extern POBJECT_TYPE IoAdapterObjectType
;
40 NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside
;
41 NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside
;
43 VOID INIT_FUNCTION
IopInitLookasideLists(VOID
);
45 #if defined (ALLOC_PRAGMA)
46 #pragma alloc_text(INIT, IoInitCancelHandling)
47 #pragma alloc_text(INIT, IoInitShutdownNotification)
48 #pragma alloc_text(INIT, IopInitLookasideLists)
49 #pragma alloc_text(INIT, IoInit)
50 #pragma alloc_text(INIT, IoInit2)
51 #pragma alloc_text(INIT, IoInit3)
55 /* INIT FUNCTIONS ************************************************************/
59 IoInitCancelHandling(VOID
)
61 KeInitializeSpinLock(&CancelSpinLock
);
66 IoInitShutdownNotification (VOID
)
68 InitializeListHead(&ShutdownListHead
);
69 KeInitializeSpinLock(&ShutdownListLock
);
74 IopInitLookasideLists(VOID
)
76 ULONG LargeIrpSize
, SmallIrpSize
;
79 PNPAGED_LOOKASIDE_LIST CurrentList
= NULL
;
81 /* Calculate the sizes */
82 LargeIrpSize
= sizeof(IRP
) + (8 * sizeof(IO_STACK_LOCATION
));
83 SmallIrpSize
= sizeof(IRP
) + sizeof(IO_STACK_LOCATION
);
85 /* Initialize the Lookaside List for Large IRPs */
86 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside
,
94 /* Initialize the Lookaside List for Small IRPs */
95 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside
,
103 /* Initialize the Lookaside List for I\O Completion */
104 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside
,
108 sizeof(IO_COMPLETION_PACKET
),
112 /* Now allocate the per-processor lists */
113 for (i
= 0; i
< KeNumberProcessors
; i
++)
115 /* Get the PRCB for this CPU */
116 Prcb
= ((PKPCR
)(KPCR_BASE
+ i
* PAGE_SIZE
))->Prcb
;
117 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i
, Prcb
);
119 /* Set the Large IRP List */
120 Prcb
->PPLookasideList
[LookasideLargeIrpList
].L
= &IoLargeIrpLookaside
.L
;
121 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
122 sizeof(NPAGED_LOOKASIDE_LIST
),
126 /* Initialize the Lookaside List for Large IRPs */
127 ExInitializeNPagedLookasideList(CurrentList
,
137 CurrentList
= &IoLargeIrpLookaside
;
139 Prcb
->PPLookasideList
[LookasideLargeIrpList
].P
= &CurrentList
->L
;
141 /* Set the Small IRP List */
142 Prcb
->PPLookasideList
[LookasideSmallIrpList
].L
= &IoSmallIrpLookaside
.L
;
143 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
144 sizeof(NPAGED_LOOKASIDE_LIST
),
148 /* Initialize the Lookaside List for Large IRPs */
149 ExInitializeNPagedLookasideList(CurrentList
,
159 CurrentList
= &IoSmallIrpLookaside
;
161 Prcb
->PPLookasideList
[LookasideSmallIrpList
].P
= &CurrentList
->L
;
163 /* Set the I/O Completion List */
164 Prcb
->PPLookasideList
[LookasideCompletionList
].L
= &IoCompletionPacketLookaside
.L
;
165 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
166 sizeof(NPAGED_LOOKASIDE_LIST
),
170 /* Initialize the Lookaside List for Large IRPs */
171 ExInitializeNPagedLookasideList(CurrentList
,
181 CurrentList
= &IoCompletionPacketLookaside
;
183 Prcb
->PPLookasideList
[LookasideCompletionList
].P
= &CurrentList
->L
;
186 DPRINT("Done allocation\n");
193 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
195 OBJECT_ATTRIBUTES ObjectAttributes
;
196 UNICODE_STRING DirName
;
197 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices");
200 IopInitDriverImplementation();
202 DPRINT("Creating Device Object Type\n");
204 /* Initialize the Driver object type */
205 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
206 RtlInitUnicodeString(&Name
, L
"Device");
207 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
208 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DEVICE_OBJECT
);
209 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
210 ObjectTypeInitializer
.ValidAccessMask
= FILE_ALL_ACCESS
;
211 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
212 ObjectTypeInitializer
.GenericMapping
= IopFileMapping
;
213 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &IoDeviceObjectType
);
215 /* Do the Adapter Type */
216 RtlInitUnicodeString(&Name
, L
"Adapter");
217 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &IoAdapterObjectType
);
219 /* Do the Controller Type */
220 RtlInitUnicodeString(&Name
, L
"Controller");
221 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(CONTROLLER_OBJECT
);
222 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &IoControllerObjectType
);
224 /* Initialize the File object type */
225 RtlInitUnicodeString(&Name
, L
"File");
226 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
227 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(FILE_OBJECT
);
228 ObjectTypeInitializer
.CloseProcedure
= IopCloseFile
;
229 ObjectTypeInitializer
.DeleteProcedure
= IopDeleteFile
;
230 ObjectTypeInitializer
.SecurityProcedure
= IopSecurityFile
;
231 ObjectTypeInitializer
.QueryNameProcedure
= IopQueryNameFile
;
232 ObjectTypeInitializer
.UseDefaultObject
= FALSE
;
233 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &IoFileObjectType
);
236 * Create the '\Driver' object directory
238 RtlInitUnicodeString(&DirName
, L
"\\Driver");
239 InitializeObjectAttributes(&ObjectAttributes
,
244 ZwCreateDirectoryObject(&Handle
,
249 * Create the '\FileSystem' object directory
251 RtlInitUnicodeString(&DirName
,
253 InitializeObjectAttributes(&ObjectAttributes
,
258 ZwCreateDirectoryObject(&Handle
,
263 * Create the '\Device' directory
265 RtlInitUnicodeString(&DirName
,
267 InitializeObjectAttributes(&ObjectAttributes
,
272 ZwCreateDirectoryObject(&Handle
,
277 * Create the '\??' directory
279 RtlInitUnicodeString(&DirName
,
281 InitializeObjectAttributes(&ObjectAttributes
,
286 ZwCreateDirectoryObject(&Handle
,
291 * Create the '\ArcName' directory
293 RtlInitUnicodeString(&DirName
,
295 InitializeObjectAttributes(&ObjectAttributes
,
300 ZwCreateDirectoryObject(&Handle
,
305 * Initialize remaining subsubsystem
307 IoInitCancelHandling();
308 IoInitFileSystemImplementation();
309 IoInitVpbImplementation();
310 IoInitShutdownNotification();
311 IopInitPnpNotificationImplementation();
313 IopInitTimerImplementation();
314 IopInitIoCompletionImplementation();
315 IopInitLookasideLists();
318 * Create link from '\DosDevices' to '\??' directory
320 RtlInitUnicodeString(&DirName
,
322 IoCreateSymbolicLink(&LinkName
,
326 * Initialize PnP manager
333 IoInit2(BOOLEAN BootLog
)
335 PDEVICE_NODE DeviceNode
;
336 PDRIVER_OBJECT DriverObject
;
337 LDR_DATA_TABLE_ENTRY ModuleObject
;
342 IoCreateDriverList();
344 KeInitializeSpinLock (&IoStatisticsLock
);
346 /* Initialize raw filesystem driver */
348 /* Use IopRootDeviceNode for now */
349 Status
= IopCreateDeviceNode(IopRootDeviceNode
,
352 if (!NT_SUCCESS(Status
))
354 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status
);
358 ModuleObject
.DllBase
= NULL
;
359 ModuleObject
.SizeOfImage
= 0;
360 ModuleObject
.EntryPoint
= RawFsDriverEntry
;
362 Status
= IopInitializeDriverModule(
365 &DeviceNode
->ServiceName
,
368 if (!NT_SUCCESS(Status
))
370 IopFreeDeviceNode(DeviceNode
);
371 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status
);
375 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
376 if (!NT_SUCCESS(Status
))
378 IopFreeDeviceNode(DeviceNode
);
379 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
383 Status
= IopStartDevice(DeviceNode
);
384 if (!NT_SUCCESS(Status
))
386 IopFreeDeviceNode(DeviceNode
);
387 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status
);
392 * Initialize PnP root releations
394 IopInvalidateDeviceRelations(
398 /* Start boot logging */
399 IopInitBootLog(BootLog
);
401 /* Load boot start drivers */
402 IopInitializeBootDrivers();
412 /* Create ARC names for boot devices */
415 /* Create the SystemRoot symbolic link */
416 DPRINT("CommandLine: %s\n", (PCHAR
)KeLoaderBlock
.CommandLine
);
417 Status
= IoCreateSystemRootLink((PCHAR
)KeLoaderBlock
.CommandLine
);
418 if (!NT_SUCCESS(Status
)) {
419 CPRINT("IoCreateSystemRootLink FAILED: (0x%x) - ", Status
);
420 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE
);
426 /* I/O is now setup for disk access, so phase 3 */
427 KdInitSystem(3, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
429 /* Load services for devices found by PnP manager */
430 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
432 /* Load system start drivers */
433 IopInitializeSystemDrivers();
434 IoDestroyDriverList();
436 /* Stop boot logging */
439 /* Assign drive letters */
440 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
446 /* FUNCTIONS *****************************************************************/
453 IoAcquireCancelSpinLock(PKIRQL Irql
)
455 KeAcquireSpinLock(&CancelSpinLock
,Irql
);
463 IoGetInitialStack(VOID
)
465 return(PsGetCurrentThread()->Tcb
.InitialStack
);
473 IoGetStackLimits(OUT PULONG LowLimit
,
474 OUT PULONG HighLimit
)
476 *LowLimit
= (ULONG
)NtCurrentTeb()->Tib
.StackLimit
;
477 *HighLimit
= (ULONG
)NtCurrentTeb()->Tib
.StackBase
;
485 IoIsSystemThread(IN PETHREAD Thread
)
487 /* Call the Ps Function */
488 return PsIsSystemThread(Thread
);
495 IoIsWdmVersionAvailable(IN UCHAR MajorVersion
,
496 IN UCHAR MinorVersion
)
498 /* MinorVersion = 0x20 : WinXP
505 if (MajorVersion
<= 1 && MinorVersion
<= 0x10)
515 IoReleaseCancelSpinLock(KIRQL Irql
)
517 KeReleaseSpinLock(&CancelSpinLock
,Irql
);
525 IoThreadToProcess(IN PETHREAD Thread
)
527 return(Thread
->ThreadsProcess
);