Geoff Chappell - Software Analyst
The OBJECT_BASIC_INFORMATION structure is what a successful call to ZwQueryObject or NtQueryObject produces in its output buffer when given the information class ObjectBasicInformation (0). Most of the information so obtained is about whatever object is referenced by the Handle argument.
The OBJECT_BASIC_INFORMATION structure is not documented. This is plainly very much by design. A PUBLIC_OBJECT_BASIC_INFORMATION is defined in WINTERNL.H from the Software Development Kit (SDK) and in NTIFS.H from the Windows Driver Kit (WDK). Even then, this availability doesn’t begin until the kits for Windows 7. This public definition—which does, remember, have a different name—provides only the first four members plus an array which is commented as being “reserved for internal use”.
Microsoft does publish the practical equivalent of a C-language definition as type information in a handful of private symbol files that Microsoft has included in packages of public symbol files, starting with Windows 8, and continues to make available through Microsoft’s public symbol server. These private symbol files are not for the kernel, where the structure is prepared, nor even for low-level user-mode DLLs that interpret the structure. They are instead for various higher-level user-mode DLLs such as URLMON.DLL. The latter is here singled out because of its origins in Internet Explorer and thence for the strong suggestion that Microsoft’s programmers of Internet Explorer had access to more details of low-level Windows programming than Microsoft publishes for wider use.
Type information for the structure has also seeped out at the other end of the Windows timeline, though not in symbol files but in statically linked libraries: GDISRVL.LIB from the Device Driver Kit (DDK) for Windows NT 3.51; and SHELL32.LIB from the DDK for Windows NT 4.0.
The OBJECT_BASIC_INFORMATION is 0x38 bytes in both 32-bit and 64-bit Windows in all versions.
Offset | Definition | Versions |
---|---|---|
0x00 |
ULONG Attributes; |
all |
0x04 |
ULONG GrantedAccess; |
all |
0x08 |
ULONG HandleCount; |
all |
0x0C |
ULONG PointerCount; |
all |
0x10 |
ULONG PagedPoolCharge; |
all |
0x14 |
ULONG NonPagedPoolCharge; |
all |
0x18 |
ULONG TotalNumberOfObjects; |
3.10 only |
ULONG Reserved [3]; |
3.50 and higher | |
0x1C (3.10) |
ULONG TotalNumberOfHandles; |
3.10 only |
0x20 (3.10) | unknown dword | 3.10 only |
0x24 |
ULONG NameInfoSize; |
all |
0x28 |
ULONG TypeInfoSize; |
all |
0x2C |
ULONG SecurityDescriptorSize; |
all |
0x30 |
LARGE_INTEGER CreationTime; |
all |
The three dwords at offset 0x18 are known to be defined as Reserved as early as version 3.51. They are computed for version 3.10 but not for any version since. What distinguishes these three, when they were meaningful, is that they tell not directly of the one object that is referenced by the Handle argument but of all objects of the same type as that one object. The three are respectively the total numbers of objects, handles and references. Version 3.50 moves two of them to the OBJECT_TYPE_INFORMATION, which is where the names that are proposed above come from.
The three dwords at offset 0x24 tell how many bytes would be required for the output buffer if the caller proceeds to other queries for the same Handle:
These other queries produce some variable amount of information, e.g., a fixed-size structure followed by a variable-size name in Unicode characters. The caller who does not know in advance how big a buffer to provide can either guess or make two calls. But the caller who first queries for basic information can know in advance. In theory, sizes that will suffice for the other queries are available almost incidentally while computing the basic information. In practice, the knowledge is not exact. The TypeInfoSize can be too small in version 3.50 and higher because the query for ObjectTypeInformation rounds its size up to a multiple of four or eight bytes (in 32-bit and 64-bit Windows, respectively) but this is not accounted for when computing the TypeInfoSize.