Alex Ionescu <ionucu@videotron.ca>
[reactos.git] / reactos / ntoskrnl / io / iomgr.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/iomgr.c
6 * PURPOSE: Initializes the io manager
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES ****************************************************************/
12
13 #include <ntoskrnl.h>
14 #include "../dbg/kdb.h"
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* GLOBALS *******************************************************************/
19
20 #define TAG_DEVICE_TYPE TAG('D', 'E', 'V', 'T')
21 #define TAG_FILE_TYPE TAG('F', 'I', 'L', 'E')
22 #define TAG_ADAPTER_TYPE TAG('A', 'D', 'P', 'T')
23
24 /* DATA ********************************************************************/
25
26
27 POBJECT_TYPE EXPORTED IoDeviceObjectType = NULL;
28 POBJECT_TYPE EXPORTED IoFileObjectType = NULL;
29 ULONG EXPORTED IoReadOperationCount = 0;
30 ULONGLONG EXPORTED IoReadTransferCount = 0;
31 ULONG EXPORTED IoWriteOperationCount = 0;
32 ULONGLONG EXPORTED IoWriteTransferCount = 0;
33 ULONG IoOtherOperationCount = 0;
34 ULONGLONG IoOtherTransferCount = 0;
35 KSPIN_LOCK EXPORTED IoStatisticsLock = 0;
36
37 static GENERIC_MAPPING IopFileMapping = {FILE_GENERIC_READ,
38 FILE_GENERIC_WRITE,
39 FILE_GENERIC_EXECUTE,
40 FILE_ALL_ACCESS};
41
42 /* FUNCTIONS ****************************************************************/
43
44 VOID STDCALL
45 IopCloseFile(PVOID ObjectBody,
46 ULONG HandleCount)
47 {
48 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
49 PIRP Irp;
50 PIO_STACK_LOCATION StackPtr;
51 NTSTATUS Status;
52
53 DPRINT("IopCloseFile()\n");
54
55 if (HandleCount > 0 || FileObject->DeviceObject == NULL)
56 {
57 return;
58 }
59
60 #if 0
61 //NOTE: Allmost certain that the latest changes to I/O Mgr makes this redundant (OriginalFileObject case)
62 ObReferenceObjectByPointer(FileObject,
63 STANDARD_RIGHTS_REQUIRED,
64 IoFileObjectType,
65 UserMode);
66 #endif
67
68 KeResetEvent( &FileObject->Event );
69
70 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_CLEANUP,
71 FileObject->DeviceObject,
72 NULL,
73 0,
74 NULL,
75 &FileObject->Event,
76 NULL);
77 StackPtr = IoGetNextIrpStackLocation(Irp);
78 StackPtr->FileObject = FileObject;
79
80 Status = IoCallDriver(FileObject->DeviceObject, Irp);
81 if (Status == STATUS_PENDING)
82 {
83 KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE, NULL);
84 }
85 }
86
87
88 VOID STDCALL
89 IopDeleteFile(PVOID ObjectBody)
90 {
91 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
92 PIRP Irp;
93 PIO_STACK_LOCATION StackPtr;
94 NTSTATUS Status;
95
96 DPRINT("IopDeleteFile()\n");
97
98 if (FileObject->DeviceObject)
99 {
100 #if 0
101 //NOTE: Allmost certain that the latest changes to I/O Mgr makes this redundant (OriginalFileObject case)
102
103 ObReferenceObjectByPointer(ObjectBody,
104 STANDARD_RIGHTS_REQUIRED,
105 IoFileObjectType,
106 UserMode);
107 #endif
108 KeResetEvent( &FileObject->Event );
109
110 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, TRUE);
111 if (Irp == NULL)
112 {
113 /*
114 * FIXME: This case should eventually be handled. We should wait
115 * until enough memory is available to allocate the IRP.
116 */
117 ASSERT(FALSE);
118 }
119
120 Irp->UserEvent = &FileObject->Event;
121 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
122 Irp->Flags |= IRP_CLOSE_OPERATION;
123
124 StackPtr = IoGetNextIrpStackLocation(Irp);
125 StackPtr->MajorFunction = IRP_MJ_CLOSE;
126 StackPtr->DeviceObject = FileObject->DeviceObject;
127 StackPtr->FileObject = FileObject;
128
129 Status = IoCallDriver(FileObject->DeviceObject, Irp);
130 if (Status == STATUS_PENDING)
131 {
132 KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE, NULL);
133 }
134 }
135
136 if (FileObject->FileName.Buffer != NULL)
137 {
138 ExFreePool(FileObject->FileName.Buffer);
139 FileObject->FileName.Buffer = 0;
140 }
141 }
142
143
144 static NTSTATUS
145 IopSetDefaultSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
146 PSECURITY_DESCRIPTOR SecurityDescriptor,
147 PULONG BufferLength)
148 {
149 ULONG_PTR Current;
150 ULONG SidSize;
151 ULONG SdSize;
152 NTSTATUS Status;
153
154 DPRINT("IopSetDefaultSecurityDescriptor() called\n");
155
156 if (SecurityInformation == 0)
157 {
158 return STATUS_ACCESS_DENIED;
159 }
160
161 SidSize = RtlLengthSid(SeWorldSid);
162 SdSize = sizeof(SECURITY_DESCRIPTOR) + (2 * SidSize);
163
164 if (*BufferLength < SdSize)
165 {
166 *BufferLength = SdSize;
167 return STATUS_BUFFER_TOO_SMALL;
168 }
169
170 *BufferLength = SdSize;
171
172 Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
173 SECURITY_DESCRIPTOR_REVISION);
174 if (!NT_SUCCESS(Status))
175 {
176 return Status;
177 }
178
179 SecurityDescriptor->Control |= SE_SELF_RELATIVE;
180 Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR);
181
182 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
183 {
184 RtlCopyMemory((PVOID)Current,
185 SeWorldSid,
186 SidSize);
187 SecurityDescriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
188 Current += SidSize;
189 }
190
191 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
192 {
193 RtlCopyMemory((PVOID)Current,
194 SeWorldSid,
195 SidSize);
196 SecurityDescriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
197 Current += SidSize;
198 }
199
200 if (SecurityInformation & DACL_SECURITY_INFORMATION)
201 {
202 SecurityDescriptor->Control |= SE_DACL_PRESENT;
203 }
204
205 if (SecurityInformation & SACL_SECURITY_INFORMATION)
206 {
207 SecurityDescriptor->Control |= SE_SACL_PRESENT;
208 }
209
210 return STATUS_SUCCESS;
211 }
212
213
214 NTSTATUS STDCALL
215 IopSecurityFile(PVOID ObjectBody,
216 SECURITY_OPERATION_CODE OperationCode,
217 SECURITY_INFORMATION SecurityInformation,
218 PSECURITY_DESCRIPTOR SecurityDescriptor,
219 PULONG BufferLength)
220 {
221 IO_STATUS_BLOCK IoStatusBlock;
222 PIO_STACK_LOCATION StackPtr;
223 PFILE_OBJECT FileObject;
224 PIRP Irp;
225 NTSTATUS Status;
226
227 DPRINT("IopSecurityFile() called\n");
228
229 FileObject = (PFILE_OBJECT)ObjectBody;
230
231 switch (OperationCode)
232 {
233 case SetSecurityDescriptor:
234 DPRINT("Set security descriptor\n");
235 KeResetEvent(&FileObject->Event);
236 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_SECURITY,
237 FileObject->DeviceObject,
238 NULL,
239 0,
240 NULL,
241 &FileObject->Event,
242 &IoStatusBlock);
243
244 StackPtr = IoGetNextIrpStackLocation(Irp);
245 StackPtr->FileObject = FileObject;
246
247 StackPtr->Parameters.SetSecurity.SecurityInformation = SecurityInformation;
248 StackPtr->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
249
250 Status = IoCallDriver(FileObject->DeviceObject, Irp);
251 if (Status == STATUS_PENDING)
252 {
253 KeWaitForSingleObject(&FileObject->Event,
254 Executive,
255 KernelMode,
256 FALSE,
257 NULL);
258 Status = IoStatusBlock.Status;
259 }
260
261 if (Status == STATUS_INVALID_DEVICE_REQUEST)
262 {
263 Status = STATUS_SUCCESS;
264 }
265 return Status;
266
267 case QuerySecurityDescriptor:
268 DPRINT("Query security descriptor\n");
269 KeResetEvent(&FileObject->Event);
270 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_SECURITY,
271 FileObject->DeviceObject,
272 NULL,
273 0,
274 NULL,
275 &FileObject->Event,
276 &IoStatusBlock);
277
278 Irp->UserBuffer = SecurityDescriptor;
279
280 StackPtr = IoGetNextIrpStackLocation(Irp);
281 StackPtr->FileObject = FileObject;
282
283 StackPtr->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
284 StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
285
286 Status = IoCallDriver(FileObject->DeviceObject, Irp);
287 if (Status == STATUS_PENDING)
288 {
289 KeWaitForSingleObject(&FileObject->Event,
290 Executive,
291 KernelMode,
292 FALSE,
293 NULL);
294 Status = IoStatusBlock.Status;
295 }
296
297 if (Status == STATUS_INVALID_DEVICE_REQUEST)
298 {
299 Status = IopSetDefaultSecurityDescriptor(SecurityInformation,
300 SecurityDescriptor,
301 BufferLength);
302 }
303 else
304 {
305 /* FIXME: Is this correct?? */
306 *BufferLength = IoStatusBlock.Information;
307 }
308 return Status;
309
310 case DeleteSecurityDescriptor:
311 DPRINT("Delete security descriptor\n");
312 return STATUS_SUCCESS;
313
314 case AssignSecurityDescriptor:
315 DPRINT("Assign security descriptor\n");
316 return STATUS_SUCCESS;
317 }
318
319 return STATUS_UNSUCCESSFUL;
320 }
321
322
323 NTSTATUS STDCALL
324 IopQueryNameFile(PVOID ObjectBody,
325 POBJECT_NAME_INFORMATION ObjectNameInfo,
326 ULONG Length,
327 PULONG ReturnLength)
328 {
329 POBJECT_NAME_INFORMATION LocalInfo;
330 PFILE_NAME_INFORMATION FileNameInfo;
331 PFILE_OBJECT FileObject;
332 ULONG LocalReturnLength;
333 NTSTATUS Status;
334
335 DPRINT ("IopQueryNameFile() called\n");
336
337 FileObject = (PFILE_OBJECT)ObjectBody;
338
339 LocalInfo = ExAllocatePool (NonPagedPool,
340 sizeof(OBJECT_NAME_INFORMATION) +
341 MAX_PATH * sizeof(WCHAR));
342 if (LocalInfo == NULL)
343 return STATUS_INSUFFICIENT_RESOURCES;
344
345 Status = ObQueryNameString (FileObject->DeviceObject->Vpb->RealDevice,
346 LocalInfo,
347 MAX_PATH * sizeof(WCHAR),
348 &LocalReturnLength);
349 if (!NT_SUCCESS (Status))
350 {
351 ExFreePool (LocalInfo);
352 return Status;
353 }
354 DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
355
356 Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
357 &LocalInfo->Name);
358
359 ExFreePool (LocalInfo);
360
361 FileNameInfo = ExAllocatePool (NonPagedPool,
362 MAX_PATH * sizeof(WCHAR) + sizeof(ULONG));
363 if (FileNameInfo == NULL)
364 return STATUS_INSUFFICIENT_RESOURCES;
365
366 Status = IoQueryFileInformation (FileObject,
367 FileNameInformation,
368 MAX_PATH * sizeof(WCHAR) + sizeof(ULONG),
369 FileNameInfo,
370 NULL);
371 if (Status != STATUS_SUCCESS)
372 {
373 ExFreePool (FileNameInfo);
374 return Status;
375 }
376
377 Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
378 FileNameInfo->FileName);
379
380 DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
381
382 ExFreePool (FileNameInfo);
383
384 return Status;
385 }
386
387
388 VOID INIT_FUNCTION
389 IoInit (VOID)
390 {
391 OBJECT_ATTRIBUTES ObjectAttributes;
392 UNICODE_STRING DirName;
393 UNICODE_STRING LinkName;
394 HANDLE Handle;
395
396 IopInitDriverImplementation();
397
398 /*
399 * Register iomgr types: DeviceObjectType
400 */
401 IoDeviceObjectType = ExAllocatePool (NonPagedPool,
402 sizeof (OBJECT_TYPE));
403
404 IoDeviceObjectType->Tag = TAG_DEVICE_TYPE;
405 IoDeviceObjectType->TotalObjects = 0;
406 IoDeviceObjectType->TotalHandles = 0;
407 IoDeviceObjectType->PeakObjects = 0;
408 IoDeviceObjectType->PeakHandles = 0;
409 IoDeviceObjectType->PagedPoolCharge = 0;
410 IoDeviceObjectType->NonpagedPoolCharge = sizeof (DEVICE_OBJECT);
411 IoDeviceObjectType->Mapping = &IopFileMapping;
412 IoDeviceObjectType->Dump = NULL;
413 IoDeviceObjectType->Open = NULL;
414 IoDeviceObjectType->Close = NULL;
415 IoDeviceObjectType->Delete = NULL;
416 IoDeviceObjectType->Parse = NULL;
417 IoDeviceObjectType->Security = NULL;
418 IoDeviceObjectType->QueryName = NULL;
419 IoDeviceObjectType->OkayToClose = NULL;
420 IoDeviceObjectType->Create = IopCreateDevice;
421 IoDeviceObjectType->DuplicationNotify = NULL;
422
423 RtlInitUnicodeString(&IoDeviceObjectType->TypeName, L"Device");
424
425 ObpCreateTypeObject(IoDeviceObjectType);
426
427 /*
428 * Register iomgr types: FileObjectType
429 * (alias DriverObjectType)
430 */
431 IoFileObjectType = ExAllocatePool (NonPagedPool, sizeof (OBJECT_TYPE));
432
433 IoFileObjectType->Tag = TAG_FILE_TYPE;
434 IoFileObjectType->TotalObjects = 0;
435 IoFileObjectType->TotalHandles = 0;
436 IoFileObjectType->PeakObjects = 0;
437 IoFileObjectType->PeakHandles = 0;
438 IoFileObjectType->PagedPoolCharge = 0;
439 IoFileObjectType->NonpagedPoolCharge = sizeof(FILE_OBJECT);
440 IoFileObjectType->Mapping = &IopFileMapping;
441 IoFileObjectType->Dump = NULL;
442 IoFileObjectType->Open = NULL;
443 IoFileObjectType->Close = IopCloseFile;
444 IoFileObjectType->Delete = IopDeleteFile;
445 IoFileObjectType->Parse = NULL;
446 IoFileObjectType->Security = IopSecurityFile;
447 IoFileObjectType->QueryName = IopQueryNameFile;
448 IoFileObjectType->OkayToClose = NULL;
449 IoFileObjectType->Create = IopCreateFile;
450 IoFileObjectType->DuplicationNotify = NULL;
451
452 RtlInitUnicodeString(&IoFileObjectType->TypeName, L"File");
453
454 ObpCreateTypeObject(IoFileObjectType);
455
456 /*
457 * Register iomgr types: AdapterObjectType
458 */
459 IoAdapterObjectType = ExAllocatePool (NonPagedPool,
460 sizeof (OBJECT_TYPE));
461 RtlZeroMemory(IoAdapterObjectType, sizeof(OBJECT_TYPE));
462 IoAdapterObjectType->Tag = TAG_ADAPTER_TYPE;
463 IoAdapterObjectType->PeakObjects = 0;
464 IoAdapterObjectType->PeakHandles = 0;
465 IoDeviceObjectType->Mapping = &IopFileMapping;
466 RtlInitUnicodeString(&IoAdapterObjectType->TypeName, L"Adapter");
467 ObpCreateTypeObject(IoAdapterObjectType);
468
469 /*
470 * Create the '\Driver' object directory
471 */
472 RtlRosInitUnicodeStringFromLiteral(&DirName, L"\\Driver");
473 InitializeObjectAttributes(&ObjectAttributes,
474 &DirName,
475 0,
476 NULL,
477 NULL);
478 ZwCreateDirectoryObject(&Handle,
479 0,
480 &ObjectAttributes);
481
482 /*
483 * Create the '\FileSystem' object directory
484 */
485 RtlRosInitUnicodeStringFromLiteral(&DirName,
486 L"\\FileSystem");
487 InitializeObjectAttributes(&ObjectAttributes,
488 &DirName,
489 0,
490 NULL,
491 NULL);
492 ZwCreateDirectoryObject(&Handle,
493 0,
494 &ObjectAttributes);
495
496 /*
497 * Create the '\Device' directory
498 */
499 RtlRosInitUnicodeStringFromLiteral(&DirName,
500 L"\\Device");
501 InitializeObjectAttributes(&ObjectAttributes,
502 &DirName,
503 0,
504 NULL,
505 NULL);
506 ZwCreateDirectoryObject(&Handle,
507 0,
508 &ObjectAttributes);
509
510 /*
511 * Create the '\??' directory
512 */
513 RtlRosInitUnicodeStringFromLiteral(&DirName,
514 L"\\??");
515 InitializeObjectAttributes(&ObjectAttributes,
516 &DirName,
517 0,
518 NULL,
519 NULL);
520 ZwCreateDirectoryObject(&Handle,
521 0,
522 &ObjectAttributes);
523
524 /*
525 * Create the '\ArcName' directory
526 */
527 RtlRosInitUnicodeStringFromLiteral(&DirName,
528 L"\\ArcName");
529 InitializeObjectAttributes(&ObjectAttributes,
530 &DirName,
531 0,
532 NULL,
533 NULL);
534 ZwCreateDirectoryObject(&Handle,
535 0,
536 &ObjectAttributes);
537
538 /*
539 * Initialize remaining subsubsystem
540 */
541 IoInitCancelHandling();
542 IoInitFileSystemImplementation();
543 IoInitVpbImplementation();
544 IoInitShutdownNotification();
545 IopInitErrorLog();
546 IopInitTimerImplementation();
547 IopInitIoCompletionImplementation();
548
549 /*
550 * Create link from '\DosDevices' to '\??' directory
551 */
552 RtlRosInitUnicodeStringFromLiteral(&LinkName,
553 L"\\DosDevices");
554 RtlRosInitUnicodeStringFromLiteral(&DirName,
555 L"\\??");
556 IoCreateSymbolicLink(&LinkName,
557 &DirName);
558
559 /*
560 * Initialize PnP manager
561 */
562 PnpInit();
563 }
564
565
566 VOID
567 INIT_FUNCTION
568 IoInit2(BOOLEAN BootLog)
569 {
570 PDEVICE_NODE DeviceNode;
571 PDRIVER_OBJECT DriverObject;
572 MODULE_OBJECT ModuleObject;
573 NTSTATUS Status;
574
575 IoCreateDriverList();
576
577 KeInitializeSpinLock (&IoStatisticsLock);
578
579 /* Initialize raw filesystem driver */
580
581 /* Use IopRootDeviceNode for now */
582 Status = IopCreateDeviceNode(IopRootDeviceNode,
583 NULL,
584 &DeviceNode);
585 if (!NT_SUCCESS(Status))
586 {
587 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
588 return;
589 }
590
591 ModuleObject.Base = NULL;
592 ModuleObject.Length = 0;
593 ModuleObject.EntryPoint = RawFsDriverEntry;
594
595 Status = IopInitializeDriverModule(
596 DeviceNode,
597 &ModuleObject,
598 TRUE,
599 &DriverObject);
600 if (!NT_SUCCESS(Status))
601 {
602 IopFreeDeviceNode(DeviceNode);
603 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
604 return;
605 }
606
607 Status = IopInitializeDevice(DeviceNode, DriverObject);
608 if (!NT_SUCCESS(Status))
609 {
610 IopFreeDeviceNode(DeviceNode);
611 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
612 return;
613 }
614
615 /*
616 * Initialize PnP root releations
617 */
618 IopInvalidateDeviceRelations(
619 IopRootDeviceNode,
620 BusRelations);
621
622 /* Start boot logging */
623 IopInitBootLog(BootLog);
624
625 /* Load boot start drivers */
626 IopInitializeBootDrivers();
627 }
628
629 VOID
630 STDCALL
631 INIT_FUNCTION
632 IoInit3(VOID)
633 {
634 NTSTATUS Status;
635
636 /* Create ARC names for boot devices */
637 IoCreateArcNames();
638
639 /* Create the SystemRoot symbolic link */
640 CPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
641 Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
642 if (!NT_SUCCESS(Status)) {
643 DbgPrint("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
644 DbgPrintErrorMessage (Status);
645 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
646 }
647
648 /* Start Profiling on a Debug Build */
649 #if defined(KDBG)
650 KdbInit();
651 #endif /* KDBG */
652
653 /* I/O is now setup for disk access, so start the debugging logger thread. */
654 if (KdDebugState & KD_DEBUG_FILELOG) DebugLogInit2();
655
656 /* Load services for devices found by PnP manager */
657 IopInitializePnpServices(IopRootDeviceNode, FALSE);
658
659 /* Load system start drivers */
660 IopInitializeSystemDrivers();
661 IoDestroyDriverList();
662
663 /* Stop boot logging */
664 IopStopBootLog();
665
666 /* Assign drive letters */
667 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
668 NULL,
669 NULL,
670 NULL);
671 }
672
673 /*
674 * @implemented
675 */
676 PGENERIC_MAPPING STDCALL
677 IoGetFileObjectGenericMapping(VOID)
678 {
679 return(&IopFileMapping);
680 }
681
682 /* EOF */