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 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
161 return STATUS_SUCCESS
;
167 IopParseDevice(IN PVOID ParseObject
,
169 IN OUT PACCESS_STATE AccessState
,
170 IN KPROCESSOR_MODE AccessMode
,
172 IN OUT PUNICODE_STRING CompleteName
,
173 IN OUT PUNICODE_STRING RemainingName
,
174 IN OUT PVOID Context
,
175 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
178 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
179 PDEVICE_OBJECT OriginalDeviceObject
= (PDEVICE_OBJECT
)ParseObject
;
180 PDEVICE_OBJECT DeviceObject
, OwnerDevice
;
182 PFILE_OBJECT FileObject
;
185 PEXTENDED_IO_STACK_LOCATION StackLoc
;
186 IO_SECURITY_CONTEXT SecurityContext
;
187 IO_STATUS_BLOCK IoStatusBlock
;
188 BOOLEAN DirectOpen
= FALSE
, OpenCancelled
, UseDummyFile
;
189 OBJECT_ATTRIBUTES ObjectAttributes
;
191 PDUMMY_FILE_OBJECT DummyFileObject
;
192 PFILE_BASIC_INFORMATION FileBasicInfo
;
194 KPROCESSOR_MODE CheckMode
;
195 BOOLEAN VolumeOpen
= FALSE
;
196 ACCESS_MASK DesiredAccess
, GrantedAccess
;
197 BOOLEAN AccessGranted
, LockHeld
= FALSE
;
198 PPRIVILEGE_SET Privileges
= NULL
;
199 UNICODE_STRING FileString
;
200 IOTRACE(IO_FILE_DEBUG
, "ParseObject: %p. RemainingName: %wZ\n",
201 ParseObject
, RemainingName
);
206 /* Validate the open packet */
207 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
209 /* Check if we have a related file object */
210 if (OpenPacket
->RelatedFileObject
)
212 /* Use the related file object's device object */
213 OriginalDeviceObject
= OpenPacket
->RelatedFileObject
->DeviceObject
;
216 /* Validate device status */
217 Status
= IopCheckDeviceAndDriver(OpenPacket
, OriginalDeviceObject
);
218 if (!NT_SUCCESS(Status
))
220 /* We failed, return status */
221 OpenPacket
->FinalStatus
= Status
;
225 /* Map the generic mask and set the new mapping in the access state */
226 RtlMapGenericMask(&AccessState
->RemainingDesiredAccess
,
227 &IoFileObjectType
->TypeInfo
.GenericMapping
);
228 RtlMapGenericMask(&AccessState
->OriginalDesiredAccess
,
229 &IoFileObjectType
->TypeInfo
.GenericMapping
);
230 SeSetAccessStateGenericMapping(AccessState
,
231 &IoFileObjectType
->TypeInfo
.GenericMapping
);
232 DesiredAccess
= AccessState
->RemainingDesiredAccess
;
234 /* Check what kind of access checks to do */
235 if ((AccessMode
!= KernelMode
) ||
236 (OpenPacket
->Options
& IO_FORCE_ACCESS_CHECK
))
238 /* Call is from user-mode or kernel is forcing checks */
239 CheckMode
= UserMode
;
243 /* Call is from the kernel */
244 CheckMode
= KernelMode
;
247 /* Check privilege for backup or restore operation */
248 IopCheckBackupRestorePrivilege(AccessState
,
249 &OpenPacket
->CreateOptions
,
251 OpenPacket
->Disposition
);
253 /* Check if we are re-parsing */
254 if (((OpenPacket
->Override
) && !(RemainingName
->Length
)) ||
255 (AccessState
->Flags
& SE_BACKUP_PRIVILEGES_CHECKED
))
257 /* Get granted access from the last call */
258 DesiredAccess
|= AccessState
->PreviouslyGrantedAccess
;
261 /* Check if this is a volume open */
262 if ((OpenPacket
->RelatedFileObject
) &&
263 (OpenPacket
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
) &&
264 !(RemainingName
->Length
))
270 /* Now check if we need access checks */
271 if (((AccessMode
!= KernelMode
) ||
272 (OpenPacket
->Options
& IO_FORCE_ACCESS_CHECK
)) &&
273 (!(OpenPacket
->RelatedFileObject
) || (VolumeOpen
)) &&
274 !(OpenPacket
->Override
))
276 /* Check if a device object is being parsed */
277 if (!RemainingName
->Length
)
279 /* Lock the subject context */
280 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
283 /* Do access check */
284 AccessGranted
= SeAccessCheck(OriginalDeviceObject
->
286 &AccessState
->SubjectSecurityContext
,
292 TypeInfo
.GenericMapping
,
298 /* Append and free the privileges */
299 SeAppendPrivileges(AccessState
, Privileges
);
300 SeFreePrivileges(Privileges
);
303 /* Check if we got access */
306 /* Update access state */
307 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
308 AccessState
->RemainingDesiredAccess
&= ~(GrantedAccess
&
310 OpenPacket
->Override
= TRUE
;
313 FileString
.Length
= 8;
314 FileString
.MaximumLength
= 8;
315 FileString
.Buffer
= L
"File";
317 /* Do Audit/Alarm for open operation */
318 SeOpenObjectAuditAlarm(&FileString
,
319 OriginalDeviceObject
,
321 OriginalDeviceObject
->SecurityDescriptor
,
326 &AccessState
->GenerateOnClose
);
330 /* Check if we need to do traverse validation */
331 if (!(AccessState
->Flags
& TOKEN_HAS_TRAVERSE_PRIVILEGE
) ||
332 ((OriginalDeviceObject
->DeviceType
== FILE_DEVICE_DISK
) ||
333 (OriginalDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
)))
335 /* Check if this is a restricted token */
336 if (!(AccessState
->Flags
& TOKEN_IS_RESTRICTED
))
338 /* Do the FAST traverse check */
339 AccessGranted
= SeFastTraverseCheck(OriginalDeviceObject
->SecurityDescriptor
,
347 AccessGranted
= FALSE
;
350 /* Check if we failed to get access */
353 /* Lock the subject context */
354 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
357 /* Do access check */
358 AccessGranted
= SeAccessCheck(OriginalDeviceObject
->
360 &AccessState
->SubjectSecurityContext
,
366 TypeInfo
.GenericMapping
,
372 /* Append and free the privileges */
373 SeAppendPrivileges(AccessState
, Privileges
);
374 SeFreePrivileges(Privileges
);
378 /* FIXME: Do Audit/Alarm for traverse check */
382 /* Access automatically granted */
383 AccessGranted
= TRUE
;
387 /* Check if we hold the lock */
391 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
394 /* Check if access failed */
397 /* Dereference the device and fail */
398 DPRINT1("Traverse access failed!\n");
399 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
400 return STATUS_ACCESS_DENIED
;
404 /* Check if we can simply use a dummy file */
405 UseDummyFile
= ((OpenPacket
->QueryOnly
) || (OpenPacket
->DeleteOnly
));
407 /* Check if this is a direct open */
408 if (!(RemainingName
->Length
) &&
409 !(OpenPacket
->RelatedFileObject
) &&
410 ((DesiredAccess
& ~(SYNCHRONIZE
|
411 FILE_READ_ATTRIBUTES
|
413 ACCESS_SYSTEM_SECURITY
|
418 /* Remember this for later */
422 /* FIXME: Small hack still exists, have to check why...
423 * This is triggered multiple times by usetup and then once per boot.
426 !(RemainingName
->Length
) &&
427 !(OpenPacket
->RelatedFileObject
) &&
428 ((wcsstr(CompleteName
->Buffer
, L
"Harddisk")) ||
429 (wcsstr(CompleteName
->Buffer
, L
"Floppy"))) &&
432 DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
433 DesiredAccess
& ~(SYNCHRONIZE
|
434 FILE_READ_ATTRIBUTES
|
436 ACCESS_SYSTEM_SECURITY
|
442 /* Check if we have a related FO that wasn't a direct open */
443 if ((OpenPacket
->RelatedFileObject
) &&
444 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
446 /* The device object is the one we were given */
447 DeviceObject
= ParseObject
;
449 /* Check if the related FO had a VPB */
450 if (OpenPacket
->RelatedFileObject
->Vpb
)
452 /* Yes, remember it */
453 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
456 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
461 /* The device object is the one we were given */
462 DeviceObject
= OriginalDeviceObject
;
464 /* Check if it has a VPB */
465 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
467 /* Check if the VPB is mounted, and mount it */
468 Vpb
= IopCheckVpbMounted(OpenPacket
,
469 OriginalDeviceObject
,
472 if (!Vpb
) return Status
;
474 /* Get the VPB's device object */
475 DeviceObject
= Vpb
->DeviceObject
;
478 /* Check if there's an attached device */
479 if (DeviceObject
->AttachedDevice
)
481 /* Get the attached device */
482 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
486 /* Check if this is a secure FSD */
487 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
488 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
491 DPRINT("Fix Secure FSD support!!!\n");
494 /* Allocate the IRP */
495 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
498 /* Dereference the device and VPB, then fail */
499 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
500 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
501 return STATUS_INSUFFICIENT_RESOURCES
;
504 /* Now set the IRP data */
505 Irp
->RequestorMode
= AccessMode
;
506 Irp
->Flags
= IRP_CREATE_OPERATION
|
507 IRP_SYNCHRONOUS_API
|
508 IRP_DEFER_IO_COMPLETION
;
509 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
510 Irp
->UserIosb
= &IoStatusBlock
;
511 Irp
->MdlAddress
= NULL
;
512 Irp
->PendingReturned
= FALSE
;
513 Irp
->UserEvent
= NULL
;
515 Irp
->CancelRoutine
= NULL
;
516 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
518 /* Setup the security context */
519 SecurityContext
.SecurityQos
= SecurityQos
;
520 SecurityContext
.AccessState
= AccessState
;
521 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
522 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
524 /* Get the I/O Stack location */
525 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
526 StackLoc
->Control
= 0;
528 /* Check what kind of file this is */
529 switch (OpenPacket
->CreateFileType
)
532 case CreateFileTypeNone
:
534 /* Set the major function and EA Length */
535 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
536 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
539 StackLoc
->Flags
= (UCHAR
)OpenPacket
->Options
;
540 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ?
541 SL_CASE_SENSITIVE
: 0;
545 case CreateFileTypeNamedPipe
:
547 /* Set the named pipe MJ and set the parameters */
548 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
549 StackLoc
->Parameters
.CreatePipe
.Parameters
=
550 OpenPacket
->MailslotOrPipeParameters
;
554 case CreateFileTypeMailslot
:
556 /* Set the mailslot MJ and set the parameters */
557 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
558 StackLoc
->Parameters
.CreateMailslot
.Parameters
=
559 OpenPacket
->MailslotOrPipeParameters
;
563 /* Set the common data */
564 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
565 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
566 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
567 (OpenPacket
->CreateOptions
&
569 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
570 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
571 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
573 /* Check if we really need to create an object */
576 /* Create the actual file object */
577 InitializeObjectAttributes(&ObjectAttributes
,
582 Status
= ObCreateObject(KernelMode
,
590 (PVOID
*)&FileObject
);
591 if (!NT_SUCCESS(Status
))
593 /* Create failed, free the IRP */
596 /* Dereference the device and VPB */
597 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
598 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
600 /* We failed, return status */
601 OpenPacket
->FinalStatus
= Status
;
605 /* Clear the file object */
606 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
608 /* Check if this is Synch I/O */
609 if (OpenPacket
->CreateOptions
&
610 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
612 /* Set the synch flag */
613 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
615 /* Check if it's also alertable */
616 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
618 /* It is, set the alertable flag */
619 FileObject
->Flags
|= FO_ALERTABLE_IO
;
623 /* Check if this is synch I/O */
624 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
626 /* Initialize the event */
627 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
630 /* Check if the caller requested no intermediate buffering */
631 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
633 /* Set the correct flag for the FSD to read */
634 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
637 /* Check if the caller requested write through support */
638 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
640 /* Set the correct flag for the FSD to read */
641 FileObject
->Flags
|= FO_WRITE_THROUGH
;
644 /* Check if the caller says the file will be only read sequentially */
645 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
647 /* Set the correct flag for the FSD to read */
648 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
651 /* Check if the caller believes the file will be only read randomly */
652 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
654 /* Set the correct flag for the FSD to read */
655 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
660 /* Use the dummy object instead */
661 DummyFileObject
= OpenPacket
->DummyFileObject
;
662 RtlZeroMemory(DummyFileObject
, sizeof(DUMMY_FILE_OBJECT
));
665 FileObject
= (PFILE_OBJECT
)&DummyFileObject
->ObjectHeader
.Body
;
666 DummyFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
667 DummyFileObject
->ObjectHeader
.PointerCount
= 1;
670 /* Setup the file header */
671 FileObject
->Type
= IO_TYPE_FILE
;
672 FileObject
->Size
= sizeof(FILE_OBJECT
);
673 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
674 FileObject
->DeviceObject
= OriginalDeviceObject
;
676 /* Check if this is a direct device open */
677 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
679 /* Check if the caller wants case sensitivity */
680 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
682 /* Tell the driver about it */
683 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
686 /* Now set the file object */
687 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
688 StackLoc
->FileObject
= FileObject
;
690 /* Check if the file object has a name */
691 if (RemainingName
->Length
)
693 /* Setup the unicode string */
694 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
696 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
701 if (!FileObject
->FileName
.Buffer
)
703 /* Failed to allocate the name, free the IRP */
706 /* Dereference the device object and VPB */
707 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
708 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
710 /* Clear the FO and dereference it */
711 FileObject
->DeviceObject
= NULL
;
712 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
715 return STATUS_INSUFFICIENT_RESOURCES
;
720 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
722 /* Initialize the File Object event and set the FO */
723 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
724 OpenPacket
->FileObject
= FileObject
;
726 /* Queue the IRP and call the driver */
727 IopQueueIrpToThread(Irp
);
728 Status
= IoCallDriver(DeviceObject
, Irp
);
729 if (Status
== STATUS_PENDING
)
731 /* Wait for the driver to complete the create */
732 KeWaitForSingleObject(&FileObject
->Event
,
738 /* Get the new status */
739 Status
= IoStatusBlock
.Status
;
743 /* We'll have to complete it ourselves */
744 ASSERT(!Irp
->PendingReturned
);
745 ASSERT(!Irp
->MdlAddress
);
747 /* Completion happens at APC_LEVEL */
748 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
750 /* Get the new I/O Status block ourselves */
751 IoStatusBlock
= Irp
->IoStatus
;
752 Status
= IoStatusBlock
.Status
;
754 /* Manually signal the even, we can't have any waiters */
755 FileObject
->Event
.Header
.SignalState
= 1;
757 /* Now that we've signaled the events, de-associate the IRP */
758 IopUnQueueIrpFromThread(Irp
);
760 /* Check if the IRP had an input buffer */
761 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
762 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
764 /* Free it. A driver might've tacked one on */
765 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
768 /* Free the IRP and bring the IRQL back down */
770 KeLowerIrql(OldIrql
);
773 /* Copy the I/O Status */
774 OpenPacket
->Information
= IoStatusBlock
.Information
;
776 /* The driver failed to create the file */
777 if (!NT_SUCCESS(Status
))
779 /* Check if we have a name */
780 if (FileObject
->FileName
.Length
)
783 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
784 FileObject
->FileName
.Length
= 0;
787 /* Clear its device object */
788 FileObject
->DeviceObject
= NULL
;
790 /* Save this now because the FO might go away */
791 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
794 /* Clear the file object in the open packet */
795 OpenPacket
->FileObject
= NULL
;
797 /* Dereference the file object */
798 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
800 /* Dereference the device object */
801 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
803 /* Unless the driver cancelled the open, dereference the VPB */
804 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpbAndFree(Vpb
);
806 /* Set the status and return */
807 OpenPacket
->FinalStatus
= Status
;
810 else if (Status
== STATUS_REPARSE
)
812 /* FIXME: We don't handle this at all! */
816 /* Get the owner of the File Object */
817 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
820 * It's possible that the device to whom we sent the IRP to
821 * isn't actually the device that ended opening the file object
824 if (OwnerDevice
!= DeviceObject
)
826 /* We have to de-reference the VPB we had associated */
827 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
829 /* And re-associate with the actual one */
830 Vpb
= FileObject
->Vpb
;
831 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
834 /* Make sure we are not using a dummy */
837 /* Check if this was a volume open */
838 if ((!(FileObject
->RelatedFileObject
) ||
839 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
840 !(FileObject
->FileName
.Length
))
842 /* All signs point to it, but make sure it was actually an FSD */
843 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
844 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
845 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
846 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
848 /* The owner device is an FSD, so this is a volume open for real */
849 FileObject
->Flags
|= FO_VOLUME_OPEN
;
853 /* Reference the object and set the parse check */
854 ObReferenceObject(FileObject
);
855 *Object
= FileObject
;
856 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
857 OpenPacket
->ParseCheck
= TRUE
;
858 return OpenPacket
->FinalStatus
;
862 /* Check if this was a query */
863 if (OpenPacket
->QueryOnly
)
865 /* Check if the caller wants basic info only */
866 if (!OpenPacket
->FullAttributes
)
868 /* Allocate the buffer */
869 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
870 sizeof(*FileBasicInfo
),
875 Status
= IoQueryFileInformation(FileObject
,
876 FileBasicInformation
,
877 sizeof(*FileBasicInfo
),
880 if (NT_SUCCESS(Status
))
883 RtlCopyMemory(OpenPacket
->BasicInformation
,
888 /* Free our buffer */
889 ExFreePoolWithTag(FileBasicInfo
, TAG_IO
);
894 Status
= STATUS_INSUFFICIENT_RESOURCES
;
899 /* This is a full query */
900 Status
= IoQueryFileInformation(
902 FileNetworkOpenInformation
,
903 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
904 OpenPacket
->NetworkInformation
,
906 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
910 /* Delete the file object */
911 IopDeleteFile(FileObject
);
913 /* Clear out the file */
914 OpenPacket
->FileObject
= NULL
;
916 /* Set and return status */
917 OpenPacket
->FinalStatus
= Status
;
918 OpenPacket
->ParseCheck
= TRUE
;
925 IopParseFile(IN PVOID ParseObject
,
927 IN OUT PACCESS_STATE AccessState
,
928 IN KPROCESSOR_MODE AccessMode
,
930 IN OUT PUNICODE_STRING CompleteName
,
931 IN OUT PUNICODE_STRING RemainingName
,
932 IN OUT PVOID Context OPTIONAL
,
933 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
937 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
939 /* Validate the open packet */
940 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
942 /* Get the device object */
943 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
944 OpenPacket
->RelatedFileObject
= ParseObject
;
946 /* Call the main routine */
947 return IopParseDevice(DeviceObject
,
961 IopDeleteFile(IN PVOID ObjectBody
)
963 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
965 PIO_STACK_LOCATION StackPtr
;
968 PDEVICE_OBJECT DeviceObject
;
969 BOOLEAN DereferenceDone
= FALSE
;
972 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
974 /* Check if the file has a device object */
975 if (FileObject
->DeviceObject
)
977 /* Check if this is a direct open or not */
978 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
980 /* Get the attached device */
981 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
985 /* Use the file object's device object */
986 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
990 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
991 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
993 /* Check if the handle wasn't created yet */
994 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
996 /* Send the cleanup IRP */
997 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
1000 /* Clear and set up Events */
1001 KeClearEvent(&FileObject
->Event
);
1002 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1004 /* Allocate an IRP */
1005 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1009 Irp
->UserEvent
= &Event
;
1010 Irp
->UserIosb
= &Irp
->IoStatus
;
1011 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1012 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1013 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1015 /* Set up Stack Pointer Data */
1016 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1017 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
1018 StackPtr
->FileObject
= FileObject
;
1021 IopQueueIrpToThread(Irp
);
1023 /* Get the VPB and check if this isn't a direct open */
1024 Vpb
= FileObject
->Vpb
;
1025 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1027 /* Dereference the VPB before the close */
1028 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1031 /* Check if the FS will never disappear by itself */
1032 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1034 /* Dereference it */
1035 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1036 DereferenceDone
= TRUE
;
1039 /* Call the FS Driver */
1040 Status
= IoCallDriver(DeviceObject
, Irp
);
1041 if (Status
== STATUS_PENDING
)
1043 /* Wait for completion */
1044 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1047 /* De-queue the IRP */
1048 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1049 IopUnQueueIrpFromThread(Irp
);
1050 KeLowerIrql(OldIrql
);
1055 /* Clear the file name */
1056 if (FileObject
->FileName
.Buffer
)
1058 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1059 FileObject
->FileName
.Buffer
= NULL
;
1062 /* Check if the FO had a completion port */
1063 if (FileObject
->CompletionContext
)
1066 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1067 ExFreePool(FileObject
->CompletionContext
);
1070 /* Check if the FO had extension */
1071 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1073 /* Release filter context structure if any */
1074 FsRtlPTeardownPerFileObjectContexts(FileObject
);
1077 /* Check if dereference has been done yet */
1078 if (!DereferenceDone
)
1080 /* Dereference device object */
1081 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1088 IopSecurityFile(IN PVOID ObjectBody
,
1089 IN SECURITY_OPERATION_CODE OperationCode
,
1090 IN PSECURITY_INFORMATION SecurityInformation
,
1091 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1092 IN OUT PULONG BufferLength
,
1093 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1094 IN POOL_TYPE PoolType
,
1095 IN OUT PGENERIC_MAPPING GenericMapping
)
1097 IO_STATUS_BLOCK IoStatusBlock
;
1098 PIO_STACK_LOCATION StackPtr
;
1099 PFILE_OBJECT FileObject
;
1100 PDEVICE_OBJECT DeviceObject
;
1102 BOOLEAN LocalEvent
= FALSE
;
1104 NTSTATUS Status
= STATUS_SUCCESS
;
1106 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1108 /* Check if this is a device or file */
1109 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1112 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1118 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1120 /* Check if this is a direct open */
1121 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1123 /* Get the Device Object */
1124 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1128 /* Otherwise, use the direct device*/
1129 DeviceObject
= FileObject
->DeviceObject
;
1133 /* Check if the request was for a device object */
1134 if (!(FileObject
) ||
1135 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1136 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1138 /* Check what kind of request this was */
1139 if (OperationCode
== QuerySecurityDescriptor
)
1141 return SeQuerySecurityDescriptorInfo(SecurityInformation
,
1144 &DeviceObject
->SecurityDescriptor
);
1146 else if (OperationCode
== DeleteSecurityDescriptor
)
1148 /* Simply return success */
1149 return STATUS_SUCCESS
;
1151 else if (OperationCode
== AssignSecurityDescriptor
)
1153 /* Make absolutely sure this is a device object */
1154 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1156 /* Assign the Security Descriptor */
1157 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
1160 /* Return success */
1161 return STATUS_SUCCESS
;
1165 DPRINT1("FIXME: Set SD unimplemented for Devices\n");
1166 return STATUS_SUCCESS
;
1169 else if (OperationCode
== DeleteSecurityDescriptor
)
1171 /* Same as for devices, do nothing */
1172 return STATUS_SUCCESS
;
1175 /* At this point, we know we're a file. Reference it */
1176 ObReferenceObject(FileObject
);
1178 /* Check if we should use Sync IO or not */
1179 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1181 /* Lock the file object */
1182 IopLockFileObject(FileObject
);
1186 /* Use local event */
1187 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1191 /* Clear the File Object event */
1192 KeClearEvent(&FileObject
->Event
);
1194 /* Get the device object */
1195 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1197 /* Allocate the IRP */
1198 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1199 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1202 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1203 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1204 Irp
->RequestorMode
= ExGetPreviousMode();
1205 Irp
->UserIosb
= &IoStatusBlock
;
1206 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1207 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1208 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1210 /* Set Stack Parameters */
1211 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1212 StackPtr
->FileObject
= FileObject
;
1214 /* Check if this is a query or set */
1215 if (OperationCode
== QuerySecurityDescriptor
)
1217 /* Set the major function and parameters */
1218 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1219 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1220 *SecurityInformation
;
1221 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1222 Irp
->UserBuffer
= SecurityDescriptor
;
1226 /* Set the major function and parameters for a set */
1227 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1228 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1229 *SecurityInformation
;
1230 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1235 IopQueueIrpToThread(Irp
);
1237 /* Update operation counts */
1238 IopUpdateOperationCount(IopOtherTransfer
);
1240 /* Call the Driver */
1241 Status
= IoCallDriver(DeviceObject
, Irp
);
1243 /* Check if this was async I/O */
1246 /* Check if the IRP is pending completion */
1247 if (Status
== STATUS_PENDING
)
1249 /* Wait on the local event */
1250 KeWaitForSingleObject(&Event
,
1255 Status
= IoStatusBlock
.Status
;
1260 /* Check if the IRP is pending completion */
1261 if (Status
== STATUS_PENDING
)
1263 /* Wait on the file object */
1264 KeWaitForSingleObject(&FileObject
->Event
,
1269 Status
= FileObject
->FinalStatus
;
1272 /* Release the lock */
1273 IopUnlockFileObject(FileObject
);
1276 /* This Driver doesn't implement Security, so try to give it a default */
1277 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1279 /* Was this a query? */
1280 if (OperationCode
== QuerySecurityDescriptor
)
1282 /* Set a World Security Descriptor */
1283 Status
= SeSetWorldSecurityDescriptor(*SecurityInformation
,
1289 /* It wasn't a query, so just fake success */
1290 Status
= STATUS_SUCCESS
;
1293 else if (OperationCode
== QuerySecurityDescriptor
)
1295 /* Callers usually expect the normalized form */
1296 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1301 *BufferLength
= (ULONG
)IoStatusBlock
.Information
;
1303 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1305 /* Get the exception code */
1306 Status
= _SEH2_GetExceptionCode();
1317 IopQueryNameFile(IN PVOID ObjectBody
,
1319 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1321 OUT PULONG ReturnLength
,
1322 IN KPROCESSOR_MODE PreviousMode
)
1324 POBJECT_NAME_INFORMATION LocalInfo
;
1325 PFILE_NAME_INFORMATION LocalFileInfo
;
1326 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1327 ULONG LocalReturnLength
, FileLength
;
1328 BOOLEAN LengthMismatch
= FALSE
;
1331 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1333 /* Validate length */
1334 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1336 /* Wrong length, fail */
1337 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
1338 return STATUS_INFO_LENGTH_MISMATCH
;
1341 /* Allocate Buffer */
1342 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1343 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1345 /* Query the name */
1346 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1349 &LocalReturnLength
);
1350 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1352 /* Free the buffer and fail */
1353 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1357 /* Copy the information */
1358 RtlCopyMemory(ObjectNameInfo
,
1360 (LocalReturnLength
> Length
) ?
1361 Length
: LocalReturnLength
);
1363 /* Set buffer pointer */
1364 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1365 ObjectNameInfo
->Name
.Buffer
= p
;
1367 /* Advance in buffer */
1368 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1370 /* Check if this already filled our buffer */
1371 if (LocalReturnLength
> Length
)
1373 /* Set the length mismatch to true, so that we can return
1374 * the proper buffer size to the caller later
1376 LengthMismatch
= TRUE
;
1378 /* Save the initial buffer length value */
1379 *ReturnLength
= LocalReturnLength
;
1382 /* Now get the file name buffer and check the length needed */
1383 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1384 FileLength
= Length
-
1386 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1388 /* Query the File name */
1389 Status
= IoQueryFileInformation(FileObject
,
1390 FileNameInformation
,
1391 LengthMismatch
? Length
: FileLength
,
1393 &LocalReturnLength
);
1394 if (NT_ERROR(Status
))
1396 /* Fail on errors only, allow warnings */
1397 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1401 /* If the provided buffer is too small, return the required size */
1404 /* Add the required length */
1405 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1407 /* Free the allocated buffer and return failure */
1408 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1409 return STATUS_BUFFER_OVERFLOW
;
1412 /* Now calculate the new lengths left */
1413 FileLength
= LocalReturnLength
-
1414 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1415 LocalReturnLength
= (ULONG
)((ULONG_PTR
)p
-
1416 (ULONG_PTR
)ObjectNameInfo
+
1417 LocalFileInfo
->FileNameLength
);
1419 /* Write the Name and null-terminate it */
1420 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1421 p
+= (FileLength
/ sizeof(WCHAR
));
1423 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1425 /* Return the length needed */
1426 *ReturnLength
= LocalReturnLength
;
1428 /* Setup the length and maximum length */
1429 FileLength
= (ULONG
)((ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
);
1430 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1431 sizeof(OBJECT_NAME_INFORMATION
);
1432 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1433 sizeof(UNICODE_NULL
);
1435 /* Free buffer and return */
1436 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1442 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1443 IN PVOID ObjectBody
,
1444 IN ACCESS_MASK GrantedAccess
,
1445 IN ULONG HandleCount
,
1446 IN ULONG SystemHandleCount
)
1448 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1451 PIO_STACK_LOCATION StackPtr
;
1453 PDEVICE_OBJECT DeviceObject
;
1455 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1457 /* If this isn't the last handle for the current process, quit */
1458 if (HandleCount
!= 1) return;
1460 /* Check if the file is locked and has more then one handle opened */
1461 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1463 DPRINT1("We need to unlock this file!\n");
1467 /* Make sure this is the last handle */
1468 if (SystemHandleCount
!= 1) return;
1470 /* Check if this is a direct open or not */
1471 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1473 /* Get the attached device */
1474 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1478 /* Get the FO's device */
1479 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1482 /* Set the handle created flag */
1483 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1485 /* Check if this is a sync FO and lock it */
1486 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1488 /* Clear and set up Events */
1489 KeClearEvent(&FileObject
->Event
);
1490 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1492 /* Allocate an IRP */
1493 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1497 Irp
->UserEvent
= &Event
;
1498 Irp
->UserIosb
= &Irp
->IoStatus
;
1499 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1500 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1501 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1502 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1504 /* Set up Stack Pointer Data */
1505 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1506 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1507 StackPtr
->FileObject
= FileObject
;
1510 IopQueueIrpToThread(Irp
);
1512 /* Update operation counts */
1513 IopUpdateOperationCount(IopOtherTransfer
);
1515 /* Call the FS Driver */
1516 Status
= IoCallDriver(DeviceObject
, Irp
);
1517 if (Status
== STATUS_PENDING
)
1519 /* Wait for completion */
1520 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1523 /* Unqueue the IRP */
1524 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1525 IopUnQueueIrpFromThread(Irp
);
1526 KeLowerIrql(OldIrql
);
1531 /* Release the lock if we were holding it */
1532 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1537 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1538 IN FILE_INFORMATION_CLASS FileInformationClass
,
1539 IN ULONG FileInformationSize
,
1540 OUT PVOID FileInformation
)
1543 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1544 DUMMY_FILE_OBJECT DummyFileObject
;
1545 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1547 OPEN_PACKET OpenPacket
;
1550 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
1552 /* Check if the caller was user mode */
1553 if (AccessMode
!= KernelMode
)
1555 /* Protect probe in SEH */
1558 /* Probe the buffer */
1559 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
1561 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1563 /* Return the exception code */
1564 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1569 /* Check if this is a basic or full request */
1570 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
1572 /* Setup the Open Packet */
1573 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1574 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1575 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1576 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
1577 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
1578 OpenPacket
.Disposition
= FILE_OPEN
;
1579 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
1580 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
1581 (AccessMode
!= KernelMode
) ?
1582 &NetworkOpenInfo
: FileInformation
;
1583 OpenPacket
.QueryOnly
= TRUE
;
1584 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
1585 OpenPacket
.DummyFileObject
= &DummyFileObject
;
1587 /* Update the operation count */
1588 IopUpdateOperationCount(IopOtherTransfer
);
1591 * Attempt opening the file. This will call the I/O Parse Routine for
1592 * the File Object (IopParseDevice) which will use the dummy file obejct
1593 * send the IRP to its device object. Note that we have two statuses
1594 * to worry about: the Object Manager's status (in Status) and the I/O
1595 * status, which is in the Open Packet's Final Status, and determined
1596 * by the Parse Check member.
1598 Status
= ObOpenObjectByName(ObjectAttributes
,
1602 FILE_READ_ATTRIBUTES
,
1605 if (OpenPacket
.ParseCheck
!= TRUE
)
1612 /* Use the Io status */
1613 Status
= OpenPacket
.FinalStatus
;
1616 /* Check if we were succesful and this was user mode and a full query */
1617 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
1619 /* Enter SEH for copy */
1622 /* Copy the buffer back */
1623 RtlCopyMemory(FileInformation
,
1625 FileInformationSize
);
1627 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1629 /* Get exception code */
1630 Status
= _SEH2_GetExceptionCode();
1641 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject
)
1643 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1646 /* FIXME: return NULL for the moment ~ */
1655 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject
,
1656 IN PVOID FilterContext
,
1659 if (!(FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
))
1661 return STATUS_INVALID_PARAMETER
;
1666 return STATUS_NOT_IMPLEMENTED
;
1669 /* FUNCTIONS *****************************************************************/
1676 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
1678 IN BOOLEAN SetOperation
)
1681 return STATUS_NOT_IMPLEMENTED
;
1689 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
1690 IN ULONG QuotaLength
,
1691 OUT PULONG ErrorOffset
)
1694 return STATUS_NOT_IMPLEMENTED
;
1702 IoCreateFile(OUT PHANDLE FileHandle
,
1703 IN ACCESS_MASK DesiredAccess
,
1704 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1705 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1706 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1707 IN ULONG FileAttributes
,
1708 IN ULONG ShareAccess
,
1709 IN ULONG Disposition
,
1710 IN ULONG CreateOptions
,
1711 IN PVOID EaBuffer OPTIONAL
,
1713 IN CREATE_FILE_TYPE CreateFileType
,
1714 IN PVOID ExtraCreateParameters OPTIONAL
,
1717 KPROCESSOR_MODE AccessMode
;
1718 HANDLE LocalHandle
= 0;
1719 LARGE_INTEGER SafeAllocationSize
;
1720 volatile PVOID SystemEaBuffer
= NULL
;
1721 NTSTATUS Status
= STATUS_SUCCESS
;
1722 OPEN_PACKET OpenPacket
;
1723 ULONG EaErrorOffset
;
1726 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
1728 /* Check if we have no parameter checking to do */
1729 if (Options
& IO_NO_PARAMETER_CHECKING
)
1731 /* Then force kernel-mode access to avoid checks */
1732 AccessMode
= KernelMode
;
1736 /* Otherwise, use the actual mode */
1737 AccessMode
= ExGetPreviousMode();
1740 /* Check if the call came from user mode */
1741 if (AccessMode
!= KernelMode
)
1745 ProbeForWriteHandle(FileHandle
);
1746 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1749 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
1753 SafeAllocationSize
.QuadPart
= 0;
1756 if ((EaBuffer
) && (EaLength
))
1758 ProbeForRead(EaBuffer
, EaLength
, sizeof(ULONG
));
1760 /* marshal EaBuffer */
1761 SystemEaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1766 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1769 RtlCopyMemory(SystemEaBuffer
, EaBuffer
, EaLength
);
1771 /* Validate the buffer */
1772 Status
= IoCheckEaBufferValidity(SystemEaBuffer
,
1775 IoStatusBlock
->Status
= Status
;
1776 IoStatusBlock
->Information
= EaErrorOffset
;
1779 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1781 /* Return the exception code */
1782 Status
= _SEH2_GetExceptionCode();
1788 /* Check if this is a device attach */
1789 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
1791 /* Set the flag properly */
1792 Options
|= IO_ATTACH_DEVICE
;
1793 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
1796 /* Check if we have allocation size */
1800 SafeAllocationSize
= *AllocationSize
;
1804 /* Otherwise, no size */
1805 SafeAllocationSize
.QuadPart
= 0;
1808 /* Check if we have an EA packet */
1809 if ((EaBuffer
) && (EaLength
))
1811 /* Allocate the kernel copy */
1812 SystemEaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1815 if (!SystemEaBuffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1818 RtlCopyMemory(SystemEaBuffer
, EaBuffer
, EaLength
);
1820 /* Validate the buffer */
1821 Status
= IoCheckEaBufferValidity(SystemEaBuffer
,
1824 IoStatusBlock
->Status
= Status
;
1825 IoStatusBlock
->Information
= EaErrorOffset
;
1829 if (!NT_SUCCESS(Status
))
1831 DPRINT1("FIXME: IoCheckEaBufferValidity() failed with Status: %lx\n",
1834 /* Free SystemEaBuffer if needed and return the error */
1835 if (SystemEaBuffer
) ExFreePoolWithTag(SystemEaBuffer
, TAG_EA
);
1839 /* Setup the Open Packet */
1840 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1841 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1842 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1843 OpenPacket
.OriginalAttributes
= *ObjectAttributes
;
1844 OpenPacket
.AllocationSize
= SafeAllocationSize
;
1845 OpenPacket
.CreateOptions
= CreateOptions
;
1846 OpenPacket
.FileAttributes
= (USHORT
)FileAttributes
;
1847 OpenPacket
.ShareAccess
= (USHORT
)ShareAccess
;
1848 OpenPacket
.EaBuffer
= SystemEaBuffer
;
1849 OpenPacket
.EaLength
= EaLength
;
1850 OpenPacket
.Options
= Options
;
1851 OpenPacket
.Disposition
= Disposition
;
1852 OpenPacket
.CreateFileType
= CreateFileType
;
1853 OpenPacket
.MailslotOrPipeParameters
= ExtraCreateParameters
;
1855 /* Update the operation count */
1856 IopUpdateOperationCount(IopOtherTransfer
);
1859 * Attempt opening the file. This will call the I/O Parse Routine for
1860 * the File Object (IopParseDevice) which will create the object and
1861 * send the IRP to its device object. Note that we have two statuses
1862 * to worry about: the Object Manager's status (in Status) and the I/O
1863 * status, which is in the Open Packet's Final Status, and determined
1864 * by the Parse Check member.
1866 Status
= ObOpenObjectByName(ObjectAttributes
,
1874 /* Free the EA Buffer */
1875 if (OpenPacket
.EaBuffer
) ExFreePool(OpenPacket
.EaBuffer
);
1877 /* Now check for Ob or Io failure */
1878 if (!(NT_SUCCESS(Status
)) || (OpenPacket
.ParseCheck
!= TRUE
))
1880 /* Check if Ob thinks well went well */
1881 if (NT_SUCCESS(Status
))
1884 * Tell it otherwise. Because we didn't use an ObjectType,
1885 * it incorrectly returned us a handle to God knows what.
1887 ZwClose(LocalHandle
);
1888 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
1891 /* Now check the Io status */
1892 if (!NT_SUCCESS(OpenPacket
.FinalStatus
))
1894 /* Use this status instead of Ob's */
1895 Status
= OpenPacket
.FinalStatus
;
1897 /* Check if it was only a warning */
1898 if (NT_WARNING(Status
))
1900 /* Protect write with SEH */
1903 /* In this case, we copy the I/O Status back */
1904 IoStatusBlock
->Information
= OpenPacket
.Information
;
1905 IoStatusBlock
->Status
= OpenPacket
.FinalStatus
;
1907 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1909 /* Get exception code */
1910 Status
= _SEH2_GetExceptionCode();
1915 else if ((OpenPacket
.FileObject
) && (OpenPacket
.ParseCheck
!= 1))
1918 * This can happen in the very bizarre case where the parse routine
1919 * actually executed more then once (due to a reparse) and ended
1920 * up failing after already having created the File Object.
1922 if (OpenPacket
.FileObject
->FileName
.Length
)
1924 /* It had a name, free it */
1925 ExFreePoolWithTag(OpenPacket
.FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1928 /* Clear the device object to invalidate the FO, and dereference */
1929 OpenPacket
.FileObject
->DeviceObject
= NULL
;
1930 ObDereferenceObject(OpenPacket
.FileObject
);
1935 /* We reached success and have a valid file handle */
1936 OpenPacket
.FileObject
->Flags
|= FO_HANDLE_CREATED
;
1938 /* Enter SEH for write back */
1941 /* Write back the handle and I/O Status */
1942 *FileHandle
= LocalHandle
;
1943 IoStatusBlock
->Information
= OpenPacket
.Information
;
1944 IoStatusBlock
->Status
= OpenPacket
.FinalStatus
;
1946 /* Get the Io status */
1947 Status
= OpenPacket
.FinalStatus
;
1949 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1951 /* Get the exception status */
1952 Status
= _SEH2_GetExceptionCode();
1957 /* Check if we were 100% successful */
1958 if ((OpenPacket
.ParseCheck
== TRUE
) && (OpenPacket
.FileObject
))
1960 /* Dereference the File Object */
1961 ObDereferenceObject(OpenPacket
.FileObject
);
1973 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1974 IN ACCESS_MASK DesiredAccess
,
1975 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1976 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1977 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1978 IN ULONG FileAttributes
,
1979 IN ULONG ShareAccess
,
1980 IN ULONG Disposition
,
1981 IN ULONG CreateOptions
,
1982 IN PVOID EaBuffer OPTIONAL
,
1984 IN CREATE_FILE_TYPE CreateFileType
,
1985 IN PVOID ExtraCreateParameters OPTIONAL
,
1987 IN PVOID DeviceObject
)
1990 return STATUS_NOT_IMPLEMENTED
;
1998 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1999 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
2000 OUT PHANDLE FileObjectHandle OPTIONAL
)
2002 PFILE_OBJECT CreatedFileObject
;
2005 OBJECT_ATTRIBUTES ObjectAttributes
;
2007 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2009 /* Choose Device Object */
2010 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2012 /* Reference the device object and initialize attributes */
2013 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2014 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2016 /* Create the File Object */
2017 Status
= ObCreateObject(KernelMode
,
2022 sizeof(FILE_OBJECT
),
2023 sizeof(FILE_OBJECT
),
2025 (PVOID
*)&CreatedFileObject
);
2026 if (!NT_SUCCESS(Status
))
2029 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2030 ExRaiseStatus(Status
);
2033 /* Set File Object Data */
2034 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2035 CreatedFileObject
->DeviceObject
= DeviceObject
;
2036 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2037 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2038 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2040 /* Initialize the wait event */
2041 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2043 /* Insert it to create a handle for it */
2044 Status
= ObInsertObject(CreatedFileObject
,
2048 (PVOID
*)&CreatedFileObject
,
2050 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2052 /* Set the handle created flag */
2053 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2054 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2056 /* Check if we have a VPB */
2057 if (DeviceObject
->Vpb
)
2060 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2063 /* Check if the caller wants the handle */
2064 if (FileObjectHandle
)
2067 *FileObjectHandle
= FileHandle
;
2068 ObDereferenceObject(CreatedFileObject
);
2072 /* Otherwise, close it */
2073 ObCloseHandle(FileHandle
, KernelMode
);
2076 /* Return the file object */
2077 return CreatedFileObject
;
2085 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2086 IN PDEVICE_OBJECT DeviceObject
)
2088 /* Call the newer function */
2089 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2097 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2098 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2100 PFILE_OBJECT CreatedFileObject
;
2102 OBJECT_ATTRIBUTES ObjectAttributes
;
2104 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2106 /* Choose Device Object */
2107 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2109 /* Reference the device object and initialize attributes */
2110 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2111 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2113 /* Create the File Object */
2114 Status
= ObCreateObject(KernelMode
,
2119 sizeof(FILE_OBJECT
),
2120 sizeof(FILE_OBJECT
),
2122 (PVOID
*)&CreatedFileObject
);
2123 if (!NT_SUCCESS(Status
))
2126 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2127 ExRaiseStatus(Status
);
2130 /* Set File Object Data */
2131 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2132 CreatedFileObject
->DeviceObject
= DeviceObject
;
2133 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2134 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2135 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2137 /* Initialize the wait event */
2138 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2140 /* Destroy create information */
2141 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2143 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2145 /* Set the handle created flag */
2146 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2147 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2149 /* Check if we have a VPB */
2150 if (DeviceObject
->Vpb
)
2153 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2156 /* Return the file object */
2157 return CreatedFileObject
;
2165 IoGetFileObjectGenericMapping(VOID
)
2167 /* Return the mapping */
2168 return &IopFileMapping
;
2176 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2178 /* Return the flag status */
2179 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2187 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2188 IN ACCESS_MASK DesiredAccess
,
2189 IN ULONG OpenOptions
,
2190 OUT PIO_STATUS_BLOCK IoStatus
,
2191 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2194 DUMMY_FILE_OBJECT DummyFileObject
;
2196 OPEN_PACKET OpenPacket
;
2198 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2200 /* Setup the Open Packet */
2201 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2202 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2203 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2204 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2205 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2206 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2207 OpenPacket
.Disposition
= FILE_OPEN
;
2208 OpenPacket
.NetworkInformation
= Buffer
;
2209 OpenPacket
.QueryOnly
= TRUE
;
2210 OpenPacket
.FullAttributes
= TRUE
;
2211 OpenPacket
.DummyFileObject
= &DummyFileObject
;
2214 * Attempt opening the file. This will call the I/O Parse Routine for
2215 * the File Object (IopParseDevice) which will use the dummy file obejct
2216 * send the IRP to its device object. Note that we have two statuses
2217 * to worry about: the Object Manager's status (in Status) and the I/O
2218 * status, which is in the Open Packet's Final Status, and determined
2219 * by the Parse Check member.
2221 Status
= ObOpenObjectByName(ObjectAttributes
,
2228 if (OpenPacket
.ParseCheck
!= TRUE
)
2231 IoStatus
->Status
= Status
;
2235 /* Use the Io status */
2236 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2237 IoStatus
->Information
= OpenPacket
.Information
;
2240 /* Return success */
2249 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2250 OUT PSHARE_ACCESS ShareAccess
)
2254 /* Check if the file has an extension */
2255 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2257 /* Check if caller specified to ignore access checks */
2258 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2260 /* Don't update share access */
2265 /* Otherwise, check if there's any access present */
2266 if ((FileObject
->ReadAccess
) ||
2267 (FileObject
->WriteAccess
) ||
2268 (FileObject
->DeleteAccess
))
2270 /* Increase the open count */
2271 ShareAccess
->OpenCount
++;
2273 /* Add new share access */
2274 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2275 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2276 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2277 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2278 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2279 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2288 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2289 IN ULONG DesiredShareAccess
,
2290 IN PFILE_OBJECT FileObject
,
2291 IN PSHARE_ACCESS ShareAccess
,
2295 BOOLEAN WriteAccess
;
2296 BOOLEAN DeleteAccess
;
2298 BOOLEAN SharedWrite
;
2299 BOOLEAN SharedDelete
;
2302 /* Get access masks */
2303 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2304 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2305 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2307 /* Set them in the file object */
2308 FileObject
->ReadAccess
= ReadAccess
;
2309 FileObject
->WriteAccess
= WriteAccess
;
2310 FileObject
->DeleteAccess
= DeleteAccess
;
2312 /* Check if the file has an extension */
2313 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2315 /* Check if caller specified to ignore access checks */
2316 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2318 /* Don't check share access */
2319 return STATUS_SUCCESS
;
2323 /* Check if we have any access */
2324 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2326 /* Get shared access masks */
2327 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2328 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2329 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2332 FileObject
->SharedRead
= SharedRead
;
2333 FileObject
->SharedWrite
= SharedWrite
;
2334 FileObject
->SharedDelete
= SharedDelete
;
2336 /* Check if the shared access is violated */
2338 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2340 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2342 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2343 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2344 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2345 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2347 /* Sharing violation, fail */
2348 return STATUS_SHARING_VIOLATION
;
2351 /* It's not, check if caller wants us to update it */
2354 /* Increase open count */
2355 ShareAccess
->OpenCount
++;
2357 /* Update shared access */
2358 ShareAccess
->Readers
+= ReadAccess
;
2359 ShareAccess
->Writers
+= WriteAccess
;
2360 ShareAccess
->Deleters
+= DeleteAccess
;
2361 ShareAccess
->SharedRead
+= SharedRead
;
2362 ShareAccess
->SharedWrite
+= SharedWrite
;
2363 ShareAccess
->SharedDelete
+= SharedDelete
;
2367 /* Validation successful */
2368 return STATUS_SUCCESS
;
2376 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2377 IN PSHARE_ACCESS ShareAccess
)
2381 /* Check if the file has an extension */
2382 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2384 /* Check if caller specified to ignore access checks */
2385 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2387 /* Don't update share access */
2392 /* Otherwise, check if there's any access present */
2393 if ((FileObject
->ReadAccess
) ||
2394 (FileObject
->WriteAccess
) ||
2395 (FileObject
->DeleteAccess
))
2397 /* Decrement the open count */
2398 ShareAccess
->OpenCount
--;
2400 /* Remove share access */
2401 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
2402 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
2403 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
2404 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
2405 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
2406 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
2415 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
2416 IN ULONG DesiredShareAccess
,
2417 IN PFILE_OBJECT FileObject
,
2418 OUT PSHARE_ACCESS ShareAccess
)
2421 BOOLEAN WriteAccess
;
2422 BOOLEAN DeleteAccess
;
2424 BOOLEAN SharedWrite
;
2425 BOOLEAN SharedDelete
;
2426 BOOLEAN Update
= TRUE
;
2429 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2430 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2431 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2433 /* Check if the file has an extension */
2434 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2436 /* Check if caller specified to ignore access checks */
2437 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2439 /* Don't update share access */
2444 /* Update basic access */
2445 FileObject
->ReadAccess
= ReadAccess
;
2446 FileObject
->WriteAccess
= WriteAccess
;
2447 FileObject
->DeleteAccess
= DeleteAccess
;
2449 /* Check if we have no access as all */
2450 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
2452 /* Check if we need to update the structure */
2453 if (!Update
) return;
2455 /* Otherwise, clear data */
2456 ShareAccess
->OpenCount
= 0;
2457 ShareAccess
->Readers
= 0;
2458 ShareAccess
->Writers
= 0;
2459 ShareAccess
->Deleters
= 0;
2460 ShareAccess
->SharedRead
= 0;
2461 ShareAccess
->SharedWrite
= 0;
2462 ShareAccess
->SharedDelete
= 0;
2466 /* Calculate shared access */
2467 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2468 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2469 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2471 /* Set it in the FO */
2472 FileObject
->SharedRead
= SharedRead
;
2473 FileObject
->SharedWrite
= SharedWrite
;
2474 FileObject
->SharedDelete
= SharedDelete
;
2476 /* Check if we need to update the structure */
2477 if (!Update
) return;
2479 /* Otherwise, set data */
2480 ShareAccess
->OpenCount
= 1;
2481 ShareAccess
->Readers
= ReadAccess
;
2482 ShareAccess
->Writers
= WriteAccess
;
2483 ShareAccess
->Deleters
= DeleteAccess
;
2484 ShareAccess
->SharedRead
= SharedRead
;
2485 ShareAccess
->SharedWrite
= SharedWrite
;
2486 ShareAccess
->SharedDelete
= SharedDelete
;
2495 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
2496 IN PFILE_OBJECT FileObject
)
2502 PIO_STACK_LOCATION Stack
;
2504 /* Check if handles were already created for the
2505 * open file. If so, that's over.
2507 if (FileObject
->Flags
& FO_HANDLE_CREATED
)
2508 KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN
,
2509 (ULONG_PTR
)FileObject
,
2510 (ULONG_PTR
)DeviceObject
, 0, 0);
2512 /* Reset the events */
2513 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2514 KeClearEvent(&FileObject
->Event
);
2516 /* Allocate the IRP we'll use */
2517 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
2518 /* Properly set it */
2519 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2520 Irp
->UserEvent
= &Event
;
2521 Irp
->UserIosb
= &Irp
->IoStatus
;
2522 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2523 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2524 Irp
->RequestorMode
= KernelMode
;
2525 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
2527 Stack
= IoGetNextIrpStackLocation(Irp
);
2528 Stack
->MajorFunction
= IRP_MJ_CLEANUP
;
2529 Stack
->FileObject
= FileObject
;
2531 /* Put on top of IRPs list of the thread */
2532 IopQueueIrpToThread(Irp
);
2534 /* Call the driver */
2535 Status
= IoCallDriver(DeviceObject
, Irp
);
2536 if (Status
== STATUS_PENDING
)
2538 KeWaitForSingleObject(&Event
, UserRequest
,
2539 KernelMode
, FALSE
, NULL
);
2542 /* Remove from IRPs list */
2543 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2544 IopUnQueueIrpFromThread(Irp
);
2545 KeLowerIrql(OldIrql
);
2550 /* Clear the event */
2551 KeClearEvent(&FileObject
->Event
);
2552 /* And finally, mark the open operation as canceled */
2553 FileObject
->Flags
|= FO_FILE_OPEN_CANCELLED
;
2561 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
2562 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
2565 return STATUS_NOT_IMPLEMENTED
;
2573 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
2576 NTSTATUS Status
= STATUS_SUCCESS
;
2579 /* Get the flag status */
2580 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2582 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
2583 if (Remote
&& !FlagSet
)
2586 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
2588 else if (!Remote
&& FlagSet
)
2590 /* Remove the flag */
2591 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
2596 Status
= STATUS_INVALID_PARAMETER_MIX
;
2608 NtCreateFile(PHANDLE FileHandle
,
2609 ACCESS_MASK DesiredAccess
,
2610 POBJECT_ATTRIBUTES ObjectAttributes
,
2611 PIO_STATUS_BLOCK IoStatusBlock
,
2612 PLARGE_INTEGER AllocateSize
,
2613 ULONG FileAttributes
,
2615 ULONG CreateDisposition
,
2616 ULONG CreateOptions
,
2620 /* Call the I/O Function */
2621 return IoCreateFile(FileHandle
,
2639 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
2640 IN ACCESS_MASK DesiredAccess
,
2641 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2642 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2643 IN ULONG CreateOptions
,
2644 IN ULONG MailslotQuota
,
2645 IN ULONG MaxMessageSize
,
2646 IN PLARGE_INTEGER TimeOut
)
2648 MAILSLOT_CREATE_PARAMETERS Buffer
;
2651 /* Check for Timeout */
2654 /* check if the call came from user mode */
2655 if (KeGetPreviousMode() != KernelMode
)
2657 /* Enter SEH for Probe */
2660 /* Probe the timeout */
2661 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
2663 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2665 /* Return the exception code */
2666 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2672 /* Otherwise, capture directly */
2673 Buffer
.ReadTimeout
= *TimeOut
;
2676 /* Set the correct setting */
2677 Buffer
.TimeoutSpecified
= TRUE
;
2681 /* Tell the FSD we don't have a timeout */
2682 Buffer
.TimeoutSpecified
= FALSE
;
2686 Buffer
.MailslotQuota
= MailslotQuota
;
2687 Buffer
.MaximumMessageSize
= MaxMessageSize
;
2690 return IoCreateFile(FileHandle
,
2696 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2701 CreateFileTypeMailslot
,
2708 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
2709 IN ACCESS_MASK DesiredAccess
,
2710 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2711 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2712 IN ULONG ShareAccess
,
2713 IN ULONG CreateDisposition
,
2714 IN ULONG CreateOptions
,
2715 IN ULONG NamedPipeType
,
2717 IN ULONG CompletionMode
,
2718 IN ULONG MaximumInstances
,
2719 IN ULONG InboundQuota
,
2720 IN ULONG OutboundQuota
,
2721 IN PLARGE_INTEGER DefaultTimeout
)
2723 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
2726 /* Check for Timeout */
2729 /* check if the call came from user mode */
2730 if (KeGetPreviousMode() != KernelMode
)
2732 /* Enter SEH for Probe */
2735 /* Probe the timeout */
2736 Buffer
.DefaultTimeout
=
2737 ProbeForReadLargeInteger(DefaultTimeout
);
2739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2741 /* Return the exception code */
2742 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2748 /* Otherwise, capture directly */
2749 Buffer
.DefaultTimeout
= *DefaultTimeout
;
2752 /* Set the correct setting */
2753 Buffer
.TimeoutSpecified
= TRUE
;
2757 /* Tell the FSD we don't have a timeout */
2758 Buffer
.TimeoutSpecified
= FALSE
;
2762 Buffer
.NamedPipeType
= NamedPipeType
;
2763 Buffer
.ReadMode
= ReadMode
;
2764 Buffer
.CompletionMode
= CompletionMode
;
2765 Buffer
.MaximumInstances
= MaximumInstances
;
2766 Buffer
.InboundQuota
= InboundQuota
;
2767 Buffer
.OutboundQuota
= OutboundQuota
;
2770 return IoCreateFile(FileHandle
,
2781 CreateFileTypeNamedPipe
,
2788 NtFlushWriteBuffer(VOID
)
2792 /* Call the kernel */
2793 KeFlushWriteBuffer();
2794 return STATUS_SUCCESS
;
2802 NtOpenFile(OUT PHANDLE FileHandle
,
2803 IN ACCESS_MASK DesiredAccess
,
2804 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2805 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2806 IN ULONG ShareAccess
,
2807 IN ULONG OpenOptions
)
2809 /* Call the I/O Function */
2810 return IoCreateFile(FileHandle
,
2828 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2829 OUT PFILE_BASIC_INFORMATION FileInformation
)
2831 /* Call the internal helper API */
2832 return IopQueryAttributesFile(ObjectAttributes
,
2833 FileBasicInformation
,
2834 sizeof(FILE_BASIC_INFORMATION
),
2840 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2841 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2843 /* Call the internal helper API */
2844 return IopQueryAttributesFile(ObjectAttributes
,
2845 FileNetworkOpenInformation
,
2846 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2851 * @name NtCancelIoFile
2853 * Cancel all pending I/O operations in the current thread for specified
2857 * Handle to file object to cancel requests for. No specific
2858 * access rights are needed.
2859 * @param IoStatusBlock
2860 * Pointer to status block which is filled with final completition
2861 * status on successful return.
2869 NtCancelIoFile(IN HANDLE FileHandle
,
2870 OUT PIO_STATUS_BLOCK IoStatusBlock
)
2872 PFILE_OBJECT FileObject
;
2876 BOOLEAN OurIrpsInList
= FALSE
;
2877 LARGE_INTEGER Interval
;
2878 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2880 PLIST_ENTRY ListHead
, NextEntry
;
2882 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2884 /* Check the previous mode */
2885 if (PreviousMode
!= KernelMode
)
2887 /* Enter SEH for probing */
2890 /* Probe the I/O Status Block */
2891 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2893 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2895 /* Return the exception code */
2896 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2901 /* Reference the file object */
2902 Status
= ObReferenceObjectByHandle(FileHandle
,
2906 (PVOID
*)&FileObject
,
2908 if (!NT_SUCCESS(Status
)) return Status
;
2910 /* IRP cancellations are synchronized at APC_LEVEL. */
2911 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2913 /* Get the current thread */
2914 Thread
= PsGetCurrentThread();
2916 /* Update the operation counts */
2917 IopUpdateOperationCount(IopOtherTransfer
);
2920 ListHead
= &Thread
->IrpList
;
2921 NextEntry
= ListHead
->Flink
;
2922 while (ListHead
!= NextEntry
)
2924 /* Get the IRP and check if the File Object matches */
2925 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
2926 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
2928 /* Cancel this IRP and keep looping */
2930 OurIrpsInList
= TRUE
;
2933 /* Go to the next entry */
2934 NextEntry
= NextEntry
->Flink
;
2937 /* Lower the IRQL */
2938 KeLowerIrql(OldIrql
);
2940 /* Check if we had found an IRP */
2943 /* Setup a 10ms wait */
2944 Interval
.QuadPart
= -100000;
2947 while (OurIrpsInList
)
2950 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
2951 OurIrpsInList
= FALSE
;
2954 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2956 /* Now loop the list again */
2957 NextEntry
= ListHead
->Flink
;
2958 while (NextEntry
!= ListHead
)
2960 /* Get the IRP and check if the File Object matches */
2961 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
2962 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
2965 OurIrpsInList
= TRUE
;
2969 /* Go to the next entry */
2970 NextEntry
= NextEntry
->Flink
;
2973 /* Lower the IRQL */
2974 KeLowerIrql(OldIrql
);
2978 /* Enter SEH for writing back the I/O Status */
2982 IoStatusBlock
->Status
= STATUS_SUCCESS
;
2983 IoStatusBlock
->Information
= 0;
2985 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2987 /* Ignore exception */
2991 /* Dereference the file object and return success */
2992 ObDereferenceObject(FileObject
);
2993 return STATUS_SUCCESS
;
3001 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
3004 DUMMY_FILE_OBJECT DummyFileObject
;
3006 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
3007 OPEN_PACKET OpenPacket
;
3009 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
3011 /* Setup the Open Packet */
3012 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
3013 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
3014 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
3015 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
3016 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
3019 OpenPacket
.Disposition
= FILE_OPEN
;
3020 OpenPacket
.DeleteOnly
= TRUE
;
3021 OpenPacket
.DummyFileObject
= &DummyFileObject
;
3023 /* Update the operation counts */
3024 IopUpdateOperationCount(IopOtherTransfer
);
3027 * Attempt opening the file. This will call the I/O Parse Routine for
3028 * the File Object (IopParseDevice) which will use the dummy file obejct
3029 * send the IRP to its device object. Note that we have two statuses
3030 * to worry about: the Object Manager's status (in Status) and the I/O
3031 * status, which is in the Open Packet's Final Status, and determined
3032 * by the Parse Check member.
3034 Status
= ObOpenObjectByName(ObjectAttributes
,
3041 if (OpenPacket
.ParseCheck
!= TRUE
) return Status
;
3043 /* Retrn the Io status */
3044 return OpenPacket
.FinalStatus
;