2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/file.c
5 * PURPOSE: Functions that deal with managing the FILE_OBJECT itself.
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 * Filip Navara (navaraf@reactos.org)
12 /* INCLUDES *****************************************************************/
18 /* PRIVATE FUNCTIONS *********************************************************/
22 IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState
,
23 IN OUT PULONG CreateOptions
,
24 IN KPROCESSOR_MODE PreviousMode
,
27 ACCESS_MASK DesiredAccess
, ReadAccess
, WriteAccess
;
28 PRIVILEGE_SET Privileges
;
29 BOOLEAN AccessGranted
, HaveBackupPriv
= FALSE
, CheckRestore
= FALSE
;
32 /* Don't do anything if privileges were checked already */
33 if (AccessState
->Flags
& SE_BACKUP_PRIVILEGES_CHECKED
) return;
35 /* Check if the file was actually opened for backup purposes */
36 if (*CreateOptions
& FILE_OPEN_FOR_BACKUP_INTENT
)
38 /* Set the check flag since were doing it now */
39 AccessState
->Flags
|= SE_BACKUP_PRIVILEGES_CHECKED
;
41 /* Set the access masks required */
42 ReadAccess
= READ_CONTROL
|
43 ACCESS_SYSTEM_SECURITY
|
46 WriteAccess
= WRITE_DAC
|
48 ACCESS_SYSTEM_SECURITY
|
51 FILE_ADD_SUBDIRECTORY
|
53 DesiredAccess
= AccessState
->RemainingDesiredAccess
;
55 /* Check if desired access was the maximum */
56 if (DesiredAccess
& MAXIMUM_ALLOWED
)
58 /* Then add all the access masks required */
59 DesiredAccess
|= (ReadAccess
| WriteAccess
);
62 /* Check if the file already exists */
63 if (Disposition
& FILE_OPEN
)
65 /* Check if desired access has the read mask */
66 if (ReadAccess
& DesiredAccess
)
68 /* Setup the privilege check lookup */
69 Privileges
.PrivilegeCount
= 1;
70 Privileges
.Control
= PRIVILEGE_SET_ALL_NECESSARY
;
71 Privileges
.Privilege
[0].Luid
= SeBackupPrivilege
;
72 Privileges
.Privilege
[0].Attributes
= 0;
73 AccessGranted
= SePrivilegeCheck(&Privileges
,
75 SubjectSecurityContext
,
79 /* Remember that backup was allowed */
80 HaveBackupPriv
= TRUE
;
82 /* Append the privileges and update the access state */
83 SeAppendPrivileges(AccessState
, &Privileges
);
84 AccessState
->PreviouslyGrantedAccess
|= (DesiredAccess
& ReadAccess
);
85 AccessState
->RemainingDesiredAccess
&= ~ReadAccess
;
86 DesiredAccess
&= ~ReadAccess
;
88 /* Set backup privilege for the token */
89 AccessState
->Flags
|= TOKEN_HAS_BACKUP_PRIVILEGE
;
95 /* Caller is creating the file, check restore privileges later */
99 /* Check if caller wants write access or if it's creating a file */
100 if ((WriteAccess
& DesiredAccess
) || (CheckRestore
))
102 /* Setup the privilege lookup and do it */
103 Privileges
.PrivilegeCount
= 1;
104 Privileges
.Control
= PRIVILEGE_SET_ALL_NECESSARY
;
105 Privileges
.Privilege
[0].Luid
= SeRestorePrivilege
;
106 Privileges
.Privilege
[0].Attributes
= 0;
107 AccessGranted
= SePrivilegeCheck(&Privileges
,
108 &AccessState
->SubjectSecurityContext
,
112 /* Remember that privilege was given */
113 HaveBackupPriv
= TRUE
;
115 /* Append the privileges and update the access state */
116 SeAppendPrivileges(AccessState
, &Privileges
);
117 AccessState
->PreviouslyGrantedAccess
|= (DesiredAccess
& WriteAccess
);
118 AccessState
->RemainingDesiredAccess
&= ~WriteAccess
;
120 /* Set restore privilege for the token */
121 AccessState
->Flags
|= TOKEN_HAS_RESTORE_PRIVILEGE
;
125 /* If we don't have the privilege, remove the option */
126 if (!HaveBackupPriv
) *CreateOptions
&= ~FILE_OPEN_FOR_BACKUP_INTENT
;
132 IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket
,
133 IN PDEVICE_OBJECT DeviceObject
)
135 /* Make sure the object is valid */
136 if ((IoGetDevObjExtension(DeviceObject
)->ExtensionFlags
&
137 (DOE_UNLOAD_PENDING
|
140 DOE_REMOVE_PROCESSED
)) ||
141 (DeviceObject
->Flags
& DO_DEVICE_INITIALIZING
))
143 /* It's unloading or initializing, so fail */
144 DPRINT1("You are seeing this because the following ROS driver: %wZ\n"
145 " sucks. Please fix it's AddDevice Routine\n",
146 &DeviceObject
->DriverObject
->DriverName
);
147 return STATUS_NO_SUCH_DEVICE
;
149 else if ((DeviceObject
->Flags
& DO_EXCLUSIVE
) &&
150 (DeviceObject
->ReferenceCount
) &&
151 !(OpenPacket
->RelatedFileObject
) &&
152 !(OpenPacket
->Options
& IO_ATTACH_DEVICE
))
154 return STATUS_ACCESS_DENIED
;
159 /* Increase reference count */
160 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
161 return STATUS_SUCCESS
;
167 IopParseDevice(IN PVOID ParseObject
,
169 IN OUT PACCESS_STATE AccessState
,
170 IN KPROCESSOR_MODE AccessMode
,
172 IN OUT PUNICODE_STRING CompleteName
,
173 IN OUT PUNICODE_STRING RemainingName
,
174 IN OUT PVOID Context
,
175 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
178 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
179 PDEVICE_OBJECT OriginalDeviceObject
= (PDEVICE_OBJECT
)ParseObject
;
180 PDEVICE_OBJECT DeviceObject
, OwnerDevice
;
182 PFILE_OBJECT FileObject
;
185 PEXTENDED_IO_STACK_LOCATION StackLoc
;
186 IO_SECURITY_CONTEXT SecurityContext
;
187 IO_STATUS_BLOCK IoStatusBlock
;
188 BOOLEAN DirectOpen
= FALSE
, OpenCancelled
, UseDummyFile
;
189 OBJECT_ATTRIBUTES ObjectAttributes
;
191 PDUMMY_FILE_OBJECT LocalFileObject
;
192 PFILE_BASIC_INFORMATION FileBasicInfo
;
194 KPROCESSOR_MODE CheckMode
;
195 BOOLEAN VolumeOpen
= FALSE
;
196 ACCESS_MASK DesiredAccess
, GrantedAccess
;
197 BOOLEAN AccessGranted
, LockHeld
= FALSE
;
198 PPRIVILEGE_SET Privileges
= NULL
;
199 UNICODE_STRING FileString
;
200 IOTRACE(IO_FILE_DEBUG
, "ParseObject: %p. RemainingName: %wZ\n",
201 ParseObject
, RemainingName
);
206 /* Validate the open packet */
207 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
209 /* Check if we have a related file object */
210 if (OpenPacket
->RelatedFileObject
)
212 /* Use the related file object's device object */
213 OriginalDeviceObject
= OpenPacket
->RelatedFileObject
->DeviceObject
;
216 /* Validate device status */
217 Status
= IopCheckDeviceAndDriver(OpenPacket
, OriginalDeviceObject
);
218 if (!NT_SUCCESS(Status
))
220 /* We failed, return status */
221 OpenPacket
->FinalStatus
= Status
;
225 /* Map the generic mask and set the new mapping in the access state */
226 RtlMapGenericMask(&AccessState
->RemainingDesiredAccess
,
227 &IoFileObjectType
->TypeInfo
.GenericMapping
);
228 RtlMapGenericMask(&AccessState
->OriginalDesiredAccess
,
229 &IoFileObjectType
->TypeInfo
.GenericMapping
);
230 SeSetAccessStateGenericMapping(AccessState
,
231 &IoFileObjectType
->TypeInfo
.GenericMapping
);
232 DesiredAccess
= AccessState
->RemainingDesiredAccess
;
234 /* Check what kind of access checks to do */
235 if ((AccessMode
!= KernelMode
) ||
236 (OpenPacket
->Options
& IO_FORCE_ACCESS_CHECK
))
238 /* Call is from user-mode or kernel is forcing checks */
239 CheckMode
= UserMode
;
243 /* Call is from the kernel */
244 CheckMode
= KernelMode
;
247 /* Check privilege for backup or restore operation */
248 IopCheckBackupRestorePrivilege(AccessState
,
249 &OpenPacket
->CreateOptions
,
251 OpenPacket
->Disposition
);
253 /* Check if we are re-parsing */
254 if (((OpenPacket
->Override
) && !(RemainingName
->Length
)) ||
255 (AccessState
->Flags
& SE_BACKUP_PRIVILEGES_CHECKED
))
257 /* Get granted access from the last call */
258 DesiredAccess
|= AccessState
->PreviouslyGrantedAccess
;
261 /* Check if this is a volume open */
262 if ((OpenPacket
->RelatedFileObject
) &&
263 (OpenPacket
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
) &&
264 !(RemainingName
->Length
))
270 /* Now check if we need access checks */
271 if (((AccessMode
!= KernelMode
) ||
272 (OpenPacket
->Options
& IO_FORCE_ACCESS_CHECK
)) &&
273 (!(OpenPacket
->RelatedFileObject
) || (VolumeOpen
)) &&
274 !(OpenPacket
->Override
))
276 /* Check if a device object is being parsed */
277 if (!RemainingName
->Length
)
279 /* Lock the subject context */
280 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
283 /* Do access check */
284 AccessGranted
= SeAccessCheck(OriginalDeviceObject
->
286 &AccessState
->SubjectSecurityContext
,
292 TypeInfo
.GenericMapping
,
298 /* Append and free the privileges */
299 SeAppendPrivileges(AccessState
, Privileges
);
300 SeFreePrivileges(Privileges
);
303 /* Check if we got access */
306 /* Update access state */
307 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
308 AccessState
->RemainingDesiredAccess
&= ~(GrantedAccess
&
310 OpenPacket
->Override
= TRUE
;
313 FileString
.Length
= 8;
314 FileString
.MaximumLength
= 8;
315 FileString
.Buffer
= L
"File";
317 /* Do Audit/Alarm for open operation */
318 SeOpenObjectAuditAlarm(&FileString
,
319 OriginalDeviceObject
,
321 OriginalDeviceObject
->SecurityDescriptor
,
326 &AccessState
->GenerateOnClose
);
330 /* Check if we need to do traverse validation */
331 if (!(AccessState
->Flags
& TOKEN_HAS_TRAVERSE_PRIVILEGE
) ||
332 ((OriginalDeviceObject
->DeviceType
== FILE_DEVICE_DISK
) ||
333 (OriginalDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
)))
335 /* Check if this is a restricted token */
336 if (!(AccessState
->Flags
& TOKEN_IS_RESTRICTED
))
338 /* Do the FAST traverse check */
339 AccessGranted
= SeFastTraverseCheck(OriginalDeviceObject
->SecurityDescriptor
,
347 AccessGranted
= FALSE
;
350 /* Check if we failed to get access */
353 /* Lock the subject context */
354 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
357 /* Do access check */
358 AccessGranted
= SeAccessCheck(OriginalDeviceObject
->
360 &AccessState
->SubjectSecurityContext
,
366 TypeInfo
.GenericMapping
,
372 /* Append and free the privileges */
373 SeAppendPrivileges(AccessState
, Privileges
);
374 SeFreePrivileges(Privileges
);
378 /* FIXME: Do Audit/Alarm for traverse check */
382 /* Access automatically granted */
383 AccessGranted
= TRUE
;
387 /* Check if we hold the lock */
391 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
394 /* Check if access failed */
397 /* Dereference the device and fail */
398 DPRINT1("Traverse access failed!\n");
399 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
400 return STATUS_ACCESS_DENIED
;
404 /* Check if we can simply use a dummy file */
405 UseDummyFile
= ((OpenPacket
->QueryOnly
) || (OpenPacket
->DeleteOnly
));
407 /* Check if this is a direct open */
408 if (!(RemainingName
->Length
) &&
409 !(OpenPacket
->RelatedFileObject
) &&
410 ((DesiredAccess
& ~(SYNCHRONIZE
|
411 FILE_READ_ATTRIBUTES
|
413 ACCESS_SYSTEM_SECURITY
|
418 /* Remember this for later */
422 /* FIXME: Small hack still exists, have to check why...
423 * This is triggered multiple times by usetup and then once per boot.
426 !(RemainingName
->Length
) &&
427 !(OpenPacket
->RelatedFileObject
) &&
428 ((wcsstr(CompleteName
->Buffer
, L
"Harddisk")) ||
429 (wcsstr(CompleteName
->Buffer
, L
"Floppy"))) &&
432 DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
433 DesiredAccess
& ~(SYNCHRONIZE
|
434 FILE_READ_ATTRIBUTES
|
436 ACCESS_SYSTEM_SECURITY
|
442 /* Check if we have a related FO that wasn't a direct open */
443 if ((OpenPacket
->RelatedFileObject
) &&
444 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
446 /* The device object is the one we were given */
447 DeviceObject
= ParseObject
;
449 /* Check if the related FO had a VPB */
450 if (OpenPacket
->RelatedFileObject
->Vpb
)
452 /* Yes, remember it */
453 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
456 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
461 /* The device object is the one we were given */
462 DeviceObject
= OriginalDeviceObject
;
464 /* Check if it has a VPB */
465 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
467 /* Check if the VPB is mounted, and mount it */
468 Vpb
= IopCheckVpbMounted(OpenPacket
,
469 OriginalDeviceObject
,
472 if (!Vpb
) return Status
;
474 /* Get the VPB's device object */
475 DeviceObject
= Vpb
->DeviceObject
;
478 /* Check if there's an attached device */
479 if (DeviceObject
->AttachedDevice
)
481 /* Get the attached device */
482 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
486 /* Check if this is a secure FSD */
487 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
488 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
491 DPRINT("Fix Secure FSD support!!!\n");
494 /* Allocate the IRP */
495 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
498 /* Dereference the device and VPB, then fail */
499 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
500 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
501 return STATUS_INSUFFICIENT_RESOURCES
;
504 /* Now set the IRP data */
505 Irp
->RequestorMode
= AccessMode
;
506 Irp
->Flags
= IRP_CREATE_OPERATION
| IRP_SYNCHRONOUS_API
| IRP_DEFER_IO_COMPLETION
;
507 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
508 Irp
->UserIosb
= &IoStatusBlock
;
509 Irp
->MdlAddress
= NULL
;
510 Irp
->PendingReturned
= FALSE
;
511 Irp
->UserEvent
= NULL
;
513 Irp
->CancelRoutine
= NULL
;
514 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
516 /* Setup the security context */
517 SecurityContext
.SecurityQos
= SecurityQos
;
518 SecurityContext
.AccessState
= AccessState
;
519 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
520 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
522 /* Get the I/O Stack location */
523 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
524 StackLoc
->Control
= 0;
526 /* Check what kind of file this is */
527 switch (OpenPacket
->CreateFileType
)
530 case CreateFileTypeNone
:
532 /* Set the major function and EA Length */
533 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
534 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
537 StackLoc
->Flags
= (UCHAR
)OpenPacket
->Options
;
538 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ? SL_CASE_SENSITIVE
: 0;
542 case CreateFileTypeNamedPipe
:
544 /* Set the named pipe MJ and set the parameters */
545 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
546 StackLoc
->Parameters
.CreatePipe
.Parameters
= OpenPacket
->ExtraCreateParameters
;
550 case CreateFileTypeMailslot
:
552 /* Set the mailslot MJ and set the parameters */
553 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
554 StackLoc
->Parameters
.CreateMailslot
.Parameters
= OpenPacket
->ExtraCreateParameters
;
558 /* Set the common data */
559 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
560 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
561 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
562 (OpenPacket
->CreateOptions
&
564 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
565 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
566 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
568 /* Check if we really need to create an object */
571 /* Create the actual file object */
572 InitializeObjectAttributes(&ObjectAttributes
,
577 Status
= ObCreateObject(KernelMode
,
585 (PVOID
*)&FileObject
);
586 if (!NT_SUCCESS(Status
))
588 /* Create failed, free the IRP */
591 /* Dereference the device and VPB */
592 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
593 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
595 /* We failed, return status */
596 OpenPacket
->FinalStatus
= Status
;
600 /* Clear the file object */
601 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
603 /* Check if this is Synch I/O */
604 if (OpenPacket
->CreateOptions
&
605 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
607 /* Set the synch flag */
608 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
610 /* Check if it's also alertable */
611 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
613 /* It is, set the alertable flag */
614 FileObject
->Flags
|= FO_ALERTABLE_IO
;
618 /* Check if this is synch I/O */
619 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
621 /* Initialize the event */
622 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
625 /* Check if the caller requested no intermediate buffering */
626 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
628 /* Set the correct flag for the FSD to read */
629 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
632 /* Check if the caller requested write through support */
633 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
635 /* Set the correct flag for the FSD to read */
636 FileObject
->Flags
|= FO_WRITE_THROUGH
;
639 /* Check if the caller says the file will be only read sequentially */
640 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
642 /* Set the correct flag for the FSD to read */
643 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
646 /* Check if the caller believes the file will be only read randomly */
647 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
649 /* Set the correct flag for the FSD to read */
650 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
655 /* Use the dummy object instead */
656 LocalFileObject
= OpenPacket
->LocalFileObject
;
657 RtlZeroMemory(LocalFileObject
, sizeof(DUMMY_FILE_OBJECT
));
660 FileObject
= (PFILE_OBJECT
)&LocalFileObject
->ObjectHeader
.Body
;
661 LocalFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
662 LocalFileObject
->ObjectHeader
.PointerCount
= 1;
665 /* Setup the file header */
666 FileObject
->Type
= IO_TYPE_FILE
;
667 FileObject
->Size
= sizeof(FILE_OBJECT
);
668 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
669 FileObject
->DeviceObject
= OriginalDeviceObject
;
671 /* Check if this is a direct device open */
672 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
674 /* Check if the caller wants case sensitivity */
675 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
677 /* Tell the driver about it */
678 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
681 /* Now set the file object */
682 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
683 StackLoc
->FileObject
= FileObject
;
685 /* Check if the file object has a name */
686 if (RemainingName
->Length
)
688 /* Setup the unicode string */
689 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
691 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
696 if (!FileObject
->FileName
.Buffer
)
698 /* Failed to allocate the name, free the IRP */
701 /* Dereference the device object and VPB */
702 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
703 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
705 /* Clear the FO and dereference it */
706 FileObject
->DeviceObject
= NULL
;
707 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
710 return STATUS_INSUFFICIENT_RESOURCES
;
715 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
717 /* Initialize the File Object event and set the FO */
718 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
719 OpenPacket
->FileObject
= FileObject
;
721 /* Queue the IRP and call the driver */
722 IopQueueIrpToThread(Irp
);
723 Status
= IoCallDriver(DeviceObject
, Irp
);
724 if (Status
== STATUS_PENDING
)
726 /* Wait for the driver to complete the create */
727 KeWaitForSingleObject(&FileObject
->Event
,
733 /* Get the new status */
734 Status
= IoStatusBlock
.Status
;
738 /* We'll have to complete it ourselves */
739 ASSERT(!Irp
->PendingReturned
);
740 ASSERT(!Irp
->MdlAddress
);
742 /* Completion happens at APC_LEVEL */
743 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
745 /* Get the new I/O Status block ourselves */
746 IoStatusBlock
= Irp
->IoStatus
;
747 Status
= IoStatusBlock
.Status
;
749 /* Manually signal the even, we can't have any waiters */
750 FileObject
->Event
.Header
.SignalState
= 1;
752 /* Now that we've signaled the events, de-associate the IRP */
753 IopUnQueueIrpFromThread(Irp
);
755 /* Check if the IRP had an input buffer */
756 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
757 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
759 /* Free it. A driver might've tacked one on */
760 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
763 /* Free the IRP and bring the IRQL back down */
765 KeLowerIrql(OldIrql
);
768 /* Copy the I/O Status */
769 OpenPacket
->Information
= IoStatusBlock
.Information
;
771 /* The driver failed to create the file */
772 if (!NT_SUCCESS(Status
))
774 /* Check if we have a name */
775 if (FileObject
->FileName
.Length
)
778 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
779 FileObject
->FileName
.Length
= 0;
782 /* Clear its device object */
783 FileObject
->DeviceObject
= NULL
;
785 /* Save this now because the FO might go away */
786 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
789 /* Clear the file object in the open packet */
790 OpenPacket
->FileObject
= NULL
;
792 /* Dereference the file object */
793 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
795 /* Dereference the device object */
796 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
798 /* Unless the driver cancelled the open, dereference the VPB */
799 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpbAndFree(Vpb
);
801 /* Set the status and return */
802 OpenPacket
->FinalStatus
= Status
;
805 else if (Status
== STATUS_REPARSE
)
807 /* FIXME: We don't handle this at all! */
811 /* Get the owner of the File Object */
812 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
815 * It's possible that the device to whom we sent the IRP to
816 * isn't actually the device that ended opening the file object
819 if (OwnerDevice
!= DeviceObject
)
821 /* We have to de-reference the VPB we had associated */
822 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
824 /* And re-associate with the actual one */
825 Vpb
= FileObject
->Vpb
;
826 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
829 /* Make sure we are not using a dummy */
832 /* Check if this was a volume open */
833 if ((!(FileObject
->RelatedFileObject
) ||
834 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
835 !(FileObject
->FileName
.Length
))
837 /* All signs point to it, but make sure it was actually an FSD */
838 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
839 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
840 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
841 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
843 /* The owner device is an FSD, so this is a volume open for real */
844 FileObject
->Flags
|= FO_VOLUME_OPEN
;
848 /* Reference the object and set the parse check */
849 ObReferenceObject(FileObject
);
850 *Object
= FileObject
;
851 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
852 OpenPacket
->ParseCheck
= TRUE
;
853 return OpenPacket
->FinalStatus
;
857 /* Check if this was a query */
858 if (OpenPacket
->QueryOnly
)
860 /* Check if the caller wants basic info only */
861 if (!OpenPacket
->FullAttributes
)
863 /* Allocate the buffer */
864 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
865 sizeof(*FileBasicInfo
),
870 Status
= IoQueryFileInformation(FileObject
,
871 FileBasicInformation
,
872 sizeof(*FileBasicInfo
),
875 if (NT_SUCCESS(Status
))
878 RtlCopyMemory(OpenPacket
->BasicInformation
,
883 /* Free our buffer */
884 ExFreePoolWithTag(FileBasicInfo
, TAG_IO
);
889 Status
= STATUS_INSUFFICIENT_RESOURCES
;
894 /* This is a full query */
895 Status
= IoQueryFileInformation(
897 FileNetworkOpenInformation
,
898 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
899 OpenPacket
->NetworkInformation
,
901 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
905 /* Delete the file object */
906 IopDeleteFile(FileObject
);
908 /* Clear out the file */
909 OpenPacket
->FileObject
= NULL
;
911 /* Set and return status */
912 OpenPacket
->FinalStatus
= Status
;
913 OpenPacket
->ParseCheck
= TRUE
;
920 IopParseFile(IN PVOID ParseObject
,
922 IN OUT PACCESS_STATE AccessState
,
923 IN KPROCESSOR_MODE AccessMode
,
925 IN OUT PUNICODE_STRING CompleteName
,
926 IN OUT PUNICODE_STRING RemainingName
,
927 IN OUT PVOID Context OPTIONAL
,
928 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
932 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
934 /* Validate the open packet */
935 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
937 /* Get the device object */
938 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
939 OpenPacket
->RelatedFileObject
= ParseObject
;
941 /* Call the main routine */
942 return IopParseDevice(DeviceObject
,
956 IopDeleteFile(IN PVOID ObjectBody
)
958 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
960 PIO_STACK_LOCATION StackPtr
;
963 PDEVICE_OBJECT DeviceObject
;
964 BOOLEAN DereferenceDone
= FALSE
;
967 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
969 /* Check if the file has a device object */
970 if (FileObject
->DeviceObject
)
972 /* Check if this is a direct open or not */
973 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
975 /* Get the attached device */
976 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
980 /* Use the file object's device object */
981 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
985 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
986 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
988 /* Check if the handle wasn't created yet */
989 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
991 /* Send the cleanup IRP */
992 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
995 /* Clear and set up Events */
996 KeClearEvent(&FileObject
->Event
);
997 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
999 /* Allocate an IRP */
1000 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1004 Irp
->UserEvent
= &Event
;
1005 Irp
->UserIosb
= &Irp
->IoStatus
;
1006 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1007 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1008 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1010 /* Set up Stack Pointer Data */
1011 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1012 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
1013 StackPtr
->FileObject
= FileObject
;
1016 IopQueueIrpToThread(Irp
);
1018 /* Get the VPB and check if this isn't a direct open */
1019 Vpb
= FileObject
->Vpb
;
1020 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1022 /* Dereference the VPB before the close */
1023 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1026 /* Check if the FS will never disappear by itself */
1027 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1029 /* Dereference it */
1030 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1031 DereferenceDone
= TRUE
;
1034 /* Call the FS Driver */
1035 Status
= IoCallDriver(DeviceObject
, Irp
);
1036 if (Status
== STATUS_PENDING
)
1038 /* Wait for completion */
1039 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1042 /* De-queue the IRP */
1043 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1044 IopUnQueueIrpFromThread(Irp
);
1045 KeLowerIrql(OldIrql
);
1050 /* Clear the file name */
1051 if (FileObject
->FileName
.Buffer
)
1053 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1054 FileObject
->FileName
.Buffer
= NULL
;
1057 /* Check if the FO had a completion port */
1058 if (FileObject
->CompletionContext
)
1061 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1062 ExFreePool(FileObject
->CompletionContext
);
1065 /* Check if the FO had extension */
1066 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1068 /* Release filter context structure if any */
1069 FsRtlPTeardownPerFileObjectContexts(FileObject
);
1072 /* Check if dereference has been done yet */
1073 if (!DereferenceDone
)
1075 /* Dereference device object */
1076 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1083 IopSecurityFile(IN PVOID ObjectBody
,
1084 IN SECURITY_OPERATION_CODE OperationCode
,
1085 IN PSECURITY_INFORMATION SecurityInformation
,
1086 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1087 IN OUT PULONG BufferLength
,
1088 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1089 IN POOL_TYPE PoolType
,
1090 IN OUT PGENERIC_MAPPING GenericMapping
)
1092 IO_STATUS_BLOCK IoStatusBlock
;
1093 PIO_STACK_LOCATION StackPtr
;
1094 PFILE_OBJECT FileObject
;
1095 PDEVICE_OBJECT DeviceObject
;
1097 BOOLEAN LocalEvent
= FALSE
;
1099 NTSTATUS Status
= STATUS_SUCCESS
;
1101 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1103 /* Check if this is a device or file */
1104 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1107 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1113 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1115 /* Check if this is a direct open */
1116 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1118 /* Get the Device Object */
1119 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1123 /* Otherwise, use the direct device*/
1124 DeviceObject
= FileObject
->DeviceObject
;
1128 /* Check if the request was for a device object */
1129 if (!(FileObject
) ||
1130 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1131 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1133 /* Check what kind of request this was */
1134 if (OperationCode
== QuerySecurityDescriptor
)
1136 return SeQuerySecurityDescriptorInfo(SecurityInformation
,
1139 &DeviceObject
->SecurityDescriptor
);
1141 else if (OperationCode
== DeleteSecurityDescriptor
)
1143 /* Simply return success */
1144 return STATUS_SUCCESS
;
1146 else if (OperationCode
== AssignSecurityDescriptor
)
1148 /* Make absolutely sure this is a device object */
1149 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1151 /* Assign the Security Descriptor */
1152 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
1155 /* Return success */
1156 return STATUS_SUCCESS
;
1160 DPRINT1("FIXME: Set SD unimplemented for Devices\n");
1161 return STATUS_SUCCESS
;
1164 else if (OperationCode
== DeleteSecurityDescriptor
)
1166 /* Same as for devices, do nothing */
1167 return STATUS_SUCCESS
;
1170 /* At this point, we know we're a file. Reference it */
1171 ObReferenceObject(FileObject
);
1173 /* Check if we should use Sync IO or not */
1174 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1176 /* Lock the file object */
1177 IopLockFileObject(FileObject
);
1181 /* Use local event */
1182 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1186 /* Clear the File Object event */
1187 KeClearEvent(&FileObject
->Event
);
1189 /* Get the device object */
1190 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1192 /* Allocate the IRP */
1193 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1194 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1197 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1198 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1199 Irp
->RequestorMode
= ExGetPreviousMode();
1200 Irp
->UserIosb
= &IoStatusBlock
;
1201 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1202 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1203 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1205 /* Set Stack Parameters */
1206 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1207 StackPtr
->FileObject
= FileObject
;
1209 /* Check if this is a query or set */
1210 if (OperationCode
== QuerySecurityDescriptor
)
1212 /* Set the major function and parameters */
1213 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1214 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1215 *SecurityInformation
;
1216 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1217 Irp
->UserBuffer
= SecurityDescriptor
;
1221 /* Set the major function and parameters for a set */
1222 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1223 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1224 *SecurityInformation
;
1225 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1230 IopQueueIrpToThread(Irp
);
1232 /* Update operation counts */
1233 IopUpdateOperationCount(IopOtherTransfer
);
1235 /* Call the Driver */
1236 Status
= IoCallDriver(DeviceObject
, Irp
);
1238 /* Check if this was async I/O */
1241 /* Check if the IRP is pending completion */
1242 if (Status
== STATUS_PENDING
)
1244 /* Wait on the local event */
1245 KeWaitForSingleObject(&Event
,
1250 Status
= IoStatusBlock
.Status
;
1255 /* Check if the IRP is pending completion */
1256 if (Status
== STATUS_PENDING
)
1258 /* Wait on the file object */
1259 KeWaitForSingleObject(&FileObject
->Event
,
1264 Status
= FileObject
->FinalStatus
;
1267 /* Release the lock */
1268 IopUnlockFileObject(FileObject
);
1271 /* This Driver doesn't implement Security, so try to give it a default */
1272 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1274 /* Was this a query? */
1275 if (OperationCode
== QuerySecurityDescriptor
)
1277 /* Set a World Security Descriptor */
1278 Status
= SeSetWorldSecurityDescriptor(*SecurityInformation
,
1284 /* It wasn't a query, so just fake success */
1285 Status
= STATUS_SUCCESS
;
1288 else if (OperationCode
== QuerySecurityDescriptor
)
1290 /* Callers usually expect the normalized form */
1291 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1296 *BufferLength
= (ULONG
)IoStatusBlock
.Information
;
1298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1300 /* Get the exception code */
1301 Status
= _SEH2_GetExceptionCode();
1312 IopQueryNameFile(IN PVOID ObjectBody
,
1314 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1316 OUT PULONG ReturnLength
,
1317 IN KPROCESSOR_MODE PreviousMode
)
1319 POBJECT_NAME_INFORMATION LocalInfo
;
1320 PFILE_NAME_INFORMATION LocalFileInfo
;
1321 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1322 ULONG LocalReturnLength
, FileLength
;
1323 BOOLEAN LengthMismatch
= FALSE
;
1326 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1328 /* Validate length */
1329 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1331 /* Wrong length, fail */
1332 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
1333 return STATUS_INFO_LENGTH_MISMATCH
;
1336 /* Allocate Buffer */
1337 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1338 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1340 /* Query the name */
1341 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1344 &LocalReturnLength
);
1345 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1347 /* Free the buffer and fail */
1348 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1352 /* Copy the information */
1353 RtlCopyMemory(ObjectNameInfo
,
1355 (LocalReturnLength
> Length
) ?
1356 Length
: LocalReturnLength
);
1358 /* Set buffer pointer */
1359 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1360 ObjectNameInfo
->Name
.Buffer
= p
;
1362 /* Advance in buffer */
1363 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1365 /* Check if this already filled our buffer */
1366 if (LocalReturnLength
> Length
)
1368 /* Set the length mismatch to true, so that we can return
1369 * the proper buffer size to the caller later
1371 LengthMismatch
= TRUE
;
1373 /* Save the initial buffer length value */
1374 *ReturnLength
= LocalReturnLength
;
1377 /* Now get the file name buffer and check the length needed */
1378 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1379 FileLength
= Length
-
1381 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1383 /* Query the File name */
1384 Status
= IoQueryFileInformation(FileObject
,
1385 FileNameInformation
,
1386 LengthMismatch
? Length
: FileLength
,
1388 &LocalReturnLength
);
1389 if (NT_ERROR(Status
))
1391 /* Fail on errors only, allow warnings */
1392 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1396 /* If the provided buffer is too small, return the required size */
1399 /* Add the required length */
1400 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1402 /* Free the allocated buffer and return failure */
1403 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1404 return STATUS_BUFFER_OVERFLOW
;
1407 /* Now calculate the new lengths left */
1408 FileLength
= LocalReturnLength
-
1409 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1410 LocalReturnLength
= (ULONG
)((ULONG_PTR
)p
-
1411 (ULONG_PTR
)ObjectNameInfo
+
1412 LocalFileInfo
->FileNameLength
);
1414 /* Write the Name and null-terminate it */
1415 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1416 p
+= (FileLength
/ sizeof(WCHAR
));
1418 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1420 /* Return the length needed */
1421 *ReturnLength
= LocalReturnLength
;
1423 /* Setup the length and maximum length */
1424 FileLength
= (ULONG
)((ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
);
1425 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1426 sizeof(OBJECT_NAME_INFORMATION
);
1427 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1428 sizeof(UNICODE_NULL
);
1430 /* Free buffer and return */
1431 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1437 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1438 IN PVOID ObjectBody
,
1439 IN ACCESS_MASK GrantedAccess
,
1440 IN ULONG HandleCount
,
1441 IN ULONG SystemHandleCount
)
1443 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1446 PIO_STACK_LOCATION StackPtr
;
1448 PDEVICE_OBJECT DeviceObject
;
1450 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1452 /* If this isn't the last handle for the current process, quit */
1453 if (HandleCount
!= 1) return;
1455 /* Check if the file is locked and has more then one handle opened */
1456 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1458 DPRINT1("We need to unlock this file!\n");
1462 /* Make sure this is the last handle */
1463 if (SystemHandleCount
!= 1) return;
1465 /* Check if this is a direct open or not */
1466 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1468 /* Get the attached device */
1469 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1473 /* Get the FO's device */
1474 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1477 /* Set the handle created flag */
1478 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1480 /* Check if this is a sync FO and lock it */
1481 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1483 /* Clear and set up Events */
1484 KeClearEvent(&FileObject
->Event
);
1485 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1487 /* Allocate an IRP */
1488 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1492 Irp
->UserEvent
= &Event
;
1493 Irp
->UserIosb
= &Irp
->IoStatus
;
1494 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1495 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1496 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1497 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1499 /* Set up Stack Pointer Data */
1500 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1501 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1502 StackPtr
->FileObject
= FileObject
;
1505 IopQueueIrpToThread(Irp
);
1507 /* Update operation counts */
1508 IopUpdateOperationCount(IopOtherTransfer
);
1510 /* Call the FS Driver */
1511 Status
= IoCallDriver(DeviceObject
, Irp
);
1512 if (Status
== STATUS_PENDING
)
1514 /* Wait for completion */
1515 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1518 /* Unqueue the IRP */
1519 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1520 IopUnQueueIrpFromThread(Irp
);
1521 KeLowerIrql(OldIrql
);
1526 /* Release the lock if we were holding it */
1527 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1532 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1533 IN FILE_INFORMATION_CLASS FileInformationClass
,
1534 IN ULONG FileInformationSize
,
1535 OUT PVOID FileInformation
)
1538 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1539 DUMMY_FILE_OBJECT LocalFileObject
;
1540 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1542 OPEN_PACKET OpenPacket
;
1545 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
1547 /* Check if the caller was user mode */
1548 if (AccessMode
!= KernelMode
)
1550 /* Protect probe in SEH */
1553 /* Probe the buffer */
1554 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
1556 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1558 /* Return the exception code */
1559 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1564 /* Check if this is a basic or full request */
1565 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
1567 /* Setup the Open Packet */
1568 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
1569 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
1570 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
1571 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
1572 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
1573 OpenPacket
.Disposition
= FILE_OPEN
;
1574 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
1575 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
1576 (AccessMode
!= KernelMode
) ?
1577 &NetworkOpenInfo
: FileInformation
;
1578 OpenPacket
.QueryOnly
= TRUE
;
1579 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
1580 OpenPacket
.LocalFileObject
= &LocalFileObject
;
1582 /* Update the operation count */
1583 IopUpdateOperationCount(IopOtherTransfer
);
1586 * Attempt opening the file. This will call the I/O Parse Routine for
1587 * the File Object (IopParseDevice) which will use the dummy file obejct
1588 * send the IRP to its device object. Note that we have two statuses
1589 * to worry about: the Object Manager's status (in Status) and the I/O
1590 * status, which is in the Open Packet's Final Status, and determined
1591 * by the Parse Check member.
1593 Status
= ObOpenObjectByName(ObjectAttributes
,
1597 FILE_READ_ATTRIBUTES
,
1600 if (OpenPacket
.ParseCheck
!= TRUE
)
1607 /* Use the Io status */
1608 Status
= OpenPacket
.FinalStatus
;
1611 /* Check if we were succesful and this was user mode and a full query */
1612 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
1614 /* Enter SEH for copy */
1617 /* Copy the buffer back */
1618 RtlCopyMemory(FileInformation
,
1620 FileInformationSize
);
1622 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1624 /* Get exception code */
1625 Status
= _SEH2_GetExceptionCode();
1636 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject
)
1638 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1641 /* FIXME: return NULL for the moment ~ */
1650 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject
,
1651 IN PVOID FilterContext
,
1654 if (!(FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
))
1656 return STATUS_INVALID_PARAMETER
;
1661 return STATUS_NOT_IMPLEMENTED
;
1664 /* FUNCTIONS *****************************************************************/
1671 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
1673 IN BOOLEAN SetOperation
)
1676 return STATUS_NOT_IMPLEMENTED
;
1684 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
1685 IN ULONG QuotaLength
,
1686 OUT PULONG ErrorOffset
)
1689 return STATUS_NOT_IMPLEMENTED
;
1697 IoCreateFile(OUT PHANDLE FileHandle
,
1698 IN ACCESS_MASK DesiredAccess
,
1699 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1700 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1701 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1702 IN ULONG FileAttributes
,
1703 IN ULONG ShareAccess
,
1704 IN ULONG Disposition
,
1705 IN ULONG CreateOptions
,
1706 IN PVOID EaBuffer OPTIONAL
,
1708 IN CREATE_FILE_TYPE CreateFileType
,
1709 IN PVOID ExtraCreateParameters OPTIONAL
,
1712 KPROCESSOR_MODE AccessMode
;
1713 HANDLE LocalHandle
= 0;
1714 LARGE_INTEGER SafeAllocationSize
;
1715 NTSTATUS Status
= STATUS_SUCCESS
;
1716 PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters
;
1717 POPEN_PACKET OpenPacket
;
1718 ULONG EaErrorOffset
;
1720 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
1723 /* Check if we have no parameter checking to do */
1724 if (Options
& IO_NO_PARAMETER_CHECKING
)
1726 /* Then force kernel-mode access to avoid checks */
1727 AccessMode
= KernelMode
;
1731 /* Otherwise, use the actual mode */
1732 AccessMode
= ExGetPreviousMode();
1735 /* Check if we need to do parameter checking */
1736 if ((AccessMode
!= KernelMode
) || (Options
& IO_CHECK_CREATE_PARAMETERS
))
1738 /* Validate parameters */
1739 if (FileAttributes
& ~FILE_ATTRIBUTE_VALID_FLAGS
)
1741 DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n");
1742 return STATUS_INVALID_PARAMETER
;
1745 if (ShareAccess
& ~FILE_SHARE_VALID_FLAGS
)
1747 DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n");
1748 return STATUS_INVALID_PARAMETER
;
1751 if (Disposition
> FILE_MAXIMUM_DISPOSITION
)
1753 DPRINT1("File Create 'Disposition' Parameter is out of range!\n");
1754 return STATUS_INVALID_PARAMETER
;
1757 if (CreateOptions
& ~FILE_VALID_OPTION_FLAGS
)
1759 DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n");
1760 return STATUS_INVALID_PARAMETER
;
1763 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
)) &&
1764 (!(DesiredAccess
& SYNCHRONIZE
)))
1766 DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n");
1767 return STATUS_INVALID_PARAMETER
;
1770 if ((CreateOptions
& FILE_DELETE_ON_CLOSE
) && (!(DesiredAccess
& DELETE
)))
1772 DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n");
1773 return STATUS_INVALID_PARAMETER
;
1776 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
)) ==
1777 (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
))
1779 DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n");
1780 return STATUS_INVALID_PARAMETER
;
1783 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
1784 (CreateOptions
& ~(FILE_DIRECTORY_FILE
|
1785 FILE_SYNCHRONOUS_IO_ALERT
|
1786 FILE_SYNCHRONOUS_IO_NONALERT
|
1787 FILE_WRITE_THROUGH
|
1788 FILE_COMPLETE_IF_OPLOCKED
|
1789 FILE_OPEN_FOR_BACKUP_INTENT
|
1790 FILE_DELETE_ON_CLOSE
|
1791 FILE_OPEN_FOR_FREE_SPACE_QUERY
|
1792 FILE_OPEN_BY_FILE_ID
|
1793 FILE_NO_COMPRESSION
|
1794 FILE_OPEN_REPARSE_POINT
)))
1796 DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n");
1797 return STATUS_INVALID_PARAMETER
;
1800 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
1801 (Disposition
!= FILE_CREATE
) && (Disposition
!= FILE_OPEN
) && (Disposition
!= FILE_OPEN_IF
))
1803 DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n");
1804 return STATUS_INVALID_PARAMETER
;
1807 if ((CreateOptions
& FILE_COMPLETE_IF_OPLOCKED
) && (CreateOptions
& FILE_RESERVE_OPFILTER
))
1809 DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n");
1810 return STATUS_INVALID_PARAMETER
;
1813 if ((CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
) && (DesiredAccess
& FILE_APPEND_DATA
))
1815 DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n");
1816 return STATUS_INVALID_PARAMETER
;
1819 /* Now check if this is a named pipe */
1820 if (CreateFileType
== CreateFileTypeNamedPipe
)
1822 /* Make sure we have extra parameters */
1823 if (!ExtraCreateParameters
)
1825 return STATUS_INVALID_PARAMETER
;
1828 /* Get the parameters and validate them */
1829 NamedPipeCreateParameters
= ExtraCreateParameters
;
1830 if ((NamedPipeCreateParameters
->NamedPipeType
> FILE_PIPE_MESSAGE_TYPE
) ||
1831 (NamedPipeCreateParameters
->ReadMode
> FILE_PIPE_MESSAGE_MODE
) ||
1832 (NamedPipeCreateParameters
->CompletionMode
> FILE_PIPE_COMPLETE_OPERATION
) ||
1833 (ShareAccess
& FILE_SHARE_DELETE
) ||
1834 ((Disposition
< FILE_OPEN
) || (Disposition
> FILE_OPEN_IF
)) ||
1835 (CreateOptions
& ~FILE_VALID_PIPE_OPTION_FLAGS
))
1837 /* Invalid named pipe create */
1838 return STATUS_INVALID_PARAMETER
;
1841 else if (CreateFileType
== CreateFileTypeMailslot
)
1843 /* Make sure we have extra parameters */
1844 if (!ExtraCreateParameters
)
1846 return STATUS_INVALID_PARAMETER
;
1849 /* Get the parameters and validate them */
1850 if ((ShareAccess
& FILE_SHARE_DELETE
) ||
1851 !(ShareAccess
& ~FILE_SHARE_WRITE
) ||
1852 (Disposition
!= FILE_CREATE
) ||
1853 (CreateOptions
& ~FILE_VALID_MAILSLOT_OPTION_FLAGS
))
1855 /* Invalid mailslot create */
1856 return STATUS_INVALID_PARAMETER
;
1861 /* Allocate the open packet */
1862 OpenPacket
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*OpenPacket
), 'pOoI');
1863 if (!OpenPacket
) return STATUS_INSUFFICIENT_RESOURCES
;
1864 RtlZeroMemory(OpenPacket
, sizeof(*OpenPacket
));
1866 /* Check if the call came from user mode */
1867 if (AccessMode
!= KernelMode
)
1871 /* Probe the output parameters */
1872 ProbeForWriteHandle(FileHandle
);
1873 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1875 /* Probe the allocation size if one was passed in */
1878 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
1882 SafeAllocationSize
.QuadPart
= 0;
1885 /* Make sure it's valid */
1886 if (SafeAllocationSize
.QuadPart
< 0)
1888 RtlRaiseStatus(STATUS_INVALID_PARAMETER
);
1891 /* Check if EA was passed in */
1892 if ((EaBuffer
) && (EaLength
))
1895 ProbeForRead(EaBuffer
, EaLength
, sizeof(ULONG
));
1897 /* And marshall it */
1898 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1901 OpenPacket
->EaLength
= EaLength
;
1902 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
1904 /* Validate the buffer */
1905 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
1908 if (!NT_SUCCESS(Status
))
1910 /* Undo everything if it's invalid */
1911 DPRINT1("Invalid EA buffer\n");
1912 IoStatusBlock
->Status
= Status
;
1913 IoStatusBlock
->Information
= EaErrorOffset
;
1914 RtlRaiseStatus(Status
);
1918 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1920 /* Return the exception code */
1921 if (OpenPacket
->EaBuffer
!= NULL
) ExFreePool(OpenPacket
->EaBuffer
);
1922 ExFreePool(OpenPacket
);
1923 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1929 /* Check if this is a device attach */
1930 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
1932 /* Set the flag properly */
1933 Options
|= IO_ATTACH_DEVICE
;
1934 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
1937 /* Check if we have allocation size */
1941 SafeAllocationSize
= *AllocationSize
;
1945 /* Otherwise, no size */
1946 SafeAllocationSize
.QuadPart
= 0;
1949 /* Check if we have an EA packet */
1950 if ((EaBuffer
) && (EaLength
))
1952 /* Allocate the kernel copy */
1953 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1956 if (!OpenPacket
->EaBuffer
)
1958 ExFreePool(OpenPacket
);
1959 return STATUS_INSUFFICIENT_RESOURCES
;
1963 OpenPacket
->EaLength
= EaLength
;
1964 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
1966 /* Validate the buffer */
1967 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
1970 if (!NT_SUCCESS(Status
))
1972 /* Undo everything if it's invalid */
1973 DPRINT1("Invalid EA buffer\n");
1974 ExFreePool(OpenPacket
->EaBuffer
);
1975 IoStatusBlock
->Status
= Status
;
1976 IoStatusBlock
->Information
= EaErrorOffset
;
1977 ExFreePool(OpenPacket
);
1983 /* Setup the Open Packet */
1984 OpenPacket
->Type
= IO_TYPE_OPEN_PACKET
;
1985 OpenPacket
->Size
= sizeof(*OpenPacket
);
1986 OpenPacket
->AllocationSize
= SafeAllocationSize
;
1987 OpenPacket
->CreateOptions
= CreateOptions
;
1988 OpenPacket
->FileAttributes
= (USHORT
)FileAttributes
;
1989 OpenPacket
->ShareAccess
= (USHORT
)ShareAccess
;
1990 OpenPacket
->Options
= Options
;
1991 OpenPacket
->Disposition
= Disposition
;
1992 OpenPacket
->CreateFileType
= CreateFileType
;
1993 OpenPacket
->ExtraCreateParameters
= ExtraCreateParameters
;
1995 /* Update the operation count */
1996 IopUpdateOperationCount(IopOtherTransfer
);
1999 * Attempt opening the file. This will call the I/O Parse Routine for
2000 * the File Object (IopParseDevice) which will create the object and
2001 * send the IRP to its device object. Note that we have two statuses
2002 * to worry about: the Object Manager's status (in Status) and the I/O
2003 * status, which is in the Open Packet's Final Status, and determined
2004 * by the Parse Check member.
2006 Status
= ObOpenObjectByName(ObjectAttributes
,
2014 /* Free the EA Buffer */
2015 if (OpenPacket
->EaBuffer
) ExFreePool(OpenPacket
->EaBuffer
);
2017 /* Now check for Ob or Io failure */
2018 if (!(NT_SUCCESS(Status
)) || (OpenPacket
->ParseCheck
!= TRUE
))
2020 /* Check if Ob thinks well went well */
2021 if (NT_SUCCESS(Status
))
2024 * Tell it otherwise. Because we didn't use an ObjectType,
2025 * it incorrectly returned us a handle to God knows what.
2027 ZwClose(LocalHandle
);
2028 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
2031 /* Now check the Io status */
2032 if (!NT_SUCCESS(OpenPacket
->FinalStatus
))
2034 /* Use this status instead of Ob's */
2035 Status
= OpenPacket
->FinalStatus
;
2037 /* Check if it was only a warning */
2038 if (NT_WARNING(Status
))
2040 /* Protect write with SEH */
2043 /* In this case, we copy the I/O Status back */
2044 IoStatusBlock
->Information
= OpenPacket
->Information
;
2045 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2047 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2049 /* Get exception code */
2050 Status
= _SEH2_GetExceptionCode();
2055 else if ((OpenPacket
->FileObject
) && (OpenPacket
->ParseCheck
!= 1))
2058 * This can happen in the very bizarre case where the parse routine
2059 * actually executed more then once (due to a reparse) and ended
2060 * up failing after already having created the File Object.
2062 if (OpenPacket
->FileObject
->FileName
.Length
)
2064 /* It had a name, free it */
2065 ExFreePoolWithTag(OpenPacket
->FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
2068 /* Clear the device object to invalidate the FO, and dereference */
2069 OpenPacket
->FileObject
->DeviceObject
= NULL
;
2070 ObDereferenceObject(OpenPacket
->FileObject
);
2075 /* We reached success and have a valid file handle */
2076 OpenPacket
->FileObject
->Flags
|= FO_HANDLE_CREATED
;
2077 ASSERT(OpenPacket
->FileObject
->Type
== IO_TYPE_FILE
);
2079 /* Enter SEH for write back */
2082 /* Write back the handle and I/O Status */
2083 *FileHandle
= LocalHandle
;
2084 IoStatusBlock
->Information
= OpenPacket
->Information
;
2085 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2087 /* Get the Io status */
2088 Status
= OpenPacket
->FinalStatus
;
2090 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2092 /* Get the exception status */
2093 Status
= _SEH2_GetExceptionCode();
2098 /* Check if we were 100% successful */
2099 if ((OpenPacket
->ParseCheck
== TRUE
) && (OpenPacket
->FileObject
))
2101 /* Dereference the File Object */
2102 ObDereferenceObject(OpenPacket
->FileObject
);
2106 ExFreePool(OpenPacket
);
2115 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
2116 IN ACCESS_MASK DesiredAccess
,
2117 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2118 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2119 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2120 IN ULONG FileAttributes
,
2121 IN ULONG ShareAccess
,
2122 IN ULONG Disposition
,
2123 IN ULONG CreateOptions
,
2124 IN PVOID EaBuffer OPTIONAL
,
2126 IN CREATE_FILE_TYPE CreateFileType
,
2127 IN PVOID ExtraCreateParameters OPTIONAL
,
2129 IN PVOID DeviceObject
)
2132 return STATUS_NOT_IMPLEMENTED
;
2140 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
2141 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
2142 OUT PHANDLE FileObjectHandle OPTIONAL
)
2144 PFILE_OBJECT CreatedFileObject
;
2147 OBJECT_ATTRIBUTES ObjectAttributes
;
2149 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2151 /* Choose Device Object */
2152 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2154 /* Reference the device object and initialize attributes */
2155 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2156 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2158 /* Create the File Object */
2159 Status
= ObCreateObject(KernelMode
,
2164 sizeof(FILE_OBJECT
),
2165 sizeof(FILE_OBJECT
),
2167 (PVOID
*)&CreatedFileObject
);
2168 if (!NT_SUCCESS(Status
))
2171 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2172 ExRaiseStatus(Status
);
2175 /* Set File Object Data */
2176 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2177 CreatedFileObject
->DeviceObject
= DeviceObject
;
2178 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2179 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2180 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2182 /* Initialize the wait event */
2183 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2185 /* Insert it to create a handle for it */
2186 Status
= ObInsertObject(CreatedFileObject
,
2190 (PVOID
*)&CreatedFileObject
,
2192 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2194 /* Set the handle created flag */
2195 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2196 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2198 /* Check if we have a VPB */
2199 if (DeviceObject
->Vpb
)
2202 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2205 /* Check if the caller wants the handle */
2206 if (FileObjectHandle
)
2209 *FileObjectHandle
= FileHandle
;
2210 ObDereferenceObject(CreatedFileObject
);
2214 /* Otherwise, close it */
2215 ObCloseHandle(FileHandle
, KernelMode
);
2218 /* Return the file object */
2219 return CreatedFileObject
;
2227 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2228 IN PDEVICE_OBJECT DeviceObject
)
2230 /* Call the newer function */
2231 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2239 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2240 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2242 PFILE_OBJECT CreatedFileObject
;
2244 OBJECT_ATTRIBUTES ObjectAttributes
;
2246 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2248 /* Choose Device Object */
2249 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2251 /* Reference the device object and initialize attributes */
2252 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2253 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2255 /* Create the File Object */
2256 Status
= ObCreateObject(KernelMode
,
2261 sizeof(FILE_OBJECT
),
2262 sizeof(FILE_OBJECT
),
2264 (PVOID
*)&CreatedFileObject
);
2265 if (!NT_SUCCESS(Status
))
2268 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2269 ExRaiseStatus(Status
);
2272 /* Set File Object Data */
2273 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2274 CreatedFileObject
->DeviceObject
= DeviceObject
;
2275 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2276 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2277 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2279 /* Initialize the wait event */
2280 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2282 /* Destroy create information */
2283 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2285 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2287 /* Set the handle created flag */
2288 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2289 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2291 /* Check if we have a VPB */
2292 if (DeviceObject
->Vpb
)
2295 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2298 /* Return the file object */
2299 return CreatedFileObject
;
2307 IoGetFileObjectGenericMapping(VOID
)
2309 /* Return the mapping */
2310 return &IopFileMapping
;
2318 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2320 /* Return the flag status */
2321 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2329 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2330 IN ACCESS_MASK DesiredAccess
,
2331 IN ULONG OpenOptions
,
2332 OUT PIO_STATUS_BLOCK IoStatus
,
2333 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2336 DUMMY_FILE_OBJECT LocalFileObject
;
2338 OPEN_PACKET OpenPacket
;
2340 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2342 /* Setup the Open Packet */
2343 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2344 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2345 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2346 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2347 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2348 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2349 OpenPacket
.Disposition
= FILE_OPEN
;
2350 OpenPacket
.NetworkInformation
= Buffer
;
2351 OpenPacket
.QueryOnly
= TRUE
;
2352 OpenPacket
.FullAttributes
= TRUE
;
2353 OpenPacket
.LocalFileObject
= &LocalFileObject
;
2356 * Attempt opening the file. This will call the I/O Parse Routine for
2357 * the File Object (IopParseDevice) which will use the dummy file obejct
2358 * send the IRP to its device object. Note that we have two statuses
2359 * to worry about: the Object Manager's status (in Status) and the I/O
2360 * status, which is in the Open Packet's Final Status, and determined
2361 * by the Parse Check member.
2363 Status
= ObOpenObjectByName(ObjectAttributes
,
2370 if (OpenPacket
.ParseCheck
!= TRUE
)
2373 IoStatus
->Status
= Status
;
2377 /* Use the Io status */
2378 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2379 IoStatus
->Information
= OpenPacket
.Information
;
2382 /* Return success */
2391 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2392 OUT PSHARE_ACCESS ShareAccess
)
2396 /* Check if the file has an extension */
2397 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2399 /* Check if caller specified to ignore access checks */
2400 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2402 /* Don't update share access */
2407 /* Otherwise, check if there's any access present */
2408 if ((FileObject
->ReadAccess
) ||
2409 (FileObject
->WriteAccess
) ||
2410 (FileObject
->DeleteAccess
))
2412 /* Increase the open count */
2413 ShareAccess
->OpenCount
++;
2415 /* Add new share access */
2416 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2417 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2418 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2419 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2420 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2421 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2430 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2431 IN ULONG DesiredShareAccess
,
2432 IN PFILE_OBJECT FileObject
,
2433 IN PSHARE_ACCESS ShareAccess
,
2437 BOOLEAN WriteAccess
;
2438 BOOLEAN DeleteAccess
;
2440 BOOLEAN SharedWrite
;
2441 BOOLEAN SharedDelete
;
2444 /* Get access masks */
2445 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2446 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2447 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2449 /* Set them in the file object */
2450 FileObject
->ReadAccess
= ReadAccess
;
2451 FileObject
->WriteAccess
= WriteAccess
;
2452 FileObject
->DeleteAccess
= DeleteAccess
;
2454 /* Check if the file has an extension */
2455 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2457 /* Check if caller specified to ignore access checks */
2458 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2460 /* Don't check share access */
2461 return STATUS_SUCCESS
;
2465 /* Check if we have any access */
2466 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2468 /* Get shared access masks */
2469 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2470 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2471 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2474 FileObject
->SharedRead
= SharedRead
;
2475 FileObject
->SharedWrite
= SharedWrite
;
2476 FileObject
->SharedDelete
= SharedDelete
;
2478 /* Check if the shared access is violated */
2480 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2482 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2484 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2485 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2486 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2487 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2489 /* Sharing violation, fail */
2490 return STATUS_SHARING_VIOLATION
;
2493 /* It's not, check if caller wants us to update it */
2496 /* Increase open count */
2497 ShareAccess
->OpenCount
++;
2499 /* Update shared access */
2500 ShareAccess
->Readers
+= ReadAccess
;
2501 ShareAccess
->Writers
+= WriteAccess
;
2502 ShareAccess
->Deleters
+= DeleteAccess
;
2503 ShareAccess
->SharedRead
+= SharedRead
;
2504 ShareAccess
->SharedWrite
+= SharedWrite
;
2505 ShareAccess
->SharedDelete
+= SharedDelete
;
2509 /* Validation successful */
2510 return STATUS_SUCCESS
;
2518 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2519 IN PSHARE_ACCESS ShareAccess
)
2523 /* Check if the file has an extension */
2524 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2526 /* Check if caller specified to ignore access checks */
2527 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2529 /* Don't update share access */
2534 /* Otherwise, check if there's any access present */
2535 if ((FileObject
->ReadAccess
) ||
2536 (FileObject
->WriteAccess
) ||
2537 (FileObject
->DeleteAccess
))
2539 /* Decrement the open count */
2540 ShareAccess
->OpenCount
--;
2542 /* Remove share access */
2543 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
2544 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
2545 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
2546 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
2547 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
2548 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
2557 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
2558 IN ULONG DesiredShareAccess
,
2559 IN PFILE_OBJECT FileObject
,
2560 OUT PSHARE_ACCESS ShareAccess
)
2563 BOOLEAN WriteAccess
;
2564 BOOLEAN DeleteAccess
;
2566 BOOLEAN SharedWrite
;
2567 BOOLEAN SharedDelete
;
2568 BOOLEAN Update
= TRUE
;
2571 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2572 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2573 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2575 /* Check if the file has an extension */
2576 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2578 /* Check if caller specified to ignore access checks */
2579 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2581 /* Don't update share access */
2586 /* Update basic access */
2587 FileObject
->ReadAccess
= ReadAccess
;
2588 FileObject
->WriteAccess
= WriteAccess
;
2589 FileObject
->DeleteAccess
= DeleteAccess
;
2591 /* Check if we have no access as all */
2592 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
2594 /* Check if we need to update the structure */
2595 if (!Update
) return;
2597 /* Otherwise, clear data */
2598 ShareAccess
->OpenCount
= 0;
2599 ShareAccess
->Readers
= 0;
2600 ShareAccess
->Writers
= 0;
2601 ShareAccess
->Deleters
= 0;
2602 ShareAccess
->SharedRead
= 0;
2603 ShareAccess
->SharedWrite
= 0;
2604 ShareAccess
->SharedDelete
= 0;
2608 /* Calculate shared access */
2609 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2610 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2611 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2613 /* Set it in the FO */
2614 FileObject
->SharedRead
= SharedRead
;
2615 FileObject
->SharedWrite
= SharedWrite
;
2616 FileObject
->SharedDelete
= SharedDelete
;
2618 /* Check if we need to update the structure */
2619 if (!Update
) return;
2621 /* Otherwise, set data */
2622 ShareAccess
->OpenCount
= 1;
2623 ShareAccess
->Readers
= ReadAccess
;
2624 ShareAccess
->Writers
= WriteAccess
;
2625 ShareAccess
->Deleters
= DeleteAccess
;
2626 ShareAccess
->SharedRead
= SharedRead
;
2627 ShareAccess
->SharedWrite
= SharedWrite
;
2628 ShareAccess
->SharedDelete
= SharedDelete
;
2637 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
2638 IN PFILE_OBJECT FileObject
)
2644 PIO_STACK_LOCATION Stack
;
2646 /* Check if handles were already created for the
2647 * open file. If so, that's over.
2649 if (FileObject
->Flags
& FO_HANDLE_CREATED
)
2650 KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN
,
2651 (ULONG_PTR
)FileObject
,
2652 (ULONG_PTR
)DeviceObject
, 0, 0);
2654 /* Reset the events */
2655 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2656 KeClearEvent(&FileObject
->Event
);
2658 /* Allocate the IRP we'll use */
2659 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
2660 /* Properly set it */
2661 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2662 Irp
->UserEvent
= &Event
;
2663 Irp
->UserIosb
= &Irp
->IoStatus
;
2664 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2665 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2666 Irp
->RequestorMode
= KernelMode
;
2667 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
2669 Stack
= IoGetNextIrpStackLocation(Irp
);
2670 Stack
->MajorFunction
= IRP_MJ_CLEANUP
;
2671 Stack
->FileObject
= FileObject
;
2673 /* Put on top of IRPs list of the thread */
2674 IopQueueIrpToThread(Irp
);
2676 /* Call the driver */
2677 Status
= IoCallDriver(DeviceObject
, Irp
);
2678 if (Status
== STATUS_PENDING
)
2680 KeWaitForSingleObject(&Event
, UserRequest
,
2681 KernelMode
, FALSE
, NULL
);
2684 /* Remove from IRPs list */
2685 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2686 IopUnQueueIrpFromThread(Irp
);
2687 KeLowerIrql(OldIrql
);
2692 /* Clear the event */
2693 KeClearEvent(&FileObject
->Event
);
2694 /* And finally, mark the open operation as canceled */
2695 FileObject
->Flags
|= FO_FILE_OPEN_CANCELLED
;
2703 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
2704 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
2707 return STATUS_NOT_IMPLEMENTED
;
2715 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
2718 NTSTATUS Status
= STATUS_SUCCESS
;
2721 /* Get the flag status */
2722 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2724 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
2725 if (Remote
&& !FlagSet
)
2728 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
2730 else if (!Remote
&& FlagSet
)
2732 /* Remove the flag */
2733 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
2738 Status
= STATUS_INVALID_PARAMETER_MIX
;
2750 NtCreateFile(PHANDLE FileHandle
,
2751 ACCESS_MASK DesiredAccess
,
2752 POBJECT_ATTRIBUTES ObjectAttributes
,
2753 PIO_STATUS_BLOCK IoStatusBlock
,
2754 PLARGE_INTEGER AllocateSize
,
2755 ULONG FileAttributes
,
2757 ULONG CreateDisposition
,
2758 ULONG CreateOptions
,
2762 /* Call the I/O Function */
2763 return IoCreateFile(FileHandle
,
2781 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
2782 IN ACCESS_MASK DesiredAccess
,
2783 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2784 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2785 IN ULONG CreateOptions
,
2786 IN ULONG MailslotQuota
,
2787 IN ULONG MaxMessageSize
,
2788 IN PLARGE_INTEGER TimeOut
)
2790 MAILSLOT_CREATE_PARAMETERS Buffer
;
2793 /* Check for Timeout */
2796 /* check if the call came from user mode */
2797 if (KeGetPreviousMode() != KernelMode
)
2799 /* Enter SEH for Probe */
2802 /* Probe the timeout */
2803 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
2805 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2807 /* Return the exception code */
2808 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2814 /* Otherwise, capture directly */
2815 Buffer
.ReadTimeout
= *TimeOut
;
2818 /* Set the correct setting */
2819 Buffer
.TimeoutSpecified
= TRUE
;
2823 /* Tell the FSD we don't have a timeout */
2824 Buffer
.TimeoutSpecified
= FALSE
;
2828 Buffer
.MailslotQuota
= MailslotQuota
;
2829 Buffer
.MaximumMessageSize
= MaxMessageSize
;
2832 return IoCreateFile(FileHandle
,
2838 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2843 CreateFileTypeMailslot
,
2850 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
2851 IN ACCESS_MASK DesiredAccess
,
2852 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2853 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2854 IN ULONG ShareAccess
,
2855 IN ULONG CreateDisposition
,
2856 IN ULONG CreateOptions
,
2857 IN ULONG NamedPipeType
,
2859 IN ULONG CompletionMode
,
2860 IN ULONG MaximumInstances
,
2861 IN ULONG InboundQuota
,
2862 IN ULONG OutboundQuota
,
2863 IN PLARGE_INTEGER DefaultTimeout
)
2865 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
2868 /* Check for Timeout */
2871 /* check if the call came from user mode */
2872 if (KeGetPreviousMode() != KernelMode
)
2874 /* Enter SEH for Probe */
2877 /* Probe the timeout */
2878 Buffer
.DefaultTimeout
=
2879 ProbeForReadLargeInteger(DefaultTimeout
);
2881 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2883 /* Return the exception code */
2884 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2890 /* Otherwise, capture directly */
2891 Buffer
.DefaultTimeout
= *DefaultTimeout
;
2894 /* Set the correct setting */
2895 Buffer
.TimeoutSpecified
= TRUE
;
2899 /* Tell the FSD we don't have a timeout */
2900 Buffer
.TimeoutSpecified
= FALSE
;
2904 Buffer
.NamedPipeType
= NamedPipeType
;
2905 Buffer
.ReadMode
= ReadMode
;
2906 Buffer
.CompletionMode
= CompletionMode
;
2907 Buffer
.MaximumInstances
= MaximumInstances
;
2908 Buffer
.InboundQuota
= InboundQuota
;
2909 Buffer
.OutboundQuota
= OutboundQuota
;
2912 return IoCreateFile(FileHandle
,
2923 CreateFileTypeNamedPipe
,
2930 NtFlushWriteBuffer(VOID
)
2934 /* Call the kernel */
2935 KeFlushWriteBuffer();
2936 return STATUS_SUCCESS
;
2944 NtOpenFile(OUT PHANDLE FileHandle
,
2945 IN ACCESS_MASK DesiredAccess
,
2946 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2947 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2948 IN ULONG ShareAccess
,
2949 IN ULONG OpenOptions
)
2951 /* Call the I/O Function */
2952 return IoCreateFile(FileHandle
,
2970 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2971 OUT PFILE_BASIC_INFORMATION FileInformation
)
2973 /* Call the internal helper API */
2974 return IopQueryAttributesFile(ObjectAttributes
,
2975 FileBasicInformation
,
2976 sizeof(FILE_BASIC_INFORMATION
),
2982 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2983 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2985 /* Call the internal helper API */
2986 return IopQueryAttributesFile(ObjectAttributes
,
2987 FileNetworkOpenInformation
,
2988 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2993 * @name NtCancelIoFile
2995 * Cancel all pending I/O operations in the current thread for specified
2999 * Handle to file object to cancel requests for. No specific
3000 * access rights are needed.
3001 * @param IoStatusBlock
3002 * Pointer to status block which is filled with final completition
3003 * status on successful return.
3011 NtCancelIoFile(IN HANDLE FileHandle
,
3012 OUT PIO_STATUS_BLOCK IoStatusBlock
)
3014 PFILE_OBJECT FileObject
;
3018 BOOLEAN OurIrpsInList
= FALSE
;
3019 LARGE_INTEGER Interval
;
3020 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3022 PLIST_ENTRY ListHead
, NextEntry
;
3024 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3026 /* Check the previous mode */
3027 if (PreviousMode
!= KernelMode
)
3029 /* Enter SEH for probing */
3032 /* Probe the I/O Status Block */
3033 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3035 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3037 /* Return the exception code */
3038 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3043 /* Reference the file object */
3044 Status
= ObReferenceObjectByHandle(FileHandle
,
3048 (PVOID
*)&FileObject
,
3050 if (!NT_SUCCESS(Status
)) return Status
;
3052 /* IRP cancellations are synchronized at APC_LEVEL. */
3053 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3055 /* Get the current thread */
3056 Thread
= PsGetCurrentThread();
3058 /* Update the operation counts */
3059 IopUpdateOperationCount(IopOtherTransfer
);
3062 ListHead
= &Thread
->IrpList
;
3063 NextEntry
= ListHead
->Flink
;
3064 while (ListHead
!= NextEntry
)
3066 /* Get the IRP and check if the File Object matches */
3067 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3068 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3070 /* Cancel this IRP and keep looping */
3072 OurIrpsInList
= TRUE
;
3075 /* Go to the next entry */
3076 NextEntry
= NextEntry
->Flink
;
3079 /* Lower the IRQL */
3080 KeLowerIrql(OldIrql
);
3082 /* Check if we had found an IRP */
3085 /* Setup a 10ms wait */
3086 Interval
.QuadPart
= -100000;
3089 while (OurIrpsInList
)
3092 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
3093 OurIrpsInList
= FALSE
;
3096 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3098 /* Now loop the list again */
3099 NextEntry
= ListHead
->Flink
;
3100 while (NextEntry
!= ListHead
)
3102 /* Get the IRP and check if the File Object matches */
3103 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3104 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3107 OurIrpsInList
= TRUE
;
3111 /* Go to the next entry */
3112 NextEntry
= NextEntry
->Flink
;
3115 /* Lower the IRQL */
3116 KeLowerIrql(OldIrql
);
3120 /* Enter SEH for writing back the I/O Status */
3124 IoStatusBlock
->Status
= STATUS_SUCCESS
;
3125 IoStatusBlock
->Information
= 0;
3127 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3129 /* Ignore exception */
3133 /* Dereference the file object and return success */
3134 ObDereferenceObject(FileObject
);
3135 return STATUS_SUCCESS
;
3143 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
3146 DUMMY_FILE_OBJECT LocalFileObject
;
3148 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
3149 OPEN_PACKET OpenPacket
;
3151 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
3153 /* Setup the Open Packet */
3154 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
3155 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
3156 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
3157 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
3158 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
3161 OpenPacket
.Disposition
= FILE_OPEN
;
3162 OpenPacket
.DeleteOnly
= TRUE
;
3163 OpenPacket
.LocalFileObject
= &LocalFileObject
;
3165 /* Update the operation counts */
3166 IopUpdateOperationCount(IopOtherTransfer
);
3169 * Attempt opening the file. This will call the I/O Parse Routine for
3170 * the File Object (IopParseDevice) which will use the dummy file obejct
3171 * send the IRP to its device object. Note that we have two statuses
3172 * to worry about: the Object Manager's status (in Status) and the I/O
3173 * status, which is in the Open Packet's Final Status, and determined
3174 * by the Parse Check member.
3176 Status
= ObOpenObjectByName(ObjectAttributes
,
3183 if (OpenPacket
.ParseCheck
!= TRUE
) return Status
;
3185 /* Retrn the Io status */
3186 return OpenPacket
.FinalStatus
;