上 WRK 代码
PFILE_OBJECT
IoCreateStreamFileObjectLite(
IN PFILE_OBJECT FileObject OPTIONAL,
IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
/*++
Routine Description:
This routine is invoked to create a new file object that represents an
alternate data stream for an existing file object. The input file object
represents the file object that already exists for a file, and the newly
created stream file object is used to access other parts of the file
other than the data. Some uses of stream file objects are the EAs or
the SECURITY_DESCRIPTORs on the file. The stream file object allows
the file system to cache these parts of the file just as if they were
an entire to themselves.
It is also possible to use stream file objects to represent virtual
volume files. This allows various parts of the on-disk structure to
be viewed as a virtual file and therefore be cached using the same logic
in the file system. For this case, the device object pointer is used
to create the file object.
<strong>This call differs from IoCreateStreamFileObject in that it performs no
handle management and does not result in a call to the file system
cleanup entry.</strong>
Arguments:
FileObject - Pointer to the file object to which the new stream file
is related. This pointer is optional.
DeviceObject - Pointer to the device object on which the stream file
is to be opened. This pointer is not optional if the FileObject
pointer is not specified.
Return Value:
The function value is a pointer to the newly created stream file object.
--*/
{
PFILE_OBJECT newFileObject;
OBJECT_ATTRIBUTES objectAttributes;
NTSTATUS status;
PAGED_CODE();
//
// Begin by getting the device object from either the file object or
// the device object parameter.
//
if (ARGUMENT_PRESENT( FileObject )) {
DeviceObject = FileObject->DeviceObject;
}
//
// if the driver has been marked for an unload or deleted operation, and
// the reference count goes to zero, then the driver may need to be
// unloaded or deleted at this point.
// file that is being made, not a real file open request. In essence,
// no new file is really being opened.
//
IopInterlockedIncrementUlong( LockQueueIoDatabaseLock,
&DeviceObject->ReferenceCount );
//
// Initialize the object attributes that will be used to create the file
// object.
//
InitializeObjectAttributes( &objectAttributes,
(PUNICODE_STRING) NULL,
0,
(HANDLE) NULL,
(PSECURITY_DESCRIPTOR) NULL );
//
// Create the new file object.
//
<strong>status = ObCreateObject( KernelMode,
IoFileObjectType,
&objectAttributes,
KernelMode,
(PVOID) NULL,
(ULONG) sizeof( FILE_OBJECT ),
(ULONG) sizeof( FILE_OBJECT ),
0,
(PVOID *) &newFileObject );</strong>
if (!NT_SUCCESS( status )) {
IopDecrementDeviceObjectRef( DeviceObject, FALSE, FALSE );
ExRaiseStatus( status );
}
//
// Initialize the common fields of the file object.
//
RtlZeroMemory( newFileObject, sizeof( FILE_OBJECT ) );
newFileObject->Type = IO_TYPE_FILE;
newFileObject->Size = sizeof( FILE_OBJECT );
<strong>newFileObject->DeviceObject = DeviceObject;</strong>
newFileObject->Flags = FO_STREAM_FILE;
KeInitializeEvent( &newFileObject->Event, SynchronizationEvent, FALSE );
//
// Clean up from the creation.
//
ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(newFileObject)->ObjectCreateInfo);
OBJECT_TO_OBJECT_HEADER(newFileObject)->ObjectCreateInfo = NULL;
newFileObject->Flags |= FO_HANDLE_CREATED;
ASSERT( newFileObject->Type == IO_TYPE_FILE );
//
// Synchronize here with the file system to make sure that
// volumes don't go away while en route to the FS.
//
if (DeviceObject->Vpb) {
IopInterlockedIncrementUlong( LockQueueIoVpbLock,
(PLONG) &DeviceObject->Vpb->ReferenceCount );
}
return newFileObject;
}
很简单 1 创建一个FILE_OBJECT 对象newFileObject
2 将newFileObject和DeviceObject相关联 newFileObject->DeviceObject = DeviceObject;
我们继续看 IoCreateStreamFileObject
PFILE_OBJECT
IoCreateStreamFileObject(
IN PFILE_OBJECT FileObject OPTIONAL,
IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
{
return (IoCreateStreamFileObjectEx(FileObject, DeviceObject, NULL));
}
PFILE_OBJECT
IoCreateStreamFileObjectEx(
IN PFILE_OBJECT FileObject OPTIONAL,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
OUT PHANDLE FileHandle OPTIONAL
)
/*++
Routine Description:
This routine is invoked to create a new file object that represents an
alternate data stream for an existing file object. The input file object
represents the file object that already exists for a file, and the newly
created stream file object is used to access other parts of the file
other than the data. Some uses of stream file objects are the EAs or
the SECURITY_DESCRIPTORs on the file. The stream file object allows
the file system to cache these parts of the file just as if they were
an entire to themselves.
It is also possible to use stream file objects to represent virtual
volume files. This allows various parts of the on-disk structure to
be viewed as a virtual file and therefore be cached using the same logic
in the file system. For this case, the device object pointer is used
to create the file object.
Arguments:
FileObject - Pointer to the file object to which the new stream file
is related. This pointer is optional.
DeviceObject - Pointer to the device object on which the stream file
is to be opened. This pointer is not optional if the FileObject
pointer is not specified.
FileHandle - Out parameter for handle if necessary.
Return Value:
The function value is a pointer to the newly created stream file object.
--*/
{
PFILE_OBJECT newFileObject;
OBJECT_ATTRIBUTES objectAttributes;
<strong>HANDLE handle;</strong>
NTSTATUS status;
PAGED_CODE();
//
// Begin by getting the device object from either the file object or
// the device object parameter.
//
if (ARGUMENT_PRESENT( FileObject )) {
DeviceObject = FileObject->DeviceObject;
}
//
// Increment the reference count for the target device object. Note
// that no check is made to determine whether or not the device driver
// is attempting to unload since this is an implicit open of a pseudo-
// file that is being made, not a real file open request. In essence,
// no new file is really being opened.
//
IopInterlockedIncrementUlong( LockQueueIoDatabaseLock,
&DeviceObject->ReferenceCount );
//
// Initialize the object attributes that will be used to create the file
// object.
//
InitializeObjectAttributes( &objectAttributes,
(PUNICODE_STRING) NULL,
OBJ_KERNEL_HANDLE,
(HANDLE) NULL,
(PSECURITY_DESCRIPTOR) NULL );
//
// Create the new file object.
//
status = ObCreateObject( KernelMode,
IoFileObjectType,
&objectAttributes,
KernelMode,
(PVOID) NULL,
(ULONG) sizeof( FILE_OBJECT ),
(ULONG) sizeof( FILE_OBJECT ),
0,
(PVOID *) &newFileObject );
if (!NT_SUCCESS( status )) {
IopDecrementDeviceObjectRef( DeviceObject, FALSE, FALSE );
ExRaiseStatus( status );
}
//
// Initialize the common fields of the file object.
//
RtlZeroMemory( newFileObject, sizeof( FILE_OBJECT ) );
newFileObject->Type = IO_TYPE_FILE;
newFileObject->Size = sizeof( FILE_OBJECT );
newFileObject->DeviceObject = DeviceObject;
newFileObject->Flags = FO_STREAM_FILE;
KeInitializeEvent( &newFileObject->Event, SynchronizationEvent, FALSE );
//
// Insert the device object into the table. Note that this is done w/a
// pointer bias so that the object cannot go away if some random user
// application closes the handle before this code is finished w/it.
//
<strong>status = ObInsertObject( newFileObject,
NULL,
FILE_READ_DATA,
1,
(PVOID *) &newFileObject,
&handle );</strong>
if (!NT_SUCCESS( status )) {
ExRaiseStatus( status );
}
//
// The insert completed successfully. Update the bookkeeping so that the
// fact that there is a handle is reflected.
//
newFileObject->Flags |= FO_HANDLE_CREATED;
ASSERT( newFileObject->Type == IO_TYPE_FILE );
//
// Synchronize here with the file system to make sure that
// volumes don't go away while en route to the FS.
//
if (DeviceObject->Vpb) {
IopInterlockedIncrementUlong( LockQueueIoVpbLock,
(PLONG) &DeviceObject->Vpb->ReferenceCount );
}
//
// Finally, close the handle to the file. and clear the forward cluster
//
<strong>if (FileHandle == NULL) {
ObCloseHandle( handle , KernelMode);
} else {
*FileHandle = handle;
//
// Get rid of the reference in ObInsertObject.
//
ObDereferenceObject(newFileObject);
}
</strong>
ASSERT( NT_SUCCESS( status ) );
return newFileObject;
}
我们首先看见的差别在于 Routine Description, IoCreateStreamFileObjectLite比IoCreateStreamFileObjectEx多了一段描述
<strong>This call(IoCreateStreamFileObjectLite) differs from IoCreateStreamFileObject in that it performs no
handle management and does not result in a call to the file system cleanup entry.</strong>
正因为 Lite轻量级的意思, 所以IoCreateStreamFileObjectLite相对而言,缺少了 句柄管理以及不会导 文件系统的 Cluanup 这个 入口的调用。
那么, 代码里究竟区别在哪里呢?
在 IoCreateStreamFileObjectEx 多声明了一个变量
<pre name="code" class="cpp">HANDLE handle;
而两个函数之间的差别也就是关于这个变量的
<pre name="code" class="cpp">status = ObInsertObject( newFileObject,
NULL,
FILE_READ_DATA,
1,
(PVOID *) &newFileObject,
&handle );
if (FileHandle == NULL) {
ObCloseHandle( handle , KernelMode);
} else {
*FileHandle = handle;
//
// Get rid of the reference in ObInsertObject.
//
ObDereferenceObject(newFileObject);
}
我们看这个函数 ObInsertObject
NTSTATUS
ObInsertObject (
__in PVOID Object,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in ULONG ObjectPointerBias,
__out_opt PVOID *NewObject,
__out_opt PHANDLE Handle
)
/*++
Routine Description:
This routine inserts an object into the current processes handle table.
The Object header includes a pointer to a SecurityDescriptor passed in
an object creation call. This SecurityDescriptor is not assumed to have
been captured. This routine is responsible for making an appropriate
SecurityDescriptor and removing the reference in the object header.
Arguments:
Object - Supplies a pointer to the new object body
AccessState - Optionally supplies the access state for the new
handle
DesiredAccess - Optionally supplies the desired access we want for the
new handle
ObjectPointerBias - Supplies a bias to apply for the pointer count for the
object
<strong>NewObject - Optionally receives the pointer to the new object that we've
created a handle for
Handle - Receives the new handle, If NULL then no handle is created.
Objects that don't have handles created must be unnamed and
have an object bias of zero.</strong>
Return Value:
An appropriate NTSTATUS value.
--*/
{......}
这个函数比较复杂 = = 以后专题分析。