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 /* FIXME: Small hack still exists, have to check why...
408 * This is triggered multiple times by usetup and then once per boot.
410 if (ExpInTextModeSetup
&&
412 !(RemainingName
->Length
) &&
413 !(OpenPacket
->RelatedFileObject
) &&
414 ((wcsstr(CompleteName
->Buffer
, L
"Harddisk")) ||
415 (wcsstr(CompleteName
->Buffer
, L
"Floppy"))) &&
418 DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
419 DesiredAccess
& ~(SYNCHRONIZE
|
420 FILE_READ_ATTRIBUTES
|
422 ACCESS_SYSTEM_SECURITY
|
428 /* Check if this is a direct open */
429 if (!(RemainingName
->Length
) &&
430 !(OpenPacket
->RelatedFileObject
) &&
431 ((DesiredAccess
& ~(SYNCHRONIZE
|
432 FILE_READ_ATTRIBUTES
|
434 ACCESS_SYSTEM_SECURITY
|
439 /* Remember this for later */
443 /* Check if we have a related FO that wasn't a direct open */
444 if ((OpenPacket
->RelatedFileObject
) &&
445 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
447 /* The device object is the one we were given */
448 DeviceObject
= ParseObject
;
450 /* Check if the related FO had a VPB */
451 if (OpenPacket
->RelatedFileObject
->Vpb
)
453 /* Yes, remember it */
454 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
457 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
462 /* The device object is the one we were given */
463 DeviceObject
= OriginalDeviceObject
;
465 /* Check if it has a VPB */
466 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
468 /* Check if the VPB is mounted, and mount it */
469 Vpb
= IopCheckVpbMounted(OpenPacket
,
470 OriginalDeviceObject
,
473 if (!Vpb
) return Status
;
475 /* Get the VPB's device object */
476 DeviceObject
= Vpb
->DeviceObject
;
479 /* Check if there's an attached device */
480 if (DeviceObject
->AttachedDevice
)
482 /* Get the attached device */
483 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
487 /* Check if this is a secure FSD */
488 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
489 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
492 DPRINT("Fix Secure FSD support!!!\n");
495 /* Allocate the IRP */
496 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
499 /* Dereference the device and VPB, then fail */
500 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
501 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
502 return STATUS_INSUFFICIENT_RESOURCES
;
505 /* Now set the IRP data */
506 Irp
->RequestorMode
= AccessMode
;
507 Irp
->Flags
= IRP_CREATE_OPERATION
| IRP_SYNCHRONOUS_API
| IRP_DEFER_IO_COMPLETION
;
508 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
509 Irp
->UserIosb
= &IoStatusBlock
;
510 Irp
->MdlAddress
= NULL
;
511 Irp
->PendingReturned
= FALSE
;
512 Irp
->UserEvent
= NULL
;
514 Irp
->CancelRoutine
= NULL
;
515 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
517 /* Setup the security context */
518 SecurityContext
.SecurityQos
= SecurityQos
;
519 SecurityContext
.AccessState
= AccessState
;
520 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
521 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
523 /* Get the I/O Stack location */
524 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
525 StackLoc
->Control
= 0;
527 /* Check what kind of file this is */
528 switch (OpenPacket
->CreateFileType
)
531 case CreateFileTypeNone
:
533 /* Set the major function and EA Length */
534 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
535 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
538 StackLoc
->Flags
= (UCHAR
)OpenPacket
->Options
;
539 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ? SL_CASE_SENSITIVE
: 0;
543 case CreateFileTypeNamedPipe
:
545 /* Set the named pipe MJ and set the parameters */
546 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
547 StackLoc
->Parameters
.CreatePipe
.Parameters
= OpenPacket
->ExtraCreateParameters
;
551 case CreateFileTypeMailslot
:
553 /* Set the mailslot MJ and set the parameters */
554 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
555 StackLoc
->Parameters
.CreateMailslot
.Parameters
= OpenPacket
->ExtraCreateParameters
;
559 /* Set the common data */
560 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
561 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
562 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
563 (OpenPacket
->CreateOptions
&
565 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
566 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
567 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
569 /* Check if we really need to create an object */
572 /* Create the actual file object */
573 InitializeObjectAttributes(&ObjectAttributes
,
578 Status
= ObCreateObject(KernelMode
,
586 (PVOID
*)&FileObject
);
587 if (!NT_SUCCESS(Status
))
589 /* Create failed, free the IRP */
592 /* Dereference the device and VPB */
593 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
594 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
596 /* We failed, return status */
597 OpenPacket
->FinalStatus
= Status
;
601 /* Clear the file object */
602 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
604 /* Check if this is Synch I/O */
605 if (OpenPacket
->CreateOptions
&
606 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
608 /* Set the synch flag */
609 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
611 /* Check if it's also alertable */
612 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
614 /* It is, set the alertable flag */
615 FileObject
->Flags
|= FO_ALERTABLE_IO
;
619 /* Check if this is synch I/O */
620 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
622 /* Initialize the event */
623 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
626 /* Check if the caller requested no intermediate buffering */
627 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
629 /* Set the correct flag for the FSD to read */
630 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
633 /* Check if the caller requested write through support */
634 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
636 /* Set the correct flag for the FSD to read */
637 FileObject
->Flags
|= FO_WRITE_THROUGH
;
640 /* Check if the caller says the file will be only read sequentially */
641 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
643 /* Set the correct flag for the FSD to read */
644 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
647 /* Check if the caller believes the file will be only read randomly */
648 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
650 /* Set the correct flag for the FSD to read */
651 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
656 /* Use the dummy object instead */
657 LocalFileObject
= OpenPacket
->LocalFileObject
;
658 RtlZeroMemory(LocalFileObject
, sizeof(DUMMY_FILE_OBJECT
));
661 FileObject
= (PFILE_OBJECT
)&LocalFileObject
->ObjectHeader
.Body
;
662 LocalFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
663 LocalFileObject
->ObjectHeader
.PointerCount
= 1;
666 /* Setup the file header */
667 FileObject
->Type
= IO_TYPE_FILE
;
668 FileObject
->Size
= sizeof(FILE_OBJECT
);
669 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
670 FileObject
->DeviceObject
= OriginalDeviceObject
;
672 /* Check if this is a direct device open */
673 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
675 /* Check if the caller wants case sensitivity */
676 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
678 /* Tell the driver about it */
679 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
682 /* Now set the file object */
683 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
684 StackLoc
->FileObject
= FileObject
;
686 /* Check if the file object has a name */
687 if (RemainingName
->Length
)
689 /* Setup the unicode string */
690 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
692 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
697 if (!FileObject
->FileName
.Buffer
)
699 /* Failed to allocate the name, free the IRP */
702 /* Dereference the device object and VPB */
703 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
704 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
706 /* Clear the FO and dereference it */
707 FileObject
->DeviceObject
= NULL
;
708 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
711 return STATUS_INSUFFICIENT_RESOURCES
;
716 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
718 /* Initialize the File Object event and set the FO */
719 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
720 OpenPacket
->FileObject
= FileObject
;
722 /* Queue the IRP and call the driver */
723 IopQueueIrpToThread(Irp
);
724 Status
= IoCallDriver(DeviceObject
, Irp
);
725 if (Status
== STATUS_PENDING
)
727 /* Wait for the driver to complete the create */
728 KeWaitForSingleObject(&FileObject
->Event
,
734 /* Get the new status */
735 Status
= IoStatusBlock
.Status
;
739 /* We'll have to complete it ourselves */
740 ASSERT(!Irp
->PendingReturned
);
741 ASSERT(!Irp
->MdlAddress
);
743 /* Completion happens at APC_LEVEL */
744 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
746 /* Get the new I/O Status block ourselves */
747 IoStatusBlock
= Irp
->IoStatus
;
748 Status
= IoStatusBlock
.Status
;
750 /* Manually signal the even, we can't have any waiters */
751 FileObject
->Event
.Header
.SignalState
= 1;
753 /* Now that we've signaled the events, de-associate the IRP */
754 IopUnQueueIrpFromThread(Irp
);
756 /* Check if the IRP had an input buffer */
757 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
758 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
760 /* Free it. A driver might've tacked one on */
761 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
764 /* Free the IRP and bring the IRQL back down */
766 KeLowerIrql(OldIrql
);
769 /* Copy the I/O Status */
770 OpenPacket
->Information
= IoStatusBlock
.Information
;
772 /* The driver failed to create the file */
773 if (!NT_SUCCESS(Status
))
775 /* Check if we have a name */
776 if (FileObject
->FileName
.Length
)
779 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
780 FileObject
->FileName
.Length
= 0;
783 /* Clear its device object */
784 FileObject
->DeviceObject
= NULL
;
786 /* Save this now because the FO might go away */
787 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
790 /* Clear the file object in the open packet */
791 OpenPacket
->FileObject
= NULL
;
793 /* Dereference the file object */
794 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
796 /* Dereference the device object */
797 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
799 /* Unless the driver cancelled the open, dereference the VPB */
800 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpbAndFree(Vpb
);
802 /* Set the status and return */
803 OpenPacket
->FinalStatus
= Status
;
806 else if (Status
== STATUS_REPARSE
)
808 /* FIXME: We don't handle this at all! */
812 /* Get the owner of the File Object */
813 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
816 * It's possible that the device to whom we sent the IRP to
817 * isn't actually the device that ended opening the file object
820 if (OwnerDevice
!= DeviceObject
)
822 /* We have to de-reference the VPB we had associated */
823 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
825 /* And re-associate with the actual one */
826 Vpb
= FileObject
->Vpb
;
827 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
830 /* Make sure we are not using a dummy */
833 /* Check if this was a volume open */
834 if ((!(FileObject
->RelatedFileObject
) ||
835 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
836 !(FileObject
->FileName
.Length
))
838 /* All signs point to it, but make sure it was actually an FSD */
839 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
840 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
841 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
842 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
844 /* The owner device is an FSD, so this is a volume open for real */
845 FileObject
->Flags
|= FO_VOLUME_OPEN
;
849 /* Reference the object and set the parse check */
850 ObReferenceObject(FileObject
);
851 *Object
= FileObject
;
852 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
853 OpenPacket
->ParseCheck
= TRUE
;
854 return OpenPacket
->FinalStatus
;
858 /* Check if this was a query */
859 if (OpenPacket
->QueryOnly
)
861 /* Check if the caller wants basic info only */
862 if (!OpenPacket
->FullAttributes
)
864 /* Allocate the buffer */
865 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
866 sizeof(*FileBasicInfo
),
871 Status
= IoQueryFileInformation(FileObject
,
872 FileBasicInformation
,
873 sizeof(*FileBasicInfo
),
876 if (NT_SUCCESS(Status
))
879 RtlCopyMemory(OpenPacket
->BasicInformation
,
884 /* Free our buffer */
885 ExFreePoolWithTag(FileBasicInfo
, TAG_IO
);
890 Status
= STATUS_INSUFFICIENT_RESOURCES
;
895 /* This is a full query */
896 Status
= IoQueryFileInformation(
898 FileNetworkOpenInformation
,
899 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
900 OpenPacket
->NetworkInformation
,
902 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
906 /* Delete the file object */
907 IopDeleteFile(FileObject
);
909 /* Clear out the file */
910 OpenPacket
->FileObject
= NULL
;
912 /* Set and return status */
913 OpenPacket
->FinalStatus
= Status
;
914 OpenPacket
->ParseCheck
= TRUE
;
921 IopParseFile(IN PVOID ParseObject
,
923 IN OUT PACCESS_STATE AccessState
,
924 IN KPROCESSOR_MODE AccessMode
,
926 IN OUT PUNICODE_STRING CompleteName
,
927 IN OUT PUNICODE_STRING RemainingName
,
928 IN OUT PVOID Context OPTIONAL
,
929 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
933 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
935 /* Validate the open packet */
936 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
938 /* Get the device object */
939 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
940 OpenPacket
->RelatedFileObject
= ParseObject
;
942 /* Call the main routine */
943 return IopParseDevice(DeviceObject
,
957 IopDeleteFile(IN PVOID ObjectBody
)
959 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
961 PIO_STACK_LOCATION StackPtr
;
964 PDEVICE_OBJECT DeviceObject
;
965 BOOLEAN DereferenceDone
= FALSE
;
968 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
970 /* Check if the file has a device object */
971 if (FileObject
->DeviceObject
)
973 /* Check if this is a direct open or not */
974 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
976 /* Get the attached device */
977 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
981 /* Use the file object's device object */
982 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
986 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
987 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
989 /* Check if the handle wasn't created yet */
990 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
992 /* Send the cleanup IRP */
993 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
996 /* Clear and set up Events */
997 KeClearEvent(&FileObject
->Event
);
998 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1000 /* Allocate an IRP */
1001 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1005 Irp
->UserEvent
= &Event
;
1006 Irp
->UserIosb
= &Irp
->IoStatus
;
1007 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1008 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1009 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1011 /* Set up Stack Pointer Data */
1012 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1013 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
1014 StackPtr
->FileObject
= FileObject
;
1017 IopQueueIrpToThread(Irp
);
1019 /* Get the VPB and check if this isn't a direct open */
1020 Vpb
= FileObject
->Vpb
;
1021 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1023 /* Dereference the VPB before the close */
1024 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1027 /* Check if the FS will never disappear by itself */
1028 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1030 /* Dereference it */
1031 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1032 DereferenceDone
= TRUE
;
1035 /* Call the FS Driver */
1036 Status
= IoCallDriver(DeviceObject
, Irp
);
1037 if (Status
== STATUS_PENDING
)
1039 /* Wait for completion */
1040 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1043 /* De-queue the IRP */
1044 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1045 IopUnQueueIrpFromThread(Irp
);
1046 KeLowerIrql(OldIrql
);
1051 /* Clear the file name */
1052 if (FileObject
->FileName
.Buffer
)
1054 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1055 FileObject
->FileName
.Buffer
= NULL
;
1058 /* Check if the FO had a completion port */
1059 if (FileObject
->CompletionContext
)
1062 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1063 ExFreePool(FileObject
->CompletionContext
);
1066 /* Check if the FO had extension */
1067 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1069 /* Release filter context structure if any */
1070 FsRtlPTeardownPerFileObjectContexts(FileObject
);
1073 /* Check if dereference has been done yet */
1074 if (!DereferenceDone
)
1076 /* Dereference device object */
1077 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1084 IopSecurityFile(IN PVOID ObjectBody
,
1085 IN SECURITY_OPERATION_CODE OperationCode
,
1086 IN PSECURITY_INFORMATION SecurityInformation
,
1087 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1088 IN OUT PULONG BufferLength
,
1089 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1090 IN POOL_TYPE PoolType
,
1091 IN OUT PGENERIC_MAPPING GenericMapping
)
1093 IO_STATUS_BLOCK IoStatusBlock
;
1094 PIO_STACK_LOCATION StackPtr
;
1095 PFILE_OBJECT FileObject
;
1096 PDEVICE_OBJECT DeviceObject
;
1098 BOOLEAN LocalEvent
= FALSE
;
1100 NTSTATUS Status
= STATUS_SUCCESS
;
1102 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1104 /* Check if this is a device or file */
1105 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1108 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1114 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1116 /* Check if this is a direct open */
1117 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1119 /* Get the Device Object */
1120 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1124 /* Otherwise, use the direct device*/
1125 DeviceObject
= FileObject
->DeviceObject
;
1129 /* Check if the request was for a device object */
1130 if (!(FileObject
) ||
1131 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1132 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1134 /* Check what kind of request this was */
1135 if (OperationCode
== QuerySecurityDescriptor
)
1137 return SeQuerySecurityDescriptorInfo(SecurityInformation
,
1140 &DeviceObject
->SecurityDescriptor
);
1142 else if (OperationCode
== DeleteSecurityDescriptor
)
1144 /* Simply return success */
1145 return STATUS_SUCCESS
;
1147 else if (OperationCode
== AssignSecurityDescriptor
)
1149 /* Make absolutely sure this is a device object */
1150 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1152 /* Assign the Security Descriptor */
1153 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
1156 /* Return success */
1157 return STATUS_SUCCESS
;
1161 DPRINT1("FIXME: Set SD unimplemented for Devices\n");
1162 return STATUS_SUCCESS
;
1165 else if (OperationCode
== DeleteSecurityDescriptor
)
1167 /* Same as for devices, do nothing */
1168 return STATUS_SUCCESS
;
1171 /* At this point, we know we're a file. Reference it */
1172 ObReferenceObject(FileObject
);
1174 /* Check if we should use Sync IO or not */
1175 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1177 /* Lock the file object */
1178 IopLockFileObject(FileObject
);
1182 /* Use local event */
1183 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1187 /* Clear the File Object event */
1188 KeClearEvent(&FileObject
->Event
);
1190 /* Get the device object */
1191 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1193 /* Allocate the IRP */
1194 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1195 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1198 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1199 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1200 Irp
->RequestorMode
= ExGetPreviousMode();
1201 Irp
->UserIosb
= &IoStatusBlock
;
1202 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1203 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1204 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1206 /* Set Stack Parameters */
1207 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1208 StackPtr
->FileObject
= FileObject
;
1210 /* Check if this is a query or set */
1211 if (OperationCode
== QuerySecurityDescriptor
)
1213 /* Set the major function and parameters */
1214 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1215 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1216 *SecurityInformation
;
1217 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1218 Irp
->UserBuffer
= SecurityDescriptor
;
1222 /* Set the major function and parameters for a set */
1223 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1224 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1225 *SecurityInformation
;
1226 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1231 IopQueueIrpToThread(Irp
);
1233 /* Update operation counts */
1234 IopUpdateOperationCount(IopOtherTransfer
);
1236 /* Call the Driver */
1237 Status
= IoCallDriver(DeviceObject
, Irp
);
1239 /* Check if this was async I/O */
1242 /* Check if the IRP is pending completion */
1243 if (Status
== STATUS_PENDING
)
1245 /* Wait on the local event */
1246 KeWaitForSingleObject(&Event
,
1251 Status
= IoStatusBlock
.Status
;
1256 /* Check if the IRP is pending completion */
1257 if (Status
== STATUS_PENDING
)
1259 /* Wait on the file object */
1260 KeWaitForSingleObject(&FileObject
->Event
,
1265 Status
= FileObject
->FinalStatus
;
1268 /* Release the lock */
1269 IopUnlockFileObject(FileObject
);
1272 /* This Driver doesn't implement Security, so try to give it a default */
1273 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1275 /* Was this a query? */
1276 if (OperationCode
== QuerySecurityDescriptor
)
1278 /* Set a World Security Descriptor */
1279 Status
= SeSetWorldSecurityDescriptor(*SecurityInformation
,
1285 /* It wasn't a query, so just fake success */
1286 Status
= STATUS_SUCCESS
;
1289 else if (OperationCode
== QuerySecurityDescriptor
)
1291 /* Callers usually expect the normalized form */
1292 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1297 *BufferLength
= (ULONG
)IoStatusBlock
.Information
;
1299 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1301 /* Get the exception code */
1302 Status
= _SEH2_GetExceptionCode();
1313 IopQueryNameFile(IN PVOID ObjectBody
,
1315 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1317 OUT PULONG ReturnLength
,
1318 IN KPROCESSOR_MODE PreviousMode
)
1320 POBJECT_NAME_INFORMATION LocalInfo
;
1321 PFILE_NAME_INFORMATION LocalFileInfo
;
1322 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1323 ULONG LocalReturnLength
, FileLength
;
1324 BOOLEAN LengthMismatch
= FALSE
;
1327 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1329 /* Validate length */
1330 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1332 /* Wrong length, fail */
1333 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
1334 return STATUS_INFO_LENGTH_MISMATCH
;
1337 /* Allocate Buffer */
1338 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1339 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1341 /* Query the name */
1342 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1345 &LocalReturnLength
);
1346 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1348 /* Free the buffer and fail */
1349 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1353 /* Copy the information */
1354 RtlCopyMemory(ObjectNameInfo
,
1356 (LocalReturnLength
> Length
) ?
1357 Length
: LocalReturnLength
);
1359 /* Set buffer pointer */
1360 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1361 ObjectNameInfo
->Name
.Buffer
= p
;
1363 /* Advance in buffer */
1364 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1366 /* Check if this already filled our buffer */
1367 if (LocalReturnLength
> Length
)
1369 /* Set the length mismatch to true, so that we can return
1370 * the proper buffer size to the caller later
1372 LengthMismatch
= TRUE
;
1374 /* Save the initial buffer length value */
1375 *ReturnLength
= LocalReturnLength
;
1378 /* Now get the file name buffer and check the length needed */
1379 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1380 FileLength
= Length
-
1382 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1384 /* Query the File name */
1385 Status
= IoQueryFileInformation(FileObject
,
1386 FileNameInformation
,
1387 LengthMismatch
? Length
: FileLength
,
1389 &LocalReturnLength
);
1390 if (NT_ERROR(Status
))
1392 /* Fail on errors only, allow warnings */
1393 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1397 /* If the provided buffer is too small, return the required size */
1400 /* Add the required length */
1401 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1403 /* Free the allocated buffer and return failure */
1404 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1405 return STATUS_BUFFER_OVERFLOW
;
1408 /* Now calculate the new lengths left */
1409 FileLength
= LocalReturnLength
-
1410 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1411 LocalReturnLength
= (ULONG
)((ULONG_PTR
)p
-
1412 (ULONG_PTR
)ObjectNameInfo
+
1413 LocalFileInfo
->FileNameLength
);
1415 /* Write the Name and null-terminate it */
1416 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1417 p
+= (FileLength
/ sizeof(WCHAR
));
1419 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1421 /* Return the length needed */
1422 *ReturnLength
= LocalReturnLength
;
1424 /* Setup the length and maximum length */
1425 FileLength
= (ULONG
)((ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
);
1426 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1427 sizeof(OBJECT_NAME_INFORMATION
);
1428 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1429 sizeof(UNICODE_NULL
);
1431 /* Free buffer and return */
1432 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1438 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1439 IN PVOID ObjectBody
,
1440 IN ACCESS_MASK GrantedAccess
,
1441 IN ULONG HandleCount
,
1442 IN ULONG SystemHandleCount
)
1444 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1447 PIO_STACK_LOCATION StackPtr
;
1449 PDEVICE_OBJECT DeviceObject
;
1451 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1453 /* If this isn't the last handle for the current process, quit */
1454 if (HandleCount
!= 1) return;
1456 /* Check if the file is locked and has more then one handle opened */
1457 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1459 DPRINT1("We need to unlock this file!\n");
1463 /* Make sure this is the last handle */
1464 if (SystemHandleCount
!= 1) return;
1466 /* Check if this is a direct open or not */
1467 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1469 /* Get the attached device */
1470 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1474 /* Get the FO's device */
1475 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1478 /* Set the handle created flag */
1479 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1481 /* Check if this is a sync FO and lock it */
1482 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1484 /* Clear and set up Events */
1485 KeClearEvent(&FileObject
->Event
);
1486 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1488 /* Allocate an IRP */
1489 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1493 Irp
->UserEvent
= &Event
;
1494 Irp
->UserIosb
= &Irp
->IoStatus
;
1495 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1496 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1497 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1498 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1500 /* Set up Stack Pointer Data */
1501 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1502 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1503 StackPtr
->FileObject
= FileObject
;
1506 IopQueueIrpToThread(Irp
);
1508 /* Update operation counts */
1509 IopUpdateOperationCount(IopOtherTransfer
);
1511 /* Call the FS Driver */
1512 Status
= IoCallDriver(DeviceObject
, Irp
);
1513 if (Status
== STATUS_PENDING
)
1515 /* Wait for completion */
1516 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1519 /* Unqueue the IRP */
1520 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1521 IopUnQueueIrpFromThread(Irp
);
1522 KeLowerIrql(OldIrql
);
1527 /* Release the lock if we were holding it */
1528 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1533 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1534 IN FILE_INFORMATION_CLASS FileInformationClass
,
1535 IN ULONG FileInformationSize
,
1536 OUT PVOID FileInformation
)
1539 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1540 DUMMY_FILE_OBJECT LocalFileObject
;
1541 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1543 OPEN_PACKET OpenPacket
;
1546 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
1548 /* Check if the caller was user mode */
1549 if (AccessMode
!= KernelMode
)
1551 /* Protect probe in SEH */
1554 /* Probe the buffer */
1555 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
1557 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1559 /* Return the exception code */
1560 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1565 /* Check if this is a basic or full request */
1566 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
1568 /* Setup the Open Packet */
1569 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1570 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1571 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1572 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
1573 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
1574 OpenPacket
.Disposition
= FILE_OPEN
;
1575 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
1576 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
1577 (AccessMode
!= KernelMode
) ?
1578 &NetworkOpenInfo
: FileInformation
;
1579 OpenPacket
.QueryOnly
= TRUE
;
1580 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
1581 OpenPacket
.LocalFileObject
= &LocalFileObject
;
1583 /* Update the operation count */
1584 IopUpdateOperationCount(IopOtherTransfer
);
1587 * Attempt opening the file. This will call the I/O Parse Routine for
1588 * the File Object (IopParseDevice) which will use the dummy file obejct
1589 * send the IRP to its device object. Note that we have two statuses
1590 * to worry about: the Object Manager's status (in Status) and the I/O
1591 * status, which is in the Open Packet's Final Status, and determined
1592 * by the Parse Check member.
1594 Status
= ObOpenObjectByName(ObjectAttributes
,
1598 FILE_READ_ATTRIBUTES
,
1601 if (OpenPacket
.ParseCheck
!= TRUE
)
1604 DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
1605 ObjectAttributes
->ObjectName
, Status
);
1610 /* Use the Io status */
1611 Status
= OpenPacket
.FinalStatus
;
1614 /* Check if we were succesful and this was user mode and a full query */
1615 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
1617 /* Enter SEH for copy */
1620 /* Copy the buffer back */
1621 RtlCopyMemory(FileInformation
,
1623 FileInformationSize
);
1625 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1627 /* Get exception code */
1628 Status
= _SEH2_GetExceptionCode();
1639 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject
)
1641 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1644 /* FIXME: return NULL for the moment ~ */
1653 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject
,
1654 IN PVOID FilterContext
,
1657 if (!(FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
))
1659 return STATUS_INVALID_PARAMETER
;
1664 return STATUS_NOT_IMPLEMENTED
;
1667 /* FUNCTIONS *****************************************************************/
1674 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
1676 IN BOOLEAN SetOperation
)
1679 return STATUS_NOT_IMPLEMENTED
;
1687 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
1688 IN ULONG QuotaLength
,
1689 OUT PULONG ErrorOffset
)
1692 return STATUS_NOT_IMPLEMENTED
;
1700 IoCreateFile(OUT PHANDLE FileHandle
,
1701 IN ACCESS_MASK DesiredAccess
,
1702 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1703 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1704 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1705 IN ULONG FileAttributes
,
1706 IN ULONG ShareAccess
,
1707 IN ULONG Disposition
,
1708 IN ULONG CreateOptions
,
1709 IN PVOID EaBuffer OPTIONAL
,
1711 IN CREATE_FILE_TYPE CreateFileType
,
1712 IN PVOID ExtraCreateParameters OPTIONAL
,
1715 KPROCESSOR_MODE AccessMode
;
1716 HANDLE LocalHandle
= 0;
1717 LARGE_INTEGER SafeAllocationSize
;
1718 NTSTATUS Status
= STATUS_SUCCESS
;
1719 PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters
;
1720 POPEN_PACKET OpenPacket
;
1721 ULONG EaErrorOffset
;
1723 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
1726 /* Check if we have no parameter checking to do */
1727 if (Options
& IO_NO_PARAMETER_CHECKING
)
1729 /* Then force kernel-mode access to avoid checks */
1730 AccessMode
= KernelMode
;
1734 /* Otherwise, use the actual mode */
1735 AccessMode
= ExGetPreviousMode();
1738 /* Check if we need to do parameter checking */
1739 if ((AccessMode
!= KernelMode
) || (Options
& IO_CHECK_CREATE_PARAMETERS
))
1741 /* Validate parameters */
1742 if (FileAttributes
& ~FILE_ATTRIBUTE_VALID_FLAGS
)
1744 DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n");
1745 return STATUS_INVALID_PARAMETER
;
1748 if (ShareAccess
& ~FILE_SHARE_VALID_FLAGS
)
1750 DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n");
1751 return STATUS_INVALID_PARAMETER
;
1754 if (Disposition
> FILE_MAXIMUM_DISPOSITION
)
1756 DPRINT1("File Create 'Disposition' Parameter is out of range!\n");
1757 return STATUS_INVALID_PARAMETER
;
1760 if (CreateOptions
& ~FILE_VALID_OPTION_FLAGS
)
1762 DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n");
1763 return STATUS_INVALID_PARAMETER
;
1766 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
)) &&
1767 (!(DesiredAccess
& SYNCHRONIZE
)))
1769 DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n");
1770 return STATUS_INVALID_PARAMETER
;
1773 if ((CreateOptions
& FILE_DELETE_ON_CLOSE
) && (!(DesiredAccess
& DELETE
)))
1775 DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n");
1776 return STATUS_INVALID_PARAMETER
;
1779 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
)) ==
1780 (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
))
1782 DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n");
1783 return STATUS_INVALID_PARAMETER
;
1786 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
1787 (CreateOptions
& ~(FILE_DIRECTORY_FILE
|
1788 FILE_SYNCHRONOUS_IO_ALERT
|
1789 FILE_SYNCHRONOUS_IO_NONALERT
|
1790 FILE_WRITE_THROUGH
|
1791 FILE_COMPLETE_IF_OPLOCKED
|
1792 FILE_OPEN_FOR_BACKUP_INTENT
|
1793 FILE_DELETE_ON_CLOSE
|
1794 FILE_OPEN_FOR_FREE_SPACE_QUERY
|
1795 FILE_OPEN_BY_FILE_ID
|
1796 FILE_NO_COMPRESSION
|
1797 FILE_OPEN_REPARSE_POINT
)))
1799 DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n");
1800 return STATUS_INVALID_PARAMETER
;
1803 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
1804 (Disposition
!= FILE_CREATE
) && (Disposition
!= FILE_OPEN
) && (Disposition
!= FILE_OPEN_IF
))
1806 DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n");
1807 return STATUS_INVALID_PARAMETER
;
1810 if ((CreateOptions
& FILE_COMPLETE_IF_OPLOCKED
) && (CreateOptions
& FILE_RESERVE_OPFILTER
))
1812 DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n");
1813 return STATUS_INVALID_PARAMETER
;
1816 if ((CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
) && (DesiredAccess
& FILE_APPEND_DATA
))
1818 DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n");
1819 return STATUS_INVALID_PARAMETER
;
1822 /* Now check if this is a named pipe */
1823 if (CreateFileType
== CreateFileTypeNamedPipe
)
1825 /* Make sure we have extra parameters */
1826 if (!ExtraCreateParameters
)
1828 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
1829 return STATUS_INVALID_PARAMETER
;
1832 /* Get the parameters and validate them */
1833 NamedPipeCreateParameters
= ExtraCreateParameters
;
1834 if ((NamedPipeCreateParameters
->NamedPipeType
> FILE_PIPE_MESSAGE_TYPE
) ||
1835 (NamedPipeCreateParameters
->ReadMode
> FILE_PIPE_MESSAGE_MODE
) ||
1836 (NamedPipeCreateParameters
->CompletionMode
> FILE_PIPE_COMPLETE_OPERATION
) ||
1837 (ShareAccess
& FILE_SHARE_DELETE
) ||
1838 ((Disposition
< FILE_OPEN
) || (Disposition
> FILE_OPEN_IF
)) ||
1839 (CreateOptions
& ~FILE_VALID_PIPE_OPTION_FLAGS
))
1841 /* Invalid named pipe create */
1842 DPRINT1("Invalid named pipe create\n");
1843 return STATUS_INVALID_PARAMETER
;
1846 else if (CreateFileType
== CreateFileTypeMailslot
)
1848 /* Make sure we have extra parameters */
1849 if (!ExtraCreateParameters
)
1851 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
1852 return STATUS_INVALID_PARAMETER
;
1855 /* Get the parameters and validate them */
1856 if ((ShareAccess
& FILE_SHARE_DELETE
) ||
1857 !(ShareAccess
& ~FILE_SHARE_WRITE
) ||
1858 (Disposition
!= FILE_CREATE
) ||
1859 (CreateOptions
& ~FILE_VALID_MAILSLOT_OPTION_FLAGS
))
1861 /* Invalid mailslot create */
1862 DPRINT1("Invalid mailslot create\n");
1863 return STATUS_INVALID_PARAMETER
;
1868 /* Allocate the open packet */
1869 OpenPacket
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*OpenPacket
), 'pOoI');
1870 if (!OpenPacket
) return STATUS_INSUFFICIENT_RESOURCES
;
1871 RtlZeroMemory(OpenPacket
, sizeof(*OpenPacket
));
1873 /* Check if the call came from user mode */
1874 if (AccessMode
!= KernelMode
)
1878 /* Probe the output parameters */
1879 ProbeForWriteHandle(FileHandle
);
1880 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1882 /* Probe the allocation size if one was passed in */
1885 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
1889 SafeAllocationSize
.QuadPart
= 0;
1892 /* Make sure it's valid */
1893 if (SafeAllocationSize
.QuadPart
< 0)
1895 RtlRaiseStatus(STATUS_INVALID_PARAMETER
);
1898 /* Check if EA was passed in */
1899 if ((EaBuffer
) && (EaLength
))
1902 ProbeForRead(EaBuffer
, EaLength
, sizeof(ULONG
));
1904 /* And marshall it */
1905 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1908 OpenPacket
->EaLength
= EaLength
;
1909 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
1911 /* Validate the buffer */
1912 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
1915 if (!NT_SUCCESS(Status
))
1917 /* Undo everything if it's invalid */
1918 DPRINT1("Invalid EA buffer\n");
1919 IoStatusBlock
->Status
= Status
;
1920 IoStatusBlock
->Information
= EaErrorOffset
;
1921 RtlRaiseStatus(Status
);
1925 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1927 /* Return the exception code */
1928 if (OpenPacket
->EaBuffer
!= NULL
) ExFreePool(OpenPacket
->EaBuffer
);
1929 ExFreePool(OpenPacket
);
1930 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1936 /* Check if this is a device attach */
1937 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
1939 /* Set the flag properly */
1940 Options
|= IO_ATTACH_DEVICE
;
1941 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
1944 /* Check if we have allocation size */
1948 SafeAllocationSize
= *AllocationSize
;
1952 /* Otherwise, no size */
1953 SafeAllocationSize
.QuadPart
= 0;
1956 /* Check if we have an EA packet */
1957 if ((EaBuffer
) && (EaLength
))
1959 /* Allocate the kernel copy */
1960 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1963 if (!OpenPacket
->EaBuffer
)
1965 ExFreePool(OpenPacket
);
1966 DPRINT1("Failed to allocate open packet EA buffer\n");
1967 return STATUS_INSUFFICIENT_RESOURCES
;
1971 OpenPacket
->EaLength
= EaLength
;
1972 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
1974 /* Validate the buffer */
1975 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
1978 if (!NT_SUCCESS(Status
))
1980 /* Undo everything if it's invalid */
1981 DPRINT1("Invalid EA buffer\n");
1982 ExFreePool(OpenPacket
->EaBuffer
);
1983 IoStatusBlock
->Status
= Status
;
1984 IoStatusBlock
->Information
= EaErrorOffset
;
1985 ExFreePool(OpenPacket
);
1991 /* Setup the Open Packet */
1992 OpenPacket
->Type
= IO_TYPE_OPEN_PACKET
;
1993 OpenPacket
->Size
= sizeof(*OpenPacket
);
1994 OpenPacket
->AllocationSize
= SafeAllocationSize
;
1995 OpenPacket
->CreateOptions
= CreateOptions
;
1996 OpenPacket
->FileAttributes
= (USHORT
)FileAttributes
;
1997 OpenPacket
->ShareAccess
= (USHORT
)ShareAccess
;
1998 OpenPacket
->Options
= Options
;
1999 OpenPacket
->Disposition
= Disposition
;
2000 OpenPacket
->CreateFileType
= CreateFileType
;
2001 OpenPacket
->ExtraCreateParameters
= ExtraCreateParameters
;
2003 /* Update the operation count */
2004 IopUpdateOperationCount(IopOtherTransfer
);
2007 * Attempt opening the file. This will call the I/O Parse Routine for
2008 * the File Object (IopParseDevice) which will create the object and
2009 * send the IRP to its device object. Note that we have two statuses
2010 * to worry about: the Object Manager's status (in Status) and the I/O
2011 * status, which is in the Open Packet's Final Status, and determined
2012 * by the Parse Check member.
2014 Status
= ObOpenObjectByName(ObjectAttributes
,
2022 /* Free the EA Buffer */
2023 if (OpenPacket
->EaBuffer
) ExFreePool(OpenPacket
->EaBuffer
);
2025 /* Now check for Ob or Io failure */
2026 if (!(NT_SUCCESS(Status
)) || (OpenPacket
->ParseCheck
!= TRUE
))
2028 /* Check if Ob thinks well went well */
2029 if (NT_SUCCESS(Status
))
2032 * Tell it otherwise. Because we didn't use an ObjectType,
2033 * it incorrectly returned us a handle to God knows what.
2035 ZwClose(LocalHandle
);
2036 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
2039 /* Now check the Io status */
2040 if (!NT_SUCCESS(OpenPacket
->FinalStatus
))
2042 /* Use this status instead of Ob's */
2043 Status
= OpenPacket
->FinalStatus
;
2045 /* Check if it was only a warning */
2046 if (NT_WARNING(Status
))
2048 /* Protect write with SEH */
2051 /* In this case, we copy the I/O Status back */
2052 IoStatusBlock
->Information
= OpenPacket
->Information
;
2053 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2055 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2057 /* Get exception code */
2058 Status
= _SEH2_GetExceptionCode();
2063 else if ((OpenPacket
->FileObject
) && (OpenPacket
->ParseCheck
!= 1))
2066 * This can happen in the very bizarre case where the parse routine
2067 * actually executed more then once (due to a reparse) and ended
2068 * up failing after already having created the File Object.
2070 if (OpenPacket
->FileObject
->FileName
.Length
)
2072 /* It had a name, free it */
2073 ExFreePoolWithTag(OpenPacket
->FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
2076 /* Clear the device object to invalidate the FO, and dereference */
2077 OpenPacket
->FileObject
->DeviceObject
= NULL
;
2078 ObDereferenceObject(OpenPacket
->FileObject
);
2083 /* We reached success and have a valid file handle */
2084 OpenPacket
->FileObject
->Flags
|= FO_HANDLE_CREATED
;
2085 ASSERT(OpenPacket
->FileObject
->Type
== IO_TYPE_FILE
);
2087 /* Enter SEH for write back */
2090 /* Write back the handle and I/O Status */
2091 *FileHandle
= LocalHandle
;
2092 IoStatusBlock
->Information
= OpenPacket
->Information
;
2093 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2095 /* Get the Io status */
2096 Status
= OpenPacket
->FinalStatus
;
2098 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2100 /* Get the exception status */
2101 Status
= _SEH2_GetExceptionCode();
2106 /* Check if we were 100% successful */
2107 if ((OpenPacket
->ParseCheck
!= FALSE
) && (OpenPacket
->FileObject
))
2109 /* Dereference the File Object */
2110 ObDereferenceObject(OpenPacket
->FileObject
);
2114 ExFreePool(OpenPacket
);
2123 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
2124 IN ACCESS_MASK DesiredAccess
,
2125 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2126 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2127 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2128 IN ULONG FileAttributes
,
2129 IN ULONG ShareAccess
,
2130 IN ULONG Disposition
,
2131 IN ULONG CreateOptions
,
2132 IN PVOID EaBuffer OPTIONAL
,
2134 IN CREATE_FILE_TYPE CreateFileType
,
2135 IN PVOID ExtraCreateParameters OPTIONAL
,
2137 IN PVOID DeviceObject
)
2140 return STATUS_NOT_IMPLEMENTED
;
2148 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
2149 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
2150 OUT PHANDLE FileObjectHandle OPTIONAL
)
2152 PFILE_OBJECT CreatedFileObject
;
2155 OBJECT_ATTRIBUTES ObjectAttributes
;
2157 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2159 /* Choose Device Object */
2160 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2162 /* Reference the device object and initialize attributes */
2163 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2164 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2166 /* Create the File Object */
2167 Status
= ObCreateObject(KernelMode
,
2172 sizeof(FILE_OBJECT
),
2173 sizeof(FILE_OBJECT
),
2175 (PVOID
*)&CreatedFileObject
);
2176 if (!NT_SUCCESS(Status
))
2179 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2180 ExRaiseStatus(Status
);
2183 /* Set File Object Data */
2184 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2185 CreatedFileObject
->DeviceObject
= DeviceObject
;
2186 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2187 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2188 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2190 /* Initialize the wait event */
2191 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2193 /* Insert it to create a handle for it */
2194 Status
= ObInsertObject(CreatedFileObject
,
2198 (PVOID
*)&CreatedFileObject
,
2200 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2202 /* Set the handle created flag */
2203 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2204 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2206 /* Check if we have a VPB */
2207 if (DeviceObject
->Vpb
)
2210 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2213 /* Check if the caller wants the handle */
2214 if (FileObjectHandle
)
2217 *FileObjectHandle
= FileHandle
;
2218 ObDereferenceObject(CreatedFileObject
);
2222 /* Otherwise, close it */
2223 ObCloseHandle(FileHandle
, KernelMode
);
2226 /* Return the file object */
2227 return CreatedFileObject
;
2235 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2236 IN PDEVICE_OBJECT DeviceObject
)
2238 /* Call the newer function */
2239 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2247 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2248 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2250 PFILE_OBJECT CreatedFileObject
;
2252 OBJECT_ATTRIBUTES ObjectAttributes
;
2254 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2256 /* Choose Device Object */
2257 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2259 /* Reference the device object and initialize attributes */
2260 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2261 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2263 /* Create the File Object */
2264 Status
= ObCreateObject(KernelMode
,
2269 sizeof(FILE_OBJECT
),
2270 sizeof(FILE_OBJECT
),
2272 (PVOID
*)&CreatedFileObject
);
2273 if (!NT_SUCCESS(Status
))
2276 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2277 ExRaiseStatus(Status
);
2280 /* Set File Object Data */
2281 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2282 CreatedFileObject
->DeviceObject
= DeviceObject
;
2283 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2284 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2285 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2287 /* Initialize the wait event */
2288 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2290 /* Destroy create information */
2291 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2293 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2295 /* Set the handle created flag */
2296 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2297 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2299 /* Check if we have a VPB */
2300 if (DeviceObject
->Vpb
)
2303 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2306 /* Return the file object */
2307 return CreatedFileObject
;
2315 IoGetFileObjectGenericMapping(VOID
)
2317 /* Return the mapping */
2318 return &IopFileMapping
;
2326 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2328 /* Return the flag status */
2329 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2337 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2338 IN ACCESS_MASK DesiredAccess
,
2339 IN ULONG OpenOptions
,
2340 OUT PIO_STATUS_BLOCK IoStatus
,
2341 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2344 DUMMY_FILE_OBJECT LocalFileObject
;
2346 OPEN_PACKET OpenPacket
;
2348 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2350 /* Setup the Open Packet */
2351 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2352 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2353 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2354 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2355 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2356 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2357 OpenPacket
.Disposition
= FILE_OPEN
;
2358 OpenPacket
.NetworkInformation
= Buffer
;
2359 OpenPacket
.QueryOnly
= TRUE
;
2360 OpenPacket
.FullAttributes
= TRUE
;
2361 OpenPacket
.LocalFileObject
= &LocalFileObject
;
2364 * Attempt opening the file. This will call the I/O Parse Routine for
2365 * the File Object (IopParseDevice) which will use the dummy file obejct
2366 * send the IRP to its device object. Note that we have two statuses
2367 * to worry about: the Object Manager's status (in Status) and the I/O
2368 * status, which is in the Open Packet's Final Status, and determined
2369 * by the Parse Check member.
2371 Status
= ObOpenObjectByName(ObjectAttributes
,
2378 if (OpenPacket
.ParseCheck
== FALSE
)
2381 IoStatus
->Status
= Status
;
2385 /* Use the Io status */
2386 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2387 IoStatus
->Information
= OpenPacket
.Information
;
2390 /* Return success */
2399 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2400 OUT PSHARE_ACCESS ShareAccess
)
2404 /* Check if the file has an extension */
2405 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2407 /* Check if caller specified to ignore access checks */
2408 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2410 /* Don't update share access */
2415 /* Otherwise, check if there's any access present */
2416 if ((FileObject
->ReadAccess
) ||
2417 (FileObject
->WriteAccess
) ||
2418 (FileObject
->DeleteAccess
))
2420 /* Increase the open count */
2421 ShareAccess
->OpenCount
++;
2423 /* Add new share access */
2424 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2425 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2426 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2427 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2428 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2429 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2438 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2439 IN ULONG DesiredShareAccess
,
2440 IN PFILE_OBJECT FileObject
,
2441 IN PSHARE_ACCESS ShareAccess
,
2445 BOOLEAN WriteAccess
;
2446 BOOLEAN DeleteAccess
;
2448 BOOLEAN SharedWrite
;
2449 BOOLEAN SharedDelete
;
2452 /* Get access masks */
2453 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2454 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2455 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2457 /* Set them in the file object */
2458 FileObject
->ReadAccess
= ReadAccess
;
2459 FileObject
->WriteAccess
= WriteAccess
;
2460 FileObject
->DeleteAccess
= DeleteAccess
;
2462 /* Check if the file has an extension */
2463 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2465 /* Check if caller specified to ignore access checks */
2466 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2468 /* Don't check share access */
2469 return STATUS_SUCCESS
;
2473 /* Check if we have any access */
2474 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2476 /* Get shared access masks */
2477 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2478 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2479 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2482 FileObject
->SharedRead
= SharedRead
;
2483 FileObject
->SharedWrite
= SharedWrite
;
2484 FileObject
->SharedDelete
= SharedDelete
;
2486 /* Check if the shared access is violated */
2488 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2490 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2492 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2493 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2494 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2495 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2497 /* Sharing violation, fail */
2498 return STATUS_SHARING_VIOLATION
;
2501 /* It's not, check if caller wants us to update it */
2504 /* Increase open count */
2505 ShareAccess
->OpenCount
++;
2507 /* Update shared access */
2508 ShareAccess
->Readers
+= ReadAccess
;
2509 ShareAccess
->Writers
+= WriteAccess
;
2510 ShareAccess
->Deleters
+= DeleteAccess
;
2511 ShareAccess
->SharedRead
+= SharedRead
;
2512 ShareAccess
->SharedWrite
+= SharedWrite
;
2513 ShareAccess
->SharedDelete
+= SharedDelete
;
2517 /* Validation successful */
2518 return STATUS_SUCCESS
;
2526 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2527 IN PSHARE_ACCESS ShareAccess
)
2531 /* Check if the file has an extension */
2532 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2534 /* Check if caller specified to ignore access checks */
2535 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2537 /* Don't update share access */
2542 /* Otherwise, check if there's any access present */
2543 if ((FileObject
->ReadAccess
) ||
2544 (FileObject
->WriteAccess
) ||
2545 (FileObject
->DeleteAccess
))
2547 /* Decrement the open count */
2548 ShareAccess
->OpenCount
--;
2550 /* Remove share access */
2551 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
2552 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
2553 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
2554 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
2555 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
2556 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
2565 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
2566 IN ULONG DesiredShareAccess
,
2567 IN PFILE_OBJECT FileObject
,
2568 OUT PSHARE_ACCESS ShareAccess
)
2571 BOOLEAN WriteAccess
;
2572 BOOLEAN DeleteAccess
;
2574 BOOLEAN SharedWrite
;
2575 BOOLEAN SharedDelete
;
2576 BOOLEAN Update
= TRUE
;
2579 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2580 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2581 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2583 /* Check if the file has an extension */
2584 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2586 /* Check if caller specified to ignore access checks */
2587 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2589 /* Don't update share access */
2594 /* Update basic access */
2595 FileObject
->ReadAccess
= ReadAccess
;
2596 FileObject
->WriteAccess
= WriteAccess
;
2597 FileObject
->DeleteAccess
= DeleteAccess
;
2599 /* Check if we have no access as all */
2600 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
2602 /* Check if we need to update the structure */
2603 if (!Update
) return;
2605 /* Otherwise, clear data */
2606 ShareAccess
->OpenCount
= 0;
2607 ShareAccess
->Readers
= 0;
2608 ShareAccess
->Writers
= 0;
2609 ShareAccess
->Deleters
= 0;
2610 ShareAccess
->SharedRead
= 0;
2611 ShareAccess
->SharedWrite
= 0;
2612 ShareAccess
->SharedDelete
= 0;
2616 /* Calculate shared access */
2617 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2618 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2619 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2621 /* Set it in the FO */
2622 FileObject
->SharedRead
= SharedRead
;
2623 FileObject
->SharedWrite
= SharedWrite
;
2624 FileObject
->SharedDelete
= SharedDelete
;
2626 /* Check if we need to update the structure */
2627 if (!Update
) return;
2629 /* Otherwise, set data */
2630 ShareAccess
->OpenCount
= 1;
2631 ShareAccess
->Readers
= ReadAccess
;
2632 ShareAccess
->Writers
= WriteAccess
;
2633 ShareAccess
->Deleters
= DeleteAccess
;
2634 ShareAccess
->SharedRead
= SharedRead
;
2635 ShareAccess
->SharedWrite
= SharedWrite
;
2636 ShareAccess
->SharedDelete
= SharedDelete
;
2645 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
2646 IN PFILE_OBJECT FileObject
)
2652 PIO_STACK_LOCATION Stack
;
2654 /* Check if handles were already created for the
2655 * open file. If so, that's over.
2657 if (FileObject
->Flags
& FO_HANDLE_CREATED
)
2658 KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN
,
2659 (ULONG_PTR
)FileObject
,
2660 (ULONG_PTR
)DeviceObject
, 0, 0);
2662 /* Reset the events */
2663 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2664 KeClearEvent(&FileObject
->Event
);
2666 /* Allocate the IRP we'll use */
2667 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
2668 /* Properly set it */
2669 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2670 Irp
->UserEvent
= &Event
;
2671 Irp
->UserIosb
= &Irp
->IoStatus
;
2672 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2673 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2674 Irp
->RequestorMode
= KernelMode
;
2675 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
2677 Stack
= IoGetNextIrpStackLocation(Irp
);
2678 Stack
->MajorFunction
= IRP_MJ_CLEANUP
;
2679 Stack
->FileObject
= FileObject
;
2681 /* Put on top of IRPs list of the thread */
2682 IopQueueIrpToThread(Irp
);
2684 /* Call the driver */
2685 Status
= IoCallDriver(DeviceObject
, Irp
);
2686 if (Status
== STATUS_PENDING
)
2688 KeWaitForSingleObject(&Event
, UserRequest
,
2689 KernelMode
, FALSE
, NULL
);
2692 /* Remove from IRPs list */
2693 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2694 IopUnQueueIrpFromThread(Irp
);
2695 KeLowerIrql(OldIrql
);
2700 /* Clear the event */
2701 KeClearEvent(&FileObject
->Event
);
2702 /* And finally, mark the open operation as canceled */
2703 FileObject
->Flags
|= FO_FILE_OPEN_CANCELLED
;
2711 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
2712 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
2715 return STATUS_NOT_IMPLEMENTED
;
2723 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
2726 NTSTATUS Status
= STATUS_SUCCESS
;
2729 /* Get the flag status */
2730 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2732 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
2733 if (Remote
&& !FlagSet
)
2736 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
2738 else if (!Remote
&& FlagSet
)
2740 /* Remove the flag */
2741 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
2746 Status
= STATUS_INVALID_PARAMETER_MIX
;
2758 NtCreateFile(PHANDLE FileHandle
,
2759 ACCESS_MASK DesiredAccess
,
2760 POBJECT_ATTRIBUTES ObjectAttributes
,
2761 PIO_STATUS_BLOCK IoStatusBlock
,
2762 PLARGE_INTEGER AllocateSize
,
2763 ULONG FileAttributes
,
2765 ULONG CreateDisposition
,
2766 ULONG CreateOptions
,
2770 /* Call the I/O Function */
2771 return IoCreateFile(FileHandle
,
2789 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
2790 IN ACCESS_MASK DesiredAccess
,
2791 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2792 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2793 IN ULONG CreateOptions
,
2794 IN ULONG MailslotQuota
,
2795 IN ULONG MaxMessageSize
,
2796 IN PLARGE_INTEGER TimeOut
)
2798 MAILSLOT_CREATE_PARAMETERS Buffer
;
2801 /* Check for Timeout */
2804 /* check if the call came from user mode */
2805 if (KeGetPreviousMode() != KernelMode
)
2807 /* Enter SEH for Probe */
2810 /* Probe the timeout */
2811 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
2813 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2815 /* Return the exception code */
2816 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2822 /* Otherwise, capture directly */
2823 Buffer
.ReadTimeout
= *TimeOut
;
2826 /* Set the correct setting */
2827 Buffer
.TimeoutSpecified
= TRUE
;
2831 /* Tell the FSD we don't have a timeout */
2832 Buffer
.TimeoutSpecified
= FALSE
;
2836 Buffer
.MailslotQuota
= MailslotQuota
;
2837 Buffer
.MaximumMessageSize
= MaxMessageSize
;
2840 return IoCreateFile(FileHandle
,
2846 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2851 CreateFileTypeMailslot
,
2858 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
2859 IN ACCESS_MASK DesiredAccess
,
2860 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2861 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2862 IN ULONG ShareAccess
,
2863 IN ULONG CreateDisposition
,
2864 IN ULONG CreateOptions
,
2865 IN ULONG NamedPipeType
,
2867 IN ULONG CompletionMode
,
2868 IN ULONG MaximumInstances
,
2869 IN ULONG InboundQuota
,
2870 IN ULONG OutboundQuota
,
2871 IN PLARGE_INTEGER DefaultTimeout
)
2873 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
2876 /* Check for Timeout */
2879 /* check if the call came from user mode */
2880 if (KeGetPreviousMode() != KernelMode
)
2882 /* Enter SEH for Probe */
2885 /* Probe the timeout */
2886 Buffer
.DefaultTimeout
=
2887 ProbeForReadLargeInteger(DefaultTimeout
);
2889 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2891 /* Return the exception code */
2892 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2898 /* Otherwise, capture directly */
2899 Buffer
.DefaultTimeout
= *DefaultTimeout
;
2902 /* Set the correct setting */
2903 Buffer
.TimeoutSpecified
= TRUE
;
2907 /* Tell the FSD we don't have a timeout */
2908 Buffer
.TimeoutSpecified
= FALSE
;
2912 Buffer
.NamedPipeType
= NamedPipeType
;
2913 Buffer
.ReadMode
= ReadMode
;
2914 Buffer
.CompletionMode
= CompletionMode
;
2915 Buffer
.MaximumInstances
= MaximumInstances
;
2916 Buffer
.InboundQuota
= InboundQuota
;
2917 Buffer
.OutboundQuota
= OutboundQuota
;
2920 return IoCreateFile(FileHandle
,
2931 CreateFileTypeNamedPipe
,
2938 NtFlushWriteBuffer(VOID
)
2942 /* Call the kernel */
2943 KeFlushWriteBuffer();
2944 return STATUS_SUCCESS
;
2952 NtOpenFile(OUT PHANDLE FileHandle
,
2953 IN ACCESS_MASK DesiredAccess
,
2954 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2955 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2956 IN ULONG ShareAccess
,
2957 IN ULONG OpenOptions
)
2959 /* Call the I/O Function */
2960 return IoCreateFile(FileHandle
,
2978 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2979 OUT PFILE_BASIC_INFORMATION FileInformation
)
2981 /* Call the internal helper API */
2982 return IopQueryAttributesFile(ObjectAttributes
,
2983 FileBasicInformation
,
2984 sizeof(FILE_BASIC_INFORMATION
),
2990 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2991 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2993 /* Call the internal helper API */
2994 return IopQueryAttributesFile(ObjectAttributes
,
2995 FileNetworkOpenInformation
,
2996 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
3001 * @name NtCancelIoFile
3003 * Cancel all pending I/O operations in the current thread for specified
3007 * Handle to file object to cancel requests for. No specific
3008 * access rights are needed.
3009 * @param IoStatusBlock
3010 * Pointer to status block which is filled with final completition
3011 * status on successful return.
3019 NtCancelIoFile(IN HANDLE FileHandle
,
3020 OUT PIO_STATUS_BLOCK IoStatusBlock
)
3022 PFILE_OBJECT FileObject
;
3026 BOOLEAN OurIrpsInList
= FALSE
;
3027 LARGE_INTEGER Interval
;
3028 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3030 PLIST_ENTRY ListHead
, NextEntry
;
3032 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3034 /* Check the previous mode */
3035 if (PreviousMode
!= KernelMode
)
3037 /* Enter SEH for probing */
3040 /* Probe the I/O Status Block */
3041 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3043 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3045 /* Return the exception code */
3046 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3051 /* Reference the file object */
3052 Status
= ObReferenceObjectByHandle(FileHandle
,
3056 (PVOID
*)&FileObject
,
3058 if (!NT_SUCCESS(Status
)) return Status
;
3060 /* IRP cancellations are synchronized at APC_LEVEL. */
3061 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3063 /* Get the current thread */
3064 Thread
= PsGetCurrentThread();
3066 /* Update the operation counts */
3067 IopUpdateOperationCount(IopOtherTransfer
);
3070 ListHead
= &Thread
->IrpList
;
3071 NextEntry
= ListHead
->Flink
;
3072 while (ListHead
!= NextEntry
)
3074 /* Get the IRP and check if the File Object matches */
3075 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3076 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3078 /* Cancel this IRP and keep looping */
3080 OurIrpsInList
= TRUE
;
3083 /* Go to the next entry */
3084 NextEntry
= NextEntry
->Flink
;
3087 /* Lower the IRQL */
3088 KeLowerIrql(OldIrql
);
3090 /* Check if we had found an IRP */
3093 /* Setup a 10ms wait */
3094 Interval
.QuadPart
= -100000;
3097 while (OurIrpsInList
)
3100 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
3101 OurIrpsInList
= FALSE
;
3104 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3106 /* Now loop the list again */
3107 NextEntry
= ListHead
->Flink
;
3108 while (NextEntry
!= ListHead
)
3110 /* Get the IRP and check if the File Object matches */
3111 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3112 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3115 OurIrpsInList
= TRUE
;
3119 /* Go to the next entry */
3120 NextEntry
= NextEntry
->Flink
;
3123 /* Lower the IRQL */
3124 KeLowerIrql(OldIrql
);
3128 /* Enter SEH for writing back the I/O Status */
3132 IoStatusBlock
->Status
= STATUS_SUCCESS
;
3133 IoStatusBlock
->Information
= 0;
3135 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3137 /* Ignore exception */
3141 /* Dereference the file object and return success */
3142 ObDereferenceObject(FileObject
);
3143 return STATUS_SUCCESS
;
3151 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
3154 DUMMY_FILE_OBJECT LocalFileObject
;
3156 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
3157 OPEN_PACKET OpenPacket
;
3159 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
3161 /* Setup the Open Packet */
3162 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
3163 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
3164 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
3165 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
3166 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
3169 OpenPacket
.Disposition
= FILE_OPEN
;
3170 OpenPacket
.DeleteOnly
= TRUE
;
3171 OpenPacket
.LocalFileObject
= &LocalFileObject
;
3173 /* Update the operation counts */
3174 IopUpdateOperationCount(IopOtherTransfer
);
3177 * Attempt opening the file. This will call the I/O Parse Routine for
3178 * the File Object (IopParseDevice) which will use the dummy file obejct
3179 * send the IRP to its device object. Note that we have two statuses
3180 * to worry about: the Object Manager's status (in Status) and the I/O
3181 * status, which is in the Open Packet's Final Status, and determined
3182 * by the Parse Check member.
3184 Status
= ObOpenObjectByName(ObjectAttributes
,
3191 if (OpenPacket
.ParseCheck
== FALSE
) return Status
;
3193 /* Retrn the Io status */
3194 return OpenPacket
.FinalStatus
;