-move structs OBJECT_TYPE/OBJECT_HEADER into private headers
[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 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * REVISION HISTORY:
9 * 29/07/98: Created
10 */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <ntoskrnl.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 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_CLOSE,
110 FileObject->DeviceObject,
111 NULL,
112 0,
113 NULL,
114 &FileObject->Event,
115 NULL);
116 Irp->Flags |= IRP_CLOSE_OPERATION;
117 StackPtr = IoGetNextIrpStackLocation(Irp);
118 StackPtr->FileObject = FileObject;
119
120 Status = IoCallDriver(FileObject->DeviceObject, Irp);
121 if (Status == STATUS_PENDING)
122 {
123 KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE, NULL);
124 }
125 }
126
127 if (FileObject->FileName.Buffer != NULL)
128 {
129 ExFreePool(FileObject->FileName.Buffer);
130 FileObject->FileName.Buffer = 0;
131 }
132 }
133
134
135 static NTSTATUS
136 IopSetDefaultSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
137 PSECURITY_DESCRIPTOR SecurityDescriptor,
138 PULONG BufferLength)
139 {
140 ULONG_PTR Current;
141 ULONG SidSize;
142 ULONG SdSize;
143 NTSTATUS Status;
144
145 DPRINT("IopSetDefaultSecurityDescriptor() called\n");
146
147 if (SecurityInformation == 0)
148 {
149 return STATUS_ACCESS_DENIED;
150 }
151
152 SidSize = RtlLengthSid(SeWorldSid);
153 SdSize = sizeof(SECURITY_DESCRIPTOR) + (2 * SidSize);
154
155 if (*BufferLength < SdSize)
156 {
157 *BufferLength = SdSize;
158 return STATUS_BUFFER_TOO_SMALL;
159 }
160
161 *BufferLength = SdSize;
162
163 Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
164 SECURITY_DESCRIPTOR_REVISION);
165 if (!NT_SUCCESS(Status))
166 {
167 return Status;
168 }
169
170 SecurityDescriptor->Control |= SE_SELF_RELATIVE;
171 Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR);
172
173 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
174 {
175 RtlCopyMemory((PVOID)Current,
176 SeWorldSid,
177 SidSize);
178 SecurityDescriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
179 Current += SidSize;
180 }
181
182 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
183 {
184 RtlCopyMemory((PVOID)Current,
185 SeWorldSid,
186 SidSize);
187 SecurityDescriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
188 Current += SidSize;
189 }
190
191 if (SecurityInformation & DACL_SECURITY_INFORMATION)
192 {
193 SecurityDescriptor->Control |= SE_DACL_PRESENT;
194 }
195
196 if (SecurityInformation & SACL_SECURITY_INFORMATION)
197 {
198 SecurityDescriptor->Control |= SE_SACL_PRESENT;
199 }
200
201 return STATUS_SUCCESS;
202 }
203
204
205 NTSTATUS STDCALL
206 IopSecurityFile(PVOID ObjectBody,
207 SECURITY_OPERATION_CODE OperationCode,
208 SECURITY_INFORMATION SecurityInformation,
209 PSECURITY_DESCRIPTOR SecurityDescriptor,
210 PULONG BufferLength)
211 {
212 IO_STATUS_BLOCK IoStatusBlock;
213 PIO_STACK_LOCATION StackPtr;
214 PFILE_OBJECT FileObject;
215 PIRP Irp;
216 NTSTATUS Status;
217
218 DPRINT("IopSecurityFile() called\n");
219
220 FileObject = (PFILE_OBJECT)ObjectBody;
221
222 switch (OperationCode)
223 {
224 case SetSecurityDescriptor:
225 DPRINT("Set security descriptor\n");
226 KeResetEvent(&FileObject->Event);
227 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_SECURITY,
228 FileObject->DeviceObject,
229 NULL,
230 0,
231 NULL,
232 &FileObject->Event,
233 &IoStatusBlock);
234
235 StackPtr = IoGetNextIrpStackLocation(Irp);
236 StackPtr->FileObject = FileObject;
237
238 StackPtr->Parameters.SetSecurity.SecurityInformation = SecurityInformation;
239 StackPtr->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
240
241 Status = IoCallDriver(FileObject->DeviceObject, Irp);
242 if (Status == STATUS_PENDING)
243 {
244 KeWaitForSingleObject(&FileObject->Event,
245 Executive,
246 KernelMode,
247 FALSE,
248 NULL);
249 Status = IoStatusBlock.Status;
250 }
251
252 if (Status == STATUS_INVALID_DEVICE_REQUEST)
253 {
254 Status = STATUS_SUCCESS;
255 }
256 return Status;
257
258 case QuerySecurityDescriptor:
259 DPRINT("Query security descriptor\n");
260 KeResetEvent(&FileObject->Event);
261 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_SECURITY,
262 FileObject->DeviceObject,
263 NULL,
264 0,
265 NULL,
266 &FileObject->Event,
267 &IoStatusBlock);
268
269 Irp->UserBuffer = SecurityDescriptor;
270
271 StackPtr = IoGetNextIrpStackLocation(Irp);
272 StackPtr->FileObject = FileObject;
273
274 StackPtr->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
275 StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
276
277 Status = IoCallDriver(FileObject->DeviceObject, Irp);
278 if (Status == STATUS_PENDING)
279 {
280 KeWaitForSingleObject(&FileObject->Event,
281 Executive,
282 KernelMode,
283 FALSE,
284 NULL);
285 Status = IoStatusBlock.Status;
286 }
287
288 if (Status == STATUS_INVALID_DEVICE_REQUEST)
289 {
290 Status = IopSetDefaultSecurityDescriptor(SecurityInformation,
291 SecurityDescriptor,
292 BufferLength);
293 }
294 else
295 {
296 /* FIXME: Is this correct?? */
297 *BufferLength = IoStatusBlock.Information;
298 }
299 return Status;
300
301 case DeleteSecurityDescriptor:
302 DPRINT("Delete security descriptor\n");
303 return STATUS_SUCCESS;
304
305 case AssignSecurityDescriptor:
306 DPRINT("Assign security descriptor\n");
307 return STATUS_SUCCESS;
308 }
309
310 return STATUS_UNSUCCESSFUL;
311 }
312
313
314 NTSTATUS STDCALL
315 IopQueryNameFile(PVOID ObjectBody,
316 POBJECT_NAME_INFORMATION ObjectNameInfo,
317 ULONG Length,
318 PULONG ReturnLength)
319 {
320 POBJECT_NAME_INFORMATION LocalInfo;
321 PFILE_NAME_INFORMATION FileNameInfo;
322 PFILE_OBJECT FileObject;
323 ULONG LocalReturnLength;
324 NTSTATUS Status;
325
326 DPRINT ("IopQueryNameFile() called\n");
327
328 FileObject = (PFILE_OBJECT)ObjectBody;
329
330 LocalInfo = ExAllocatePool (NonPagedPool,
331 sizeof(OBJECT_NAME_INFORMATION) +
332 MAX_PATH * sizeof(WCHAR));
333 if (LocalInfo == NULL)
334 return STATUS_INSUFFICIENT_RESOURCES;
335
336 Status = ObQueryNameString (FileObject->DeviceObject->Vpb->RealDevice,
337 LocalInfo,
338 MAX_PATH * sizeof(WCHAR),
339 &LocalReturnLength);
340 if (!NT_SUCCESS (Status))
341 {
342 ExFreePool (LocalInfo);
343 return Status;
344 }
345 DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
346
347 Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
348 &LocalInfo->Name);
349
350 ExFreePool (LocalInfo);
351
352 FileNameInfo = ExAllocatePool (NonPagedPool,
353 MAX_PATH * sizeof(WCHAR) + sizeof(ULONG));
354 if (FileNameInfo == NULL)
355 return STATUS_INSUFFICIENT_RESOURCES;
356
357 Status = IoQueryFileInformation (FileObject,
358 FileNameInformation,
359 MAX_PATH * sizeof(WCHAR) + sizeof(ULONG),
360 FileNameInfo,
361 NULL);
362 if (Status != STATUS_SUCCESS)
363 {
364 ExFreePool (FileNameInfo);
365 return Status;
366 }
367
368 Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
369 FileNameInfo->FileName);
370
371 DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
372
373 ExFreePool (FileNameInfo);
374
375 return Status;
376 }
377
378
379 VOID INIT_FUNCTION
380 IoInit (VOID)
381 {
382 OBJECT_ATTRIBUTES ObjectAttributes;
383 UNICODE_STRING DirName;
384 UNICODE_STRING LinkName;
385 HANDLE Handle;
386
387 IopInitDriverImplementation();
388
389 /*
390 * Register iomgr types: DeviceObjectType
391 */
392 IoDeviceObjectType = ExAllocatePool (NonPagedPool,
393 sizeof (OBJECT_TYPE));
394
395 IoDeviceObjectType->Tag = TAG_DEVICE_TYPE;
396 IoDeviceObjectType->TotalObjects = 0;
397 IoDeviceObjectType->TotalHandles = 0;
398 IoDeviceObjectType->PeakObjects = 0;
399 IoDeviceObjectType->PeakHandles = 0;
400 IoDeviceObjectType->PagedPoolCharge = 0;
401 IoDeviceObjectType->NonpagedPoolCharge = sizeof (DEVICE_OBJECT);
402 IoDeviceObjectType->Mapping = &IopFileMapping;
403 IoDeviceObjectType->Dump = NULL;
404 IoDeviceObjectType->Open = NULL;
405 IoDeviceObjectType->Close = NULL;
406 IoDeviceObjectType->Delete = NULL;
407 IoDeviceObjectType->Parse = NULL;
408 IoDeviceObjectType->Security = NULL;
409 IoDeviceObjectType->QueryName = NULL;
410 IoDeviceObjectType->OkayToClose = NULL;
411 IoDeviceObjectType->Create = IopCreateDevice;
412 IoDeviceObjectType->DuplicationNotify = NULL;
413
414 RtlRosInitUnicodeStringFromLiteral(&IoDeviceObjectType->TypeName, L"Device");
415
416 ObpCreateTypeObject(IoDeviceObjectType);
417
418 /*
419 * Register iomgr types: FileObjectType
420 * (alias DriverObjectType)
421 */
422 IoFileObjectType = ExAllocatePool (NonPagedPool, sizeof (OBJECT_TYPE));
423
424 IoFileObjectType->Tag = TAG_FILE_TYPE;
425 IoFileObjectType->TotalObjects = 0;
426 IoFileObjectType->TotalHandles = 0;
427 IoFileObjectType->PeakObjects = 0;
428 IoFileObjectType->PeakHandles = 0;
429 IoFileObjectType->PagedPoolCharge = 0;
430 IoFileObjectType->NonpagedPoolCharge = sizeof(FILE_OBJECT);
431 IoFileObjectType->Mapping = &IopFileMapping;
432 IoFileObjectType->Dump = NULL;
433 IoFileObjectType->Open = NULL;
434 IoFileObjectType->Close = IopCloseFile;
435 IoFileObjectType->Delete = IopDeleteFile;
436 IoFileObjectType->Parse = NULL;
437 IoFileObjectType->Security = IopSecurityFile;
438 IoFileObjectType->QueryName = IopQueryNameFile;
439 IoFileObjectType->OkayToClose = NULL;
440 IoFileObjectType->Create = IopCreateFile;
441 IoFileObjectType->DuplicationNotify = NULL;
442
443 RtlRosInitUnicodeStringFromLiteral(&IoFileObjectType->TypeName, L"File");
444
445 ObpCreateTypeObject(IoFileObjectType);
446
447 /*
448 * Register iomgr types: AdapterObjectType
449 */
450 IoAdapterObjectType = ExAllocatePool (NonPagedPool,
451 sizeof (OBJECT_TYPE));
452 RtlZeroMemory(IoAdapterObjectType, sizeof(OBJECT_TYPE));
453 IoAdapterObjectType->Tag = TAG_ADAPTER_TYPE;
454 IoAdapterObjectType->PeakObjects = 0;
455 IoAdapterObjectType->PeakHandles = 0;
456 IoDeviceObjectType->Mapping = &IopFileMapping;
457 RtlRosInitUnicodeStringFromLiteral(&IoAdapterObjectType->TypeName, L"Adapter");
458 ObpCreateTypeObject(IoAdapterObjectType);
459
460 /*
461 * Create the '\Driver' object directory
462 */
463 RtlRosInitUnicodeStringFromLiteral(&DirName, L"\\Driver");
464 InitializeObjectAttributes(&ObjectAttributes,
465 &DirName,
466 0,
467 NULL,
468 NULL);
469 NtCreateDirectoryObject(&Handle,
470 0,
471 &ObjectAttributes);
472
473 /*
474 * Create the '\FileSystem' object directory
475 */
476 RtlRosInitUnicodeStringFromLiteral(&DirName,
477 L"\\FileSystem");
478 InitializeObjectAttributes(&ObjectAttributes,
479 &DirName,
480 0,
481 NULL,
482 NULL);
483 NtCreateDirectoryObject(&Handle,
484 0,
485 &ObjectAttributes);
486
487 /*
488 * Create the '\Device' directory
489 */
490 RtlRosInitUnicodeStringFromLiteral(&DirName,
491 L"\\Device");
492 InitializeObjectAttributes(&ObjectAttributes,
493 &DirName,
494 0,
495 NULL,
496 NULL);
497 ZwCreateDirectoryObject(&Handle,
498 0,
499 &ObjectAttributes);
500
501 /*
502 * Create the '\??' directory
503 */
504 RtlRosInitUnicodeStringFromLiteral(&DirName,
505 L"\\??");
506 InitializeObjectAttributes(&ObjectAttributes,
507 &DirName,
508 0,
509 NULL,
510 NULL);
511 ZwCreateDirectoryObject(&Handle,
512 0,
513 &ObjectAttributes);
514
515 /*
516 * Create the '\ArcName' directory
517 */
518 RtlRosInitUnicodeStringFromLiteral(&DirName,
519 L"\\ArcName");
520 InitializeObjectAttributes(&ObjectAttributes,
521 &DirName,
522 0,
523 NULL,
524 NULL);
525 ZwCreateDirectoryObject(&Handle,
526 0,
527 &ObjectAttributes);
528
529 /*
530 * Initialize remaining subsubsystem
531 */
532 IoInitCancelHandling();
533 IoInitFileSystemImplementation();
534 IoInitVpbImplementation();
535 IoInitShutdownNotification();
536 IopInitErrorLog();
537 IopInitTimerImplementation();
538 IopInitIoCompletionImplementation();
539
540 /*
541 * Create link from '\DosDevices' to '\??' directory
542 */
543 RtlRosInitUnicodeStringFromLiteral(&LinkName,
544 L"\\DosDevices");
545 RtlRosInitUnicodeStringFromLiteral(&DirName,
546 L"\\??");
547 IoCreateSymbolicLink(&LinkName,
548 &DirName);
549
550 /*
551 * Initialize PnP manager
552 */
553 PnpInit();
554 }
555
556
557 VOID INIT_FUNCTION
558 IoInit2(VOID)
559 {
560 PDEVICE_NODE DeviceNode;
561 PDRIVER_OBJECT DriverObject;
562 MODULE_OBJECT ModuleObject;
563 NTSTATUS Status;
564
565 KeInitializeSpinLock (&IoStatisticsLock);
566
567 /* Initialize raw filesystem driver */
568
569 /* Use IopRootDeviceNode for now */
570 Status = IopCreateDeviceNode(IopRootDeviceNode,
571 NULL,
572 &DeviceNode);
573 if (!NT_SUCCESS(Status))
574 {
575 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
576 return;
577 }
578
579 ModuleObject.Base = NULL;
580 ModuleObject.Length = 0;
581 ModuleObject.EntryPoint = RawFsDriverEntry;
582
583 Status = IopInitializeDriverModule(
584 DeviceNode,
585 &ModuleObject,
586 TRUE,
587 &DriverObject);
588 if (!NT_SUCCESS(Status))
589 {
590 IopFreeDeviceNode(DeviceNode);
591 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
592 return;
593 }
594
595 Status = IopInitializeDevice(DeviceNode, DriverObject);
596 if (!NT_SUCCESS(Status))
597 {
598 IopFreeDeviceNode(DeviceNode);
599 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
600 return;
601 }
602
603 /*
604 * Initialize PnP root releations
605 */
606 IopInvalidateDeviceRelations(
607 IopRootDeviceNode,
608 BusRelations);
609 }
610
611 /*
612 * @implemented
613 */
614 PGENERIC_MAPPING STDCALL
615 IoGetFileObjectGenericMapping(VOID)
616 {
617 return(&IopFileMapping);
618 }
619
620 /* EOF */