2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/file.c
5 * PURPOSE: Functions that deal with managing the FILE_OBJECT itself.
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 * Filip Navara (navaraf@reactos.org)
12 /* INCLUDES *****************************************************************/
18 /* PRIVATE FUNCTIONS *********************************************************/
22 IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState
,
23 IN OUT PULONG CreateOptions
,
24 IN KPROCESSOR_MODE PreviousMode
,
27 ACCESS_MASK DesiredAccess
, ReadAccess
, WriteAccess
;
28 PRIVILEGE_SET Privileges
;
29 BOOLEAN AccessGranted
, HaveBackupPriv
= FALSE
, CheckRestore
= FALSE
;
32 /* Don't do anything if privileges were checked already */
33 if (AccessState
->Flags
& SE_BACKUP_PRIVILEGES_CHECKED
) return;
35 /* Check if the file was actually opened for backup purposes */
36 if (*CreateOptions
& FILE_OPEN_FOR_BACKUP_INTENT
)
38 /* Set the check flag since were doing it now */
39 AccessState
->Flags
|= SE_BACKUP_PRIVILEGES_CHECKED
;
41 /* Set the access masks required */
42 ReadAccess
= READ_CONTROL
|
43 ACCESS_SYSTEM_SECURITY
|
46 WriteAccess
= WRITE_DAC
|
48 ACCESS_SYSTEM_SECURITY
|
51 FILE_ADD_SUBDIRECTORY
|
53 DesiredAccess
= AccessState
->RemainingDesiredAccess
;
55 /* Check if desired access was the maximum */
56 if (DesiredAccess
& MAXIMUM_ALLOWED
)
58 /* Then add all the access masks required */
59 DesiredAccess
|= (ReadAccess
| WriteAccess
);
62 /* Check if the file already exists */
63 if (Disposition
& FILE_OPEN
)
65 /* Check if desired access has the read mask */
66 if (ReadAccess
& DesiredAccess
)
68 /* Setup the privilege check lookup */
69 Privileges
.PrivilegeCount
= 1;
70 Privileges
.Control
= PRIVILEGE_SET_ALL_NECESSARY
;
71 Privileges
.Privilege
[0].Luid
= SeBackupPrivilege
;
72 Privileges
.Privilege
[0].Attributes
= 0;
73 AccessGranted
= SePrivilegeCheck(&Privileges
,
75 SubjectSecurityContext
,
79 /* Remember that backup was allowed */
80 HaveBackupPriv
= TRUE
;
82 /* Append the privileges and update the access state */
83 SeAppendPrivileges(AccessState
, &Privileges
);
84 AccessState
->PreviouslyGrantedAccess
|= (DesiredAccess
& ReadAccess
);
85 AccessState
->RemainingDesiredAccess
&= ~ReadAccess
;
86 DesiredAccess
&= ~ReadAccess
;
88 /* Set backup privilege for the token */
89 AccessState
->Flags
|= TOKEN_HAS_BACKUP_PRIVILEGE
;
95 /* Caller is creating the file, check restore privileges later */
99 /* Check if caller wants write access or if it's creating a file */
100 if ((WriteAccess
& DesiredAccess
) || (CheckRestore
))
102 /* Setup the privilege lookup and do it */
103 Privileges
.PrivilegeCount
= 1;
104 Privileges
.Control
= PRIVILEGE_SET_ALL_NECESSARY
;
105 Privileges
.Privilege
[0].Luid
= SeRestorePrivilege
;
106 Privileges
.Privilege
[0].Attributes
= 0;
107 AccessGranted
= SePrivilegeCheck(&Privileges
,
108 &AccessState
->SubjectSecurityContext
,
112 /* Remember that privilege was given */
113 HaveBackupPriv
= TRUE
;
115 /* Append the privileges and update the access state */
116 SeAppendPrivileges(AccessState
, &Privileges
);
117 AccessState
->PreviouslyGrantedAccess
|= (DesiredAccess
& WriteAccess
);
118 AccessState
->RemainingDesiredAccess
&= ~WriteAccess
;
120 /* Set restore privilege for the token */
121 AccessState
->Flags
|= TOKEN_HAS_RESTORE_PRIVILEGE
;
125 /* If we don't have the privilege, remove the option */
126 if (!HaveBackupPriv
) *CreateOptions
&= ~FILE_OPEN_FOR_BACKUP_INTENT
;
132 IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket
,
133 IN PDEVICE_OBJECT DeviceObject
)
135 /* Make sure the object is valid */
136 if ((IoGetDevObjExtension(DeviceObject
)->ExtensionFlags
&
137 (DOE_UNLOAD_PENDING
|
140 DOE_REMOVE_PROCESSED
)) ||
141 (DeviceObject
->Flags
& DO_DEVICE_INITIALIZING
))
143 /* It's unloading or initializing, so fail */
144 DPRINT1("You are seeing this because the following ROS driver: %wZ\n"
145 " sucks. Please fix it's AddDevice Routine\n",
146 &DeviceObject
->DriverObject
->DriverName
);
147 return STATUS_NO_SUCH_DEVICE
;
149 else if ((DeviceObject
->Flags
& DO_EXCLUSIVE
) &&
150 (DeviceObject
->ReferenceCount
) &&
151 !(OpenPacket
->RelatedFileObject
) &&
152 !(OpenPacket
->Options
& IO_ATTACH_DEVICE
))
154 return STATUS_ACCESS_DENIED
;
159 /* Increase reference count */
160 DeviceObject
->ReferenceCount
++;
161 return STATUS_SUCCESS
;
167 IopParseDevice(IN PVOID ParseObject
,
169 IN OUT PACCESS_STATE AccessState
,
170 IN KPROCESSOR_MODE AccessMode
,
172 IN OUT PUNICODE_STRING CompleteName
,
173 IN OUT PUNICODE_STRING RemainingName
,
174 IN OUT PVOID Context
,
175 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
178 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
179 PDEVICE_OBJECT OriginalDeviceObject
= (PDEVICE_OBJECT
)ParseObject
;
180 PDEVICE_OBJECT DeviceObject
, OwnerDevice
;
182 PFILE_OBJECT FileObject
;
185 PEXTENDED_IO_STACK_LOCATION StackLoc
;
186 IO_SECURITY_CONTEXT SecurityContext
;
187 IO_STATUS_BLOCK IoStatusBlock
;
188 BOOLEAN DirectOpen
= FALSE
, OpenCancelled
, UseDummyFile
;
189 OBJECT_ATTRIBUTES ObjectAttributes
;
191 PDUMMY_FILE_OBJECT DummyFileObject
;
192 PFILE_BASIC_INFORMATION FileBasicInfo
;
194 KPROCESSOR_MODE CheckMode
;
195 BOOLEAN VolumeOpen
= FALSE
;
196 ACCESS_MASK DesiredAccess
, GrantedAccess
;
197 BOOLEAN AccessGranted
, LockHeld
= FALSE
;
198 PPRIVILEGE_SET Privileges
= NULL
;
199 IOTRACE(IO_FILE_DEBUG
, "ParseObject: %p. RemainingName: %wZ\n",
200 ParseObject
, RemainingName
);
205 /* Validate the open packet */
206 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
208 /* Check if we have a related file object */
209 if (OpenPacket
->RelatedFileObject
)
211 /* Use the related file object's device object */
212 OriginalDeviceObject
= OpenPacket
->RelatedFileObject
->DeviceObject
;
215 /* Validate device status */
216 Status
= IopCheckDeviceAndDriver(OpenPacket
, OriginalDeviceObject
);
217 if (!NT_SUCCESS(Status
))
219 /* We failed, return status */
220 OpenPacket
->FinalStatus
= Status
;
224 /* Map the generic mask and set the new mapping in the access state */
225 RtlMapGenericMask(&AccessState
->RemainingDesiredAccess
,
226 &IoFileObjectType
->TypeInfo
.GenericMapping
);
227 RtlMapGenericMask(&AccessState
->OriginalDesiredAccess
,
228 &IoFileObjectType
->TypeInfo
.GenericMapping
);
229 SeSetAccessStateGenericMapping(AccessState
,
230 &IoFileObjectType
->TypeInfo
.GenericMapping
);
231 DesiredAccess
= AccessState
->RemainingDesiredAccess
;
233 /* Check what kind of access checks to do */
234 if ((AccessMode
!= KernelMode
) ||
235 (OpenPacket
->Options
& IO_FORCE_ACCESS_CHECK
))
237 /* Call is from user-mode or kernel is forcing checks */
238 CheckMode
= UserMode
;
242 /* Call is from the kernel */
243 CheckMode
= KernelMode
;
246 /* Check privilege for backup or restore operation */
247 IopCheckBackupRestorePrivilege(AccessState
,
248 &OpenPacket
->CreateOptions
,
250 OpenPacket
->Disposition
);
252 /* Check if we are re-parsing */
253 if (((OpenPacket
->Override
) && !(RemainingName
->Length
)) ||
254 (AccessState
->Flags
& SE_BACKUP_PRIVILEGES_CHECKED
))
256 /* Get granted access from the last call */
257 DesiredAccess
|= AccessState
->PreviouslyGrantedAccess
;
260 /* Check if this is a volume open */
261 if ((OpenPacket
->RelatedFileObject
) &&
262 (OpenPacket
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
) &&
263 !(RemainingName
->Length
))
269 /* Now check if we need access checks */
270 if (((AccessMode
!= KernelMode
) ||
271 (OpenPacket
->Options
& IO_FORCE_ACCESS_CHECK
)) &&
272 (!(OpenPacket
->RelatedFileObject
) || (VolumeOpen
)) &&
273 !(OpenPacket
->Override
))
275 /* Check if a device object is being parsed */
276 if (!RemainingName
->Length
)
278 /* Lock the subject context */
279 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
282 /* Do access check */
283 AccessGranted
= SeAccessCheck(OriginalDeviceObject
->
285 &AccessState
->SubjectSecurityContext
,
291 TypeInfo
.GenericMapping
,
297 /* Append and free the privileges */
298 SeAppendPrivileges(AccessState
, Privileges
);
299 SeFreePrivileges(Privileges
);
302 /* Check if we got access */
305 /* Update access state */
306 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
307 AccessState
->RemainingDesiredAccess
&= ~(GrantedAccess
&
309 OpenPacket
->Override
= TRUE
;
312 /* FIXME: Do Audit/Alarm for open operation */
316 /* Check if we need to do traverse validation */
317 if (!(AccessState
->Flags
& TOKEN_HAS_TRAVERSE_PRIVILEGE
) ||
318 ((OriginalDeviceObject
->DeviceType
== FILE_DEVICE_DISK
) ||
319 (OriginalDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
)))
321 /* Check if this is a restricted token */
322 if (!(AccessState
->Flags
& TOKEN_IS_RESTRICTED
))
324 /* FIXME: Do the FAST traverse check */
325 AccessGranted
= FALSE
;
330 AccessGranted
= FALSE
;
333 /* Check if we failed to get access */
336 /* Lock the subject context */
337 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
340 /* Do access check */
341 AccessGranted
= SeAccessCheck(OriginalDeviceObject
->
343 &AccessState
->SubjectSecurityContext
,
349 TypeInfo
.GenericMapping
,
355 /* Append and free the privileges */
356 SeAppendPrivileges(AccessState
, Privileges
);
357 SeFreePrivileges(Privileges
);
361 /* FIXME: Do Audit/Alarm for traverse check */
365 /* Access automatically granted */
366 AccessGranted
= TRUE
;
370 /* Check if we hold the lock */
374 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
377 /* Check if access failed */
380 /* Dereference the device and fail */
381 DPRINT1("Traverse access failed!\n");
382 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
383 return STATUS_ACCESS_DENIED
;
387 /* Check if we can simply use a dummy file */
388 UseDummyFile
= ((OpenPacket
->QueryOnly
) || (OpenPacket
->DeleteOnly
));
390 /* Check if this is a direct open */
391 if (!(RemainingName
->Length
) &&
392 !(OpenPacket
->RelatedFileObject
) &&
393 ((DesiredAccess
& ~(SYNCHRONIZE
|
394 FILE_READ_ATTRIBUTES
|
396 ACCESS_SYSTEM_SECURITY
|
401 /* Remember this for later */
405 /* FIXME: Small hack still exists, have to check why...
406 * This is triggered multiple times by usetup and then once per boot.
409 !(RemainingName
->Length
) &&
410 !(OpenPacket
->RelatedFileObject
) &&
411 ((wcsstr(CompleteName
->Buffer
, L
"Harddisk")) ||
412 (wcsstr(CompleteName
->Buffer
, L
"Floppy"))) &&
415 DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
416 DesiredAccess
& ~(SYNCHRONIZE
|
417 FILE_READ_ATTRIBUTES
|
419 ACCESS_SYSTEM_SECURITY
|
425 /* Check if we have a related FO that wasn't a direct open */
426 if ((OpenPacket
->RelatedFileObject
) &&
427 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
429 /* The device object is the one we were given */
430 DeviceObject
= ParseObject
;
432 /* Check if the related FO had a VPB */
433 if (OpenPacket
->RelatedFileObject
->Vpb
)
435 /* Yes, remember it */
436 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
439 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
444 /* The device object is the one we were given */
445 DeviceObject
= OriginalDeviceObject
;
447 /* Check if it has a VPB */
448 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
450 /* Check if the VPB is mounted, and mount it */
451 Vpb
= IopCheckVpbMounted(OpenPacket
,
452 OriginalDeviceObject
,
455 if (!Vpb
) return Status
;
457 /* Get the VPB's device object */
458 DeviceObject
= Vpb
->DeviceObject
;
461 /* Check if there's an attached device */
462 if (DeviceObject
->AttachedDevice
)
464 /* Get the attached device */
465 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
469 /* Check if this is a secure FSD */
470 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
471 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
474 DPRINT("Fix Secure FSD support!!!\n");
477 /* Allocate the IRP */
478 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
481 /* Dereference the device and VPB, then fail */
482 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
483 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
484 return STATUS_INSUFFICIENT_RESOURCES
;
487 /* Now set the IRP data */
488 Irp
->RequestorMode
= AccessMode
;
489 Irp
->Flags
= IRP_CREATE_OPERATION
|
490 IRP_SYNCHRONOUS_API
|
491 IRP_DEFER_IO_COMPLETION
;
492 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
493 Irp
->UserIosb
= &IoStatusBlock
;
494 Irp
->MdlAddress
= NULL
;
495 Irp
->PendingReturned
= FALSE
;
496 Irp
->UserEvent
= NULL
;
498 Irp
->CancelRoutine
= NULL
;
499 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
501 /* Setup the security context */
502 SecurityContext
.SecurityQos
= SecurityQos
;
503 SecurityContext
.AccessState
= AccessState
;
504 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
505 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
507 /* Get the I/O Stack location */
508 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
509 StackLoc
->Control
= 0;
511 /* Check what kind of file this is */
512 switch (OpenPacket
->CreateFileType
)
515 case CreateFileTypeNone
:
517 /* Set the major function and EA Length */
518 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
519 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
522 StackLoc
->Flags
= (UCHAR
)OpenPacket
->Options
;
523 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ?
524 SL_CASE_SENSITIVE
: 0;
528 case CreateFileTypeNamedPipe
:
530 /* Set the named pipe MJ and set the parameters */
531 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
532 StackLoc
->Parameters
.CreatePipe
.Parameters
=
533 OpenPacket
->MailslotOrPipeParameters
;
537 case CreateFileTypeMailslot
:
539 /* Set the mailslot MJ and set the parameters */
540 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
541 StackLoc
->Parameters
.CreateMailslot
.Parameters
=
542 OpenPacket
->MailslotOrPipeParameters
;
546 /* Set the common data */
547 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
548 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
549 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
550 (OpenPacket
->CreateOptions
&
552 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
553 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
554 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
556 /* Check if we really need to create an object */
559 /* Create the actual file object */
560 InitializeObjectAttributes(&ObjectAttributes
,
565 Status
= ObCreateObject(KernelMode
,
573 (PVOID
*)&FileObject
);
574 if (!NT_SUCCESS(Status
))
576 /* Create failed, free the IRP */
579 /* Dereference the device and VPB */
580 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
581 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
583 /* We failed, return status */
584 OpenPacket
->FinalStatus
= Status
;
588 /* Clear the file object */
589 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
591 /* Check if this is Synch I/O */
592 if (OpenPacket
->CreateOptions
&
593 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
595 /* Set the synch flag */
596 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
598 /* Check if it's also alertable */
599 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
601 /* It is, set the alertable flag */
602 FileObject
->Flags
|= FO_ALERTABLE_IO
;
606 /* Check if this is synch I/O */
607 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
609 /* Initialize the event */
610 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
613 /* Check if the caller requested no intermediate buffering */
614 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
616 /* Set the correct flag for the FSD to read */
617 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
620 /* Check if the caller requested write through support */
621 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
623 /* Set the correct flag for the FSD to read */
624 FileObject
->Flags
|= FO_WRITE_THROUGH
;
627 /* Check if the caller says the file will be only read sequentially */
628 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
630 /* Set the correct flag for the FSD to read */
631 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
634 /* Check if the caller believes the file will be only read randomly */
635 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
637 /* Set the correct flag for the FSD to read */
638 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
643 /* Use the dummy object instead */
644 DummyFileObject
= OpenPacket
->DummyFileObject
;
645 RtlZeroMemory(DummyFileObject
, sizeof(DUMMY_FILE_OBJECT
));
648 FileObject
= (PFILE_OBJECT
)&DummyFileObject
->ObjectHeader
.Body
;
649 DummyFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
650 DummyFileObject
->ObjectHeader
.PointerCount
= 1;
653 /* Setup the file header */
654 FileObject
->Type
= IO_TYPE_FILE
;
655 FileObject
->Size
= sizeof(FILE_OBJECT
);
656 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
657 FileObject
->DeviceObject
= OriginalDeviceObject
;
659 /* Check if this is a direct device open */
660 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
662 /* Check if the caller wants case sensitivity */
663 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
665 /* Tell the driver about it */
666 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
669 /* Now set the file object */
670 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
671 StackLoc
->FileObject
= FileObject
;
673 /* Check if the file object has a name */
674 if (RemainingName
->Length
)
676 /* Setup the unicode string */
677 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
679 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
684 if (!FileObject
->FileName
.Buffer
)
686 /* Failed to allocate the name, free the IRP */
689 /* Dereference the device object and VPB */
690 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
691 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
693 /* Clear the FO and dereference it */
694 FileObject
->DeviceObject
= NULL
;
695 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
698 return STATUS_INSUFFICIENT_RESOURCES
;
703 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
705 /* Initialize the File Object event and set the FO */
706 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
707 OpenPacket
->FileObject
= FileObject
;
709 /* Queue the IRP and call the driver */
710 IopQueueIrpToThread(Irp
);
711 Status
= IoCallDriver(DeviceObject
, Irp
);
712 if (Status
== STATUS_PENDING
)
714 /* Wait for the driver to complete the create */
715 KeWaitForSingleObject(&FileObject
->Event
,
721 /* Get the new status */
722 Status
= IoStatusBlock
.Status
;
726 /* We'll have to complete it ourselves */
727 ASSERT(!Irp
->PendingReturned
);
728 ASSERT(!Irp
->MdlAddress
);
730 /* Completion happens at APC_LEVEL */
731 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
733 /* Get the new I/O Status block ourselves */
734 IoStatusBlock
= Irp
->IoStatus
;
735 Status
= IoStatusBlock
.Status
;
737 /* Manually signal the even, we can't have any waiters */
738 FileObject
->Event
.Header
.SignalState
= 1;
740 /* Now that we've signaled the events, de-associate the IRP */
741 IopUnQueueIrpFromThread(Irp
);
743 /* Check if the IRP had an input buffer */
744 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
745 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
747 /* Free it. A driver might've tacked one on */
748 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
751 /* Free the IRP and bring the IRQL back down */
753 KeLowerIrql(OldIrql
);
756 /* Copy the I/O Status */
757 OpenPacket
->Information
= IoStatusBlock
.Information
;
759 /* The driver failed to create the file */
760 if (!NT_SUCCESS(Status
))
762 /* Check if we have a name */
763 if (FileObject
->FileName
.Length
)
766 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
767 FileObject
->FileName
.Length
= 0;
770 /* Clear its device object */
771 FileObject
->DeviceObject
= NULL
;
773 /* Save this now because the FO might go away */
774 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
777 /* Clear the file object in the open packet */
778 OpenPacket
->FileObject
= NULL
;
780 /* Dereference the file object */
781 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
783 /* Dereference the device object */
784 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
786 /* Unless the driver cancelled the open, dereference the VPB */
787 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpbAndFree(Vpb
);
789 /* Set the status and return */
790 OpenPacket
->FinalStatus
= Status
;
793 else if (Status
== STATUS_REPARSE
)
795 /* FIXME: We don't handle this at all! */
799 /* Get the owner of the File Object */
800 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
803 * It's possible that the device to whom we sent the IRP to
804 * isn't actually the device that ended opening the file object
807 if (OwnerDevice
!= DeviceObject
)
809 /* We have to de-reference the VPB we had associated */
810 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
812 /* And re-associate with the actual one */
813 Vpb
= FileObject
->Vpb
;
814 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
817 /* Make sure we are not using a dummy */
820 /* Check if this was a volume open */
821 if ((!(FileObject
->RelatedFileObject
) ||
822 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
823 !(FileObject
->FileName
.Length
))
825 /* All signs point to it, but make sure it was actually an FSD */
826 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
827 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
828 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
829 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
831 /* The owner device is an FSD, so this is a volume open for real */
832 FileObject
->Flags
|= FO_VOLUME_OPEN
;
836 /* Reference the object and set the parse check */
837 ObReferenceObject(FileObject
);
838 *Object
= FileObject
;
839 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
840 OpenPacket
->ParseCheck
= TRUE
;
841 return OpenPacket
->FinalStatus
;
845 /* Check if this was a query */
846 if (OpenPacket
->QueryOnly
)
848 /* Check if the caller wants basic info only */
849 if (!OpenPacket
->FullAttributes
)
851 /* Allocate the buffer */
852 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
853 sizeof(*FileBasicInfo
),
858 Status
= IoQueryFileInformation(FileObject
,
859 FileBasicInformation
,
860 sizeof(*FileBasicInfo
),
863 if (NT_SUCCESS(Status
))
866 RtlCopyMemory(OpenPacket
->BasicInformation
,
871 /* Free our buffer */
872 ExFreePoolWithTag(FileBasicInfo
, TAG_IO
);
877 Status
= STATUS_INSUFFICIENT_RESOURCES
;
882 /* This is a full query */
883 Status
= IoQueryFileInformation(
885 FileNetworkOpenInformation
,
886 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
887 OpenPacket
->NetworkInformation
,
889 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
893 /* Delete the file object */
894 IopDeleteFile(FileObject
);
896 /* Clear out the file */
897 OpenPacket
->FileObject
= NULL
;
899 /* Set and return status */
900 OpenPacket
->FinalStatus
= Status
;
901 OpenPacket
->ParseCheck
= TRUE
;
908 IopParseFile(IN PVOID ParseObject
,
910 IN OUT PACCESS_STATE AccessState
,
911 IN KPROCESSOR_MODE AccessMode
,
913 IN OUT PUNICODE_STRING CompleteName
,
914 IN OUT PUNICODE_STRING RemainingName
,
915 IN OUT PVOID Context OPTIONAL
,
916 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
920 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
922 /* Validate the open packet */
923 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
925 /* Get the device object */
926 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
927 OpenPacket
->RelatedFileObject
= ParseObject
;
929 /* Call the main routine */
930 return IopParseDevice(DeviceObject
,
944 IopDeleteFile(IN PVOID ObjectBody
)
946 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
948 PIO_STACK_LOCATION StackPtr
;
951 PDEVICE_OBJECT DeviceObject
;
952 BOOLEAN DereferenceDone
= FALSE
;
955 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
957 /* Check if the file has a device object */
958 if (FileObject
->DeviceObject
)
960 /* Check if this is a direct open or not */
961 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
963 /* Get the attached device */
964 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
968 /* Use the file object's device object */
969 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
973 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
974 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
976 /* Check if the handle wasn't created yet */
977 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
979 /* Send the cleanup IRP */
980 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
983 /* Clear and set up Events */
984 KeClearEvent(&FileObject
->Event
);
985 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
987 /* Allocate an IRP */
988 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
992 Irp
->UserEvent
= &Event
;
993 Irp
->UserIosb
= &Irp
->IoStatus
;
994 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
995 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
996 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
998 /* Set up Stack Pointer Data */
999 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1000 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
1001 StackPtr
->FileObject
= FileObject
;
1004 IopQueueIrpToThread(Irp
);
1006 /* Get the VPB and check if this isn't a direct open */
1007 Vpb
= FileObject
->Vpb
;
1008 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1010 /* Dereference the VPB before the close */
1011 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1014 /* Check if the FS will never disappear by itself */
1015 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1017 /* Dereference it */
1018 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1019 DereferenceDone
= TRUE
;
1022 /* Call the FS Driver */
1023 Status
= IoCallDriver(DeviceObject
, Irp
);
1024 if (Status
== STATUS_PENDING
)
1026 /* Wait for completion */
1027 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1030 /* De-queue the IRP */
1031 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1032 IopUnQueueIrpFromThread(Irp
);
1033 KeLowerIrql(OldIrql
);
1038 /* Clear the file name */
1039 if (FileObject
->FileName
.Buffer
)
1041 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1042 FileObject
->FileName
.Buffer
= NULL
;
1045 /* Check if the FO had a completion port */
1046 if (FileObject
->CompletionContext
)
1049 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1050 ExFreePool(FileObject
->CompletionContext
);
1053 /* Check if the FO had extension */
1054 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1056 /* Release filter context structure if any */
1057 FsRtlPTeardownPerFileObjectContexts(FileObject
);
1060 /* Check if dereference has been done yet */
1061 if (!DereferenceDone
)
1063 /* Dereference device object */
1064 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1071 IopSecurityFile(IN PVOID ObjectBody
,
1072 IN SECURITY_OPERATION_CODE OperationCode
,
1073 IN PSECURITY_INFORMATION SecurityInformation
,
1074 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1075 IN OUT PULONG BufferLength
,
1076 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1077 IN POOL_TYPE PoolType
,
1078 IN OUT PGENERIC_MAPPING GenericMapping
)
1080 IO_STATUS_BLOCK IoStatusBlock
;
1081 PIO_STACK_LOCATION StackPtr
;
1082 PFILE_OBJECT FileObject
;
1083 PDEVICE_OBJECT DeviceObject
;
1085 BOOLEAN LocalEvent
= FALSE
;
1087 NTSTATUS Status
= STATUS_SUCCESS
;
1089 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1091 /* Check if this is a device or file */
1092 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1095 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1101 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1103 /* Check if this is a direct open */
1104 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1106 /* Get the Device Object */
1107 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1111 /* Otherwise, use the direct device*/
1112 DeviceObject
= FileObject
->DeviceObject
;
1116 /* Check if the request was for a device object */
1117 if (!(FileObject
) ||
1118 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1119 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1121 /* Check what kind of request this was */
1122 if (OperationCode
== QuerySecurityDescriptor
)
1124 return SeQuerySecurityDescriptorInfo(SecurityInformation
,
1127 &DeviceObject
->SecurityDescriptor
);
1129 else if (OperationCode
== DeleteSecurityDescriptor
)
1131 /* Simply return success */
1132 return STATUS_SUCCESS
;
1134 else if (OperationCode
== AssignSecurityDescriptor
)
1136 /* Make absolutely sure this is a device object */
1137 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1139 /* Assign the Security Descriptor */
1140 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
1143 /* Return success */
1144 return STATUS_SUCCESS
;
1148 DPRINT1("FIXME: Set SD unimplemented for Devices\n");
1149 return STATUS_SUCCESS
;
1152 else if (OperationCode
== DeleteSecurityDescriptor
)
1154 /* Same as for devices, do nothing */
1155 return STATUS_SUCCESS
;
1158 /* At this point, we know we're a file. Reference it */
1159 ObReferenceObject(FileObject
);
1161 /* Check if we should use Sync IO or not */
1162 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1164 /* Lock the file object */
1165 IopLockFileObject(FileObject
);
1169 /* Use local event */
1170 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1174 /* Clear the File Object event */
1175 KeClearEvent(&FileObject
->Event
);
1177 /* Get the device object */
1178 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1180 /* Allocate the IRP */
1181 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1182 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1185 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1186 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1187 Irp
->RequestorMode
= ExGetPreviousMode();
1188 Irp
->UserIosb
= &IoStatusBlock
;
1189 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1190 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1191 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1193 /* Set Stack Parameters */
1194 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1195 StackPtr
->FileObject
= FileObject
;
1197 /* Check if this is a query or set */
1198 if (OperationCode
== QuerySecurityDescriptor
)
1200 /* Set the major function and parameters */
1201 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1202 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1203 *SecurityInformation
;
1204 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1205 Irp
->UserBuffer
= SecurityDescriptor
;
1209 /* Set the major function and parameters for a set */
1210 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1211 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1212 *SecurityInformation
;
1213 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1218 IopQueueIrpToThread(Irp
);
1220 /* Update operation counts */
1221 IopUpdateOperationCount(IopOtherTransfer
);
1223 /* Call the Driver */
1224 Status
= IoCallDriver(DeviceObject
, Irp
);
1226 /* Check if this was async I/O */
1229 /* Check if the IRP is pending completion */
1230 if (Status
== STATUS_PENDING
)
1232 /* Wait on the local event */
1233 KeWaitForSingleObject(&Event
,
1238 Status
= IoStatusBlock
.Status
;
1243 /* Check if the IRP is pending completion */
1244 if (Status
== STATUS_PENDING
)
1246 /* Wait on the file object */
1247 KeWaitForSingleObject(&FileObject
->Event
,
1252 Status
= FileObject
->FinalStatus
;
1255 /* Release the lock */
1256 IopUnlockFileObject(FileObject
);
1259 /* This Driver doesn't implement Security, so try to give it a default */
1260 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1262 /* Was this a query? */
1263 if (OperationCode
== QuerySecurityDescriptor
)
1265 /* Set a World Security Descriptor */
1266 Status
= SeSetWorldSecurityDescriptor(*SecurityInformation
,
1272 /* It wasn't a query, so just fake success */
1273 Status
= STATUS_SUCCESS
;
1276 else if (OperationCode
== QuerySecurityDescriptor
)
1278 /* Callers usually expect the normalized form */
1279 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1284 *BufferLength
= (ULONG
)IoStatusBlock
.Information
;
1286 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1288 /* Get the exception code */
1289 Status
= _SEH2_GetExceptionCode();
1300 IopQueryNameFile(IN PVOID ObjectBody
,
1302 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1304 OUT PULONG ReturnLength
,
1305 IN KPROCESSOR_MODE PreviousMode
)
1307 POBJECT_NAME_INFORMATION LocalInfo
;
1308 PFILE_NAME_INFORMATION LocalFileInfo
;
1309 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1310 ULONG LocalReturnLength
, FileLength
;
1311 BOOLEAN LengthMismatch
= FALSE
;
1314 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1316 /* Validate length */
1317 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1319 /* Wrong length, fail */
1320 return STATUS_INFO_LENGTH_MISMATCH
;
1323 /* Allocate Buffer */
1324 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1325 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1327 /* Query the name */
1328 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1331 &LocalReturnLength
);
1332 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1334 /* Free the buffer and fail */
1335 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1339 /* Copy the information */
1340 RtlCopyMemory(ObjectNameInfo
,
1342 (LocalReturnLength
> Length
) ?
1343 Length
: LocalReturnLength
);
1345 /* Set buffer pointer */
1346 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1347 ObjectNameInfo
->Name
.Buffer
= p
;
1349 /* Advance in buffer */
1350 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1352 /* Check if this already filled our buffer */
1353 if (LocalReturnLength
> Length
)
1355 /* Set the length mismatch to true, so that we can return
1356 * the proper buffer size to the caller later
1358 LengthMismatch
= TRUE
;
1360 /* Save the initial buffer length value */
1361 *ReturnLength
= LocalReturnLength
;
1364 /* Now get the file name buffer and check the length needed */
1365 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1366 FileLength
= Length
-
1368 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1370 /* Query the File name */
1371 Status
= IoQueryFileInformation(FileObject
,
1372 FileNameInformation
,
1373 LengthMismatch
? Length
: FileLength
,
1375 &LocalReturnLength
);
1376 if (NT_ERROR(Status
))
1378 /* Fail on errors only, allow warnings */
1379 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1383 /* If the provided buffer is too small, return the required size */
1386 /* Add the required length */
1387 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1389 /* Free the allocated buffer and return failure */
1390 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1391 return STATUS_BUFFER_OVERFLOW
;
1394 /* Now calculate the new lengths left */
1395 FileLength
= LocalReturnLength
-
1396 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1397 LocalReturnLength
= (ULONG
)((ULONG_PTR
)p
-
1398 (ULONG_PTR
)ObjectNameInfo
+
1399 LocalFileInfo
->FileNameLength
);
1401 /* Write the Name and null-terminate it */
1402 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1403 p
+= (FileLength
/ sizeof(WCHAR
));
1405 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1407 /* Return the length needed */
1408 *ReturnLength
= LocalReturnLength
;
1410 /* Setup the length and maximum length */
1411 FileLength
= (ULONG
)((ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
);
1412 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1413 sizeof(OBJECT_NAME_INFORMATION
);
1414 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1415 sizeof(UNICODE_NULL
);
1417 /* Free buffer and return */
1418 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1424 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1425 IN PVOID ObjectBody
,
1426 IN ACCESS_MASK GrantedAccess
,
1427 IN ULONG HandleCount
,
1428 IN ULONG SystemHandleCount
)
1430 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1433 PIO_STACK_LOCATION StackPtr
;
1435 PDEVICE_OBJECT DeviceObject
;
1437 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1439 /* If this isn't the last handle for the current process, quit */
1440 if (HandleCount
!= 1) return;
1442 /* Check if the file is locked and has more then one handle opened */
1443 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1445 DPRINT1("We need to unlock this file!\n");
1449 /* Make sure this is the last handle */
1450 if (SystemHandleCount
!= 1) return;
1452 /* Check if this is a direct open or not */
1453 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1455 /* Get the attached device */
1456 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1460 /* Get the FO's device */
1461 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1464 /* Set the handle created flag */
1465 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1467 /* Check if this is a sync FO and lock it */
1468 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1470 /* Clear and set up Events */
1471 KeClearEvent(&FileObject
->Event
);
1472 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1474 /* Allocate an IRP */
1475 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1479 Irp
->UserEvent
= &Event
;
1480 Irp
->UserIosb
= &Irp
->IoStatus
;
1481 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1482 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1483 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1484 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1486 /* Set up Stack Pointer Data */
1487 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1488 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1489 StackPtr
->FileObject
= FileObject
;
1492 IopQueueIrpToThread(Irp
);
1494 /* Update operation counts */
1495 IopUpdateOperationCount(IopOtherTransfer
);
1497 /* Call the FS Driver */
1498 Status
= IoCallDriver(DeviceObject
, Irp
);
1499 if (Status
== STATUS_PENDING
)
1501 /* Wait for completion */
1502 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1505 /* Unqueue the IRP */
1506 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1507 IopUnQueueIrpFromThread(Irp
);
1508 KeLowerIrql(OldIrql
);
1513 /* Release the lock if we were holding it */
1514 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1519 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1520 IN FILE_INFORMATION_CLASS FileInformationClass
,
1521 IN ULONG FileInformationSize
,
1522 OUT PVOID FileInformation
)
1525 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1526 DUMMY_FILE_OBJECT DummyFileObject
;
1527 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1529 OPEN_PACKET OpenPacket
;
1532 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
1534 /* Check if the caller was user mode */
1535 if (AccessMode
!= KernelMode
)
1537 /* Protect probe in SEH */
1540 /* Probe the buffer */
1541 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
1543 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1545 /* Return the exception code */
1546 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1551 /* Check if this is a basic or full request */
1552 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
1554 /* Setup the Open Packet */
1555 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1556 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1557 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1558 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
1559 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
1560 OpenPacket
.Disposition
= FILE_OPEN
;
1561 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
1562 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
1563 (AccessMode
!= KernelMode
) ?
1564 &NetworkOpenInfo
: FileInformation
;
1565 OpenPacket
.QueryOnly
= TRUE
;
1566 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
1567 OpenPacket
.DummyFileObject
= &DummyFileObject
;
1569 /* Update the operation count */
1570 IopUpdateOperationCount(IopOtherTransfer
);
1573 * Attempt opening the file. This will call the I/O Parse Routine for
1574 * the File Object (IopParseDevice) which will use the dummy file obejct
1575 * send the IRP to its device object. Note that we have two statuses
1576 * to worry about: the Object Manager's status (in Status) and the I/O
1577 * status, which is in the Open Packet's Final Status, and determined
1578 * by the Parse Check member.
1580 Status
= ObOpenObjectByName(ObjectAttributes
,
1584 FILE_READ_ATTRIBUTES
,
1587 if (OpenPacket
.ParseCheck
!= TRUE
)
1594 /* Use the Io status */
1595 Status
= OpenPacket
.FinalStatus
;
1598 /* Check if we were succesful and this was user mode and a full query */
1599 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
1601 /* Enter SEH for copy */
1604 /* Copy the buffer back */
1605 RtlCopyMemory(FileInformation
,
1607 FileInformationSize
);
1609 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1611 /* Get exception code */
1612 Status
= _SEH2_GetExceptionCode();
1623 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject
)
1625 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1628 /* FIXME: return NULL for the moment ~ */
1637 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject
,
1638 IN PVOID FilterContext
,
1641 if (!(FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
))
1643 return STATUS_INVALID_PARAMETER
;
1648 return STATUS_NOT_IMPLEMENTED
;
1651 /* FUNCTIONS *****************************************************************/
1658 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
1660 IN BOOLEAN SetOperation
)
1663 return STATUS_NOT_IMPLEMENTED
;
1671 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
1672 IN ULONG QuotaLength
,
1673 OUT PULONG ErrorOffset
)
1676 return STATUS_NOT_IMPLEMENTED
;
1684 IoCreateFile(OUT PHANDLE FileHandle
,
1685 IN ACCESS_MASK DesiredAccess
,
1686 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1687 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1688 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1689 IN ULONG FileAttributes
,
1690 IN ULONG ShareAccess
,
1691 IN ULONG Disposition
,
1692 IN ULONG CreateOptions
,
1693 IN PVOID EaBuffer OPTIONAL
,
1695 IN CREATE_FILE_TYPE CreateFileType
,
1696 IN PVOID ExtraCreateParameters OPTIONAL
,
1699 KPROCESSOR_MODE AccessMode
;
1700 HANDLE LocalHandle
= 0;
1701 LARGE_INTEGER SafeAllocationSize
;
1702 PVOID SystemEaBuffer
= NULL
;
1704 OPEN_PACKET OpenPacket
;
1705 ULONG EaErrorOffset
;
1708 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
1710 /* Check if we have no parameter checking to do */
1711 if (Options
& IO_NO_PARAMETER_CHECKING
)
1713 /* Then force kernel-mode access to avoid checks */
1714 AccessMode
= KernelMode
;
1718 /* Otherwise, use the actual mode */
1719 AccessMode
= ExGetPreviousMode();
1722 /* Check if the call came from user mode */
1723 if (AccessMode
!= KernelMode
)
1727 ProbeForWriteHandle(FileHandle
);
1728 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1731 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
1735 SafeAllocationSize
.QuadPart
= 0;
1738 if ((EaBuffer
) && (EaLength
))
1740 ProbeForRead(EaBuffer
,
1744 /* marshal EaBuffer */
1745 SystemEaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1750 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1753 RtlCopyMemory(SystemEaBuffer
, EaBuffer
, EaLength
);
1755 /* Validate the buffer */
1756 Status
= IoCheckEaBufferValidity(SystemEaBuffer
,
1759 if (!NT_SUCCESS(Status
))
1761 DPRINT1("FIXME: IoCheckEaBufferValidity() failed with "
1762 "Status: %lx\n",Status
);
1764 /* Free EA Buffer and return the error */
1765 ExFreePoolWithTag(SystemEaBuffer
, TAG_EA
);
1766 _SEH2_YIELD(return Status
);
1770 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1772 /* Free SystemEaBuffer if needed */
1773 if (SystemEaBuffer
) ExFreePoolWithTag(SystemEaBuffer
, TAG_EA
);
1775 /* Return the exception code */
1776 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1782 /* Check if this is a device attach */
1783 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
1785 /* Set the flag properly */
1786 Options
|= IO_ATTACH_DEVICE
;
1787 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
1790 /* Check if we have allocation size */
1794 SafeAllocationSize
= *AllocationSize
;
1798 /* Otherwise, no size */
1799 SafeAllocationSize
.QuadPart
= 0;
1802 /* Check if we have an EA packet */
1803 if ((EaBuffer
) && (EaLength
))
1805 /* Allocate the kernel copy */
1806 SystemEaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1809 if (!SystemEaBuffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1812 RtlCopyMemory(SystemEaBuffer
, EaBuffer
, EaLength
);
1814 /* Validate the buffer */
1815 Status
= IoCheckEaBufferValidity(SystemEaBuffer
,
1818 if (!NT_SUCCESS(Status
))
1820 DPRINT1("FIXME: IoCheckEaBufferValidity() failed with "
1821 "Status: %lx\n",Status
);
1826 /* Setup the Open Packet */
1827 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1828 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1829 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1830 OpenPacket
.OriginalAttributes
= *ObjectAttributes
;
1831 OpenPacket
.AllocationSize
= SafeAllocationSize
;
1832 OpenPacket
.CreateOptions
= CreateOptions
;
1833 OpenPacket
.FileAttributes
= (USHORT
)FileAttributes
;
1834 OpenPacket
.ShareAccess
= (USHORT
)ShareAccess
;
1835 OpenPacket
.EaBuffer
= SystemEaBuffer
;
1836 OpenPacket
.EaLength
= EaLength
;
1837 OpenPacket
.Options
= Options
;
1838 OpenPacket
.Disposition
= Disposition
;
1839 OpenPacket
.CreateFileType
= CreateFileType
;
1840 OpenPacket
.MailslotOrPipeParameters
= ExtraCreateParameters
;
1842 /* Update the operation count */
1843 IopUpdateOperationCount(IopOtherTransfer
);
1846 * Attempt opening the file. This will call the I/O Parse Routine for
1847 * the File Object (IopParseDevice) which will create the object and
1848 * send the IRP to its device object. Note that we have two statuses
1849 * to worry about: the Object Manager's status (in Status) and the I/O
1850 * status, which is in the Open Packet's Final Status, and determined
1851 * by the Parse Check member.
1853 Status
= ObOpenObjectByName(ObjectAttributes
,
1861 /* Free the EA Buffer */
1862 if (OpenPacket
.EaBuffer
) ExFreePool(OpenPacket
.EaBuffer
);
1864 /* Now check for Ob or Io failure */
1865 if (!(NT_SUCCESS(Status
)) || (OpenPacket
.ParseCheck
!= TRUE
))
1867 /* Check if Ob thinks well went well */
1868 if (NT_SUCCESS(Status
))
1871 * Tell it otherwise. Because we didn't use an ObjectType,
1872 * it incorrectly returned us a handle to God knows what.
1874 ZwClose(LocalHandle
);
1875 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
1878 /* Now check the Io status */
1879 if (!NT_SUCCESS(OpenPacket
.FinalStatus
))
1881 /* Use this status instead of Ob's */
1882 Status
= OpenPacket
.FinalStatus
;
1884 /* Check if it was only a warning */
1885 if (NT_WARNING(Status
))
1887 /* Protect write with SEH */
1890 /* In this case, we copy the I/O Status back */
1891 IoStatusBlock
->Information
= OpenPacket
.Information
;
1892 IoStatusBlock
->Status
= OpenPacket
.FinalStatus
;
1894 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1896 /* Get exception code */
1897 Status
= _SEH2_GetExceptionCode();
1902 else if ((OpenPacket
.FileObject
) && (OpenPacket
.ParseCheck
!= 1))
1905 * This can happen in the very bizarre case where the parse routine
1906 * actually executed more then once (due to a reparse) and ended
1907 * up failing after already having created the File Object.
1909 if (OpenPacket
.FileObject
->FileName
.Length
)
1911 /* It had a name, free it */
1912 ExFreePoolWithTag(OpenPacket
.FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1915 /* Clear the device object to invalidate the FO, and dereference */
1916 OpenPacket
.FileObject
->DeviceObject
= NULL
;
1917 ObDereferenceObject(OpenPacket
.FileObject
);
1922 /* We reached success and have a valid file handle */
1923 OpenPacket
.FileObject
->Flags
|= FO_HANDLE_CREATED
;
1925 /* Enter SEH for write back */
1928 /* Write back the handle and I/O Status */
1929 *FileHandle
= LocalHandle
;
1930 IoStatusBlock
->Information
= OpenPacket
.Information
;
1931 IoStatusBlock
->Status
= OpenPacket
.FinalStatus
;
1933 /* Get the Io status */
1934 Status
= OpenPacket
.FinalStatus
;
1936 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1938 /* Get the exception status */
1939 Status
= _SEH2_GetExceptionCode();
1944 /* Check if we were 100% successful */
1945 if ((OpenPacket
.ParseCheck
== TRUE
) && (OpenPacket
.FileObject
))
1947 /* Dereference the File Object */
1948 ObDereferenceObject(OpenPacket
.FileObject
);
1960 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1961 IN ACCESS_MASK DesiredAccess
,
1962 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1963 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1964 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1965 IN ULONG FileAttributes
,
1966 IN ULONG ShareAccess
,
1967 IN ULONG Disposition
,
1968 IN ULONG CreateOptions
,
1969 IN PVOID EaBuffer OPTIONAL
,
1971 IN CREATE_FILE_TYPE CreateFileType
,
1972 IN PVOID ExtraCreateParameters OPTIONAL
,
1974 IN PVOID DeviceObject
)
1977 return STATUS_NOT_IMPLEMENTED
;
1985 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1986 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1987 OUT PHANDLE FileObjectHandle OPTIONAL
)
1989 PFILE_OBJECT CreatedFileObject
;
1992 OBJECT_ATTRIBUTES ObjectAttributes
;
1994 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
1996 /* Choose Device Object */
1997 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1999 /* Reference the device object and initialize attributes */
2000 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2001 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2003 /* Create the File Object */
2004 Status
= ObCreateObject(KernelMode
,
2009 sizeof(FILE_OBJECT
),
2010 sizeof(FILE_OBJECT
),
2012 (PVOID
*)&CreatedFileObject
);
2013 if (!NT_SUCCESS(Status
))
2016 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2017 ExRaiseStatus(Status
);
2020 /* Set File Object Data */
2021 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2022 CreatedFileObject
->DeviceObject
= DeviceObject
;
2023 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2024 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2025 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2027 /* Initialize the wait event */
2028 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2030 /* Insert it to create a handle for it */
2031 Status
= ObInsertObject(CreatedFileObject
,
2035 (PVOID
*)&CreatedFileObject
,
2037 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2039 /* Set the handle created flag */
2040 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2041 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2043 /* Check if we have a VPB */
2044 if (DeviceObject
->Vpb
)
2047 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2050 /* Check if the caller wants the handle */
2051 if (FileObjectHandle
)
2054 *FileObjectHandle
= FileHandle
;
2055 ObDereferenceObject(CreatedFileObject
);
2059 /* Otherwise, close it */
2060 ObCloseHandle(FileHandle
, KernelMode
);
2063 /* Return the file object */
2064 return CreatedFileObject
;
2072 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2073 IN PDEVICE_OBJECT DeviceObject
)
2075 /* Call the newer function */
2076 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2084 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2085 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2087 PFILE_OBJECT CreatedFileObject
;
2089 OBJECT_ATTRIBUTES ObjectAttributes
;
2091 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2093 /* Choose Device Object */
2094 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2096 /* Reference the device object and initialize attributes */
2097 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2098 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2100 /* Create the File Object */
2101 Status
= ObCreateObject(KernelMode
,
2106 sizeof(FILE_OBJECT
),
2107 sizeof(FILE_OBJECT
),
2109 (PVOID
*)&CreatedFileObject
);
2110 if (!NT_SUCCESS(Status
))
2113 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2114 ExRaiseStatus(Status
);
2117 /* Set File Object Data */
2118 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2119 CreatedFileObject
->DeviceObject
= DeviceObject
;
2120 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2121 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2122 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2124 /* Initialize the wait event */
2125 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2127 /* Destroy create information */
2128 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2130 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2132 /* Set the handle created flag */
2133 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2134 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2136 /* Check if we have a VPB */
2137 if (DeviceObject
->Vpb
)
2140 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2143 /* Return the file object */
2144 return CreatedFileObject
;
2152 IoGetFileObjectGenericMapping(VOID
)
2154 /* Return the mapping */
2155 return &IopFileMapping
;
2163 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2165 /* Return the flag status */
2166 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2174 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2175 IN ACCESS_MASK DesiredAccess
,
2176 IN ULONG OpenOptions
,
2177 OUT PIO_STATUS_BLOCK IoStatus
,
2178 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2181 DUMMY_FILE_OBJECT DummyFileObject
;
2183 OPEN_PACKET OpenPacket
;
2185 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2187 /* Setup the Open Packet */
2188 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2189 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2190 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2191 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2192 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2193 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2194 OpenPacket
.Disposition
= FILE_OPEN
;
2195 OpenPacket
.NetworkInformation
= Buffer
;
2196 OpenPacket
.QueryOnly
= TRUE
;
2197 OpenPacket
.FullAttributes
= TRUE
;
2198 OpenPacket
.DummyFileObject
= &DummyFileObject
;
2201 * Attempt opening the file. This will call the I/O Parse Routine for
2202 * the File Object (IopParseDevice) which will use the dummy file obejct
2203 * send the IRP to its device object. Note that we have two statuses
2204 * to worry about: the Object Manager's status (in Status) and the I/O
2205 * status, which is in the Open Packet's Final Status, and determined
2206 * by the Parse Check member.
2208 Status
= ObOpenObjectByName(ObjectAttributes
,
2215 if (OpenPacket
.ParseCheck
!= TRUE
)
2218 IoStatus
->Status
= Status
;
2222 /* Use the Io status */
2223 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2224 IoStatus
->Information
= OpenPacket
.Information
;
2227 /* Return success */
2236 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2237 OUT PSHARE_ACCESS ShareAccess
)
2241 /* Check if the file has an extension */
2242 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2244 /* Check if caller specified to ignore access checks */
2245 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2247 /* Don't update share access */
2252 /* Otherwise, check if there's any access present */
2253 if ((FileObject
->ReadAccess
) ||
2254 (FileObject
->WriteAccess
) ||
2255 (FileObject
->DeleteAccess
))
2257 /* Increase the open count */
2258 ShareAccess
->OpenCount
++;
2260 /* Add new share access */
2261 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2262 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2263 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2264 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2265 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2266 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2275 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2276 IN ULONG DesiredShareAccess
,
2277 IN PFILE_OBJECT FileObject
,
2278 IN PSHARE_ACCESS ShareAccess
,
2282 BOOLEAN WriteAccess
;
2283 BOOLEAN DeleteAccess
;
2285 BOOLEAN SharedWrite
;
2286 BOOLEAN SharedDelete
;
2289 /* Get access masks */
2290 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2291 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2292 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2294 /* Set them in the file object */
2295 FileObject
->ReadAccess
= ReadAccess
;
2296 FileObject
->WriteAccess
= WriteAccess
;
2297 FileObject
->DeleteAccess
= DeleteAccess
;
2299 /* Check if the file has an extension */
2300 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2302 /* Check if caller specified to ignore access checks */
2303 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2305 /* Don't check share access */
2306 return STATUS_SUCCESS
;
2310 /* Check if we have any access */
2311 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2313 /* Get shared access masks */
2314 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2315 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2316 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2319 FileObject
->SharedRead
= SharedRead
;
2320 FileObject
->SharedWrite
= SharedWrite
;
2321 FileObject
->SharedDelete
= SharedDelete
;
2323 /* Check if the shared access is violated */
2325 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2327 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2329 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2330 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2331 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2332 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2334 /* Sharing violation, fail */
2335 return STATUS_SHARING_VIOLATION
;
2338 /* It's not, check if caller wants us to update it */
2341 /* Increase open count */
2342 ShareAccess
->OpenCount
++;
2344 /* Update shared access */
2345 ShareAccess
->Readers
+= ReadAccess
;
2346 ShareAccess
->Writers
+= WriteAccess
;
2347 ShareAccess
->Deleters
+= DeleteAccess
;
2348 ShareAccess
->SharedRead
+= SharedRead
;
2349 ShareAccess
->SharedWrite
+= SharedWrite
;
2350 ShareAccess
->SharedDelete
+= SharedDelete
;
2354 /* Validation successful */
2355 return STATUS_SUCCESS
;
2363 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2364 IN PSHARE_ACCESS ShareAccess
)
2368 /* Check if the file has an extension */
2369 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2371 /* Check if caller specified to ignore access checks */
2372 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2374 /* Don't update share access */
2379 /* Otherwise, check if there's any access present */
2380 if ((FileObject
->ReadAccess
) ||
2381 (FileObject
->WriteAccess
) ||
2382 (FileObject
->DeleteAccess
))
2384 /* Decrement the open count */
2385 ShareAccess
->OpenCount
--;
2387 /* Remove share access */
2388 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
2389 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
2390 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
2391 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
2392 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
2393 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
2402 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
2403 IN ULONG DesiredShareAccess
,
2404 IN PFILE_OBJECT FileObject
,
2405 OUT PSHARE_ACCESS ShareAccess
)
2408 BOOLEAN WriteAccess
;
2409 BOOLEAN DeleteAccess
;
2411 BOOLEAN SharedWrite
;
2412 BOOLEAN SharedDelete
;
2413 BOOLEAN Update
= TRUE
;
2416 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2417 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2418 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2420 /* Check if the file has an extension */
2421 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2423 /* Check if caller specified to ignore access checks */
2424 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2426 /* Don't update share access */
2431 /* Update basic access */
2432 FileObject
->ReadAccess
= ReadAccess
;
2433 FileObject
->WriteAccess
= WriteAccess
;
2434 FileObject
->DeleteAccess
= DeleteAccess
;
2436 /* Check if we have no access as all */
2437 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
2439 /* Check if we need to update the structure */
2440 if (!Update
) return;
2442 /* Otherwise, clear data */
2443 ShareAccess
->OpenCount
= 0;
2444 ShareAccess
->Readers
= 0;
2445 ShareAccess
->Writers
= 0;
2446 ShareAccess
->Deleters
= 0;
2447 ShareAccess
->SharedRead
= 0;
2448 ShareAccess
->SharedWrite
= 0;
2449 ShareAccess
->SharedDelete
= 0;
2453 /* Calculate shared access */
2454 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2455 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2456 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2458 /* Set it in the FO */
2459 FileObject
->SharedRead
= SharedRead
;
2460 FileObject
->SharedWrite
= SharedWrite
;
2461 FileObject
->SharedDelete
= SharedDelete
;
2463 /* Check if we need to update the structure */
2464 if (!Update
) return;
2466 /* Otherwise, set data */
2467 ShareAccess
->OpenCount
= 1;
2468 ShareAccess
->Readers
= ReadAccess
;
2469 ShareAccess
->Writers
= WriteAccess
;
2470 ShareAccess
->Deleters
= DeleteAccess
;
2471 ShareAccess
->SharedRead
= SharedRead
;
2472 ShareAccess
->SharedWrite
= SharedWrite
;
2473 ShareAccess
->SharedDelete
= SharedDelete
;
2482 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
2483 IN PFILE_OBJECT FileObject
)
2493 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
2494 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
2497 return STATUS_NOT_IMPLEMENTED
;
2505 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
2508 NTSTATUS Status
= STATUS_SUCCESS
;
2511 /* Get the flag status */
2512 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2514 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
2515 if (Remote
&& !FlagSet
)
2518 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
2520 else if (!Remote
&& FlagSet
)
2522 /* Remove the flag */
2523 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
2528 Status
= STATUS_INVALID_PARAMETER_MIX
;
2540 NtCreateFile(PHANDLE FileHandle
,
2541 ACCESS_MASK DesiredAccess
,
2542 POBJECT_ATTRIBUTES ObjectAttributes
,
2543 PIO_STATUS_BLOCK IoStatusBlock
,
2544 PLARGE_INTEGER AllocateSize
,
2545 ULONG FileAttributes
,
2547 ULONG CreateDisposition
,
2548 ULONG CreateOptions
,
2552 /* Call the I/O Function */
2553 return IoCreateFile(FileHandle
,
2571 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
2572 IN ACCESS_MASK DesiredAccess
,
2573 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2574 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2575 IN ULONG CreateOptions
,
2576 IN ULONG MailslotQuota
,
2577 IN ULONG MaxMessageSize
,
2578 IN PLARGE_INTEGER TimeOut
)
2580 MAILSLOT_CREATE_PARAMETERS Buffer
;
2583 /* Check for Timeout */
2586 /* check if the call came from user mode */
2587 if (KeGetPreviousMode() != KernelMode
)
2589 /* Enter SEH for Probe */
2592 /* Probe the timeout */
2593 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
2595 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2597 /* Return the exception code */
2598 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2604 /* Otherwise, capture directly */
2605 Buffer
.ReadTimeout
= *TimeOut
;
2608 /* Set the correct setting */
2609 Buffer
.TimeoutSpecified
= TRUE
;
2613 /* Tell the FSD we don't have a timeout */
2614 Buffer
.TimeoutSpecified
= FALSE
;
2618 Buffer
.MailslotQuota
= MailslotQuota
;
2619 Buffer
.MaximumMessageSize
= MaxMessageSize
;
2622 return IoCreateFile(FileHandle
,
2628 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2633 CreateFileTypeMailslot
,
2640 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
2641 IN ACCESS_MASK DesiredAccess
,
2642 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2643 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2644 IN ULONG ShareAccess
,
2645 IN ULONG CreateDisposition
,
2646 IN ULONG CreateOptions
,
2647 IN ULONG NamedPipeType
,
2649 IN ULONG CompletionMode
,
2650 IN ULONG MaximumInstances
,
2651 IN ULONG InboundQuota
,
2652 IN ULONG OutboundQuota
,
2653 IN PLARGE_INTEGER DefaultTimeout
)
2655 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
2658 /* Check for Timeout */
2661 /* check if the call came from user mode */
2662 if (KeGetPreviousMode() != KernelMode
)
2664 /* Enter SEH for Probe */
2667 /* Probe the timeout */
2668 Buffer
.DefaultTimeout
=
2669 ProbeForReadLargeInteger(DefaultTimeout
);
2671 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2673 /* Return the exception code */
2674 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2680 /* Otherwise, capture directly */
2681 Buffer
.DefaultTimeout
= *DefaultTimeout
;
2684 /* Set the correct setting */
2685 Buffer
.TimeoutSpecified
= TRUE
;
2689 /* Tell the FSD we don't have a timeout */
2690 Buffer
.TimeoutSpecified
= FALSE
;
2694 Buffer
.NamedPipeType
= NamedPipeType
;
2695 Buffer
.ReadMode
= ReadMode
;
2696 Buffer
.CompletionMode
= CompletionMode
;
2697 Buffer
.MaximumInstances
= MaximumInstances
;
2698 Buffer
.InboundQuota
= InboundQuota
;
2699 Buffer
.OutboundQuota
= OutboundQuota
;
2702 return IoCreateFile(FileHandle
,
2713 CreateFileTypeNamedPipe
,
2720 NtFlushWriteBuffer(VOID
)
2724 /* Call the kernel */
2725 KeFlushWriteBuffer();
2726 return STATUS_SUCCESS
;
2734 NtOpenFile(OUT PHANDLE FileHandle
,
2735 IN ACCESS_MASK DesiredAccess
,
2736 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2737 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2738 IN ULONG ShareAccess
,
2739 IN ULONG OpenOptions
)
2741 /* Call the I/O Function */
2742 return IoCreateFile(FileHandle
,
2760 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2761 OUT PFILE_BASIC_INFORMATION FileInformation
)
2763 /* Call the internal helper API */
2764 return IopQueryAttributesFile(ObjectAttributes
,
2765 FileBasicInformation
,
2766 sizeof(FILE_BASIC_INFORMATION
),
2772 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2773 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2775 /* Call the internal helper API */
2776 return IopQueryAttributesFile(ObjectAttributes
,
2777 FileNetworkOpenInformation
,
2778 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2783 * @name NtCancelIoFile
2785 * Cancel all pending I/O operations in the current thread for specified
2789 * Handle to file object to cancel requests for. No specific
2790 * access rights are needed.
2791 * @param IoStatusBlock
2792 * Pointer to status block which is filled with final completition
2793 * status on successful return.
2801 NtCancelIoFile(IN HANDLE FileHandle
,
2802 OUT PIO_STATUS_BLOCK IoStatusBlock
)
2804 PFILE_OBJECT FileObject
;
2808 BOOLEAN OurIrpsInList
= FALSE
;
2809 LARGE_INTEGER Interval
;
2810 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2812 PLIST_ENTRY ListHead
, NextEntry
;
2814 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2816 /* Check the previous mode */
2817 if (PreviousMode
!= KernelMode
)
2819 /* Enter SEH for probing */
2822 /* Probe the I/O Status Block */
2823 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2825 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2827 /* Return the exception code */
2828 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2833 /* Reference the file object */
2834 Status
= ObReferenceObjectByHandle(FileHandle
,
2838 (PVOID
*)&FileObject
,
2840 if (!NT_SUCCESS(Status
)) return Status
;
2842 /* IRP cancellations are synchronized at APC_LEVEL. */
2843 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2845 /* Get the current thread */
2846 Thread
= PsGetCurrentThread();
2848 /* Update the operation counts */
2849 IopUpdateOperationCount(IopOtherTransfer
);
2852 ListHead
= &Thread
->IrpList
;
2853 NextEntry
= ListHead
->Flink
;
2854 while (ListHead
!= NextEntry
)
2856 /* Get the IRP and check if the File Object matches */
2857 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
2858 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
2860 /* Cancel this IRP and keep looping */
2862 OurIrpsInList
= TRUE
;
2865 /* Go to the next entry */
2866 NextEntry
= NextEntry
->Flink
;
2869 /* Lower the IRQL */
2870 KeLowerIrql(OldIrql
);
2872 /* Check if we had found an IRP */
2875 /* Setup a 10ms wait */
2876 Interval
.QuadPart
= -100000;
2879 while (OurIrpsInList
)
2882 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
2883 OurIrpsInList
= FALSE
;
2886 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2888 /* Now loop the list again */
2889 NextEntry
= ListHead
->Flink
;
2890 while (NextEntry
!= ListHead
)
2892 /* Get the IRP and check if the File Object matches */
2893 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
2894 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
2897 OurIrpsInList
= TRUE
;
2901 /* Go to the next entry */
2902 NextEntry
= NextEntry
->Flink
;
2905 /* Lower the IRQL */
2906 KeLowerIrql(OldIrql
);
2910 /* Enter SEH for writing back the I/O Status */
2914 IoStatusBlock
->Status
= STATUS_SUCCESS
;
2915 IoStatusBlock
->Information
= 0;
2917 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2919 /* Ignore exception */
2923 /* Dereference the file object and return success */
2924 ObDereferenceObject(FileObject
);
2925 return STATUS_SUCCESS
;
2933 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
2936 DUMMY_FILE_OBJECT DummyFileObject
;
2938 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
2939 OPEN_PACKET OpenPacket
;
2941 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
2943 /* Setup the Open Packet */
2944 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2945 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2946 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2947 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
2948 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
2951 OpenPacket
.Disposition
= FILE_OPEN
;
2952 OpenPacket
.DeleteOnly
= TRUE
;
2953 OpenPacket
.DummyFileObject
= &DummyFileObject
;
2955 /* Update the operation counts */
2956 IopUpdateOperationCount(IopOtherTransfer
);
2959 * Attempt opening the file. This will call the I/O Parse Routine for
2960 * the File Object (IopParseDevice) which will use the dummy file obejct
2961 * send the IRP to its device object. Note that we have two statuses
2962 * to worry about: the Object Manager's status (in Status) and the I/O
2963 * status, which is in the Open Packet's Final Status, and determined
2964 * by the Parse Check member.
2966 Status
= ObOpenObjectByName(ObjectAttributes
,
2973 if (OpenPacket
.ParseCheck
!= TRUE
) return Status
;
2975 /* Retrn the Io status */
2976 return OpenPacket
.FinalStatus
;