2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/file.c
5 * PURPOSE: Functions that deal with managing the FILE_OBJECT itself.
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 * Filip Navara (navaraf@reactos.org)
12 /* INCLUDES *****************************************************************/
18 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 PEXTENDED_IO_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
);
593 /* The device object is the one we were given */
594 DeviceObject
= OriginalDeviceObject
;
596 /* Check if it has a VPB */
597 if ((OriginalDeviceObject
->Vpb
) && !(DirectOpen
))
599 /* Check if the VPB is mounted, and mount it */
600 Vpb
= IopCheckVpbMounted(OpenPacket
,
601 OriginalDeviceObject
,
604 if (!Vpb
) return Status
;
606 /* Get the VPB's device object */
607 DeviceObject
= Vpb
->DeviceObject
;
610 /* Check if there's an attached device */
611 if (DeviceObject
->AttachedDevice
)
613 /* Get the attached device */
614 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
618 /* If we traversed a mount point, reset the information */
619 if (OpenPacket
->TraversedMountPoint
)
621 OpenPacket
->TraversedMountPoint
= FALSE
;
624 /* Check if this is a secure FSD */
625 if ((DeviceObject
->Characteristics
& FILE_DEVICE_SECURE_OPEN
) &&
626 ((OpenPacket
->RelatedFileObject
) || (RemainingName
->Length
)) &&
629 DPRINT("Fix Secure FSD support!!!\n");
632 /* Allocate the IRP */
633 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
636 /* Dereference the device and VPB, then fail */
637 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
638 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
639 return STATUS_INSUFFICIENT_RESOURCES
;
642 /* Now set the IRP data */
643 Irp
->RequestorMode
= AccessMode
;
644 Irp
->Flags
= IRP_CREATE_OPERATION
| IRP_SYNCHRONOUS_API
| IRP_DEFER_IO_COMPLETION
;
645 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
646 Irp
->UserIosb
= &IoStatusBlock
;
647 Irp
->MdlAddress
= NULL
;
648 Irp
->PendingReturned
= FALSE
;
649 Irp
->UserEvent
= NULL
;
651 Irp
->CancelRoutine
= NULL
;
652 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
654 /* Setup the security context */
655 SecurityContext
.SecurityQos
= SecurityQos
;
656 SecurityContext
.AccessState
= AccessState
;
657 SecurityContext
.DesiredAccess
= AccessState
->RemainingDesiredAccess
;
658 SecurityContext
.FullCreateOptions
= OpenPacket
->CreateOptions
;
660 /* Get the I/O Stack location */
661 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
662 StackLoc
->Control
= 0;
664 /* Check what kind of file this is */
665 switch (OpenPacket
->CreateFileType
)
668 case CreateFileTypeNone
:
670 /* Set the major function and EA Length */
671 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
672 StackLoc
->Parameters
.Create
.EaLength
= OpenPacket
->EaLength
;
675 StackLoc
->Flags
= (UCHAR
)OpenPacket
->Options
;
676 StackLoc
->Flags
|= !(Attributes
& OBJ_CASE_INSENSITIVE
) ? SL_CASE_SENSITIVE
: 0;
680 case CreateFileTypeNamedPipe
:
682 /* Set the named pipe MJ and set the parameters */
683 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
684 StackLoc
->Parameters
.CreatePipe
.Parameters
= OpenPacket
->ExtraCreateParameters
;
688 case CreateFileTypeMailslot
:
690 /* Set the mailslot MJ and set the parameters */
691 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
692 StackLoc
->Parameters
.CreateMailslot
.Parameters
= OpenPacket
->ExtraCreateParameters
;
696 /* Set the common data */
697 Irp
->Overlay
.AllocationSize
= OpenPacket
->AllocationSize
;
698 Irp
->AssociatedIrp
.SystemBuffer
= OpenPacket
->EaBuffer
;
699 StackLoc
->Parameters
.Create
.Options
= (OpenPacket
->Disposition
<< 24) |
700 (OpenPacket
->CreateOptions
&
702 StackLoc
->Parameters
.Create
.FileAttributes
= OpenPacket
->FileAttributes
;
703 StackLoc
->Parameters
.Create
.ShareAccess
= OpenPacket
->ShareAccess
;
704 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
706 /* Check if we really need to create an object */
709 /* Create the actual file object */
710 InitializeObjectAttributes(&ObjectAttributes
,
715 Status
= ObCreateObject(KernelMode
,
723 (PVOID
*)&FileObject
);
724 if (!NT_SUCCESS(Status
))
726 /* Create failed, free the IRP */
729 /* Dereference the device and VPB */
730 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
731 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
733 /* We failed, return status */
734 OpenPacket
->FinalStatus
= Status
;
738 /* Clear the file object */
739 RtlZeroMemory(FileObject
, sizeof(FILE_OBJECT
));
741 /* Check if this is Synch I/O */
742 if (OpenPacket
->CreateOptions
&
743 (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
745 /* Set the synch flag */
746 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
748 /* Check if it's also alertable */
749 if (OpenPacket
->CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
751 /* It is, set the alertable flag */
752 FileObject
->Flags
|= FO_ALERTABLE_IO
;
756 /* Check if this is synch I/O */
757 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
759 /* Initialize the event */
760 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, FALSE
);
763 /* Check if the caller requested no intermediate buffering */
764 if (OpenPacket
->CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
766 /* Set the correct flag for the FSD to read */
767 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
770 /* Check if the caller requested write through support */
771 if (OpenPacket
->CreateOptions
& FILE_WRITE_THROUGH
)
773 /* Set the correct flag for the FSD to read */
774 FileObject
->Flags
|= FO_WRITE_THROUGH
;
777 /* Check if the caller says the file will be only read sequentially */
778 if (OpenPacket
->CreateOptions
& FILE_SEQUENTIAL_ONLY
)
780 /* Set the correct flag for the FSD to read */
781 FileObject
->Flags
|= FO_SEQUENTIAL_ONLY
;
784 /* Check if the caller believes the file will be only read randomly */
785 if (OpenPacket
->CreateOptions
& FILE_RANDOM_ACCESS
)
787 /* Set the correct flag for the FSD to read */
788 FileObject
->Flags
|= FO_RANDOM_ACCESS
;
793 /* Use the dummy object instead */
794 LocalFileObject
= OpenPacket
->LocalFileObject
;
795 RtlZeroMemory(LocalFileObject
, sizeof(DUMMY_FILE_OBJECT
));
798 FileObject
= (PFILE_OBJECT
)&LocalFileObject
->ObjectHeader
.Body
;
799 LocalFileObject
->ObjectHeader
.Type
= IoFileObjectType
;
800 LocalFileObject
->ObjectHeader
.PointerCount
= 1;
803 /* Setup the file header */
804 FileObject
->Type
= IO_TYPE_FILE
;
805 FileObject
->Size
= sizeof(FILE_OBJECT
);
806 FileObject
->RelatedFileObject
= OpenPacket
->RelatedFileObject
;
807 FileObject
->DeviceObject
= OriginalDeviceObject
;
809 /* Check if this is a direct device open */
810 if (DirectOpen
) FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
812 /* Check if the caller wants case sensitivity */
813 if (!(Attributes
& OBJ_CASE_INSENSITIVE
))
815 /* Tell the driver about it */
816 FileObject
->Flags
|= FO_OPENED_CASE_SENSITIVE
;
819 /* Now set the file object */
820 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
821 StackLoc
->FileObject
= FileObject
;
823 /* Check if the file object has a name */
824 if (RemainingName
->Length
)
826 /* Setup the unicode string */
827 FileObject
->FileName
.MaximumLength
= RemainingName
->Length
+
829 FileObject
->FileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
834 if (!FileObject
->FileName
.Buffer
)
836 /* Failed to allocate the name, free the IRP */
839 /* Dereference the device object and VPB */
840 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
841 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
843 /* Clear the FO and dereference it */
844 FileObject
->DeviceObject
= NULL
;
845 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
848 return STATUS_INSUFFICIENT_RESOURCES
;
853 RtlCopyUnicodeString(&FileObject
->FileName
, RemainingName
);
855 /* Initialize the File Object event and set the FO */
856 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
857 OpenPacket
->FileObject
= FileObject
;
859 /* Queue the IRP and call the driver */
860 IopQueueIrpToThread(Irp
);
861 Status
= IoCallDriver(DeviceObject
, Irp
);
862 if (Status
== STATUS_PENDING
)
864 /* Wait for the driver to complete the create */
865 KeWaitForSingleObject(&FileObject
->Event
,
871 /* Get the new status */
872 Status
= IoStatusBlock
.Status
;
876 /* We'll have to complete it ourselves */
877 ASSERT(!Irp
->PendingReturned
);
878 ASSERT(!Irp
->MdlAddress
);
880 /* Handle name change if required */
881 if (Status
== STATUS_REPARSE
)
883 /* Check this is a mount point */
884 if (Irp
->IoStatus
.Information
== IO_REPARSE_TAG_MOUNT_POINT
)
886 PREPARSE_DATA_BUFFER ReparseData
;
888 /* Reparse point attributes were passed by the driver in the auxiliary buffer */
889 ASSERT(Irp
->Tail
.Overlay
.AuxiliaryBuffer
!= NULL
);
890 ReparseData
= (PREPARSE_DATA_BUFFER
)Irp
->Tail
.Overlay
.AuxiliaryBuffer
;
892 ASSERT(ReparseData
->ReparseTag
== IO_REPARSE_TAG_MOUNT_POINT
);
893 ASSERT(ReparseData
->ReparseDataLength
< MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
894 ASSERT(ReparseData
->Reserved
< MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
896 IopDoNameTransmogrify(Irp
, FileObject
, ReparseData
);
900 /* Completion happens at APC_LEVEL */
901 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
903 /* Get the new I/O Status block ourselves */
904 IoStatusBlock
= Irp
->IoStatus
;
905 Status
= IoStatusBlock
.Status
;
907 /* Manually signal the even, we can't have any waiters */
908 FileObject
->Event
.Header
.SignalState
= 1;
910 /* Now that we've signaled the events, de-associate the IRP */
911 IopUnQueueIrpFromThread(Irp
);
913 /* Check if the IRP had an input buffer */
914 if ((Irp
->Flags
& IRP_BUFFERED_IO
) &&
915 (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
))
917 /* Free it. A driver might've tacked one on */
918 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
921 /* Free the IRP and bring the IRQL back down */
923 KeLowerIrql(OldIrql
);
926 /* Copy the I/O Status */
927 OpenPacket
->Information
= IoStatusBlock
.Information
;
929 /* The driver failed to create the file */
930 if (!NT_SUCCESS(Status
))
932 /* Check if we have a name */
933 if (FileObject
->FileName
.Length
)
936 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
937 FileObject
->FileName
.Length
= 0;
940 /* Clear its device object */
941 FileObject
->DeviceObject
= NULL
;
943 /* Save this now because the FO might go away */
944 OpenCancelled
= FileObject
->Flags
& FO_FILE_OPEN_CANCELLED
?
947 /* Clear the file object in the open packet */
948 OpenPacket
->FileObject
= NULL
;
950 /* Dereference the file object */
951 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
953 /* Dereference the device object */
954 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
956 /* Unless the driver cancelled the open, dereference the VPB */
957 if (!(OpenCancelled
) && (Vpb
)) IopDereferenceVpbAndFree(Vpb
);
959 /* Set the status and return */
960 OpenPacket
->FinalStatus
= Status
;
963 else if (Status
== STATUS_REPARSE
)
965 if (OpenPacket
->Information
== IO_REPARSE
||
966 OpenPacket
->Information
== IO_REPARSE_TAG_MOUNT_POINT
)
968 /* Update CompleteName with reparse info which got updated in IopDoNameTransmogrify() */
969 if (CompleteName
->MaximumLength
< FileObject
->FileName
.Length
)
971 PWSTR NewCompleteName
;
973 /* Allocate a new buffer for the string */
974 NewCompleteName
= ExAllocatePoolWithTag(PagedPool
, FileObject
->FileName
.Length
, TAG_IO_NAME
);
975 if (NewCompleteName
== NULL
)
977 OpenPacket
->FinalStatus
= STATUS_INSUFFICIENT_RESOURCES
;
978 return STATUS_INSUFFICIENT_RESOURCES
;
981 /* Release the old one */
982 if (CompleteName
->Buffer
!= NULL
)
984 ExFreePoolWithTag(CompleteName
->Buffer
, 0);
987 /* And setup the new one */
988 CompleteName
->Buffer
= NewCompleteName
;
989 CompleteName
->MaximumLength
= FileObject
->FileName
.Length
;
992 /* Copy our new complete name */
993 RtlCopyUnicodeString(CompleteName
, &FileObject
->FileName
);
995 if (OpenPacket
->Information
== IO_REPARSE_TAG_MOUNT_POINT
)
997 OpenPacket
->RelatedFileObject
= NULL
;
1001 /* Check if we have a name */
1002 if (FileObject
->FileName
.Length
)
1005 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, 0);
1006 FileObject
->FileName
.Length
= 0;
1009 /* Clear its device object */
1010 FileObject
->DeviceObject
= NULL
;
1012 /* Clear the file object in the open packet */
1013 OpenPacket
->FileObject
= NULL
;
1015 /* Dereference the file object */
1016 if (!UseDummyFile
) ObDereferenceObject(FileObject
);
1018 /* Dereference the device object */
1019 IopDereferenceDeviceObject(OriginalDeviceObject
, FALSE
);
1021 /* Unless the driver cancelled the open, dereference the VPB */
1022 if (Vpb
!= NULL
) IopDereferenceVpbAndFree(Vpb
);
1024 if (OpenPacket
->Information
!= IO_REMOUNT
)
1026 OpenPacket
->RelatedFileObject
= NULL
;
1028 /* Inform we traversed a mount point for later attempt */
1029 if (OpenPacket
->Information
== IO_REPARSE_TAG_MOUNT_POINT
)
1031 OpenPacket
->TraversedMountPoint
= 1;
1034 /* In case we override checks, but got this on volume open, fail hard */
1035 if (OpenPacket
->Override
)
1037 KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN
,
1038 (ULONG_PTR
)OriginalDeviceObject
,
1039 (ULONG_PTR
)DeviceObject
,
1040 (ULONG_PTR
)CompleteName
,
1041 OpenPacket
->Information
);
1044 /* Return to IO/OB so that information can be upgraded */
1045 return STATUS_REPARSE
;
1048 /* Loop again and reattempt an opening */
1055 if (Attempt
== IOP_MAX_REPARSE_TRAVERSAL
)
1056 return STATUS_UNSUCCESSFUL
;
1058 /* Get the owner of the File Object */
1059 OwnerDevice
= IoGetRelatedDeviceObject(FileObject
);
1062 * It's possible that the device to whom we sent the IRP to
1063 * isn't actually the device that ended opening the file object
1066 if (OwnerDevice
!= DeviceObject
)
1068 /* We have to de-reference the VPB we had associated */
1069 if (Vpb
) IopDereferenceVpbAndFree(Vpb
);
1071 /* And re-associate with the actual one */
1072 Vpb
= FileObject
->Vpb
;
1073 if (Vpb
) InterlockedIncrement((PLONG
)&Vpb
->ReferenceCount
);
1076 /* Make sure we are not using a dummy */
1079 /* Check if this was a volume open */
1080 if ((!(FileObject
->RelatedFileObject
) ||
1081 (FileObject
->RelatedFileObject
->Flags
& FO_VOLUME_OPEN
)) &&
1082 !(FileObject
->FileName
.Length
))
1084 /* All signs point to it, but make sure it was actually an FSD */
1085 if ((OwnerDevice
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
1086 (OwnerDevice
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
1087 (OwnerDevice
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
) ||
1088 (OwnerDevice
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
))
1090 /* The owner device is an FSD, so this is a volume open for real */
1091 FileObject
->Flags
|= FO_VOLUME_OPEN
;
1095 /* Reference the object and set the parse check */
1096 ObReferenceObject(FileObject
);
1097 *Object
= FileObject
;
1098 OpenPacket
->FinalStatus
= IoStatusBlock
.Status
;
1099 OpenPacket
->ParseCheck
= TRUE
;
1100 return OpenPacket
->FinalStatus
;
1104 /* Check if this was a query */
1105 if (OpenPacket
->QueryOnly
)
1107 /* Check if the caller wants basic info only */
1108 if (!OpenPacket
->FullAttributes
)
1110 /* Allocate the buffer */
1111 FileBasicInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1112 sizeof(*FileBasicInfo
),
1117 Status
= IoQueryFileInformation(FileObject
,
1118 FileBasicInformation
,
1119 sizeof(*FileBasicInfo
),
1122 if (NT_SUCCESS(Status
))
1125 RtlCopyMemory(OpenPacket
->BasicInformation
,
1130 /* Free our buffer */
1131 ExFreePoolWithTag(FileBasicInfo
, TAG_IO
);
1136 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1141 /* This is a full query */
1142 Status
= IoQueryFileInformation(
1144 FileNetworkOpenInformation
,
1145 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
1146 OpenPacket
->NetworkInformation
,
1148 if (!NT_SUCCESS(Status
)) ASSERT(Status
!= STATUS_NOT_IMPLEMENTED
);
1152 /* Delete the file object */
1153 IopDeleteFile(FileObject
);
1155 /* Clear out the file */
1156 OpenPacket
->FileObject
= NULL
;
1158 /* Set and return status */
1159 OpenPacket
->FinalStatus
= Status
;
1160 OpenPacket
->ParseCheck
= TRUE
;
1167 IopParseFile(IN PVOID ParseObject
,
1168 IN PVOID ObjectType
,
1169 IN OUT PACCESS_STATE AccessState
,
1170 IN KPROCESSOR_MODE AccessMode
,
1171 IN ULONG Attributes
,
1172 IN OUT PUNICODE_STRING CompleteName
,
1173 IN OUT PUNICODE_STRING RemainingName
,
1174 IN OUT PVOID Context OPTIONAL
,
1175 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL
,
1179 POPEN_PACKET OpenPacket
= (POPEN_PACKET
)Context
;
1181 /* Validate the open packet */
1182 if (!IopValidateOpenPacket(OpenPacket
)) return STATUS_OBJECT_TYPE_MISMATCH
;
1184 /* Get the device object */
1185 DeviceObject
= IoGetRelatedDeviceObject(ParseObject
);
1186 OpenPacket
->RelatedFileObject
= ParseObject
;
1188 /* Call the main routine */
1189 return IopParseDevice(DeviceObject
,
1203 IopDeleteFile(IN PVOID ObjectBody
)
1205 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1207 PIO_STACK_LOCATION StackPtr
;
1210 PDEVICE_OBJECT DeviceObject
;
1211 BOOLEAN DereferenceDone
= FALSE
;
1214 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1216 /* Check if the file has a device object */
1217 if (FileObject
->DeviceObject
)
1219 /* Check if this is a direct open or not */
1220 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1222 /* Get the attached device */
1223 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1227 /* Use the file object's device object */
1228 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1232 ASSERT(!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
1233 (InterlockedExchange((PLONG
)&FileObject
->Busy
, TRUE
) == FALSE
));
1235 /* Check if the handle wasn't created yet */
1236 if (!(FileObject
->Flags
& FO_HANDLE_CREATED
))
1238 /* Send the cleanup IRP */
1239 IopCloseFile(NULL
, ObjectBody
, 0, 1, 1);
1242 /* Clear and set up Events */
1243 KeClearEvent(&FileObject
->Event
);
1244 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1246 /* Allocate an IRP */
1247 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1251 Irp
->UserEvent
= &Event
;
1252 Irp
->UserIosb
= &Irp
->IoStatus
;
1253 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1254 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1255 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1257 /* Set up Stack Pointer Data */
1258 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1259 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
1260 StackPtr
->FileObject
= FileObject
;
1263 IopQueueIrpToThread(Irp
);
1265 /* Get the VPB and check if this isn't a direct open */
1266 Vpb
= FileObject
->Vpb
;
1267 if ((Vpb
) && !(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1269 /* Dereference the VPB before the close */
1270 InterlockedDecrement((PLONG
)&Vpb
->ReferenceCount
);
1273 /* Check if the FS will never disappear by itself */
1274 if (FileObject
->DeviceObject
->Flags
& DO_NEVER_LAST_DEVICE
)
1276 /* Dereference it */
1277 InterlockedDecrement(&FileObject
->DeviceObject
->ReferenceCount
);
1278 DereferenceDone
= TRUE
;
1281 /* Call the FS Driver */
1282 Status
= IoCallDriver(DeviceObject
, Irp
);
1283 if (Status
== STATUS_PENDING
)
1285 /* Wait for completion */
1286 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1289 /* De-queue the IRP */
1290 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1291 IopUnQueueIrpFromThread(Irp
);
1292 KeLowerIrql(OldIrql
);
1297 /* Clear the file name */
1298 if (FileObject
->FileName
.Buffer
)
1300 ExFreePoolWithTag(FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
1301 FileObject
->FileName
.Buffer
= NULL
;
1304 /* Check if the FO had a completion port */
1305 if (FileObject
->CompletionContext
)
1308 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
1309 ExFreePool(FileObject
->CompletionContext
);
1312 /* Check if the FO had extension */
1313 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1315 /* Release filter context structure if any */
1316 FsRtlPTeardownPerFileObjectContexts(FileObject
);
1319 /* Check if dereference has been done yet */
1320 if (!DereferenceDone
)
1322 /* Dereference device object */
1323 IopDereferenceDeviceObject(FileObject
->DeviceObject
, FALSE
);
1330 IopGetDeviceAttachmentBase(IN PDEVICE_OBJECT DeviceObject
)
1332 PDEVICE_OBJECT PDO
= DeviceObject
;
1334 /* Go down the stack to attempt to get the PDO */
1335 for (; ((PEXTENDED_DEVOBJ_EXTENSION
)PDO
->DeviceObjectExtension
)->AttachedTo
!= NULL
;
1336 PDO
= ((PEXTENDED_DEVOBJ_EXTENSION
)PDO
->DeviceObjectExtension
)->AttachedTo
);
1343 IopGetDevicePDO(IN PDEVICE_OBJECT DeviceObject
)
1348 ASSERT(DeviceObject
!= NULL
);
1350 OldIrql
= KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock
);
1351 /* Get the base DO */
1352 PDO
= IopGetDeviceAttachmentBase(DeviceObject
);
1353 /* Check whether that's really a PDO and if so, keep it */
1354 if ((PDO
->Flags
& DO_BUS_ENUMERATED_DEVICE
) != DO_BUS_ENUMERATED_DEVICE
)
1360 ObReferenceObject(PDO
);
1362 KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock
, OldIrql
);
1369 IopSetDeviceSecurityDescriptor(IN PDEVICE_OBJECT DeviceObject
,
1370 IN PSECURITY_INFORMATION SecurityInformation
,
1371 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1372 IN POOL_TYPE PoolType
,
1373 IN PGENERIC_MAPPING GenericMapping
)
1376 PSECURITY_DESCRIPTOR OldSecurityDescriptor
, CachedSecurityDescriptor
, NewSecurityDescriptor
;
1380 /* Keep attempting till we find our old SD or fail */
1383 KeEnterCriticalRegion();
1384 ExAcquireResourceSharedLite(&IopSecurityResource
, TRUE
);
1386 /* Get our old SD and reference it */
1387 OldSecurityDescriptor
= DeviceObject
->SecurityDescriptor
;
1388 if (OldSecurityDescriptor
!= NULL
)
1390 ObReferenceSecurityDescriptor(OldSecurityDescriptor
, 1);
1393 ExReleaseResourceLite(&IopSecurityResource
);
1394 KeLeaveCriticalRegion();
1396 /* Set the SD information */
1397 NewSecurityDescriptor
= OldSecurityDescriptor
;
1398 Status
= SeSetSecurityDescriptorInfo(NULL
, SecurityInformation
,
1399 SecurityDescriptor
, &NewSecurityDescriptor
,
1400 PoolType
, GenericMapping
);
1402 if (!NT_SUCCESS(Status
))
1404 if (OldSecurityDescriptor
!= NULL
)
1406 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, 1);
1412 /* Add the new DS to the internal cache */
1413 Status
= ObLogSecurityDescriptor(NewSecurityDescriptor
,
1414 &CachedSecurityDescriptor
, 1);
1415 ExFreePool(NewSecurityDescriptor
);
1416 if (!NT_SUCCESS(Status
))
1418 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, 1);
1422 KeEnterCriticalRegion();
1423 ExAcquireResourceExclusiveLite(&IopSecurityResource
, TRUE
);
1424 /* Check if someone changed it in our back */
1425 if (DeviceObject
->SecurityDescriptor
== OldSecurityDescriptor
)
1427 /* We're clear, do the swap */
1428 DeviceObject
->SecurityDescriptor
= CachedSecurityDescriptor
;
1429 ExReleaseResourceLite(&IopSecurityResource
);
1430 KeLeaveCriticalRegion();
1432 /* And dereference old SD (twice - us + not in use) */
1433 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, 2);
1437 ExReleaseResourceLite(&IopSecurityResource
);
1438 KeLeaveCriticalRegion();
1440 /* If so, try again */
1441 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, 1);
1442 ObDereferenceSecurityDescriptor(CachedSecurityDescriptor
, 1);
1450 IopSetDeviceSecurityDescriptors(IN PDEVICE_OBJECT UpperDeviceObject
,
1451 IN PDEVICE_OBJECT PhysicalDeviceObject
,
1452 IN PSECURITY_INFORMATION SecurityInformation
,
1453 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1454 IN POOL_TYPE PoolType
,
1455 IN PGENERIC_MAPPING GenericMapping
)
1457 PDEVICE_OBJECT CurrentDO
= PhysicalDeviceObject
, NextDevice
;
1458 NTSTATUS Status
= STATUS_SUCCESS
, TmpStatus
;
1462 ASSERT(PhysicalDeviceObject
!= NULL
);
1464 /* We always reference the DO we're working on */
1465 ObReferenceObject(CurrentDO
);
1467 /* Go up from PDO to latest DO */
1470 /* Attempt to set the new SD on it */
1471 TmpStatus
= IopSetDeviceSecurityDescriptor(CurrentDO
, SecurityInformation
,
1472 SecurityDescriptor
, PoolType
,
1474 /* Was our last one? Remember that status then */
1475 if (CurrentDO
== UpperDeviceObject
)
1480 /* Try to move to the next DO (and thus, reference it) */
1481 NextDevice
= CurrentDO
->AttachedDevice
;
1484 ObReferenceObject(NextDevice
);
1487 /* Dereference current DO and move to the next one */
1488 ObDereferenceObject(CurrentDO
);
1489 CurrentDO
= NextDevice
;
1491 while (CurrentDO
!= NULL
);
1498 IopGetSetSecurityObject(IN PVOID ObjectBody
,
1499 IN SECURITY_OPERATION_CODE OperationCode
,
1500 IN PSECURITY_INFORMATION SecurityInformation
,
1501 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1502 IN OUT PULONG BufferLength
,
1503 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
1504 IN POOL_TYPE PoolType
,
1505 IN OUT PGENERIC_MAPPING GenericMapping
)
1507 IO_STATUS_BLOCK IoStatusBlock
;
1508 PIO_STACK_LOCATION StackPtr
;
1509 PFILE_OBJECT FileObject
;
1510 PDEVICE_OBJECT DeviceObject
;
1512 BOOLEAN LocalEvent
= FALSE
;
1514 NTSTATUS Status
= STATUS_SUCCESS
;
1516 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1518 /* Check if this is a device or file */
1519 if (((PFILE_OBJECT
)ObjectBody
)->Type
== IO_TYPE_DEVICE
)
1522 DeviceObject
= (PDEVICE_OBJECT
)ObjectBody
;
1528 FileObject
= (PFILE_OBJECT
)ObjectBody
;
1530 /* Check if this is a direct open */
1531 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1533 /* Get the Device Object */
1534 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1538 /* Otherwise, use the direct device*/
1539 DeviceObject
= FileObject
->DeviceObject
;
1543 /* Check if the request was for a device object */
1544 if (!(FileObject
) ||
1545 (!(FileObject
->FileName
.Length
) && !(FileObject
->RelatedFileObject
)) ||
1546 (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
1548 /* Check what kind of request this was */
1549 if (OperationCode
== QuerySecurityDescriptor
)
1551 return SeQuerySecurityDescriptorInfo(SecurityInformation
,
1554 &DeviceObject
->SecurityDescriptor
);
1556 else if (OperationCode
== DeleteSecurityDescriptor
)
1558 /* Simply return success */
1559 return STATUS_SUCCESS
;
1561 else if (OperationCode
== AssignSecurityDescriptor
)
1563 Status
= STATUS_SUCCESS
;
1565 /* Make absolutely sure this is a device object */
1566 if (!(FileObject
) || !(FileObject
->Flags
& FO_STREAM_FILE
))
1568 PSECURITY_DESCRIPTOR CachedSecurityDescriptor
;
1570 /* Add the security descriptor in cache */
1571 Status
= ObLogSecurityDescriptor(SecurityDescriptor
, &CachedSecurityDescriptor
, 1);
1572 if (NT_SUCCESS(Status
))
1574 KeEnterCriticalRegion();
1575 ExAcquireResourceExclusiveLite(&IopSecurityResource
, TRUE
);
1577 /* Assign the Security Descriptor */
1578 DeviceObject
->SecurityDescriptor
= CachedSecurityDescriptor
;
1580 ExReleaseResourceLite(&IopSecurityResource
);
1581 KeLeaveCriticalRegion();
1588 else if (OperationCode
== SetSecurityDescriptor
)
1590 /* Get the Physical Device Object if any */
1591 PDEVICE_OBJECT PDO
= IopGetDevicePDO(DeviceObject
);
1595 /* Apply the new SD to any DO in the path from PDO to current DO */
1596 Status
= IopSetDeviceSecurityDescriptors(DeviceObject
, PDO
,
1597 SecurityInformation
,
1599 PoolType
, GenericMapping
);
1600 ObDereferenceObject(PDO
);
1604 /* Otherwise, just set for ourselves */
1605 Status
= IopSetDeviceSecurityDescriptor(DeviceObject
,
1606 SecurityInformation
,
1608 PoolType
, GenericMapping
);
1611 return STATUS_SUCCESS
;
1614 /* Shouldn't happen */
1615 return STATUS_SUCCESS
;
1617 else if (OperationCode
== DeleteSecurityDescriptor
)
1619 /* Same as for devices, do nothing */
1620 return STATUS_SUCCESS
;
1623 /* At this point, we know we're a file. Reference it */
1624 ObReferenceObject(FileObject
);
1626 /* Check if we should use Sync IO or not */
1627 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1629 /* Lock the file object */
1630 IopLockFileObject(FileObject
);
1634 /* Use local event */
1635 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1639 /* Clear the File Object event */
1640 KeClearEvent(&FileObject
->Event
);
1642 /* Get the device object */
1643 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1645 /* Allocate the IRP */
1646 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1647 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1650 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1651 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1652 Irp
->RequestorMode
= ExGetPreviousMode();
1653 Irp
->UserIosb
= &IoStatusBlock
;
1654 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1655 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1656 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1658 /* Set Stack Parameters */
1659 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1660 StackPtr
->FileObject
= FileObject
;
1662 /* Check if this is a query or set */
1663 if (OperationCode
== QuerySecurityDescriptor
)
1665 /* Set the major function and parameters */
1666 StackPtr
->MajorFunction
= IRP_MJ_QUERY_SECURITY
;
1667 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
=
1668 *SecurityInformation
;
1669 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
1670 Irp
->UserBuffer
= SecurityDescriptor
;
1674 /* Set the major function and parameters for a set */
1675 StackPtr
->MajorFunction
= IRP_MJ_SET_SECURITY
;
1676 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
=
1677 *SecurityInformation
;
1678 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
=
1683 IopQueueIrpToThread(Irp
);
1685 /* Update operation counts */
1686 IopUpdateOperationCount(IopOtherTransfer
);
1688 /* Call the Driver */
1689 Status
= IoCallDriver(DeviceObject
, Irp
);
1691 /* Check if this was async I/O */
1694 /* Check if the IRP is pending completion */
1695 if (Status
== STATUS_PENDING
)
1697 /* Wait on the local event */
1698 KeWaitForSingleObject(&Event
,
1703 Status
= IoStatusBlock
.Status
;
1708 /* Check if the IRP is pending completion */
1709 if (Status
== STATUS_PENDING
)
1711 /* Wait on the file object */
1712 KeWaitForSingleObject(&FileObject
->Event
,
1717 Status
= FileObject
->FinalStatus
;
1720 /* Release the lock */
1721 IopUnlockFileObject(FileObject
);
1724 /* This Driver doesn't implement Security, so try to give it a default */
1725 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
1727 /* Was this a query? */
1728 if (OperationCode
== QuerySecurityDescriptor
)
1730 /* Set a World Security Descriptor */
1731 Status
= SeSetWorldSecurityDescriptor(*SecurityInformation
,
1737 /* It wasn't a query, so just fake success */
1738 Status
= STATUS_SUCCESS
;
1741 else if (OperationCode
== QuerySecurityDescriptor
)
1743 /* Callers usually expect the normalized form */
1744 if (Status
== STATUS_BUFFER_OVERFLOW
) Status
= STATUS_BUFFER_TOO_SMALL
;
1749 *BufferLength
= (ULONG
)IoStatusBlock
.Information
;
1751 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1753 /* Get the exception code */
1754 Status
= _SEH2_GetExceptionCode();
1765 IopQueryNameFile(IN PVOID ObjectBody
,
1767 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
1769 OUT PULONG ReturnLength
,
1770 IN KPROCESSOR_MODE PreviousMode
)
1772 POBJECT_NAME_INFORMATION LocalInfo
;
1773 PFILE_NAME_INFORMATION LocalFileInfo
;
1774 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1775 ULONG LocalReturnLength
, FileLength
;
1776 BOOLEAN LengthMismatch
= FALSE
;
1779 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1781 /* Validate length */
1782 if (Length
< sizeof(OBJECT_NAME_INFORMATION
))
1784 /* Wrong length, fail */
1785 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
1786 return STATUS_INFO_LENGTH_MISMATCH
;
1789 /* Allocate Buffer */
1790 LocalInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_IO
);
1791 if (!LocalInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
1793 /* Query the name */
1794 Status
= ObQueryNameString(FileObject
->DeviceObject
,
1797 &LocalReturnLength
);
1798 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
1800 /* Free the buffer and fail */
1801 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1805 /* Copy the information */
1806 RtlCopyMemory(ObjectNameInfo
,
1808 (LocalReturnLength
> Length
) ?
1809 Length
: LocalReturnLength
);
1811 /* Set buffer pointer */
1812 p
= (PWCHAR
)(ObjectNameInfo
+ 1);
1813 ObjectNameInfo
->Name
.Buffer
= p
;
1815 /* Advance in buffer */
1816 p
+= (LocalInfo
->Name
.Length
/ sizeof(WCHAR
));
1818 /* Check if this already filled our buffer */
1819 if (LocalReturnLength
> Length
)
1821 /* Set the length mismatch to true, so that we can return
1822 * the proper buffer size to the caller later
1824 LengthMismatch
= TRUE
;
1826 /* Save the initial buffer length value */
1827 *ReturnLength
= LocalReturnLength
;
1830 /* Now get the file name buffer and check the length needed */
1831 LocalFileInfo
= (PFILE_NAME_INFORMATION
)LocalInfo
;
1832 FileLength
= Length
-
1834 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1836 /* Query the File name */
1837 Status
= IoQueryFileInformation(FileObject
,
1838 FileNameInformation
,
1839 LengthMismatch
? Length
: FileLength
,
1841 &LocalReturnLength
);
1842 if (NT_ERROR(Status
))
1844 /* Fail on errors only, allow warnings */
1845 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1849 /* If the provided buffer is too small, return the required size */
1852 /* Add the required length */
1853 *ReturnLength
+= LocalFileInfo
->FileNameLength
;
1855 /* Free the allocated buffer and return failure */
1856 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1857 return STATUS_BUFFER_OVERFLOW
;
1860 /* Now calculate the new lengths left */
1861 FileLength
= LocalReturnLength
-
1862 FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
1863 LocalReturnLength
= (ULONG
)((ULONG_PTR
)p
-
1864 (ULONG_PTR
)ObjectNameInfo
+
1865 LocalFileInfo
->FileNameLength
);
1867 /* Write the Name and null-terminate it */
1868 RtlCopyMemory(p
, LocalFileInfo
->FileName
, FileLength
);
1869 p
+= (FileLength
/ sizeof(WCHAR
));
1871 LocalReturnLength
+= sizeof(UNICODE_NULL
);
1873 /* Return the length needed */
1874 *ReturnLength
= LocalReturnLength
;
1876 /* Setup the length and maximum length */
1877 FileLength
= (ULONG
)((ULONG_PTR
)p
- (ULONG_PTR
)ObjectNameInfo
);
1878 ObjectNameInfo
->Name
.Length
= (USHORT
)FileLength
-
1879 sizeof(OBJECT_NAME_INFORMATION
);
1880 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)ObjectNameInfo
->Name
.Length
+
1881 sizeof(UNICODE_NULL
);
1883 /* Free buffer and return */
1884 ExFreePoolWithTag(LocalInfo
, TAG_IO
);
1890 IopCloseFile(IN PEPROCESS Process OPTIONAL
,
1891 IN PVOID ObjectBody
,
1892 IN ACCESS_MASK GrantedAccess
,
1893 IN ULONG HandleCount
,
1894 IN ULONG SystemHandleCount
)
1896 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
1899 PIO_STACK_LOCATION StackPtr
;
1901 PDEVICE_OBJECT DeviceObject
;
1903 IOTRACE(IO_FILE_DEBUG
, "ObjectBody: %p\n", ObjectBody
);
1905 /* If this isn't the last handle for the current process, quit */
1906 if (HandleCount
!= 1) return;
1908 /* Check if the file is locked and has more then one handle opened */
1909 if ((FileObject
->LockOperation
) && (SystemHandleCount
!= 1))
1911 DPRINT1("We need to unlock this file!\n");
1915 /* Make sure this is the last handle */
1916 if (SystemHandleCount
!= 1) return;
1918 /* Check if this is a direct open or not */
1919 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1921 /* Get the attached device */
1922 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1926 /* Get the FO's device */
1927 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1930 /* Set the handle created flag */
1931 FileObject
->Flags
|= FO_HANDLE_CREATED
;
1933 /* Check if this is a sync FO and lock it */
1934 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopLockFileObject(FileObject
);
1936 /* Clear and set up Events */
1937 KeClearEvent(&FileObject
->Event
);
1938 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1940 /* Allocate an IRP */
1941 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1945 Irp
->UserEvent
= &Event
;
1946 Irp
->UserIosb
= &Irp
->IoStatus
;
1947 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1948 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1949 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1950 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
1952 /* Set up Stack Pointer Data */
1953 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1954 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
1955 StackPtr
->FileObject
= FileObject
;
1958 IopQueueIrpToThread(Irp
);
1960 /* Update operation counts */
1961 IopUpdateOperationCount(IopOtherTransfer
);
1963 /* Call the FS Driver */
1964 Status
= IoCallDriver(DeviceObject
, Irp
);
1965 if (Status
== STATUS_PENDING
)
1967 /* Wait for completion */
1968 KeWaitForSingleObject(&Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
1971 /* Unqueue the IRP */
1972 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1973 IopUnQueueIrpFromThread(Irp
);
1974 KeLowerIrql(OldIrql
);
1979 /* Release the lock if we were holding it */
1980 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
1985 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1986 IN FILE_INFORMATION_CLASS FileInformationClass
,
1987 IN ULONG FileInformationSize
,
1988 OUT PVOID FileInformation
)
1991 KPROCESSOR_MODE AccessMode
= ExGetPreviousMode();
1992 DUMMY_FILE_OBJECT LocalFileObject
;
1993 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo
;
1995 OPEN_PACKET OpenPacket
;
1998 IOTRACE(IO_FILE_DEBUG
, "Class: %lx\n", FileInformationClass
);
2000 /* Check if the caller was user mode */
2001 if (AccessMode
!= KernelMode
)
2003 /* Protect probe in SEH */
2006 /* Probe the buffer */
2007 ProbeForWrite(FileInformation
, FileInformationSize
, sizeof(ULONG
));
2009 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2011 /* Return the exception code */
2012 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2017 /* Check if this is a basic or full request */
2018 IsBasic
= (FileInformationSize
== sizeof(FILE_BASIC_INFORMATION
));
2020 /* Setup the Open Packet */
2021 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2022 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2023 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2024 OpenPacket
.CreateOptions
= FILE_OPEN_REPARSE_POINT
;
2025 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2026 OpenPacket
.Disposition
= FILE_OPEN
;
2027 OpenPacket
.BasicInformation
= IsBasic
? FileInformation
: NULL
;
2028 OpenPacket
.NetworkInformation
= IsBasic
? &NetworkOpenInfo
:
2029 (AccessMode
!= KernelMode
) ?
2030 &NetworkOpenInfo
: FileInformation
;
2031 OpenPacket
.QueryOnly
= TRUE
;
2032 OpenPacket
.FullAttributes
= IsBasic
? FALSE
: TRUE
;
2033 OpenPacket
.LocalFileObject
= &LocalFileObject
;
2035 /* Update the operation count */
2036 IopUpdateOperationCount(IopOtherTransfer
);
2039 * Attempt opening the file. This will call the I/O Parse Routine for
2040 * the File Object (IopParseDevice) which will use the dummy file obejct
2041 * send the IRP to its device object. Note that we have two statuses
2042 * to worry about: the Object Manager's status (in Status) and the I/O
2043 * status, which is in the Open Packet's Final Status, and determined
2044 * by the Parse Check member.
2046 Status
= ObOpenObjectByName(ObjectAttributes
,
2050 FILE_READ_ATTRIBUTES
,
2053 if (OpenPacket
.ParseCheck
!= TRUE
)
2056 DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
2057 ObjectAttributes
->ObjectName
, Status
);
2062 /* Use the Io status */
2063 Status
= OpenPacket
.FinalStatus
;
2066 /* Check if we were succesful and this was user mode and a full query */
2067 if ((NT_SUCCESS(Status
)) && (AccessMode
!= KernelMode
) && !(IsBasic
))
2069 /* Enter SEH for copy */
2072 /* Copy the buffer back */
2073 RtlCopyMemory(FileInformation
,
2075 FileInformationSize
);
2077 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2079 /* Get exception code */
2080 Status
= _SEH2_GetExceptionCode();
2091 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject
)
2093 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2096 /* FIXME: return NULL for the moment ~ */
2105 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject
,
2106 IN PVOID FilterContext
,
2109 if (!(FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
))
2111 return STATUS_INVALID_PARAMETER
;
2116 return STATUS_NOT_IMPLEMENTED
;
2119 /* FUNCTIONS *****************************************************************/
2126 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
2128 IN BOOLEAN SetOperation
)
2131 return STATUS_NOT_IMPLEMENTED
;
2139 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
2140 IN ULONG QuotaLength
,
2141 OUT PULONG ErrorOffset
)
2144 return STATUS_NOT_IMPLEMENTED
;
2152 IoCreateFile(OUT PHANDLE FileHandle
,
2153 IN ACCESS_MASK DesiredAccess
,
2154 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2155 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2156 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2157 IN ULONG FileAttributes
,
2158 IN ULONG ShareAccess
,
2159 IN ULONG Disposition
,
2160 IN ULONG CreateOptions
,
2161 IN PVOID EaBuffer OPTIONAL
,
2163 IN CREATE_FILE_TYPE CreateFileType
,
2164 IN PVOID ExtraCreateParameters OPTIONAL
,
2167 KPROCESSOR_MODE AccessMode
;
2168 HANDLE LocalHandle
= 0;
2169 LARGE_INTEGER SafeAllocationSize
;
2170 NTSTATUS Status
= STATUS_SUCCESS
;
2171 PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters
;
2172 POPEN_PACKET OpenPacket
;
2173 ULONG EaErrorOffset
;
2175 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2178 /* Check if we have no parameter checking to do */
2179 if (Options
& IO_NO_PARAMETER_CHECKING
)
2181 /* Then force kernel-mode access to avoid checks */
2182 AccessMode
= KernelMode
;
2186 /* Otherwise, use the actual mode */
2187 AccessMode
= ExGetPreviousMode();
2190 /* Check if we need to do parameter checking */
2191 if ((AccessMode
!= KernelMode
) || (Options
& IO_CHECK_CREATE_PARAMETERS
))
2193 /* Validate parameters */
2194 if (FileAttributes
& ~FILE_ATTRIBUTE_VALID_FLAGS
)
2196 DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n");
2197 return STATUS_INVALID_PARAMETER
;
2200 if (ShareAccess
& ~FILE_SHARE_VALID_FLAGS
)
2202 DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n");
2203 return STATUS_INVALID_PARAMETER
;
2206 if (Disposition
> FILE_MAXIMUM_DISPOSITION
)
2208 DPRINT1("File Create 'Disposition' Parameter is out of range!\n");
2209 return STATUS_INVALID_PARAMETER
;
2212 if (CreateOptions
& ~FILE_VALID_OPTION_FLAGS
)
2214 DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n");
2215 return STATUS_INVALID_PARAMETER
;
2218 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
)) &&
2219 (!(DesiredAccess
& SYNCHRONIZE
)))
2221 DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n");
2222 return STATUS_INVALID_PARAMETER
;
2225 if ((CreateOptions
& FILE_DELETE_ON_CLOSE
) && (!(DesiredAccess
& DELETE
)))
2227 DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n");
2228 return STATUS_INVALID_PARAMETER
;
2231 if ((CreateOptions
& (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
)) ==
2232 (FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SYNCHRONOUS_IO_ALERT
))
2234 DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n");
2235 return STATUS_INVALID_PARAMETER
;
2238 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
2239 (CreateOptions
& ~(FILE_DIRECTORY_FILE
|
2240 FILE_SYNCHRONOUS_IO_ALERT
|
2241 FILE_SYNCHRONOUS_IO_NONALERT
|
2242 FILE_WRITE_THROUGH
|
2243 FILE_COMPLETE_IF_OPLOCKED
|
2244 FILE_OPEN_FOR_BACKUP_INTENT
|
2245 FILE_DELETE_ON_CLOSE
|
2246 FILE_OPEN_FOR_FREE_SPACE_QUERY
|
2247 FILE_OPEN_BY_FILE_ID
|
2248 FILE_NO_COMPRESSION
|
2249 FILE_OPEN_REPARSE_POINT
)))
2251 DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n");
2252 return STATUS_INVALID_PARAMETER
;
2255 if ((CreateOptions
& FILE_DIRECTORY_FILE
) && !(CreateOptions
& FILE_NON_DIRECTORY_FILE
) &&
2256 (Disposition
!= FILE_CREATE
) && (Disposition
!= FILE_OPEN
) && (Disposition
!= FILE_OPEN_IF
))
2258 DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n");
2259 return STATUS_INVALID_PARAMETER
;
2262 if ((CreateOptions
& FILE_COMPLETE_IF_OPLOCKED
) && (CreateOptions
& FILE_RESERVE_OPFILTER
))
2264 DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n");
2265 return STATUS_INVALID_PARAMETER
;
2268 if ((CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
) && (DesiredAccess
& FILE_APPEND_DATA
))
2270 DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n");
2271 return STATUS_INVALID_PARAMETER
;
2274 /* Now check if this is a named pipe */
2275 if (CreateFileType
== CreateFileTypeNamedPipe
)
2277 /* Make sure we have extra parameters */
2278 if (!ExtraCreateParameters
)
2280 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
2281 return STATUS_INVALID_PARAMETER
;
2284 /* Get the parameters and validate them */
2285 NamedPipeCreateParameters
= ExtraCreateParameters
;
2286 if ((NamedPipeCreateParameters
->NamedPipeType
> FILE_PIPE_MESSAGE_TYPE
) ||
2287 (NamedPipeCreateParameters
->ReadMode
> FILE_PIPE_MESSAGE_MODE
) ||
2288 (NamedPipeCreateParameters
->CompletionMode
> FILE_PIPE_COMPLETE_OPERATION
) ||
2289 (ShareAccess
& FILE_SHARE_DELETE
) ||
2290 ((Disposition
< FILE_OPEN
) || (Disposition
> FILE_OPEN_IF
)) ||
2291 (CreateOptions
& ~FILE_VALID_PIPE_OPTION_FLAGS
))
2293 /* Invalid named pipe create */
2294 DPRINT1("Invalid named pipe create\n");
2295 return STATUS_INVALID_PARAMETER
;
2298 else if (CreateFileType
== CreateFileTypeMailslot
)
2300 /* Make sure we have extra parameters */
2301 if (!ExtraCreateParameters
)
2303 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
2304 return STATUS_INVALID_PARAMETER
;
2307 /* Get the parameters and validate them */
2308 if ((ShareAccess
& FILE_SHARE_DELETE
) ||
2309 !(ShareAccess
& ~FILE_SHARE_WRITE
) ||
2310 (Disposition
!= FILE_CREATE
) ||
2311 (CreateOptions
& ~FILE_VALID_MAILSLOT_OPTION_FLAGS
))
2313 /* Invalid mailslot create */
2314 DPRINT1("Invalid mailslot create\n");
2315 return STATUS_INVALID_PARAMETER
;
2320 /* Allocate the open packet */
2321 OpenPacket
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*OpenPacket
), 'pOoI');
2322 if (!OpenPacket
) return STATUS_INSUFFICIENT_RESOURCES
;
2323 RtlZeroMemory(OpenPacket
, sizeof(*OpenPacket
));
2325 /* Check if the call came from user mode */
2326 if (AccessMode
!= KernelMode
)
2330 /* Probe the output parameters */
2331 ProbeForWriteHandle(FileHandle
);
2332 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2334 /* Probe the allocation size if one was passed in */
2337 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
2341 SafeAllocationSize
.QuadPart
= 0;
2344 /* Make sure it's valid */
2345 if (SafeAllocationSize
.QuadPart
< 0)
2347 RtlRaiseStatus(STATUS_INVALID_PARAMETER
);
2350 /* Check if EA was passed in */
2351 if ((EaBuffer
) && (EaLength
))
2354 ProbeForRead(EaBuffer
, EaLength
, sizeof(ULONG
));
2356 /* And marshall it */
2357 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2360 OpenPacket
->EaLength
= EaLength
;
2361 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
2363 /* Validate the buffer */
2364 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
2367 if (!NT_SUCCESS(Status
))
2369 /* Undo everything if it's invalid */
2370 DPRINT1("Invalid EA buffer\n");
2371 IoStatusBlock
->Status
= Status
;
2372 IoStatusBlock
->Information
= EaErrorOffset
;
2373 RtlRaiseStatus(Status
);
2377 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2379 /* Return the exception code */
2380 if (OpenPacket
->EaBuffer
!= NULL
) ExFreePool(OpenPacket
->EaBuffer
);
2381 ExFreePool(OpenPacket
);
2382 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2388 /* Check if this is a device attach */
2389 if (CreateOptions
& IO_ATTACH_DEVICE_API
)
2391 /* Set the flag properly */
2392 Options
|= IO_ATTACH_DEVICE
;
2393 CreateOptions
&= ~IO_ATTACH_DEVICE_API
;
2396 /* Check if we have allocation size */
2400 SafeAllocationSize
= *AllocationSize
;
2404 /* Otherwise, no size */
2405 SafeAllocationSize
.QuadPart
= 0;
2408 /* Check if we have an EA packet */
2409 if ((EaBuffer
) && (EaLength
))
2411 /* Allocate the kernel copy */
2412 OpenPacket
->EaBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2415 if (!OpenPacket
->EaBuffer
)
2417 ExFreePool(OpenPacket
);
2418 DPRINT1("Failed to allocate open packet EA buffer\n");
2419 return STATUS_INSUFFICIENT_RESOURCES
;
2423 OpenPacket
->EaLength
= EaLength
;
2424 RtlCopyMemory(OpenPacket
->EaBuffer
, EaBuffer
, EaLength
);
2426 /* Validate the buffer */
2427 Status
= IoCheckEaBufferValidity(OpenPacket
->EaBuffer
,
2430 if (!NT_SUCCESS(Status
))
2432 /* Undo everything if it's invalid */
2433 DPRINT1("Invalid EA buffer\n");
2434 ExFreePool(OpenPacket
->EaBuffer
);
2435 IoStatusBlock
->Status
= Status
;
2436 IoStatusBlock
->Information
= EaErrorOffset
;
2437 ExFreePool(OpenPacket
);
2443 /* Setup the Open Packet */
2444 OpenPacket
->Type
= IO_TYPE_OPEN_PACKET
;
2445 OpenPacket
->Size
= sizeof(*OpenPacket
);
2446 OpenPacket
->AllocationSize
= SafeAllocationSize
;
2447 OpenPacket
->CreateOptions
= CreateOptions
;
2448 OpenPacket
->FileAttributes
= (USHORT
)FileAttributes
;
2449 OpenPacket
->ShareAccess
= (USHORT
)ShareAccess
;
2450 OpenPacket
->Options
= Options
;
2451 OpenPacket
->Disposition
= Disposition
;
2452 OpenPacket
->CreateFileType
= CreateFileType
;
2453 OpenPacket
->ExtraCreateParameters
= ExtraCreateParameters
;
2455 /* Update the operation count */
2456 IopUpdateOperationCount(IopOtherTransfer
);
2459 * Attempt opening the file. This will call the I/O Parse Routine for
2460 * the File Object (IopParseDevice) which will create the object and
2461 * send the IRP to its device object. Note that we have two statuses
2462 * to worry about: the Object Manager's status (in Status) and the I/O
2463 * status, which is in the Open Packet's Final Status, and determined
2464 * by the Parse Check member.
2466 Status
= ObOpenObjectByName(ObjectAttributes
,
2474 /* Free the EA Buffer */
2475 if (OpenPacket
->EaBuffer
) ExFreePool(OpenPacket
->EaBuffer
);
2477 /* Now check for Ob or Io failure */
2478 if (!(NT_SUCCESS(Status
)) || (OpenPacket
->ParseCheck
!= TRUE
))
2480 /* Check if Ob thinks well went well */
2481 if (NT_SUCCESS(Status
))
2484 * Tell it otherwise. Because we didn't use an ObjectType,
2485 * it incorrectly returned us a handle to God knows what.
2487 ZwClose(LocalHandle
);
2488 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
2491 /* Now check the Io status */
2492 if (!NT_SUCCESS(OpenPacket
->FinalStatus
))
2494 /* Use this status instead of Ob's */
2495 Status
= OpenPacket
->FinalStatus
;
2497 /* Check if it was only a warning */
2498 if (NT_WARNING(Status
))
2500 /* Protect write with SEH */
2503 /* In this case, we copy the I/O Status back */
2504 IoStatusBlock
->Information
= OpenPacket
->Information
;
2505 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2509 /* Get exception code */
2510 Status
= _SEH2_GetExceptionCode();
2515 else if ((OpenPacket
->FileObject
) && (OpenPacket
->ParseCheck
!= 1))
2518 * This can happen in the very bizarre case where the parse routine
2519 * actually executed more then once (due to a reparse) and ended
2520 * up failing after already having created the File Object.
2522 if (OpenPacket
->FileObject
->FileName
.Length
)
2524 /* It had a name, free it */
2525 ExFreePoolWithTag(OpenPacket
->FileObject
->FileName
.Buffer
, TAG_IO_NAME
);
2528 /* Clear the device object to invalidate the FO, and dereference */
2529 OpenPacket
->FileObject
->DeviceObject
= NULL
;
2530 ObDereferenceObject(OpenPacket
->FileObject
);
2535 /* We reached success and have a valid file handle */
2536 OpenPacket
->FileObject
->Flags
|= FO_HANDLE_CREATED
;
2537 ASSERT(OpenPacket
->FileObject
->Type
== IO_TYPE_FILE
);
2539 /* Enter SEH for write back */
2542 /* Write back the handle and I/O Status */
2543 *FileHandle
= LocalHandle
;
2544 IoStatusBlock
->Information
= OpenPacket
->Information
;
2545 IoStatusBlock
->Status
= OpenPacket
->FinalStatus
;
2547 /* Get the Io status */
2548 Status
= OpenPacket
->FinalStatus
;
2550 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2552 /* Get the exception status */
2553 Status
= _SEH2_GetExceptionCode();
2558 /* Check if we were 100% successful */
2559 if ((OpenPacket
->ParseCheck
!= FALSE
) && (OpenPacket
->FileObject
))
2561 /* Dereference the File Object */
2562 ObDereferenceObject(OpenPacket
->FileObject
);
2566 ExFreePool(OpenPacket
);
2575 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
2576 IN ACCESS_MASK DesiredAccess
,
2577 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2578 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2579 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
2580 IN ULONG FileAttributes
,
2581 IN ULONG ShareAccess
,
2582 IN ULONG Disposition
,
2583 IN ULONG CreateOptions
,
2584 IN PVOID EaBuffer OPTIONAL
,
2586 IN CREATE_FILE_TYPE CreateFileType
,
2587 IN PVOID ExtraCreateParameters OPTIONAL
,
2589 IN PVOID DeviceObject
)
2592 return STATUS_NOT_IMPLEMENTED
;
2600 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
2601 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
2602 OUT PHANDLE FileObjectHandle OPTIONAL
)
2604 PFILE_OBJECT CreatedFileObject
;
2607 OBJECT_ATTRIBUTES ObjectAttributes
;
2609 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2611 /* Choose Device Object */
2612 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2614 /* Reference the device object and initialize attributes */
2615 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2616 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2618 /* Create the File Object */
2619 Status
= ObCreateObject(KernelMode
,
2624 sizeof(FILE_OBJECT
),
2625 sizeof(FILE_OBJECT
),
2627 (PVOID
*)&CreatedFileObject
);
2628 if (!NT_SUCCESS(Status
))
2631 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2632 ExRaiseStatus(Status
);
2635 /* Set File Object Data */
2636 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2637 CreatedFileObject
->DeviceObject
= DeviceObject
;
2638 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2639 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2640 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2642 /* Initialize the wait event */
2643 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2645 /* Insert it to create a handle for it */
2646 Status
= ObInsertObject(CreatedFileObject
,
2650 (PVOID
*)&CreatedFileObject
,
2652 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
2654 /* Set the handle created flag */
2655 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2656 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2658 /* Check if we have a VPB */
2659 if (DeviceObject
->Vpb
)
2662 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2665 /* Check if the caller wants the handle */
2666 if (FileObjectHandle
)
2669 *FileObjectHandle
= FileHandle
;
2670 ObDereferenceObject(CreatedFileObject
);
2674 /* Otherwise, close it */
2675 ObCloseHandle(FileHandle
, KernelMode
);
2678 /* Return the file object */
2679 return CreatedFileObject
;
2687 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject
,
2688 IN PDEVICE_OBJECT DeviceObject
)
2690 /* Call the newer function */
2691 return IoCreateStreamFileObjectEx(FileObject
, DeviceObject
, NULL
);
2699 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
2700 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
2702 PFILE_OBJECT CreatedFileObject
;
2704 OBJECT_ATTRIBUTES ObjectAttributes
;
2706 IOTRACE(IO_FILE_DEBUG
, "FileObject: %p\n", FileObject
);
2708 /* Choose Device Object */
2709 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
2711 /* Reference the device object and initialize attributes */
2712 InterlockedIncrement(&DeviceObject
->ReferenceCount
);
2713 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
2715 /* Create the File Object */
2716 Status
= ObCreateObject(KernelMode
,
2721 sizeof(FILE_OBJECT
),
2722 sizeof(FILE_OBJECT
),
2724 (PVOID
*)&CreatedFileObject
);
2725 if (!NT_SUCCESS(Status
))
2728 IopDereferenceDeviceObject(DeviceObject
, FALSE
);
2729 ExRaiseStatus(Status
);
2732 /* Set File Object Data */
2733 RtlZeroMemory(CreatedFileObject
, sizeof(FILE_OBJECT
));
2734 CreatedFileObject
->DeviceObject
= DeviceObject
;
2735 CreatedFileObject
->Type
= IO_TYPE_FILE
;
2736 CreatedFileObject
->Size
= sizeof(FILE_OBJECT
);
2737 CreatedFileObject
->Flags
= FO_STREAM_FILE
;
2739 /* Initialize the wait event */
2740 KeInitializeEvent(&CreatedFileObject
->Event
, SynchronizationEvent
, FALSE
);
2742 /* Destroy create information */
2743 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->
2745 OBJECT_TO_OBJECT_HEADER(CreatedFileObject
)->ObjectCreateInfo
= NULL
;
2747 /* Set the handle created flag */
2748 CreatedFileObject
->Flags
|= FO_HANDLE_CREATED
;
2749 ASSERT(CreatedFileObject
->Type
== IO_TYPE_FILE
);
2751 /* Check if we have a VPB */
2752 if (DeviceObject
->Vpb
)
2755 InterlockedIncrement((PLONG
)&DeviceObject
->Vpb
->ReferenceCount
);
2758 /* Return the file object */
2759 return CreatedFileObject
;
2767 IoGetFileObjectGenericMapping(VOID
)
2769 /* Return the mapping */
2770 return &IopFileMapping
;
2778 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
2780 /* Return the flag status */
2781 return FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
2789 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2790 IN ACCESS_MASK DesiredAccess
,
2791 IN ULONG OpenOptions
,
2792 OUT PIO_STATUS_BLOCK IoStatus
,
2793 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
)
2796 DUMMY_FILE_OBJECT LocalFileObject
;
2798 OPEN_PACKET OpenPacket
;
2800 IOTRACE(IO_FILE_DEBUG
, "FileName: %wZ\n", ObjectAttributes
->ObjectName
);
2802 /* Setup the Open Packet */
2803 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
2804 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
2805 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
2806 OpenPacket
.CreateOptions
= OpenOptions
| FILE_OPEN_REPARSE_POINT
;
2807 OpenPacket
.ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
2808 OpenPacket
.Options
= IO_FORCE_ACCESS_CHECK
;
2809 OpenPacket
.Disposition
= FILE_OPEN
;
2810 OpenPacket
.NetworkInformation
= Buffer
;
2811 OpenPacket
.QueryOnly
= TRUE
;
2812 OpenPacket
.FullAttributes
= TRUE
;
2813 OpenPacket
.LocalFileObject
= &LocalFileObject
;
2816 * Attempt opening the file. This will call the I/O Parse Routine for
2817 * the File Object (IopParseDevice) which will use the dummy file obejct
2818 * send the IRP to its device object. Note that we have two statuses
2819 * to worry about: the Object Manager's status (in Status) and the I/O
2820 * status, which is in the Open Packet's Final Status, and determined
2821 * by the Parse Check member.
2823 Status
= ObOpenObjectByName(ObjectAttributes
,
2830 if (OpenPacket
.ParseCheck
== FALSE
)
2833 IoStatus
->Status
= Status
;
2837 /* Use the Io status */
2838 IoStatus
->Status
= OpenPacket
.FinalStatus
;
2839 IoStatus
->Information
= OpenPacket
.Information
;
2842 /* Return success */
2851 IoUpdateShareAccess(IN PFILE_OBJECT FileObject
,
2852 OUT PSHARE_ACCESS ShareAccess
)
2856 /* Check if the file has an extension */
2857 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2859 /* Check if caller specified to ignore access checks */
2860 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2862 /* Don't update share access */
2867 /* Otherwise, check if there's any access present */
2868 if ((FileObject
->ReadAccess
) ||
2869 (FileObject
->WriteAccess
) ||
2870 (FileObject
->DeleteAccess
))
2872 /* Increase the open count */
2873 ShareAccess
->OpenCount
++;
2875 /* Add new share access */
2876 ShareAccess
->Readers
+= FileObject
->ReadAccess
;
2877 ShareAccess
->Writers
+= FileObject
->WriteAccess
;
2878 ShareAccess
->Deleters
+= FileObject
->DeleteAccess
;
2879 ShareAccess
->SharedRead
+= FileObject
->SharedRead
;
2880 ShareAccess
->SharedWrite
+= FileObject
->SharedWrite
;
2881 ShareAccess
->SharedDelete
+= FileObject
->SharedDelete
;
2890 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess
,
2891 IN ULONG DesiredShareAccess
,
2892 IN PFILE_OBJECT FileObject
,
2893 IN PSHARE_ACCESS ShareAccess
,
2897 BOOLEAN WriteAccess
;
2898 BOOLEAN DeleteAccess
;
2900 BOOLEAN SharedWrite
;
2901 BOOLEAN SharedDelete
;
2904 /* Get access masks */
2905 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
2906 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
2907 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
2909 /* Set them in the file object */
2910 FileObject
->ReadAccess
= ReadAccess
;
2911 FileObject
->WriteAccess
= WriteAccess
;
2912 FileObject
->DeleteAccess
= DeleteAccess
;
2914 /* Check if the file has an extension */
2915 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2917 /* Check if caller specified to ignore access checks */
2918 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2920 /* Don't check share access */
2921 return STATUS_SUCCESS
;
2925 /* Check if we have any access */
2926 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
2928 /* Get shared access masks */
2929 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
2930 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
2931 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
2934 FileObject
->SharedRead
= SharedRead
;
2935 FileObject
->SharedWrite
= SharedWrite
;
2936 FileObject
->SharedDelete
= SharedDelete
;
2938 /* Check if the shared access is violated */
2940 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
2942 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
2944 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
2945 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
2946 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
2947 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
2949 /* Sharing violation, fail */
2950 return STATUS_SHARING_VIOLATION
;
2953 /* It's not, check if caller wants us to update it */
2956 /* Increase open count */
2957 ShareAccess
->OpenCount
++;
2959 /* Update shared access */
2960 ShareAccess
->Readers
+= ReadAccess
;
2961 ShareAccess
->Writers
+= WriteAccess
;
2962 ShareAccess
->Deleters
+= DeleteAccess
;
2963 ShareAccess
->SharedRead
+= SharedRead
;
2964 ShareAccess
->SharedWrite
+= SharedWrite
;
2965 ShareAccess
->SharedDelete
+= SharedDelete
;
2969 /* Validation successful */
2970 return STATUS_SUCCESS
;
2978 IoRemoveShareAccess(IN PFILE_OBJECT FileObject
,
2979 IN PSHARE_ACCESS ShareAccess
)
2983 /* Check if the file has an extension */
2984 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
2986 /* Check if caller specified to ignore access checks */
2987 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
2989 /* Don't update share access */
2994 /* Otherwise, check if there's any access present */
2995 if ((FileObject
->ReadAccess
) ||
2996 (FileObject
->WriteAccess
) ||
2997 (FileObject
->DeleteAccess
))
2999 /* Decrement the open count */
3000 ShareAccess
->OpenCount
--;
3002 /* Remove share access */
3003 ShareAccess
->Readers
-= FileObject
->ReadAccess
;
3004 ShareAccess
->Writers
-= FileObject
->WriteAccess
;
3005 ShareAccess
->Deleters
-= FileObject
->DeleteAccess
;
3006 ShareAccess
->SharedRead
-= FileObject
->SharedRead
;
3007 ShareAccess
->SharedWrite
-= FileObject
->SharedWrite
;
3008 ShareAccess
->SharedDelete
-= FileObject
->SharedDelete
;
3017 IoSetShareAccess(IN ACCESS_MASK DesiredAccess
,
3018 IN ULONG DesiredShareAccess
,
3019 IN PFILE_OBJECT FileObject
,
3020 OUT PSHARE_ACCESS ShareAccess
)
3023 BOOLEAN WriteAccess
;
3024 BOOLEAN DeleteAccess
;
3026 BOOLEAN SharedWrite
;
3027 BOOLEAN SharedDelete
;
3028 BOOLEAN Update
= TRUE
;
3031 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
3032 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
3033 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
3035 /* Check if the file has an extension */
3036 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
3038 /* Check if caller specified to ignore access checks */
3039 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3041 /* Don't update share access */
3046 /* Update basic access */
3047 FileObject
->ReadAccess
= ReadAccess
;
3048 FileObject
->WriteAccess
= WriteAccess
;
3049 FileObject
->DeleteAccess
= DeleteAccess
;
3051 /* Check if we have no access as all */
3052 if (!(ReadAccess
) && !(WriteAccess
) && !(DeleteAccess
))
3054 /* Check if we need to update the structure */
3055 if (!Update
) return;
3057 /* Otherwise, clear data */
3058 ShareAccess
->OpenCount
= 0;
3059 ShareAccess
->Readers
= 0;
3060 ShareAccess
->Writers
= 0;
3061 ShareAccess
->Deleters
= 0;
3062 ShareAccess
->SharedRead
= 0;
3063 ShareAccess
->SharedWrite
= 0;
3064 ShareAccess
->SharedDelete
= 0;
3068 /* Calculate shared access */
3069 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
3070 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
3071 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
3073 /* Set it in the FO */
3074 FileObject
->SharedRead
= SharedRead
;
3075 FileObject
->SharedWrite
= SharedWrite
;
3076 FileObject
->SharedDelete
= SharedDelete
;
3078 /* Check if we need to update the structure */
3079 if (!Update
) return;
3081 /* Otherwise, set data */
3082 ShareAccess
->OpenCount
= 1;
3083 ShareAccess
->Readers
= ReadAccess
;
3084 ShareAccess
->Writers
= WriteAccess
;
3085 ShareAccess
->Deleters
= DeleteAccess
;
3086 ShareAccess
->SharedRead
= SharedRead
;
3087 ShareAccess
->SharedWrite
= SharedWrite
;
3088 ShareAccess
->SharedDelete
= SharedDelete
;
3097 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject
,
3098 IN PFILE_OBJECT FileObject
)
3104 PIO_STACK_LOCATION Stack
;
3106 /* Check if handles were already created for the
3107 * open file. If so, that's over.
3109 if (FileObject
->Flags
& FO_HANDLE_CREATED
)
3110 KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN
,
3111 (ULONG_PTR
)FileObject
,
3112 (ULONG_PTR
)DeviceObject
, 0, 0);
3114 /* Reset the events */
3115 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3116 KeClearEvent(&FileObject
->Event
);
3118 /* Allocate the IRP we'll use */
3119 Irp
= IopAllocateIrpMustSucceed(DeviceObject
->StackSize
);
3120 /* Properly set it */
3121 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3122 Irp
->UserEvent
= &Event
;
3123 Irp
->UserIosb
= &Irp
->IoStatus
;
3124 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3125 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3126 Irp
->RequestorMode
= KernelMode
;
3127 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
3129 Stack
= IoGetNextIrpStackLocation(Irp
);
3130 Stack
->MajorFunction
= IRP_MJ_CLEANUP
;
3131 Stack
->FileObject
= FileObject
;
3133 /* Put on top of IRPs list of the thread */
3134 IopQueueIrpToThread(Irp
);
3136 /* Call the driver */
3137 Status
= IoCallDriver(DeviceObject
, Irp
);
3138 if (Status
== STATUS_PENDING
)
3140 KeWaitForSingleObject(&Event
, UserRequest
,
3141 KernelMode
, FALSE
, NULL
);
3144 /* Remove from IRPs list */
3145 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3146 IopUnQueueIrpFromThread(Irp
);
3147 KeLowerIrql(OldIrql
);
3152 /* Clear the event */
3153 KeClearEvent(&FileObject
->Event
);
3154 /* And finally, mark the open operation as canceled */
3155 FileObject
->Flags
|= FO_FILE_OPEN_CANCELLED
;
3163 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
3164 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
3167 return STATUS_NOT_IMPLEMENTED
;
3175 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
3178 NTSTATUS Status
= STATUS_SUCCESS
;
3181 /* Get the flag status */
3182 FlagSet
= FileObject
->Flags
& FO_REMOTE_ORIGIN
? TRUE
: FALSE
;
3184 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
3185 if (Remote
&& !FlagSet
)
3188 FileObject
->Flags
|= FO_REMOTE_ORIGIN
;
3190 else if (!Remote
&& FlagSet
)
3192 /* Remove the flag */
3193 FileObject
->Flags
&= ~FO_REMOTE_ORIGIN
;
3198 Status
= STATUS_INVALID_PARAMETER_MIX
;
3210 NtCreateFile(PHANDLE FileHandle
,
3211 ACCESS_MASK DesiredAccess
,
3212 POBJECT_ATTRIBUTES ObjectAttributes
,
3213 PIO_STATUS_BLOCK IoStatusBlock
,
3214 PLARGE_INTEGER AllocateSize
,
3215 ULONG FileAttributes
,
3217 ULONG CreateDisposition
,
3218 ULONG CreateOptions
,
3222 /* Call the I/O Function */
3223 return IoCreateFile(FileHandle
,
3241 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
3242 IN ACCESS_MASK DesiredAccess
,
3243 IN POBJECT_ATTRIBUTES ObjectAttributes
,
3244 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3245 IN ULONG CreateOptions
,
3246 IN ULONG MailslotQuota
,
3247 IN ULONG MaxMessageSize
,
3248 IN PLARGE_INTEGER TimeOut
)
3250 MAILSLOT_CREATE_PARAMETERS Buffer
;
3253 /* Check for Timeout */
3256 /* check if the call came from user mode */
3257 if (KeGetPreviousMode() != KernelMode
)
3259 /* Enter SEH for Probe */
3262 /* Probe the timeout */
3263 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
3265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3267 /* Return the exception code */
3268 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3274 /* Otherwise, capture directly */
3275 Buffer
.ReadTimeout
= *TimeOut
;
3278 /* Set the correct setting */
3279 Buffer
.TimeoutSpecified
= TRUE
;
3283 /* Tell the FSD we don't have a timeout */
3284 Buffer
.TimeoutSpecified
= FALSE
;
3288 Buffer
.MailslotQuota
= MailslotQuota
;
3289 Buffer
.MaximumMessageSize
= MaxMessageSize
;
3292 return IoCreateFile(FileHandle
,
3298 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3303 CreateFileTypeMailslot
,
3310 NtCreateNamedPipeFile(OUT PHANDLE FileHandle
,
3311 IN ACCESS_MASK DesiredAccess
,
3312 IN POBJECT_ATTRIBUTES ObjectAttributes
,
3313 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3314 IN ULONG ShareAccess
,
3315 IN ULONG CreateDisposition
,
3316 IN ULONG CreateOptions
,
3317 IN ULONG NamedPipeType
,
3319 IN ULONG CompletionMode
,
3320 IN ULONG MaximumInstances
,
3321 IN ULONG InboundQuota
,
3322 IN ULONG OutboundQuota
,
3323 IN PLARGE_INTEGER DefaultTimeout
)
3325 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
3328 /* Check for Timeout */
3331 /* check if the call came from user mode */
3332 if (KeGetPreviousMode() != KernelMode
)
3334 /* Enter SEH for Probe */
3337 /* Probe the timeout */
3338 Buffer
.DefaultTimeout
=
3339 ProbeForReadLargeInteger(DefaultTimeout
);
3341 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3343 /* Return the exception code */
3344 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3350 /* Otherwise, capture directly */
3351 Buffer
.DefaultTimeout
= *DefaultTimeout
;
3354 /* Set the correct setting */
3355 Buffer
.TimeoutSpecified
= TRUE
;
3359 /* Tell the FSD we don't have a timeout */
3360 Buffer
.TimeoutSpecified
= FALSE
;
3364 Buffer
.NamedPipeType
= NamedPipeType
;
3365 Buffer
.ReadMode
= ReadMode
;
3366 Buffer
.CompletionMode
= CompletionMode
;
3367 Buffer
.MaximumInstances
= MaximumInstances
;
3368 Buffer
.InboundQuota
= InboundQuota
;
3369 Buffer
.OutboundQuota
= OutboundQuota
;
3372 return IoCreateFile(FileHandle
,
3383 CreateFileTypeNamedPipe
,
3390 NtFlushWriteBuffer(VOID
)
3394 /* Call the kernel */
3395 KeFlushWriteBuffer();
3396 return STATUS_SUCCESS
;
3404 NtOpenFile(OUT PHANDLE FileHandle
,
3405 IN ACCESS_MASK DesiredAccess
,
3406 IN POBJECT_ATTRIBUTES ObjectAttributes
,
3407 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3408 IN ULONG ShareAccess
,
3409 IN ULONG OpenOptions
)
3411 /* Call the I/O Function */
3412 return IoCreateFile(FileHandle
,
3430 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
3431 OUT PFILE_BASIC_INFORMATION FileInformation
)
3433 /* Call the internal helper API */
3434 return IopQueryAttributesFile(ObjectAttributes
,
3435 FileBasicInformation
,
3436 sizeof(FILE_BASIC_INFORMATION
),
3442 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
3443 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
3445 /* Call the internal helper API */
3446 return IopQueryAttributesFile(ObjectAttributes
,
3447 FileNetworkOpenInformation
,
3448 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
3453 * @name NtCancelIoFile
3455 * Cancel all pending I/O operations in the current thread for specified
3459 * Handle to file object to cancel requests for. No specific
3460 * access rights are needed.
3461 * @param IoStatusBlock
3462 * Pointer to status block which is filled with final completition
3463 * status on successful return.
3471 NtCancelIoFile(IN HANDLE FileHandle
,
3472 OUT PIO_STATUS_BLOCK IoStatusBlock
)
3474 PFILE_OBJECT FileObject
;
3478 BOOLEAN OurIrpsInList
= FALSE
;
3479 LARGE_INTEGER Interval
;
3480 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3482 PLIST_ENTRY ListHead
, NextEntry
;
3484 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3486 /* Check the previous mode */
3487 if (PreviousMode
!= KernelMode
)
3489 /* Enter SEH for probing */
3492 /* Probe the I/O Status Block */
3493 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3495 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3497 /* Return the exception code */
3498 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3503 /* Reference the file object */
3504 Status
= ObReferenceObjectByHandle(FileHandle
,
3508 (PVOID
*)&FileObject
,
3510 if (!NT_SUCCESS(Status
)) return Status
;
3512 /* IRP cancellations are synchronized at APC_LEVEL. */
3513 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3515 /* Get the current thread */
3516 Thread
= PsGetCurrentThread();
3518 /* Update the operation counts */
3519 IopUpdateOperationCount(IopOtherTransfer
);
3522 ListHead
= &Thread
->IrpList
;
3523 NextEntry
= ListHead
->Flink
;
3524 while (ListHead
!= NextEntry
)
3526 /* Get the IRP and check if the File Object matches */
3527 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3528 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3530 /* Cancel this IRP and keep looping */
3532 OurIrpsInList
= TRUE
;
3535 /* Go to the next entry */
3536 NextEntry
= NextEntry
->Flink
;
3539 /* Lower the IRQL */
3540 KeLowerIrql(OldIrql
);
3542 /* Check if we had found an IRP */
3545 /* Setup a 10ms wait */
3546 Interval
.QuadPart
= -100000;
3549 while (OurIrpsInList
)
3552 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
3553 OurIrpsInList
= FALSE
;
3556 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3558 /* Now loop the list again */
3559 NextEntry
= ListHead
->Flink
;
3560 while (NextEntry
!= ListHead
)
3562 /* Get the IRP and check if the File Object matches */
3563 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
3564 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
3567 OurIrpsInList
= TRUE
;
3571 /* Go to the next entry */
3572 NextEntry
= NextEntry
->Flink
;
3575 /* Lower the IRQL */
3576 KeLowerIrql(OldIrql
);
3580 /* Enter SEH for writing back the I/O Status */
3584 IoStatusBlock
->Status
= STATUS_SUCCESS
;
3585 IoStatusBlock
->Information
= 0;
3587 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3589 /* Ignore exception */
3593 /* Dereference the file object and return success */
3594 ObDereferenceObject(FileObject
);
3595 return STATUS_SUCCESS
;
3603 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
3606 DUMMY_FILE_OBJECT LocalFileObject
;
3608 KPROCESSOR_MODE AccessMode
= KeGetPreviousMode();
3609 OPEN_PACKET OpenPacket
;
3611 IOTRACE(IO_API_DEBUG
, "FileMame: %wZ\n", ObjectAttributes
->ObjectName
);
3613 /* Setup the Open Packet */
3614 RtlZeroMemory(&OpenPacket
, sizeof(OPEN_PACKET
));
3615 OpenPacket
.Type
= IO_TYPE_OPEN_PACKET
;
3616 OpenPacket
.Size
= sizeof(OPEN_PACKET
);
3617 OpenPacket
.CreateOptions
= FILE_DELETE_ON_CLOSE
;
3618 OpenPacket
.ShareAccess
= FILE_SHARE_READ
|
3621 OpenPacket
.Disposition
= FILE_OPEN
;
3622 OpenPacket
.DeleteOnly
= TRUE
;
3623 OpenPacket
.LocalFileObject
= &LocalFileObject
;
3625 /* Update the operation counts */
3626 IopUpdateOperationCount(IopOtherTransfer
);
3629 * Attempt opening the file. This will call the I/O Parse Routine for
3630 * the File Object (IopParseDevice) which will use the dummy file obejct
3631 * send the IRP to its device object. Note that we have two statuses
3632 * to worry about: the Object Manager's status (in Status) and the I/O
3633 * status, which is in the Open Packet's Final Status, and determined
3634 * by the Parse Check member.
3636 Status
= ObOpenObjectByName(ObjectAttributes
,
3643 if (OpenPacket
.ParseCheck
== FALSE
) return Status
;
3645 /* Retrn the Io status */
3646 return OpenPacket
.FinalStatus
;