C# – Get object type number in Windows 64 bits

I am trying to port some C++ code into C# which then should run on a 64 bits operating system. It’s not easy for me to do that because all of functions which I need, are relevant to system API with little documentations and examples because only system programmers works with these API. The fact that it may be simple when implementing on OS 32 bits. However on OS 64 bits there are difference at the size of pointer and therefore I must adjust code so that it can run smoothly. One of the code snippets which I want to port is getting object type number of a defined type through API NtQueryObject so that I can get type number of a object type like following

int nFileObjectTypeNumber = GetObjectTypeNumber("File");

NtQueryObject retrieves various kinds of object information. Therefore if I want to get number of a defined object, I should query information of all types and makes a loop to find out the object number of that type.

1. Query all types information

To query information of all types, I must use NtQueryObject with option of ObjectAllTypesInformation. Because NTQueryObject does not give back the correct buffer size so I guess by running loop until we do not have result of STATUS_INFO_LENGTH_MISMATCH any more

public enum ObjectInformationClass : int
{
	ObjectBasicInformation = 0,
	ObjectNameInformation = 1,
	ObjectTypeInformation = 2,
	ObjectAllTypesInformation = 3,
	ObjectHandleInformation = 4
}
public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;

IntPtr ipBufferObjectType = IntPtr.Zero;
int nLength = 0;

while ((uint)NtQueryObject(0, (int) ObjectInformationClass.ObjectAllTypesInformation, ipBufferObjectType, nLength, ref nLength) == STATUS_INFO_LENGTH_MISMATCH)
{
        Marshal.FreeHGlobal(ipBufferObjectType);
	ipBufferObjectType = Marshal.AllocHGlobal(nLength);
}

After looping to get information of all types, the pointer ipBufferObjectType will point to a memory section has a following structure.

As you can see in image above, the pointer points to first field which indicates how many types are there in the operation system. To get quantity of these types we can read value at that pointer. However the pointer size of 64 bits OS is 8 bytes, therefore the size of this field is 8 bytes too. So we must read completely 8 bytes and jump to the first object type.

if (Is64Bits())
{
	lTypeCount = Marshal.ReadInt64(ipBufferObjectType, 0);
	ipTypeInfo = new IntPtr(ipBufferObjectType.ToInt64() + 8);
}
else
{
	lTypeCount = Marshal.ReadInt32(ipBufferObjectType, 0);
	ipTypeInfo = new IntPtr(ipBufferObjectType.ToInt32() + 4);
}

2. Loop and find object number of type
After define how many types are there, we make a for-loop, get name of each object type and compare it to our desired one. If we found it then give result back.

for (int nIndex = 0; nIndex < lTypeCount; nIndex++)
{
	IntPtr ipTemp = IntPtr.Zero;
	Int64 nSize = 0;
	otiTemp = (OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipTypeInfo, otiTemp.GetType());
	if (Is64Bits())
	{
		ipTemp = new IntPtr(Convert.ToInt64(otiTemp.Name.Buffer.ToString(), 10) >> 32);
		nSize =  ipTemp.ToInt64() - ipTypeInfo.ToInt64() ;
	}
	else
	{
		ipTemp = otiTemp.Name.Buffer;
		nSize = ipTemp.ToInt32() - ipTypeInfo.ToInt32();
	}

	strType = Marshal.PtrToStringUni(ipTemp, otiTemp.Name.Length >> 1);
	if (p == strType)
	{
		return nIndex + 1;
	}
	if (Is64Bits())
	{
		ipTypeInfo = new IntPtr(ipTypeInfo.ToInt64() + nSize + otiTemp.Name.MaximumLength);
		while (ipTypeInfo.ToInt64() % 8 != 0)
		{
			ipTypeInfo = new IntPtr(ipTypeInfo.ToInt64() + 1);
		}
	}
	else
	{
		ipTypeInfo = new IntPtr(ipTypeInfo.ToInt32() + nSize + otiTemp.Name.MaximumLength);
		while (ipTypeInfo.ToInt64() % 4 != 0)
		{
			ipTypeInfo = new IntPtr(ipTypeInfo.ToInt64() + 1);
		}
	}
}

In the loop, you can see that I calculate the size of OBJECT_TYPE_INFORMATION too. This task can be done with Marshal.SizeOf(otiTemp) but I found out that it lacks 4 bytes when using on 64 bits system therefore I decide to calculate it myself by substracting pointer of section name by pointer to object type. At the end, I must parse the pointer so that it jumps correctly to the next object type section.
The complete source code you can download here “Get Object Type Number

Leave a Reply

Your email address will not be published. Required fields are marked *