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