2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/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 extern ERESOURCE IopSecurityResource
;
20 /* PRIVATE FUNCTIONS *********************************************************/
24 IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState
,
25 IN OUT PULONG CreateOptions
,
26 IN KPROCESSOR_MODE PreviousMode
,
29 ACCESS_MASK DesiredAccess
, ReadAccess
, WriteAccess
;
30 PRIVILEGE_SET Privileges
;
31 BOOLEAN AccessGranted
, HaveBackupPriv
= FALSE
, CheckRestore
= FALSE
;
34 /* Don't do anything if privileges were checked already */
35 if (AccessState
->Flags
& SE_BACKUP_PRIVILEGES_CHECKED
) return;
37 /* Check if the file was actually opened for backup purposes */
38 if (*CreateOptions
& FILE_OPEN_FOR_BACKUP_INTENT
)
40 /* Set the check flag since were doing it now */
41 AccessState
->Flags
|= SE_BACKUP_PRIVILEGES_CHECKED
;
43 /* Set the access masks required */
44 ReadAccess
= READ_CONTROL
|
45 ACCESS_SYSTEM_SECURITY
|
48 WriteAccess
= WRITE_DAC
|
50 ACCESS_SYSTEM_SECURITY
|
53 FILE_ADD_SUBDIRECTORY
|
55 DesiredAccess
= AccessState
->RemainingDesiredAccess
;
57 /* Check if desired access was the maximum */
58 if (DesiredAccess
& MAXIMUM_ALLOWED
)
60 /* Then add all the access masks required */
61 DesiredAccess
|= (ReadAccess
| WriteAccess
);
64 /* Check if the file already exists */
65 if (Disposition
& FILE_OPEN
)
67 /* Check if desired access has the read mask */
68 if (ReadAccess
& DesiredAccess
)
70 /* Setup the privilege check lookup */
71 Privileges
.PrivilegeCount
= 1;
72 Privileges
.Control
= PRIVILEGE_SET_ALL_NECESSARY
;
73 Privileges
.Privilege
[0].Luid
= SeBackupPrivilege
;
74 Privileges
.Privilege
[0].Attributes
= 0;
75 AccessGranted
= SePrivilegeCheck(&Privileges
,
77 SubjectSecurityContext
,
81 /* Remember that backup was allowed */
82 HaveBackupPriv
= TRUE
;
84 /* Append the privileges and update the access state */
85 SeAppendPrivileges(AccessState
, &Privileges
);
86 AccessState
->PreviouslyGrantedAccess
|= (DesiredAccess
& ReadAccess
);
87 AccessState
->RemainingDesiredAccess
&= ~ReadAccess
;
88 DesiredAccess
&= ~ReadAccess
;
90 /* Set backup privilege for the token */
91 AccessState
->Flags
|= TOKEN_HAS_BACKUP_PRIVILEGE
;
97 /* Caller is creating the file, check restore privileges later */
101 /* Check if caller wants write access or if it's creating a file */
102 if ((WriteAccess
& DesiredAccess
) || (CheckRestore
))
104 /* Setup the privilege lookup and do it */
105 Privileges
.PrivilegeCount
= 1;
106 Privileges
.Control
= PRIVILEGE_SET_ALL_NECESSARY
;
107 Privileges
.Privilege
[0].Luid
= SeRestorePrivilege
;
108 Privileges
.Privilege
[0].Attributes
= 0;
109 AccessGranted
= SePrivilegeCheck(&Privileges
,
110 &AccessState
->SubjectSecurityContext
,
114 /* Remember that privilege was given */
115 HaveBackupPriv
= TRUE
;
117 /* Append the privileges and update the access state */
118 SeAppendPrivileges(AccessState
, &Privileges
);
119 AccessState
->PreviouslyGrantedAccess
|= (DesiredAccess
& WriteAccess
);
120 AccessState
->RemainingDesiredAccess
&= ~WriteAccess
;
122 /* Set restore privilege for the token */
123 AccessState
->Flags
|= TOKEN_HAS_RESTORE_PRIVILEGE
;
127 /* If we don't have the privilege, remove the option */
128 if (!HaveBackupPriv
) *CreateOptions
&= ~FILE_OPEN_FOR_BACKUP_INTENT
;
134 IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket
,
135 IN PDEVICE_OBJECT DeviceObject
)
137 /* Make sure the object is valid */
138 if ((IoGetDevObjExtension(DeviceObject
)->ExtensionFlags
&
139 (DOE_UNLOAD_PENDING
|
142 DOE_REMOVE_PROCESSED
)) ||
143 (DeviceObject
->Flags
& DO_DEVICE_INITIALIZING
))
145 /* It's unloading or initializing, so fail */
146 DPRINT1("You are seeing this because the following ROS driver: %wZ\n"
147 " sucks. Please fix it's AddDevice Routine\n",
148 &DeviceObject
->DriverObject
->DriverName
);
149 return STATUS_NO_SUCH_DEVICE
;
151 else if ((DeviceObject
->Flags
& DO_EXCLUSIVE
) &&
152 (DeviceObject
->ReferenceCount
) &&
153 !(OpenPacket
->RelatedFileObject
) &&
154 !(OpenPacket
->Options
& IO_ATTACH_DEVICE
))
156 return STATUS_ACCESS_DENIED
;
161 /* Increase reference count */
162 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
163 return STATUS_SUCCESS
;
169 IopDoNameTransmogrify(IN PIRP Irp
,
170 IN PFILE_OBJECT FileObject
,
171 IN PREPARSE_DATA_BUFFER DataBuffer
)
175 USHORT RequiredLength
;
180 ASSERT(Irp
->IoStatus
.Status
== STATUS_REPARSE
);
181 ASSERT(Irp
->IoStatus
.Information
== IO_REPARSE_TAG_MOUNT_POINT
);
182 ASSERT(Irp
->Tail
.Overlay
.AuxiliaryBuffer
!= NULL
);
183 ASSERT(DataBuffer
!= NULL
);
184 ASSERT(DataBuffer
->ReparseTag
== IO_REPARSE_TAG_MOUNT_POINT
);
185 ASSERT(DataBuffer
->ReparseDataLength
< MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
186 ASSERT(DataBuffer
->Reserved
< MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
188 /* First of all, validate data */
189 if (DataBuffer
->ReparseDataLength
< REPARSE_DATA_BUFFER_HEADER_SIZE
||
190 (DataBuffer
->SymbolicLinkReparseBuffer
.PrintNameLength
+
191 DataBuffer
->SymbolicLinkReparseBuffer
.SubstituteNameLength
+
192 FIELD_OFFSET(REPARSE_DATA_BUFFER
, MountPointReparseBuffer
.PathBuffer
[0])) > MAXIMUM_REPARSE_DATA_BUFFER_SIZE
)
194 Irp
->IoStatus
.Status
= STATUS_IO_REPARSE_DATA_INVALID
;
197 /* Everything went right */
198 if (NT_SUCCESS(Irp
->IoStatus
.Status
))
200 /* Compute buffer & length */
201 Buffer
= (PWSTR
)((ULONG_PTR
)DataBuffer
->MountPointReparseBuffer
.PathBuffer
+
202 DataBuffer
->MountPointReparseBuffer
.SubstituteNameOffset
);
203 Length
= DataBuffer
->MountPointReparseBuffer
.SubstituteNameLength
;
205 /* Check we don't overflow */
206 if (((ULONG
)MAXUSHORT
- DataBuffer
->Reserved
) <= (Length
+ sizeof(UNICODE_NULL
)))
208 Irp
->IoStatus
.Status
= STATUS_IO_REPARSE_DATA_INVALID
;
212 /* Compute how much mem we'll need */
213 RequiredLength
= DataBuffer
->Reserved
+ Length
+ sizeof(UNICODE_NULL
);
215 /* Check if FileObject can already hold what we need */
216 if (FileObject
->FileName
.MaximumLength
>= RequiredLength
)
218 NewBuffer
= FileObject
->FileName
.Buffer
;
222 /* Allocate otherwise */
223 NewBuffer
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_IO_NAME
);
224 if (NewBuffer
== NULL
)
226 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
232 /* Everything went right */
233 if (NT_SUCCESS(Irp
->IoStatus
.Status
))
236 if (DataBuffer
->Reserved
)
238 RtlMoveMemory((PWSTR
)((ULONG_PTR
)NewBuffer
+ Length
),
239 (PWSTR
)((ULONG_PTR
)FileObject
->FileName
.Buffer
+ FileObject
->FileName
.Length
- DataBuffer
->Reserved
),
240 DataBuffer
->Reserved
);
246 RtlCopyMemory(NewBuffer
, Buffer
, Length
);
249 /* And finally replace buffer if new one was allocated */
250 FileObject
->FileName
.Length
= RequiredLength
- sizeof(UNICODE_NULL
);
251 if (NewBuffer
!= FileObject
->FileName
.Buffer
)
253 if (FileObject
->FileName
.Buffer
)
255 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
258 FileObject
->FileName
.Buffer
= NewBuffer
;
259 FileObject
->FileName
.MaximumLength
= RequiredLength
;
260 FileObject
->FileName
.Buffer
[RequiredLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
264 /* We don't need them anymore - it was allocated by the driver */
265 ExFreePool(DataBuffer
);
270 IopParseDevice(IN PVOID ParseObject
,
272 IN OUT PACCESS_STATE AccessState
,
273 IN KPROCESSOR_MODE AccessMode
,
275 IN OUT PUNICODE_STRING CompleteName
,
276 IN OUT PUNICODE_STRING RemainingName
,
277 IN OUT PVOID Context
,
278 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
281 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
282 PDEVICE_OBJECT OriginalDeviceObject
= (PDEVICE_OBJECT
)ParseObject
;
283 PDEVICE_OBJECT DeviceObject
, OwnerDevice
;
285 PFILE_OBJECT FileObject
;
288 PIO_STACK_LOCATION StackLoc
;
289 IO_SECURITY_CONTEXT SecurityContext
;
290 IO_STATUS_BLOCK IoStatusBlock
;
291 BOOLEAN DirectOpen
= FALSE
, OpenCancelled
, UseDummyFile
;
292 OBJECT_ATTRIBUTES ObjectAttributes
;
294 PDUMMY_FILE_OBJECT LocalFileObject
;
295 PFILE_BASIC_INFORMATION FileBasicInfo
;
297 KPROCESSOR_MODE CheckMode
;
298 BOOLEAN VolumeOpen
= FALSE
;
299 ACCESS_MASK DesiredAccess
, GrantedAccess
;
300 BOOLEAN AccessGranted
, LockHeld
= FALSE
;
301 PPRIVILEGE_SET Privileges
= NULL
;
302 UNICODE_STRING FileString
;
304 IOTRACE(IO_FILE_DEBUG
, "ParseObject: %p. RemainingName: %wZ\n",
305 ParseObject
, RemainingName
);
307 for (Attempt
= 0; Attempt
< IOP_MAX_REPARSE_TRAVERSAL
; ++Attempt
)
312 /* Validate the open packet */
313 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
315 /* Valide reparse point in case we traversed a mountpoint */
316 if (OpenPacket
->TraversedMountPoint
)
318 /* This is a reparse point we understand */
319 ASSERT(OpenPacket
->Information
== IO_REPARSE_TAG_MOUNT_POINT
);
321 /* Make sure we're dealing with correct DO */
322 if (OriginalDeviceObject
->DeviceType
!= FILE_DEVICE_DISK
&&
323 OriginalDeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
&&
324 OriginalDeviceObject
->DeviceType
!= FILE_DEVICE_VIRTUAL_DISK
&&
325 OriginalDeviceObject
->DeviceType
!= FILE_DEVICE_TAPE
)
327 OpenPacket
->FinalStatus
= STATUS_IO_REPARSE_DATA_INVALID
;
328 return STATUS_IO_REPARSE_DATA_INVALID
;
332 /* Check if we have a related file object */
333 if (OpenPacket
->RelatedFileObject
)
335 /* Use the related file object's device object */
336 OriginalDeviceObject
= OpenPacket
->RelatedFileObject
->DeviceObject
;
339 /* Validate device status */
340 Status
= IopCheckDeviceAndDriver(OpenPacket
, OriginalDeviceObject
);
341 if (!NT_SUCCESS(Status
))
343 /* We failed, return status */
344 OpenPacket
->FinalStatus
= Status
;
348 /* Map the generic mask and set the new mapping in the access state */
349 RtlMapGenericMask(&AccessState
->RemainingDesiredAccess
,
350 &IoFileObjectType
->TypeInfo
.GenericMapping
);
351 RtlMapGenericMask(&AccessState
->OriginalDesiredAccess
,
352 &IoFileObjectType
->TypeInfo
.GenericMapping
);
353 SeSetAccessStateGenericMapping(AccessState
,
354 &IoFileObjectType
->TypeInfo
.GenericMapping
);
355 DesiredAccess
= AccessState
->RemainingDesiredAccess
;
357 /* Check what kind of access checks to do */
358 if ((AccessMode
!= KernelMode
) ||
359 (OpenPacket
->Options
& IO_FORCE_ACCESS_CHECK
))
361 /* Call is from user-mode or kernel is forcing checks */
362 CheckMode
= UserMode
;
366 /* Call is from the kernel */
367 CheckMode
= KernelMode
;
370 /* Check privilege for backup or restore operation */
371 IopCheckBackupRestorePrivilege(AccessState
,
372 &OpenPacket
->CreateOptions
,
374 OpenPacket
->Disposition
);
376 /* Check if we are re-parsing */
377 if (((OpenPacket
->Override
) && !(RemainingName
->Length
)) ||
378 (AccessState
->Flags
& SE_BACKUP_PRIVILEGES_CHECKED
))
380 /* Get granted access from the last call */
381 DesiredAccess
|= AccessState
->PreviouslyGrantedAccess
;
384 /* Check if this is a volume open */
385 if ((OpenPacket
->RelatedFileObject
) &&
386 (OpenPacket
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
) &&
387 !(RemainingName
->Length
))
393 /* Now check if we need access checks */
394 if (((AccessMode
!= KernelMode
) ||
395 (OpenPacket
->Options
& IO_FORCE_ACCESS_CHECK
)) &&
396 (!(OpenPacket
->RelatedFileObject
) || (VolumeOpen
)) &&
397 !(OpenPacket
->Override
))
399 KeEnterCriticalRegion();
400 ExAcquireResourceSharedLite(&IopSecurityResource
, TRUE
);
402 /* Check if a device object is being parsed */
403 if (!RemainingName
->Length
)
405 /* Lock the subject context */
406 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
409 /* Do access check */
410 AccessGranted
= SeAccessCheck(OriginalDeviceObject
->
412 &AccessState
->SubjectSecurityContext
,
418 TypeInfo
.GenericMapping
,
424 /* Append and free the privileges */
425 SeAppendPrivileges(AccessState
, Privileges
);
426 SeFreePrivileges(Privileges
);
429 /* Check if we got access */
432 /* Update access state */
433 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
434 AccessState
->RemainingDesiredAccess
&= ~(GrantedAccess
&
436 OpenPacket
->Override
= TRUE
;
439 FileString
.Length
= 8;
440 FileString
.MaximumLength
= 8;
441 FileString
.Buffer
= L
"File";
443 /* Do Audit/Alarm for open operation */
444 SeOpenObjectAuditAlarm(&FileString
,
445 OriginalDeviceObject
,
447 OriginalDeviceObject
->SecurityDescriptor
,
452 &AccessState
->GenerateOnClose
);
456 /* Check if we need to do traverse validation */
457 if (!(AccessState
->Flags
& TOKEN_HAS_TRAVERSE_PRIVILEGE
) ||
458 ((OriginalDeviceObject
->DeviceType
== FILE_DEVICE_DISK
) ||
459 (OriginalDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
)))
461 /* Check if this is a restricted token */
462 if (!(AccessState
->Flags
& TOKEN_IS_RESTRICTED
))
464 /* Do the FAST traverse check */
465 AccessGranted
= SeFastTraverseCheck(OriginalDeviceObject
->SecurityDescriptor
,
473 AccessGranted
= FALSE
;
476 /* Check if we failed to get access */
479 /* Lock the subject context */
480 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
483 /* Do access check */
484 AccessGranted
= SeAccessCheck(OriginalDeviceObject
->
486 &AccessState
->SubjectSecurityContext
,
492 TypeInfo
.GenericMapping
,
498 /* Append and free the privileges */
499 SeAppendPrivileges(AccessState
, Privileges
);
500 SeFreePrivileges(Privileges
);
504 /* FIXME: Do Audit/Alarm for traverse check */
508 /* Access automatically granted */
509 AccessGranted
= TRUE
;
513 ExReleaseResourceLite(&IopSecurityResource
);
514 KeLeaveCriticalRegion();
516 /* Check if we hold the lock */
520 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
523 /* Check if access failed */
526 /* Dereference the device and fail */
527 DPRINT1("Traverse access failed!\n");
528 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
529 return STATUS_ACCESS_DENIED
;
533 /* Check if we can simply use a dummy file */
534 UseDummyFile
= ((OpenPacket
->QueryOnly
) || (OpenPacket
->DeleteOnly
));
537 /* FIXME: Small hack still exists, have to check why...
538 * This is triggered multiple times by usetup and then once per boot.
540 if (ExpInTextModeSetup
&&
542 !(RemainingName
->Length
) &&
543 !(OpenPacket
->RelatedFileObject
) &&
544 ((wcsstr(CompleteName
->Buffer
, L
"Harddisk")) ||
545 (wcsstr(CompleteName
->Buffer
, L
"Floppy"))) &&
548 DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n",
549 DesiredAccess
& ~(SYNCHRONIZE
|
550 FILE_READ_ATTRIBUTES
|
552 ACCESS_SYSTEM_SECURITY
|
559 /* Check if this is a direct open */
560 if (!(RemainingName
->Length
) &&
561 !(OpenPacket
->RelatedFileObject
) &&
562 ((DesiredAccess
& ~(SYNCHRONIZE
|
563 FILE_READ_ATTRIBUTES
|
565 ACCESS_SYSTEM_SECURITY
|
570 /* Remember this for later */
574 /* Check if we have a related FO that wasn't a direct open */
575 if ((OpenPacket
->RelatedFileObject
) &&
576 !(OpenPacket
->RelatedFileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
578 /* The device object is the one we were given */
579 DeviceObject
= ParseObject
;
581 /* Check if the related FO had a VPB */
582 if (OpenPacket
->RelatedFileObject
->Vpb
)
584 /* Yes, remember it */
585 Vpb
= OpenPacket
->RelatedFileObject
->Vpb
;
588 InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
590 /* Check if we were given a specific top level device to use */
591 if (OpenPacket
->InternalFlags
& IOP_USE_TOP_LEVEL_DEVICE_HINT
)
593 DeviceObject
= Vpb
->DeviceObject
;
599 /* Check if it has a VPB */
600 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
602 /* Check if the VPB is mounted, and mount it */
603 Vpb
= IopCheckVpbMounted(OpenPacket
,
604 OriginalDeviceObject
,
607 if (!Vpb
) return Status
;
609 /* Get the VPB's device object */
610 DeviceObject
= Vpb
->DeviceObject
;
614 /* The device object is the one we were given */
615 DeviceObject
= OriginalDeviceObject
;
618 /* If we weren't given a specific top level device, look for an attached device */
619 if (!(OpenPacket
->InternalFlags
& IOP_USE_TOP_LEVEL_DEVICE_HINT
) &&
620 DeviceObject
->AttachedDevice
)
622 /* Get the attached device */
623 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
627 if (OpenPacket
->InternalFlags
& IOP_USE_TOP_LEVEL_DEVICE_HINT
)
629 // FIXME: Verify our device object is good to use
630 ASSERT(DirectOpen
== FALSE
);
633 /* If we traversed a mount point, reset the information */
634 if (OpenPacket
->TraversedMountPoint
)
636 OpenPacket
->TraversedMountPoint
= FALSE
;
639 /* Check if this is a secure FSD */
640 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
641 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
644 DPRINT("Fix Secure FSD support!!!\n");
647 /* Allocate the IRP */
648 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
651 /* Dereference the device and VPB, then fail */
652 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
653 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
654 return STATUS_INSUFFICIENT_RESOURCES
;
657 /* Now set the IRP data */
658 Irp
->RequestorMode
= AccessMode
;
659 Irp
->Flags
= IRP_CREATE_OPERATION
| IRP_SYNCHRONOUS_API
| IRP_DEFER_IO_COMPLETION
;
660 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
661 Irp
->UserIosb
= &IoStatusBlock
;
662 Irp
->MdlAddress
= NULL
;
663 Irp
->PendingReturned
= FALSE
;
664 Irp
->UserEvent
= NULL
;
666 Irp
->CancelRoutine
= NULL
;
667 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
669 /* Setup the security context */
670 SecurityContext
.SecurityQos
= SecurityQos
;
671 SecurityContext
.AccessState
= AccessState
;
672 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
673 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
675 /* Get the I/O Stack location */
676 StackLoc
= IoGetNextIrpStackLocation(Irp
);
677 StackLoc
->Control
= 0;
679 /* Check what kind of file this is */
680 switch (OpenPacket
->CreateFileType
)
683 case CreateFileTypeNone
:
685 /* Set the major function and EA Length */
686 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
687 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
690 StackLoc
->Flags
= (UCHAR
)OpenPacket
->Options
;
691 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ? SL_CASE_SENSITIVE
: 0;
695 case CreateFileTypeNamedPipe
:
697 /* Set the named pipe MJ and set the parameters */
698 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
699 StackLoc
->Parameters
.CreatePipe
.Parameters
= OpenPacket
->ExtraCreateParameters
;
703 case CreateFileTypeMailslot
:
705 /* Set the mailslot MJ and set the parameters */
706 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
707 StackLoc
->Parameters
.CreateMailslot
.Parameters
= OpenPacket
->ExtraCreateParameters
;
711 /* Set the common data */
712 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
713 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
714 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
715 (OpenPacket
->CreateOptions
&
717 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
718 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
719 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
721 /* Check if we really need to create an object */
724 ULONG ObjectSize
= sizeof(FILE_OBJECT
);
726 /* Tag on space for a file object extension */
727 if (OpenPacket
->InternalFlags
& IOP_CREATE_FILE_OBJECT_EXTENSION
)
728 ObjectSize
+= sizeof(FILE_OBJECT_EXTENSION
);
730 /* Create the actual file object */
731 InitializeObjectAttributes(&ObjectAttributes
,
736 Status
= ObCreateObject(KernelMode
,
744 (PVOID
*)&FileObject
);
745 if (!NT_SUCCESS(Status
))
747 /* Create failed, free the IRP */
750 /* Dereference the device and VPB */
751 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
752 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
754 /* We failed, return status */
755 OpenPacket
->FinalStatus
= Status
;
759 /* Clear the file object */
760 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
762 /* Check if this is Synch I/O */
763 if (OpenPacket
->CreateOptions
&
764 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
766 /* Set the synch flag */
767 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
769 /* Check if it's also alertable */
770 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
772 /* It is, set the alertable flag */
773 FileObject
->Flags
|= FO_ALERTABLE_IO
;
777 /* Check if this is synch I/O */
778 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
780 /* Initialize the event */
781 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
784 /* Check if the caller requested no intermediate buffering */
785 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
787 /* Set the correct flag for the FSD to read */
788 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
791 /* Check if the caller requested write through support */
792 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
794 /* Set the correct flag for the FSD to read */
795 FileObject
->Flags
|= FO_WRITE_THROUGH
;
798 /* Check if the caller says the file will be only read sequentially */
799 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
801 /* Set the correct flag for the FSD to read */
802 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
805 /* Check if the caller believes the file will be only read randomly */
806 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
808 /* Set the correct flag for the FSD to read */
809 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
812 /* Check if we were asked to setup a file object extension */
813 if (OpenPacket
->InternalFlags
& IOP_CREATE_FILE_OBJECT_EXTENSION
)
815 PFILE_OBJECT_EXTENSION FileObjectExtension
;
817 /* Make sure the file object knows it has an extension */
818 FileObject
->Flags
|= FO_FILE_OBJECT_HAS_EXTENSION
;
820 FileObjectExtension
= (PFILE_OBJECT_EXTENSION
)(FileObject
+ 1);
821 FileObject
->FileObjectExtension
= FileObjectExtension
;
823 /* Add the top level device which we'll send the request to */
824 if (OpenPacket
->InternalFlags
& IOP_USE_TOP_LEVEL_DEVICE_HINT
)
826 FileObjectExtension
->TopDeviceObjectHint
= DeviceObject
;
832 /* Use the dummy object instead */
833 LocalFileObject
= OpenPacket
->LocalFileObject
;
834 RtlZeroMemory(LocalFileObject
, sizeof(DUMMY_FILE_OBJECT
));
837 FileObject
= (PFILE_OBJECT
)&LocalFileObject
->ObjectHeader
.Body
;
838 LocalFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
839 LocalFileObject
->ObjectHeader
.PointerCount
= 1;
842 /* Setup the file header */
843 FileObject
->Type
= IO_TYPE_FILE
;
844 FileObject
->Size
= sizeof(FILE_OBJECT
);
845 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
846 FileObject
->DeviceObject
= OriginalDeviceObject
;
848 /* Check if this is a direct device open */
849 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
851 /* Check if the caller wants case sensitivity */
852 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
854 /* Tell the driver about it */
855 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
858 /* Now set the file object */
859 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
860 StackLoc
->FileObject
= FileObject
;
862 /* Check if the file object has a name */
863 if (RemainingName
->Length
)
865 /* Setup the unicode string */
866 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
868 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
873 if (!FileObject
->FileName
.Buffer
)
875 /* Failed to allocate the name, free the IRP */
878 /* Dereference the device object and VPB */
879 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
880 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
882 /* Clear the FO and dereference it */
883 FileObject
->DeviceObject
= NULL
;
884 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
887 return STATUS_INSUFFICIENT_RESOURCES
;
892 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
894 /* Initialize the File Object event and set the FO */
895 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
896 OpenPacket
->FileObject
= FileObject
;
898 /* Queue the IRP and call the driver */
899 IopQueueIrpToThread(Irp
);
900 Status
= IoCallDriver(DeviceObject
, Irp
);
901 if (Status
== STATUS_PENDING
)
903 /* Wait for the driver to complete the create */
904 KeWaitForSingleObject(&FileObject
->Event
,
910 /* Get the new status */
911 Status
= IoStatusBlock
.Status
;
915 /* We'll have to complete it ourselves */
916 ASSERT(!Irp
->PendingReturned
);
917 ASSERT(!Irp
->MdlAddress
);
919 /* Handle name change if required */
920 if (Status
== STATUS_REPARSE
)
922 /* Check this is a mount point */
923 if (Irp
->IoStatus
.Information
== IO_REPARSE_TAG_MOUNT_POINT
)
925 PREPARSE_DATA_BUFFER ReparseData
;
927 /* Reparse point attributes were passed by the driver in the auxiliary buffer */
928 ASSERT(Irp
->Tail
.Overlay
.AuxiliaryBuffer
!= NULL
);
929 ReparseData
= (PREPARSE_DATA_BUFFER
)Irp
->Tail
.Overlay
.AuxiliaryBuffer
;
931 ASSERT(ReparseData
->ReparseTag
== IO_REPARSE_TAG_MOUNT_POINT
);
932 ASSERT(ReparseData
->ReparseDataLength
< MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
933 ASSERT(ReparseData
->Reserved
< MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
935 IopDoNameTransmogrify(Irp
, FileObject
, ReparseData
);
939 /* Completion happens at APC_LEVEL */
940 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
942 /* Get the new I/O Status block ourselves */
943 IoStatusBlock
= Irp
->IoStatus
;
944 Status
= IoStatusBlock
.Status
;
946 /* Manually signal the even, we can't have any waiters */
947 FileObject
->Event
.Header
.SignalState
= 1;
949 /* Now that we've signaled the events, de-associate the IRP */
950 IopUnQueueIrpFromThread(Irp
);
952 /* Check if the IRP had an input buffer */
953 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
954 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
956 /* Free it. A driver might've tacked one on */
957 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
960 /* Free the IRP and bring the IRQL back down */
962 KeLowerIrql(OldIrql
);
965 /* Copy the I/O Status */
966 OpenPacket
->Information
= IoStatusBlock
.Information
;
968 /* The driver failed to create the file */
969 if (!NT_SUCCESS(Status
))
971 /* Check if we have a name */
972 if (FileObject
->FileName
.Length
)
975 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
976 FileObject
->FileName
.Length
= 0;
979 /* Clear its device object */
980 FileObject
->DeviceObject
= NULL
;
982 /* Save this now because the FO might go away */
983 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
986 /* Clear the file object in the open packet */
987 OpenPacket
->FileObject
= NULL
;
989 /* Dereference the file object */
990 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
992 /* Dereference the device object */
993 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
995 /* Unless the driver cancelled the open, dereference the VPB */
996 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpbAndFree(Vpb
);
998 /* Set the status and return */
999 OpenPacket
->FinalStatus
= Status
;
1002 else if (Status
== STATUS_REPARSE
)
1004 if (OpenPacket
->Information
== IO_REPARSE
||
1005 OpenPacket
->Information
== IO_REPARSE_TAG_MOUNT_POINT
)
1007 /* Update CompleteName with reparse info which got updated in IopDoNameTransmogrify() */
1008 if (CompleteName
->MaximumLength
< FileObject
->FileName
.Length
)
1010 PWSTR NewCompleteName
;
1012 /* Allocate a new buffer for the string */
1013 NewCompleteName
= ExAllocatePoolWithTag(PagedPool
, FileObject
->FileName
.Length
, TAG_IO_NAME
);
1014 if (NewCompleteName
== NULL
)
1016 OpenPacket
->FinalStatus
= STATUS_INSUFFICIENT_RESOURCES
;
1017 return STATUS_INSUFFICIENT_RESOURCES
;
1020 /* Release the old one */
1021 if (CompleteName
->Buffer
!= NULL
)
1023 ExFreePoolWithTag(CompleteName
->Buffer
, 0);
1026 /* And setup the new one */
1027 CompleteName
->Buffer
= NewCompleteName
;
1028 CompleteName
->MaximumLength
= FileObject
->FileName
.Length
;
1031 /* Copy our new complete name */
1032 RtlCopyUnicodeString(CompleteName
, &FileObject
->FileName
);
1034 if (OpenPacket
->Information
== IO_REPARSE_TAG_MOUNT_POINT
)
1036 OpenPacket
->RelatedFileObject
= NULL
;
1040 /* Check if we have a name */
1041 if (FileObject
->FileName
.Length
)
1044 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, 0);
1045 FileObject
->FileName
.Length
= 0;
1048 /* Clear its device object */
1049 FileObject
->DeviceObject
= NULL
;
1051 /* Clear the file object in the open packet */
1052 OpenPacket
->FileObject
= NULL
;
1054 /* Dereference the file object */
1055 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
1057 /* Dereference the device object */
1058 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
1060 /* Unless the driver cancelled the open, dereference the VPB */
1061 if (Vpb
!= NULL
) IopDereferenceVpbAndFree(Vpb
);
1063 if (OpenPacket
->Information
!= IO_REMOUNT
)
1065 OpenPacket
->RelatedFileObject
= NULL
;
1067 /* Inform we traversed a mount point for later attempt */
1068 if (OpenPacket
->Information
== IO_REPARSE_TAG_MOUNT_POINT
)
1070 OpenPacket
->TraversedMountPoint
= 1;
1073 /* In case we override checks, but got this on volume open, fail hard */
1074 if (OpenPacket
->Override
)
1076 KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN
,
1077 (ULONG_PTR
)OriginalDeviceObject
,
1078 (ULONG_PTR
)DeviceObject
,
1079 (ULONG_PTR
)CompleteName
,
1080 OpenPacket
->Information
);
1083 /* Return to IO/OB so that information can be upgraded */
1084 return STATUS_REPARSE
;
1087 /* Loop again and reattempt an opening */
1094 if (Attempt
== IOP_MAX_REPARSE_TRAVERSAL
)
1095 return STATUS_UNSUCCESSFUL
;
1097 /* Get the owner of the File Object */
1098 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
1101 * It's possible that the device to whom we sent the IRP to
1102 * isn't actually the device that ended opening the file object
1105 if (OwnerDevice
!= DeviceObject
)
1107 /* We have to de-reference the VPB we had associated */
1108 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
1110 /* And re-associate with the actual one */
1111 Vpb
= FileObject
->Vpb
;
1112 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
1115 /* Make sure we are not using a dummy */
1118 /* Check if this was a volume open */
1119 if ((!(FileObject
->RelatedFileObject
) ||
1120 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
1121 !(FileObject
->FileName
.Length
))
1123 /* All signs point to it, but make sure it was actually an FSD */
1124 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
1125 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
1126 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
1127 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
1129 /* The owner device is an FSD, so this is a volume open for real */
1130 FileObject
->Flags
|= FO_VOLUME_OPEN
;
1134 /* Reference the object and set the parse check */
1135 ObReferenceObject(FileObject
);
1136 *Object
= FileObject
;
1137 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
1138 OpenPacket
->ParseCheck
= TRUE
;
1139 return OpenPacket
->FinalStatus
;
1143 /* Check if this was a query */
1144 if (OpenPacket
->QueryOnly
)
1146 /* Check if the caller wants basic info only */
1147 if (!OpenPacket
->FullAttributes
)
1149 /* Allocate the buffer */
1150 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1151 sizeof(*FileBasicInfo
),
1156 Status
= IoQueryFileInformation(FileObject
,
1157 FileBasicInformation
,
1158 sizeof(*FileBasicInfo
),
1161 if (NT_SUCCESS(Status
))
1164 RtlCopyMemory(OpenPacket
->BasicInformation
,
1169 /* Free our buffer */
1170 ExFreePoolWithTag(FileBasicInfo
, TAG_IO
);
1175 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1180 /* This is a full query */
1181 Status
= IoQueryFileInformation(
1183 FileNetworkOpenInformation
,
1184 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
1185 OpenPacket
->NetworkInformation
,
1187 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
1191 /* Delete the file object */
1192 IopDeleteFile(FileObject
);
1194 /* Clear out the file */
1195 OpenPacket
->FileObject
= NULL
;
1197 /* Set and return status */
1198 OpenPacket
->FinalStatus
= Status
;
1199 OpenPacket
->ParseCheck
= TRUE
;
1206 IopParseFile(IN PVOID ParseObject
,
1207 IN PVOID ObjectType
,
1208 IN OUT PACCESS_STATE AccessState
,
1209 IN KPROCESSOR_MODE AccessMode
,
1210 IN ULONG Attributes
,
1211 IN OUT PUNICODE_STRING CompleteName
,
1212 IN OUT PUNICODE_STRING RemainingName
,
1213 IN OUT PVOID Context OPTIONAL
,
1214 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
1218 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
1220 /* Validate the open packet */
1221 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
1223 /* Get the device object */
1224 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
1225 OpenPacket
->RelatedFileObject
= ParseObject
;
1227 /* Call the main routine */
1228 return IopParseDevice(DeviceObject
,
1242 IopDeleteFile(IN PVOID ObjectBody
)
1244 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1246 PIO_STACK_LOCATION StackPtr
;
1249 PDEVICE_OBJECT DeviceObject
;
1250 BOOLEAN DereferenceDone
= FALSE
;
1253 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1255 /* Check if the file has a device object */
1256 if (FileObject
->DeviceObject
)
1258 /* Check if this is a direct open or not */
1259 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1261 /* Get the attached device */
1262 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1266 /* Use the file object's device object */
1267 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1271 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
1272 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
1274 /* Check if the handle wasn't created yet */
1275 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
1277 /* Send the cleanup IRP */
1278 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
1281 /* Clear and set up Events */
1282 KeClearEvent(&FileObject
->Event
);
1283 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1285 /* Allocate an IRP */
1286 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
1289 Irp
->UserEvent
= &Event
;
1290 Irp
->UserIosb
= &Irp
->IoStatus
;
1291 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1292 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1293 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1295 /* Set up Stack Pointer Data */
1296 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1297 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
1298 StackPtr
->FileObject
= FileObject
;
1301 IopQueueIrpToThread(Irp
);
1303 /* Get the VPB and check if this isn't a direct open */
1304 Vpb
= FileObject
->Vpb
;
1305 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1307 /* Dereference the VPB before the close */
1308 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1311 /* Check if the FS will never disappear by itself */
1312 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1314 /* Dereference it */
1315 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1316 DereferenceDone
= TRUE
;
1319 /* Call the FS Driver */
1320 Status
= IoCallDriver(DeviceObject
, Irp
);
1321 if (Status
== STATUS_PENDING
)
1323 /* Wait for completion */
1324 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1327 /* De-queue the IRP */
1328 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1329 IopUnQueueIrpFromThread(Irp
);
1330 KeLowerIrql(OldIrql
);
1335 /* Clear the file name */
1336 if (FileObject
->FileName
.Buffer
)
1338 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1339 FileObject
->FileName
.Buffer
= NULL
;
1342 /* Check if the FO had a completion port */
1343 if (FileObject
->CompletionContext
)
1346 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1347 ExFreePool(FileObject
->CompletionContext
);
1350 /* Check if the FO had extension */
1351 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1353 /* Release filter context structure if any */
1354 FsRtlPTeardownPerFileObjectContexts(FileObject
);
1357 /* Check if dereference has been done yet */
1358 if (!DereferenceDone
)
1360 /* Dereference device object */
1361 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1368 IopGetDeviceAttachmentBase(IN PDEVICE_OBJECT DeviceObject
)
1370 PDEVICE_OBJECT PDO
= DeviceObject
;
1372 /* Go down the stack to attempt to get the PDO */
1373 for (; ((PEXTENDED_DEVOBJ_EXTENSION
)PDO
->DeviceObjectExtension
)->AttachedTo
!= NULL
;
1374 PDO
= ((PEXTENDED_DEVOBJ_EXTENSION
)PDO
->DeviceObjectExtension
)->AttachedTo
);
1381 IopGetDevicePDO(IN PDEVICE_OBJECT DeviceObject
)
1386 ASSERT(DeviceObject
!= NULL
);
1388 OldIrql
= KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock
);
1389 /* Get the base DO */
1390 PDO
= IopGetDeviceAttachmentBase(DeviceObject
);
1391 /* Check whether that's really a PDO and if so, keep it */
1392 if ((PDO
->Flags
& DO_BUS_ENUMERATED_DEVICE
) != DO_BUS_ENUMERATED_DEVICE
)
1398 ObReferenceObject(PDO
);
1400 KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock
, OldIrql
);
1407 IopSetDeviceSecurityDescriptor(IN PDEVICE_OBJECT DeviceObject
,
1408 IN PSECURITY_INFORMATION SecurityInformation
,
1409 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1410 IN POOL_TYPE PoolType
,
1411 IN PGENERIC_MAPPING GenericMapping
)
1414 PSECURITY_DESCRIPTOR OldSecurityDescriptor
, CachedSecurityDescriptor
, NewSecurityDescriptor
;
1418 /* Keep attempting till we find our old SD or fail */
1421 KeEnterCriticalRegion();
1422 ExAcquireResourceSharedLite(&IopSecurityResource
, TRUE
);
1424 /* Get our old SD and reference it */
1425 OldSecurityDescriptor
= DeviceObject
->SecurityDescriptor
;
1426 if (OldSecurityDescriptor
!= NULL
)
1428 ObReferenceSecurityDescriptor(OldSecurityDescriptor
, 1);
1431 ExReleaseResourceLite(&IopSecurityResource
);
1432 KeLeaveCriticalRegion();
1434 /* Set the SD information */
1435 NewSecurityDescriptor
= OldSecurityDescriptor
;
1436 Status
= SeSetSecurityDescriptorInfo(NULL
, SecurityInformation
,
1437 SecurityDescriptor
, &NewSecurityDescriptor
,
1438 PoolType
, GenericMapping
);
1440 if (!NT_SUCCESS(Status
))
1442 if (OldSecurityDescriptor
!= NULL
)
1444 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, 1);
1450 /* Add the new DS to the internal cache */
1451 Status
= ObLogSecurityDescriptor(NewSecurityDescriptor
,
1452 &CachedSecurityDescriptor
, 1);
1453 ExFreePool(NewSecurityDescriptor
);
1454 if (!NT_SUCCESS(Status
))
1456 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, 1);
1460 KeEnterCriticalRegion();
1461 ExAcquireResourceExclusiveLite(&IopSecurityResource
, TRUE
);
1462 /* Check if someone changed it in our back */
1463 if (DeviceObject
->SecurityDescriptor
== OldSecurityDescriptor
)
1465 /* We're clear, do the swap */
1466 DeviceObject
->SecurityDescriptor
= CachedSecurityDescriptor
;
1467 ExReleaseResourceLite(&IopSecurityResource
);
1468 KeLeaveCriticalRegion();
1470 /* And dereference old SD (twice - us + not in use) */
1471 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, 2);
1475 ExReleaseResourceLite(&IopSecurityResource
);
1476 KeLeaveCriticalRegion();
1478 /* If so, try again */
1479 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, 1);
1480 ObDereferenceSecurityDescriptor(CachedSecurityDescriptor
, 1);
1488 IopSetDeviceSecurityDescriptors(IN PDEVICE_OBJECT UpperDeviceObject
,
1489 IN PDEVICE_OBJECT PhysicalDeviceObject
,
1490 IN PSECURITY_INFORMATION SecurityInformation
,
1491 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1492 IN POOL_TYPE PoolType
,
1493 IN PGENERIC_MAPPING GenericMapping
)
1495 PDEVICE_OBJECT CurrentDO
= PhysicalDeviceObject
, NextDevice
;
1496 NTSTATUS Status
= STATUS_SUCCESS
, TmpStatus
;
1500 ASSERT(PhysicalDeviceObject
!= NULL
);
1502 /* We always reference the DO we're working on */
1503 ObReferenceObject(CurrentDO
);
1505 /* Go up from PDO to latest DO */
1508 /* Attempt to set the new SD on it */
1509 TmpStatus
= IopSetDeviceSecurityDescriptor(CurrentDO
, SecurityInformation
,
1510 SecurityDescriptor
, PoolType
,
1512 /* Was our last one? Remember that status then */
1513 if (CurrentDO
== UpperDeviceObject
)
1518 /* Try to move to the next DO (and thus, reference it) */
1519 NextDevice
= CurrentDO
->AttachedDevice
;
1522 ObReferenceObject(NextDevice
);
1525 /* Dereference current DO and move to the next one */
1526 ObDereferenceObject(CurrentDO
);
1527 CurrentDO
= NextDevice
;
1529 while (CurrentDO
!= NULL
);
1536 IopGetSetSecurityObject(IN PVOID ObjectBody
,
1537 IN SECURITY_OPERATION_CODE OperationCode
,
1538 IN PSECURITY_INFORMATION SecurityInformation
,
1539 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1540 IN OUT PULONG BufferLength
,
1541 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1542 IN POOL_TYPE PoolType
,
1543 IN OUT PGENERIC_MAPPING GenericMapping
)
1545 IO_STATUS_BLOCK IoStatusBlock
;
1546 PIO_STACK_LOCATION StackPtr
;
1547 PFILE_OBJECT FileObject
;
1548 PDEVICE_OBJECT DeviceObject
;
1550 BOOLEAN LocalEvent
= FALSE
;
1552 NTSTATUS Status
= STATUS_SUCCESS
;
1554 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1556 /* Check if this is a device or file */
1557 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1560 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1566 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1568 /* Check if this is a direct open */
1569 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1571 /* Get the Device Object */
1572 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1576 /* Otherwise, use the direct device*/
1577 DeviceObject
= FileObject
->DeviceObject
;
1581 /* Check if the request was for a device object */
1582 if (!(FileObject
) ||
1583 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1584 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1586 /* Check what kind of request this was */
1587 if (OperationCode
== QuerySecurityDescriptor
)
1589 return SeQuerySecurityDescriptorInfo(SecurityInformation
,
1592 &DeviceObject
->SecurityDescriptor
);
1594 else if (OperationCode
== DeleteSecurityDescriptor
)
1596 /* Simply return success */
1597 return STATUS_SUCCESS
;
1599 else if (OperationCode
== AssignSecurityDescriptor
)
1601 Status
= STATUS_SUCCESS
;
1603 /* Make absolutely sure this is a device object */
1604 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1606 PSECURITY_DESCRIPTOR CachedSecurityDescriptor
;
1608 /* Add the security descriptor in cache */
1609 Status
= ObLogSecurityDescriptor(SecurityDescriptor
, &CachedSecurityDescriptor
, 1);
1610 if (NT_SUCCESS(Status
))
1612 KeEnterCriticalRegion();
1613 ExAcquireResourceExclusiveLite(&IopSecurityResource
, TRUE
);
1615 /* Assign the Security Descriptor */
1616 DeviceObject
->SecurityDescriptor
= CachedSecurityDescriptor
;
1618 ExReleaseResourceLite(&IopSecurityResource
);
1619 KeLeaveCriticalRegion();
1626 else if (OperationCode
== SetSecurityDescriptor
)
1628 /* Get the Physical Device Object if any */
1629 PDEVICE_OBJECT PDO
= IopGetDevicePDO(DeviceObject
);
1633 /* Apply the new SD to any DO in the path from PDO to current DO */
1634 Status
= IopSetDeviceSecurityDescriptors(DeviceObject
, PDO
,
1635 SecurityInformation
,
1637 PoolType
, GenericMapping
);
1638 ObDereferenceObject(PDO
);
1642 /* Otherwise, just set for ourselves */
1643 Status
= IopSetDeviceSecurityDescriptor(DeviceObject
,
1644 SecurityInformation
,
1646 PoolType
, GenericMapping
);
1649 return STATUS_SUCCESS
;
1652 /* Shouldn't happen */
1653 return STATUS_SUCCESS
;
1655 else if (OperationCode
== DeleteSecurityDescriptor
)
1657 /* Same as for devices, do nothing */
1658 return STATUS_SUCCESS
;
1661 /* At this point, we know we're a file. Reference it */
1662 ObReferenceObject(FileObject
);
1664 /* Check if we should use Sync IO or not */
1665 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1667 /* Lock the file object */
1668 IopLockFileObject(FileObject
);
1672 /* Use local event */
1673 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1677 /* Clear the File Object event */
1678 KeClearEvent(&FileObject
->Event
);
1680 /* Get the device object */
1681 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1683 /* Allocate the IRP */
1684 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1685 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1688 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1689 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1690 Irp
->RequestorMode
= ExGetPreviousMode();
1691 Irp
->UserIosb
= &IoStatusBlock
;
1692 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1693 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1694 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1696 /* Set Stack Parameters */
1697 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1698 StackPtr
->FileObject
= FileObject
;
1700 /* Check if this is a query or set */
1701 if (OperationCode
== QuerySecurityDescriptor
)
1703 /* Set the major function and parameters */
1704 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1705 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1706 *SecurityInformation
;
1707 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1708 Irp
->UserBuffer
= SecurityDescriptor
;
1712 /* Set the major function and parameters for a set */
1713 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1714 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1715 *SecurityInformation
;
1716 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1721 IopQueueIrpToThread(Irp
);
1723 /* Update operation counts */
1724 IopUpdateOperationCount(IopOtherTransfer
);
1726 /* Call the Driver */
1727 Status
= IoCallDriver(DeviceObject
, Irp
);
1729 /* Check if this was async I/O */
1732 /* Check if the IRP is pending completion */
1733 if (Status
== STATUS_PENDING
)
1735 /* Wait on the local event */
1736 KeWaitForSingleObject(&Event
,
1741 Status
= IoStatusBlock
.Status
;
1746 /* Check if the IRP is pending completion */
1747 if (Status
== STATUS_PENDING
)
1749 /* Wait on the file object */
1750 KeWaitForSingleObject(&FileObject
->Event
,
1755 Status
= FileObject
->FinalStatus
;
1758 /* Release the lock */
1759 IopUnlockFileObject(FileObject
);
1762 /* This Driver doesn't implement Security, so try to give it a default */
1763 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1765 /* Was this a query? */
1766 if (OperationCode
== QuerySecurityDescriptor
)
1768 /* Set a World Security Descriptor */
1769 Status
= SeSetWorldSecurityDescriptor(*SecurityInformation
,
1775 /* It wasn't a query, so just fake success */
1776 Status
= STATUS_SUCCESS
;
1779 else if (OperationCode
== QuerySecurityDescriptor
)
1781 /* Callers usually expect the normalized form */
1782 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1787 *BufferLength
= (ULONG
)IoStatusBlock
.Information
;
1789 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1791 /* Get the exception code */
1792 Status
= _SEH2_GetExceptionCode();
1803 IopQueryNameFile(IN PVOID ObjectBody
,
1805 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1807 OUT PULONG ReturnLength
,
1808 IN KPROCESSOR_MODE PreviousMode
)
1810 POBJECT_NAME_INFORMATION LocalInfo
;
1811 PFILE_NAME_INFORMATION LocalFileInfo
;
1812 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1813 ULONG LocalReturnLength
, FileLength
;
1814 BOOLEAN LengthMismatch
= FALSE
;
1817 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1819 /* Validate length */
1820 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1822 /* Wrong length, fail */
1823 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
1824 return STATUS_INFO_LENGTH_MISMATCH
;
1827 /* Allocate Buffer */
1828 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1829 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1831 /* Query the name */
1832 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1835 &LocalReturnLength
);
1836 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1838 /* Free the buffer and fail */
1839 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1843 /* Copy the information */
1844 RtlCopyMemory(ObjectNameInfo
,
1846 (LocalReturnLength
> Length
) ?
1847 Length
: LocalReturnLength
);
1849 /* Set buffer pointer */
1850 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1851 ObjectNameInfo
->Name
.Buffer
= p
;
1853 /* Advance in buffer */
1854 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1856 /* Check if this already filled our buffer */
1857 if (LocalReturnLength
> Length
)
1859 /* Set the length mismatch to true, so that we can return
1860 * the proper buffer size to the caller later
1862 LengthMismatch
= TRUE
;
1864 /* Save the initial buffer length value */
1865 *ReturnLength
= LocalReturnLength
;
1868 /* Now get the file name buffer and check the length needed */
1869 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1870 FileLength
= Length
-
1872 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1874 /* Query the File name */
1875 Status
= IoQueryFileInformation(FileObject
,
1876 FileNameInformation
,
1877 LengthMismatch
? Length
: FileLength
,
1879 &LocalReturnLength
);
1880 if (NT_ERROR(Status
))
1882 /* Fail on errors only, allow warnings */
1883 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1887 /* If the provided buffer is too small, return the required size */
1890 /* Add the required length */
1891 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1893 /* Free the allocated buffer and return failure */
1894 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1895 return STATUS_BUFFER_OVERFLOW
;
1898 /* Now calculate the new lengths left */
1899 FileLength
= LocalReturnLength
-
1900 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1901 LocalReturnLength
= (ULONG
)((ULONG_PTR
)p
-
1902 (ULONG_PTR
)ObjectNameInfo
+
1903 LocalFileInfo
->FileNameLength
);
1905 /* Write the Name and null-terminate it */
1906 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1907 p
+= (FileLength
/ sizeof(WCHAR
));
1909 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1911 /* Return the length needed */
1912 *ReturnLength
= LocalReturnLength
;
1914 /* Setup the length and maximum length */
1915 FileLength
= (ULONG
)((ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
);
1916 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1917 sizeof(OBJECT_NAME_INFORMATION
);
1918 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1919 sizeof(UNICODE_NULL
);
1921 /* Free buffer and return */
1922 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1928 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1929 IN PVOID ObjectBody
,
1930 IN ACCESS_MASK GrantedAccess
,
1931 IN ULONG HandleCount
,
1932 IN ULONG SystemHandleCount
)
1934 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1937 PIO_STACK_LOCATION StackPtr
;
1939 PDEVICE_OBJECT DeviceObject
;
1941 IO_STATUS_BLOCK IoStatusBlock
;
1942 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1944 /* If this isn't the last handle for the current process, quit */
1945 if (HandleCount
!= 1) return;
1947 /* Check if the file is locked and has more then one handle opened */
1948 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1950 /* Check if this is a direct open or not */
1951 if (BooleanFlagOn(FileObject
->Flags
, FO_DIRECT_DEVICE_OPEN
))
1953 /* Get the attached device */
1954 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1958 /* Get the FO's device */
1959 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1962 /* Check if this is a sync FO and lock it */
1963 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
1965 IopLockFileObject(FileObject
);
1968 /* Go the FastIO path if possible, otherwise fall back to IRP */
1969 if (DeviceObject
->DriverObject
->FastIoDispatch
== NULL
||
1970 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoUnlockAll
== NULL
||
1971 !DeviceObject
->DriverObject
->FastIoDispatch
->FastIoUnlockAll(FileObject
, PsGetCurrentProcess(), &IoStatusBlock
, DeviceObject
))
1973 /* Clear and set up Events */
1974 KeClearEvent(&FileObject
->Event
);
1975 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1977 /* Allocate an IRP */
1978 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
1981 Irp
->UserEvent
= &Event
;
1982 Irp
->UserIosb
= &Irp
->IoStatus
;
1983 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1984 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1985 Irp
->RequestorMode
= KernelMode
;
1986 Irp
->Flags
= IRP_SYNCHRONOUS_API
;
1987 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1988 ObReferenceObject(FileObject
);
1990 /* Set up Stack Pointer Data */
1991 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1992 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1993 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_ALL
;
1994 StackPtr
->FileObject
= FileObject
;
1997 IopQueueIrpToThread(Irp
);
1999 /* Call the FS Driver */
2000 Status
= IoCallDriver(DeviceObject
, Irp
);
2001 if (Status
== STATUS_PENDING
)
2003 /* Wait for completion */
2004 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
2007 /* IO will unqueue & free for us */
2010 /* Release the lock if we were holding it */
2011 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
2013 IopUnlockFileObject(FileObject
);
2017 /* Make sure this is the last handle */
2018 if (SystemHandleCount
!= 1) return;
2020 /* Check if this is a direct open or not */
2021 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2023 /* Get the attached device */
2024 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2028 /* Get the FO's device */
2029 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2032 /* Set the handle created flag */
2033 FileObject
->Flags
|= FO_HANDLE_CREATED
;
2035 /* Check if this is a sync FO and lock it */
2036 if (Process
!= NULL
&&
2037 BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
2039 IopLockFileObject(FileObject
);
2042 /* Clear and set up Events */
2043 KeClearEvent(&FileObject
->Event
);
2044 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2046 /* Allocate an IRP */
2047 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
2050 Irp
->UserEvent
= &Event
;
2051 Irp
->UserIosb
= &Irp
->IoStatus
;
2052 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2053 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2054 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2055 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
2057 /* Set up Stack Pointer Data */
2058 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2059 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
2060 StackPtr
->FileObject
= FileObject
;
2063 IopQueueIrpToThread(Irp
);
2065 /* Update operation counts */
2066 IopUpdateOperationCount(IopOtherTransfer
);
2068 /* Call the FS Driver */
2069 Status
= IoCallDriver(DeviceObject
, Irp
);
2070 if (Status
== STATUS_PENDING
)
2072 /* Wait for completion */
2073 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
2076 /* Unqueue the IRP */
2077 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2078 IopUnQueueIrpFromThread(Irp
);
2079 KeLowerIrql(OldIrql
);
2084 /* Release the lock if we were holding it */
2085 if (Process
!= NULL
&&
2086 BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
2088 IopUnlockFileObject(FileObject
);
2094 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2095 IN FILE_INFORMATION_CLASS FileInformationClass
,
2096 IN ULONG FileInformationSize
,
2097 OUT PVOID FileInformation
)
2100 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
2101 DUMMY_FILE_OBJECT LocalFileObject
;
2102 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
2104 OPEN_PACKET OpenPacket
;
2107 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
2109 /* Check if the caller was user mode */
2110 if (AccessMode
!= KernelMode
)
2112 /* Protect probe in SEH */
2115 /* Probe the buffer */
2116 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
2118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2120 /* Return the exception code */
2121 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2126 /* Check if this is a basic or full request */
2127 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
2129 /* Setup the Open Packet */
2130 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2131 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2132 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2133 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
2134 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2135 OpenPacket
.Disposition
= FILE_OPEN
;
2136 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
2137 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
2138 (AccessMode
!= KernelMode
) ?
2139 &NetworkOpenInfo
: FileInformation
;
2140 OpenPacket
.QueryOnly
= TRUE
;
2141 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
2142 OpenPacket
.LocalFileObject
= &LocalFileObject
;
2144 /* Update the operation count */
2145 IopUpdateOperationCount(IopOtherTransfer
);
2148 * Attempt opening the file. This will call the I/O Parse Routine for
2149 * the File Object (IopParseDevice) which will use the dummy file obejct
2150 * send the IRP to its device object. Note that we have two statuses
2151 * to worry about: the Object Manager's status (in Status) and the I/O
2152 * status, which is in the Open Packet's Final Status, and determined
2153 * by the Parse Check member.
2155 Status
= ObOpenObjectByName(ObjectAttributes
,
2159 FILE_READ_ATTRIBUTES
,
2162 if (OpenPacket
.ParseCheck
== FALSE
)
2165 DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
2166 ObjectAttributes
->ObjectName
, Status
);
2171 /* Use the Io status */
2172 Status
= OpenPacket
.FinalStatus
;
2175 /* Check if we were succesful and this was user mode and a full query */
2176 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
2178 /* Enter SEH for copy */
2181 /* Copy the buffer back */
2182 RtlCopyMemory(FileInformation
,
2184 FileInformationSize
);
2186 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2188 /* Get exception code */
2189 Status
= _SEH2_GetExceptionCode();
2200 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject
)
2202 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2205 /* FIXME: return NULL for the moment ~ */
2214 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject
,
2215 IN PVOID FilterContext
,
2218 if (!(FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
))
2220 return STATUS_INVALID_PARAMETER
;
2225 return STATUS_NOT_IMPLEMENTED
;
2230 IopCreateFile(OUT PHANDLE FileHandle
,
2231 IN ACCESS_MASK DesiredAccess
,
2232 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2233 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2234 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2235 IN ULONG FileAttributes
,
2236 IN ULONG ShareAccess
,
2237 IN ULONG Disposition
,
2238 IN ULONG CreateOptions
,
2239 IN PVOID EaBuffer OPTIONAL
,
2241 IN CREATE_FILE_TYPE CreateFileType
,
2242 IN PVOID ExtraCreateParameters OPTIONAL
,
2245 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2247 KPROCESSOR_MODE AccessMode
;
2248 HANDLE LocalHandle
= 0;
2249 LARGE_INTEGER SafeAllocationSize
;
2250 NTSTATUS Status
= STATUS_SUCCESS
;
2251 PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters
;
2252 POPEN_PACKET OpenPacket
;
2253 ULONG EaErrorOffset
;
2256 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2259 /* Check if we have no parameter checking to do */
2260 if (Options
& IO_NO_PARAMETER_CHECKING
)
2262 /* Then force kernel-mode access to avoid checks */
2263 AccessMode
= KernelMode
;
2267 /* Otherwise, use the actual mode */
2268 AccessMode
= ExGetPreviousMode();
2271 /* Check if we need to do parameter checking */
2272 if ((AccessMode
!= KernelMode
) || (Options
& IO_CHECK_CREATE_PARAMETERS
))
2274 /* Validate parameters */
2275 if (FileAttributes
& ~FILE_ATTRIBUTE_VALID_FLAGS
)
2277 DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n");
2278 return STATUS_INVALID_PARAMETER
;
2281 if (ShareAccess
& ~FILE_SHARE_VALID_FLAGS
)
2283 DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n");
2284 return STATUS_INVALID_PARAMETER
;
2287 if (Disposition
> FILE_MAXIMUM_DISPOSITION
)
2289 DPRINT1("File Create 'Disposition' Parameter is out of range!\n");
2290 return STATUS_INVALID_PARAMETER
;
2293 if (CreateOptions
& ~FILE_VALID_OPTION_FLAGS
)
2295 DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n");
2296 return STATUS_INVALID_PARAMETER
;
2299 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
)) &&
2300 (!(DesiredAccess
& SYNCHRONIZE
)))
2302 DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n");
2303 return STATUS_INVALID_PARAMETER
;
2306 if ((CreateOptions
& FILE_DELETE_ON_CLOSE
) && (!(DesiredAccess
& DELETE
)))
2308 DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n");
2309 return STATUS_INVALID_PARAMETER
;
2312 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
)) ==
2313 (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
))
2315 DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n");
2316 return STATUS_INVALID_PARAMETER
;
2319 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
2320 (CreateOptions
& ~(FILE_DIRECTORY_FILE
|
2321 FILE_SYNCHRONOUS_IO_ALERT
|
2322 FILE_SYNCHRONOUS_IO_NONALERT
|
2323 FILE_WRITE_THROUGH
|
2324 FILE_COMPLETE_IF_OPLOCKED
|
2325 FILE_OPEN_FOR_BACKUP_INTENT
|
2326 FILE_DELETE_ON_CLOSE
|
2327 FILE_OPEN_FOR_FREE_SPACE_QUERY
|
2328 FILE_OPEN_BY_FILE_ID
|
2329 FILE_NO_COMPRESSION
|
2330 FILE_OPEN_REPARSE_POINT
)))
2332 DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n");
2333 return STATUS_INVALID_PARAMETER
;
2336 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
2337 (Disposition
!= FILE_CREATE
) && (Disposition
!= FILE_OPEN
) && (Disposition
!= FILE_OPEN_IF
))
2339 DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n");
2340 return STATUS_INVALID_PARAMETER
;
2343 if ((CreateOptions
& FILE_COMPLETE_IF_OPLOCKED
) && (CreateOptions
& FILE_RESERVE_OPFILTER
))
2345 DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n");
2346 return STATUS_INVALID_PARAMETER
;
2349 if ((CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
) && (DesiredAccess
& FILE_APPEND_DATA
))
2351 DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n");
2352 return STATUS_INVALID_PARAMETER
;
2355 /* Now check if this is a named pipe */
2356 if (CreateFileType
== CreateFileTypeNamedPipe
)
2358 /* Make sure we have extra parameters */
2359 if (!ExtraCreateParameters
)
2361 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
2362 return STATUS_INVALID_PARAMETER
;
2365 /* Get the parameters and validate them */
2366 NamedPipeCreateParameters
= ExtraCreateParameters
;
2367 if ((NamedPipeCreateParameters
->NamedPipeType
> FILE_PIPE_MESSAGE_TYPE
) ||
2368 (NamedPipeCreateParameters
->ReadMode
> FILE_PIPE_MESSAGE_MODE
) ||
2369 (NamedPipeCreateParameters
->CompletionMode
> FILE_PIPE_COMPLETE_OPERATION
) ||
2370 (ShareAccess
& FILE_SHARE_DELETE
) ||
2371 ((Disposition
< FILE_OPEN
) || (Disposition
> FILE_OPEN_IF
)) ||
2372 (CreateOptions
& ~FILE_VALID_PIPE_OPTION_FLAGS
))
2374 /* Invalid named pipe create */
2375 DPRINT1("Invalid named pipe create\n");
2376 return STATUS_INVALID_PARAMETER
;
2379 else if (CreateFileType
== CreateFileTypeMailslot
)
2381 /* Make sure we have extra parameters */
2382 if (!ExtraCreateParameters
)
2384 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
2385 return STATUS_INVALID_PARAMETER
;
2388 /* Get the parameters and validate them */
2389 if ((ShareAccess
& FILE_SHARE_DELETE
) ||
2390 !(ShareAccess
& ~FILE_SHARE_WRITE
) ||
2391 (Disposition
!= FILE_CREATE
) ||
2392 (CreateOptions
& ~FILE_VALID_MAILSLOT_OPTION_FLAGS
))
2394 /* Invalid mailslot create */
2395 DPRINT1("Invalid mailslot create\n");
2396 return STATUS_INVALID_PARAMETER
;
2401 /* Allocate the open packet */
2402 OpenPacket
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*OpenPacket
), 'pOoI');
2403 if (!OpenPacket
) return STATUS_INSUFFICIENT_RESOURCES
;
2404 RtlZeroMemory(OpenPacket
, sizeof(*OpenPacket
));
2406 /* Check if the call came from user mode */
2407 if (AccessMode
!= KernelMode
)
2411 /* Probe the output parameters */
2412 ProbeForWriteHandle(FileHandle
);
2413 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2415 /* Probe the allocation size if one was passed in */
2418 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
2422 SafeAllocationSize
.QuadPart
= 0;
2425 /* Make sure it's valid */
2426 if (SafeAllocationSize
.QuadPart
< 0)
2428 RtlRaiseStatus(STATUS_INVALID_PARAMETER
);
2431 /* Check if EA was passed in */
2432 if ((EaBuffer
) && (EaLength
))
2435 ProbeForRead(EaBuffer
, EaLength
, sizeof(ULONG
));
2437 /* And marshall it */
2438 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2441 OpenPacket
->EaLength
= EaLength
;
2442 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
2444 /* Validate the buffer */
2445 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
2448 if (!NT_SUCCESS(Status
))
2450 /* Undo everything if it's invalid */
2451 DPRINT1("Invalid EA buffer\n");
2452 IoStatusBlock
->Status
= Status
;
2453 IoStatusBlock
->Information
= EaErrorOffset
;
2454 RtlRaiseStatus(Status
);
2458 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2460 /* Return the exception code */
2461 if (OpenPacket
->EaBuffer
!= NULL
) ExFreePool(OpenPacket
->EaBuffer
);
2462 ExFreePool(OpenPacket
);
2463 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2469 /* Check if this is a device attach */
2470 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
2472 /* Set the flag properly */
2473 Options
|= IO_ATTACH_DEVICE
;
2474 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
2477 /* Check if we have allocation size */
2481 SafeAllocationSize
= *AllocationSize
;
2485 /* Otherwise, no size */
2486 SafeAllocationSize
.QuadPart
= 0;
2489 /* Check if we have an EA packet */
2490 if ((EaBuffer
) && (EaLength
))
2492 /* Allocate the kernel copy */
2493 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2496 if (!OpenPacket
->EaBuffer
)
2498 ExFreePool(OpenPacket
);
2499 DPRINT1("Failed to allocate open packet EA buffer\n");
2500 return STATUS_INSUFFICIENT_RESOURCES
;
2504 OpenPacket
->EaLength
= EaLength
;
2505 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
2507 /* Validate the buffer */
2508 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
2511 if (!NT_SUCCESS(Status
))
2513 /* Undo everything if it's invalid */
2514 DPRINT1("Invalid EA buffer\n");
2515 ExFreePool(OpenPacket
->EaBuffer
);
2516 IoStatusBlock
->Status
= Status
;
2517 IoStatusBlock
->Information
= EaErrorOffset
;
2518 ExFreePool(OpenPacket
);
2524 /* Setup the Open Packet */
2525 OpenPacket
->Type
= IO_TYPE_OPEN_PACKET
;
2526 OpenPacket
->Size
= sizeof(*OpenPacket
);
2527 OpenPacket
->AllocationSize
= SafeAllocationSize
;
2528 OpenPacket
->CreateOptions
= CreateOptions
;
2529 OpenPacket
->FileAttributes
= (USHORT
)FileAttributes
;
2530 OpenPacket
->ShareAccess
= (USHORT
)ShareAccess
;
2531 OpenPacket
->Options
= Options
;
2532 OpenPacket
->Disposition
= Disposition
;
2533 OpenPacket
->CreateFileType
= CreateFileType
;
2534 OpenPacket
->ExtraCreateParameters
= ExtraCreateParameters
;
2535 OpenPacket
->InternalFlags
= Flags
;
2536 OpenPacket
->TopDeviceObjectHint
= DeviceObject
;
2538 /* Update the operation count */
2539 IopUpdateOperationCount(IopOtherTransfer
);
2542 * Attempt opening the file. This will call the I/O Parse Routine for
2543 * the File Object (IopParseDevice) which will create the object and
2544 * send the IRP to its device object. Note that we have two statuses
2545 * to worry about: the Object Manager's status (in Status) and the I/O
2546 * status, which is in the Open Packet's Final Status, and determined
2547 * by the Parse Check member.
2549 Status
= ObOpenObjectByName(ObjectAttributes
,
2557 /* Free the EA Buffer */
2558 if (OpenPacket
->EaBuffer
) ExFreePool(OpenPacket
->EaBuffer
);
2560 /* Now check for Ob or Io failure */
2561 if (!(NT_SUCCESS(Status
)) || (OpenPacket
->ParseCheck
== FALSE
))
2563 /* Check if Ob thinks well went well */
2564 if (NT_SUCCESS(Status
))
2567 * Tell it otherwise. Because we didn't use an ObjectType,
2568 * it incorrectly returned us a handle to God knows what.
2570 ZwClose(LocalHandle
);
2571 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
2574 /* Now check the Io status */
2575 if (!NT_SUCCESS(OpenPacket
->FinalStatus
))
2577 /* Use this status instead of Ob's */
2578 Status
= OpenPacket
->FinalStatus
;
2580 /* Check if it was only a warning */
2581 if (NT_WARNING(Status
))
2583 /* Protect write with SEH */
2586 /* In this case, we copy the I/O Status back */
2587 IoStatusBlock
->Information
= OpenPacket
->Information
;
2588 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2590 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2592 /* Get exception code */
2593 Status
= _SEH2_GetExceptionCode();
2598 else if ((OpenPacket
->FileObject
) && (OpenPacket
->ParseCheck
== FALSE
))
2601 * This can happen in the very bizarre case where the parse routine
2602 * actually executed more then once (due to a reparse) and ended
2603 * up failing after already having created the File Object.
2605 if (OpenPacket
->FileObject
->FileName
.Length
)
2607 /* It had a name, free it */
2608 ExFreePoolWithTag(OpenPacket
->FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
2611 /* Clear the device object to invalidate the FO, and dereference */
2612 OpenPacket
->FileObject
->DeviceObject
= NULL
;
2613 ObDereferenceObject(OpenPacket
->FileObject
);
2618 /* We reached success and have a valid file handle */
2619 OpenPacket
->FileObject
->Flags
|= FO_HANDLE_CREATED
;
2620 ASSERT(OpenPacket
->FileObject
->Type
== IO_TYPE_FILE
);
2622 /* Enter SEH for write back */
2625 /* Write back the handle and I/O Status */
2626 *FileHandle
= LocalHandle
;
2627 IoStatusBlock
->Information
= OpenPacket
->Information
;
2628 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2630 /* Get the Io status */
2631 Status
= OpenPacket
->FinalStatus
;
2633 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2635 /* Get the exception status */
2636 Status
= _SEH2_GetExceptionCode();
2641 /* Check if we were 100% successful */
2642 if ((OpenPacket
->ParseCheck
!= FALSE
) && (OpenPacket
->FileObject
))
2644 /* Dereference the File Object */
2645 ObDereferenceObject(OpenPacket
->FileObject
);
2649 ExFreePool(OpenPacket
);
2653 /* FUNCTIONS *****************************************************************/
2660 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
2662 IN BOOLEAN SetOperation
)
2665 return STATUS_NOT_IMPLEMENTED
;
2673 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
2674 IN ULONG QuotaLength
,
2675 OUT PULONG ErrorOffset
)
2678 return STATUS_NOT_IMPLEMENTED
;
2686 IoCreateFile(OUT PHANDLE FileHandle
,
2687 IN ACCESS_MASK DesiredAccess
,
2688 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2689 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2690 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2691 IN ULONG FileAttributes
,
2692 IN ULONG ShareAccess
,
2693 IN ULONG Disposition
,
2694 IN ULONG CreateOptions
,
2695 IN PVOID EaBuffer OPTIONAL
,
2697 IN CREATE_FILE_TYPE CreateFileType
,
2698 IN PVOID ExtraCreateParameters OPTIONAL
,
2703 return IopCreateFile(FileHandle
,
2715 ExtraCreateParameters
,
2726 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
2727 IN ACCESS_MASK DesiredAccess
,
2728 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2729 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2730 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2731 IN ULONG FileAttributes
,
2732 IN ULONG ShareAccess
,
2733 IN ULONG Disposition
,
2734 IN ULONG CreateOptions
,
2735 IN PVOID EaBuffer OPTIONAL
,
2737 IN CREATE_FILE_TYPE CreateFileType
,
2738 IN PVOID ExtraCreateParameters OPTIONAL
,
2740 IN PVOID DeviceObject
)
2746 /* Check if we were passed a device to send the create request to*/
2749 /* We'll tag this request into a file object extension */
2750 Flags
= (IOP_CREATE_FILE_OBJECT_EXTENSION
| IOP_USE_TOP_LEVEL_DEVICE_HINT
);
2753 return IopCreateFile(FileHandle
,
2765 ExtraCreateParameters
,
2766 Options
| IO_NO_PARAMETER_CHECKING
,
2776 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
2777 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
2778 OUT PHANDLE FileObjectHandle OPTIONAL
)
2780 PFILE_OBJECT CreatedFileObject
;
2783 OBJECT_ATTRIBUTES ObjectAttributes
;
2785 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2787 /* Choose Device Object */
2788 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2790 /* Reference the device object and initialize attributes */
2791 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2792 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2794 /* Create the File Object */
2795 Status
= ObCreateObject(KernelMode
,
2800 sizeof(FILE_OBJECT
),
2801 sizeof(FILE_OBJECT
),
2803 (PVOID
*)&CreatedFileObject
);
2804 if (!NT_SUCCESS(Status
))
2807 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2808 ExRaiseStatus(Status
);
2811 /* Set File Object Data */
2812 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2813 CreatedFileObject
->DeviceObject
= DeviceObject
;
2814 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2815 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2816 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2818 /* Initialize the wait event */
2819 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2821 /* Insert it to create a handle for it */
2822 Status
= ObInsertObject(CreatedFileObject
,
2826 (PVOID
*)&CreatedFileObject
,
2828 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2830 /* Set the handle created flag */
2831 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2832 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2834 /* Check if we have a VPB */
2835 if (DeviceObject
->Vpb
)
2838 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2841 /* Check if the caller wants the handle */
2842 if (FileObjectHandle
)
2845 *FileObjectHandle
= FileHandle
;
2846 ObDereferenceObject(CreatedFileObject
);
2850 /* Otherwise, close it */
2851 ObCloseHandle(FileHandle
, KernelMode
);
2854 /* Return the file object */
2855 return CreatedFileObject
;
2863 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2864 IN PDEVICE_OBJECT DeviceObject
)
2866 /* Call the newer function */
2867 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2875 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2876 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2878 PFILE_OBJECT CreatedFileObject
;
2880 OBJECT_ATTRIBUTES ObjectAttributes
;
2882 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2884 /* Choose Device Object */
2885 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2887 /* Reference the device object and initialize attributes */
2888 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2889 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2891 /* Create the File Object */
2892 Status
= ObCreateObject(KernelMode
,
2897 sizeof(FILE_OBJECT
),
2898 sizeof(FILE_OBJECT
),
2900 (PVOID
*)&CreatedFileObject
);
2901 if (!NT_SUCCESS(Status
))
2904 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2905 ExRaiseStatus(Status
);
2908 /* Set File Object Data */
2909 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2910 CreatedFileObject
->DeviceObject
= DeviceObject
;
2911 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2912 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2913 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2915 /* Initialize the wait event */
2916 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2918 /* Destroy create information */
2919 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2921 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2923 /* Set the handle created flag */
2924 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2925 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2927 /* Check if we have a VPB */
2928 if (DeviceObject
->Vpb
)
2931 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2934 /* Return the file object */
2935 return CreatedFileObject
;
2943 IoGetFileObjectGenericMapping(VOID
)
2945 /* Return the mapping */
2946 return &IopFileMapping
;
2954 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2956 /* Return the flag status */
2957 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2965 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2966 IN ACCESS_MASK DesiredAccess
,
2967 IN ULONG OpenOptions
,
2968 OUT PIO_STATUS_BLOCK IoStatus
,
2969 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2972 DUMMY_FILE_OBJECT LocalFileObject
;
2974 OPEN_PACKET OpenPacket
;
2976 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2978 /* Setup the Open Packet */
2979 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2980 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2981 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2982 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2983 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2984 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2985 OpenPacket
.Disposition
= FILE_OPEN
;
2986 OpenPacket
.NetworkInformation
= Buffer
;
2987 OpenPacket
.QueryOnly
= TRUE
;
2988 OpenPacket
.FullAttributes
= TRUE
;
2989 OpenPacket
.LocalFileObject
= &LocalFileObject
;
2992 * Attempt opening the file. This will call the I/O Parse Routine for
2993 * the File Object (IopParseDevice) which will use the dummy file obejct
2994 * send the IRP to its device object. Note that we have two statuses
2995 * to worry about: the Object Manager's status (in Status) and the I/O
2996 * status, which is in the Open Packet's Final Status, and determined
2997 * by the Parse Check member.
2999 Status
= ObOpenObjectByName(ObjectAttributes
,
3006 if (OpenPacket
.ParseCheck
== FALSE
)
3009 IoStatus
->Status
= Status
;
3013 /* Use the Io status */
3014 IoStatus
->Status
= OpenPacket
.FinalStatus
;
3015 IoStatus
->Information
= OpenPacket
.Information
;
3018 /* Return success */
3027 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
3028 OUT PSHARE_ACCESS ShareAccess
)
3032 /* Check if the file has an extension */
3033 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
3035 /* Check if caller specified to ignore access checks */
3036 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3038 /* Don't update share access */
3043 /* Otherwise, check if there's any access present */
3044 if ((FileObject
->ReadAccess
) ||
3045 (FileObject
->WriteAccess
) ||
3046 (FileObject
->DeleteAccess
))
3048 /* Increase the open count */
3049 ShareAccess
->OpenCount
++;
3051 /* Add new share access */
3052 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
3053 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
3054 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
3055 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
3056 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
3057 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
3066 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
3067 IN ULONG DesiredShareAccess
,
3068 IN PFILE_OBJECT FileObject
,
3069 IN PSHARE_ACCESS ShareAccess
,
3073 BOOLEAN WriteAccess
;
3074 BOOLEAN DeleteAccess
;
3076 BOOLEAN SharedWrite
;
3077 BOOLEAN SharedDelete
;
3080 /* Get access masks */
3081 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
3082 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
3083 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
3085 /* Set them in the file object */
3086 FileObject
->ReadAccess
= ReadAccess
;
3087 FileObject
->WriteAccess
= WriteAccess
;
3088 FileObject
->DeleteAccess
= DeleteAccess
;
3090 /* Check if the file has an extension */
3091 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
3093 /* Check if caller specified to ignore access checks */
3094 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3096 /* Don't check share access */
3097 return STATUS_SUCCESS
;
3101 /* Check if we have any access */
3102 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
3104 /* Get shared access masks */
3105 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
3106 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
3107 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
3110 FileObject
->SharedRead
= SharedRead
;
3111 FileObject
->SharedWrite
= SharedWrite
;
3112 FileObject
->SharedDelete
= SharedDelete
;
3114 /* Check if the shared access is violated */
3116 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
3118 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
3120 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
3121 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
3122 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
3123 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
3125 /* Sharing violation, fail */
3126 return STATUS_SHARING_VIOLATION
;
3129 /* It's not, check if caller wants us to update it */
3132 /* Increase open count */
3133 ShareAccess
->OpenCount
++;
3135 /* Update shared access */
3136 ShareAccess
->Readers
+= ReadAccess
;
3137 ShareAccess
->Writers
+= WriteAccess
;
3138 ShareAccess
->Deleters
+= DeleteAccess
;
3139 ShareAccess
->SharedRead
+= SharedRead
;
3140 ShareAccess
->SharedWrite
+= SharedWrite
;
3141 ShareAccess
->SharedDelete
+= SharedDelete
;
3145 /* Validation successful */
3146 return STATUS_SUCCESS
;
3154 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
3155 IN PSHARE_ACCESS ShareAccess
)
3159 /* Check if the file has an extension */
3160 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
3162 /* Check if caller specified to ignore access checks */
3163 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3165 /* Don't update share access */
3170 /* Otherwise, check if there's any access present */
3171 if ((FileObject
->ReadAccess
) ||
3172 (FileObject
->WriteAccess
) ||
3173 (FileObject
->DeleteAccess
))
3175 /* Decrement the open count */
3176 ShareAccess
->OpenCount
--;
3178 /* Remove share access */
3179 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
3180 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
3181 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
3182 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
3183 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
3184 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
3193 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
3194 IN ULONG DesiredShareAccess
,
3195 IN PFILE_OBJECT FileObject
,
3196 OUT PSHARE_ACCESS ShareAccess
)
3199 BOOLEAN WriteAccess
;
3200 BOOLEAN DeleteAccess
;
3202 BOOLEAN SharedWrite
;
3203 BOOLEAN SharedDelete
;
3204 BOOLEAN Update
= TRUE
;
3207 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
3208 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
3209 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
3211 /* Check if the file has an extension */
3212 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
3214 /* Check if caller specified to ignore access checks */
3215 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3217 /* Don't update share access */
3222 /* Update basic access */
3223 FileObject
->ReadAccess
= ReadAccess
;
3224 FileObject
->WriteAccess
= WriteAccess
;
3225 FileObject
->DeleteAccess
= DeleteAccess
;
3227 /* Check if we have no access as all */
3228 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
3230 /* Check if we need to update the structure */
3231 if (!Update
) return;
3233 /* Otherwise, clear data */
3234 ShareAccess
->OpenCount
= 0;
3235 ShareAccess
->Readers
= 0;
3236 ShareAccess
->Writers
= 0;
3237 ShareAccess
->Deleters
= 0;
3238 ShareAccess
->SharedRead
= 0;
3239 ShareAccess
->SharedWrite
= 0;
3240 ShareAccess
->SharedDelete
= 0;
3244 /* Calculate shared access */
3245 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
3246 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
3247 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
3249 /* Set it in the FO */
3250 FileObject
->SharedRead
= SharedRead
;
3251 FileObject
->SharedWrite
= SharedWrite
;
3252 FileObject
->SharedDelete
= SharedDelete
;
3254 /* Check if we need to update the structure */
3255 if (!Update
) return;
3257 /* Otherwise, set data */
3258 ShareAccess
->OpenCount
= 1;
3259 ShareAccess
->Readers
= ReadAccess
;
3260 ShareAccess
->Writers
= WriteAccess
;
3261 ShareAccess
->Deleters
= DeleteAccess
;
3262 ShareAccess
->SharedRead
= SharedRead
;
3263 ShareAccess
->SharedWrite
= SharedWrite
;
3264 ShareAccess
->SharedDelete
= SharedDelete
;
3273 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
3274 IN PFILE_OBJECT FileObject
)
3280 PIO_STACK_LOCATION Stack
;
3282 /* Check if handles were already created for the
3283 * open file. If so, that's over.
3285 if (FileObject
->Flags
& FO_HANDLE_CREATED
)
3286 KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN
,
3287 (ULONG_PTR
)FileObject
,
3288 (ULONG_PTR
)DeviceObject
, 0, 0);
3290 /* Reset the events */
3291 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3292 KeClearEvent(&FileObject
->Event
);
3294 /* Allocate the IRP we'll use */
3295 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
3296 /* Properly set it */
3297 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3298 Irp
->UserEvent
= &Event
;
3299 Irp
->UserIosb
= &Irp
->IoStatus
;
3300 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3301 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3302 Irp
->RequestorMode
= KernelMode
;
3303 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
3305 Stack
= IoGetNextIrpStackLocation(Irp
);
3306 Stack
->MajorFunction
= IRP_MJ_CLEANUP
;
3307 Stack
->FileObject
= FileObject
;
3309 /* Put on top of IRPs list of the thread */
3310 IopQueueIrpToThread(Irp
);
3312 /* Call the driver */
3313 Status
= IoCallDriver(DeviceObject
, Irp
);
3314 if (Status
== STATUS_PENDING
)
3316 KeWaitForSingleObject(&Event
, UserRequest
,
3317 KernelMode
, FALSE
, NULL
);
3320 /* Remove from IRPs list */
3321 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3322 IopUnQueueIrpFromThread(Irp
);
3323 KeLowerIrql(OldIrql
);
3328 /* Clear the event */
3329 KeClearEvent(&FileObject
->Event
);
3330 /* And finally, mark the open operation as canceled */
3331 FileObject
->Flags
|= FO_FILE_OPEN_CANCELLED
;
3339 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
3340 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
3343 return STATUS_NOT_IMPLEMENTED
;
3351 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
3354 NTSTATUS Status
= STATUS_SUCCESS
;
3357 /* Get the flag status */
3358 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
3360 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
3361 if (Remote
&& !FlagSet
)
3364 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
3366 else if (!Remote
&& FlagSet
)
3368 /* Remove the flag */
3369 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
3374 Status
= STATUS_INVALID_PARAMETER_MIX
;
3386 NtCreateFile(PHANDLE FileHandle
,
3387 ACCESS_MASK DesiredAccess
,
3388 POBJECT_ATTRIBUTES ObjectAttributes
,
3389 PIO_STATUS_BLOCK IoStatusBlock
,
3390 PLARGE_INTEGER AllocateSize
,
3391 ULONG FileAttributes
,
3393 ULONG CreateDisposition
,
3394 ULONG CreateOptions
,
3398 /* Call the I/O Function */
3399 return IoCreateFile(FileHandle
,
3417 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
3418 IN ACCESS_MASK DesiredAccess
,
3419 IN POBJECT_ATTRIBUTES ObjectAttributes
,
3420 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3421 IN ULONG CreateOptions
,
3422 IN ULONG MailslotQuota
,
3423 IN ULONG MaxMessageSize
,
3424 IN PLARGE_INTEGER TimeOut
)
3426 MAILSLOT_CREATE_PARAMETERS Buffer
;
3429 /* Check for Timeout */
3432 /* check if the call came from user mode */
3433 if (KeGetPreviousMode() != KernelMode
)
3435 /* Enter SEH for Probe */
3438 /* Probe the timeout */
3439 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
3441 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3443 /* Return the exception code */
3444 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3450 /* Otherwise, capture directly */
3451 Buffer
.ReadTimeout
= *TimeOut
;
3454 /* Set the correct setting */
3455 Buffer
.TimeoutSpecified
= TRUE
;
3459 /* Tell the FSD we don't have a timeout */
3460 Buffer
.TimeoutSpecified
= FALSE
;
3464 Buffer
.MailslotQuota
= MailslotQuota
;
3465 Buffer
.MaximumMessageSize
= MaxMessageSize
;
3468 return IoCreateFile(FileHandle
,
3474 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3479 CreateFileTypeMailslot
,
3486 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
3487 IN ACCESS_MASK DesiredAccess
,
3488 IN POBJECT_ATTRIBUTES ObjectAttributes
,
3489 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3490 IN ULONG ShareAccess
,
3491 IN ULONG CreateDisposition
,
3492 IN ULONG CreateOptions
,
3493 IN ULONG NamedPipeType
,
3495 IN ULONG CompletionMode
,
3496 IN ULONG MaximumInstances
,
3497 IN ULONG InboundQuota
,
3498 IN ULONG OutboundQuota
,
3499 IN PLARGE_INTEGER DefaultTimeout
)
3501 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
3504 /* Check for Timeout */
3507 /* check if the call came from user mode */
3508 if (KeGetPreviousMode() != KernelMode
)
3510 /* Enter SEH for Probe */
3513 /* Probe the timeout */
3514 Buffer
.DefaultTimeout
=
3515 ProbeForReadLargeInteger(DefaultTimeout
);
3517 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3519 /* Return the exception code */
3520 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3526 /* Otherwise, capture directly */
3527 Buffer
.DefaultTimeout
= *DefaultTimeout
;
3530 /* Set the correct setting */
3531 Buffer
.TimeoutSpecified
= TRUE
;
3535 /* Tell the FSD we don't have a timeout */
3536 Buffer
.TimeoutSpecified
= FALSE
;
3540 Buffer
.NamedPipeType
= NamedPipeType
;
3541 Buffer
.ReadMode
= ReadMode
;
3542 Buffer
.CompletionMode
= CompletionMode
;
3543 Buffer
.MaximumInstances
= MaximumInstances
;
3544 Buffer
.InboundQuota
= InboundQuota
;
3545 Buffer
.OutboundQuota
= OutboundQuota
;
3548 return IoCreateFile(FileHandle
,
3559 CreateFileTypeNamedPipe
,
3566 NtFlushWriteBuffer(VOID
)
3570 /* Call the kernel */
3571 KeFlushWriteBuffer();
3572 return STATUS_SUCCESS
;
3580 NtOpenFile(OUT PHANDLE FileHandle
,
3581 IN ACCESS_MASK DesiredAccess
,
3582 IN POBJECT_ATTRIBUTES ObjectAttributes
,
3583 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3584 IN ULONG ShareAccess
,
3585 IN ULONG OpenOptions
)
3587 /* Call the I/O Function */
3588 return IoCreateFile(FileHandle
,
3606 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
3607 OUT PFILE_BASIC_INFORMATION FileInformation
)
3609 /* Call the internal helper API */
3610 return IopQueryAttributesFile(ObjectAttributes
,
3611 FileBasicInformation
,
3612 sizeof(FILE_BASIC_INFORMATION
),
3618 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
3619 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
3621 /* Call the internal helper API */
3622 return IopQueryAttributesFile(ObjectAttributes
,
3623 FileNetworkOpenInformation
,
3624 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
3629 * @name NtCancelIoFile
3631 * Cancel all pending I/O operations in the current thread for specified
3635 * Handle to file object to cancel requests for. No specific
3636 * access rights are needed.
3637 * @param IoStatusBlock
3638 * Pointer to status block which is filled with final completition
3639 * status on successful return.
3647 NtCancelIoFile(IN HANDLE FileHandle
,
3648 OUT PIO_STATUS_BLOCK IoStatusBlock
)
3650 PFILE_OBJECT FileObject
;
3654 BOOLEAN OurIrpsInList
= FALSE
;
3655 LARGE_INTEGER Interval
;
3656 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3658 PLIST_ENTRY ListHead
, NextEntry
;
3660 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3662 /* Check the previous mode */
3663 if (PreviousMode
!= KernelMode
)
3665 /* Enter SEH for probing */
3668 /* Probe the I/O Status Block */
3669 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3671 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3673 /* Return the exception code */
3674 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3679 /* Reference the file object */
3680 Status
= ObReferenceObjectByHandle(FileHandle
,
3684 (PVOID
*)&FileObject
,
3686 if (!NT_SUCCESS(Status
)) return Status
;
3688 /* IRP cancellations are synchronized at APC_LEVEL. */
3689 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3691 /* Get the current thread */
3692 Thread
= PsGetCurrentThread();
3694 /* Update the operation counts */
3695 IopUpdateOperationCount(IopOtherTransfer
);
3698 ListHead
= &Thread
->IrpList
;
3699 NextEntry
= ListHead
->Flink
;
3700 while (ListHead
!= NextEntry
)
3702 /* Get the IRP and check if the File Object matches */
3703 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3704 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3706 /* Cancel this IRP and keep looping */
3708 OurIrpsInList
= TRUE
;
3711 /* Go to the next entry */
3712 NextEntry
= NextEntry
->Flink
;
3715 /* Lower the IRQL */
3716 KeLowerIrql(OldIrql
);
3718 /* Check if we had found an IRP */
3721 /* Setup a 10ms wait */
3722 Interval
.QuadPart
= -100000;
3725 while (OurIrpsInList
)
3728 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
3729 OurIrpsInList
= FALSE
;
3732 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3734 /* Now loop the list again */
3735 NextEntry
= ListHead
->Flink
;
3736 while (NextEntry
!= ListHead
)
3738 /* Get the IRP and check if the File Object matches */
3739 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3740 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3743 OurIrpsInList
= TRUE
;
3747 /* Go to the next entry */
3748 NextEntry
= NextEntry
->Flink
;
3751 /* Lower the IRQL */
3752 KeLowerIrql(OldIrql
);
3756 /* Enter SEH for writing back the I/O Status */
3760 IoStatusBlock
->Status
= STATUS_SUCCESS
;
3761 IoStatusBlock
->Information
= 0;
3763 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3765 /* Ignore exception */
3769 /* Dereference the file object and return success */
3770 ObDereferenceObject(FileObject
);
3771 return STATUS_SUCCESS
;
3779 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
3782 DUMMY_FILE_OBJECT LocalFileObject
;
3784 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
3785 OPEN_PACKET OpenPacket
;
3787 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
3789 /* Setup the Open Packet */
3790 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
3791 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
3792 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
3793 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
3794 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
3797 OpenPacket
.Disposition
= FILE_OPEN
;
3798 OpenPacket
.DeleteOnly
= TRUE
;
3799 OpenPacket
.LocalFileObject
= &LocalFileObject
;
3801 /* Update the operation counts */
3802 IopUpdateOperationCount(IopOtherTransfer
);
3805 * Attempt opening the file. This will call the I/O Parse Routine for
3806 * the File Object (IopParseDevice) which will use the dummy file obejct
3807 * send the IRP to its device object. Note that we have two statuses
3808 * to worry about: the Object Manager's status (in Status) and the I/O
3809 * status, which is in the Open Packet's Final Status, and determined
3810 * by the Parse Check member.
3812 Status
= ObOpenObjectByName(ObjectAttributes
,
3819 if (OpenPacket
.ParseCheck
== FALSE
) return Status
;
3821 /* Retrn the Io status */
3822 return OpenPacket
.FinalStatus
;