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 OPTIONAL
,
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 #if 0 // USETUP IS BROKEN!
394 ((DesiredAccess
& ~(SYNCHRONIZE
|
395 FILE_READ_ATTRIBUTES
|
397 ACCESS_SYSTEM_SECURITY
|
403 if (DesiredAccess
& ~(SYNCHRONIZE
|
404 FILE_READ_ATTRIBUTES
|
406 ACCESS_SYSTEM_SECURITY
|
410 DPRINT1("FIXME: Broken Parse due to invalid DesiredAccess: %lx\n",
414 /* Remember this for later */
418 /* Check if we have a related FO that wasn't a direct open */
419 if ((OpenPacket
->RelatedFileObject
) &&
420 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
422 /* The device object is the one we were given */
423 DeviceObject
= ParseObject
;
425 /* Check if the related FO had a VPB */
426 if (OpenPacket
->RelatedFileObject
->Vpb
)
428 /* Yes, remember it */
429 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
432 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
437 /* The device object is the one we were given */
438 DeviceObject
= OriginalDeviceObject
;
440 /* Check if it has a VPB */
441 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
443 /* Check if the VPB is mounted, and mount it */
444 Vpb
= IopCheckVpbMounted(OpenPacket
,
445 OriginalDeviceObject
,
448 if (!Vpb
) return Status
;
450 /* Get the VPB's device object */
451 DeviceObject
= Vpb
->DeviceObject
;
454 /* Check if there's an attached device */
455 if (DeviceObject
->AttachedDevice
)
457 /* Get the attached device */
458 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
462 /* Check if this is a secure FSD */
463 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
464 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
467 DPRINT1("Fix Secure FSD support!!!\n");
470 /* Allocate the IRP */
471 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
474 /* Dereference the device and VPB, then fail */
475 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
476 if (Vpb
) IopDereferenceVpb(Vpb
);
477 return STATUS_INSUFFICIENT_RESOURCES
;
480 /* Now set the IRP data */
481 Irp
->RequestorMode
= AccessMode
;
482 Irp
->Flags
= IRP_CREATE_OPERATION
|
483 IRP_SYNCHRONOUS_API
|
484 IRP_DEFER_IO_COMPLETION
;
485 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
486 Irp
->UserIosb
= &IoStatusBlock
;
487 Irp
->MdlAddress
= NULL
;
488 Irp
->PendingReturned
= FALSE
;
489 Irp
->UserEvent
= NULL
;
491 Irp
->CancelRoutine
= NULL
;
492 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
494 /* Setup the security context */
495 SecurityContext
.SecurityQos
= SecurityQos
;
496 SecurityContext
.AccessState
= AccessState
;
497 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
498 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
500 /* Get the I/O Stack location */
501 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
502 StackLoc
->Control
= 0;
504 /* Check what kind of file this is */
505 switch (OpenPacket
->CreateFileType
)
508 case CreateFileTypeNone
:
510 /* Set the major function and EA Length */
511 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
512 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
515 StackLoc
->Flags
= OpenPacket
->Options
;
516 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ?
517 SL_CASE_SENSITIVE
: 0;
521 case CreateFileTypeNamedPipe
:
523 /* Set the named pipe MJ and set the parameters */
524 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
525 StackLoc
->Parameters
.CreatePipe
.Parameters
=
526 OpenPacket
->MailslotOrPipeParameters
;
530 case CreateFileTypeMailslot
:
532 /* Set the mailslot MJ and set the parameters */
533 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
534 StackLoc
->Parameters
.CreateMailslot
.Parameters
=
535 OpenPacket
->MailslotOrPipeParameters
;
539 /* Set the common data */
540 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
541 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
542 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
543 (OpenPacket
->CreateOptions
&
545 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
546 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
547 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
549 /* Check if we really need to create an object */
552 /* Create the actual file object */
553 InitializeObjectAttributes(&ObjectAttributes
,
558 Status
= ObCreateObject(KernelMode
,
566 (PVOID
*)&FileObject
);
567 if (!NT_SUCCESS(Status
))
569 /* Create failed, free the IRP */
572 /* Dereference the device and VPB */
573 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
574 if (Vpb
) IopDereferenceVpb(Vpb
);
576 /* We failed, return status */
577 OpenPacket
->FinalStatus
= Status
;
581 /* Clear the file object */
582 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
584 /* Check if this is Synch I/O */
585 if (OpenPacket
->CreateOptions
&
586 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
588 /* Set the synch flag */
589 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
591 /* Check if it's also alertable */
592 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
594 /* It is, set the alertable flag */
595 FileObject
->Flags
|= FO_ALERTABLE_IO
;
599 /* Check if this is synch I/O */
600 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
602 /* Initialize the event */
603 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
606 /* Check if the caller requested no intermediate buffering */
607 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
609 /* Set the correct flag for the FSD to read */
610 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
613 /* Check if the caller requested write through support */
614 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
616 /* Set the correct flag for the FSD to read */
617 FileObject
->Flags
|= FO_WRITE_THROUGH
;
620 /* Check if the caller says the file will be only read sequentially */
621 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
623 /* Set the correct flag for the FSD to read */
624 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
627 /* Check if the caller believes the file will be only read randomly */
628 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
630 /* Set the correct flag for the FSD to read */
631 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
636 /* Use the dummy object instead */
637 DummyFileObject
= OpenPacket
->DummyFileObject
;
638 RtlZeroMemory(DummyFileObject
, sizeof(DUMMY_FILE_OBJECT
));
641 FileObject
= (PFILE_OBJECT
)&DummyFileObject
->ObjectHeader
.Body
;
642 DummyFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
643 DummyFileObject
->ObjectHeader
.PointerCount
= 1;
646 /* Setup the file header */
647 FileObject
->Type
= IO_TYPE_FILE
;
648 FileObject
->Size
= sizeof(FILE_OBJECT
);
649 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
650 FileObject
->DeviceObject
= OriginalDeviceObject
;
652 /* Check if this is a direct device open */
653 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
655 /* Check if the caller wants case sensitivity */
656 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
658 /* Tell the driver about it */
659 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
662 /* Now set the file object */
663 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
664 StackLoc
->FileObject
= FileObject
;
666 /* Check if the file object has a name */
667 if (RemainingName
->Length
)
669 /* Setup the unicode string */
670 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
672 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
677 if (!FileObject
->FileName
.Buffer
)
679 /* Failed to allocate the name, free the IRP */
682 /* Dereference the device object and VPB */
683 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
684 if (Vpb
) IopDereferenceVpb(Vpb
);
686 /* Clear the FO and dereference it */
687 FileObject
->DeviceObject
= NULL
;
688 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
691 return STATUS_INSUFFICIENT_RESOURCES
;
696 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
698 /* Initialize the File Object event and set the FO */
699 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
700 OpenPacket
->FileObject
= FileObject
;
702 /* Queue the IRP and call the driver */
703 IopQueueIrpToThread(Irp
);
704 Status
= IoCallDriver(DeviceObject
, Irp
);
705 if (Status
== STATUS_PENDING
)
707 /* Wait for the driver to complete the create */
708 KeWaitForSingleObject(&FileObject
->Event
,
714 /* Get the new status */
715 Status
= IoStatusBlock
.Status
;
719 /* We'll have to complete it ourselves */
720 ASSERT(!Irp
->PendingReturned
);
721 ASSERT(!Irp
->MdlAddress
);
723 /* Completion happens at APC_LEVEL */
724 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
726 /* Get the new I/O Status block ourselves */
727 IoStatusBlock
= Irp
->IoStatus
;
728 Status
= IoStatusBlock
.Status
;
730 /* Manually signal the even, we can't have any waiters */
731 FileObject
->Event
.Header
.SignalState
= 1;
733 /* Now that we've signaled the events, de-associate the IRP */
734 IopUnQueueIrpFromThread(Irp
);
736 /* Check if the IRP had an input buffer */
737 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
738 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
740 /* Free it. A driver might've tacked one on */
741 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
744 /* Free the IRP and bring the IRQL back down */
746 KeLowerIrql(OldIrql
);
749 /* Copy the I/O Status */
750 OpenPacket
->Information
= IoStatusBlock
.Information
;
752 /* The driver failed to create the file */
753 if (!NT_SUCCESS(Status
))
755 /* Check if we have a name */
756 if (FileObject
->FileName
.Length
)
759 ExFreePool(FileObject
->FileName
.Buffer
);
760 FileObject
->FileName
.Length
= 0;
763 /* Clear its device object */
764 FileObject
->DeviceObject
= NULL
;
766 /* Save this now because the FO might go away */
767 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
;
769 /* Clear the file object in the open packet */
770 OpenPacket
->FileObject
= NULL
;
772 /* Dereference the file object */
773 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
775 /* Dereference the device object */
776 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
778 /* Unless the driver cancelled the open, dereference the VPB */
779 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpb(Vpb
);
781 /* Set the status and return */
782 OpenPacket
->FinalStatus
= Status
;
785 else if (Status
== STATUS_REPARSE
)
787 /* FIXME: We don't handle this at all! */
791 /* Get the owner of the File Object */
792 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
795 * It's possible that the device to whom we sent the IRP to
796 * isn't actually the device that ended opening the file object
799 if (OwnerDevice
!= DeviceObject
)
801 /* We have to de-reference the VPB we had associated */
802 if (Vpb
) IopDereferenceVpb(Vpb
);
804 /* And re-associate with the actual one */
805 Vpb
= FileObject
->Vpb
;
806 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
809 /* Make sure we are not using a dummy */
812 /* Check if this was a volume open */
813 if ((!(FileObject
->RelatedFileObject
) ||
814 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
815 !(FileObject
->FileName
.Length
))
817 /* All signs point to it, but make sure it was actually an FSD */
818 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
819 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
820 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
821 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
823 /* The owner device is an FSD, so this is a volume open for real */
824 FileObject
->Flags
|= FO_VOLUME_OPEN
;
828 /* Reference the object and set the parse check */
829 ObReferenceObject(FileObject
);
830 *Object
= FileObject
;
831 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
832 OpenPacket
->ParseCheck
= TRUE
;
833 return OpenPacket
->FinalStatus
;
837 /* Check if this was a query */
838 if (OpenPacket
->QueryOnly
)
840 /* Check if the caller wants basic info only */
841 if (!OpenPacket
->FullAttributes
)
843 /* Allocate the buffer */
844 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
845 sizeof(*FileBasicInfo
),
850 Status
= IoQueryFileInformation(FileObject
,
851 FileBasicInformation
,
852 sizeof(*FileBasicInfo
),
855 if (NT_SUCCESS(Status
))
858 RtlCopyMemory(OpenPacket
->BasicInformation
,
863 /* Free our buffer */
864 ExFreePool(FileBasicInfo
);
869 Status
= STATUS_INSUFFICIENT_RESOURCES
;
874 /* This is a full query */
875 Status
= IoQueryFileInformation(
877 FileNetworkOpenInformation
,
878 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
879 OpenPacket
->NetworkInformation
,
881 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
885 /* Delete the file object */
886 IopDeleteFile(FileObject
);
888 /* Clear out the file */
889 OpenPacket
->FileObject
= NULL
;
891 /* Set and return status */
892 OpenPacket
->FinalStatus
= Status
;
893 OpenPacket
->ParseCheck
= TRUE
;
900 IopParseFile(IN PVOID ParseObject
,
902 IN OUT PACCESS_STATE AccessState
,
903 IN KPROCESSOR_MODE AccessMode
,
905 IN OUT PUNICODE_STRING CompleteName
,
906 IN OUT PUNICODE_STRING RemainingName
,
907 IN OUT PVOID Context OPTIONAL
,
908 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
912 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
914 /* Validate the open packet */
915 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
917 /* Get the device object */
918 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
919 OpenPacket
->RelatedFileObject
= ParseObject
;
921 /* Call the main routine */
922 return IopParseDevice(DeviceObject
,
936 IopDeleteFile(IN PVOID ObjectBody
)
938 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
940 PIO_STACK_LOCATION StackPtr
;
943 PDEVICE_OBJECT DeviceObject
;
944 BOOLEAN DereferenceDone
= FALSE
;
947 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
949 /* Check if the file has a device object */
950 if (FileObject
->DeviceObject
)
952 /* Check if this is a direct open or not */
953 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
955 /* Get the attached device */
956 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
960 /* Use the file object's device object */
961 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
965 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
966 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
968 /* Check if the handle wasn't created yet */
969 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
971 /* Send the cleanup IRP */
972 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
975 /* Clear and set up Events */
976 KeClearEvent(&FileObject
->Event
);
977 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
979 /* Allocate an IRP */
980 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
984 Irp
->UserEvent
= &Event
;
985 Irp
->UserIosb
= &Irp
->IoStatus
;
986 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
987 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
988 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
990 /* Set up Stack Pointer Data */
991 StackPtr
= IoGetNextIrpStackLocation(Irp
);
992 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
993 StackPtr
->FileObject
= FileObject
;
996 IopQueueIrpToThread(Irp
);
998 /* Get the VPB and check if this isn't a direct open */
999 Vpb
= FileObject
->Vpb
;
1000 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1002 /* Dereference the VPB before the close */
1003 InterlockedDecrement(&Vpb
->ReferenceCount
);
1006 /* Check if the FS will never disappear by itself */
1007 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1009 /* Dereference it */
1010 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1011 DereferenceDone
= TRUE
;
1014 /* Call the FS Driver */
1015 Status
= IoCallDriver(DeviceObject
, Irp
);
1016 if (Status
== STATUS_PENDING
)
1018 /* Wait for completion */
1019 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1022 /* De-queue the IRP */
1023 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1024 IopUnQueueIrpFromThread(Irp
);
1025 KeLowerIrql(OldIrql
);
1030 /* Clear the file name */
1031 if (FileObject
->FileName
.Buffer
)
1033 ExFreePool(FileObject
->FileName
.Buffer
);
1034 FileObject
->FileName
.Buffer
= NULL
;
1037 /* Check if the FO had a completion port */
1038 if (FileObject
->CompletionContext
)
1041 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1042 ExFreePool(FileObject
->CompletionContext
);
1045 /* Check if dereference has been done yet */
1046 if (!DereferenceDone
)
1048 /* Dereference device object */
1049 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1056 IopSecurityFile(IN PVOID ObjectBody
,
1057 IN SECURITY_OPERATION_CODE OperationCode
,
1058 IN SECURITY_INFORMATION SecurityInformation
,
1059 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1060 IN OUT PULONG BufferLength
,
1061 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1062 IN POOL_TYPE PoolType
,
1063 IN OUT PGENERIC_MAPPING GenericMapping
)
1065 IO_STATUS_BLOCK IoStatusBlock
;
1066 PIO_STACK_LOCATION StackPtr
;
1067 PFILE_OBJECT FileObject
;
1068 PDEVICE_OBJECT DeviceObject
;
1070 BOOLEAN LocalEvent
= FALSE
;
1072 NTSTATUS Status
= STATUS_SUCCESS
;
1074 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1076 /* Check if this is a device or file */
1077 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1080 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1086 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1088 /* Check if this is a direct open */
1089 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1091 /* Get the Device Object */
1092 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1096 /* Otherwise, use the direct device*/
1097 DeviceObject
= FileObject
->DeviceObject
;
1101 /* Check if the request was for a device object */
1102 if (!(FileObject
) ||
1103 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1104 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1106 /* Check what kind of request this was */
1107 if (OperationCode
== QuerySecurityDescriptor
)
1109 DPRINT1("FIXME: Device Query security descriptor UNHANDLED\n");
1110 return STATUS_SUCCESS
;
1112 else if (OperationCode
== DeleteSecurityDescriptor
)
1114 /* Simply return success */
1115 return STATUS_SUCCESS
;
1117 else if (OperationCode
== AssignSecurityDescriptor
)
1119 /* Make absolutely sure this is a device object */
1120 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1122 /* Assign the Security Descriptor */
1123 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
1126 /* Return success */
1127 return STATUS_SUCCESS
;
1131 DPRINT1("FIXME: Set SD unimplemented for Devices\n");
1132 return STATUS_SUCCESS
;
1135 else if (OperationCode
== DeleteSecurityDescriptor
)
1137 /* Same as for devices, do nothing */
1138 return STATUS_SUCCESS
;
1141 /* At this point, we know we're a file. Reference it */
1142 ObReferenceObject(FileObject
);
1144 /* Check if we should use Sync IO or not */
1145 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1147 /* Lock the file object */
1148 IopLockFileObject(FileObject
);
1152 /* Use local event */
1153 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1157 /* Clear the File Object event */
1158 KeClearEvent(&FileObject
->Event
);
1160 /* Get the device object */
1161 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1163 /* Allocate the IRP */
1164 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1165 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1168 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1169 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1170 Irp
->RequestorMode
= ExGetPreviousMode();
1171 Irp
->UserIosb
= &IoStatusBlock
;
1172 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1173 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1174 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1176 /* Set Stack Parameters */
1177 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1178 StackPtr
->FileObject
= FileObject
;
1180 /* Check if this is a query or set */
1181 if (OperationCode
== QuerySecurityDescriptor
)
1183 /* Set the major function and parameters */
1184 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1185 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1186 SecurityInformation
;
1187 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1188 Irp
->UserBuffer
= SecurityDescriptor
;
1192 /* Set the major function and parameters for a set */
1193 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1194 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1195 SecurityInformation
;
1196 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1201 IopQueueIrpToThread(Irp
);
1203 /* Update operation counts */
1204 IopUpdateOperationCount(IopOtherTransfer
);
1206 /* Call the Driver */
1207 Status
= IoCallDriver(DeviceObject
, Irp
);
1209 /* Check if this was async I/O */
1212 /* Check if the IRP is pending completion */
1213 if (Status
== STATUS_PENDING
)
1215 /* Wait on the local event */
1216 KeWaitForSingleObject(&Event
,
1221 Status
= IoStatusBlock
.Status
;
1226 /* Check if the IRP is pending completion */
1227 if (Status
== STATUS_PENDING
)
1229 /* Wait on the file object */
1230 KeWaitForSingleObject(&FileObject
->Event
,
1235 Status
= FileObject
->FinalStatus
;
1238 /* Release the lock */
1239 IopUnlockFileObject(FileObject
);
1242 /* This Driver doesn't implement Security, so try to give it a default */
1243 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1245 /* Was this a query? */
1246 if (OperationCode
== QuerySecurityDescriptor
)
1248 /* Set a World Security Descriptor */
1249 Status
= SeSetWorldSecurityDescriptor(SecurityInformation
,
1255 /* It wasn't a query, so just fake success */
1256 Status
= STATUS_SUCCESS
;
1259 else if (OperationCode
== QuerySecurityDescriptor
)
1261 /* Callers usually expect the normalized form */
1262 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1265 *BufferLength
= IoStatusBlock
.Information
;
1274 IopQueryNameFile(IN PVOID ObjectBody
,
1276 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1278 OUT PULONG ReturnLength
,
1279 IN KPROCESSOR_MODE PreviousMode
)
1281 POBJECT_NAME_INFORMATION LocalInfo
;
1282 PFILE_NAME_INFORMATION LocalFileInfo
;
1283 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1284 ULONG LocalReturnLength
, FileLength
;
1287 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1289 /* Validate length */
1290 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1292 /* Wrong length, fail */
1293 return STATUS_INFO_LENGTH_MISMATCH
;
1296 /* Allocate Buffer */
1297 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1298 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1300 /* Query the name */
1301 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1304 &LocalReturnLength
);
1305 if (!NT_SUCCESS(Status
))
1307 /* Free the buffer and fail */
1308 ExFreePool(LocalInfo
);
1312 /* Copy the information */
1313 RtlCopyMemory(ObjectNameInfo
,
1315 (LocalReturnLength
> Length
) ?
1316 Length
: LocalReturnLength
);
1318 /* Set buffer pointer */
1319 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1320 ObjectNameInfo
->Name
.Buffer
= p
;
1322 /* Advance in buffer */
1323 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1325 /* Check if this already filled our buffer */
1326 if (LocalReturnLength
> Length
)
1328 /* Free the buffer and fail */
1329 ExFreePool(LocalInfo
);
1330 return STATUS_BUFFER_OVERFLOW
;
1333 /* Now get the file name buffer and check the length needed */
1334 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1335 FileLength
= Length
-
1337 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1339 /* Query the File name */
1340 Status
= IoQueryFileInformation(FileObject
,
1341 FileNameInformation
,
1344 &LocalReturnLength
);
1345 if (NT_ERROR(Status
))
1347 /* Fail on errors only, allow warnings */
1348 ExFreePool(LocalInfo
);
1352 /* ROS HACK. VFAT SUCKS */
1353 if (NT_WARNING(Status
)) LocalReturnLength
= FileLength
;
1355 /* Now calculate the new lengths left */
1356 FileLength
= LocalReturnLength
-
1357 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1358 LocalReturnLength
= (ULONG_PTR
)p
-
1359 (ULONG_PTR
)ObjectNameInfo
+
1360 LocalFileInfo
->FileNameLength
;
1362 /* Write the Name and null-terminate it */
1363 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1364 p
+= (FileLength
/ sizeof(WCHAR
));
1366 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1368 /* Return the length needed */
1369 *ReturnLength
= LocalReturnLength
;
1371 /* Setup the length and maximum length */
1372 FileLength
= (ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
;
1373 ObjectNameInfo
->Name
.Length
= FileLength
- sizeof(OBJECT_NAME_INFORMATION
);
1374 ObjectNameInfo
->Name
.MaximumLength
= ObjectNameInfo
->Name
.Length
+
1375 sizeof(UNICODE_NULL
);
1377 /* Free buffer and return */
1378 ExFreePool(LocalInfo
);
1384 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1385 IN PVOID ObjectBody
,
1386 IN ACCESS_MASK GrantedAccess
,
1387 IN ULONG HandleCount
,
1388 IN ULONG SystemHandleCount
)
1390 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1393 PIO_STACK_LOCATION StackPtr
;
1395 PDEVICE_OBJECT DeviceObject
;
1397 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1399 /* Check if the file is locked and has more then one handle opened */
1400 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1402 DPRINT1("We need to unlock this file!\n");
1406 /* Make sure this is the last handle */
1407 if (SystemHandleCount
!= 1) return;
1409 /* Check if this is a direct open or not */
1410 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1412 /* Get the attached device */
1413 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1417 /* Get the FO's device */
1418 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1421 /* Set the handle created flag */
1422 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1424 /* Check if this is a sync FO and lock it */
1425 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1427 /* Clear and set up Events */
1428 KeClearEvent(&FileObject
->Event
);
1429 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1431 /* Allocate an IRP */
1432 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1436 Irp
->UserEvent
= &Event
;
1437 Irp
->UserIosb
= &Irp
->IoStatus
;
1438 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1439 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1440 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1441 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1443 /* Set up Stack Pointer Data */
1444 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1445 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1446 StackPtr
->FileObject
= FileObject
;
1449 IopQueueIrpToThread(Irp
);
1451 /* Update operation counts */
1452 IopUpdateOperationCount(IopOtherTransfer
);
1454 /* Call the FS Driver */
1455 Status
= IoCallDriver(DeviceObject
, Irp
);
1456 if (Status
== STATUS_PENDING
)
1458 /* Wait for completion */
1459 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1462 /* Unqueue the IRP */
1463 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1464 IopUnQueueIrpFromThread(Irp
);
1465 KeLowerIrql(OldIrql
);
1470 /* Release the lock if we were holding it */
1471 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1476 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1477 IN FILE_INFORMATION_CLASS FileInformationClass
,
1478 IN ULONG FileInformationSize
,
1479 OUT PVOID FileInformation
)
1481 NTSTATUS Status
= STATUS_SUCCESS
;
1482 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1483 DUMMY_FILE_OBJECT DummyFileObject
;
1484 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1486 OPEN_PACKET OpenPacket
;
1489 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
1491 /* Check if the caller was user mode */
1492 if (AccessMode
!= KernelMode
)
1494 /* Protect probe in SEH */
1497 /* Probe the buffer */
1498 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
1502 /* Get the exception code */
1503 Status
= _SEH_GetExceptionCode();
1507 /* Fail on exception */
1508 if (!NT_SUCCESS(Status
))return Status
;
1511 /* Check if this is a basic or full request */
1512 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
1514 /* Setup the Open Packet */
1515 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1516 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1517 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1518 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
1519 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
1520 OpenPacket
.Disposition
= FILE_OPEN
;
1521 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
1522 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
1523 (AccessMode
!= KernelMode
) ?
1524 &NetworkOpenInfo
: FileInformation
;
1525 OpenPacket
.QueryOnly
= TRUE
;
1526 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
1527 OpenPacket
.DummyFileObject
= &DummyFileObject
;
1529 /* Update the operation count */
1530 IopUpdateOperationCount(IopOtherTransfer
);
1533 * Attempt opening the file. This will call the I/O Parse Routine for
1534 * the File Object (IopParseDevice) which will use the dummy file obejct
1535 * send the IRP to its device object. Note that we have two statuses
1536 * to worry about: the Object Manager's status (in Status) and the I/O
1537 * status, which is in the Open Packet's Final Status, and determined
1538 * by the Parse Check member.
1540 Status
= ObOpenObjectByName(ObjectAttributes
,
1544 FILE_READ_ATTRIBUTES
,
1547 if (OpenPacket
.ParseCheck
!= TRUE
)
1554 /* Use the Io status */
1555 Status
= OpenPacket
.FinalStatus
;
1558 /* Check if we were succesful and this was user mode and a full query */
1559 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
1561 /* Enter SEH for copy */
1564 /* Copy the buffer back */
1565 RtlCopyMemory(FileInformation
,
1567 FileInformationSize
);
1571 /* Get exception code */
1572 Status
= _SEH_GetExceptionCode();
1581 /* FUNCTIONS *****************************************************************/
1588 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
1590 IN BOOLEAN SetOperation
)
1593 return STATUS_NOT_IMPLEMENTED
;
1601 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
1602 IN ULONG QuotaLength
,
1603 OUT PULONG ErrorOffset
)
1606 return STATUS_NOT_IMPLEMENTED
;
1614 IoCreateFile(OUT PHANDLE FileHandle
,
1615 IN ACCESS_MASK DesiredAccess
,
1616 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1617 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1618 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1619 IN ULONG FileAttributes
,
1620 IN ULONG ShareAccess
,
1621 IN ULONG Disposition
,
1622 IN ULONG CreateOptions
,
1623 IN PVOID EaBuffer OPTIONAL
,
1625 IN CREATE_FILE_TYPE CreateFileType
,
1626 IN PVOID ExtraCreateParameters OPTIONAL
,
1629 KPROCESSOR_MODE AccessMode
;
1630 HANDLE LocalHandle
= 0;
1631 LARGE_INTEGER SafeAllocationSize
;
1632 PVOID SystemEaBuffer
= NULL
;
1633 NTSTATUS Status
= STATUS_SUCCESS
;
1634 OPEN_PACKET OpenPacket
;
1636 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
1638 /* Check if we have no parameter checking to do */
1639 if (Options
& IO_NO_PARAMETER_CHECKING
)
1641 /* Then force kernel-mode access to avoid checks */
1642 AccessMode
= KernelMode
;
1646 /* Otherwise, use the actual mode */
1647 AccessMode
= ExGetPreviousMode();
1650 /* Check if the call came from user mode */
1651 if (AccessMode
!= KernelMode
)
1655 ProbeForWriteHandle(FileHandle
);
1656 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1659 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
1663 SafeAllocationSize
.QuadPart
= 0;
1666 if ((EaBuffer
) && (EaLength
))
1668 ProbeForRead(EaBuffer
,
1672 /* marshal EaBuffer */
1673 SystemEaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1678 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1682 RtlCopyMemory(SystemEaBuffer
, EaBuffer
, EaLength
);
1687 Status
= _SEH_GetExceptionCode();
1691 if(!NT_SUCCESS(Status
)) return Status
;
1695 /* Check if this is a device attach */
1696 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
1698 /* Set the flag properly */
1699 Options
|= IO_ATTACH_DEVICE
;
1700 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
1703 /* Check if we have allocation size */
1707 SafeAllocationSize
= *AllocationSize
;
1711 /* Otherwise, no size */
1712 SafeAllocationSize
.QuadPart
= 0;
1715 /* Check if we have an EA packet */
1716 if ((EaBuffer
) && (EaLength
))
1718 /* Allocate the kernel copy */
1719 SystemEaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1722 if (!SystemEaBuffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1725 RtlCopyMemory(SystemEaBuffer
, EaBuffer
, EaLength
);
1727 /* Validate the buffer */
1728 Status
= IoCheckEaBufferValidity(SystemEaBuffer
,
1731 if (!NT_SUCCESS(Status
))
1733 /* FIXME: Fail once function is implemented */
1738 /* Setup the Open Packet */
1739 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1740 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1741 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1742 OpenPacket
.OriginalAttributes
= *ObjectAttributes
;
1743 OpenPacket
.AllocationSize
= SafeAllocationSize
;
1744 OpenPacket
.CreateOptions
= CreateOptions
;
1745 OpenPacket
.FileAttributes
= FileAttributes
;
1746 OpenPacket
.ShareAccess
= ShareAccess
;
1747 OpenPacket
.EaBuffer
= SystemEaBuffer
;
1748 OpenPacket
.EaLength
= EaLength
;
1749 OpenPacket
.Options
= Options
;
1750 OpenPacket
.Disposition
= Disposition
;
1751 OpenPacket
.CreateFileType
= CreateFileType
;
1752 OpenPacket
.MailslotOrPipeParameters
= ExtraCreateParameters
;
1754 /* Update the operation count */
1755 IopUpdateOperationCount(IopOtherTransfer
);
1758 * Attempt opening the file. This will call the I/O Parse Routine for
1759 * the File Object (IopParseDevice) which will create the object and
1760 * send the IRP to its device object. Note that we have two statuses
1761 * to worry about: the Object Manager's status (in Status) and the I/O
1762 * status, which is in the Open Packet's Final Status, and determined
1763 * by the Parse Check member.
1765 Status
= ObOpenObjectByName(ObjectAttributes
,
1773 /* Free the EA Buffer */
1774 if (OpenPacket
.EaBuffer
) ExFreePool(OpenPacket
.EaBuffer
);
1776 /* Now check for Ob or Io failure */
1777 if (!(NT_SUCCESS(Status
)) || (OpenPacket
.ParseCheck
!= TRUE
))
1779 /* Check if Ob thinks well went well */
1780 if (NT_SUCCESS(Status
))
1783 * Tell it otherwise. Because we didn't use an ObjectType,
1784 * it incorrectly returned us a handle to God knows what.
1786 ZwClose(LocalHandle
);
1787 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
1790 /* Now check the Io status */
1791 if (!NT_SUCCESS(OpenPacket
.FinalStatus
))
1793 /* Use this status instead of Ob's */
1794 Status
= OpenPacket
.FinalStatus
;
1796 /* Check if it was only a warning */
1797 if (NT_WARNING(Status
))
1799 /* Protect write with SEH */
1802 /* In this case, we copy the I/O Status back */
1803 IoStatusBlock
->Information
= OpenPacket
.Information
;
1804 IoStatusBlock
->Status
= OpenPacket
.FinalStatus
;
1808 /* Get exception code */
1809 Status
= _SEH_GetExceptionCode();
1814 else if ((OpenPacket
.FileObject
) && (OpenPacket
.ParseCheck
!= 1))
1817 * This can happen in the very bizarre case where the parse routine
1818 * actually executed more then once (due to a reparse) and ended
1819 * up failing after already having created the File Object.
1821 if (OpenPacket
.FileObject
->FileName
.Length
)
1823 /* It had a name, free it */
1824 ExFreePool(OpenPacket
.FileObject
->FileName
.Buffer
);
1827 /* Clear the device object to invalidate the FO, and dereference */
1828 OpenPacket
.FileObject
->DeviceObject
= NULL
;
1829 ObDereferenceObject(OpenPacket
.FileObject
);
1834 /* We reached success and have a valid file handle */
1835 OpenPacket
.FileObject
->Flags
|= FO_HANDLE_CREATED
;
1837 /* Enter SEH for write back */
1840 /* Write back the handle and I/O Status */
1841 *FileHandle
= LocalHandle
;
1842 IoStatusBlock
->Information
= OpenPacket
.Information
;
1843 IoStatusBlock
->Status
= OpenPacket
.FinalStatus
;
1845 /* Get the Io status */
1846 Status
= OpenPacket
.FinalStatus
;
1850 /* Get the exception status */
1851 Status
= _SEH_GetExceptionCode();
1856 /* Check if we were 100% successful */
1857 if ((OpenPacket
.ParseCheck
== TRUE
) && (OpenPacket
.FileObject
))
1859 /* Dereference the File Object */
1860 ObDereferenceObject(OpenPacket
.FileObject
);
1872 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1873 IN ACCESS_MASK DesiredAccess
,
1874 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1875 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1876 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1877 IN ULONG FileAttributes
,
1878 IN ULONG ShareAccess
,
1879 IN ULONG Disposition
,
1880 IN ULONG CreateOptions
,
1881 IN PVOID EaBuffer OPTIONAL
,
1883 IN CREATE_FILE_TYPE CreateFileType
,
1884 IN PVOID ExtraCreateParameters OPTIONAL
,
1886 IN PVOID DeviceObject
)
1889 return STATUS_NOT_IMPLEMENTED
;
1897 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1898 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1899 OUT PHANDLE FileObjectHandle OPTIONAL
)
1901 PFILE_OBJECT CreatedFileObject
;
1904 OBJECT_ATTRIBUTES ObjectAttributes
;
1906 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
1908 /* Choose Device Object */
1909 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1911 /* Reference the device object and initialize attributes */
1912 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
1913 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
1915 /* Create the File Object */
1916 Status
= ObCreateObject(KernelMode
,
1921 sizeof(FILE_OBJECT
),
1922 sizeof(FILE_OBJECT
),
1924 (PVOID
*)&CreatedFileObject
);
1925 if (!NT_SUCCESS(Status
))
1928 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
1929 ExRaiseStatus(Status
);
1932 /* Set File Object Data */
1933 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
1934 CreatedFileObject
->DeviceObject
= DeviceObject
;
1935 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1936 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
1937 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
1939 /* Initialize the wait event */
1940 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
1942 /* Insert it to create a handle for it */
1943 Status
= ObInsertObject(CreatedFileObject
,
1947 (PVOID
*)&CreatedFileObject
,
1949 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
1951 /* Set the handle created flag */
1952 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
1953 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
1955 /* Check if we have a VPB */
1956 if (DeviceObject
->Vpb
)
1959 InterlockedIncrement(&DeviceObject
->Vpb
->ReferenceCount
);
1962 /* Check if the caller wants the handle */
1963 if (FileObjectHandle
)
1966 *FileObjectHandle
= FileHandle
;
1967 ObDereferenceObject(CreatedFileObject
);
1971 /* Otherwise, close it */
1972 ObCloseHandle(FileHandle
, KernelMode
);
1975 /* Return the file object */
1976 return CreatedFileObject
;
1984 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
1985 IN PDEVICE_OBJECT DeviceObject
)
1987 /* Call the newer function */
1988 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
1996 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1997 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1999 PFILE_OBJECT CreatedFileObject
;
2001 OBJECT_ATTRIBUTES ObjectAttributes
;
2003 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2005 /* Choose Device Object */
2006 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2008 /* Reference the device object and initialize attributes */
2009 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2010 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2012 /* Create the File Object */
2013 Status
= ObCreateObject(KernelMode
,
2018 sizeof(FILE_OBJECT
),
2019 sizeof(FILE_OBJECT
),
2021 (PVOID
*)&CreatedFileObject
);
2022 if (!NT_SUCCESS(Status
))
2025 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2026 ExRaiseStatus(Status
);
2029 /* Set File Object Data */
2030 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2031 CreatedFileObject
->DeviceObject
= DeviceObject
;
2032 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2033 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2034 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2036 /* Initialize the wait event */
2037 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2039 /* Destroy create information */
2040 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2042 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2044 /* Set the handle created flag */
2045 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2046 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2048 /* Check if we have a VPB */
2049 if (DeviceObject
->Vpb
)
2052 InterlockedIncrement(&DeviceObject
->Vpb
->ReferenceCount
);
2055 /* Return the file object */
2056 return CreatedFileObject
;
2064 IoGetFileObjectGenericMapping(VOID
)
2066 /* Return the mapping */
2067 return &IopFileMapping
;
2075 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2077 /* Return the flag status */
2078 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
2086 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2087 IN ACCESS_MASK DesiredAccess
,
2088 IN ULONG OpenOptions
,
2089 OUT PIO_STATUS_BLOCK IoStatus
,
2090 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2093 DUMMY_FILE_OBJECT DummyFileObject
;
2095 OPEN_PACKET OpenPacket
;
2097 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2099 /* Setup the Open Packet */
2100 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2101 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2102 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2103 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2104 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2105 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2106 OpenPacket
.Disposition
= FILE_OPEN
;
2107 OpenPacket
.NetworkInformation
= Buffer
;
2108 OpenPacket
.QueryOnly
= TRUE
;
2109 OpenPacket
.FullAttributes
= TRUE
;
2110 OpenPacket
.DummyFileObject
= &DummyFileObject
;
2113 * Attempt opening the file. This will call the I/O Parse Routine for
2114 * the File Object (IopParseDevice) which will use the dummy file obejct
2115 * send the IRP to its device object. Note that we have two statuses
2116 * to worry about: the Object Manager's status (in Status) and the I/O
2117 * status, which is in the Open Packet's Final Status, and determined
2118 * by the Parse Check member.
2120 Status
= ObOpenObjectByName(ObjectAttributes
,
2127 if (OpenPacket
.ParseCheck
!= TRUE
)
2130 IoStatus
->Status
= Status
;
2134 /* Use the Io status */
2135 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2136 IoStatus
->Information
= OpenPacket
.Information
;
2139 /* Return success */
2148 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2149 OUT PSHARE_ACCESS ShareAccess
)
2153 /* Check if the file has an extension */
2154 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2156 /* Check if caller specified to ignore access checks */
2157 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2159 /* Don't update share access */
2164 /* Otherwise, check if there's any access present */
2165 if ((FileObject
->ReadAccess
) ||
2166 (FileObject
->WriteAccess
) ||
2167 (FileObject
->DeleteAccess
))
2169 /* Increase the open count */
2170 ShareAccess
->OpenCount
++;
2172 /* Add new share access */
2173 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2174 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2175 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2176 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2177 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2178 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2187 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2188 IN ULONG DesiredShareAccess
,
2189 IN PFILE_OBJECT FileObject
,
2190 IN PSHARE_ACCESS ShareAccess
,
2194 BOOLEAN WriteAccess
;
2195 BOOLEAN DeleteAccess
;
2197 BOOLEAN SharedWrite
;
2198 BOOLEAN SharedDelete
;
2201 /* Get access masks */
2202 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2203 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2204 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2206 /* Set them in the file object */
2207 FileObject
->ReadAccess
= ReadAccess
;
2208 FileObject
->WriteAccess
= WriteAccess
;
2209 FileObject
->DeleteAccess
= DeleteAccess
;
2211 /* Check if the file has an extension */
2212 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2214 /* Check if caller specified to ignore access checks */
2215 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2217 /* Don't check share access */
2218 return STATUS_SUCCESS
;
2222 /* Check if we have any access */
2223 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2225 /* Get shared access masks */
2226 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2227 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2228 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2231 FileObject
->SharedRead
= SharedRead
;
2232 FileObject
->SharedWrite
= SharedWrite
;
2233 FileObject
->SharedDelete
= SharedDelete
;
2235 /* Check if the shared access is violated */
2237 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2239 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2241 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2242 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2243 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2244 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2246 /* Sharing violation, fail */
2247 return STATUS_SHARING_VIOLATION
;
2250 /* It's not, check if caller wants us to update it */
2253 /* Increase open count */
2254 ShareAccess
->OpenCount
++;
2256 /* Update shared access */
2257 ShareAccess
->Readers
+= ReadAccess
;
2258 ShareAccess
->Writers
+= WriteAccess
;
2259 ShareAccess
->Deleters
+= DeleteAccess
;
2260 ShareAccess
->SharedRead
+= SharedRead
;
2261 ShareAccess
->SharedWrite
+= SharedWrite
;
2262 ShareAccess
->SharedDelete
+= SharedDelete
;
2266 /* Validation successful */
2267 return STATUS_SUCCESS
;
2275 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2276 IN PSHARE_ACCESS ShareAccess
)
2280 /* Check if the file has an extension */
2281 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2283 /* Check if caller specified to ignore access checks */
2284 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2286 /* Don't update share access */
2291 /* Otherwise, check if there's any access present */
2292 if ((FileObject
->ReadAccess
) ||
2293 (FileObject
->WriteAccess
) ||
2294 (FileObject
->DeleteAccess
))
2296 /* Decrement the open count */
2297 ShareAccess
->OpenCount
--;
2299 /* Remove share access */
2300 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
2301 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
2302 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
2303 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
2304 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
2305 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
2314 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
2315 IN ULONG DesiredShareAccess
,
2316 IN PFILE_OBJECT FileObject
,
2317 OUT PSHARE_ACCESS ShareAccess
)
2320 BOOLEAN WriteAccess
;
2321 BOOLEAN DeleteAccess
;
2323 BOOLEAN SharedWrite
;
2324 BOOLEAN SharedDelete
;
2325 BOOLEAN Update
= TRUE
;
2328 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2329 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2330 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2332 /* Check if the file has an extension */
2333 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2335 /* Check if caller specified to ignore access checks */
2336 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2338 /* Don't update share access */
2343 /* Update basic access */
2344 FileObject
->ReadAccess
= ReadAccess
;
2345 FileObject
->WriteAccess
= WriteAccess
;
2346 FileObject
->DeleteAccess
= DeleteAccess
;
2348 /* Check if we have no access as all */
2349 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
2351 /* Check if we need to update the structure */
2352 if (!Update
) return;
2354 /* Otherwise, clear data */
2355 ShareAccess
->OpenCount
= 0;
2356 ShareAccess
->Readers
= 0;
2357 ShareAccess
->Writers
= 0;
2358 ShareAccess
->Deleters
= 0;
2359 ShareAccess
->SharedRead
= 0;
2360 ShareAccess
->SharedWrite
= 0;
2361 ShareAccess
->SharedDelete
= 0;
2365 /* Calculate shared access */
2366 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2367 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2368 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2370 /* Set it in the FO */
2371 FileObject
->SharedRead
= SharedRead
;
2372 FileObject
->SharedWrite
= SharedWrite
;
2373 FileObject
->SharedDelete
= SharedDelete
;
2375 /* Check if we need to update the structure */
2376 if (!Update
) return;
2378 /* Otherwise, set data */
2379 ShareAccess
->OpenCount
= 1;
2380 ShareAccess
->Readers
= ReadAccess
;
2381 ShareAccess
->Writers
= WriteAccess
;
2382 ShareAccess
->Deleters
= DeleteAccess
;
2383 ShareAccess
->SharedRead
= SharedRead
;
2384 ShareAccess
->SharedWrite
= SharedWrite
;
2385 ShareAccess
->SharedDelete
= SharedDelete
;
2394 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
2395 IN PFILE_OBJECT FileObject
)
2405 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
2406 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
2409 return STATUS_NOT_IMPLEMENTED
;
2417 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
2421 return STATUS_NOT_IMPLEMENTED
;
2429 NtCreateFile(PHANDLE FileHandle
,
2430 ACCESS_MASK DesiredAccess
,
2431 POBJECT_ATTRIBUTES ObjectAttributes
,
2432 PIO_STATUS_BLOCK IoStatusBlock
,
2433 PLARGE_INTEGER AllocateSize
,
2434 ULONG FileAttributes
,
2436 ULONG CreateDisposition
,
2437 ULONG CreateOptions
,
2441 /* Call the I/O Function */
2442 return IoCreateFile(FileHandle
,
2460 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
2461 IN ACCESS_MASK DesiredAccess
,
2462 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2463 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2464 IN ULONG CreateOptions
,
2465 IN ULONG MailslotQuota
,
2466 IN ULONG MaxMessageSize
,
2467 IN PLARGE_INTEGER TimeOut
)
2469 MAILSLOT_CREATE_PARAMETERS Buffer
;
2470 NTSTATUS Status
= STATUS_SUCCESS
;
2473 /* Check for Timeout */
2476 /* check if the call came from user mode */
2477 if (KeGetPreviousMode() != KernelMode
)
2479 /* Enter SEH for Probe */
2482 /* Probe the timeout */
2483 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
2487 /* Get exception code */
2488 Status
= _SEH_GetExceptionCode();
2492 /* Return the exception */
2493 if (!NT_SUCCESS(Status
)) return Status
;
2497 /* Otherwise, capture directly */
2498 Buffer
.ReadTimeout
= *TimeOut
;
2501 /* Set the correct setting */
2502 Buffer
.TimeoutSpecified
= TRUE
;
2506 /* Tell the FSD we don't have a timeout */
2507 Buffer
.TimeoutSpecified
= FALSE
;
2511 Buffer
.MailslotQuota
= MailslotQuota
;
2512 Buffer
.MaximumMessageSize
= MaxMessageSize
;
2515 return IoCreateFile(FileHandle
,
2521 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2526 CreateFileTypeMailslot
,
2533 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
2534 IN ACCESS_MASK DesiredAccess
,
2535 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2536 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2537 IN ULONG ShareAccess
,
2538 IN ULONG CreateDisposition
,
2539 IN ULONG CreateOptions
,
2540 IN ULONG NamedPipeType
,
2542 IN ULONG CompletionMode
,
2543 IN ULONG MaximumInstances
,
2544 IN ULONG InboundQuota
,
2545 IN ULONG OutboundQuota
,
2546 IN PLARGE_INTEGER DefaultTimeout
)
2548 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
2549 NTSTATUS Status
= STATUS_SUCCESS
;
2552 /* Check for Timeout */
2555 /* check if the call came from user mode */
2556 if (KeGetPreviousMode() != KernelMode
)
2558 /* Enter SEH for Probe */
2561 /* Probe the timeout */
2562 Buffer
.DefaultTimeout
=
2563 ProbeForReadLargeInteger(DefaultTimeout
);
2567 /* Get exception code */
2568 Status
= _SEH_GetExceptionCode();
2572 /* Return the exception */
2573 if (!NT_SUCCESS(Status
)) return Status
;
2577 /* Otherwise, capture directly */
2578 Buffer
.DefaultTimeout
= *DefaultTimeout
;
2581 /* Set the correct setting */
2582 Buffer
.TimeoutSpecified
= TRUE
;
2586 /* Tell the FSD we don't have a timeout */
2587 Buffer
.TimeoutSpecified
= FALSE
;
2591 Buffer
.NamedPipeType
= NamedPipeType
;
2592 Buffer
.ReadMode
= ReadMode
;
2593 Buffer
.CompletionMode
= CompletionMode
;
2594 Buffer
.MaximumInstances
= MaximumInstances
;
2595 Buffer
.InboundQuota
= InboundQuota
;
2596 Buffer
.OutboundQuota
= OutboundQuota
;
2599 return IoCreateFile(FileHandle
,
2610 CreateFileTypeNamedPipe
,
2617 NtFlushWriteBuffer(VOID
)
2621 /* Call the kernel */
2622 KeFlushWriteBuffer();
2623 return STATUS_SUCCESS
;
2631 NtOpenFile(OUT PHANDLE FileHandle
,
2632 IN ACCESS_MASK DesiredAccess
,
2633 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2634 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2635 IN ULONG ShareAccess
,
2636 IN ULONG OpenOptions
)
2638 /* Call the I/O Function */
2639 return IoCreateFile(FileHandle
,
2657 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2658 OUT PFILE_BASIC_INFORMATION FileInformation
)
2660 /* Call the internal helper API */
2661 return IopQueryAttributesFile(ObjectAttributes
,
2662 FileBasicInformation
,
2663 sizeof(FILE_BASIC_INFORMATION
),
2669 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2670 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2672 /* Call the internal helper API */
2673 return IopQueryAttributesFile(ObjectAttributes
,
2674 FileNetworkOpenInformation
,
2675 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2680 * @name NtCancelIoFile
2682 * Cancel all pending I/O operations in the current thread for specified
2686 * Handle to file object to cancel requests for. No specific
2687 * access rights are needed.
2688 * @param IoStatusBlock
2689 * Pointer to status block which is filled with final completition
2690 * status on successful return.
2698 NtCancelIoFile(IN HANDLE FileHandle
,
2699 OUT PIO_STATUS_BLOCK IoStatusBlock
)
2701 PFILE_OBJECT FileObject
;
2705 BOOLEAN OurIrpsInList
= FALSE
;
2706 LARGE_INTEGER Interval
;
2707 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2708 NTSTATUS Status
= STATUS_SUCCESS
;
2709 PLIST_ENTRY ListHead
, NextEntry
;
2711 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2713 /* Check the previous mode */
2714 if (PreviousMode
!= KernelMode
)
2716 /* Enter SEH for probing */
2719 /* Probe the I/O Status Block */
2720 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2724 /* Get the exception code */
2725 Status
= _SEH_GetExceptionCode();
2729 /* Return exception code on failure */
2730 if (!NT_SUCCESS(Status
)) return Status
;
2733 /* Reference the file object */
2734 Status
= ObReferenceObjectByHandle(FileHandle
,
2738 (PVOID
*)&FileObject
,
2740 if (!NT_SUCCESS(Status
)) return Status
;
2742 /* IRP cancellations are synchronized at APC_LEVEL. */
2743 OldIrql
= KfRaiseIrql(APC_LEVEL
);
2745 /* Get the current thread */
2746 Thread
= PsGetCurrentThread();
2748 /* Update the operation counts */
2749 IopUpdateOperationCount(IopOtherTransfer
);
2752 ListHead
= &Thread
->IrpList
;
2753 NextEntry
= ListHead
->Flink
;
2754 while (ListHead
!= NextEntry
)
2756 /* Get the IRP and check if the File Object matches */
2757 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
2758 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
2760 /* Cancel this IRP and keep looping */
2762 OurIrpsInList
= TRUE
;
2765 /* Go to the next entry */
2766 NextEntry
= NextEntry
->Flink
;
2769 /* Lower the IRQL */
2770 KfLowerIrql(OldIrql
);
2772 /* Check if we had found an IRP */
2775 /* Setup a 10ms wait */
2776 Interval
.QuadPart
= -100000;
2779 while (OurIrpsInList
)
2782 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
2783 OurIrpsInList
= FALSE
;
2786 OldIrql
= KfRaiseIrql(APC_LEVEL
);
2788 /* Now loop the list again */
2789 NextEntry
= ListHead
->Flink
;
2790 while (NextEntry
!= ListHead
)
2792 /* Get the IRP and check if the File Object matches */
2793 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
2794 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
2797 OurIrpsInList
= TRUE
;
2801 /* Go to the next entry */
2802 NextEntry
= NextEntry
->Flink
;
2805 /* Lower the IRQL */
2806 KeLowerIrql(OldIrql
);
2810 /* Enter SEH for writing back the I/O Status */
2814 IoStatusBlock
->Status
= STATUS_SUCCESS
;
2815 IoStatusBlock
->Information
= 0;
2823 /* Dereference the file object and return success */
2824 ObDereferenceObject(FileObject
);
2825 return STATUS_SUCCESS
;
2833 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
2836 DUMMY_FILE_OBJECT DummyFileObject
;
2838 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
2839 OPEN_PACKET OpenPacket
;
2841 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
2843 /* Setup the Open Packet */
2844 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2845 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2846 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2847 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
2848 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
2851 OpenPacket
.Disposition
= FILE_OPEN
;
2852 OpenPacket
.DeleteOnly
= TRUE
;
2853 OpenPacket
.DummyFileObject
= &DummyFileObject
;
2855 /* Update the operation counts */
2856 IopUpdateOperationCount(IopOtherTransfer
);
2859 * Attempt opening the file. This will call the I/O Parse Routine for
2860 * the File Object (IopParseDevice) which will use the dummy file obejct
2861 * send the IRP to its device object. Note that we have two statuses
2862 * to worry about: the Object Manager's status (in Status) and the I/O
2863 * status, which is in the Open Packet's Final Status, and determined
2864 * by the Parse Check member.
2866 Status
= ObOpenObjectByName(ObjectAttributes
,
2873 if (OpenPacket
.ParseCheck
!= TRUE
) return Status
;
2875 /* Retrn the Io status */
2876 return OpenPacket
.FinalStatus
;