- Some misc changes to fix some of the 250+ warnings in the MSVC build.
[reactos.git] / reactos / ntoskrnl / io / iomgr / iomgr.c
1 /*
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
6 *
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 */
9
10 /* INCLUDES ****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 ULONG IopTraceLevel = IO_IRP_DEBUG;
17
18 // should go into a proper header
19 VOID
20 NTAPI
21 IoSynchronousInvalidateDeviceRelations(
22 IN PDEVICE_OBJECT DeviceObject,
23 IN DEVICE_RELATION_TYPE Type
24 );
25
26
27 /* DATA ********************************************************************/
28
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;
41
42 GENERIC_MAPPING IopFileMapping = {
43 FILE_GENERIC_READ,
44 FILE_GENERIC_WRITE,
45 FILE_GENERIC_EXECUTE,
46 FILE_ALL_ACCESS};
47
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;
55
56 VOID INIT_FUNCTION IopInitLookasideLists(VOID);
57
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)
63 #endif
64
65 /* INIT FUNCTIONS ************************************************************/
66
67 VOID
68 INIT_FUNCTION
69 IoInitCancelHandling(VOID)
70 {
71 extern KSPIN_LOCK CancelSpinLock;
72 KeInitializeSpinLock(&CancelSpinLock);
73 }
74
75 VOID
76 INIT_FUNCTION
77 IoInitShutdownNotification (VOID)
78 {
79 InitializeListHead(&ShutdownListHead);
80 KeInitializeSpinLock(&ShutdownListLock);
81 }
82
83 VOID
84 INIT_FUNCTION
85 IopInitLookasideLists(VOID)
86 {
87 ULONG LargeIrpSize, SmallIrpSize, MdlSize;
88 LONG i;
89 PKPRCB Prcb;
90 PNPAGED_LOOKASIDE_LIST CurrentList = NULL;
91
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));
96
97 /* Initialize the Lookaside List for Large IRPs */
98 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside,
99 NULL,
100 NULL,
101 0,
102 LargeIrpSize,
103 IO_LARGEIRP,
104 64);
105
106 /* Initialize the Lookaside List for Small IRPs */
107 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside,
108 NULL,
109 NULL,
110 0,
111 SmallIrpSize,
112 IO_SMALLIRP,
113 32);
114
115 /* Initialize the Lookaside List for I\O Completion */
116 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
117 NULL,
118 NULL,
119 0,
120 sizeof(IO_COMPLETION_PACKET),
121 IOC_TAG1,
122 32);
123
124 /* Initialize the Lookaside List for MDLs */
125 ExInitializeNPagedLookasideList(&IopMdlLookasideList,
126 NULL,
127 NULL,
128 0,
129 MdlSize,
130 TAG_MDL,
131 128);
132
133 /* Now allocate the per-processor lists */
134 for (i = 0; i < KeNumberProcessors; i++)
135 {
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);
139
140 /* Set the Large IRP List */
141 Prcb->PPLookasideList[LookasideLargeIrpList].L = &IoLargeIrpLookaside.L;
142 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
143 sizeof(NPAGED_LOOKASIDE_LIST),
144 IO_LARGEIRP_CPU);
145 if (CurrentList)
146 {
147 /* Initialize the Lookaside List for Large IRPs */
148 ExInitializeNPagedLookasideList(CurrentList,
149 NULL,
150 NULL,
151 0,
152 LargeIrpSize,
153 IO_LARGEIRP_CPU,
154 64);
155 }
156 else
157 {
158 CurrentList = &IoLargeIrpLookaside;
159 }
160 Prcb->PPLookasideList[LookasideLargeIrpList].P = &CurrentList->L;
161
162 /* Set the Small IRP List */
163 Prcb->PPLookasideList[LookasideSmallIrpList].L = &IoSmallIrpLookaside.L;
164 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
165 sizeof(NPAGED_LOOKASIDE_LIST),
166 IO_SMALLIRP_CPU);
167 if (CurrentList)
168 {
169 /* Initialize the Lookaside List for Small IRPs */
170 ExInitializeNPagedLookasideList(CurrentList,
171 NULL,
172 NULL,
173 0,
174 SmallIrpSize,
175 IO_SMALLIRP_CPU,
176 32);
177 }
178 else
179 {
180 CurrentList = &IoSmallIrpLookaside;
181 }
182 Prcb->PPLookasideList[LookasideSmallIrpList].P = &CurrentList->L;
183
184 /* Set the I/O Completion List */
185 Prcb->PPLookasideList[LookasideCompletionList].L = &IoCompletionPacketLookaside.L;
186 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
187 sizeof(NPAGED_LOOKASIDE_LIST),
188 IO_SMALLIRP_CPU);
189 if (CurrentList)
190 {
191 /* Initialize the Lookaside List for Large IRPs */
192 ExInitializeNPagedLookasideList(CurrentList,
193 NULL,
194 NULL,
195 0,
196 sizeof(IO_COMPLETION_PACKET),
197 IO_SMALLIRP_CPU,
198 32);
199 }
200 else
201 {
202 CurrentList = &IoCompletionPacketLookaside;
203 }
204 Prcb->PPLookasideList[LookasideCompletionList].P = &CurrentList->L;
205
206 /* Set the MDL Completion List */
207 Prcb->PPLookasideList[LookasideMdlList].L = &IopMdlLookasideList.L;
208 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
209 sizeof(NPAGED_LOOKASIDE_LIST),
210 TAG_MDL);
211 if (CurrentList)
212 {
213 /* Initialize the Lookaside List for MDLs */
214 ExInitializeNPagedLookasideList(CurrentList,
215 NULL,
216 NULL,
217 0,
218 SmallIrpSize,
219 TAG_MDL,
220 128);
221 }
222 else
223 {
224 CurrentList = &IopMdlLookasideList;
225 }
226 Prcb->PPLookasideList[LookasideMdlList].P = &CurrentList->L;
227 }
228
229 DPRINT("Done allocation\n");
230 }
231
232
233 BOOLEAN
234 INIT_FUNCTION
235 NTAPI
236 IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
237 {
238 PDEVICE_NODE DeviceNode;
239 PDRIVER_OBJECT DriverObject;
240 LDR_DATA_TABLE_ENTRY ModuleObject;
241 NTSTATUS Status;
242 CHAR Buffer[256];
243 ANSI_STRING NtBootPath, RootString;
244 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
245 UNICODE_STRING Name;
246 OBJECT_ATTRIBUTES ObjectAttributes;
247 UNICODE_STRING DirName;
248 UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\DosDevices");
249 HANDLE Handle;
250
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;
259
260 /* Do the Adapter Type */
261 RtlInitUnicodeString(&Name, L"Adapter");
262 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoAdapterObjectType);
263
264 /* Do the Controller Type */
265 RtlInitUnicodeString(&Name, L"Controller");
266 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
267 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoControllerObjectType);
268
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);
275
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);
283
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);
292
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);
307
308 /*
309 * Create the '\Driver' object directory
310 */
311 RtlInitUnicodeString(&DirName, L"\\Driver");
312 InitializeObjectAttributes(&ObjectAttributes,
313 &DirName,
314 0,
315 NULL,
316 NULL);
317 ZwCreateDirectoryObject(&Handle,
318 0,
319 &ObjectAttributes);
320
321 /*
322 * Create the '\FileSystem' object directory
323 */
324 RtlInitUnicodeString(&DirName,
325 L"\\FileSystem");
326 InitializeObjectAttributes(&ObjectAttributes,
327 &DirName,
328 0,
329 NULL,
330 NULL);
331 ZwCreateDirectoryObject(&Handle,
332 0,
333 &ObjectAttributes);
334
335 /*
336 * Create the '\Device' directory
337 */
338 RtlInitUnicodeString(&DirName,
339 L"\\Device");
340 InitializeObjectAttributes(&ObjectAttributes,
341 &DirName,
342 0,
343 NULL,
344 NULL);
345 ZwCreateDirectoryObject(&Handle,
346 0,
347 &ObjectAttributes);
348
349 /*
350 * Create the '\??' directory
351 */
352 RtlInitUnicodeString(&DirName,
353 L"\\??");
354 InitializeObjectAttributes(&ObjectAttributes,
355 &DirName,
356 0,
357 NULL,
358 NULL);
359 ZwCreateDirectoryObject(&Handle,
360 0,
361 &ObjectAttributes);
362
363 /*
364 * Create the '\ArcName' directory
365 */
366 RtlInitUnicodeString(&DirName,
367 L"\\ArcName");
368 InitializeObjectAttributes(&ObjectAttributes,
369 &DirName,
370 0,
371 NULL,
372 NULL);
373 ZwCreateDirectoryObject(&Handle,
374 0,
375 &ObjectAttributes);
376
377 /*
378 * Initialize remaining subsubsystem
379 */
380 IopInitDriverImplementation();
381 IoInitCancelHandling();
382 IoInitFileSystemImplementation();
383 IoInitVpbImplementation();
384 IoInitShutdownNotification();
385 IopInitPnpNotificationImplementation();
386 IopInitErrorLog();
387 IopInitTimerImplementation();
388 IopInitLookasideLists();
389
390 /*
391 * Create link from '\DosDevices' to '\??' directory
392 */
393 RtlInitUnicodeString(&DirName,
394 L"\\??");
395 IoCreateSymbolicLink(&LinkName,
396 &DirName);
397
398 /*
399 * Initialize PnP manager
400 */
401 PnpInit();
402
403 RtlInitEmptyAnsiString(&NtBootPath, Buffer, sizeof(Buffer));
404
405 PnpInit2();
406
407 IoCreateDriverList();
408
409 KeInitializeSpinLock (&IoStatisticsLock);
410
411 /* Initialize raw filesystem driver */
412
413 /* Use IopRootDeviceNode for now */
414 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
415 if (!NT_SUCCESS(Status))
416 {
417 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
418 return FALSE;
419 }
420
421 ModuleObject.DllBase = NULL;
422 ModuleObject.SizeOfImage = 0;
423 ModuleObject.EntryPoint = RawFsDriverEntry;
424
425 Status = IopInitializeDriverModule(DeviceNode,
426 &ModuleObject,
427 &DeviceNode->ServiceName,
428 TRUE,
429 &DriverObject);
430 if (!NT_SUCCESS(Status))
431 {
432 IopFreeDeviceNode(DeviceNode);
433 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
434 return FALSE;
435 }
436
437 Status = IopInitializeDevice(DeviceNode, DriverObject);
438 if (!NT_SUCCESS(Status))
439 {
440 IopFreeDeviceNode(DeviceNode);
441 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
442 return FALSE;
443 }
444
445 Status = IopStartDevice(DeviceNode);
446 if (!NT_SUCCESS(Status))
447 {
448 IopFreeDeviceNode(DeviceNode);
449 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
450 return FALSE;
451 }
452
453 /*
454 * Initialize PnP root releations
455 */
456 IoSynchronousInvalidateDeviceRelations(IopRootDeviceNode->
457 PhysicalDeviceObject,
458 BusRelations);
459
460 /* Load boot start drivers */
461 IopInitializeBootDrivers();
462
463 /* Call back drivers that asked for */
464 IopReinitializeBootDrivers();
465
466 /* Create ARC names for boot devices */
467 IopCreateArcNames(LoaderBlock);
468
469 /* Read KDB Data */
470 KdbInit();
471
472 /* I/O is now setup for disk access, so phase 3 */
473 KdInitSystem(3, LoaderBlock);
474
475 /* Load services for devices found by PnP manager */
476 IopInitializePnpServices(IopRootDeviceNode, FALSE);
477
478 /* Load system start drivers */
479 IopInitializeSystemDrivers();
480
481 /* Destroy the group driver list */
482 IoDestroyDriverList();
483
484 /* Reinitialize drivers that requested it */
485 IopReinitializeDrivers();
486
487 /* Convert SystemRoot from ARC to NT path */
488 Status = IopReassignSystemRoot(LoaderBlock, &NtBootPath);
489 if (!NT_SUCCESS(Status)) return FALSE;
490
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,
496 TAG_IO);
497
498 /* Convert the path into the ANSI_STRING */
499 Status = RtlUnicodeStringToAnsiString(&RootString, &NtSystemRoot, FALSE);
500 if (!NT_SUCCESS(Status)) return FALSE;
501
502 /* Assign drive letters */
503 IoAssignDriveLetters(LoaderBlock,
504 &NtBootPath,
505 RootString.Buffer,
506 &RootString);
507
508 /* Update system root */
509 Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &RootString, FALSE);
510 if (!NT_SUCCESS(Status)) return FALSE;
511
512 /* Load the System DLL and its Entrypoints */
513 if (!NT_SUCCESS(PsLocateSystemDll())) return FALSE;
514
515 /* Return success */
516 return TRUE;
517 }
518
519 /* EOF */