52a8a9d0c02077032d433de1a28efcaa50cf7373
[reactos.git] / reactos / ntoskrnl / io / 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 /* GLOBALS *******************************************************************/
17
18 #define TAG_DEVICE_TYPE TAG('D', 'E', 'V', 'T')
19 #define TAG_FILE_TYPE TAG('F', 'I', 'L', 'E')
20 #define TAG_ADAPTER_TYPE TAG('A', 'D', 'P', 'T')
21 #define IO_LARGEIRP TAG('I', 'r', 'p', 'l')
22 #define IO_SMALLIRP TAG('I', 'r', 'p', 's')
23 #define IO_LARGEIRP_CPU TAG('I', 'r', 'p', 'L')
24 #define IO_SMALLIRP_CPU TAG('I', 'r', 'p', 'S')
25 #define IOC_TAG TAG('I', 'p', 'c', ' ')
26 #define IOC_CPU TAG('I', 'p', 'c', 'P')
27
28 /* DATA ********************************************************************/
29
30 POBJECT_TYPE EXPORTED IoDeviceObjectType = NULL;
31 POBJECT_TYPE EXPORTED IoFileObjectType = NULL;
32 extern POBJECT_TYPE IoControllerObjectType;
33 ULONG EXPORTED IoReadOperationCount = 0;
34 ULONGLONG EXPORTED IoReadTransferCount = 0;
35 ULONG EXPORTED IoWriteOperationCount = 0;
36 ULONGLONG EXPORTED IoWriteTransferCount = 0;
37 ULONG IoOtherOperationCount = 0;
38 ULONGLONG IoOtherTransferCount = 0;
39 KSPIN_LOCK EXPORTED IoStatisticsLock = 0;
40
41 GENERIC_MAPPING IopFileMapping = {
42 FILE_GENERIC_READ,
43 FILE_GENERIC_WRITE,
44 FILE_GENERIC_EXECUTE,
45 FILE_ALL_ACCESS};
46
47 static KSPIN_LOCK CancelSpinLock;
48 extern LIST_ENTRY ShutdownListHead;
49 extern KSPIN_LOCK ShutdownListLock;
50 extern NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
51 NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside;
52 NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside;
53
54 /* INIT FUNCTIONS ************************************************************/
55
56 VOID
57 INIT_FUNCTION
58 IoInitCancelHandling(VOID)
59 {
60 KeInitializeSpinLock(&CancelSpinLock);
61 }
62
63 VOID
64 INIT_FUNCTION
65 IoInitShutdownNotification (VOID)
66 {
67 InitializeListHead(&ShutdownListHead);
68 KeInitializeSpinLock(&ShutdownListLock);
69 }
70
71 VOID
72 INIT_FUNCTION
73 IopInitLookasideLists(VOID)
74 {
75 ULONG LargeIrpSize, SmallIrpSize;
76 ULONG i;
77 PKPRCB Prcb;
78 PNPAGED_LOOKASIDE_LIST CurrentList = NULL;
79
80 /* Calculate the sizes */
81 LargeIrpSize = sizeof(IRP) + (8 * sizeof(IO_STACK_LOCATION));
82 SmallIrpSize = sizeof(IRP) + sizeof(IO_STACK_LOCATION);
83
84 /* Initialize the Lookaside List for Large IRPs */
85 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside,
86 NULL,
87 NULL,
88 0,
89 LargeIrpSize,
90 IO_LARGEIRP,
91 0);
92
93 /* Initialize the Lookaside List for Small IRPs */
94 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside,
95 NULL,
96 NULL,
97 0,
98 SmallIrpSize,
99 IO_SMALLIRP,
100 0);
101
102 /* Initialize the Lookaside List for I\O Completion */
103 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
104 NULL,
105 NULL,
106 0,
107 sizeof(IO_COMPLETION_PACKET),
108 IOC_TAG,
109 0);
110
111 /* Now allocate the per-processor lists */
112 for (i = 0; i < KeNumberProcessors; i++)
113 {
114 /* Get the PRCB for this CPU */
115 Prcb = ((PKPCR)(KPCR_BASE + i * PAGE_SIZE))->Prcb;
116 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i, Prcb);
117
118 /* Set the Large IRP List */
119 Prcb->PPLookasideList[LookasideLargeIrpList].L = &IoLargeIrpLookaside.L;
120 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
121 sizeof(NPAGED_LOOKASIDE_LIST),
122 IO_LARGEIRP_CPU);
123 if (CurrentList)
124 {
125 /* Initialize the Lookaside List for Large IRPs */
126 ExInitializeNPagedLookasideList(CurrentList,
127 NULL,
128 NULL,
129 0,
130 LargeIrpSize,
131 IO_LARGEIRP_CPU,
132 0);
133 }
134 else
135 {
136 CurrentList = &IoLargeIrpLookaside;
137 }
138 Prcb->PPLookasideList[LookasideLargeIrpList].P = &CurrentList->L;
139
140 /* Set the Small IRP List */
141 Prcb->PPLookasideList[LookasideSmallIrpList].L = &IoSmallIrpLookaside.L;
142 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
143 sizeof(NPAGED_LOOKASIDE_LIST),
144 IO_SMALLIRP_CPU);
145 if (CurrentList)
146 {
147 /* Initialize the Lookaside List for Large IRPs */
148 ExInitializeNPagedLookasideList(CurrentList,
149 NULL,
150 NULL,
151 0,
152 SmallIrpSize,
153 IO_SMALLIRP_CPU,
154 0);
155 }
156 else
157 {
158 CurrentList = &IoSmallIrpLookaside;
159 }
160 Prcb->PPLookasideList[LookasideSmallIrpList].P = &CurrentList->L;
161
162 /* Set the I/O Completion List */
163 Prcb->PPLookasideList[LookasideCompletionList].L = &IoCompletionPacketLookaside.L;
164 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
165 sizeof(NPAGED_LOOKASIDE_LIST),
166 IO_SMALLIRP_CPU);
167 if (CurrentList)
168 {
169 /* Initialize the Lookaside List for Large IRPs */
170 ExInitializeNPagedLookasideList(CurrentList,
171 NULL,
172 NULL,
173 0,
174 SmallIrpSize,
175 IOC_CPU,
176 0);
177 }
178 else
179 {
180 CurrentList = &IoCompletionPacketLookaside;
181 }
182 Prcb->PPLookasideList[LookasideCompletionList].P = &CurrentList->L;
183 }
184
185 DPRINT("Done allocation\n");
186 }
187
188 VOID
189 INIT_FUNCTION
190 IoInit (VOID)
191 {
192 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
193 UNICODE_STRING Name;
194 OBJECT_ATTRIBUTES ObjectAttributes;
195 UNICODE_STRING DirName;
196 UNICODE_STRING LinkName;
197 HANDLE Handle;
198
199 IopInitDriverImplementation();
200
201 DPRINT1("Creating Device Object Type\n");
202
203 /* Initialize the Driver object type */
204 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
205 RtlInitUnicodeString(&Name, L"Device");
206 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
207 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEVICE_OBJECT);
208 ObjectTypeInitializer.PoolType = NonPagedPool;
209 ObjectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
210 ObjectTypeInitializer.UseDefaultObject = TRUE;
211 ObjectTypeInitializer.GenericMapping = IopFileMapping;
212 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoDeviceObjectType);
213
214 /* Do the Adapter Type */
215 RtlInitUnicodeString(&Name, L"Adapter");
216 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoAdapterObjectType);
217
218 /* Do the Controller Type */
219 RtlInitUnicodeString(&Name, L"Controller");
220 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
221 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoControllerObjectType);
222
223 /* Initialize the File object type */
224 RtlInitUnicodeString(&Name, L"File");
225 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
226 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(FILE_OBJECT);
227 ObjectTypeInitializer.CloseProcedure = IopCloseFile;
228 ObjectTypeInitializer.DeleteProcedure = IopDeleteFile;
229 ObjectTypeInitializer.SecurityProcedure = IopSecurityFile;
230 ObjectTypeInitializer.QueryNameProcedure = IopQueryNameFile;
231 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoFileObjectType);
232
233 /*
234 * Create the '\Driver' object directory
235 */
236 RtlRosInitUnicodeStringFromLiteral(&DirName, L"\\Driver");
237 InitializeObjectAttributes(&ObjectAttributes,
238 &DirName,
239 0,
240 NULL,
241 NULL);
242 ZwCreateDirectoryObject(&Handle,
243 0,
244 &ObjectAttributes);
245
246 /*
247 * Create the '\FileSystem' object directory
248 */
249 RtlRosInitUnicodeStringFromLiteral(&DirName,
250 L"\\FileSystem");
251 InitializeObjectAttributes(&ObjectAttributes,
252 &DirName,
253 0,
254 NULL,
255 NULL);
256 ZwCreateDirectoryObject(&Handle,
257 0,
258 &ObjectAttributes);
259
260 /*
261 * Create the '\Device' directory
262 */
263 RtlRosInitUnicodeStringFromLiteral(&DirName,
264 L"\\Device");
265 InitializeObjectAttributes(&ObjectAttributes,
266 &DirName,
267 0,
268 NULL,
269 NULL);
270 ZwCreateDirectoryObject(&Handle,
271 0,
272 &ObjectAttributes);
273
274 /*
275 * Create the '\??' directory
276 */
277 RtlRosInitUnicodeStringFromLiteral(&DirName,
278 L"\\??");
279 InitializeObjectAttributes(&ObjectAttributes,
280 &DirName,
281 0,
282 NULL,
283 NULL);
284 ZwCreateDirectoryObject(&Handle,
285 0,
286 &ObjectAttributes);
287
288 /*
289 * Create the '\ArcName' directory
290 */
291 RtlRosInitUnicodeStringFromLiteral(&DirName,
292 L"\\ArcName");
293 InitializeObjectAttributes(&ObjectAttributes,
294 &DirName,
295 0,
296 NULL,
297 NULL);
298 ZwCreateDirectoryObject(&Handle,
299 0,
300 &ObjectAttributes);
301
302 /*
303 * Initialize remaining subsubsystem
304 */
305 IoInitCancelHandling();
306 IoInitFileSystemImplementation();
307 IoInitVpbImplementation();
308 IoInitShutdownNotification();
309 IopInitPnpNotificationImplementation();
310 IopInitErrorLog();
311 IopInitTimerImplementation();
312 IopInitIoCompletionImplementation();
313 IopInitLookasideLists();
314
315 /*
316 * Create link from '\DosDevices' to '\??' directory
317 */
318 RtlRosInitUnicodeStringFromLiteral(&LinkName,
319 L"\\DosDevices");
320 RtlRosInitUnicodeStringFromLiteral(&DirName,
321 L"\\??");
322 IoCreateSymbolicLink(&LinkName,
323 &DirName);
324
325 /*
326 * Initialize PnP manager
327 */
328 PnpInit();
329 }
330
331 VOID
332 INIT_FUNCTION
333 IoInit2(BOOLEAN BootLog)
334 {
335 PDEVICE_NODE DeviceNode;
336 PDRIVER_OBJECT DriverObject;
337 MODULE_OBJECT ModuleObject;
338 NTSTATUS Status;
339
340 IoCreateDriverList();
341
342 KeInitializeSpinLock (&IoStatisticsLock);
343
344 /* Initialize raw filesystem driver */
345
346 /* Use IopRootDeviceNode for now */
347 Status = IopCreateDeviceNode(IopRootDeviceNode,
348 NULL,
349 &DeviceNode);
350 if (!NT_SUCCESS(Status))
351 {
352 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
353 return;
354 }
355
356 ModuleObject.Base = NULL;
357 ModuleObject.Length = 0;
358 ModuleObject.EntryPoint = RawFsDriverEntry;
359
360 Status = IopInitializeDriverModule(
361 DeviceNode,
362 &ModuleObject,
363 &DeviceNode->ServiceName,
364 TRUE,
365 &DriverObject);
366 if (!NT_SUCCESS(Status))
367 {
368 IopFreeDeviceNode(DeviceNode);
369 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
370 return;
371 }
372
373 Status = IopInitializeDevice(DeviceNode, DriverObject);
374 if (!NT_SUCCESS(Status))
375 {
376 IopFreeDeviceNode(DeviceNode);
377 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
378 return;
379 }
380
381 Status = IopStartDevice(DeviceNode);
382 if (!NT_SUCCESS(Status))
383 {
384 IopFreeDeviceNode(DeviceNode);
385 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
386 return;
387 }
388
389 /*
390 * Initialize PnP root releations
391 */
392 IopInvalidateDeviceRelations(
393 IopRootDeviceNode,
394 BusRelations);
395
396 /* Start boot logging */
397 IopInitBootLog(BootLog);
398
399 /* Load boot start drivers */
400 IopInitializeBootDrivers();
401 }
402
403 VOID
404 STDCALL
405 INIT_FUNCTION
406 IoInit3(VOID)
407 {
408 NTSTATUS Status;
409
410 /* Create ARC names for boot devices */
411 IoCreateArcNames();
412
413 /* Create the SystemRoot symbolic link */
414 DPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
415 Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
416 if (!NT_SUCCESS(Status)) {
417 CPRINT("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
418 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
419 }
420
421 /* Read KDB Data */
422 KdbInit();
423
424 /* I/O is now setup for disk access, so phase 3 */
425 KdInitSystem(3, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
426
427 /* Load services for devices found by PnP manager */
428 IopInitializePnpServices(IopRootDeviceNode, FALSE);
429
430 /* Load system start drivers */
431 IopInitializeSystemDrivers();
432 IoDestroyDriverList();
433
434 /* Stop boot logging */
435 IopStopBootLog();
436
437 /* Assign drive letters */
438 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
439 NULL,
440 NULL,
441 NULL);
442 }
443
444 /* FUNCTIONS *****************************************************************/
445
446 /*
447 * @implemented
448 */
449 VOID
450 STDCALL
451 IoAcquireCancelSpinLock(PKIRQL Irql)
452 {
453 KeAcquireSpinLock(&CancelSpinLock,Irql);
454 }
455
456 /*
457 * @implemented
458 */
459 PVOID
460 STDCALL
461 IoGetInitialStack(VOID)
462 {
463 return(PsGetCurrentThread()->Tcb.InitialStack);
464 }
465
466 /*
467 * @implemented
468 */
469 VOID
470 STDCALL
471 IoGetStackLimits(OUT PULONG LowLimit,
472 OUT PULONG HighLimit)
473 {
474 *LowLimit = (ULONG)NtCurrentTeb()->Tib.StackLimit;
475 *HighLimit = (ULONG)NtCurrentTeb()->Tib.StackBase;
476 }
477
478 /*
479 * @implemented
480 */
481 BOOLEAN
482 STDCALL
483 IoIsSystemThread(IN PETHREAD Thread)
484 {
485 /* Call the Ps Function */
486 return PsIsSystemThread(Thread);
487 }
488
489 /*
490 * @implemented
491 */
492 BOOLEAN STDCALL
493 IoIsWdmVersionAvailable(IN UCHAR MajorVersion,
494 IN UCHAR MinorVersion)
495 {
496 if (MajorVersion <= 1 && MinorVersion <= 10)
497 return TRUE;
498 return FALSE;
499 }
500
501 /*
502 * @implemented
503 */
504 VOID
505 STDCALL
506 IoReleaseCancelSpinLock(KIRQL Irql)
507 {
508 KeReleaseSpinLock(&CancelSpinLock,Irql);
509 }
510
511 /*
512 * @implemented
513 */
514 PEPROCESS
515 STDCALL
516 IoThreadToProcess(IN PETHREAD Thread)
517 {
518 return(Thread->ThreadsProcess);
519 }
520
521 /* EOF */