通过NtCreateFile打开设备,获得的句柄实际上指向的是一个文件对象(FILE_OBJECT),而不是设备对象(DEVICE_OBJECT).
设备对象类型的创建过程如下,是有存在ParseProcedure的 :
RtlInitUnicodeString( &nameString, L"Device" );
objectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( DEVICE_OBJECT );
objectTypeInitializer.ParseProcedure = IopParseDevice;
objectTypeInitializer.CaseInsensitive = TRUE;
objectTypeInitializer.DeleteProcedure = IopDeleteDevice;
objectTypeInitializer.SecurityProcedure = IopGetSetSecurityObject;
objectTypeInitializer.QueryNameProcedure = (OB_QUERYNAME_METHOD)NULL;
if (!NT_SUCCESS( ObCreateObjectType( &nameString,
&objectTypeInitializer,
(PSECURITY_DESCRIPTOR) NULL,
&IoDeviceObjectType ))) {
return FALSE;
}
NtCreateFile打开设备主要通过ObpLookupObjectName来找到设备对象,当找到设备对象时:
if (ParseProcedure && (!InsertObject || (ParseProcedure == ObpParseSymbolicLink))) {
。。。。。。。。
。。。。。。。。
。。。。。。。。
Status = (*ParseProcedure)( Object,
(PVOID)ObjectType,
AccessState,
AccessCheckMode,
Attributes,
ObjectName,
&RemainingName,
ParseContext,
SecurityQos,
&Object );
。。。。。。。。
。。。。。。。。
。。。。。。。。
}
因此当找到设备对象时,调用设备对象的ParseProcedure:IopParseDevice。
在IopParseDevice中,对非删除和查询炒作创建文件对象(FILE_OBJECT),文件对象的DeviceObject成员指向实际设备对象,并返回文件对象
status = ObCreateObject( KernelMode,
IoFileObjectType,
&objectAttributes,
AccessMode,
(PVOID) NULL,
fileObjectSize,
0,
0,
(PVOID *) &fileObject );
fileObject->DeviceObject = parseDeviceObject;
*Object = fileObject;
故最终NtCreateFile获得的设备句柄指向文件对象