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 LocalFileObject
;
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 /* Check if we have a related FO that wasn't a direct open */
423 if ((OpenPacket
->RelatedFileObject
) &&
424 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
426 /* The device object is the one we were given */
427 DeviceObject
= ParseObject
;
429 /* Check if the related FO had a VPB */
430 if (OpenPacket
->RelatedFileObject
->Vpb
)
432 /* Yes, remember it */
433 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
436 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
441 /* The device object is the one we were given */
442 DeviceObject
= OriginalDeviceObject
;
444 /* Check if it has a VPB */
445 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
447 /* Check if the VPB is mounted, and mount it */
448 Vpb
= IopCheckVpbMounted(OpenPacket
,
449 OriginalDeviceObject
,
452 if (!Vpb
) return Status
;
454 /* Get the VPB's device object */
455 DeviceObject
= Vpb
->DeviceObject
;
458 /* Check if there's an attached device */
459 if (DeviceObject
->AttachedDevice
)
461 /* Get the attached device */
462 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
466 /* Check if this is a secure FSD */
467 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
468 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
471 DPRINT("Fix Secure FSD support!!!\n");
474 /* Allocate the IRP */
475 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
478 /* Dereference the device and VPB, then fail */
479 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
480 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
481 return STATUS_INSUFFICIENT_RESOURCES
;
484 /* Now set the IRP data */
485 Irp
->RequestorMode
= AccessMode
;
486 Irp
->Flags
= IRP_CREATE_OPERATION
| IRP_SYNCHRONOUS_API
| IRP_DEFER_IO_COMPLETION
;
487 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
488 Irp
->UserIosb
= &IoStatusBlock
;
489 Irp
->MdlAddress
= NULL
;
490 Irp
->PendingReturned
= FALSE
;
491 Irp
->UserEvent
= NULL
;
493 Irp
->CancelRoutine
= NULL
;
494 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
496 /* Setup the security context */
497 SecurityContext
.SecurityQos
= SecurityQos
;
498 SecurityContext
.AccessState
= AccessState
;
499 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
500 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
502 /* Get the I/O Stack location */
503 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
504 StackLoc
->Control
= 0;
506 /* Check what kind of file this is */
507 switch (OpenPacket
->CreateFileType
)
510 case CreateFileTypeNone
:
512 /* Set the major function and EA Length */
513 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
514 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
517 StackLoc
->Flags
= (UCHAR
)OpenPacket
->Options
;
518 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ? SL_CASE_SENSITIVE
: 0;
522 case CreateFileTypeNamedPipe
:
524 /* Set the named pipe MJ and set the parameters */
525 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
526 StackLoc
->Parameters
.CreatePipe
.Parameters
= OpenPacket
->ExtraCreateParameters
;
530 case CreateFileTypeMailslot
:
532 /* Set the mailslot MJ and set the parameters */
533 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
534 StackLoc
->Parameters
.CreateMailslot
.Parameters
= OpenPacket
->ExtraCreateParameters
;
538 /* Set the common data */
539 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
540 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
541 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
542 (OpenPacket
->CreateOptions
&
544 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
545 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
546 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
548 /* Check if we really need to create an object */
551 /* Create the actual file object */
552 InitializeObjectAttributes(&ObjectAttributes
,
557 Status
= ObCreateObject(KernelMode
,
565 (PVOID
*)&FileObject
);
566 if (!NT_SUCCESS(Status
))
568 /* Create failed, free the IRP */
571 /* Dereference the device and VPB */
572 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
573 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
575 /* We failed, return status */
576 OpenPacket
->FinalStatus
= Status
;
580 /* Clear the file object */
581 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
583 /* Check if this is Synch I/O */
584 if (OpenPacket
->CreateOptions
&
585 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
587 /* Set the synch flag */
588 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
590 /* Check if it's also alertable */
591 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
593 /* It is, set the alertable flag */
594 FileObject
->Flags
|= FO_ALERTABLE_IO
;
598 /* Check if this is synch I/O */
599 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
601 /* Initialize the event */
602 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
605 /* Check if the caller requested no intermediate buffering */
606 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
608 /* Set the correct flag for the FSD to read */
609 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
612 /* Check if the caller requested write through support */
613 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
615 /* Set the correct flag for the FSD to read */
616 FileObject
->Flags
|= FO_WRITE_THROUGH
;
619 /* Check if the caller says the file will be only read sequentially */
620 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
622 /* Set the correct flag for the FSD to read */
623 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
626 /* Check if the caller believes the file will be only read randomly */
627 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
629 /* Set the correct flag for the FSD to read */
630 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
635 /* Use the dummy object instead */
636 LocalFileObject
= OpenPacket
->LocalFileObject
;
637 RtlZeroMemory(LocalFileObject
, sizeof(DUMMY_FILE_OBJECT
));
640 FileObject
= (PFILE_OBJECT
)&LocalFileObject
->ObjectHeader
.Body
;
641 LocalFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
642 LocalFileObject
->ObjectHeader
.PointerCount
= 1;
645 /* Setup the file header */
646 FileObject
->Type
= IO_TYPE_FILE
;
647 FileObject
->Size
= sizeof(FILE_OBJECT
);
648 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
649 FileObject
->DeviceObject
= OriginalDeviceObject
;
651 /* Check if this is a direct device open */
652 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
654 /* Check if the caller wants case sensitivity */
655 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
657 /* Tell the driver about it */
658 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
661 /* Now set the file object */
662 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
663 StackLoc
->FileObject
= FileObject
;
665 /* Check if the file object has a name */
666 if (RemainingName
->Length
)
668 /* Setup the unicode string */
669 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
671 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
676 if (!FileObject
->FileName
.Buffer
)
678 /* Failed to allocate the name, free the IRP */
681 /* Dereference the device object and VPB */
682 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
683 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
685 /* Clear the FO and dereference it */
686 FileObject
->DeviceObject
= NULL
;
687 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
690 return STATUS_INSUFFICIENT_RESOURCES
;
695 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
697 /* Initialize the File Object event and set the FO */
698 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
699 OpenPacket
->FileObject
= FileObject
;
701 /* Queue the IRP and call the driver */
702 IopQueueIrpToThread(Irp
);
703 Status
= IoCallDriver(DeviceObject
, Irp
);
704 if (Status
== STATUS_PENDING
)
706 /* Wait for the driver to complete the create */
707 KeWaitForSingleObject(&FileObject
->Event
,
713 /* Get the new status */
714 Status
= IoStatusBlock
.Status
;
718 /* We'll have to complete it ourselves */
719 ASSERT(!Irp
->PendingReturned
);
720 ASSERT(!Irp
->MdlAddress
);
722 /* Completion happens at APC_LEVEL */
723 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
725 /* Get the new I/O Status block ourselves */
726 IoStatusBlock
= Irp
->IoStatus
;
727 Status
= IoStatusBlock
.Status
;
729 /* Manually signal the even, we can't have any waiters */
730 FileObject
->Event
.Header
.SignalState
= 1;
732 /* Now that we've signaled the events, de-associate the IRP */
733 IopUnQueueIrpFromThread(Irp
);
735 /* Check if the IRP had an input buffer */
736 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
737 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
739 /* Free it. A driver might've tacked one on */
740 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
743 /* Free the IRP and bring the IRQL back down */
745 KeLowerIrql(OldIrql
);
748 /* Copy the I/O Status */
749 OpenPacket
->Information
= IoStatusBlock
.Information
;
751 /* The driver failed to create the file */
752 if (!NT_SUCCESS(Status
))
754 /* Check if we have a name */
755 if (FileObject
->FileName
.Length
)
758 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
759 FileObject
->FileName
.Length
= 0;
762 /* Clear its device object */
763 FileObject
->DeviceObject
= NULL
;
765 /* Save this now because the FO might go away */
766 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
769 /* Clear the file object in the open packet */
770 OpenPacket
->FileObject
= NULL
;
772 /* Dereference the file object */
773 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
775 /* Dereference the device object */
776 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
778 /* Unless the driver cancelled the open, dereference the VPB */
779 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpbAndFree(Vpb
);
781 /* Set the status and return */
782 OpenPacket
->FinalStatus
= Status
;
785 else if (Status
== STATUS_REPARSE
)
787 /* FIXME: We don't handle this at all! */
791 /* Get the owner of the File Object */
792 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
795 * It's possible that the device to whom we sent the IRP to
796 * isn't actually the device that ended opening the file object
799 if (OwnerDevice
!= DeviceObject
)
801 /* We have to de-reference the VPB we had associated */
802 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
804 /* And re-associate with the actual one */
805 Vpb
= FileObject
->Vpb
;
806 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
809 /* Make sure we are not using a dummy */
812 /* Check if this was a volume open */
813 if ((!(FileObject
->RelatedFileObject
) ||
814 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
815 !(FileObject
->FileName
.Length
))
817 /* All signs point to it, but make sure it was actually an FSD */
818 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
819 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
820 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
821 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
823 /* The owner device is an FSD, so this is a volume open for real */
824 FileObject
->Flags
|= FO_VOLUME_OPEN
;
828 /* Reference the object and set the parse check */
829 ObReferenceObject(FileObject
);
830 *Object
= FileObject
;
831 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
832 OpenPacket
->ParseCheck
= TRUE
;
833 return OpenPacket
->FinalStatus
;
837 /* Check if this was a query */
838 if (OpenPacket
->QueryOnly
)
840 /* Check if the caller wants basic info only */
841 if (!OpenPacket
->FullAttributes
)
843 /* Allocate the buffer */
844 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
845 sizeof(*FileBasicInfo
),
850 Status
= IoQueryFileInformation(FileObject
,
851 FileBasicInformation
,
852 sizeof(*FileBasicInfo
),
855 if (NT_SUCCESS(Status
))
858 RtlCopyMemory(OpenPacket
->BasicInformation
,
863 /* Free our buffer */
864 ExFreePoolWithTag(FileBasicInfo
, TAG_IO
);
869 Status
= STATUS_INSUFFICIENT_RESOURCES
;
874 /* This is a full query */
875 Status
= IoQueryFileInformation(
877 FileNetworkOpenInformation
,
878 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
879 OpenPacket
->NetworkInformation
,
881 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
885 /* Delete the file object */
886 IopDeleteFile(FileObject
);
888 /* Clear out the file */
889 OpenPacket
->FileObject
= NULL
;
891 /* Set and return status */
892 OpenPacket
->FinalStatus
= Status
;
893 OpenPacket
->ParseCheck
= TRUE
;
900 IopParseFile(IN PVOID ParseObject
,
902 IN OUT PACCESS_STATE AccessState
,
903 IN KPROCESSOR_MODE AccessMode
,
905 IN OUT PUNICODE_STRING CompleteName
,
906 IN OUT PUNICODE_STRING RemainingName
,
907 IN OUT PVOID Context OPTIONAL
,
908 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
912 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
914 /* Validate the open packet */
915 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
917 /* Get the device object */
918 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
919 OpenPacket
->RelatedFileObject
= ParseObject
;
921 /* Call the main routine */
922 return IopParseDevice(DeviceObject
,
936 IopDeleteFile(IN PVOID ObjectBody
)
938 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
940 PIO_STACK_LOCATION StackPtr
;
943 PDEVICE_OBJECT DeviceObject
;
944 BOOLEAN DereferenceDone
= FALSE
;
947 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
949 /* Check if the file has a device object */
950 if (FileObject
->DeviceObject
)
952 /* Check if this is a direct open or not */
953 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
955 /* Get the attached device */
956 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
960 /* Use the file object's device object */
961 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
965 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
966 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
968 /* Check if the handle wasn't created yet */
969 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
971 /* Send the cleanup IRP */
972 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
975 /* Clear and set up Events */
976 KeClearEvent(&FileObject
->Event
);
977 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
979 /* Allocate an IRP */
980 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
984 Irp
->UserEvent
= &Event
;
985 Irp
->UserIosb
= &Irp
->IoStatus
;
986 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
987 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
988 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
990 /* Set up Stack Pointer Data */
991 StackPtr
= IoGetNextIrpStackLocation(Irp
);
992 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
993 StackPtr
->FileObject
= FileObject
;
996 IopQueueIrpToThread(Irp
);
998 /* Get the VPB and check if this isn't a direct open */
999 Vpb
= FileObject
->Vpb
;
1000 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1002 /* Dereference the VPB before the close */
1003 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1006 /* Check if the FS will never disappear by itself */
1007 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1009 /* Dereference it */
1010 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1011 DereferenceDone
= TRUE
;
1014 /* Call the FS Driver */
1015 Status
= IoCallDriver(DeviceObject
, Irp
);
1016 if (Status
== STATUS_PENDING
)
1018 /* Wait for completion */
1019 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1022 /* De-queue the IRP */
1023 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1024 IopUnQueueIrpFromThread(Irp
);
1025 KeLowerIrql(OldIrql
);
1030 /* Clear the file name */
1031 if (FileObject
->FileName
.Buffer
)
1033 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1034 FileObject
->FileName
.Buffer
= NULL
;
1037 /* Check if the FO had a completion port */
1038 if (FileObject
->CompletionContext
)
1041 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1042 ExFreePool(FileObject
->CompletionContext
);
1045 /* Check if the FO had extension */
1046 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1048 /* Release filter context structure if any */
1049 FsRtlPTeardownPerFileObjectContexts(FileObject
);
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
= (ULONG
)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 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
1313 return STATUS_INFO_LENGTH_MISMATCH
;
1316 /* Allocate Buffer */
1317 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1318 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1320 /* Query the name */
1321 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1324 &LocalReturnLength
);
1325 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1327 /* Free the buffer and fail */
1328 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1332 /* Copy the information */
1333 RtlCopyMemory(ObjectNameInfo
,
1335 (LocalReturnLength
> Length
) ?
1336 Length
: LocalReturnLength
);
1338 /* Set buffer pointer */
1339 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1340 ObjectNameInfo
->Name
.Buffer
= p
;
1342 /* Advance in buffer */
1343 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1345 /* Check if this already filled our buffer */
1346 if (LocalReturnLength
> Length
)
1348 /* Set the length mismatch to true, so that we can return
1349 * the proper buffer size to the caller later
1351 LengthMismatch
= TRUE
;
1353 /* Save the initial buffer length value */
1354 *ReturnLength
= LocalReturnLength
;
1357 /* Now get the file name buffer and check the length needed */
1358 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1359 FileLength
= Length
-
1361 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1363 /* Query the File name */
1364 Status
= IoQueryFileInformation(FileObject
,
1365 FileNameInformation
,
1366 LengthMismatch
? Length
: FileLength
,
1368 &LocalReturnLength
);
1369 if (NT_ERROR(Status
))
1371 /* Fail on errors only, allow warnings */
1372 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1376 /* If the provided buffer is too small, return the required size */
1379 /* Add the required length */
1380 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1382 /* Free the allocated buffer and return failure */
1383 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1384 return STATUS_BUFFER_OVERFLOW
;
1387 /* Now calculate the new lengths left */
1388 FileLength
= LocalReturnLength
-
1389 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1390 LocalReturnLength
= (ULONG
)((ULONG_PTR
)p
-
1391 (ULONG_PTR
)ObjectNameInfo
+
1392 LocalFileInfo
->FileNameLength
);
1394 /* Write the Name and null-terminate it */
1395 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1396 p
+= (FileLength
/ sizeof(WCHAR
));
1398 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1400 /* Return the length needed */
1401 *ReturnLength
= LocalReturnLength
;
1403 /* Setup the length and maximum length */
1404 FileLength
= (ULONG
)((ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
);
1405 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1406 sizeof(OBJECT_NAME_INFORMATION
);
1407 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1408 sizeof(UNICODE_NULL
);
1410 /* Free buffer and return */
1411 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1417 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1418 IN PVOID ObjectBody
,
1419 IN ACCESS_MASK GrantedAccess
,
1420 IN ULONG HandleCount
,
1421 IN ULONG SystemHandleCount
)
1423 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1426 PIO_STACK_LOCATION StackPtr
;
1428 PDEVICE_OBJECT DeviceObject
;
1430 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1432 /* If this isn't the last handle for the current process, quit */
1433 if (HandleCount
!= 1) return;
1435 /* Check if the file is locked and has more then one handle opened */
1436 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1438 DPRINT1("We need to unlock this file!\n");
1442 /* Make sure this is the last handle */
1443 if (SystemHandleCount
!= 1) return;
1445 /* Check if this is a direct open or not */
1446 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1448 /* Get the attached device */
1449 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1453 /* Get the FO's device */
1454 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1457 /* Set the handle created flag */
1458 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1460 /* Check if this is a sync FO and lock it */
1461 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1463 /* Clear and set up Events */
1464 KeClearEvent(&FileObject
->Event
);
1465 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1467 /* Allocate an IRP */
1468 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1472 Irp
->UserEvent
= &Event
;
1473 Irp
->UserIosb
= &Irp
->IoStatus
;
1474 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1475 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1476 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1477 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1479 /* Set up Stack Pointer Data */
1480 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1481 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1482 StackPtr
->FileObject
= FileObject
;
1485 IopQueueIrpToThread(Irp
);
1487 /* Update operation counts */
1488 IopUpdateOperationCount(IopOtherTransfer
);
1490 /* Call the FS Driver */
1491 Status
= IoCallDriver(DeviceObject
, Irp
);
1492 if (Status
== STATUS_PENDING
)
1494 /* Wait for completion */
1495 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1498 /* Unqueue the IRP */
1499 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1500 IopUnQueueIrpFromThread(Irp
);
1501 KeLowerIrql(OldIrql
);
1506 /* Release the lock if we were holding it */
1507 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1512 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1513 IN FILE_INFORMATION_CLASS FileInformationClass
,
1514 IN ULONG FileInformationSize
,
1515 OUT PVOID FileInformation
)
1518 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1519 DUMMY_FILE_OBJECT LocalFileObject
;
1520 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1522 OPEN_PACKET OpenPacket
;
1525 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
1527 /* Check if the caller was user mode */
1528 if (AccessMode
!= KernelMode
)
1530 /* Protect probe in SEH */
1533 /* Probe the buffer */
1534 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
1536 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1538 /* Return the exception code */
1539 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1544 /* Check if this is a basic or full request */
1545 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
1547 /* Setup the Open Packet */
1548 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1549 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1550 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1551 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
1552 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
1553 OpenPacket
.Disposition
= FILE_OPEN
;
1554 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
1555 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
1556 (AccessMode
!= KernelMode
) ?
1557 &NetworkOpenInfo
: FileInformation
;
1558 OpenPacket
.QueryOnly
= TRUE
;
1559 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
1560 OpenPacket
.LocalFileObject
= &LocalFileObject
;
1562 /* Update the operation count */
1563 IopUpdateOperationCount(IopOtherTransfer
);
1566 * Attempt opening the file. This will call the I/O Parse Routine for
1567 * the File Object (IopParseDevice) which will use the dummy file obejct
1568 * send the IRP to its device object. Note that we have two statuses
1569 * to worry about: the Object Manager's status (in Status) and the I/O
1570 * status, which is in the Open Packet's Final Status, and determined
1571 * by the Parse Check member.
1573 Status
= ObOpenObjectByName(ObjectAttributes
,
1577 FILE_READ_ATTRIBUTES
,
1580 if (OpenPacket
.ParseCheck
!= TRUE
)
1583 DPRINT1("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
1584 ObjectAttributes
->ObjectName
, Status
);
1589 /* Use the Io status */
1590 Status
= OpenPacket
.FinalStatus
;
1593 /* Check if we were succesful and this was user mode and a full query */
1594 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
1596 /* Enter SEH for copy */
1599 /* Copy the buffer back */
1600 RtlCopyMemory(FileInformation
,
1602 FileInformationSize
);
1604 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1606 /* Get exception code */
1607 Status
= _SEH2_GetExceptionCode();
1618 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject
)
1620 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1623 /* FIXME: return NULL for the moment ~ */
1632 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject
,
1633 IN PVOID FilterContext
,
1636 if (!(FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
))
1638 return STATUS_INVALID_PARAMETER
;
1643 return STATUS_NOT_IMPLEMENTED
;
1646 /* FUNCTIONS *****************************************************************/
1653 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
1655 IN BOOLEAN SetOperation
)
1658 return STATUS_NOT_IMPLEMENTED
;
1666 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
1667 IN ULONG QuotaLength
,
1668 OUT PULONG ErrorOffset
)
1671 return STATUS_NOT_IMPLEMENTED
;
1679 IoCreateFile(OUT PHANDLE FileHandle
,
1680 IN ACCESS_MASK DesiredAccess
,
1681 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1682 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1683 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1684 IN ULONG FileAttributes
,
1685 IN ULONG ShareAccess
,
1686 IN ULONG Disposition
,
1687 IN ULONG CreateOptions
,
1688 IN PVOID EaBuffer OPTIONAL
,
1690 IN CREATE_FILE_TYPE CreateFileType
,
1691 IN PVOID ExtraCreateParameters OPTIONAL
,
1694 KPROCESSOR_MODE AccessMode
;
1695 HANDLE LocalHandle
= 0;
1696 LARGE_INTEGER SafeAllocationSize
;
1697 NTSTATUS Status
= STATUS_SUCCESS
;
1698 PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters
;
1699 POPEN_PACKET OpenPacket
;
1700 ULONG EaErrorOffset
;
1702 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
1705 /* Check if we have no parameter checking to do */
1706 if (Options
& IO_NO_PARAMETER_CHECKING
)
1708 /* Then force kernel-mode access to avoid checks */
1709 AccessMode
= KernelMode
;
1713 /* Otherwise, use the actual mode */
1714 AccessMode
= ExGetPreviousMode();
1717 /* Check if we need to do parameter checking */
1718 if ((AccessMode
!= KernelMode
) || (Options
& IO_CHECK_CREATE_PARAMETERS
))
1720 /* Validate parameters */
1721 if (FileAttributes
& ~FILE_ATTRIBUTE_VALID_FLAGS
)
1723 DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n");
1724 return STATUS_INVALID_PARAMETER
;
1727 if (ShareAccess
& ~FILE_SHARE_VALID_FLAGS
)
1729 DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n");
1730 return STATUS_INVALID_PARAMETER
;
1733 if (Disposition
> FILE_MAXIMUM_DISPOSITION
)
1735 DPRINT1("File Create 'Disposition' Parameter is out of range!\n");
1736 return STATUS_INVALID_PARAMETER
;
1739 if (CreateOptions
& ~FILE_VALID_OPTION_FLAGS
)
1741 DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n");
1742 return STATUS_INVALID_PARAMETER
;
1745 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
)) &&
1746 (!(DesiredAccess
& SYNCHRONIZE
)))
1748 DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n");
1749 return STATUS_INVALID_PARAMETER
;
1752 if ((CreateOptions
& FILE_DELETE_ON_CLOSE
) && (!(DesiredAccess
& DELETE
)))
1754 DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n");
1755 return STATUS_INVALID_PARAMETER
;
1758 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
)) ==
1759 (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
))
1761 DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n");
1762 return STATUS_INVALID_PARAMETER
;
1765 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
1766 (CreateOptions
& ~(FILE_DIRECTORY_FILE
|
1767 FILE_SYNCHRONOUS_IO_ALERT
|
1768 FILE_SYNCHRONOUS_IO_NONALERT
|
1769 FILE_WRITE_THROUGH
|
1770 FILE_COMPLETE_IF_OPLOCKED
|
1771 FILE_OPEN_FOR_BACKUP_INTENT
|
1772 FILE_DELETE_ON_CLOSE
|
1773 FILE_OPEN_FOR_FREE_SPACE_QUERY
|
1774 FILE_OPEN_BY_FILE_ID
|
1775 FILE_NO_COMPRESSION
|
1776 FILE_OPEN_REPARSE_POINT
)))
1778 DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n");
1779 return STATUS_INVALID_PARAMETER
;
1782 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
1783 (Disposition
!= FILE_CREATE
) && (Disposition
!= FILE_OPEN
) && (Disposition
!= FILE_OPEN_IF
))
1785 DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n");
1786 return STATUS_INVALID_PARAMETER
;
1789 if ((CreateOptions
& FILE_COMPLETE_IF_OPLOCKED
) && (CreateOptions
& FILE_RESERVE_OPFILTER
))
1791 DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n");
1792 return STATUS_INVALID_PARAMETER
;
1795 if ((CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
) && (DesiredAccess
& FILE_APPEND_DATA
))
1797 DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n");
1798 return STATUS_INVALID_PARAMETER
;
1801 /* Now check if this is a named pipe */
1802 if (CreateFileType
== CreateFileTypeNamedPipe
)
1804 /* Make sure we have extra parameters */
1805 if (!ExtraCreateParameters
)
1807 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
1808 return STATUS_INVALID_PARAMETER
;
1811 /* Get the parameters and validate them */
1812 NamedPipeCreateParameters
= ExtraCreateParameters
;
1813 if ((NamedPipeCreateParameters
->NamedPipeType
> FILE_PIPE_MESSAGE_TYPE
) ||
1814 (NamedPipeCreateParameters
->ReadMode
> FILE_PIPE_MESSAGE_MODE
) ||
1815 (NamedPipeCreateParameters
->CompletionMode
> FILE_PIPE_COMPLETE_OPERATION
) ||
1816 (ShareAccess
& FILE_SHARE_DELETE
) ||
1817 ((Disposition
< FILE_OPEN
) || (Disposition
> FILE_OPEN_IF
)) ||
1818 (CreateOptions
& ~FILE_VALID_PIPE_OPTION_FLAGS
))
1820 /* Invalid named pipe create */
1821 DPRINT1("Invalid named pipe create\n");
1822 return STATUS_INVALID_PARAMETER
;
1825 else if (CreateFileType
== CreateFileTypeMailslot
)
1827 /* Make sure we have extra parameters */
1828 if (!ExtraCreateParameters
)
1830 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
1831 return STATUS_INVALID_PARAMETER
;
1834 /* Get the parameters and validate them */
1835 if ((ShareAccess
& FILE_SHARE_DELETE
) ||
1836 !(ShareAccess
& ~FILE_SHARE_WRITE
) ||
1837 (Disposition
!= FILE_CREATE
) ||
1838 (CreateOptions
& ~FILE_VALID_MAILSLOT_OPTION_FLAGS
))
1840 /* Invalid mailslot create */
1841 DPRINT1("Invalid mailslot create\n");
1842 return STATUS_INVALID_PARAMETER
;
1847 /* Allocate the open packet */
1848 OpenPacket
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*OpenPacket
), 'pOoI');
1849 if (!OpenPacket
) return STATUS_INSUFFICIENT_RESOURCES
;
1850 RtlZeroMemory(OpenPacket
, sizeof(*OpenPacket
));
1852 /* Check if the call came from user mode */
1853 if (AccessMode
!= KernelMode
)
1857 /* Probe the output parameters */
1858 ProbeForWriteHandle(FileHandle
);
1859 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1861 /* Probe the allocation size if one was passed in */
1864 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
1868 SafeAllocationSize
.QuadPart
= 0;
1871 /* Make sure it's valid */
1872 if (SafeAllocationSize
.QuadPart
< 0)
1874 RtlRaiseStatus(STATUS_INVALID_PARAMETER
);
1877 /* Check if EA was passed in */
1878 if ((EaBuffer
) && (EaLength
))
1881 ProbeForRead(EaBuffer
, EaLength
, sizeof(ULONG
));
1883 /* And marshall it */
1884 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1887 OpenPacket
->EaLength
= EaLength
;
1888 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
1890 /* Validate the buffer */
1891 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
1894 if (!NT_SUCCESS(Status
))
1896 /* Undo everything if it's invalid */
1897 DPRINT1("Invalid EA buffer\n");
1898 IoStatusBlock
->Status
= Status
;
1899 IoStatusBlock
->Information
= EaErrorOffset
;
1900 RtlRaiseStatus(Status
);
1904 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1906 /* Return the exception code */
1907 if (OpenPacket
->EaBuffer
!= NULL
) ExFreePool(OpenPacket
->EaBuffer
);
1908 ExFreePool(OpenPacket
);
1909 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1915 /* Check if this is a device attach */
1916 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
1918 /* Set the flag properly */
1919 Options
|= IO_ATTACH_DEVICE
;
1920 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
1923 /* Check if we have allocation size */
1927 SafeAllocationSize
= *AllocationSize
;
1931 /* Otherwise, no size */
1932 SafeAllocationSize
.QuadPart
= 0;
1935 /* Check if we have an EA packet */
1936 if ((EaBuffer
) && (EaLength
))
1938 /* Allocate the kernel copy */
1939 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1942 if (!OpenPacket
->EaBuffer
)
1944 ExFreePool(OpenPacket
);
1945 DPRINT1("Failed to allocate open packet EA buffer\n");
1946 return STATUS_INSUFFICIENT_RESOURCES
;
1950 OpenPacket
->EaLength
= EaLength
;
1951 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
1953 /* Validate the buffer */
1954 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
1957 if (!NT_SUCCESS(Status
))
1959 /* Undo everything if it's invalid */
1960 DPRINT1("Invalid EA buffer\n");
1961 ExFreePool(OpenPacket
->EaBuffer
);
1962 IoStatusBlock
->Status
= Status
;
1963 IoStatusBlock
->Information
= EaErrorOffset
;
1964 ExFreePool(OpenPacket
);
1970 /* Setup the Open Packet */
1971 OpenPacket
->Type
= IO_TYPE_OPEN_PACKET
;
1972 OpenPacket
->Size
= sizeof(*OpenPacket
);
1973 OpenPacket
->AllocationSize
= SafeAllocationSize
;
1974 OpenPacket
->CreateOptions
= CreateOptions
;
1975 OpenPacket
->FileAttributes
= (USHORT
)FileAttributes
;
1976 OpenPacket
->ShareAccess
= (USHORT
)ShareAccess
;
1977 OpenPacket
->Options
= Options
;
1978 OpenPacket
->Disposition
= Disposition
;
1979 OpenPacket
->CreateFileType
= CreateFileType
;
1980 OpenPacket
->ExtraCreateParameters
= ExtraCreateParameters
;
1982 /* Update the operation count */
1983 IopUpdateOperationCount(IopOtherTransfer
);
1986 * Attempt opening the file. This will call the I/O Parse Routine for
1987 * the File Object (IopParseDevice) which will create the object and
1988 * send the IRP to its device object. Note that we have two statuses
1989 * to worry about: the Object Manager's status (in Status) and the I/O
1990 * status, which is in the Open Packet's Final Status, and determined
1991 * by the Parse Check member.
1993 Status
= ObOpenObjectByName(ObjectAttributes
,
2001 /* Free the EA Buffer */
2002 if (OpenPacket
->EaBuffer
) ExFreePool(OpenPacket
->EaBuffer
);
2004 /* Now check for Ob or Io failure */
2005 if (!(NT_SUCCESS(Status
)) || (OpenPacket
->ParseCheck
!= TRUE
))
2007 /* Check if Ob thinks well went well */
2008 if (NT_SUCCESS(Status
))
2011 * Tell it otherwise. Because we didn't use an ObjectType,
2012 * it incorrectly returned us a handle to God knows what.
2014 ZwClose(LocalHandle
);
2015 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
2018 /* Now check the Io status */
2019 if (!NT_SUCCESS(OpenPacket
->FinalStatus
))
2021 /* Use this status instead of Ob's */
2022 Status
= OpenPacket
->FinalStatus
;
2024 /* Check if it was only a warning */
2025 if (NT_WARNING(Status
))
2027 /* Protect write with SEH */
2030 /* In this case, we copy the I/O Status back */
2031 IoStatusBlock
->Information
= OpenPacket
->Information
;
2032 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2034 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2036 /* Get exception code */
2037 Status
= _SEH2_GetExceptionCode();
2042 else if ((OpenPacket
->FileObject
) && (OpenPacket
->ParseCheck
!= 1))
2045 * This can happen in the very bizarre case where the parse routine
2046 * actually executed more then once (due to a reparse) and ended
2047 * up failing after already having created the File Object.
2049 if (OpenPacket
->FileObject
->FileName
.Length
)
2051 /* It had a name, free it */
2052 ExFreePoolWithTag(OpenPacket
->FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
2055 /* Clear the device object to invalidate the FO, and dereference */
2056 OpenPacket
->FileObject
->DeviceObject
= NULL
;
2057 ObDereferenceObject(OpenPacket
->FileObject
);
2062 /* We reached success and have a valid file handle */
2063 OpenPacket
->FileObject
->Flags
|= FO_HANDLE_CREATED
;
2064 ASSERT(OpenPacket
->FileObject
->Type
== IO_TYPE_FILE
);
2066 /* Enter SEH for write back */
2069 /* Write back the handle and I/O Status */
2070 *FileHandle
= LocalHandle
;
2071 IoStatusBlock
->Information
= OpenPacket
->Information
;
2072 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2074 /* Get the Io status */
2075 Status
= OpenPacket
->FinalStatus
;
2077 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2079 /* Get the exception status */
2080 Status
= _SEH2_GetExceptionCode();
2085 /* Check if we were 100% successful */
2086 if ((OpenPacket
->ParseCheck
== TRUE
) && (OpenPacket
->FileObject
))
2088 /* Dereference the File Object */
2089 ObDereferenceObject(OpenPacket
->FileObject
);
2093 ExFreePool(OpenPacket
);
2102 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
2103 IN ACCESS_MASK DesiredAccess
,
2104 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2105 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2106 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2107 IN ULONG FileAttributes
,
2108 IN ULONG ShareAccess
,
2109 IN ULONG Disposition
,
2110 IN ULONG CreateOptions
,
2111 IN PVOID EaBuffer OPTIONAL
,
2113 IN CREATE_FILE_TYPE CreateFileType
,
2114 IN PVOID ExtraCreateParameters OPTIONAL
,
2116 IN PVOID DeviceObject
)
2119 return STATUS_NOT_IMPLEMENTED
;
2127 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
2128 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
2129 OUT PHANDLE FileObjectHandle OPTIONAL
)
2131 PFILE_OBJECT CreatedFileObject
;
2134 OBJECT_ATTRIBUTES ObjectAttributes
;
2136 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2138 /* Choose Device Object */
2139 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2141 /* Reference the device object and initialize attributes */
2142 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2143 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2145 /* Create the File Object */
2146 Status
= ObCreateObject(KernelMode
,
2151 sizeof(FILE_OBJECT
),
2152 sizeof(FILE_OBJECT
),
2154 (PVOID
*)&CreatedFileObject
);
2155 if (!NT_SUCCESS(Status
))
2158 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2159 ExRaiseStatus(Status
);
2162 /* Set File Object Data */
2163 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2164 CreatedFileObject
->DeviceObject
= DeviceObject
;
2165 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2166 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2167 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2169 /* Initialize the wait event */
2170 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2172 /* Insert it to create a handle for it */
2173 Status
= ObInsertObject(CreatedFileObject
,
2177 (PVOID
*)&CreatedFileObject
,
2179 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2181 /* Set the handle created flag */
2182 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2183 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2185 /* Check if we have a VPB */
2186 if (DeviceObject
->Vpb
)
2189 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2192 /* Check if the caller wants the handle */
2193 if (FileObjectHandle
)
2196 *FileObjectHandle
= FileHandle
;
2197 ObDereferenceObject(CreatedFileObject
);
2201 /* Otherwise, close it */
2202 ObCloseHandle(FileHandle
, KernelMode
);
2205 /* Return the file object */
2206 return CreatedFileObject
;
2214 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2215 IN PDEVICE_OBJECT DeviceObject
)
2217 /* Call the newer function */
2218 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2226 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2227 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2229 PFILE_OBJECT CreatedFileObject
;
2231 OBJECT_ATTRIBUTES ObjectAttributes
;
2233 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2235 /* Choose Device Object */
2236 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2238 /* Reference the device object and initialize attributes */
2239 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2240 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2242 /* Create the File Object */
2243 Status
= ObCreateObject(KernelMode
,
2248 sizeof(FILE_OBJECT
),
2249 sizeof(FILE_OBJECT
),
2251 (PVOID
*)&CreatedFileObject
);
2252 if (!NT_SUCCESS(Status
))
2255 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2256 ExRaiseStatus(Status
);
2259 /* Set File Object Data */
2260 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2261 CreatedFileObject
->DeviceObject
= DeviceObject
;
2262 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2263 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2264 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2266 /* Initialize the wait event */
2267 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2269 /* Destroy create information */
2270 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2272 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2274 /* Set the handle created flag */
2275 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2276 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2278 /* Check if we have a VPB */
2279 if (DeviceObject
->Vpb
)
2282 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2285 /* Return the file object */
2286 return CreatedFileObject
;
2294 IoGetFileObjectGenericMapping(VOID
)
2296 /* Return the mapping */
2297 return &IopFileMapping
;
2305 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2307 /* Return the flag status */
2308 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2316 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2317 IN ACCESS_MASK DesiredAccess
,
2318 IN ULONG OpenOptions
,
2319 OUT PIO_STATUS_BLOCK IoStatus
,
2320 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2323 DUMMY_FILE_OBJECT LocalFileObject
;
2325 OPEN_PACKET OpenPacket
;
2327 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2329 /* Setup the Open Packet */
2330 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2331 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2332 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2333 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2334 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2335 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2336 OpenPacket
.Disposition
= FILE_OPEN
;
2337 OpenPacket
.NetworkInformation
= Buffer
;
2338 OpenPacket
.QueryOnly
= TRUE
;
2339 OpenPacket
.FullAttributes
= TRUE
;
2340 OpenPacket
.LocalFileObject
= &LocalFileObject
;
2343 * Attempt opening the file. This will call the I/O Parse Routine for
2344 * the File Object (IopParseDevice) which will use the dummy file obejct
2345 * send the IRP to its device object. Note that we have two statuses
2346 * to worry about: the Object Manager's status (in Status) and the I/O
2347 * status, which is in the Open Packet's Final Status, and determined
2348 * by the Parse Check member.
2350 Status
= ObOpenObjectByName(ObjectAttributes
,
2357 if (OpenPacket
.ParseCheck
!= TRUE
)
2360 IoStatus
->Status
= Status
;
2364 /* Use the Io status */
2365 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2366 IoStatus
->Information
= OpenPacket
.Information
;
2369 /* Return success */
2378 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2379 OUT PSHARE_ACCESS ShareAccess
)
2383 /* Check if the file has an extension */
2384 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2386 /* Check if caller specified to ignore access checks */
2387 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2389 /* Don't update share access */
2394 /* Otherwise, check if there's any access present */
2395 if ((FileObject
->ReadAccess
) ||
2396 (FileObject
->WriteAccess
) ||
2397 (FileObject
->DeleteAccess
))
2399 /* Increase the open count */
2400 ShareAccess
->OpenCount
++;
2402 /* Add new share access */
2403 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2404 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2405 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2406 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2407 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2408 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2417 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2418 IN ULONG DesiredShareAccess
,
2419 IN PFILE_OBJECT FileObject
,
2420 IN PSHARE_ACCESS ShareAccess
,
2424 BOOLEAN WriteAccess
;
2425 BOOLEAN DeleteAccess
;
2427 BOOLEAN SharedWrite
;
2428 BOOLEAN SharedDelete
;
2431 /* Get access masks */
2432 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2433 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2434 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2436 /* Set them in the file object */
2437 FileObject
->ReadAccess
= ReadAccess
;
2438 FileObject
->WriteAccess
= WriteAccess
;
2439 FileObject
->DeleteAccess
= DeleteAccess
;
2441 /* Check if the file has an extension */
2442 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2444 /* Check if caller specified to ignore access checks */
2445 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2447 /* Don't check share access */
2448 return STATUS_SUCCESS
;
2452 /* Check if we have any access */
2453 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2455 /* Get shared access masks */
2456 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2457 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2458 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2461 FileObject
->SharedRead
= SharedRead
;
2462 FileObject
->SharedWrite
= SharedWrite
;
2463 FileObject
->SharedDelete
= SharedDelete
;
2465 /* Check if the shared access is violated */
2467 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2469 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2471 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2472 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2473 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2474 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2476 /* Sharing violation, fail */
2477 return STATUS_SHARING_VIOLATION
;
2480 /* It's not, check if caller wants us to update it */
2483 /* Increase open count */
2484 ShareAccess
->OpenCount
++;
2486 /* Update shared access */
2487 ShareAccess
->Readers
+= ReadAccess
;
2488 ShareAccess
->Writers
+= WriteAccess
;
2489 ShareAccess
->Deleters
+= DeleteAccess
;
2490 ShareAccess
->SharedRead
+= SharedRead
;
2491 ShareAccess
->SharedWrite
+= SharedWrite
;
2492 ShareAccess
->SharedDelete
+= SharedDelete
;
2496 /* Validation successful */
2497 return STATUS_SUCCESS
;
2505 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2506 IN PSHARE_ACCESS ShareAccess
)
2510 /* Check if the file has an extension */
2511 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2513 /* Check if caller specified to ignore access checks */
2514 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2516 /* Don't update share access */
2521 /* Otherwise, check if there's any access present */
2522 if ((FileObject
->ReadAccess
) ||
2523 (FileObject
->WriteAccess
) ||
2524 (FileObject
->DeleteAccess
))
2526 /* Decrement the open count */
2527 ShareAccess
->OpenCount
--;
2529 /* Remove share access */
2530 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
2531 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
2532 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
2533 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
2534 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
2535 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
2544 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
2545 IN ULONG DesiredShareAccess
,
2546 IN PFILE_OBJECT FileObject
,
2547 OUT PSHARE_ACCESS ShareAccess
)
2550 BOOLEAN WriteAccess
;
2551 BOOLEAN DeleteAccess
;
2553 BOOLEAN SharedWrite
;
2554 BOOLEAN SharedDelete
;
2555 BOOLEAN Update
= TRUE
;
2558 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2559 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2560 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2562 /* Check if the file has an extension */
2563 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2565 /* Check if caller specified to ignore access checks */
2566 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2568 /* Don't update share access */
2573 /* Update basic access */
2574 FileObject
->ReadAccess
= ReadAccess
;
2575 FileObject
->WriteAccess
= WriteAccess
;
2576 FileObject
->DeleteAccess
= DeleteAccess
;
2578 /* Check if we have no access as all */
2579 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
2581 /* Check if we need to update the structure */
2582 if (!Update
) return;
2584 /* Otherwise, clear data */
2585 ShareAccess
->OpenCount
= 0;
2586 ShareAccess
->Readers
= 0;
2587 ShareAccess
->Writers
= 0;
2588 ShareAccess
->Deleters
= 0;
2589 ShareAccess
->SharedRead
= 0;
2590 ShareAccess
->SharedWrite
= 0;
2591 ShareAccess
->SharedDelete
= 0;
2595 /* Calculate shared access */
2596 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2597 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2598 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2600 /* Set it in the FO */
2601 FileObject
->SharedRead
= SharedRead
;
2602 FileObject
->SharedWrite
= SharedWrite
;
2603 FileObject
->SharedDelete
= SharedDelete
;
2605 /* Check if we need to update the structure */
2606 if (!Update
) return;
2608 /* Otherwise, set data */
2609 ShareAccess
->OpenCount
= 1;
2610 ShareAccess
->Readers
= ReadAccess
;
2611 ShareAccess
->Writers
= WriteAccess
;
2612 ShareAccess
->Deleters
= DeleteAccess
;
2613 ShareAccess
->SharedRead
= SharedRead
;
2614 ShareAccess
->SharedWrite
= SharedWrite
;
2615 ShareAccess
->SharedDelete
= SharedDelete
;
2624 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
2625 IN PFILE_OBJECT FileObject
)
2631 PIO_STACK_LOCATION Stack
;
2633 /* Check if handles were already created for the
2634 * open file. If so, that's over.
2636 if (FileObject
->Flags
& FO_HANDLE_CREATED
)
2637 KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN
,
2638 (ULONG_PTR
)FileObject
,
2639 (ULONG_PTR
)DeviceObject
, 0, 0);
2641 /* Reset the events */
2642 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2643 KeClearEvent(&FileObject
->Event
);
2645 /* Allocate the IRP we'll use */
2646 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
2647 /* Properly set it */
2648 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2649 Irp
->UserEvent
= &Event
;
2650 Irp
->UserIosb
= &Irp
->IoStatus
;
2651 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2652 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2653 Irp
->RequestorMode
= KernelMode
;
2654 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
2656 Stack
= IoGetNextIrpStackLocation(Irp
);
2657 Stack
->MajorFunction
= IRP_MJ_CLEANUP
;
2658 Stack
->FileObject
= FileObject
;
2660 /* Put on top of IRPs list of the thread */
2661 IopQueueIrpToThread(Irp
);
2663 /* Call the driver */
2664 Status
= IoCallDriver(DeviceObject
, Irp
);
2665 if (Status
== STATUS_PENDING
)
2667 KeWaitForSingleObject(&Event
, UserRequest
,
2668 KernelMode
, FALSE
, NULL
);
2671 /* Remove from IRPs list */
2672 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2673 IopUnQueueIrpFromThread(Irp
);
2674 KeLowerIrql(OldIrql
);
2679 /* Clear the event */
2680 KeClearEvent(&FileObject
->Event
);
2681 /* And finally, mark the open operation as canceled */
2682 FileObject
->Flags
|= FO_FILE_OPEN_CANCELLED
;
2690 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
2691 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
2694 return STATUS_NOT_IMPLEMENTED
;
2702 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
2705 NTSTATUS Status
= STATUS_SUCCESS
;
2708 /* Get the flag status */
2709 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2711 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
2712 if (Remote
&& !FlagSet
)
2715 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
2717 else if (!Remote
&& FlagSet
)
2719 /* Remove the flag */
2720 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
2725 Status
= STATUS_INVALID_PARAMETER_MIX
;
2737 NtCreateFile(PHANDLE FileHandle
,
2738 ACCESS_MASK DesiredAccess
,
2739 POBJECT_ATTRIBUTES ObjectAttributes
,
2740 PIO_STATUS_BLOCK IoStatusBlock
,
2741 PLARGE_INTEGER AllocateSize
,
2742 ULONG FileAttributes
,
2744 ULONG CreateDisposition
,
2745 ULONG CreateOptions
,
2749 /* Call the I/O Function */
2750 return IoCreateFile(FileHandle
,
2768 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
2769 IN ACCESS_MASK DesiredAccess
,
2770 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2771 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2772 IN ULONG CreateOptions
,
2773 IN ULONG MailslotQuota
,
2774 IN ULONG MaxMessageSize
,
2775 IN PLARGE_INTEGER TimeOut
)
2777 MAILSLOT_CREATE_PARAMETERS Buffer
;
2780 /* Check for Timeout */
2783 /* check if the call came from user mode */
2784 if (KeGetPreviousMode() != KernelMode
)
2786 /* Enter SEH for Probe */
2789 /* Probe the timeout */
2790 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
2792 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2794 /* Return the exception code */
2795 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2801 /* Otherwise, capture directly */
2802 Buffer
.ReadTimeout
= *TimeOut
;
2805 /* Set the correct setting */
2806 Buffer
.TimeoutSpecified
= TRUE
;
2810 /* Tell the FSD we don't have a timeout */
2811 Buffer
.TimeoutSpecified
= FALSE
;
2815 Buffer
.MailslotQuota
= MailslotQuota
;
2816 Buffer
.MaximumMessageSize
= MaxMessageSize
;
2819 return IoCreateFile(FileHandle
,
2825 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2830 CreateFileTypeMailslot
,
2837 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
2838 IN ACCESS_MASK DesiredAccess
,
2839 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2840 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2841 IN ULONG ShareAccess
,
2842 IN ULONG CreateDisposition
,
2843 IN ULONG CreateOptions
,
2844 IN ULONG NamedPipeType
,
2846 IN ULONG CompletionMode
,
2847 IN ULONG MaximumInstances
,
2848 IN ULONG InboundQuota
,
2849 IN ULONG OutboundQuota
,
2850 IN PLARGE_INTEGER DefaultTimeout
)
2852 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
2855 /* Check for Timeout */
2858 /* check if the call came from user mode */
2859 if (KeGetPreviousMode() != KernelMode
)
2861 /* Enter SEH for Probe */
2864 /* Probe the timeout */
2865 Buffer
.DefaultTimeout
=
2866 ProbeForReadLargeInteger(DefaultTimeout
);
2868 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2870 /* Return the exception code */
2871 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2877 /* Otherwise, capture directly */
2878 Buffer
.DefaultTimeout
= *DefaultTimeout
;
2881 /* Set the correct setting */
2882 Buffer
.TimeoutSpecified
= TRUE
;
2886 /* Tell the FSD we don't have a timeout */
2887 Buffer
.TimeoutSpecified
= FALSE
;
2891 Buffer
.NamedPipeType
= NamedPipeType
;
2892 Buffer
.ReadMode
= ReadMode
;
2893 Buffer
.CompletionMode
= CompletionMode
;
2894 Buffer
.MaximumInstances
= MaximumInstances
;
2895 Buffer
.InboundQuota
= InboundQuota
;
2896 Buffer
.OutboundQuota
= OutboundQuota
;
2899 return IoCreateFile(FileHandle
,
2910 CreateFileTypeNamedPipe
,
2917 NtFlushWriteBuffer(VOID
)
2921 /* Call the kernel */
2922 KeFlushWriteBuffer();
2923 return STATUS_SUCCESS
;
2931 NtOpenFile(OUT PHANDLE FileHandle
,
2932 IN ACCESS_MASK DesiredAccess
,
2933 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2934 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2935 IN ULONG ShareAccess
,
2936 IN ULONG OpenOptions
)
2938 /* Call the I/O Function */
2939 return IoCreateFile(FileHandle
,
2957 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2958 OUT PFILE_BASIC_INFORMATION FileInformation
)
2960 /* Call the internal helper API */
2961 return IopQueryAttributesFile(ObjectAttributes
,
2962 FileBasicInformation
,
2963 sizeof(FILE_BASIC_INFORMATION
),
2969 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2970 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2972 /* Call the internal helper API */
2973 return IopQueryAttributesFile(ObjectAttributes
,
2974 FileNetworkOpenInformation
,
2975 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2980 * @name NtCancelIoFile
2982 * Cancel all pending I/O operations in the current thread for specified
2986 * Handle to file object to cancel requests for. No specific
2987 * access rights are needed.
2988 * @param IoStatusBlock
2989 * Pointer to status block which is filled with final completition
2990 * status on successful return.
2998 NtCancelIoFile(IN HANDLE FileHandle
,
2999 OUT PIO_STATUS_BLOCK IoStatusBlock
)
3001 PFILE_OBJECT FileObject
;
3005 BOOLEAN OurIrpsInList
= FALSE
;
3006 LARGE_INTEGER Interval
;
3007 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3009 PLIST_ENTRY ListHead
, NextEntry
;
3011 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3013 /* Check the previous mode */
3014 if (PreviousMode
!= KernelMode
)
3016 /* Enter SEH for probing */
3019 /* Probe the I/O Status Block */
3020 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3022 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3024 /* Return the exception code */
3025 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3030 /* Reference the file object */
3031 Status
= ObReferenceObjectByHandle(FileHandle
,
3035 (PVOID
*)&FileObject
,
3037 if (!NT_SUCCESS(Status
)) return Status
;
3039 /* IRP cancellations are synchronized at APC_LEVEL. */
3040 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3042 /* Get the current thread */
3043 Thread
= PsGetCurrentThread();
3045 /* Update the operation counts */
3046 IopUpdateOperationCount(IopOtherTransfer
);
3049 ListHead
= &Thread
->IrpList
;
3050 NextEntry
= ListHead
->Flink
;
3051 while (ListHead
!= NextEntry
)
3053 /* Get the IRP and check if the File Object matches */
3054 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3055 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3057 /* Cancel this IRP and keep looping */
3059 OurIrpsInList
= TRUE
;
3062 /* Go to the next entry */
3063 NextEntry
= NextEntry
->Flink
;
3066 /* Lower the IRQL */
3067 KeLowerIrql(OldIrql
);
3069 /* Check if we had found an IRP */
3072 /* Setup a 10ms wait */
3073 Interval
.QuadPart
= -100000;
3076 while (OurIrpsInList
)
3079 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
3080 OurIrpsInList
= FALSE
;
3083 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3085 /* Now loop the list again */
3086 NextEntry
= ListHead
->Flink
;
3087 while (NextEntry
!= ListHead
)
3089 /* Get the IRP and check if the File Object matches */
3090 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3091 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3094 OurIrpsInList
= TRUE
;
3098 /* Go to the next entry */
3099 NextEntry
= NextEntry
->Flink
;
3102 /* Lower the IRQL */
3103 KeLowerIrql(OldIrql
);
3107 /* Enter SEH for writing back the I/O Status */
3111 IoStatusBlock
->Status
= STATUS_SUCCESS
;
3112 IoStatusBlock
->Information
= 0;
3114 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3116 /* Ignore exception */
3120 /* Dereference the file object and return success */
3121 ObDereferenceObject(FileObject
);
3122 return STATUS_SUCCESS
;
3130 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
3133 DUMMY_FILE_OBJECT LocalFileObject
;
3135 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
3136 OPEN_PACKET OpenPacket
;
3138 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
3140 /* Setup the Open Packet */
3141 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
3142 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
3143 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
3144 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
3145 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
3148 OpenPacket
.Disposition
= FILE_OPEN
;
3149 OpenPacket
.DeleteOnly
= TRUE
;
3150 OpenPacket
.LocalFileObject
= &LocalFileObject
;
3152 /* Update the operation counts */
3153 IopUpdateOperationCount(IopOtherTransfer
);
3156 * Attempt opening the file. This will call the I/O Parse Routine for
3157 * the File Object (IopParseDevice) which will use the dummy file obejct
3158 * send the IRP to its device object. Note that we have two statuses
3159 * to worry about: the Object Manager's status (in Status) and the I/O
3160 * status, which is in the Open Packet's Final Status, and determined
3161 * by the Parse Check member.
3163 Status
= ObOpenObjectByName(ObjectAttributes
,
3170 if (OpenPacket
.ParseCheck
!= TRUE
) return Status
;
3172 /* Retrn the Io status */
3173 return OpenPacket
.FinalStatus
;