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