public static IntPtr NtQueryObject(SafeFileHandle objectHandle, OBJECT_INFORMATION_CLASS informationClass, uint informationLength = 0) { // http://www.pinvoke.net/default.aspx/ntdll.ntqueryobject if (informationLength == 0) { informationLength = (uint)Marshal.SizeOf <uint>(); } var informationPointer = Marshal.AllocHGlobal((int)informationLength); var tries = 0; NtStatus result; while (true) { result = Ntdll.NtQueryObject(objectHandle, informationClass, informationPointer, informationLength, ref informationLength); if (result == NtStatus.InfoLengthMismatch || result == NtStatus.BufferOverflow || result == NtStatus.BufferTooSmall) { Marshal.FreeHGlobal(informationPointer); // todo why not just allocate this to begin with? informationPointer = Marshal.AllocHGlobal((int)informationLength); tries++; } else if (result == NtStatus.Success || tries > 5) { break; } else { //throw new Exception("Unhandled NtStatus " + result); break; } } if (result == NtStatus.Success) { return(informationPointer); //don't forget to free the pointer with Marshal.FreeHGlobal after you're done with it } Marshal.FreeHGlobal(informationPointer); //free pointer when not Successful return(IntPtr.Zero); }
private static IEnumerable <Object> QueryDirectoryObjects(SafeFileHandle directoryHandle) { var bufferSize = 1024; var buffer = Marshal.AllocHGlobal(bufferSize); uint context = 0; // todo use object model here too var objects = new List <Object>(); for (;;) { var status = Ntdll.NtQueryDirectoryObject(directoryHandle, buffer, bufferSize, true, context == 0, ref context, out var lengthRead); if (status < 0) { break; } var objectDirectoryInformation = Marshal.PtrToStructure <OBJECT_DIRECTORY_INFORMATION>(buffer); objects.Add(objectDirectoryInformation.ToObject()); } Marshal.FreeHGlobal(buffer); return(objects); }