📄 file.c
字号:
SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
}
/* Check if access failed */
if (!AccessGranted)
{
/* Dereference the device and fail */
DPRINT1("Traverse access failed!\n");
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
return STATUS_ACCESS_DENIED;
}
}
/* Check if we can simply use a dummy file */
UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly));
/* Check if this is a direct open */
if (!(RemainingName->Length) &&
!(OpenPacket->RelatedFileObject) &&
#if 0 // USETUP IS BROKEN!
((DesiredAccess & ~(SYNCHRONIZE |
FILE_READ_ATTRIBUTES |
READ_CONTROL |
ACCESS_SYSTEM_SECURITY |
WRITE_OWNER |
WRITE_DAC)) &&
#endif
!(UseDummyFile))
{
if (DesiredAccess & ~(SYNCHRONIZE |
FILE_READ_ATTRIBUTES |
READ_CONTROL |
ACCESS_SYSTEM_SECURITY |
WRITE_OWNER |
WRITE_DAC))
{
DPRINT1("FIXME: Broken Parse due to invalid DesiredAccess: %lx\n",
DesiredAccess);
}
/* Remember this for later */
DirectOpen = TRUE;
}
/* Check if we have a related FO that wasn't a direct open */
if ((OpenPacket->RelatedFileObject) &&
!(OpenPacket->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN))
{
/* The device object is the one we were given */
DeviceObject = ParseObject;
/* Check if the related FO had a VPB */
if (OpenPacket->RelatedFileObject->Vpb)
{
/* Yes, remember it */
Vpb = OpenPacket->RelatedFileObject->Vpb;
/* Reference it */
InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
}
}
else
{
/* The device object is the one we were given */
DeviceObject = OriginalDeviceObject;
/* Check if it has a VPB */
if ((OriginalDeviceObject->Vpb) && !(DirectOpen))
{
/* Check if the VPB is mounted, and mount it */
Vpb = IopCheckVpbMounted(OpenPacket,
OriginalDeviceObject,
RemainingName,
&Status);
if (!Vpb) return Status;
/* Get the VPB's device object */
DeviceObject = Vpb->DeviceObject;
}
/* Check if there's an attached device */
if (DeviceObject->AttachedDevice)
{
/* Get the attached device */
DeviceObject = IoGetAttachedDevice(DeviceObject);
}
}
/* Check if this is a secure FSD */
if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) &&
((OpenPacket->RelatedFileObject) || (RemainingName->Length)) &&
(!VolumeOpen))
{
DPRINT1("Fix Secure FSD support!!!\n");
}
/* Allocate the IRP */
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
if (!Irp)
{
/* Dereference the device and VPB, then fail */
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
if (Vpb) IopDereferenceVpb(Vpb);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Now set the IRP data */
Irp->RequestorMode = AccessMode;
Irp->Flags = IRP_CREATE_OPERATION |
IRP_SYNCHRONOUS_API |
IRP_DEFER_IO_COMPLETION;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->UserIosb = &IoStatusBlock;
Irp->MdlAddress = NULL;
Irp->PendingReturned = FALSE;
Irp->UserEvent = NULL;
Irp->Cancel = FALSE;
Irp->CancelRoutine = NULL;
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
/* Setup the security context */
SecurityContext.SecurityQos = SecurityQos;
SecurityContext.AccessState = AccessState;
SecurityContext.DesiredAccess = AccessState->RemainingDesiredAccess;
SecurityContext.FullCreateOptions = OpenPacket->CreateOptions;
/* Get the I/O Stack location */
StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
StackLoc->Control = 0;
/* Check what kind of file this is */
switch (OpenPacket->CreateFileType)
{
/* Normal file */
case CreateFileTypeNone:
/* Set the major function and EA Length */
StackLoc->MajorFunction = IRP_MJ_CREATE;
StackLoc->Parameters.Create.EaLength = OpenPacket->EaLength;
/* Set the flags */
StackLoc->Flags = (UCHAR)OpenPacket->Options;
StackLoc->Flags |= !(Attributes & OBJ_CASE_INSENSITIVE) ?
SL_CASE_SENSITIVE: 0;
break;
/* Named pipe */
case CreateFileTypeNamedPipe:
/* Set the named pipe MJ and set the parameters */
StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
StackLoc->Parameters.CreatePipe.Parameters =
OpenPacket->MailslotOrPipeParameters;
break;
/* Mailslot */
case CreateFileTypeMailslot:
/* Set the mailslot MJ and set the parameters */
StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
StackLoc->Parameters.CreateMailslot.Parameters =
OpenPacket->MailslotOrPipeParameters;
break;
}
/* Set the common data */
Irp->Overlay.AllocationSize = OpenPacket->AllocationSize;
Irp->AssociatedIrp.SystemBuffer = OpenPacket->EaBuffer;
StackLoc->Parameters.Create.Options = (OpenPacket->Disposition << 24) |
(OpenPacket->CreateOptions &
0xFFFFFF);
StackLoc->Parameters.Create.FileAttributes = OpenPacket->FileAttributes;
StackLoc->Parameters.Create.ShareAccess = OpenPacket->ShareAccess;
StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
/* Check if we really need to create an object */
if (!UseDummyFile)
{
/* Create the actual file object */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
Attributes,
NULL,
NULL);
Status = ObCreateObject(KernelMode,
IoFileObjectType,
&ObjectAttributes,
AccessMode,
NULL,
sizeof(FILE_OBJECT),
0,
0,
(PVOID*)&FileObject);
if (!NT_SUCCESS(Status))
{
/* Create failed, free the IRP */
IoFreeIrp(Irp);
/* Dereference the device and VPB */
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
if (Vpb) IopDereferenceVpb(Vpb);
/* We failed, return status */
OpenPacket->FinalStatus = Status;
return Status;
}
/* Clear the file object */
RtlZeroMemory(FileObject, sizeof(FILE_OBJECT));
/* Check if this is Synch I/O */
if (OpenPacket->CreateOptions &
(FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
{
/* Set the synch flag */
FileObject->Flags |= FO_SYNCHRONOUS_IO;
/* Check if it's also alertable */
if (OpenPacket->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
{
/* It is, set the alertable flag */
FileObject->Flags |= FO_ALERTABLE_IO;
}
}
/* Check if this is synch I/O */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
/* Initialize the event */
KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, FALSE);
}
/* Check if the caller requested no intermediate buffering */
if (OpenPacket->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
{
/* Set the correct flag for the FSD to read */
FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
}
/* Check if the caller requested write through support */
if (OpenPacket->CreateOptions & FILE_WRITE_THROUGH)
{
/* Set the correct flag for the FSD to read */
FileObject->Flags |= FO_WRITE_THROUGH;
}
/* Check if the caller says the file will be only read sequentially */
if (OpenPacket->CreateOptions & FILE_SEQUENTIAL_ONLY)
{
/* Set the correct flag for the FSD to read */
FileObject->Flags |= FO_SEQUENTIAL_ONLY;
}
/* Check if the caller believes the file will be only read randomly */
if (OpenPacket->CreateOptions & FILE_RANDOM_ACCESS)
{
/* Set the correct flag for the FSD to read */
FileObject->Flags |= FO_RANDOM_ACCESS;
}
}
else
{
/* Use the dummy object instead */
DummyFileObject = OpenPacket->DummyFileObject;
RtlZeroMemory(DummyFileObject, sizeof(DUMMY_FILE_OBJECT));
/* Set it up */
FileObject = (PFILE_OBJECT)&DummyFileObject->ObjectHeader.Body;
DummyFileObject->ObjectHeader.Type = IoFileObjectType;
DummyFileObject->ObjectHeader.PointerCount = 1;
}
/* Setup the file header */
FileObject->Type = IO_TYPE_FILE;
FileObject->Size = sizeof(FILE_OBJECT);
FileObject->RelatedFileObject = OpenPacket->RelatedFileObject;
FileObject->DeviceObject = OriginalDeviceObject;
/* Check if this is a direct device open */
if (DirectOpen) FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
/* Check if the caller wants case sensitivity */
if (!(Attributes & OBJ_CASE_INSENSITIVE))
{
/* Tell the driver about it */
FileObject->Flags |= FO_OPENED_CASE_SENSITIVE;
}
/* Now set the file object */
Irp->Tail.Overlay.OriginalFileObject = FileObject;
StackLoc->FileObject = FileObject;
/* Check if the file object has a name */
if (RemainingName->Length)
{
/* Setup the unicode string */
FileObject->FileName.MaximumLength = RemainingName->Length +
sizeof(WCHAR);
FileObject->FileName.Buffer = ExAllocatePoolWithTag(PagedPool,
FileObject->
FileName.
MaximumLength,
TAG_IO_NAME);
if (!FileObject->FileName.Buffer)
{
/* Failed to allocate the name, free the IRP */
IoFreeIrp(Irp);
/* Dereference the device object and VPB */
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
if (Vpb) IopDereferenceVpb(Vpb);
/* Clear the FO and dereference it */
FileObject->DeviceObject = NULL;
if (!UseDummyFile) ObDereferenceObject(FileObject);
/* Fail */
return STATUS_INSUFFICIENT_RESOURCES;
}
}
/* Copy the name */
RtlCopyUnicodeString(&FileObject->FileName, RemainingName);
/* Initialize the File Object event and set the FO */
KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
OpenPacket->FileObject = FileObject;
/* Queue the IRP and call the driver */
IopQueueIrpToThread(Irp);
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
/* Wait for the driver to complete the create */
KeWaitForSingleObject(&FileObject->Event,
Executive,
KernelMode,
FALSE,
NULL);
/* Get the new status */
Status = IoStatusBlock.Status;
}
else
{
/* We'll have to complete it ourselves */
ASSERT(!Irp->PendingReturned);
ASSERT(!Irp->MdlAddress);
/* Completion happens at APC_LEVEL */
KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Get the new I/O Status block ourselves */
IoStatusBlock = Irp->IoStatus;
Status = IoStatusBlock.Status;
/* Manually signal the even, we can't have any waiters */
FileObject->Event.Header.SignalState = 1;
/* Now that we've signaled the events, de-associate the IRP */
IopUnQueueIrpFromThread(Irp);
/* Check if the IRP had an input buffer */
if ((Irp->Flags & IRP_BUFFERED_IO) &&
(Irp->Flags & IRP_DEALLOCATE_BUFFER))
{
/* Free it. A driver might've tacked one on */
ExFreePool(Irp->AssociatedIrp.SystemBuffer);
}
/* Free the IRP and bring the IRQL back down */
IoFreeIrp(Irp);
KeLowerIrql(OldIrql);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -