1e2849be1c6d905c9e220b3dfa5dc325d5342efe
[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
22 /* DATA ********************************************************************/
23
24 POBJECT_TYPE EXPORTED IoDeviceObjectType = NULL;
25 POBJECT_TYPE EXPORTED IoFileObjectType = NULL;
26 ULONG EXPORTED IoReadOperationCount = 0;
27 ULONGLONG EXPORTED IoReadTransferCount = 0;
28 ULONG EXPORTED IoWriteOperationCount = 0;
29 ULONGLONG EXPORTED IoWriteTransferCount = 0;
30 ULONG IoOtherOperationCount = 0;
31 ULONGLONG IoOtherTransferCount = 0;
32 KSPIN_LOCK EXPORTED IoStatisticsLock = 0;
33
34 GENERIC_MAPPING IopFileMapping = {
35 FILE_GENERIC_READ,
36 FILE_GENERIC_WRITE,
37 FILE_GENERIC_EXECUTE,
38 FILE_ALL_ACCESS};
39
40 static KSPIN_LOCK CancelSpinLock;
41 extern LIST_ENTRY ShutdownListHead;
42 extern KSPIN_LOCK ShutdownListLock;
43
44 /* INIT FUNCTIONS ************************************************************/
45
46 VOID
47 INIT_FUNCTION
48 IoInitCancelHandling(VOID)
49 {
50 KeInitializeSpinLock(&CancelSpinLock);
51 }
52
53 VOID
54 INIT_FUNCTION
55 IoInitShutdownNotification (VOID)
56 {
57 InitializeListHead(&ShutdownListHead);
58 KeInitializeSpinLock(&ShutdownListLock);
59 }
60
61 VOID
62 INIT_FUNCTION
63 IoInit (VOID)
64 {
65 OBJECT_ATTRIBUTES ObjectAttributes;
66 UNICODE_STRING DirName;
67 UNICODE_STRING LinkName;
68 HANDLE Handle;
69
70 IopInitDriverImplementation();
71
72 /*
73 * Register iomgr types: DeviceObjectType
74 */
75 IoDeviceObjectType = ExAllocatePool (NonPagedPool,
76 sizeof (OBJECT_TYPE));
77
78 IoDeviceObjectType->Tag = TAG_DEVICE_TYPE;
79 IoDeviceObjectType->TotalObjects = 0;
80 IoDeviceObjectType->TotalHandles = 0;
81 IoDeviceObjectType->PeakObjects = 0;
82 IoDeviceObjectType->PeakHandles = 0;
83 IoDeviceObjectType->PagedPoolCharge = 0;
84 IoDeviceObjectType->NonpagedPoolCharge = sizeof (DEVICE_OBJECT);
85 IoDeviceObjectType->Mapping = &IopFileMapping;
86 IoDeviceObjectType->Dump = NULL;
87 IoDeviceObjectType->Open = NULL;
88 IoDeviceObjectType->Close = NULL;
89 IoDeviceObjectType->Delete = NULL;
90 IoDeviceObjectType->Parse = NULL;
91 IoDeviceObjectType->Security = NULL;
92 IoDeviceObjectType->QueryName = NULL;
93 IoDeviceObjectType->OkayToClose = NULL;
94 IoDeviceObjectType->Create = NULL;
95 IoDeviceObjectType->DuplicationNotify = NULL;
96
97 RtlInitUnicodeString(&IoDeviceObjectType->TypeName, L"Device");
98
99 ObpCreateTypeObject(IoDeviceObjectType);
100
101 /*
102 * Register iomgr types: FileObjectType
103 * (alias DriverObjectType)
104 */
105 IoFileObjectType = ExAllocatePool (NonPagedPool, sizeof (OBJECT_TYPE));
106
107 IoFileObjectType->Tag = TAG_FILE_TYPE;
108 IoFileObjectType->TotalObjects = 0;
109 IoFileObjectType->TotalHandles = 0;
110 IoFileObjectType->PeakObjects = 0;
111 IoFileObjectType->PeakHandles = 0;
112 IoFileObjectType->PagedPoolCharge = 0;
113 IoFileObjectType->NonpagedPoolCharge = sizeof(FILE_OBJECT);
114 IoFileObjectType->Mapping = &IopFileMapping;
115 IoFileObjectType->Dump = NULL;
116 IoFileObjectType->Open = NULL;
117 IoFileObjectType->Close = IopCloseFile;
118 IoFileObjectType->Delete = IopDeleteFile;
119 IoFileObjectType->Parse = NULL;
120 IoFileObjectType->Security = IopSecurityFile;
121 IoFileObjectType->QueryName = IopQueryNameFile;
122 IoFileObjectType->OkayToClose = NULL;
123 IoFileObjectType->Create = IopCreateFile;
124 IoFileObjectType->DuplicationNotify = NULL;
125
126 RtlInitUnicodeString(&IoFileObjectType->TypeName, L"File");
127
128 ObpCreateTypeObject(IoFileObjectType);
129
130 /*
131 * Register iomgr types: AdapterObjectType
132 */
133 IoAdapterObjectType = ExAllocatePool (NonPagedPool,
134 sizeof (OBJECT_TYPE));
135 RtlZeroMemory(IoAdapterObjectType, sizeof(OBJECT_TYPE));
136 IoAdapterObjectType->Tag = TAG_ADAPTER_TYPE;
137 IoAdapterObjectType->PeakObjects = 0;
138 IoAdapterObjectType->PeakHandles = 0;
139 IoDeviceObjectType->Mapping = &IopFileMapping;
140 RtlInitUnicodeString(&IoAdapterObjectType->TypeName, L"Adapter");
141 ObpCreateTypeObject(IoAdapterObjectType);
142
143 /*
144 * Create the '\Driver' object directory
145 */
146 RtlRosInitUnicodeStringFromLiteral(&DirName, L"\\Driver");
147 InitializeObjectAttributes(&ObjectAttributes,
148 &DirName,
149 0,
150 NULL,
151 NULL);
152 ZwCreateDirectoryObject(&Handle,
153 0,
154 &ObjectAttributes);
155
156 /*
157 * Create the '\FileSystem' object directory
158 */
159 RtlRosInitUnicodeStringFromLiteral(&DirName,
160 L"\\FileSystem");
161 InitializeObjectAttributes(&ObjectAttributes,
162 &DirName,
163 0,
164 NULL,
165 NULL);
166 ZwCreateDirectoryObject(&Handle,
167 0,
168 &ObjectAttributes);
169
170 /*
171 * Create the '\Device' directory
172 */
173 RtlRosInitUnicodeStringFromLiteral(&DirName,
174 L"\\Device");
175 InitializeObjectAttributes(&ObjectAttributes,
176 &DirName,
177 0,
178 NULL,
179 NULL);
180 ZwCreateDirectoryObject(&Handle,
181 0,
182 &ObjectAttributes);
183
184 /*
185 * Create the '\??' directory
186 */
187 RtlRosInitUnicodeStringFromLiteral(&DirName,
188 L"\\??");
189 InitializeObjectAttributes(&ObjectAttributes,
190 &DirName,
191 0,
192 NULL,
193 NULL);
194 ZwCreateDirectoryObject(&Handle,
195 0,
196 &ObjectAttributes);
197
198 /*
199 * Create the '\ArcName' directory
200 */
201 RtlRosInitUnicodeStringFromLiteral(&DirName,
202 L"\\ArcName");
203 InitializeObjectAttributes(&ObjectAttributes,
204 &DirName,
205 0,
206 NULL,
207 NULL);
208 ZwCreateDirectoryObject(&Handle,
209 0,
210 &ObjectAttributes);
211
212 /*
213 * Initialize remaining subsubsystem
214 */
215 IoInitCancelHandling();
216 IoInitFileSystemImplementation();
217 IoInitVpbImplementation();
218 IoInitShutdownNotification();
219 IopInitPnpNotificationImplementation();
220 IopInitErrorLog();
221 IopInitTimerImplementation();
222 IopInitIoCompletionImplementation();
223
224 /*
225 * Create link from '\DosDevices' to '\??' directory
226 */
227 RtlRosInitUnicodeStringFromLiteral(&LinkName,
228 L"\\DosDevices");
229 RtlRosInitUnicodeStringFromLiteral(&DirName,
230 L"\\??");
231 IoCreateSymbolicLink(&LinkName,
232 &DirName);
233
234 /*
235 * Initialize PnP manager
236 */
237 PnpInit();
238 }
239
240 VOID
241 INIT_FUNCTION
242 IoInit2(BOOLEAN BootLog)
243 {
244 PDEVICE_NODE DeviceNode;
245 PDRIVER_OBJECT DriverObject;
246 MODULE_OBJECT ModuleObject;
247 NTSTATUS Status;
248
249 IoCreateDriverList();
250
251 KeInitializeSpinLock (&IoStatisticsLock);
252
253 /* Initialize raw filesystem driver */
254
255 /* Use IopRootDeviceNode for now */
256 Status = IopCreateDeviceNode(IopRootDeviceNode,
257 NULL,
258 &DeviceNode);
259 if (!NT_SUCCESS(Status))
260 {
261 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
262 return;
263 }
264
265 ModuleObject.Base = NULL;
266 ModuleObject.Length = 0;
267 ModuleObject.EntryPoint = RawFsDriverEntry;
268
269 Status = IopInitializeDriverModule(
270 DeviceNode,
271 &ModuleObject,
272 &DeviceNode->ServiceName,
273 TRUE,
274 &DriverObject);
275 if (!NT_SUCCESS(Status))
276 {
277 IopFreeDeviceNode(DeviceNode);
278 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
279 return;
280 }
281
282 Status = IopInitializeDevice(DeviceNode, DriverObject);
283 if (!NT_SUCCESS(Status))
284 {
285 IopFreeDeviceNode(DeviceNode);
286 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
287 return;
288 }
289
290 /*
291 * Initialize PnP root releations
292 */
293 IopInvalidateDeviceRelations(
294 IopRootDeviceNode,
295 BusRelations);
296
297 /* Start boot logging */
298 IopInitBootLog(BootLog);
299
300 /* Load boot start drivers */
301 IopInitializeBootDrivers();
302 }
303
304 VOID
305 STDCALL
306 INIT_FUNCTION
307 IoInit3(VOID)
308 {
309 NTSTATUS Status;
310
311 /* Create ARC names for boot devices */
312 IoCreateArcNames();
313
314 /* Create the SystemRoot symbolic link */
315 CPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
316 Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
317 if (!NT_SUCCESS(Status)) {
318 DbgPrint("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
319 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
320 }
321
322 /* Read KDB Data */
323 KdbInit();
324
325 /* I/O is now setup for disk access, so phase 3 */
326 KdInitSystem(3, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
327
328 /* Load services for devices found by PnP manager */
329 IopInitializePnpServices(IopRootDeviceNode, FALSE);
330
331 /* Load system start drivers */
332 IopInitializeSystemDrivers();
333 IoDestroyDriverList();
334
335 /* Stop boot logging */
336 IopStopBootLog();
337
338 /* Assign drive letters */
339 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
340 NULL,
341 NULL,
342 NULL);
343 }
344
345 /* FUNCTIONS *****************************************************************/
346
347 /*
348 * @implemented
349 */
350 VOID
351 STDCALL
352 IoAcquireCancelSpinLock(PKIRQL Irql)
353 {
354 KeAcquireSpinLock(&CancelSpinLock,Irql);
355 }
356
357 /*
358 * @implemented
359 */
360 PVOID
361 STDCALL
362 IoGetInitialStack(VOID)
363 {
364 return(PsGetCurrentThread()->Tcb.InitialStack);
365 }
366
367 /*
368 * @implemented
369 */
370 VOID
371 STDCALL
372 IoGetStackLimits(OUT PULONG LowLimit,
373 OUT PULONG HighLimit)
374 {
375 *LowLimit = (ULONG)NtCurrentTeb()->Tib.StackLimit;
376 *HighLimit = (ULONG)NtCurrentTeb()->Tib.StackBase;
377 }
378
379 /*
380 * @implemented
381 */
382 BOOLEAN
383 STDCALL
384 IoIsSystemThread(IN PETHREAD Thread)
385 {
386 /* Call the Ps Function */
387 return PsIsSystemThread(Thread);
388 }
389
390 /*
391 * @implemented
392 */
393 BOOLEAN STDCALL
394 IoIsWdmVersionAvailable(IN UCHAR MajorVersion,
395 IN UCHAR MinorVersion)
396 {
397 if (MajorVersion <= 1 && MinorVersion <= 10)
398 return TRUE;
399 return FALSE;
400 }
401
402 /*
403 * @implemented
404 */
405 VOID
406 STDCALL
407 IoReleaseCancelSpinLock(KIRQL Irql)
408 {
409 KeReleaseSpinLock(&CancelSpinLock,Irql);
410 }
411
412 /*
413 * @implemented
414 */
415 PEPROCESS
416 STDCALL
417 IoThreadToProcess(IN PETHREAD Thread)
418 {
419 return(Thread->ThreadsProcess);
420 }
421
422 /* EOF */