Resource sync from trunk.
[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 /* DATA ********************************************************************/
19
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;
31
32 GENERIC_MAPPING IopFileMapping = {
33 FILE_GENERIC_READ,
34 FILE_GENERIC_WRITE,
35 FILE_GENERIC_EXECUTE,
36 FILE_ALL_ACCESS};
37
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;
45
46 VOID INIT_FUNCTION IopInitLookasideLists(VOID);
47
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)
55 #endif
56
57 /* INIT FUNCTIONS ************************************************************/
58
59 VOID
60 INIT_FUNCTION
61 IoInitCancelHandling(VOID)
62 {
63 extern KSPIN_LOCK CancelSpinLock;
64 KeInitializeSpinLock(&CancelSpinLock);
65 }
66
67 VOID
68 INIT_FUNCTION
69 IoInitShutdownNotification (VOID)
70 {
71 InitializeListHead(&ShutdownListHead);
72 KeInitializeSpinLock(&ShutdownListLock);
73 }
74
75 VOID
76 INIT_FUNCTION
77 IopInitLookasideLists(VOID)
78 {
79 ULONG LargeIrpSize, SmallIrpSize, MdlSize;
80 LONG i;
81 PKPRCB Prcb;
82 PNPAGED_LOOKASIDE_LIST CurrentList = NULL;
83
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));
88
89 /* Initialize the Lookaside List for Large IRPs */
90 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside,
91 NULL,
92 NULL,
93 0,
94 LargeIrpSize,
95 IO_LARGEIRP,
96 64);
97
98 /* Initialize the Lookaside List for Small IRPs */
99 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside,
100 NULL,
101 NULL,
102 0,
103 SmallIrpSize,
104 IO_SMALLIRP,
105 32);
106
107 /* Initialize the Lookaside List for I\O Completion */
108 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
109 NULL,
110 NULL,
111 0,
112 sizeof(IO_COMPLETION_PACKET),
113 IOC_TAG1,
114 32);
115
116 /* Initialize the Lookaside List for MDLs */
117 ExInitializeNPagedLookasideList(&IopMdlLookasideList,
118 NULL,
119 NULL,
120 0,
121 MdlSize,
122 TAG_MDL,
123 128);
124
125 /* Now allocate the per-processor lists */
126 for (i = 0; i < KeNumberProcessors; i++)
127 {
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);
131
132 /* Set the Large IRP List */
133 Prcb->PPLookasideList[LookasideLargeIrpList].L = &IoLargeIrpLookaside.L;
134 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
135 sizeof(NPAGED_LOOKASIDE_LIST),
136 IO_LARGEIRP_CPU);
137 if (CurrentList)
138 {
139 /* Initialize the Lookaside List for Large IRPs */
140 ExInitializeNPagedLookasideList(CurrentList,
141 NULL,
142 NULL,
143 0,
144 LargeIrpSize,
145 IO_LARGEIRP_CPU,
146 64);
147 }
148 else
149 {
150 CurrentList = &IoLargeIrpLookaside;
151 }
152 Prcb->PPLookasideList[LookasideLargeIrpList].P = &CurrentList->L;
153
154 /* Set the Small IRP List */
155 Prcb->PPLookasideList[LookasideSmallIrpList].L = &IoSmallIrpLookaside.L;
156 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
157 sizeof(NPAGED_LOOKASIDE_LIST),
158 IO_SMALLIRP_CPU);
159 if (CurrentList)
160 {
161 /* Initialize the Lookaside List for Small IRPs */
162 ExInitializeNPagedLookasideList(CurrentList,
163 NULL,
164 NULL,
165 0,
166 SmallIrpSize,
167 IO_SMALLIRP_CPU,
168 32);
169 }
170 else
171 {
172 CurrentList = &IoSmallIrpLookaside;
173 }
174 Prcb->PPLookasideList[LookasideSmallIrpList].P = &CurrentList->L;
175
176 /* Set the I/O Completion List */
177 Prcb->PPLookasideList[LookasideCompletionList].L = &IoCompletionPacketLookaside.L;
178 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
179 sizeof(NPAGED_LOOKASIDE_LIST),
180 IO_SMALLIRP_CPU);
181 if (CurrentList)
182 {
183 /* Initialize the Lookaside List for Large IRPs */
184 ExInitializeNPagedLookasideList(CurrentList,
185 NULL,
186 NULL,
187 0,
188 sizeof(IO_COMPLETION_PACKET),
189 IO_SMALLIRP_CPU,
190 32);
191 }
192 else
193 {
194 CurrentList = &IoCompletionPacketLookaside;
195 }
196 Prcb->PPLookasideList[LookasideCompletionList].P = &CurrentList->L;
197
198 /* Set the MDL Completion List */
199 Prcb->PPLookasideList[LookasideMdlList].L = &IopMdlLookasideList.L;
200 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
201 sizeof(NPAGED_LOOKASIDE_LIST),
202 TAG_MDL);
203 if (CurrentList)
204 {
205 /* Initialize the Lookaside List for MDLs */
206 ExInitializeNPagedLookasideList(CurrentList,
207 NULL,
208 NULL,
209 0,
210 SmallIrpSize,
211 TAG_MDL,
212 128);
213 }
214 else
215 {
216 CurrentList = &IopMdlLookasideList;
217 }
218 Prcb->PPLookasideList[LookasideMdlList].P = &CurrentList->L;
219 }
220
221 DPRINT("Done allocation\n");
222 }
223
224 VOID
225 INIT_FUNCTION
226 IoInit (VOID)
227 {
228 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
229 UNICODE_STRING Name;
230 OBJECT_ATTRIBUTES ObjectAttributes;
231 UNICODE_STRING DirName;
232 UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\DosDevices");
233 HANDLE Handle;
234
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;
243
244 /* Do the Adapter Type */
245 RtlInitUnicodeString(&Name, L"Adapter");
246 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoAdapterObjectType);
247
248 /* Do the Controller Type */
249 RtlInitUnicodeString(&Name, L"Controller");
250 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
251 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoControllerObjectType);
252
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);
259
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);
267
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);
276
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);
291
292 /*
293 * Create the '\Driver' object directory
294 */
295 RtlInitUnicodeString(&DirName, L"\\Driver");
296 InitializeObjectAttributes(&ObjectAttributes,
297 &DirName,
298 0,
299 NULL,
300 NULL);
301 ZwCreateDirectoryObject(&Handle,
302 0,
303 &ObjectAttributes);
304
305 /*
306 * Create the '\FileSystem' object directory
307 */
308 RtlInitUnicodeString(&DirName,
309 L"\\FileSystem");
310 InitializeObjectAttributes(&ObjectAttributes,
311 &DirName,
312 0,
313 NULL,
314 NULL);
315 ZwCreateDirectoryObject(&Handle,
316 0,
317 &ObjectAttributes);
318
319 /*
320 * Create the '\Device' directory
321 */
322 RtlInitUnicodeString(&DirName,
323 L"\\Device");
324 InitializeObjectAttributes(&ObjectAttributes,
325 &DirName,
326 0,
327 NULL,
328 NULL);
329 ZwCreateDirectoryObject(&Handle,
330 0,
331 &ObjectAttributes);
332
333 /*
334 * Create the '\??' directory
335 */
336 RtlInitUnicodeString(&DirName,
337 L"\\??");
338 InitializeObjectAttributes(&ObjectAttributes,
339 &DirName,
340 0,
341 NULL,
342 NULL);
343 ZwCreateDirectoryObject(&Handle,
344 0,
345 &ObjectAttributes);
346
347 /*
348 * Create the '\ArcName' directory
349 */
350 RtlInitUnicodeString(&DirName,
351 L"\\ArcName");
352 InitializeObjectAttributes(&ObjectAttributes,
353 &DirName,
354 0,
355 NULL,
356 NULL);
357 ZwCreateDirectoryObject(&Handle,
358 0,
359 &ObjectAttributes);
360
361 /*
362 * Initialize remaining subsubsystem
363 */
364 IopInitDriverImplementation();
365 IoInitCancelHandling();
366 IoInitFileSystemImplementation();
367 IoInitVpbImplementation();
368 IoInitShutdownNotification();
369 IopInitPnpNotificationImplementation();
370 IopInitErrorLog();
371 IopInitTimerImplementation();
372 IopInitLookasideLists();
373
374 /*
375 * Create link from '\DosDevices' to '\??' directory
376 */
377 RtlInitUnicodeString(&DirName,
378 L"\\??");
379 IoCreateSymbolicLink(&LinkName,
380 &DirName);
381
382 /*
383 * Initialize PnP manager
384 */
385 PnpInit();
386 }
387
388 VOID
389 INIT_FUNCTION
390 IoInit2(BOOLEAN BootLog)
391 {
392 PDEVICE_NODE DeviceNode;
393 PDRIVER_OBJECT DriverObject;
394 LDR_DATA_TABLE_ENTRY ModuleObject;
395 NTSTATUS Status;
396
397 PnpInit2();
398
399 IoCreateDriverList();
400
401 KeInitializeSpinLock (&IoStatisticsLock);
402
403 /* Initialize raw filesystem driver */
404
405 /* Use IopRootDeviceNode for now */
406 Status = IopCreateDeviceNode(IopRootDeviceNode,
407 NULL,
408 &DeviceNode);
409 if (!NT_SUCCESS(Status))
410 {
411 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
412 return;
413 }
414
415 ModuleObject.DllBase = NULL;
416 ModuleObject.SizeOfImage = 0;
417 ModuleObject.EntryPoint = RawFsDriverEntry;
418
419 Status = IopInitializeDriverModule(
420 DeviceNode,
421 &ModuleObject,
422 &DeviceNode->ServiceName,
423 TRUE,
424 &DriverObject);
425 if (!NT_SUCCESS(Status))
426 {
427 IopFreeDeviceNode(DeviceNode);
428 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
429 return;
430 }
431
432 Status = IopInitializeDevice(DeviceNode, DriverObject);
433 if (!NT_SUCCESS(Status))
434 {
435 IopFreeDeviceNode(DeviceNode);
436 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
437 return;
438 }
439
440 Status = IopStartDevice(DeviceNode);
441 if (!NT_SUCCESS(Status))
442 {
443 IopFreeDeviceNode(DeviceNode);
444 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
445 return;
446 }
447
448 /*
449 * Initialize PnP root releations
450 */
451 IoInvalidateDeviceRelations(
452 IopRootDeviceNode->PhysicalDeviceObject,
453 BusRelations);
454
455 /* Start boot logging */
456 IopInitBootLog(BootLog);
457
458 /* Load boot start drivers */
459 IopInitializeBootDrivers();
460
461 /* Call back drivers that asked for */
462 IopReinitializeBootDrivers();
463 }
464
465 VOID
466 STDCALL
467 INIT_FUNCTION
468 IoInit3(VOID)
469 {
470 NTSTATUS Status;
471
472 /* Create ARC names for boot devices */
473 IoCreateArcNames();
474
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);
481 }
482
483 /* Read KDB Data */
484 KdbInit();
485
486 /* I/O is now setup for disk access, so phase 3 */
487 KdInitSystem(3, (PROS_LOADER_PARAMETER_BLOCK)&KeLoaderBlock);
488
489 /* Load services for devices found by PnP manager */
490 IopInitializePnpServices(IopRootDeviceNode, FALSE);
491
492 /* Load system start drivers */
493 IopInitializeSystemDrivers();
494 IoDestroyDriverList();
495
496 /* Reinitialize drivers that requested it */
497 IopReinitializeDrivers();
498
499 /* Stop boot logging */
500 IopStopBootLog();
501
502 /* Assign drive letters */
503 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
504 NULL,
505 NULL,
506 NULL);
507 }
508
509 /* EOF */