一。对象管理第一次初始化(ObInitSystem) + 类型对象的创建(ObCreateObjectType)
2011-02-16 17:04
1576 查看
一。对象管理第一次初始化(ObInitSystem) + 类型对象的创建(ObCreateObjectType)
2010年05月09日 星期日 11:10
2010年05月09日 星期日 11:10
BOOLEAN ObInitSystem (VOID) 函数在系统初始化阶段被调用 它对对象管理器进行了初始化操作。这个函数创建了目录(Directory)对象类型、类型(Type)对象类型,并且建立了对象的根目录对象"/" 初始化完毕后,系统就可以通过对象管理器提供的函数操作对象了。 ObInitSystem 会在系统初始化时被调用两次,路径分别是 KiSystemStartup -> KiInitializeKernel -> ExpInitializeExecutive -> ObInitSystem 和 KiThreadStartup -> PspSystemThreadStartup -> Phase1Initialization -> ObInitSystem 这两次调用会走函数的两条不同分支, 函数中使用全局变量InitializationPhase来控制 BOOLEAN ObInitSystem (VOID) { ..... if(InitializationPhase == 0) { //这里面是第一次初始化 } if(InitializationPhase == 1) { //第二次初始化 } return TRUE; } 第一次调用时进行的操作 1。 ObInitSystem初始化了两个LookasideList, ObpCreateInfoLookasideList用来存储OBJECT_CREATE_INFORMATION结构, ObpNameBufferLookasideList存储对象名 2。 使用 ObCreateObjectType 函数创建了 Type、Directory、SymbolicLink 类型对象 3。 为系统进程创建了句柄表 BOOLEAN ObInitSystem (VOID) { ..... if (InitializationPhase == 0) { // 首先初始化两个缓冲区,来盛放以后可能会生成的OBJECT_CREATE_INFORMATION结构和对象名 ExInitializeSystemLookasideList( &ObpCreateInfoLookasideList, NonPagedPool, sizeof(OBJECT_CREATE_INFORMATION), 'iCbO', CreateInfoMaxDepth, &ExSystemLookasideListHead ); ExInitializeSystemLookasideList( &ObpNameBufferLookasideList, PagedPool, OBJECT_NAME_BUFFER_SIZE, 'mNbO', NameBufferMaxDepth, &ExSystemLookasideListHead ); // 把两个LookasideList记录在初始化CPU的KPRCB结构中 Prcb = KeGetCurrentPrcb(); Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList; Prcb->PPLookasideList[LookasideCreateInfoList].P = &ObpCreateInfoLookasideList; Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList; Prcb->PPLookasideList[LookasideNameBufferList].P = &ObpNameBufferLookasideList; // 初始化一些同步和权限检查用到的数据 ObpRemoveObjectList = NULL; ObpInitSecurityDescriptorCache(); KeInitializeEvent( &ObpDefaultObject, NotificationEvent, TRUE ); ExInitializePushLock( &ObpLock ); PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS; PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS; KeInitializeGuardedMutex( &ObpDeviceMapLock ); // 初始化系统配额。不影响Ob管理的理解,这里略过了 PsInitializeQuotaSystem (); // 初始化系统进程的句柄表, ObpKernelHandleTable = PsGetCurrentProcess()->ObjectTable = ExCreateHandleTable( NULL ); // 删除对象时要用到WorkItem派遣到系统线程里进行, 对ObpRemoveObjectWorkItem进行初始化 // 删除对象用到的回调函数是 ObpProcessRemoveObjectQueue ExInitializeWorkItem( &ObpRemoveObjectWorkItem, ObpProcessRemoveObjectQueue, NULL ); // 创建Type对象类型 RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) ); ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer ); ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; ObjectTypeInitializer.PoolType = NonPagedPool; RtlInitUnicodeString( &TypeTypeName, L"Type" ); ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS; ObjectTypeInitializer.GenericMapping = ObpTypeMapping; ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_TYPE ); ObjectTypeInitializer.MaintainTypeList = TRUE; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.DeleteProcedure = &ObpDeleteObjectType; ObCreateObjectType( &TypeTypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObpTypeObjectType ); // 创建Directory对象类型 ObjectTypeInitializer.PoolType = OB_NAMESPACE_POOL_TYPE; RtlInitUnicodeString( &DirectoryTypeName, L"Directory" ); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_DIRECTORY ); ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS; ObjectTypeInitializer.CaseInsensitive = TRUE; ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.MaintainTypeList = FALSE; ObjectTypeInitializer.DeleteProcedure = NULL; ObCreateObjectType( &DirectoryTypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObpDirectoryObjectType ); // 清除目录对象的Synchronize权限 ObpDirectoryObjectType->TypeInfo.ValidAccessMask &= ~SYNCHRONIZE; // 创建SymbolicLink对象类型 RtlInitUnicodeString( &SymbolicLinkTypeName, L"SymbolicLink" ); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_SYMBOLIC_LINK ); ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS; ObjectTypeInitializer.CaseInsensitive = TRUE; ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping; ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink; ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink; ObCreateObjectType( &SymbolicLinkTypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObpSymbolicLinkObjectType ); ObpSymbolicLinkObjectType->TypeInfo.ValidAccessMask &= ~SYNCHRONIZE; // 之后是和Cache有关的, 略过了 } // 第一次初始化结束 if(InitializationPhase == 1) { //第二次初始化 } return TRUE; } windows运行过程中会创建许多对象实例。系统把功能相似的对象分成了不同的类型,每个对象都对应唯一一种对象类型,如目录对象(Directory)、设备对象(Device)、驱动对象(Driver)等等。 所有对象实例中都有一个指针指向一个表示它的对象类型的数据结构。同时这些对象类型本身也是一类对象——类型对象(Type)。也就是说Directory对象的类型是Type, 同时Type对象的类型是Type对象本身。Type类型是自描述的。 不知道说清楚了没有………… 上面的 ObCreateObjectType 函数就用于创建一个对象类型(Directory、SymbolicLink、Type类型)。 NTSTATUS ObCreateObjectType ( __in PUNICODE_STRING TypeName, // 类型的名称 __in POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, // 这个结构里包含了若干重要的信息, 解析函数、删除函数、默认权限等等 __in_opt PSECURITY_DESCRIPTOR SecurityDescriptor, // 不管它.... __out POBJECT_TYPE *ObjectType // 创建后的类型对象通过这个参数传递给调用者 ) { ...... //参数合法性检测 ...... // 类型名中不能包含 “/” 字符 s = TypeName->Buffer; i = TypeName->Length / sizeof( WCHAR ); while (i--) { if (*s++ == OBJ_NAME_PATH_SEPARATOR) { return( STATUS_OBJECT_NAME_INVALID ); } } // 所有的类型对象都存在与 /ObjectTypes 目录下。查询这个目录下是否有当前名字的类型, 如果存在就出错。 // 注意,第一次初始化时,在这里根目录对象ObpTypeDirectoryObject还没有建立,所以不会进入这个if ObpInitializeLookupContext( &LookupContext ); if (ObpTypeDirectoryObject) { ObpLockLookupContext( &LookupContext, ObpTypeDirectoryObject); if (ObpLookupDirectoryEntry( ObpTypeDirectoryObject, TypeName, OBJ_CASE_INSENSITIVE, FALSE, &LookupContext )) { ObpReleaseLookupContext( &LookupContext ); return( STATUS_OBJECT_NAME_COLLISION ); } } // 为类型名称生成一个空间并复制进去 ObjectName.Buffer = ExAllocatePoolWithTag( PagedPool, (ULONG)TypeName->MaximumLength, 'mNbO' ); if (ObjectName.Buffer == NULL) { ObpReleaseLookupContext( &LookupContext ); return STATUS_INSUFFICIENT_RESOURCES; } ObjectName.MaximumLength = TypeName->MaximumLength; RtlCopyUnicodeString( &ObjectName, TypeName ); // 生成对象体, 这个函数后面会详谈。NewObjectTypeHeader是对象头指针。 Status = ObpAllocateObject( NULL, KernelMode, ObpTypeObjectType, &ObjectName, sizeof( OBJECT_TYPE ), &NewObjectTypeHeader ); if (!NT_SUCCESS( Status )) { ......... } // 初始化对象头的Flag域, // TotalNumberOfObjects、TotalNumberOfHandles、HighWaterNumberOfObjects、HighWaterNumberOfHandles 为0 // Name指向类型对象名 NewObjectTypeHeader->Flags |= OB_FLAG_KERNEL_OBJECT | OB_FLAG_PERMANENT_OBJECT; NewObjectType = (POBJECT_TYPE)&NewObjectTypeHeader->Body; NewObjectType->Name = ObjectName; RtlZeroMemory( &NewObjectType->TotalNumberOfObjects, FIELD_OFFSET( OBJECT_TYPE, TypeInfo ) - FIELD_OFFSET( OBJECT_TYPE, TotalNumberOfObjects )); // 正如ObInitSystem函数中描述的一样 ObCreateObjectType 是可以创建Type类型对象本身的 // Type对象的对象类型应该指向Type本身, 若是创建Type本身, 则现在他的NewObjectTypeHeader->Type应该指向NULL // 这里修正了这种情况 if (!ObpTypeObjectType) { ObpTypeObjectType = NewObjectType; NewObjectTypeHeader->Type = ObpTypeObjectType; NewObjectType->TotalNumberOfObjects = 1; } // 又继续初始化TypeObject->TypeInfo域, 这个域是传入的ObjectTypeInitializer的复制, 并且记录了对象使用的内存大小 // TypeInfo包含了众多函数(如解析路径等), 在以后会提到 NewObjectType->TypeInfo = *ObjectTypeInitializer; NewObjectType->TypeInfo.PoolType = PoolType; if (NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST) { NewObjectType->TypeInfo.MaintainTypeList = TRUE; } StandardHeaderCharge = sizeof( OBJECT_HEADER ) + sizeof( OBJECT_HEADER_NAME_INFO ) + (ObjectTypeInitializer->MaintainHandleCount ? sizeof( OBJECT_HEADER_HANDLE_INFO ) : 0 ); if ( PoolType == NonPagedPool ) { NewObjectType->TypeInfo.DefaultNonPagedPoolCharge += StandardHeaderCharge; } else { NewObjectType->TypeInfo.DefaultPagedPoolCharge += StandardHeaderCharge; } if (ObjectTypeInitializer->SecurityProcedure == NULL) { NewObjectType->TypeInfo.SecurityProcedure = SeDefaultObjectMethod; } // Type对象中包含一个TypeList列表, 记录了所有是此类型的对象。这里初始化列表和同步数据结构 ExInitializeResourceLite( &NewObjectType->Mutex ); for (i = 0; i < OBJECT_LOCK_COUNT; i++) { ExInitializeResourceLite( &NewObjectType->ObjectLocks[i] ); } InitializeListHead( &NewObjectType->TypeList ); // DefaultObject和同步有关, 以后再关注 if (NewObjectType->TypeInfo.UseDefaultObject) { NewObjectType->TypeInfo.ValidAccessMask |= SYNCHRONIZE; NewObjectType->DefaultObject = &ObpDefaultObject; } else if (ObjectName.Length == 8 && !wcscmp( ObjectName.Buffer, L"File" )) { NewObjectType->DefaultObject = ULongToPtr( FIELD_OFFSET( FILE_OBJECT, Event ) ); } else if ( ObjectName.Length == 24 && !wcscmp( ObjectName.Buffer, L"WaitablePort")) { NewObjectType->DefaultObject = ULongToPtr( FIELD_OFFSET( LPCP_PORT_OBJECT, WaitEvent ) ); } else { NewObjectType->DefaultObject = NULL; } // OBJECT_HEADER_TO_CREATOR_INFO 函数中ObjectHeader->Flags & OB_FLAG_CREATOR_INFO是否为0 // 不为0则ObjectHeader上面为OBJECT_HEADER_CREATOR_INFO结构, OBJECT_HEADER_CREATOR_INFO中的TypeList连入ObpTypeObjectType->TypeList ObpEnterObjectTypeMutex( ObpTypeObjectType ); CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( NewObjectTypeHeader ); if (CreatorInfo != NULL) { InsertTailList( &ObpTypeObjectType->TypeList, &CreatorInfo->TypeList ); } // 全局有一个叫ObpObjectTypes的数组, 存储了所有的类型对象。当前类型的Index域是当前类型数组下标+1 NewObjectType->Index = ObpTypeObjectType->TotalNumberOfObjects; if (NewObjectType->Index < OBP_MAX_DEFINED_OBJECT_TYPES) { ObpObjectTypes[ NewObjectType->Index - 1 ] = NewObjectType; } ObpLeaveObjectTypeMutex( ObpTypeObjectType ); // 如果已经存在Directory类型, 用ObpInsertDirectoryEntry函数把当前创建的类型插入/ObjectTypes目录 // 根据第一次调用 ObInitSystem 函数初始化类型对象的顺序,Type类型对象时不会在这个目录中的。 // 在第二次初始化之前, 找到它的方法就是通过全局的ObpTypeObjectType变量, 或者ObpObjectTypes数组的第0项 if (!ObpTypeDirectoryObject || ObpInsertDirectoryEntry( ObpTypeDirectoryObject, &LookupContext, NewObjectTypeHeader )) { if (ObpTypeDirectoryObject) { ObReferenceObject( ObpTypeDirectoryObject ); } ObpReleaseLookupContext( &LookupContext ); *ObjectType = NewObjectType; return( STATUS_SUCCESS ); } else { ObpReleaseLookupContext( &LookupContext ); return( STATUS_INSUFFICIENT_RESOURCES ); } } 简单总结一下ObCreateObjectType。 所有类型对象都在 /ObjectTypes目录里, 使用ObpLookupDirectoryEntry可以查询这个目录, 若名字有冲突就出错。 ObpAllocateObject建立对象体和对象头, 这个函数以后再看。 ObCreateObjectType函数处理了Directory和Type对象没有建立好时的情况。 对象头结构是 kd> dt _OBJECT_HEADER nt!_OBJECT_HEADER +0x000 PointerCount : Int4B +0x004 HandleCount : Int4B +0x008 Type : Ptr32 _OBJECT_TYPE 这个域指向当前对象的类型, 对于类型对象它指向Type类型对象, Type对象指向Type对象本身, ObCreateObjectType函数处理了这种情况 +0x004 NextToFree : Ptr32 Void +0x00c NameInfoOffset : UChar +0x00d HandleInfoOffset : UChar +0x00e QuotaInfoOffset : UChar +0x00f Flags : UChar 有OB_FLAG_CREATOR_INFO标志说明紧挨着OBJECT_HEADER上面就是OBJECT_HEADER_CREATOR_INFO结构 +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION +0x010 QuotaBlockCharged : Ptr32 Void +0x014 SecurityDescriptor : Ptr32 Void +0x018 Body : _QUAD Type对象体结构是 kd> dt _OBJECT_TYPE nt!_OBJECT_TYPE +0x000 Mutex : _ERESOURCE +0x038 TypeList : _LIST_ENTRY 记录这个类型的所有对象、连入对象实例对应的OBJECT_HEADER_CREATOR_INFO结构 +0x040 Name : _UNICODE_STRING 对象名称(Directory、Type、SymbolicLink等) +0x048 DefaultObject : Ptr32 Void 用于同步 +0x04c Index : Uint4B Index - 1 当做ObpObjectTypes的下标找到自身, 这个数组中记录了所有的Type结构指针 +0x050 TotalNumberOfObjects : Uint4B +0x054 TotalNumberOfHandles : Uint4B +0x058 HighWaterNumberOfObjects : Uint4B +0x05c HighWaterNumberOfHandles : Uint4B +0x060 TypeInfo : _OBJECT_TYPE_INITIALIZER 这个结构记录了众多相关函数路径(如解析等) +0x0ac Key : Uint4B +0x0b0 ObjectLocks : [4] _ERESOURCE |
相关文章推荐
- 动态创建菜单,menustrip,根据权限显示菜单,控制菜单可用,反射,给窗体传值,反射对象传值,public static Object CreateInstance ( Type type, pa
- [转载内容]动态创建菜单,menustrip,根据权限显示菜单,控制菜单可用,反射,给窗体传值,反射对象传值,public static Object CreateInstance ( Type type, params Object[] args )
- 动态创建菜单,menustrip,根据权限显示菜单,控制菜单可用,反射,给窗体传值,反射对象传值,public static Object CreateInstance ( Type type, params Object[] args )
- 关于IIS无法创建'Scripting.FileSystemObject'对象
- OPC客户端调用时提示“无法将类型为“System.__ComObject”的 COM 对象强制转换为接口类型”...
- create type oracle 无返回 sql语句返回不了(创建对象 正斜杠的作用)
- JavaScript对象系统深入剖析3-创建对象Object.Create
- ActiveX 部件不能创建对象: 'Scripting.FileSystemObject'
- javascript一种新的对象创建方式-Object.create()
- Activator.CreateInstance(Type type)方法创建对象和Expression Tree创建对象性能的比较(终结版)
- 动态赋值弱类型值对象--Dynamic Create Value Object
- 运行时错误 (0x800A01AD) ActiveX 部件不能创建对象: 'Scripting.FileSystemObject'
- Object.create() --- javascript一种新的对象创建方式
- 一种新的javascript对象创建方式Object.create()
- 部分组件无法创建,Scripting.FileSystemObject(FSO)对象的建立基础!
- 【转】Oracle Object type 对象类型详解
- 1.在使用new创建数组后,此时数组还是一个引用数组。 只有再创建新的对象,并把对象赋值给数组引用,到此初始化结束2.什么是引用类型?
- javascript的创建对象object.create()和属性检测hasOwnPrototype()和propertyIsEnumerable()
- javascript一种新的对象创建方式-Object.create()
- 在使用Scripting.FileSystemObject 的时候报错automation服务器不能创建对象