forget update de.rc
[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 /* DATA ********************************************************************/
17
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;
28
29 GENERIC_MAPPING IopFileMapping = {
30 FILE_GENERIC_READ,
31 FILE_GENERIC_WRITE,
32 FILE_GENERIC_EXECUTE,
33 FILE_ALL_ACCESS};
34
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;
42
43 VOID INIT_FUNCTION IopInitLookasideLists(VOID);
44
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)
52 #endif
53
54
55 /* INIT FUNCTIONS ************************************************************/
56
57 VOID
58 INIT_FUNCTION
59 IoInitCancelHandling(VOID)
60 {
61 KeInitializeSpinLock(&CancelSpinLock);
62 }
63
64 VOID
65 INIT_FUNCTION
66 IoInitShutdownNotification (VOID)
67 {
68 InitializeListHead(&ShutdownListHead);
69 KeInitializeSpinLock(&ShutdownListLock);
70 }
71
72 VOID
73 INIT_FUNCTION
74 IopInitLookasideLists(VOID)
75 {
76 ULONG LargeIrpSize, SmallIrpSize;
77 LONG i;
78 PKPRCB Prcb;
79 PNPAGED_LOOKASIDE_LIST CurrentList = NULL;
80
81 /* Calculate the sizes */
82 LargeIrpSize = sizeof(IRP) + (8 * sizeof(IO_STACK_LOCATION));
83 SmallIrpSize = sizeof(IRP) + sizeof(IO_STACK_LOCATION);
84
85 /* Initialize the Lookaside List for Large IRPs */
86 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside,
87 NULL,
88 NULL,
89 0,
90 LargeIrpSize,
91 IO_LARGEIRP,
92 0);
93
94 /* Initialize the Lookaside List for Small IRPs */
95 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside,
96 NULL,
97 NULL,
98 0,
99 SmallIrpSize,
100 IO_SMALLIRP,
101 0);
102
103 /* Initialize the Lookaside List for I\O Completion */
104 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
105 NULL,
106 NULL,
107 0,
108 sizeof(IO_COMPLETION_PACKET),
109 IOC_TAG1,
110 0);
111
112 /* Now allocate the per-processor lists */
113 for (i = 0; i < KeNumberProcessors; i++)
114 {
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);
118
119 /* Set the Large IRP List */
120 Prcb->PPLookasideList[LookasideLargeIrpList].L = &IoLargeIrpLookaside.L;
121 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
122 sizeof(NPAGED_LOOKASIDE_LIST),
123 IO_LARGEIRP_CPU);
124 if (CurrentList)
125 {
126 /* Initialize the Lookaside List for Large IRPs */
127 ExInitializeNPagedLookasideList(CurrentList,
128 NULL,
129 NULL,
130 0,
131 LargeIrpSize,
132 IO_LARGEIRP_CPU,
133 0);
134 }
135 else
136 {
137 CurrentList = &IoLargeIrpLookaside;
138 }
139 Prcb->PPLookasideList[LookasideLargeIrpList].P = &CurrentList->L;
140
141 /* Set the Small IRP List */
142 Prcb->PPLookasideList[LookasideSmallIrpList].L = &IoSmallIrpLookaside.L;
143 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
144 sizeof(NPAGED_LOOKASIDE_LIST),
145 IO_SMALLIRP_CPU);
146 if (CurrentList)
147 {
148 /* Initialize the Lookaside List for Large IRPs */
149 ExInitializeNPagedLookasideList(CurrentList,
150 NULL,
151 NULL,
152 0,
153 SmallIrpSize,
154 IO_SMALLIRP_CPU,
155 0);
156 }
157 else
158 {
159 CurrentList = &IoSmallIrpLookaside;
160 }
161 Prcb->PPLookasideList[LookasideSmallIrpList].P = &CurrentList->L;
162
163 /* Set the I/O Completion List */
164 Prcb->PPLookasideList[LookasideCompletionList].L = &IoCompletionPacketLookaside.L;
165 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
166 sizeof(NPAGED_LOOKASIDE_LIST),
167 IO_SMALLIRP_CPU);
168 if (CurrentList)
169 {
170 /* Initialize the Lookaside List for Large IRPs */
171 ExInitializeNPagedLookasideList(CurrentList,
172 NULL,
173 NULL,
174 0,
175 SmallIrpSize,
176 IOC_CPU,
177 0);
178 }
179 else
180 {
181 CurrentList = &IoCompletionPacketLookaside;
182 }
183 Prcb->PPLookasideList[LookasideCompletionList].P = &CurrentList->L;
184 }
185
186 DPRINT("Done allocation\n");
187 }
188
189 VOID
190 INIT_FUNCTION
191 IoInit (VOID)
192 {
193 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
194 UNICODE_STRING Name;
195 OBJECT_ATTRIBUTES ObjectAttributes;
196 UNICODE_STRING DirName;
197 UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\DosDevices");
198 HANDLE Handle;
199
200 IopInitDriverImplementation();
201
202 DPRINT("Creating Device Object Type\n");
203
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);
214
215 /* Do the Adapter Type */
216 RtlInitUnicodeString(&Name, L"Adapter");
217 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoAdapterObjectType);
218
219 /* Do the Controller Type */
220 RtlInitUnicodeString(&Name, L"Controller");
221 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
222 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoControllerObjectType);
223
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);
234
235 /*
236 * Create the '\Driver' object directory
237 */
238 RtlInitUnicodeString(&DirName, L"\\Driver");
239 InitializeObjectAttributes(&ObjectAttributes,
240 &DirName,
241 0,
242 NULL,
243 NULL);
244 ZwCreateDirectoryObject(&Handle,
245 0,
246 &ObjectAttributes);
247
248 /*
249 * Create the '\FileSystem' object directory
250 */
251 RtlInitUnicodeString(&DirName,
252 L"\\FileSystem");
253 InitializeObjectAttributes(&ObjectAttributes,
254 &DirName,
255 0,
256 NULL,
257 NULL);
258 ZwCreateDirectoryObject(&Handle,
259 0,
260 &ObjectAttributes);
261
262 /*
263 * Create the '\Device' directory
264 */
265 RtlInitUnicodeString(&DirName,
266 L"\\Device");
267 InitializeObjectAttributes(&ObjectAttributes,
268 &DirName,
269 0,
270 NULL,
271 NULL);
272 ZwCreateDirectoryObject(&Handle,
273 0,
274 &ObjectAttributes);
275
276 /*
277 * Create the '\??' directory
278 */
279 RtlInitUnicodeString(&DirName,
280 L"\\??");
281 InitializeObjectAttributes(&ObjectAttributes,
282 &DirName,
283 0,
284 NULL,
285 NULL);
286 ZwCreateDirectoryObject(&Handle,
287 0,
288 &ObjectAttributes);
289
290 /*
291 * Create the '\ArcName' directory
292 */
293 RtlInitUnicodeString(&DirName,
294 L"\\ArcName");
295 InitializeObjectAttributes(&ObjectAttributes,
296 &DirName,
297 0,
298 NULL,
299 NULL);
300 ZwCreateDirectoryObject(&Handle,
301 0,
302 &ObjectAttributes);
303
304 /*
305 * Initialize remaining subsubsystem
306 */
307 IoInitCancelHandling();
308 IoInitFileSystemImplementation();
309 IoInitVpbImplementation();
310 IoInitShutdownNotification();
311 IopInitPnpNotificationImplementation();
312 IopInitErrorLog();
313 IopInitTimerImplementation();
314 IopInitIoCompletionImplementation();
315 IopInitLookasideLists();
316
317 /*
318 * Create link from '\DosDevices' to '\??' directory
319 */
320 RtlInitUnicodeString(&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 LDR_DATA_TABLE_ENTRY ModuleObject;
338 NTSTATUS Status;
339
340 PnpInit2();
341
342 IoCreateDriverList();
343
344 KeInitializeSpinLock (&IoStatisticsLock);
345
346 /* Initialize raw filesystem driver */
347
348 /* Use IopRootDeviceNode for now */
349 Status = IopCreateDeviceNode(IopRootDeviceNode,
350 NULL,
351 &DeviceNode);
352 if (!NT_SUCCESS(Status))
353 {
354 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
355 return;
356 }
357
358 ModuleObject.DllBase = NULL;
359 ModuleObject.SizeOfImage = 0;
360 ModuleObject.EntryPoint = RawFsDriverEntry;
361
362 Status = IopInitializeDriverModule(
363 DeviceNode,
364 &ModuleObject,
365 &DeviceNode->ServiceName,
366 TRUE,
367 &DriverObject);
368 if (!NT_SUCCESS(Status))
369 {
370 IopFreeDeviceNode(DeviceNode);
371 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
372 return;
373 }
374
375 Status = IopInitializeDevice(DeviceNode, DriverObject);
376 if (!NT_SUCCESS(Status))
377 {
378 IopFreeDeviceNode(DeviceNode);
379 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
380 return;
381 }
382
383 Status = IopStartDevice(DeviceNode);
384 if (!NT_SUCCESS(Status))
385 {
386 IopFreeDeviceNode(DeviceNode);
387 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
388 return;
389 }
390
391 /*
392 * Initialize PnP root releations
393 */
394 IopInvalidateDeviceRelations(
395 IopRootDeviceNode,
396 BusRelations);
397
398 /* Start boot logging */
399 IopInitBootLog(BootLog);
400
401 /* Load boot start drivers */
402 IopInitializeBootDrivers();
403 }
404
405 VOID
406 STDCALL
407 INIT_FUNCTION
408 IoInit3(VOID)
409 {
410 NTSTATUS Status;
411
412 /* Create ARC names for boot devices */
413 IoCreateArcNames();
414
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);
421 }
422
423 /* Read KDB Data */
424 KdbInit();
425
426 /* I/O is now setup for disk access, so phase 3 */
427 KdInitSystem(3, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
428
429 /* Load services for devices found by PnP manager */
430 IopInitializePnpServices(IopRootDeviceNode, FALSE);
431
432 /* Load system start drivers */
433 IopInitializeSystemDrivers();
434 IoDestroyDriverList();
435
436 /* Stop boot logging */
437 IopStopBootLog();
438
439 /* Assign drive letters */
440 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
441 NULL,
442 NULL,
443 NULL);
444 }
445
446 /* FUNCTIONS *****************************************************************/
447
448 /*
449 * @implemented
450 */
451 VOID
452 STDCALL
453 IoAcquireCancelSpinLock(PKIRQL Irql)
454 {
455 KeAcquireSpinLock(&CancelSpinLock,Irql);
456 }
457
458 /*
459 * @implemented
460 */
461 PVOID
462 STDCALL
463 IoGetInitialStack(VOID)
464 {
465 return(PsGetCurrentThread()->Tcb.InitialStack);
466 }
467
468 /*
469 * @implemented
470 */
471 VOID
472 STDCALL
473 IoGetStackLimits(OUT PULONG LowLimit,
474 OUT PULONG HighLimit)
475 {
476 *LowLimit = (ULONG)NtCurrentTeb()->Tib.StackLimit;
477 *HighLimit = (ULONG)NtCurrentTeb()->Tib.StackBase;
478 }
479
480 /*
481 * @implemented
482 */
483 BOOLEAN
484 STDCALL
485 IoIsSystemThread(IN PETHREAD Thread)
486 {
487 /* Call the Ps Function */
488 return PsIsSystemThread(Thread);
489 }
490
491 /*
492 * @implemented
493 */
494 BOOLEAN STDCALL
495 IoIsWdmVersionAvailable(IN UCHAR MajorVersion,
496 IN UCHAR MinorVersion)
497 {
498 /* MinorVersion = 0x20 : WinXP
499 0x10 : Win2k
500 0x5 : WinMe
501 <0x5 : Win98
502
503 We report Win2k now
504 */
505 if (MajorVersion <= 1 && MinorVersion <= 0x10)
506 return TRUE;
507 return FALSE;
508 }
509
510 /*
511 * @implemented
512 */
513 VOID
514 STDCALL
515 IoReleaseCancelSpinLock(KIRQL Irql)
516 {
517 KeReleaseSpinLock(&CancelSpinLock,Irql);
518 }
519
520 /*
521 * @implemented
522 */
523 PEPROCESS
524 STDCALL
525 IoThreadToProcess(IN PETHREAD Thread)
526 {
527 return(Thread->ThreadsProcess);
528 }
529
530 /* EOF */