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 */
423 /* FIXME: Small hack still exists, have to check why...
424 * This is triggered multiple times by usetup and then once per boot.
427 !(RemainingName
->Length
) &&
428 !(OpenPacket
->RelatedFileObject
) &&
429 ((wcsstr(CompleteName
->Buffer
, L
"Harddisk")) ||
430 (wcsstr(CompleteName
->Buffer
, L
"Floppy"))) &&
433 DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
434 DesiredAccess
& ~(SYNCHRONIZE
|
435 FILE_READ_ATTRIBUTES
|
437 ACCESS_SYSTEM_SECURITY
|
444 /* Check if we have a related FO that wasn't a direct open */
445 if ((OpenPacket
->RelatedFileObject
) &&
446 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
448 /* The device object is the one we were given */
449 DeviceObject
= ParseObject
;
451 /* Check if the related FO had a VPB */
452 if (OpenPacket
->RelatedFileObject
->Vpb
)
454 /* Yes, remember it */
455 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
458 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
463 /* The device object is the one we were given */
464 DeviceObject
= OriginalDeviceObject
;
466 /* Check if it has a VPB */
467 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
469 /* Check if the VPB is mounted, and mount it */
470 Vpb
= IopCheckVpbMounted(OpenPacket
,
471 OriginalDeviceObject
,
474 if (!Vpb
) return Status
;
476 /* Get the VPB's device object */
477 DeviceObject
= Vpb
->DeviceObject
;
480 /* Check if there's an attached device */
481 if (DeviceObject
->AttachedDevice
)
483 /* Get the attached device */
484 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
488 /* Check if this is a secure FSD */
489 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
490 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
493 DPRINT("Fix Secure FSD support!!!\n");
496 /* Allocate the IRP */
497 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
500 /* Dereference the device and VPB, then fail */
501 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
502 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
503 return STATUS_INSUFFICIENT_RESOURCES
;
506 /* Now set the IRP data */
507 Irp
->RequestorMode
= AccessMode
;
508 Irp
->Flags
= IRP_CREATE_OPERATION
| IRP_SYNCHRONOUS_API
| 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
) ? SL_CASE_SENSITIVE
: 0;
544 case CreateFileTypeNamedPipe
:
546 /* Set the named pipe MJ and set the parameters */
547 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
548 StackLoc
->Parameters
.CreatePipe
.Parameters
= OpenPacket
->ExtraCreateParameters
;
552 case CreateFileTypeMailslot
:
554 /* Set the mailslot MJ and set the parameters */
555 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
556 StackLoc
->Parameters
.CreateMailslot
.Parameters
= OpenPacket
->ExtraCreateParameters
;
560 /* Set the common data */
561 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
562 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
563 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
564 (OpenPacket
->CreateOptions
&
566 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
567 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
568 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
570 /* Check if we really need to create an object */
573 /* Create the actual file object */
574 InitializeObjectAttributes(&ObjectAttributes
,
579 Status
= ObCreateObject(KernelMode
,
587 (PVOID
*)&FileObject
);
588 if (!NT_SUCCESS(Status
))
590 /* Create failed, free the IRP */
593 /* Dereference the device and VPB */
594 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
595 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
597 /* We failed, return status */
598 OpenPacket
->FinalStatus
= Status
;
602 /* Clear the file object */
603 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
605 /* Check if this is Synch I/O */
606 if (OpenPacket
->CreateOptions
&
607 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
609 /* Set the synch flag */
610 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
612 /* Check if it's also alertable */
613 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
615 /* It is, set the alertable flag */
616 FileObject
->Flags
|= FO_ALERTABLE_IO
;
620 /* Check if this is synch I/O */
621 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
623 /* Initialize the event */
624 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
627 /* Check if the caller requested no intermediate buffering */
628 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
630 /* Set the correct flag for the FSD to read */
631 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
634 /* Check if the caller requested write through support */
635 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
637 /* Set the correct flag for the FSD to read */
638 FileObject
->Flags
|= FO_WRITE_THROUGH
;
641 /* Check if the caller says the file will be only read sequentially */
642 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
644 /* Set the correct flag for the FSD to read */
645 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
648 /* Check if the caller believes the file will be only read randomly */
649 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
651 /* Set the correct flag for the FSD to read */
652 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
657 /* Use the dummy object instead */
658 LocalFileObject
= OpenPacket
->LocalFileObject
;
659 RtlZeroMemory(LocalFileObject
, sizeof(DUMMY_FILE_OBJECT
));
662 FileObject
= (PFILE_OBJECT
)&LocalFileObject
->ObjectHeader
.Body
;
663 LocalFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
664 LocalFileObject
->ObjectHeader
.PointerCount
= 1;
667 /* Setup the file header */
668 FileObject
->Type
= IO_TYPE_FILE
;
669 FileObject
->Size
= sizeof(FILE_OBJECT
);
670 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
671 FileObject
->DeviceObject
= OriginalDeviceObject
;
673 /* Check if this is a direct device open */
674 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
676 /* Check if the caller wants case sensitivity */
677 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
679 /* Tell the driver about it */
680 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
683 /* Now set the file object */
684 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
685 StackLoc
->FileObject
= FileObject
;
687 /* Check if the file object has a name */
688 if (RemainingName
->Length
)
690 /* Setup the unicode string */
691 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
693 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
698 if (!FileObject
->FileName
.Buffer
)
700 /* Failed to allocate the name, free the IRP */
703 /* Dereference the device object and VPB */
704 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
705 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
707 /* Clear the FO and dereference it */
708 FileObject
->DeviceObject
= NULL
;
709 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
712 return STATUS_INSUFFICIENT_RESOURCES
;
717 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
719 /* Initialize the File Object event and set the FO */
720 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
721 OpenPacket
->FileObject
= FileObject
;
723 /* Queue the IRP and call the driver */
724 IopQueueIrpToThread(Irp
);
725 Status
= IoCallDriver(DeviceObject
, Irp
);
726 if (Status
== STATUS_PENDING
)
728 /* Wait for the driver to complete the create */
729 KeWaitForSingleObject(&FileObject
->Event
,
735 /* Get the new status */
736 Status
= IoStatusBlock
.Status
;
740 /* We'll have to complete it ourselves */
741 ASSERT(!Irp
->PendingReturned
);
742 ASSERT(!Irp
->MdlAddress
);
744 /* Completion happens at APC_LEVEL */
745 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
747 /* Get the new I/O Status block ourselves */
748 IoStatusBlock
= Irp
->IoStatus
;
749 Status
= IoStatusBlock
.Status
;
751 /* Manually signal the even, we can't have any waiters */
752 FileObject
->Event
.Header
.SignalState
= 1;
754 /* Now that we've signaled the events, de-associate the IRP */
755 IopUnQueueIrpFromThread(Irp
);
757 /* Check if the IRP had an input buffer */
758 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
759 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
761 /* Free it. A driver might've tacked one on */
762 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
765 /* Free the IRP and bring the IRQL back down */
767 KeLowerIrql(OldIrql
);
770 /* Copy the I/O Status */
771 OpenPacket
->Information
= IoStatusBlock
.Information
;
773 /* The driver failed to create the file */
774 if (!NT_SUCCESS(Status
))
776 /* Check if we have a name */
777 if (FileObject
->FileName
.Length
)
780 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
781 FileObject
->FileName
.Length
= 0;
784 /* Clear its device object */
785 FileObject
->DeviceObject
= NULL
;
787 /* Save this now because the FO might go away */
788 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
791 /* Clear the file object in the open packet */
792 OpenPacket
->FileObject
= NULL
;
794 /* Dereference the file object */
795 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
797 /* Dereference the device object */
798 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
800 /* Unless the driver cancelled the open, dereference the VPB */
801 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpbAndFree(Vpb
);
803 /* Set the status and return */
804 OpenPacket
->FinalStatus
= Status
;
807 else if (Status
== STATUS_REPARSE
)
809 /* FIXME: We don't handle this at all! */
813 /* Get the owner of the File Object */
814 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
817 * It's possible that the device to whom we sent the IRP to
818 * isn't actually the device that ended opening the file object
821 if (OwnerDevice
!= DeviceObject
)
823 /* We have to de-reference the VPB we had associated */
824 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
826 /* And re-associate with the actual one */
827 Vpb
= FileObject
->Vpb
;
828 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
831 /* Make sure we are not using a dummy */
834 /* Check if this was a volume open */
835 if ((!(FileObject
->RelatedFileObject
) ||
836 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
837 !(FileObject
->FileName
.Length
))
839 /* All signs point to it, but make sure it was actually an FSD */
840 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
841 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
842 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
843 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
845 /* The owner device is an FSD, so this is a volume open for real */
846 FileObject
->Flags
|= FO_VOLUME_OPEN
;
850 /* Reference the object and set the parse check */
851 ObReferenceObject(FileObject
);
852 *Object
= FileObject
;
853 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
854 OpenPacket
->ParseCheck
= TRUE
;
855 return OpenPacket
->FinalStatus
;
859 /* Check if this was a query */
860 if (OpenPacket
->QueryOnly
)
862 /* Check if the caller wants basic info only */
863 if (!OpenPacket
->FullAttributes
)
865 /* Allocate the buffer */
866 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
867 sizeof(*FileBasicInfo
),
872 Status
= IoQueryFileInformation(FileObject
,
873 FileBasicInformation
,
874 sizeof(*FileBasicInfo
),
877 if (NT_SUCCESS(Status
))
880 RtlCopyMemory(OpenPacket
->BasicInformation
,
885 /* Free our buffer */
886 ExFreePoolWithTag(FileBasicInfo
, TAG_IO
);
891 Status
= STATUS_INSUFFICIENT_RESOURCES
;
896 /* This is a full query */
897 Status
= IoQueryFileInformation(
899 FileNetworkOpenInformation
,
900 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
901 OpenPacket
->NetworkInformation
,
903 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
907 /* Delete the file object */
908 IopDeleteFile(FileObject
);
910 /* Clear out the file */
911 OpenPacket
->FileObject
= NULL
;
913 /* Set and return status */
914 OpenPacket
->FinalStatus
= Status
;
915 OpenPacket
->ParseCheck
= TRUE
;
922 IopParseFile(IN PVOID ParseObject
,
924 IN OUT PACCESS_STATE AccessState
,
925 IN KPROCESSOR_MODE AccessMode
,
927 IN OUT PUNICODE_STRING CompleteName
,
928 IN OUT PUNICODE_STRING RemainingName
,
929 IN OUT PVOID Context OPTIONAL
,
930 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
934 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
936 /* Validate the open packet */
937 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
939 /* Get the device object */
940 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
941 OpenPacket
->RelatedFileObject
= ParseObject
;
943 /* Call the main routine */
944 return IopParseDevice(DeviceObject
,
958 IopDeleteFile(IN PVOID ObjectBody
)
960 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
962 PIO_STACK_LOCATION StackPtr
;
965 PDEVICE_OBJECT DeviceObject
;
966 BOOLEAN DereferenceDone
= FALSE
;
969 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
971 /* Check if the file has a device object */
972 if (FileObject
->DeviceObject
)
974 /* Check if this is a direct open or not */
975 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
977 /* Get the attached device */
978 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
982 /* Use the file object's device object */
983 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
987 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
988 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
990 /* Check if the handle wasn't created yet */
991 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
993 /* Send the cleanup IRP */
994 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
997 /* Clear and set up Events */
998 KeClearEvent(&FileObject
->Event
);
999 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1001 /* Allocate an IRP */
1002 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1006 Irp
->UserEvent
= &Event
;
1007 Irp
->UserIosb
= &Irp
->IoStatus
;
1008 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1009 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1010 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1012 /* Set up Stack Pointer Data */
1013 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1014 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
1015 StackPtr
->FileObject
= FileObject
;
1018 IopQueueIrpToThread(Irp
);
1020 /* Get the VPB and check if this isn't a direct open */
1021 Vpb
= FileObject
->Vpb
;
1022 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1024 /* Dereference the VPB before the close */
1025 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1028 /* Check if the FS will never disappear by itself */
1029 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1031 /* Dereference it */
1032 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1033 DereferenceDone
= TRUE
;
1036 /* Call the FS Driver */
1037 Status
= IoCallDriver(DeviceObject
, Irp
);
1038 if (Status
== STATUS_PENDING
)
1040 /* Wait for completion */
1041 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1044 /* De-queue the IRP */
1045 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1046 IopUnQueueIrpFromThread(Irp
);
1047 KeLowerIrql(OldIrql
);
1052 /* Clear the file name */
1053 if (FileObject
->FileName
.Buffer
)
1055 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1056 FileObject
->FileName
.Buffer
= NULL
;
1059 /* Check if the FO had a completion port */
1060 if (FileObject
->CompletionContext
)
1063 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1064 ExFreePool(FileObject
->CompletionContext
);
1067 /* Check if the FO had extension */
1068 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1070 /* Release filter context structure if any */
1071 FsRtlPTeardownPerFileObjectContexts(FileObject
);
1074 /* Check if dereference has been done yet */
1075 if (!DereferenceDone
)
1077 /* Dereference device object */
1078 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1085 IopSecurityFile(IN PVOID ObjectBody
,
1086 IN SECURITY_OPERATION_CODE OperationCode
,
1087 IN PSECURITY_INFORMATION SecurityInformation
,
1088 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1089 IN OUT PULONG BufferLength
,
1090 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1091 IN POOL_TYPE PoolType
,
1092 IN OUT PGENERIC_MAPPING GenericMapping
)
1094 IO_STATUS_BLOCK IoStatusBlock
;
1095 PIO_STACK_LOCATION StackPtr
;
1096 PFILE_OBJECT FileObject
;
1097 PDEVICE_OBJECT DeviceObject
;
1099 BOOLEAN LocalEvent
= FALSE
;
1101 NTSTATUS Status
= STATUS_SUCCESS
;
1103 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1105 /* Check if this is a device or file */
1106 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1109 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1115 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1117 /* Check if this is a direct open */
1118 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1120 /* Get the Device Object */
1121 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1125 /* Otherwise, use the direct device*/
1126 DeviceObject
= FileObject
->DeviceObject
;
1130 /* Check if the request was for a device object */
1131 if (!(FileObject
) ||
1132 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1133 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1135 /* Check what kind of request this was */
1136 if (OperationCode
== QuerySecurityDescriptor
)
1138 return SeQuerySecurityDescriptorInfo(SecurityInformation
,
1141 &DeviceObject
->SecurityDescriptor
);
1143 else if (OperationCode
== DeleteSecurityDescriptor
)
1145 /* Simply return success */
1146 return STATUS_SUCCESS
;
1148 else if (OperationCode
== AssignSecurityDescriptor
)
1150 /* Make absolutely sure this is a device object */
1151 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1153 /* Assign the Security Descriptor */
1154 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
1157 /* Return success */
1158 return STATUS_SUCCESS
;
1162 DPRINT1("FIXME: Set SD unimplemented for Devices\n");
1163 return STATUS_SUCCESS
;
1166 else if (OperationCode
== DeleteSecurityDescriptor
)
1168 /* Same as for devices, do nothing */
1169 return STATUS_SUCCESS
;
1172 /* At this point, we know we're a file. Reference it */
1173 ObReferenceObject(FileObject
);
1175 /* Check if we should use Sync IO or not */
1176 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1178 /* Lock the file object */
1179 IopLockFileObject(FileObject
);
1183 /* Use local event */
1184 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1188 /* Clear the File Object event */
1189 KeClearEvent(&FileObject
->Event
);
1191 /* Get the device object */
1192 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1194 /* Allocate the IRP */
1195 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1196 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1199 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1200 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1201 Irp
->RequestorMode
= ExGetPreviousMode();
1202 Irp
->UserIosb
= &IoStatusBlock
;
1203 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1204 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1205 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1207 /* Set Stack Parameters */
1208 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1209 StackPtr
->FileObject
= FileObject
;
1211 /* Check if this is a query or set */
1212 if (OperationCode
== QuerySecurityDescriptor
)
1214 /* Set the major function and parameters */
1215 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1216 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1217 *SecurityInformation
;
1218 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1219 Irp
->UserBuffer
= SecurityDescriptor
;
1223 /* Set the major function and parameters for a set */
1224 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1225 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1226 *SecurityInformation
;
1227 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1232 IopQueueIrpToThread(Irp
);
1234 /* Update operation counts */
1235 IopUpdateOperationCount(IopOtherTransfer
);
1237 /* Call the Driver */
1238 Status
= IoCallDriver(DeviceObject
, Irp
);
1240 /* Check if this was async I/O */
1243 /* Check if the IRP is pending completion */
1244 if (Status
== STATUS_PENDING
)
1246 /* Wait on the local event */
1247 KeWaitForSingleObject(&Event
,
1252 Status
= IoStatusBlock
.Status
;
1257 /* Check if the IRP is pending completion */
1258 if (Status
== STATUS_PENDING
)
1260 /* Wait on the file object */
1261 KeWaitForSingleObject(&FileObject
->Event
,
1266 Status
= FileObject
->FinalStatus
;
1269 /* Release the lock */
1270 IopUnlockFileObject(FileObject
);
1273 /* This Driver doesn't implement Security, so try to give it a default */
1274 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1276 /* Was this a query? */
1277 if (OperationCode
== QuerySecurityDescriptor
)
1279 /* Set a World Security Descriptor */
1280 Status
= SeSetWorldSecurityDescriptor(*SecurityInformation
,
1286 /* It wasn't a query, so just fake success */
1287 Status
= STATUS_SUCCESS
;
1290 else if (OperationCode
== QuerySecurityDescriptor
)
1292 /* Callers usually expect the normalized form */
1293 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1298 *BufferLength
= (ULONG
)IoStatusBlock
.Information
;
1300 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1302 /* Get the exception code */
1303 Status
= _SEH2_GetExceptionCode();
1314 IopQueryNameFile(IN PVOID ObjectBody
,
1316 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1318 OUT PULONG ReturnLength
,
1319 IN KPROCESSOR_MODE PreviousMode
)
1321 POBJECT_NAME_INFORMATION LocalInfo
;
1322 PFILE_NAME_INFORMATION LocalFileInfo
;
1323 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1324 ULONG LocalReturnLength
, FileLength
;
1325 BOOLEAN LengthMismatch
= FALSE
;
1328 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1330 /* Validate length */
1331 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1333 /* Wrong length, fail */
1334 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
1335 return STATUS_INFO_LENGTH_MISMATCH
;
1338 /* Allocate Buffer */
1339 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1340 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1342 /* Query the name */
1343 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1346 &LocalReturnLength
);
1347 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1349 /* Free the buffer and fail */
1350 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1354 /* Copy the information */
1355 RtlCopyMemory(ObjectNameInfo
,
1357 (LocalReturnLength
> Length
) ?
1358 Length
: LocalReturnLength
);
1360 /* Set buffer pointer */
1361 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1362 ObjectNameInfo
->Name
.Buffer
= p
;
1364 /* Advance in buffer */
1365 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1367 /* Check if this already filled our buffer */
1368 if (LocalReturnLength
> Length
)
1370 /* Set the length mismatch to true, so that we can return
1371 * the proper buffer size to the caller later
1373 LengthMismatch
= TRUE
;
1375 /* Save the initial buffer length value */
1376 *ReturnLength
= LocalReturnLength
;
1379 /* Now get the file name buffer and check the length needed */
1380 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1381 FileLength
= Length
-
1383 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1385 /* Query the File name */
1386 Status
= IoQueryFileInformation(FileObject
,
1387 FileNameInformation
,
1388 LengthMismatch
? Length
: FileLength
,
1390 &LocalReturnLength
);
1391 if (NT_ERROR(Status
))
1393 /* Fail on errors only, allow warnings */
1394 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1398 /* If the provided buffer is too small, return the required size */
1401 /* Add the required length */
1402 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1404 /* Free the allocated buffer and return failure */
1405 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1406 return STATUS_BUFFER_OVERFLOW
;
1409 /* Now calculate the new lengths left */
1410 FileLength
= LocalReturnLength
-
1411 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1412 LocalReturnLength
= (ULONG
)((ULONG_PTR
)p
-
1413 (ULONG_PTR
)ObjectNameInfo
+
1414 LocalFileInfo
->FileNameLength
);
1416 /* Write the Name and null-terminate it */
1417 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1418 p
+= (FileLength
/ sizeof(WCHAR
));
1420 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1422 /* Return the length needed */
1423 *ReturnLength
= LocalReturnLength
;
1425 /* Setup the length and maximum length */
1426 FileLength
= (ULONG
)((ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
);
1427 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1428 sizeof(OBJECT_NAME_INFORMATION
);
1429 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1430 sizeof(UNICODE_NULL
);
1432 /* Free buffer and return */
1433 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1439 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1440 IN PVOID ObjectBody
,
1441 IN ACCESS_MASK GrantedAccess
,
1442 IN ULONG HandleCount
,
1443 IN ULONG SystemHandleCount
)
1445 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1448 PIO_STACK_LOCATION StackPtr
;
1450 PDEVICE_OBJECT DeviceObject
;
1452 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1454 /* If this isn't the last handle for the current process, quit */
1455 if (HandleCount
!= 1) return;
1457 /* Check if the file is locked and has more then one handle opened */
1458 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1460 DPRINT1("We need to unlock this file!\n");
1464 /* Make sure this is the last handle */
1465 if (SystemHandleCount
!= 1) return;
1467 /* Check if this is a direct open or not */
1468 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1470 /* Get the attached device */
1471 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1475 /* Get the FO's device */
1476 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1479 /* Set the handle created flag */
1480 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1482 /* Check if this is a sync FO and lock it */
1483 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1485 /* Clear and set up Events */
1486 KeClearEvent(&FileObject
->Event
);
1487 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1489 /* Allocate an IRP */
1490 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1494 Irp
->UserEvent
= &Event
;
1495 Irp
->UserIosb
= &Irp
->IoStatus
;
1496 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1497 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1498 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1499 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1501 /* Set up Stack Pointer Data */
1502 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1503 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1504 StackPtr
->FileObject
= FileObject
;
1507 IopQueueIrpToThread(Irp
);
1509 /* Update operation counts */
1510 IopUpdateOperationCount(IopOtherTransfer
);
1512 /* Call the FS Driver */
1513 Status
= IoCallDriver(DeviceObject
, Irp
);
1514 if (Status
== STATUS_PENDING
)
1516 /* Wait for completion */
1517 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1520 /* Unqueue the IRP */
1521 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1522 IopUnQueueIrpFromThread(Irp
);
1523 KeLowerIrql(OldIrql
);
1528 /* Release the lock if we were holding it */
1529 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1534 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1535 IN FILE_INFORMATION_CLASS FileInformationClass
,
1536 IN ULONG FileInformationSize
,
1537 OUT PVOID FileInformation
)
1540 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1541 DUMMY_FILE_OBJECT LocalFileObject
;
1542 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1544 OPEN_PACKET OpenPacket
;
1547 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
1549 /* Check if the caller was user mode */
1550 if (AccessMode
!= KernelMode
)
1552 /* Protect probe in SEH */
1555 /* Probe the buffer */
1556 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
1558 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1560 /* Return the exception code */
1561 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1566 /* Check if this is a basic or full request */
1567 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
1569 /* Setup the Open Packet */
1570 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1571 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1572 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1573 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
1574 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
1575 OpenPacket
.Disposition
= FILE_OPEN
;
1576 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
1577 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
1578 (AccessMode
!= KernelMode
) ?
1579 &NetworkOpenInfo
: FileInformation
;
1580 OpenPacket
.QueryOnly
= TRUE
;
1581 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
1582 OpenPacket
.LocalFileObject
= &LocalFileObject
;
1584 /* Update the operation count */
1585 IopUpdateOperationCount(IopOtherTransfer
);
1588 * Attempt opening the file. This will call the I/O Parse Routine for
1589 * the File Object (IopParseDevice) which will use the dummy file obejct
1590 * send the IRP to its device object. Note that we have two statuses
1591 * to worry about: the Object Manager's status (in Status) and the I/O
1592 * status, which is in the Open Packet's Final Status, and determined
1593 * by the Parse Check member.
1595 Status
= ObOpenObjectByName(ObjectAttributes
,
1599 FILE_READ_ATTRIBUTES
,
1602 if (OpenPacket
.ParseCheck
!= TRUE
)
1609 /* Use the Io status */
1610 Status
= OpenPacket
.FinalStatus
;
1613 /* Check if we were succesful and this was user mode and a full query */
1614 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
1616 /* Enter SEH for copy */
1619 /* Copy the buffer back */
1620 RtlCopyMemory(FileInformation
,
1622 FileInformationSize
);
1624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1626 /* Get exception code */
1627 Status
= _SEH2_GetExceptionCode();
1638 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject
)
1640 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1643 /* FIXME: return NULL for the moment ~ */
1652 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject
,
1653 IN PVOID FilterContext
,
1656 if (!(FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
))
1658 return STATUS_INVALID_PARAMETER
;
1663 return STATUS_NOT_IMPLEMENTED
;
1666 /* FUNCTIONS *****************************************************************/
1673 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
1675 IN BOOLEAN SetOperation
)
1678 return STATUS_NOT_IMPLEMENTED
;
1686 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
1687 IN ULONG QuotaLength
,
1688 OUT PULONG ErrorOffset
)
1691 return STATUS_NOT_IMPLEMENTED
;
1699 IoCreateFile(OUT PHANDLE FileHandle
,
1700 IN ACCESS_MASK DesiredAccess
,
1701 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1702 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1703 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1704 IN ULONG FileAttributes
,
1705 IN ULONG ShareAccess
,
1706 IN ULONG Disposition
,
1707 IN ULONG CreateOptions
,
1708 IN PVOID EaBuffer OPTIONAL
,
1710 IN CREATE_FILE_TYPE CreateFileType
,
1711 IN PVOID ExtraCreateParameters OPTIONAL
,
1714 KPROCESSOR_MODE AccessMode
;
1715 HANDLE LocalHandle
= 0;
1716 LARGE_INTEGER SafeAllocationSize
;
1717 NTSTATUS Status
= STATUS_SUCCESS
;
1718 PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters
;
1719 POPEN_PACKET OpenPacket
;
1720 ULONG EaErrorOffset
;
1722 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
1725 /* Check if we have no parameter checking to do */
1726 if (Options
& IO_NO_PARAMETER_CHECKING
)
1728 /* Then force kernel-mode access to avoid checks */
1729 AccessMode
= KernelMode
;
1733 /* Otherwise, use the actual mode */
1734 AccessMode
= ExGetPreviousMode();
1737 /* Check if we need to do parameter checking */
1738 if ((AccessMode
!= KernelMode
) || (Options
& IO_CHECK_CREATE_PARAMETERS
))
1740 /* Validate parameters */
1741 if (FileAttributes
& ~FILE_ATTRIBUTE_VALID_FLAGS
)
1743 DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n");
1744 return STATUS_INVALID_PARAMETER
;
1747 if (ShareAccess
& ~FILE_SHARE_VALID_FLAGS
)
1749 DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n");
1750 return STATUS_INVALID_PARAMETER
;
1753 if (Disposition
> FILE_MAXIMUM_DISPOSITION
)
1755 DPRINT1("File Create 'Disposition' Parameter is out of range!\n");
1756 return STATUS_INVALID_PARAMETER
;
1759 if (CreateOptions
& ~FILE_VALID_OPTION_FLAGS
)
1761 DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n");
1762 return STATUS_INVALID_PARAMETER
;
1765 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
)) &&
1766 (!(DesiredAccess
& SYNCHRONIZE
)))
1768 DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n");
1769 return STATUS_INVALID_PARAMETER
;
1772 if ((CreateOptions
& FILE_DELETE_ON_CLOSE
) && (!(DesiredAccess
& DELETE
)))
1774 DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n");
1775 return STATUS_INVALID_PARAMETER
;
1778 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
)) ==
1779 (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
))
1781 DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n");
1782 return STATUS_INVALID_PARAMETER
;
1785 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
1786 (CreateOptions
& ~(FILE_DIRECTORY_FILE
|
1787 FILE_SYNCHRONOUS_IO_ALERT
|
1788 FILE_SYNCHRONOUS_IO_NONALERT
|
1789 FILE_WRITE_THROUGH
|
1790 FILE_COMPLETE_IF_OPLOCKED
|
1791 FILE_OPEN_FOR_BACKUP_INTENT
|
1792 FILE_DELETE_ON_CLOSE
|
1793 FILE_OPEN_FOR_FREE_SPACE_QUERY
|
1794 FILE_OPEN_BY_FILE_ID
|
1795 FILE_NO_COMPRESSION
|
1796 FILE_OPEN_REPARSE_POINT
)))
1798 DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n");
1799 return STATUS_INVALID_PARAMETER
;
1802 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
1803 (Disposition
!= FILE_CREATE
) && (Disposition
!= FILE_OPEN
) && (Disposition
!= FILE_OPEN_IF
))
1805 DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n");
1806 return STATUS_INVALID_PARAMETER
;
1809 if ((CreateOptions
& FILE_COMPLETE_IF_OPLOCKED
) && (CreateOptions
& FILE_RESERVE_OPFILTER
))
1811 DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n");
1812 return STATUS_INVALID_PARAMETER
;
1815 if ((CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
) && (DesiredAccess
& FILE_APPEND_DATA
))
1817 DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n");
1818 return STATUS_INVALID_PARAMETER
;
1821 /* Now check if this is a named pipe */
1822 if (CreateFileType
== CreateFileTypeNamedPipe
)
1824 /* Make sure we have extra parameters */
1825 if (!ExtraCreateParameters
)
1827 return STATUS_INVALID_PARAMETER
;
1830 /* Get the parameters and validate them */
1831 NamedPipeCreateParameters
= ExtraCreateParameters
;
1832 if ((NamedPipeCreateParameters
->NamedPipeType
> FILE_PIPE_MESSAGE_TYPE
) ||
1833 (NamedPipeCreateParameters
->ReadMode
> FILE_PIPE_MESSAGE_MODE
) ||
1834 (NamedPipeCreateParameters
->CompletionMode
> FILE_PIPE_COMPLETE_OPERATION
) ||
1835 (ShareAccess
& FILE_SHARE_DELETE
) ||
1836 ((Disposition
< FILE_OPEN
) || (Disposition
> FILE_OPEN_IF
)) ||
1837 (CreateOptions
& ~FILE_VALID_PIPE_OPTION_FLAGS
))
1839 /* Invalid named pipe create */
1840 return STATUS_INVALID_PARAMETER
;
1843 else if (CreateFileType
== CreateFileTypeMailslot
)
1845 /* Make sure we have extra parameters */
1846 if (!ExtraCreateParameters
)
1848 return STATUS_INVALID_PARAMETER
;
1851 /* Get the parameters and validate them */
1852 if ((ShareAccess
& FILE_SHARE_DELETE
) ||
1853 !(ShareAccess
& ~FILE_SHARE_WRITE
) ||
1854 (Disposition
!= FILE_CREATE
) ||
1855 (CreateOptions
& ~FILE_VALID_MAILSLOT_OPTION_FLAGS
))
1857 /* Invalid mailslot create */
1858 return STATUS_INVALID_PARAMETER
;
1863 /* Allocate the open packet */
1864 OpenPacket
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*OpenPacket
), 'pOoI');
1865 if (!OpenPacket
) return STATUS_INSUFFICIENT_RESOURCES
;
1866 RtlZeroMemory(OpenPacket
, sizeof(*OpenPacket
));
1868 /* Check if the call came from user mode */
1869 if (AccessMode
!= KernelMode
)
1873 /* Probe the output parameters */
1874 ProbeForWriteHandle(FileHandle
);
1875 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1877 /* Probe the allocation size if one was passed in */
1880 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
1884 SafeAllocationSize
.QuadPart
= 0;
1887 /* Make sure it's valid */
1888 if (SafeAllocationSize
.QuadPart
< 0)
1890 RtlRaiseStatus(STATUS_INVALID_PARAMETER
);
1893 /* Check if EA was passed in */
1894 if ((EaBuffer
) && (EaLength
))
1897 ProbeForRead(EaBuffer
, EaLength
, sizeof(ULONG
));
1899 /* And marshall it */
1900 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1903 OpenPacket
->EaLength
= EaLength
;
1904 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
1906 /* Validate the buffer */
1907 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
1910 if (!NT_SUCCESS(Status
))
1912 /* Undo everything if it's invalid */
1913 DPRINT1("Invalid EA buffer\n");
1914 IoStatusBlock
->Status
= Status
;
1915 IoStatusBlock
->Information
= EaErrorOffset
;
1916 RtlRaiseStatus(Status
);
1920 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1922 /* Return the exception code */
1923 if (OpenPacket
->EaBuffer
!= NULL
) ExFreePool(OpenPacket
->EaBuffer
);
1924 ExFreePool(OpenPacket
);
1925 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1931 /* Check if this is a device attach */
1932 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
1934 /* Set the flag properly */
1935 Options
|= IO_ATTACH_DEVICE
;
1936 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
1939 /* Check if we have allocation size */
1943 SafeAllocationSize
= *AllocationSize
;
1947 /* Otherwise, no size */
1948 SafeAllocationSize
.QuadPart
= 0;
1951 /* Check if we have an EA packet */
1952 if ((EaBuffer
) && (EaLength
))
1954 /* Allocate the kernel copy */
1955 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1958 if (!OpenPacket
->EaBuffer
)
1960 ExFreePool(OpenPacket
);
1961 return STATUS_INSUFFICIENT_RESOURCES
;
1965 OpenPacket
->EaLength
= EaLength
;
1966 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
1968 /* Validate the buffer */
1969 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
1972 if (!NT_SUCCESS(Status
))
1974 /* Undo everything if it's invalid */
1975 DPRINT1("Invalid EA buffer\n");
1976 ExFreePool(OpenPacket
->EaBuffer
);
1977 IoStatusBlock
->Status
= Status
;
1978 IoStatusBlock
->Information
= EaErrorOffset
;
1979 ExFreePool(OpenPacket
);
1985 /* Setup the Open Packet */
1986 OpenPacket
->Type
= IO_TYPE_OPEN_PACKET
;
1987 OpenPacket
->Size
= sizeof(*OpenPacket
);
1988 OpenPacket
->AllocationSize
= SafeAllocationSize
;
1989 OpenPacket
->CreateOptions
= CreateOptions
;
1990 OpenPacket
->FileAttributes
= (USHORT
)FileAttributes
;
1991 OpenPacket
->ShareAccess
= (USHORT
)ShareAccess
;
1992 OpenPacket
->Options
= Options
;
1993 OpenPacket
->Disposition
= Disposition
;
1994 OpenPacket
->CreateFileType
= CreateFileType
;
1995 OpenPacket
->ExtraCreateParameters
= ExtraCreateParameters
;
1997 /* Update the operation count */
1998 IopUpdateOperationCount(IopOtherTransfer
);
2001 * Attempt opening the file. This will call the I/O Parse Routine for
2002 * the File Object (IopParseDevice) which will create the object and
2003 * send the IRP to its device object. Note that we have two statuses
2004 * to worry about: the Object Manager's status (in Status) and the I/O
2005 * status, which is in the Open Packet's Final Status, and determined
2006 * by the Parse Check member.
2008 Status
= ObOpenObjectByName(ObjectAttributes
,
2016 /* Free the EA Buffer */
2017 if (OpenPacket
->EaBuffer
) ExFreePool(OpenPacket
->EaBuffer
);
2019 /* Now check for Ob or Io failure */
2020 if (!(NT_SUCCESS(Status
)) || (OpenPacket
->ParseCheck
!= TRUE
))
2022 /* Check if Ob thinks well went well */
2023 if (NT_SUCCESS(Status
))
2026 * Tell it otherwise. Because we didn't use an ObjectType,
2027 * it incorrectly returned us a handle to God knows what.
2029 ZwClose(LocalHandle
);
2030 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
2033 /* Now check the Io status */
2034 if (!NT_SUCCESS(OpenPacket
->FinalStatus
))
2036 /* Use this status instead of Ob's */
2037 Status
= OpenPacket
->FinalStatus
;
2039 /* Check if it was only a warning */
2040 if (NT_WARNING(Status
))
2042 /* Protect write with SEH */
2045 /* In this case, we copy the I/O Status back */
2046 IoStatusBlock
->Information
= OpenPacket
->Information
;
2047 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2049 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2051 /* Get exception code */
2052 Status
= _SEH2_GetExceptionCode();
2057 else if ((OpenPacket
->FileObject
) && (OpenPacket
->ParseCheck
!= 1))
2060 * This can happen in the very bizarre case where the parse routine
2061 * actually executed more then once (due to a reparse) and ended
2062 * up failing after already having created the File Object.
2064 if (OpenPacket
->FileObject
->FileName
.Length
)
2066 /* It had a name, free it */
2067 ExFreePoolWithTag(OpenPacket
->FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
2070 /* Clear the device object to invalidate the FO, and dereference */
2071 OpenPacket
->FileObject
->DeviceObject
= NULL
;
2072 ObDereferenceObject(OpenPacket
->FileObject
);
2077 /* We reached success and have a valid file handle */
2078 OpenPacket
->FileObject
->Flags
|= FO_HANDLE_CREATED
;
2079 ASSERT(OpenPacket
->FileObject
->Type
== IO_TYPE_FILE
);
2081 /* Enter SEH for write back */
2084 /* Write back the handle and I/O Status */
2085 *FileHandle
= LocalHandle
;
2086 IoStatusBlock
->Information
= OpenPacket
->Information
;
2087 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2089 /* Get the Io status */
2090 Status
= OpenPacket
->FinalStatus
;
2092 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2094 /* Get the exception status */
2095 Status
= _SEH2_GetExceptionCode();
2100 /* Check if we were 100% successful */
2101 if ((OpenPacket
->ParseCheck
== TRUE
) && (OpenPacket
->FileObject
))
2103 /* Dereference the File Object */
2104 ObDereferenceObject(OpenPacket
->FileObject
);
2108 ExFreePool(OpenPacket
);
2117 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
2118 IN ACCESS_MASK DesiredAccess
,
2119 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2120 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2121 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2122 IN ULONG FileAttributes
,
2123 IN ULONG ShareAccess
,
2124 IN ULONG Disposition
,
2125 IN ULONG CreateOptions
,
2126 IN PVOID EaBuffer OPTIONAL
,
2128 IN CREATE_FILE_TYPE CreateFileType
,
2129 IN PVOID ExtraCreateParameters OPTIONAL
,
2131 IN PVOID DeviceObject
)
2134 return STATUS_NOT_IMPLEMENTED
;
2142 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
2143 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
2144 OUT PHANDLE FileObjectHandle OPTIONAL
)
2146 PFILE_OBJECT CreatedFileObject
;
2149 OBJECT_ATTRIBUTES ObjectAttributes
;
2151 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2153 /* Choose Device Object */
2154 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2156 /* Reference the device object and initialize attributes */
2157 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2158 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2160 /* Create the File Object */
2161 Status
= ObCreateObject(KernelMode
,
2166 sizeof(FILE_OBJECT
),
2167 sizeof(FILE_OBJECT
),
2169 (PVOID
*)&CreatedFileObject
);
2170 if (!NT_SUCCESS(Status
))
2173 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2174 ExRaiseStatus(Status
);
2177 /* Set File Object Data */
2178 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2179 CreatedFileObject
->DeviceObject
= DeviceObject
;
2180 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2181 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2182 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2184 /* Initialize the wait event */
2185 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2187 /* Insert it to create a handle for it */
2188 Status
= ObInsertObject(CreatedFileObject
,
2192 (PVOID
*)&CreatedFileObject
,
2194 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2196 /* Set the handle created flag */
2197 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2198 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2200 /* Check if we have a VPB */
2201 if (DeviceObject
->Vpb
)
2204 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2207 /* Check if the caller wants the handle */
2208 if (FileObjectHandle
)
2211 *FileObjectHandle
= FileHandle
;
2212 ObDereferenceObject(CreatedFileObject
);
2216 /* Otherwise, close it */
2217 ObCloseHandle(FileHandle
, KernelMode
);
2220 /* Return the file object */
2221 return CreatedFileObject
;
2229 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2230 IN PDEVICE_OBJECT DeviceObject
)
2232 /* Call the newer function */
2233 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2241 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2242 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2244 PFILE_OBJECT CreatedFileObject
;
2246 OBJECT_ATTRIBUTES ObjectAttributes
;
2248 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2250 /* Choose Device Object */
2251 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2253 /* Reference the device object and initialize attributes */
2254 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2255 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2257 /* Create the File Object */
2258 Status
= ObCreateObject(KernelMode
,
2263 sizeof(FILE_OBJECT
),
2264 sizeof(FILE_OBJECT
),
2266 (PVOID
*)&CreatedFileObject
);
2267 if (!NT_SUCCESS(Status
))
2270 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2271 ExRaiseStatus(Status
);
2274 /* Set File Object Data */
2275 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2276 CreatedFileObject
->DeviceObject
= DeviceObject
;
2277 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2278 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2279 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2281 /* Initialize the wait event */
2282 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2284 /* Destroy create information */
2285 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2287 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2289 /* Set the handle created flag */
2290 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2291 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2293 /* Check if we have a VPB */
2294 if (DeviceObject
->Vpb
)
2297 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2300 /* Return the file object */
2301 return CreatedFileObject
;
2309 IoGetFileObjectGenericMapping(VOID
)
2311 /* Return the mapping */
2312 return &IopFileMapping
;
2320 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2322 /* Return the flag status */
2323 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2331 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2332 IN ACCESS_MASK DesiredAccess
,
2333 IN ULONG OpenOptions
,
2334 OUT PIO_STATUS_BLOCK IoStatus
,
2335 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2338 DUMMY_FILE_OBJECT LocalFileObject
;
2340 OPEN_PACKET OpenPacket
;
2342 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2344 /* Setup the Open Packet */
2345 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2346 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2347 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2348 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2349 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2350 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2351 OpenPacket
.Disposition
= FILE_OPEN
;
2352 OpenPacket
.NetworkInformation
= Buffer
;
2353 OpenPacket
.QueryOnly
= TRUE
;
2354 OpenPacket
.FullAttributes
= TRUE
;
2355 OpenPacket
.LocalFileObject
= &LocalFileObject
;
2358 * Attempt opening the file. This will call the I/O Parse Routine for
2359 * the File Object (IopParseDevice) which will use the dummy file obejct
2360 * send the IRP to its device object. Note that we have two statuses
2361 * to worry about: the Object Manager's status (in Status) and the I/O
2362 * status, which is in the Open Packet's Final Status, and determined
2363 * by the Parse Check member.
2365 Status
= ObOpenObjectByName(ObjectAttributes
,
2372 if (OpenPacket
.ParseCheck
!= TRUE
)
2375 IoStatus
->Status
= Status
;
2379 /* Use the Io status */
2380 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2381 IoStatus
->Information
= OpenPacket
.Information
;
2384 /* Return success */
2393 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2394 OUT PSHARE_ACCESS ShareAccess
)
2398 /* Check if the file has an extension */
2399 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2401 /* Check if caller specified to ignore access checks */
2402 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2404 /* Don't update share access */
2409 /* Otherwise, check if there's any access present */
2410 if ((FileObject
->ReadAccess
) ||
2411 (FileObject
->WriteAccess
) ||
2412 (FileObject
->DeleteAccess
))
2414 /* Increase the open count */
2415 ShareAccess
->OpenCount
++;
2417 /* Add new share access */
2418 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2419 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2420 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2421 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2422 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2423 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2432 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2433 IN ULONG DesiredShareAccess
,
2434 IN PFILE_OBJECT FileObject
,
2435 IN PSHARE_ACCESS ShareAccess
,
2439 BOOLEAN WriteAccess
;
2440 BOOLEAN DeleteAccess
;
2442 BOOLEAN SharedWrite
;
2443 BOOLEAN SharedDelete
;
2446 /* Get access masks */
2447 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2448 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2449 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2451 /* Set them in the file object */
2452 FileObject
->ReadAccess
= ReadAccess
;
2453 FileObject
->WriteAccess
= WriteAccess
;
2454 FileObject
->DeleteAccess
= DeleteAccess
;
2456 /* Check if the file has an extension */
2457 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2459 /* Check if caller specified to ignore access checks */
2460 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2462 /* Don't check share access */
2463 return STATUS_SUCCESS
;
2467 /* Check if we have any access */
2468 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2470 /* Get shared access masks */
2471 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2472 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2473 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2476 FileObject
->SharedRead
= SharedRead
;
2477 FileObject
->SharedWrite
= SharedWrite
;
2478 FileObject
->SharedDelete
= SharedDelete
;
2480 /* Check if the shared access is violated */
2482 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2484 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2486 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2487 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2488 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2489 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2491 /* Sharing violation, fail */
2492 return STATUS_SHARING_VIOLATION
;
2495 /* It's not, check if caller wants us to update it */
2498 /* Increase open count */
2499 ShareAccess
->OpenCount
++;
2501 /* Update shared access */
2502 ShareAccess
->Readers
+= ReadAccess
;
2503 ShareAccess
->Writers
+= WriteAccess
;
2504 ShareAccess
->Deleters
+= DeleteAccess
;
2505 ShareAccess
->SharedRead
+= SharedRead
;
2506 ShareAccess
->SharedWrite
+= SharedWrite
;
2507 ShareAccess
->SharedDelete
+= SharedDelete
;
2511 /* Validation successful */
2512 return STATUS_SUCCESS
;
2520 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2521 IN PSHARE_ACCESS ShareAccess
)
2525 /* Check if the file has an extension */
2526 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2528 /* Check if caller specified to ignore access checks */
2529 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2531 /* Don't update share access */
2536 /* Otherwise, check if there's any access present */
2537 if ((FileObject
->ReadAccess
) ||
2538 (FileObject
->WriteAccess
) ||
2539 (FileObject
->DeleteAccess
))
2541 /* Decrement the open count */
2542 ShareAccess
->OpenCount
--;
2544 /* Remove share access */
2545 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
2546 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
2547 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
2548 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
2549 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
2550 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
2559 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
2560 IN ULONG DesiredShareAccess
,
2561 IN PFILE_OBJECT FileObject
,
2562 OUT PSHARE_ACCESS ShareAccess
)
2565 BOOLEAN WriteAccess
;
2566 BOOLEAN DeleteAccess
;
2568 BOOLEAN SharedWrite
;
2569 BOOLEAN SharedDelete
;
2570 BOOLEAN Update
= TRUE
;
2573 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2574 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2575 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2577 /* Check if the file has an extension */
2578 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2580 /* Check if caller specified to ignore access checks */
2581 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2583 /* Don't update share access */
2588 /* Update basic access */
2589 FileObject
->ReadAccess
= ReadAccess
;
2590 FileObject
->WriteAccess
= WriteAccess
;
2591 FileObject
->DeleteAccess
= DeleteAccess
;
2593 /* Check if we have no access as all */
2594 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
2596 /* Check if we need to update the structure */
2597 if (!Update
) return;
2599 /* Otherwise, clear data */
2600 ShareAccess
->OpenCount
= 0;
2601 ShareAccess
->Readers
= 0;
2602 ShareAccess
->Writers
= 0;
2603 ShareAccess
->Deleters
= 0;
2604 ShareAccess
->SharedRead
= 0;
2605 ShareAccess
->SharedWrite
= 0;
2606 ShareAccess
->SharedDelete
= 0;
2610 /* Calculate shared access */
2611 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2612 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2613 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2615 /* Set it in the FO */
2616 FileObject
->SharedRead
= SharedRead
;
2617 FileObject
->SharedWrite
= SharedWrite
;
2618 FileObject
->SharedDelete
= SharedDelete
;
2620 /* Check if we need to update the structure */
2621 if (!Update
) return;
2623 /* Otherwise, set data */
2624 ShareAccess
->OpenCount
= 1;
2625 ShareAccess
->Readers
= ReadAccess
;
2626 ShareAccess
->Writers
= WriteAccess
;
2627 ShareAccess
->Deleters
= DeleteAccess
;
2628 ShareAccess
->SharedRead
= SharedRead
;
2629 ShareAccess
->SharedWrite
= SharedWrite
;
2630 ShareAccess
->SharedDelete
= SharedDelete
;
2639 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
2640 IN PFILE_OBJECT FileObject
)
2646 PIO_STACK_LOCATION Stack
;
2648 /* Check if handles were already created for the
2649 * open file. If so, that's over.
2651 if (FileObject
->Flags
& FO_HANDLE_CREATED
)
2652 KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN
,
2653 (ULONG_PTR
)FileObject
,
2654 (ULONG_PTR
)DeviceObject
, 0, 0);
2656 /* Reset the events */
2657 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2658 KeClearEvent(&FileObject
->Event
);
2660 /* Allocate the IRP we'll use */
2661 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
2662 /* Properly set it */
2663 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2664 Irp
->UserEvent
= &Event
;
2665 Irp
->UserIosb
= &Irp
->IoStatus
;
2666 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2667 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2668 Irp
->RequestorMode
= KernelMode
;
2669 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
2671 Stack
= IoGetNextIrpStackLocation(Irp
);
2672 Stack
->MajorFunction
= IRP_MJ_CLEANUP
;
2673 Stack
->FileObject
= FileObject
;
2675 /* Put on top of IRPs list of the thread */
2676 IopQueueIrpToThread(Irp
);
2678 /* Call the driver */
2679 Status
= IoCallDriver(DeviceObject
, Irp
);
2680 if (Status
== STATUS_PENDING
)
2682 KeWaitForSingleObject(&Event
, UserRequest
,
2683 KernelMode
, FALSE
, NULL
);
2686 /* Remove from IRPs list */
2687 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2688 IopUnQueueIrpFromThread(Irp
);
2689 KeLowerIrql(OldIrql
);
2694 /* Clear the event */
2695 KeClearEvent(&FileObject
->Event
);
2696 /* And finally, mark the open operation as canceled */
2697 FileObject
->Flags
|= FO_FILE_OPEN_CANCELLED
;
2705 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
2706 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
2709 return STATUS_NOT_IMPLEMENTED
;
2717 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
2720 NTSTATUS Status
= STATUS_SUCCESS
;
2723 /* Get the flag status */
2724 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2726 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
2727 if (Remote
&& !FlagSet
)
2730 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
2732 else if (!Remote
&& FlagSet
)
2734 /* Remove the flag */
2735 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
2740 Status
= STATUS_INVALID_PARAMETER_MIX
;
2752 NtCreateFile(PHANDLE FileHandle
,
2753 ACCESS_MASK DesiredAccess
,
2754 POBJECT_ATTRIBUTES ObjectAttributes
,
2755 PIO_STATUS_BLOCK IoStatusBlock
,
2756 PLARGE_INTEGER AllocateSize
,
2757 ULONG FileAttributes
,
2759 ULONG CreateDisposition
,
2760 ULONG CreateOptions
,
2764 /* Call the I/O Function */
2765 return IoCreateFile(FileHandle
,
2783 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
2784 IN ACCESS_MASK DesiredAccess
,
2785 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2786 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2787 IN ULONG CreateOptions
,
2788 IN ULONG MailslotQuota
,
2789 IN ULONG MaxMessageSize
,
2790 IN PLARGE_INTEGER TimeOut
)
2792 MAILSLOT_CREATE_PARAMETERS Buffer
;
2795 /* Check for Timeout */
2798 /* check if the call came from user mode */
2799 if (KeGetPreviousMode() != KernelMode
)
2801 /* Enter SEH for Probe */
2804 /* Probe the timeout */
2805 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
2807 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2809 /* Return the exception code */
2810 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2816 /* Otherwise, capture directly */
2817 Buffer
.ReadTimeout
= *TimeOut
;
2820 /* Set the correct setting */
2821 Buffer
.TimeoutSpecified
= TRUE
;
2825 /* Tell the FSD we don't have a timeout */
2826 Buffer
.TimeoutSpecified
= FALSE
;
2830 Buffer
.MailslotQuota
= MailslotQuota
;
2831 Buffer
.MaximumMessageSize
= MaxMessageSize
;
2834 return IoCreateFile(FileHandle
,
2840 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2845 CreateFileTypeMailslot
,
2852 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
2853 IN ACCESS_MASK DesiredAccess
,
2854 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2855 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2856 IN ULONG ShareAccess
,
2857 IN ULONG CreateDisposition
,
2858 IN ULONG CreateOptions
,
2859 IN ULONG NamedPipeType
,
2861 IN ULONG CompletionMode
,
2862 IN ULONG MaximumInstances
,
2863 IN ULONG InboundQuota
,
2864 IN ULONG OutboundQuota
,
2865 IN PLARGE_INTEGER DefaultTimeout
)
2867 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
2870 /* Check for Timeout */
2873 /* check if the call came from user mode */
2874 if (KeGetPreviousMode() != KernelMode
)
2876 /* Enter SEH for Probe */
2879 /* Probe the timeout */
2880 Buffer
.DefaultTimeout
=
2881 ProbeForReadLargeInteger(DefaultTimeout
);
2883 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2885 /* Return the exception code */
2886 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2892 /* Otherwise, capture directly */
2893 Buffer
.DefaultTimeout
= *DefaultTimeout
;
2896 /* Set the correct setting */
2897 Buffer
.TimeoutSpecified
= TRUE
;
2901 /* Tell the FSD we don't have a timeout */
2902 Buffer
.TimeoutSpecified
= FALSE
;
2906 Buffer
.NamedPipeType
= NamedPipeType
;
2907 Buffer
.ReadMode
= ReadMode
;
2908 Buffer
.CompletionMode
= CompletionMode
;
2909 Buffer
.MaximumInstances
= MaximumInstances
;
2910 Buffer
.InboundQuota
= InboundQuota
;
2911 Buffer
.OutboundQuota
= OutboundQuota
;
2914 return IoCreateFile(FileHandle
,
2925 CreateFileTypeNamedPipe
,
2932 NtFlushWriteBuffer(VOID
)
2936 /* Call the kernel */
2937 KeFlushWriteBuffer();
2938 return STATUS_SUCCESS
;
2946 NtOpenFile(OUT PHANDLE FileHandle
,
2947 IN ACCESS_MASK DesiredAccess
,
2948 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2949 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2950 IN ULONG ShareAccess
,
2951 IN ULONG OpenOptions
)
2953 /* Call the I/O Function */
2954 return IoCreateFile(FileHandle
,
2972 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2973 OUT PFILE_BASIC_INFORMATION FileInformation
)
2975 /* Call the internal helper API */
2976 return IopQueryAttributesFile(ObjectAttributes
,
2977 FileBasicInformation
,
2978 sizeof(FILE_BASIC_INFORMATION
),
2984 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2985 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2987 /* Call the internal helper API */
2988 return IopQueryAttributesFile(ObjectAttributes
,
2989 FileNetworkOpenInformation
,
2990 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2995 * @name NtCancelIoFile
2997 * Cancel all pending I/O operations in the current thread for specified
3001 * Handle to file object to cancel requests for. No specific
3002 * access rights are needed.
3003 * @param IoStatusBlock
3004 * Pointer to status block which is filled with final completition
3005 * status on successful return.
3013 NtCancelIoFile(IN HANDLE FileHandle
,
3014 OUT PIO_STATUS_BLOCK IoStatusBlock
)
3016 PFILE_OBJECT FileObject
;
3020 BOOLEAN OurIrpsInList
= FALSE
;
3021 LARGE_INTEGER Interval
;
3022 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3024 PLIST_ENTRY ListHead
, NextEntry
;
3026 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3028 /* Check the previous mode */
3029 if (PreviousMode
!= KernelMode
)
3031 /* Enter SEH for probing */
3034 /* Probe the I/O Status Block */
3035 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3037 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3039 /* Return the exception code */
3040 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3045 /* Reference the file object */
3046 Status
= ObReferenceObjectByHandle(FileHandle
,
3050 (PVOID
*)&FileObject
,
3052 if (!NT_SUCCESS(Status
)) return Status
;
3054 /* IRP cancellations are synchronized at APC_LEVEL. */
3055 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3057 /* Get the current thread */
3058 Thread
= PsGetCurrentThread();
3060 /* Update the operation counts */
3061 IopUpdateOperationCount(IopOtherTransfer
);
3064 ListHead
= &Thread
->IrpList
;
3065 NextEntry
= ListHead
->Flink
;
3066 while (ListHead
!= NextEntry
)
3068 /* Get the IRP and check if the File Object matches */
3069 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3070 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3072 /* Cancel this IRP and keep looping */
3074 OurIrpsInList
= TRUE
;
3077 /* Go to the next entry */
3078 NextEntry
= NextEntry
->Flink
;
3081 /* Lower the IRQL */
3082 KeLowerIrql(OldIrql
);
3084 /* Check if we had found an IRP */
3087 /* Setup a 10ms wait */
3088 Interval
.QuadPart
= -100000;
3091 while (OurIrpsInList
)
3094 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
3095 OurIrpsInList
= FALSE
;
3098 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3100 /* Now loop the list again */
3101 NextEntry
= ListHead
->Flink
;
3102 while (NextEntry
!= ListHead
)
3104 /* Get the IRP and check if the File Object matches */
3105 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3106 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3109 OurIrpsInList
= TRUE
;
3113 /* Go to the next entry */
3114 NextEntry
= NextEntry
->Flink
;
3117 /* Lower the IRQL */
3118 KeLowerIrql(OldIrql
);
3122 /* Enter SEH for writing back the I/O Status */
3126 IoStatusBlock
->Status
= STATUS_SUCCESS
;
3127 IoStatusBlock
->Information
= 0;
3129 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3131 /* Ignore exception */
3135 /* Dereference the file object and return success */
3136 ObDereferenceObject(FileObject
);
3137 return STATUS_SUCCESS
;
3145 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
3148 DUMMY_FILE_OBJECT LocalFileObject
;
3150 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
3151 OPEN_PACKET OpenPacket
;
3153 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
3155 /* Setup the Open Packet */
3156 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
3157 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
3158 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
3159 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
3160 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
3163 OpenPacket
.Disposition
= FILE_OPEN
;
3164 OpenPacket
.DeleteOnly
= TRUE
;
3165 OpenPacket
.LocalFileObject
= &LocalFileObject
;
3167 /* Update the operation counts */
3168 IopUpdateOperationCount(IopOtherTransfer
);
3171 * Attempt opening the file. This will call the I/O Parse Routine for
3172 * the File Object (IopParseDevice) which will use the dummy file obejct
3173 * send the IRP to its device object. Note that we have two statuses
3174 * to worry about: the Object Manager's status (in Status) and the I/O
3175 * status, which is in the Open Packet's Final Status, and determined
3176 * by the Parse Check member.
3178 Status
= ObOpenObjectByName(ObjectAttributes
,
3185 if (OpenPacket
.ParseCheck
!= TRUE
) return Status
;
3187 /* Retrn the Io status */
3188 return OpenPacket
.FinalStatus
;