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 ((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"))) &&
414 DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
415 DesiredAccess
& ~(SYNCHRONIZE
|
416 FILE_READ_ATTRIBUTES
|
418 ACCESS_SYSTEM_SECURITY
|
424 /* Check if we have a related FO that wasn't a direct open */
425 if ((OpenPacket
->RelatedFileObject
) &&
426 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
428 /* The device object is the one we were given */
429 DeviceObject
= ParseObject
;
431 /* Check if the related FO had a VPB */
432 if (OpenPacket
->RelatedFileObject
->Vpb
)
434 /* Yes, remember it */
435 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
438 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
443 /* The device object is the one we were given */
444 DeviceObject
= OriginalDeviceObject
;
446 /* Check if it has a VPB */
447 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
449 /* Check if the VPB is mounted, and mount it */
450 Vpb
= IopCheckVpbMounted(OpenPacket
,
451 OriginalDeviceObject
,
454 if (!Vpb
) return Status
;
456 /* Get the VPB's device object */
457 DeviceObject
= Vpb
->DeviceObject
;
460 /* Check if there's an attached device */
461 if (DeviceObject
->AttachedDevice
)
463 /* Get the attached device */
464 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
468 /* Check if this is a secure FSD */
469 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
470 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
473 DPRINT("Fix Secure FSD support!!!\n");
476 /* Allocate the IRP */
477 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
480 /* Dereference the device and VPB, then fail */
481 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
482 if (Vpb
) IopDereferenceVpb(Vpb
);
483 return STATUS_INSUFFICIENT_RESOURCES
;
486 /* Now set the IRP data */
487 Irp
->RequestorMode
= AccessMode
;
488 Irp
->Flags
= IRP_CREATE_OPERATION
|
489 IRP_SYNCHRONOUS_API
|
490 IRP_DEFER_IO_COMPLETION
;
491 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
492 Irp
->UserIosb
= &IoStatusBlock
;
493 Irp
->MdlAddress
= NULL
;
494 Irp
->PendingReturned
= FALSE
;
495 Irp
->UserEvent
= NULL
;
497 Irp
->CancelRoutine
= NULL
;
498 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
500 /* Setup the security context */
501 SecurityContext
.SecurityQos
= SecurityQos
;
502 SecurityContext
.AccessState
= AccessState
;
503 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
504 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
506 /* Get the I/O Stack location */
507 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
508 StackLoc
->Control
= 0;
510 /* Check what kind of file this is */
511 switch (OpenPacket
->CreateFileType
)
514 case CreateFileTypeNone
:
516 /* Set the major function and EA Length */
517 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
518 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
521 StackLoc
->Flags
= (UCHAR
)OpenPacket
->Options
;
522 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ?
523 SL_CASE_SENSITIVE
: 0;
527 case CreateFileTypeNamedPipe
:
529 /* Set the named pipe MJ and set the parameters */
530 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
531 StackLoc
->Parameters
.CreatePipe
.Parameters
=
532 OpenPacket
->MailslotOrPipeParameters
;
536 case CreateFileTypeMailslot
:
538 /* Set the mailslot MJ and set the parameters */
539 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
540 StackLoc
->Parameters
.CreateMailslot
.Parameters
=
541 OpenPacket
->MailslotOrPipeParameters
;
545 /* Set the common data */
546 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
547 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
548 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
549 (OpenPacket
->CreateOptions
&
551 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
552 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
553 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
555 /* Check if we really need to create an object */
558 /* Create the actual file object */
559 InitializeObjectAttributes(&ObjectAttributes
,
564 Status
= ObCreateObject(KernelMode
,
572 (PVOID
*)&FileObject
);
573 if (!NT_SUCCESS(Status
))
575 /* Create failed, free the IRP */
578 /* Dereference the device and VPB */
579 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
580 if (Vpb
) IopDereferenceVpb(Vpb
);
582 /* We failed, return status */
583 OpenPacket
->FinalStatus
= Status
;
587 /* Clear the file object */
588 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
590 /* Check if this is Synch I/O */
591 if (OpenPacket
->CreateOptions
&
592 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
594 /* Set the synch flag */
595 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
597 /* Check if it's also alertable */
598 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
600 /* It is, set the alertable flag */
601 FileObject
->Flags
|= FO_ALERTABLE_IO
;
605 /* Check if this is synch I/O */
606 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
608 /* Initialize the event */
609 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
612 /* Check if the caller requested no intermediate buffering */
613 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
615 /* Set the correct flag for the FSD to read */
616 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
619 /* Check if the caller requested write through support */
620 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
622 /* Set the correct flag for the FSD to read */
623 FileObject
->Flags
|= FO_WRITE_THROUGH
;
626 /* Check if the caller says the file will be only read sequentially */
627 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
629 /* Set the correct flag for the FSD to read */
630 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
633 /* Check if the caller believes the file will be only read randomly */
634 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
636 /* Set the correct flag for the FSD to read */
637 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
642 /* Use the dummy object instead */
643 DummyFileObject
= OpenPacket
->DummyFileObject
;
644 RtlZeroMemory(DummyFileObject
, sizeof(DUMMY_FILE_OBJECT
));
647 FileObject
= (PFILE_OBJECT
)&DummyFileObject
->ObjectHeader
.Body
;
648 DummyFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
649 DummyFileObject
->ObjectHeader
.PointerCount
= 1;
652 /* Setup the file header */
653 FileObject
->Type
= IO_TYPE_FILE
;
654 FileObject
->Size
= sizeof(FILE_OBJECT
);
655 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
656 FileObject
->DeviceObject
= OriginalDeviceObject
;
658 /* Check if this is a direct device open */
659 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
661 /* Check if the caller wants case sensitivity */
662 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
664 /* Tell the driver about it */
665 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
668 /* Now set the file object */
669 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
670 StackLoc
->FileObject
= FileObject
;
672 /* Check if the file object has a name */
673 if (RemainingName
->Length
)
675 /* Setup the unicode string */
676 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
678 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
683 if (!FileObject
->FileName
.Buffer
)
685 /* Failed to allocate the name, free the IRP */
688 /* Dereference the device object and VPB */
689 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
690 if (Vpb
) IopDereferenceVpb(Vpb
);
692 /* Clear the FO and dereference it */
693 FileObject
->DeviceObject
= NULL
;
694 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
697 return STATUS_INSUFFICIENT_RESOURCES
;
702 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
704 /* Initialize the File Object event and set the FO */
705 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
706 OpenPacket
->FileObject
= FileObject
;
708 /* Queue the IRP and call the driver */
709 IopQueueIrpToThread(Irp
);
710 Status
= IoCallDriver(DeviceObject
, Irp
);
711 if (Status
== STATUS_PENDING
)
713 /* Wait for the driver to complete the create */
714 KeWaitForSingleObject(&FileObject
->Event
,
720 /* Get the new status */
721 Status
= IoStatusBlock
.Status
;
725 /* We'll have to complete it ourselves */
726 ASSERT(!Irp
->PendingReturned
);
727 ASSERT(!Irp
->MdlAddress
);
729 /* Completion happens at APC_LEVEL */
730 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
732 /* Get the new I/O Status block ourselves */
733 IoStatusBlock
= Irp
->IoStatus
;
734 Status
= IoStatusBlock
.Status
;
736 /* Manually signal the even, we can't have any waiters */
737 FileObject
->Event
.Header
.SignalState
= 1;
739 /* Now that we've signaled the events, de-associate the IRP */
740 IopUnQueueIrpFromThread(Irp
);
742 /* Check if the IRP had an input buffer */
743 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
744 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
746 /* Free it. A driver might've tacked one on */
747 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
750 /* Free the IRP and bring the IRQL back down */
752 KeLowerIrql(OldIrql
);
755 /* Copy the I/O Status */
756 OpenPacket
->Information
= IoStatusBlock
.Information
;
758 /* The driver failed to create the file */
759 if (!NT_SUCCESS(Status
))
761 /* Check if we have a name */
762 if (FileObject
->FileName
.Length
)
765 ExFreePool(FileObject
->FileName
.Buffer
);
766 FileObject
->FileName
.Length
= 0;
769 /* Clear its device object */
770 FileObject
->DeviceObject
= NULL
;
772 /* Save this now because the FO might go away */
773 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
776 /* Clear the file object in the open packet */
777 OpenPacket
->FileObject
= NULL
;
779 /* Dereference the file object */
780 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
782 /* Dereference the device object */
783 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
785 /* Unless the driver cancelled the open, dereference the VPB */
786 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpb(Vpb
);
788 /* Set the status and return */
789 OpenPacket
->FinalStatus
= Status
;
792 else if (Status
== STATUS_REPARSE
)
794 /* FIXME: We don't handle this at all! */
798 /* Get the owner of the File Object */
799 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
802 * It's possible that the device to whom we sent the IRP to
803 * isn't actually the device that ended opening the file object
806 if (OwnerDevice
!= DeviceObject
)
808 /* We have to de-reference the VPB we had associated */
809 if (Vpb
) IopDereferenceVpb(Vpb
);
811 /* And re-associate with the actual one */
812 Vpb
= FileObject
->Vpb
;
813 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
816 /* Make sure we are not using a dummy */
819 /* Check if this was a volume open */
820 if ((!(FileObject
->RelatedFileObject
) ||
821 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
822 !(FileObject
->FileName
.Length
))
824 /* All signs point to it, but make sure it was actually an FSD */
825 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
826 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
827 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
828 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
830 /* The owner device is an FSD, so this is a volume open for real */
831 FileObject
->Flags
|= FO_VOLUME_OPEN
;
835 /* Reference the object and set the parse check */
836 ObReferenceObject(FileObject
);
837 *Object
= FileObject
;
838 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
839 OpenPacket
->ParseCheck
= TRUE
;
840 return OpenPacket
->FinalStatus
;
844 /* Check if this was a query */
845 if (OpenPacket
->QueryOnly
)
847 /* Check if the caller wants basic info only */
848 if (!OpenPacket
->FullAttributes
)
850 /* Allocate the buffer */
851 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
852 sizeof(*FileBasicInfo
),
857 Status
= IoQueryFileInformation(FileObject
,
858 FileBasicInformation
,
859 sizeof(*FileBasicInfo
),
862 if (NT_SUCCESS(Status
))
865 RtlCopyMemory(OpenPacket
->BasicInformation
,
870 /* Free our buffer */
871 ExFreePool(FileBasicInfo
);
876 Status
= STATUS_INSUFFICIENT_RESOURCES
;
881 /* This is a full query */
882 Status
= IoQueryFileInformation(
884 FileNetworkOpenInformation
,
885 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
886 OpenPacket
->NetworkInformation
,
888 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
892 /* Delete the file object */
893 IopDeleteFile(FileObject
);
895 /* Clear out the file */
896 OpenPacket
->FileObject
= NULL
;
898 /* Set and return status */
899 OpenPacket
->FinalStatus
= Status
;
900 OpenPacket
->ParseCheck
= TRUE
;
907 IopParseFile(IN PVOID ParseObject
,
909 IN OUT PACCESS_STATE AccessState
,
910 IN KPROCESSOR_MODE AccessMode
,
912 IN OUT PUNICODE_STRING CompleteName
,
913 IN OUT PUNICODE_STRING RemainingName
,
914 IN OUT PVOID Context OPTIONAL
,
915 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
919 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
921 /* Validate the open packet */
922 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
924 /* Get the device object */
925 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
926 OpenPacket
->RelatedFileObject
= ParseObject
;
928 /* Call the main routine */
929 return IopParseDevice(DeviceObject
,
943 IopDeleteFile(IN PVOID ObjectBody
)
945 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
947 PIO_STACK_LOCATION StackPtr
;
950 PDEVICE_OBJECT DeviceObject
;
951 BOOLEAN DereferenceDone
= FALSE
;
954 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
956 /* Check if the file has a device object */
957 if (FileObject
->DeviceObject
)
959 /* Check if this is a direct open or not */
960 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
962 /* Get the attached device */
963 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
967 /* Use the file object's device object */
968 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
972 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
973 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
975 /* Check if the handle wasn't created yet */
976 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
978 /* Send the cleanup IRP */
979 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
982 /* Clear and set up Events */
983 KeClearEvent(&FileObject
->Event
);
984 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
986 /* Allocate an IRP */
987 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
991 Irp
->UserEvent
= &Event
;
992 Irp
->UserIosb
= &Irp
->IoStatus
;
993 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
994 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
995 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
997 /* Set up Stack Pointer Data */
998 StackPtr
= IoGetNextIrpStackLocation(Irp
);
999 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
1000 StackPtr
->FileObject
= FileObject
;
1003 IopQueueIrpToThread(Irp
);
1005 /* Get the VPB and check if this isn't a direct open */
1006 Vpb
= FileObject
->Vpb
;
1007 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1009 /* Dereference the VPB before the close */
1010 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1013 /* Check if the FS will never disappear by itself */
1014 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1016 /* Dereference it */
1017 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1018 DereferenceDone
= TRUE
;
1021 /* Call the FS Driver */
1022 Status
= IoCallDriver(DeviceObject
, Irp
);
1023 if (Status
== STATUS_PENDING
)
1025 /* Wait for completion */
1026 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1029 /* De-queue the IRP */
1030 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1031 IopUnQueueIrpFromThread(Irp
);
1032 KeLowerIrql(OldIrql
);
1037 /* Clear the file name */
1038 if (FileObject
->FileName
.Buffer
)
1040 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1041 FileObject
->FileName
.Buffer
= NULL
;
1044 /* Check if the FO had a completion port */
1045 if (FileObject
->CompletionContext
)
1048 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1049 ExFreePool(FileObject
->CompletionContext
);
1052 /* Check if dereference has been done yet */
1053 if (!DereferenceDone
)
1055 /* Dereference device object */
1056 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1063 IopSecurityFile(IN PVOID ObjectBody
,
1064 IN SECURITY_OPERATION_CODE OperationCode
,
1065 IN PSECURITY_INFORMATION SecurityInformation
,
1066 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1067 IN OUT PULONG BufferLength
,
1068 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1069 IN POOL_TYPE PoolType
,
1070 IN OUT PGENERIC_MAPPING GenericMapping
)
1072 IO_STATUS_BLOCK IoStatusBlock
;
1073 PIO_STACK_LOCATION StackPtr
;
1074 PFILE_OBJECT FileObject
;
1075 PDEVICE_OBJECT DeviceObject
;
1077 BOOLEAN LocalEvent
= FALSE
;
1079 NTSTATUS Status
= STATUS_SUCCESS
;
1081 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1083 /* Check if this is a device or file */
1084 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1087 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1093 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1095 /* Check if this is a direct open */
1096 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1098 /* Get the Device Object */
1099 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1103 /* Otherwise, use the direct device*/
1104 DeviceObject
= FileObject
->DeviceObject
;
1108 /* Check if the request was for a device object */
1109 if (!(FileObject
) ||
1110 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1111 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1113 /* Check what kind of request this was */
1114 if (OperationCode
== QuerySecurityDescriptor
)
1116 return SeQuerySecurityDescriptorInfo(SecurityInformation
,
1119 &DeviceObject
->SecurityDescriptor
);
1121 else if (OperationCode
== DeleteSecurityDescriptor
)
1123 /* Simply return success */
1124 return STATUS_SUCCESS
;
1126 else if (OperationCode
== AssignSecurityDescriptor
)
1128 /* Make absolutely sure this is a device object */
1129 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1131 /* Assign the Security Descriptor */
1132 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
1135 /* Return success */
1136 return STATUS_SUCCESS
;
1140 DPRINT1("FIXME: Set SD unimplemented for Devices\n");
1141 return STATUS_SUCCESS
;
1144 else if (OperationCode
== DeleteSecurityDescriptor
)
1146 /* Same as for devices, do nothing */
1147 return STATUS_SUCCESS
;
1150 /* At this point, we know we're a file. Reference it */
1151 ObReferenceObject(FileObject
);
1153 /* Check if we should use Sync IO or not */
1154 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1156 /* Lock the file object */
1157 IopLockFileObject(FileObject
);
1161 /* Use local event */
1162 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1166 /* Clear the File Object event */
1167 KeClearEvent(&FileObject
->Event
);
1169 /* Get the device object */
1170 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1172 /* Allocate the IRP */
1173 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1174 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1177 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1178 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1179 Irp
->RequestorMode
= ExGetPreviousMode();
1180 Irp
->UserIosb
= &IoStatusBlock
;
1181 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1182 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1183 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1185 /* Set Stack Parameters */
1186 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1187 StackPtr
->FileObject
= FileObject
;
1189 /* Check if this is a query or set */
1190 if (OperationCode
== QuerySecurityDescriptor
)
1192 /* Set the major function and parameters */
1193 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1194 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1195 *SecurityInformation
;
1196 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1197 Irp
->UserBuffer
= SecurityDescriptor
;
1201 /* Set the major function and parameters for a set */
1202 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1203 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1204 *SecurityInformation
;
1205 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1210 IopQueueIrpToThread(Irp
);
1212 /* Update operation counts */
1213 IopUpdateOperationCount(IopOtherTransfer
);
1215 /* Call the Driver */
1216 Status
= IoCallDriver(DeviceObject
, Irp
);
1218 /* Check if this was async I/O */
1221 /* Check if the IRP is pending completion */
1222 if (Status
== STATUS_PENDING
)
1224 /* Wait on the local event */
1225 KeWaitForSingleObject(&Event
,
1230 Status
= IoStatusBlock
.Status
;
1235 /* Check if the IRP is pending completion */
1236 if (Status
== STATUS_PENDING
)
1238 /* Wait on the file object */
1239 KeWaitForSingleObject(&FileObject
->Event
,
1244 Status
= FileObject
->FinalStatus
;
1247 /* Release the lock */
1248 IopUnlockFileObject(FileObject
);
1251 /* This Driver doesn't implement Security, so try to give it a default */
1252 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1254 /* Was this a query? */
1255 if (OperationCode
== QuerySecurityDescriptor
)
1257 /* Set a World Security Descriptor */
1258 Status
= SeSetWorldSecurityDescriptor(*SecurityInformation
,
1264 /* It wasn't a query, so just fake success */
1265 Status
= STATUS_SUCCESS
;
1268 else if (OperationCode
== QuerySecurityDescriptor
)
1270 /* Callers usually expect the normalized form */
1271 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1276 *BufferLength
= IoStatusBlock
.Information
;
1278 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1280 /* Get the exception code */
1281 Status
= _SEH2_GetExceptionCode();
1292 IopQueryNameFile(IN PVOID ObjectBody
,
1294 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1296 OUT PULONG ReturnLength
,
1297 IN KPROCESSOR_MODE PreviousMode
)
1299 POBJECT_NAME_INFORMATION LocalInfo
;
1300 PFILE_NAME_INFORMATION LocalFileInfo
;
1301 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1302 ULONG LocalReturnLength
, FileLength
;
1303 BOOLEAN LengthMismatch
= FALSE
;
1306 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1308 /* Validate length */
1309 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1311 /* Wrong length, fail */
1312 return STATUS_INFO_LENGTH_MISMATCH
;
1315 /* Allocate Buffer */
1316 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1317 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1319 /* Query the name */
1320 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1323 &LocalReturnLength
);
1324 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1326 /* Free the buffer and fail */
1327 ExFreePool(LocalInfo
);
1331 /* Copy the information */
1332 RtlCopyMemory(ObjectNameInfo
,
1334 (LocalReturnLength
> Length
) ?
1335 Length
: LocalReturnLength
);
1337 /* Set buffer pointer */
1338 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1339 ObjectNameInfo
->Name
.Buffer
= p
;
1341 /* Advance in buffer */
1342 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1344 /* Check if this already filled our buffer */
1345 if (LocalReturnLength
> Length
)
1347 /* Set the length mismatch to true, so that we can return
1348 * the proper buffer size to the caller later
1350 LengthMismatch
= TRUE
;
1352 /* Save the initial buffer length value */
1353 *ReturnLength
= LocalReturnLength
;
1356 /* Now get the file name buffer and check the length needed */
1357 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1358 FileLength
= Length
-
1360 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1362 /* Query the File name */
1363 Status
= IoQueryFileInformation(FileObject
,
1364 FileNameInformation
,
1365 LengthMismatch
? Length
: FileLength
,
1367 &LocalReturnLength
);
1368 if (NT_ERROR(Status
))
1370 /* Fail on errors only, allow warnings */
1371 ExFreePool(LocalInfo
);
1375 /* If the provided buffer is too small, return the required size */
1378 /* Add the required length */
1379 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1381 /* Free the allocated buffer and return failure */
1382 ExFreePool(LocalInfo
);
1383 return STATUS_BUFFER_OVERFLOW
;
1386 /* Now calculate the new lengths left */
1387 FileLength
= LocalReturnLength
-
1388 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1389 LocalReturnLength
= (ULONG_PTR
)p
-
1390 (ULONG_PTR
)ObjectNameInfo
+
1391 LocalFileInfo
->FileNameLength
;
1393 /* Write the Name and null-terminate it */
1394 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1395 p
+= (FileLength
/ sizeof(WCHAR
));
1397 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1399 /* Return the length needed */
1400 *ReturnLength
= LocalReturnLength
;
1402 /* Setup the length and maximum length */
1403 FileLength
= (ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
;
1404 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1405 sizeof(OBJECT_NAME_INFORMATION
);
1406 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1407 sizeof(UNICODE_NULL
);
1409 /* Free buffer and return */
1410 ExFreePool(LocalInfo
);
1416 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1417 IN PVOID ObjectBody
,
1418 IN ACCESS_MASK GrantedAccess
,
1419 IN ULONG HandleCount
,
1420 IN ULONG SystemHandleCount
)
1422 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1425 PIO_STACK_LOCATION StackPtr
;
1427 PDEVICE_OBJECT DeviceObject
;
1429 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1431 /* If this isn't the last handle for the current process, quit */
1432 if (HandleCount
!= 1) return;
1434 /* Check if the file is locked and has more then one handle opened */
1435 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1437 DPRINT1("We need to unlock this file!\n");
1441 /* Make sure this is the last handle */
1442 if (SystemHandleCount
!= 1) return;
1444 /* Check if this is a direct open or not */
1445 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1447 /* Get the attached device */
1448 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1452 /* Get the FO's device */
1453 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1456 /* Set the handle created flag */
1457 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1459 /* Check if this is a sync FO and lock it */
1460 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1462 /* Clear and set up Events */
1463 KeClearEvent(&FileObject
->Event
);
1464 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1466 /* Allocate an IRP */
1467 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1471 Irp
->UserEvent
= &Event
;
1472 Irp
->UserIosb
= &Irp
->IoStatus
;
1473 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1474 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1475 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1476 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1478 /* Set up Stack Pointer Data */
1479 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1480 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1481 StackPtr
->FileObject
= FileObject
;
1484 IopQueueIrpToThread(Irp
);
1486 /* Update operation counts */
1487 IopUpdateOperationCount(IopOtherTransfer
);
1489 /* Call the FS Driver */
1490 Status
= IoCallDriver(DeviceObject
, Irp
);
1491 if (Status
== STATUS_PENDING
)
1493 /* Wait for completion */
1494 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1497 /* Unqueue the IRP */
1498 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1499 IopUnQueueIrpFromThread(Irp
);
1500 KeLowerIrql(OldIrql
);
1505 /* Release the lock if we were holding it */
1506 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1511 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1512 IN FILE_INFORMATION_CLASS FileInformationClass
,
1513 IN ULONG FileInformationSize
,
1514 OUT PVOID FileInformation
)
1517 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1518 DUMMY_FILE_OBJECT DummyFileObject
;
1519 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1521 OPEN_PACKET OpenPacket
;
1524 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
1526 /* Check if the caller was user mode */
1527 if (AccessMode
!= KernelMode
)
1529 /* Protect probe in SEH */
1532 /* Probe the buffer */
1533 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
1535 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1537 /* Return the exception code */
1538 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1543 /* Check if this is a basic or full request */
1544 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
1546 /* Setup the Open Packet */
1547 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1548 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1549 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1550 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
1551 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
1552 OpenPacket
.Disposition
= FILE_OPEN
;
1553 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
1554 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
1555 (AccessMode
!= KernelMode
) ?
1556 &NetworkOpenInfo
: FileInformation
;
1557 OpenPacket
.QueryOnly
= TRUE
;
1558 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
1559 OpenPacket
.DummyFileObject
= &DummyFileObject
;
1561 /* Update the operation count */
1562 IopUpdateOperationCount(IopOtherTransfer
);
1565 * Attempt opening the file. This will call the I/O Parse Routine for
1566 * the File Object (IopParseDevice) which will use the dummy file obejct
1567 * send the IRP to its device object. Note that we have two statuses
1568 * to worry about: the Object Manager's status (in Status) and the I/O
1569 * status, which is in the Open Packet's Final Status, and determined
1570 * by the Parse Check member.
1572 Status
= ObOpenObjectByName(ObjectAttributes
,
1576 FILE_READ_ATTRIBUTES
,
1579 if (OpenPacket
.ParseCheck
!= TRUE
)
1586 /* Use the Io status */
1587 Status
= OpenPacket
.FinalStatus
;
1590 /* Check if we were succesful and this was user mode and a full query */
1591 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
1593 /* Enter SEH for copy */
1596 /* Copy the buffer back */
1597 RtlCopyMemory(FileInformation
,
1599 FileInformationSize
);
1601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1603 /* Get exception code */
1604 Status
= _SEH2_GetExceptionCode();
1613 /* FUNCTIONS *****************************************************************/
1620 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
1622 IN BOOLEAN SetOperation
)
1625 return STATUS_NOT_IMPLEMENTED
;
1633 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
1634 IN ULONG QuotaLength
,
1635 OUT PULONG ErrorOffset
)
1638 return STATUS_NOT_IMPLEMENTED
;
1646 IoCreateFile(OUT PHANDLE FileHandle
,
1647 IN ACCESS_MASK DesiredAccess
,
1648 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1649 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1650 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1651 IN ULONG FileAttributes
,
1652 IN ULONG ShareAccess
,
1653 IN ULONG Disposition
,
1654 IN ULONG CreateOptions
,
1655 IN PVOID EaBuffer OPTIONAL
,
1657 IN CREATE_FILE_TYPE CreateFileType
,
1658 IN PVOID ExtraCreateParameters OPTIONAL
,
1661 KPROCESSOR_MODE AccessMode
;
1662 HANDLE LocalHandle
= 0;
1663 LARGE_INTEGER SafeAllocationSize
;
1664 PVOID SystemEaBuffer
= NULL
;
1666 OPEN_PACKET OpenPacket
;
1667 ULONG EaErrorOffset
;
1670 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
1672 /* Check if we have no parameter checking to do */
1673 if (Options
& IO_NO_PARAMETER_CHECKING
)
1675 /* Then force kernel-mode access to avoid checks */
1676 AccessMode
= KernelMode
;
1680 /* Otherwise, use the actual mode */
1681 AccessMode
= ExGetPreviousMode();
1684 /* Check if the call came from user mode */
1685 if (AccessMode
!= KernelMode
)
1689 ProbeForWriteHandle(FileHandle
);
1690 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1693 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
1697 SafeAllocationSize
.QuadPart
= 0;
1700 if ((EaBuffer
) && (EaLength
))
1702 ProbeForRead(EaBuffer
,
1706 /* marshal EaBuffer */
1707 SystemEaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1712 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1715 RtlCopyMemory(SystemEaBuffer
, EaBuffer
, EaLength
);
1717 /* Validate the buffer */
1718 Status
= IoCheckEaBufferValidity(SystemEaBuffer
,
1721 if (!NT_SUCCESS(Status
))
1723 DPRINT1("FIXME: IoCheckEaBufferValidity() failed with "
1724 "Status: %lx\n",Status
);
1726 /* Free EA Buffer and return the error */
1727 ExFreePoolWithTag(SystemEaBuffer
, TAG_EA
);
1728 _SEH2_YIELD(return Status
);
1732 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1734 /* Free SystemEaBuffer if needed */
1735 if (SystemEaBuffer
) ExFreePoolWithTag(SystemEaBuffer
, TAG_EA
);
1737 /* Return the exception code */
1738 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1744 /* Check if this is a device attach */
1745 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
1747 /* Set the flag properly */
1748 Options
|= IO_ATTACH_DEVICE
;
1749 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
1752 /* Check if we have allocation size */
1756 SafeAllocationSize
= *AllocationSize
;
1760 /* Otherwise, no size */
1761 SafeAllocationSize
.QuadPart
= 0;
1764 /* Check if we have an EA packet */
1765 if ((EaBuffer
) && (EaLength
))
1767 /* Allocate the kernel copy */
1768 SystemEaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1771 if (!SystemEaBuffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1774 RtlCopyMemory(SystemEaBuffer
, EaBuffer
, EaLength
);
1776 /* Validate the buffer */
1777 Status
= IoCheckEaBufferValidity(SystemEaBuffer
,
1780 if (!NT_SUCCESS(Status
))
1782 DPRINT1("FIXME: IoCheckEaBufferValidity() failed with "
1783 "Status: %lx\n",Status
);
1788 /* Setup the Open Packet */
1789 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1790 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1791 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1792 OpenPacket
.OriginalAttributes
= *ObjectAttributes
;
1793 OpenPacket
.AllocationSize
= SafeAllocationSize
;
1794 OpenPacket
.CreateOptions
= CreateOptions
;
1795 OpenPacket
.FileAttributes
= (USHORT
)FileAttributes
;
1796 OpenPacket
.ShareAccess
= (USHORT
)ShareAccess
;
1797 OpenPacket
.EaBuffer
= SystemEaBuffer
;
1798 OpenPacket
.EaLength
= EaLength
;
1799 OpenPacket
.Options
= Options
;
1800 OpenPacket
.Disposition
= Disposition
;
1801 OpenPacket
.CreateFileType
= CreateFileType
;
1802 OpenPacket
.MailslotOrPipeParameters
= ExtraCreateParameters
;
1804 /* Update the operation count */
1805 IopUpdateOperationCount(IopOtherTransfer
);
1808 * Attempt opening the file. This will call the I/O Parse Routine for
1809 * the File Object (IopParseDevice) which will create the object and
1810 * send the IRP to its device object. Note that we have two statuses
1811 * to worry about: the Object Manager's status (in Status) and the I/O
1812 * status, which is in the Open Packet's Final Status, and determined
1813 * by the Parse Check member.
1815 Status
= ObOpenObjectByName(ObjectAttributes
,
1823 /* Free the EA Buffer */
1824 if (OpenPacket
.EaBuffer
) ExFreePool(OpenPacket
.EaBuffer
);
1826 /* Now check for Ob or Io failure */
1827 if (!(NT_SUCCESS(Status
)) || (OpenPacket
.ParseCheck
!= TRUE
))
1829 /* Check if Ob thinks well went well */
1830 if (NT_SUCCESS(Status
))
1833 * Tell it otherwise. Because we didn't use an ObjectType,
1834 * it incorrectly returned us a handle to God knows what.
1836 ZwClose(LocalHandle
);
1837 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
1840 /* Now check the Io status */
1841 if (!NT_SUCCESS(OpenPacket
.FinalStatus
))
1843 /* Use this status instead of Ob's */
1844 Status
= OpenPacket
.FinalStatus
;
1846 /* Check if it was only a warning */
1847 if (NT_WARNING(Status
))
1849 /* Protect write with SEH */
1852 /* In this case, we copy the I/O Status back */
1853 IoStatusBlock
->Information
= OpenPacket
.Information
;
1854 IoStatusBlock
->Status
= OpenPacket
.FinalStatus
;
1856 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1858 /* Get exception code */
1859 Status
= _SEH2_GetExceptionCode();
1864 else if ((OpenPacket
.FileObject
) && (OpenPacket
.ParseCheck
!= 1))
1867 * This can happen in the very bizarre case where the parse routine
1868 * actually executed more then once (due to a reparse) and ended
1869 * up failing after already having created the File Object.
1871 if (OpenPacket
.FileObject
->FileName
.Length
)
1873 /* It had a name, free it */
1874 ExFreePool(OpenPacket
.FileObject
->FileName
.Buffer
);
1877 /* Clear the device object to invalidate the FO, and dereference */
1878 OpenPacket
.FileObject
->DeviceObject
= NULL
;
1879 ObDereferenceObject(OpenPacket
.FileObject
);
1884 /* We reached success and have a valid file handle */
1885 OpenPacket
.FileObject
->Flags
|= FO_HANDLE_CREATED
;
1887 /* Enter SEH for write back */
1890 /* Write back the handle and I/O Status */
1891 *FileHandle
= LocalHandle
;
1892 IoStatusBlock
->Information
= OpenPacket
.Information
;
1893 IoStatusBlock
->Status
= OpenPacket
.FinalStatus
;
1895 /* Get the Io status */
1896 Status
= OpenPacket
.FinalStatus
;
1898 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1900 /* Get the exception status */
1901 Status
= _SEH2_GetExceptionCode();
1906 /* Check if we were 100% successful */
1907 if ((OpenPacket
.ParseCheck
== TRUE
) && (OpenPacket
.FileObject
))
1909 /* Dereference the File Object */
1910 ObDereferenceObject(OpenPacket
.FileObject
);
1922 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1923 IN ACCESS_MASK DesiredAccess
,
1924 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1925 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1926 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1927 IN ULONG FileAttributes
,
1928 IN ULONG ShareAccess
,
1929 IN ULONG Disposition
,
1930 IN ULONG CreateOptions
,
1931 IN PVOID EaBuffer OPTIONAL
,
1933 IN CREATE_FILE_TYPE CreateFileType
,
1934 IN PVOID ExtraCreateParameters OPTIONAL
,
1936 IN PVOID DeviceObject
)
1939 return STATUS_NOT_IMPLEMENTED
;
1947 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1948 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1949 OUT PHANDLE FileObjectHandle OPTIONAL
)
1951 PFILE_OBJECT CreatedFileObject
;
1954 OBJECT_ATTRIBUTES ObjectAttributes
;
1956 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
1958 /* Choose Device Object */
1959 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1961 /* Reference the device object and initialize attributes */
1962 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
1963 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
1965 /* Create the File Object */
1966 Status
= ObCreateObject(KernelMode
,
1971 sizeof(FILE_OBJECT
),
1972 sizeof(FILE_OBJECT
),
1974 (PVOID
*)&CreatedFileObject
);
1975 if (!NT_SUCCESS(Status
))
1978 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
1979 ExRaiseStatus(Status
);
1982 /* Set File Object Data */
1983 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
1984 CreatedFileObject
->DeviceObject
= DeviceObject
;
1985 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1986 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
1987 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
1989 /* Initialize the wait event */
1990 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
1992 /* Insert it to create a handle for it */
1993 Status
= ObInsertObject(CreatedFileObject
,
1997 (PVOID
*)&CreatedFileObject
,
1999 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2001 /* Set the handle created flag */
2002 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2003 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2005 /* Check if we have a VPB */
2006 if (DeviceObject
->Vpb
)
2009 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2012 /* Check if the caller wants the handle */
2013 if (FileObjectHandle
)
2016 *FileObjectHandle
= FileHandle
;
2017 ObDereferenceObject(CreatedFileObject
);
2021 /* Otherwise, close it */
2022 ObCloseHandle(FileHandle
, KernelMode
);
2025 /* Return the file object */
2026 return CreatedFileObject
;
2034 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2035 IN PDEVICE_OBJECT DeviceObject
)
2037 /* Call the newer function */
2038 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2046 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2047 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2049 PFILE_OBJECT CreatedFileObject
;
2051 OBJECT_ATTRIBUTES ObjectAttributes
;
2053 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2055 /* Choose Device Object */
2056 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2058 /* Reference the device object and initialize attributes */
2059 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2060 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2062 /* Create the File Object */
2063 Status
= ObCreateObject(KernelMode
,
2068 sizeof(FILE_OBJECT
),
2069 sizeof(FILE_OBJECT
),
2071 (PVOID
*)&CreatedFileObject
);
2072 if (!NT_SUCCESS(Status
))
2075 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2076 ExRaiseStatus(Status
);
2079 /* Set File Object Data */
2080 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2081 CreatedFileObject
->DeviceObject
= DeviceObject
;
2082 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2083 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2084 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2086 /* Initialize the wait event */
2087 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2089 /* Destroy create information */
2090 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2092 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2094 /* Set the handle created flag */
2095 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2096 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2098 /* Check if we have a VPB */
2099 if (DeviceObject
->Vpb
)
2102 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2105 /* Return the file object */
2106 return CreatedFileObject
;
2114 IoGetFileObjectGenericMapping(VOID
)
2116 /* Return the mapping */
2117 return &IopFileMapping
;
2125 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2127 /* Return the flag status */
2128 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2136 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2137 IN ACCESS_MASK DesiredAccess
,
2138 IN ULONG OpenOptions
,
2139 OUT PIO_STATUS_BLOCK IoStatus
,
2140 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2143 DUMMY_FILE_OBJECT DummyFileObject
;
2145 OPEN_PACKET OpenPacket
;
2147 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2149 /* Setup the Open Packet */
2150 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2151 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2152 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2153 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2154 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2155 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2156 OpenPacket
.Disposition
= FILE_OPEN
;
2157 OpenPacket
.NetworkInformation
= Buffer
;
2158 OpenPacket
.QueryOnly
= TRUE
;
2159 OpenPacket
.FullAttributes
= TRUE
;
2160 OpenPacket
.DummyFileObject
= &DummyFileObject
;
2163 * Attempt opening the file. This will call the I/O Parse Routine for
2164 * the File Object (IopParseDevice) which will use the dummy file obejct
2165 * send the IRP to its device object. Note that we have two statuses
2166 * to worry about: the Object Manager's status (in Status) and the I/O
2167 * status, which is in the Open Packet's Final Status, and determined
2168 * by the Parse Check member.
2170 Status
= ObOpenObjectByName(ObjectAttributes
,
2177 if (OpenPacket
.ParseCheck
!= TRUE
)
2180 IoStatus
->Status
= Status
;
2184 /* Use the Io status */
2185 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2186 IoStatus
->Information
= OpenPacket
.Information
;
2189 /* Return success */
2198 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2199 OUT PSHARE_ACCESS ShareAccess
)
2203 /* Check if the file has an extension */
2204 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2206 /* Check if caller specified to ignore access checks */
2207 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2209 /* Don't update share access */
2214 /* Otherwise, check if there's any access present */
2215 if ((FileObject
->ReadAccess
) ||
2216 (FileObject
->WriteAccess
) ||
2217 (FileObject
->DeleteAccess
))
2219 /* Increase the open count */
2220 ShareAccess
->OpenCount
++;
2222 /* Add new share access */
2223 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2224 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2225 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2226 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2227 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2228 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2237 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2238 IN ULONG DesiredShareAccess
,
2239 IN PFILE_OBJECT FileObject
,
2240 IN PSHARE_ACCESS ShareAccess
,
2244 BOOLEAN WriteAccess
;
2245 BOOLEAN DeleteAccess
;
2247 BOOLEAN SharedWrite
;
2248 BOOLEAN SharedDelete
;
2251 /* Get access masks */
2252 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2253 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2254 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2256 /* Set them in the file object */
2257 FileObject
->ReadAccess
= ReadAccess
;
2258 FileObject
->WriteAccess
= WriteAccess
;
2259 FileObject
->DeleteAccess
= DeleteAccess
;
2261 /* Check if the file has an extension */
2262 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2264 /* Check if caller specified to ignore access checks */
2265 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2267 /* Don't check share access */
2268 return STATUS_SUCCESS
;
2272 /* Check if we have any access */
2273 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2275 /* Get shared access masks */
2276 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2277 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2278 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2281 FileObject
->SharedRead
= SharedRead
;
2282 FileObject
->SharedWrite
= SharedWrite
;
2283 FileObject
->SharedDelete
= SharedDelete
;
2285 /* Check if the shared access is violated */
2287 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2289 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2291 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2292 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2293 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2294 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2296 /* Sharing violation, fail */
2297 return STATUS_SHARING_VIOLATION
;
2300 /* It's not, check if caller wants us to update it */
2303 /* Increase open count */
2304 ShareAccess
->OpenCount
++;
2306 /* Update shared access */
2307 ShareAccess
->Readers
+= ReadAccess
;
2308 ShareAccess
->Writers
+= WriteAccess
;
2309 ShareAccess
->Deleters
+= DeleteAccess
;
2310 ShareAccess
->SharedRead
+= SharedRead
;
2311 ShareAccess
->SharedWrite
+= SharedWrite
;
2312 ShareAccess
->SharedDelete
+= SharedDelete
;
2316 /* Validation successful */
2317 return STATUS_SUCCESS
;
2325 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2326 IN PSHARE_ACCESS ShareAccess
)
2330 /* Check if the file has an extension */
2331 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2333 /* Check if caller specified to ignore access checks */
2334 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2336 /* Don't update share access */
2341 /* Otherwise, check if there's any access present */
2342 if ((FileObject
->ReadAccess
) ||
2343 (FileObject
->WriteAccess
) ||
2344 (FileObject
->DeleteAccess
))
2346 /* Decrement the open count */
2347 ShareAccess
->OpenCount
--;
2349 /* Remove share access */
2350 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
2351 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
2352 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
2353 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
2354 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
2355 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
2364 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
2365 IN ULONG DesiredShareAccess
,
2366 IN PFILE_OBJECT FileObject
,
2367 OUT PSHARE_ACCESS ShareAccess
)
2370 BOOLEAN WriteAccess
;
2371 BOOLEAN DeleteAccess
;
2373 BOOLEAN SharedWrite
;
2374 BOOLEAN SharedDelete
;
2375 BOOLEAN Update
= TRUE
;
2378 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2379 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2380 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2382 /* Check if the file has an extension */
2383 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2385 /* Check if caller specified to ignore access checks */
2386 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2388 /* Don't update share access */
2393 /* Update basic access */
2394 FileObject
->ReadAccess
= ReadAccess
;
2395 FileObject
->WriteAccess
= WriteAccess
;
2396 FileObject
->DeleteAccess
= DeleteAccess
;
2398 /* Check if we have no access as all */
2399 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
2401 /* Check if we need to update the structure */
2402 if (!Update
) return;
2404 /* Otherwise, clear data */
2405 ShareAccess
->OpenCount
= 0;
2406 ShareAccess
->Readers
= 0;
2407 ShareAccess
->Writers
= 0;
2408 ShareAccess
->Deleters
= 0;
2409 ShareAccess
->SharedRead
= 0;
2410 ShareAccess
->SharedWrite
= 0;
2411 ShareAccess
->SharedDelete
= 0;
2415 /* Calculate shared access */
2416 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2417 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2418 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2420 /* Set it in the FO */
2421 FileObject
->SharedRead
= SharedRead
;
2422 FileObject
->SharedWrite
= SharedWrite
;
2423 FileObject
->SharedDelete
= SharedDelete
;
2425 /* Check if we need to update the structure */
2426 if (!Update
) return;
2428 /* Otherwise, set data */
2429 ShareAccess
->OpenCount
= 1;
2430 ShareAccess
->Readers
= ReadAccess
;
2431 ShareAccess
->Writers
= WriteAccess
;
2432 ShareAccess
->Deleters
= DeleteAccess
;
2433 ShareAccess
->SharedRead
= SharedRead
;
2434 ShareAccess
->SharedWrite
= SharedWrite
;
2435 ShareAccess
->SharedDelete
= SharedDelete
;
2444 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
2445 IN PFILE_OBJECT FileObject
)
2455 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
2456 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
2459 return STATUS_NOT_IMPLEMENTED
;
2467 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
2470 NTSTATUS Status
= STATUS_SUCCESS
;
2473 /* Get the flag status */
2474 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2476 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
2477 if (Remote
&& !FlagSet
)
2480 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
2482 else if (!Remote
&& FlagSet
)
2484 /* Remove the flag */
2485 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
2490 Status
= STATUS_INVALID_PARAMETER_MIX
;
2502 NtCreateFile(PHANDLE FileHandle
,
2503 ACCESS_MASK DesiredAccess
,
2504 POBJECT_ATTRIBUTES ObjectAttributes
,
2505 PIO_STATUS_BLOCK IoStatusBlock
,
2506 PLARGE_INTEGER AllocateSize
,
2507 ULONG FileAttributes
,
2509 ULONG CreateDisposition
,
2510 ULONG CreateOptions
,
2514 /* Call the I/O Function */
2515 return IoCreateFile(FileHandle
,
2533 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
2534 IN ACCESS_MASK DesiredAccess
,
2535 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2536 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2537 IN ULONG CreateOptions
,
2538 IN ULONG MailslotQuota
,
2539 IN ULONG MaxMessageSize
,
2540 IN PLARGE_INTEGER TimeOut
)
2542 MAILSLOT_CREATE_PARAMETERS Buffer
;
2545 /* Check for Timeout */
2548 /* check if the call came from user mode */
2549 if (KeGetPreviousMode() != KernelMode
)
2551 /* Enter SEH for Probe */
2554 /* Probe the timeout */
2555 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
2557 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2559 /* Return the exception code */
2560 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2566 /* Otherwise, capture directly */
2567 Buffer
.ReadTimeout
= *TimeOut
;
2570 /* Set the correct setting */
2571 Buffer
.TimeoutSpecified
= TRUE
;
2575 /* Tell the FSD we don't have a timeout */
2576 Buffer
.TimeoutSpecified
= FALSE
;
2580 Buffer
.MailslotQuota
= MailslotQuota
;
2581 Buffer
.MaximumMessageSize
= MaxMessageSize
;
2584 return IoCreateFile(FileHandle
,
2590 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2595 CreateFileTypeMailslot
,
2602 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
2603 IN ACCESS_MASK DesiredAccess
,
2604 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2605 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2606 IN ULONG ShareAccess
,
2607 IN ULONG CreateDisposition
,
2608 IN ULONG CreateOptions
,
2609 IN ULONG NamedPipeType
,
2611 IN ULONG CompletionMode
,
2612 IN ULONG MaximumInstances
,
2613 IN ULONG InboundQuota
,
2614 IN ULONG OutboundQuota
,
2615 IN PLARGE_INTEGER DefaultTimeout
)
2617 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
2620 /* Check for Timeout */
2623 /* check if the call came from user mode */
2624 if (KeGetPreviousMode() != KernelMode
)
2626 /* Enter SEH for Probe */
2629 /* Probe the timeout */
2630 Buffer
.DefaultTimeout
=
2631 ProbeForReadLargeInteger(DefaultTimeout
);
2633 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2635 /* Return the exception code */
2636 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2642 /* Otherwise, capture directly */
2643 Buffer
.DefaultTimeout
= *DefaultTimeout
;
2646 /* Set the correct setting */
2647 Buffer
.TimeoutSpecified
= TRUE
;
2651 /* Tell the FSD we don't have a timeout */
2652 Buffer
.TimeoutSpecified
= FALSE
;
2656 Buffer
.NamedPipeType
= NamedPipeType
;
2657 Buffer
.ReadMode
= ReadMode
;
2658 Buffer
.CompletionMode
= CompletionMode
;
2659 Buffer
.MaximumInstances
= MaximumInstances
;
2660 Buffer
.InboundQuota
= InboundQuota
;
2661 Buffer
.OutboundQuota
= OutboundQuota
;
2664 return IoCreateFile(FileHandle
,
2675 CreateFileTypeNamedPipe
,
2682 NtFlushWriteBuffer(VOID
)
2686 /* Call the kernel */
2687 KeFlushWriteBuffer();
2688 return STATUS_SUCCESS
;
2696 NtOpenFile(OUT PHANDLE FileHandle
,
2697 IN ACCESS_MASK DesiredAccess
,
2698 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2699 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2700 IN ULONG ShareAccess
,
2701 IN ULONG OpenOptions
)
2703 /* Call the I/O Function */
2704 return IoCreateFile(FileHandle
,
2722 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2723 OUT PFILE_BASIC_INFORMATION FileInformation
)
2725 /* Call the internal helper API */
2726 return IopQueryAttributesFile(ObjectAttributes
,
2727 FileBasicInformation
,
2728 sizeof(FILE_BASIC_INFORMATION
),
2734 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2735 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2737 /* Call the internal helper API */
2738 return IopQueryAttributesFile(ObjectAttributes
,
2739 FileNetworkOpenInformation
,
2740 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2745 * @name NtCancelIoFile
2747 * Cancel all pending I/O operations in the current thread for specified
2751 * Handle to file object to cancel requests for. No specific
2752 * access rights are needed.
2753 * @param IoStatusBlock
2754 * Pointer to status block which is filled with final completition
2755 * status on successful return.
2763 NtCancelIoFile(IN HANDLE FileHandle
,
2764 OUT PIO_STATUS_BLOCK IoStatusBlock
)
2766 PFILE_OBJECT FileObject
;
2770 BOOLEAN OurIrpsInList
= FALSE
;
2771 LARGE_INTEGER Interval
;
2772 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2774 PLIST_ENTRY ListHead
, NextEntry
;
2776 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2778 /* Check the previous mode */
2779 if (PreviousMode
!= KernelMode
)
2781 /* Enter SEH for probing */
2784 /* Probe the I/O Status Block */
2785 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2787 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2789 /* Return the exception code */
2790 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2795 /* Reference the file object */
2796 Status
= ObReferenceObjectByHandle(FileHandle
,
2800 (PVOID
*)&FileObject
,
2802 if (!NT_SUCCESS(Status
)) return Status
;
2804 /* IRP cancellations are synchronized at APC_LEVEL. */
2805 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2807 /* Get the current thread */
2808 Thread
= PsGetCurrentThread();
2810 /* Update the operation counts */
2811 IopUpdateOperationCount(IopOtherTransfer
);
2814 ListHead
= &Thread
->IrpList
;
2815 NextEntry
= ListHead
->Flink
;
2816 while (ListHead
!= NextEntry
)
2818 /* Get the IRP and check if the File Object matches */
2819 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
2820 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
2822 /* Cancel this IRP and keep looping */
2824 OurIrpsInList
= TRUE
;
2827 /* Go to the next entry */
2828 NextEntry
= NextEntry
->Flink
;
2831 /* Lower the IRQL */
2832 KeLowerIrql(OldIrql
);
2834 /* Check if we had found an IRP */
2837 /* Setup a 10ms wait */
2838 Interval
.QuadPart
= -100000;
2841 while (OurIrpsInList
)
2844 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
2845 OurIrpsInList
= FALSE
;
2848 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2850 /* Now loop the list again */
2851 NextEntry
= ListHead
->Flink
;
2852 while (NextEntry
!= ListHead
)
2854 /* Get the IRP and check if the File Object matches */
2855 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
2856 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
2859 OurIrpsInList
= TRUE
;
2863 /* Go to the next entry */
2864 NextEntry
= NextEntry
->Flink
;
2867 /* Lower the IRQL */
2868 KeLowerIrql(OldIrql
);
2872 /* Enter SEH for writing back the I/O Status */
2876 IoStatusBlock
->Status
= STATUS_SUCCESS
;
2877 IoStatusBlock
->Information
= 0;
2879 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2881 /* Ignore exception */
2885 /* Dereference the file object and return success */
2886 ObDereferenceObject(FileObject
);
2887 return STATUS_SUCCESS
;
2895 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
2898 DUMMY_FILE_OBJECT DummyFileObject
;
2900 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
2901 OPEN_PACKET OpenPacket
;
2903 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
2905 /* Setup the Open Packet */
2906 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2907 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2908 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2909 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
2910 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
2913 OpenPacket
.Disposition
= FILE_OPEN
;
2914 OpenPacket
.DeleteOnly
= TRUE
;
2915 OpenPacket
.DummyFileObject
= &DummyFileObject
;
2917 /* Update the operation counts */
2918 IopUpdateOperationCount(IopOtherTransfer
);
2921 * Attempt opening the file. This will call the I/O Parse Routine for
2922 * the File Object (IopParseDevice) which will use the dummy file obejct
2923 * send the IRP to its device object. Note that we have two statuses
2924 * to worry about: the Object Manager's status (in Status) and the I/O
2925 * status, which is in the Open Packet's Final Status, and determined
2926 * by the Parse Check member.
2928 Status
= ObOpenObjectByName(ObjectAttributes
,
2935 if (OpenPacket
.ParseCheck
!= TRUE
) return Status
;
2937 /* Retrn the Io status */
2938 return OpenPacket
.FinalStatus
;