Home > Articles > Operating Systems, Server > Microsoft Servers

  • Print
  • + Share This

Calling NtQuerySystemInformation()

Want some sample code? OK—out of the various subfunctions offered by NtQuerySystemInformation(), I have chosen the one that returns a process/thread list. Retrieving this list is a common problem that system programmers have to face, and this is also one of the few examples in which Windows NT 2000 and NT 4.0 behave differently. Actually, the specifications of NtQuerySystemInformation() and NtSetSystemInformation() have remained remarkably stable during the last major NT upgrade, except that more subfunctions were added. To my knowledge, only two of the NT4 subfunctions were changed significantly in Windows 2000, and one of them is the SystemProcessInformation subfunction we will examine now. In Windows 2000, the process structure it returns contains an additional member. Unfortunately, it is not located at the end, where it could have been safely ignored, so you have to check the operating system version before accessing the returned data.

Listing 2 shows the prototypes of NtQuerySystemInformation() and NtSetSystemInformation(). NtQuerySystemInformation() behaves similarly to other NtQuery*() functions, such as the semidocumented NtQueryInformationProcess() function. These functions usually require a zero-based Information Class parameter that selects the subfunction to be called. In Listing 2, this is the SystemInformationClass argument. SystemInformation is a pointer to a buffer allocated by the application that will receive the requested system data, and SystemInformationLength specifies its length. The format of the buffer varies dramatically, depending on the specified info class. On return, the optional ReturnLength argument indicates how many bytes were copied to the buffer. Unfortunately, several NtQuerySystemInformation() subfunctions return variable-length data and don't tell you the required buffer size in case of an overflow, so you will usually have to implement a trial-and-error loop to find out the correct size.

Listing 2 NtQuerySystemInformation() and NtSetSystemInformation()

NTSTATUS NTAPI
NtQuerySystemInformation (IN SYSTEMINFOCLASS SystemInformationClass,
             OUT PVOID      SystemInformation,
             IN DWORD      SystemInformationLength,
             OUT PDWORD     ReturnLength OPTIONAL);
NTSTATUS NTAPI
NtSetSystemInformation  (IN SYSTEMINFOCLASS SystemInformationClass,
             IN PVOID      SystemInformation,
             IN DWORD      SystemInformationLength);

In Listing 3, the system information classes available on Windows 2000 and NT 4.0 are defined. Please note the comment info classes specific to Windows 2000 that heads the subfunction numbers not available on NT 4.0. The info class we will use in the forthcoming example is named SystemProcessInformation (#5). Many NtQuerySystemInformation() subfunctions are merely wrappers around other internal ntoskrnl.exe functions; and in the case of SystemProcessInformation, the base function is ExpGetProcessInformation().

Listing 3 Available System Information Classes

typedef enum _SYSTEMINFOCLASS
  {
  SystemBasicInformation,       // 0x002C
  SystemProcessorInformation,     // 0x000C
  SystemPerformanceInformation,    // 0x0138
  SystemTimeInformation,       // 0x0020
  SystemPathInformation,       // not implemented
  SystemProcessInformation,      // 0x00F8+ per process
  SystemCallInformation,       // 0x0018 + (n * 0x0004)
  SystemConfigurationInformation,   // 0x0018
  SystemProcessorCounters,      // 0x0030 per cpu
  SystemGlobalFlag,          // 0x0004
  SystemInfo10,            // not implemented
  SystemModuleInformation,      // 0x0004 + (n * 0x011C)
  SystemLockInformation,       // 0x0004 + (n * 0x0024)
  SystemInfo13,            // not implemented
  SystemPagedPoolInformation,     // checked build only
  SystemNonPagedPoolInformation,   // checked build only
  SystemHandleInformation,      // 0x0004 + (n * 0x0010)
  SystemObjectInformation,      // 0x0038+ + (n * 0x0030+)
  SystemPagefileInformation,     // 0x0018+ per page file
  SystemInstemulInformation,     // 0x0088
  SystemInfo20,            // invalid info class
  SystemCacheInformation,       // 0x0024
  SystemPoolTagInformation,      // 0x0004 + (n * 0x001C)
  SystemProcessorStatistics,     // 0x0000, or 0x0018 per cpu
  SystemDpcInformation,        // 0x0014
  SystemMemoryUsageInformation1,   // checked build only
  SystemLoadImage,          // 0x0018, set mode only
  SystemUnloadImage,         // 0x0004, set mode only
  SystemTimeAdjustmentInformation,  // 0x000C, 0x0008 writeable
  SystemMemoryUsageInformation2,   // checked build only
  SystemInfo30,            // checked build only
  SystemInfo31,            // checked build only
  SystemCrashDumpInformation,     // 0x0004
  SystemExceptionInformation,     // 0x0010
  SystemCrashDumpStateInformation,  // 0x0008
  SystemDebuggerInformation,     // 0x0002
  SystemThreadSwitchInformation,   // 0x0030
  SystemRegistryQuotaInformation,   // 0x000C
  SystemLoadDriver,          // 0x0008, set mode only
  SystemPrioritySeparationInformation,// 0x0004, set mode only
  SystemInfo40,            // not implemented
  SystemInfo41,            // not implemented
  SystemInfo42,            // invalid info class
  SystemInfo43,            // invalid info class
  SystemTimeZoneInformation,     // 0x00AC
  SystemLookasideInformation,     // n * 0x0020
// info classes specific to Windows 2000
// WTS = Windows Terminal Server
  SystemSetTimeSlipEvent,       // set mode only
  SystemCreateSession,        // WTS, set mode only
  SystemDeleteSession,        // WTS, set mode only
  SystemInfo49,            // invalid info class
  SystemRangeStartInformation,    // 0x0004
  SystemVerifierInformation,     // 0x0068
  SystemAddVerifier,         // set mode only
  SystemSessionProcessesInformation, // WTS
  }
  SYSTEMINFOCLASS, *PSYSTEMINFOCLASS;

SystemProcessInformation is one of the NtQuerySystemInformation() subfunctions that return variable length data. The required buffer size depends on the number of processes and threads currently running. The data is returned in a single monolithic memory block, comprising a list of structures—one per process. Each process structure contains an array of fixed-length thread structures. Because the length of each process structure varies with the number of threads the corresponding process hosts, they are linked by a member that indicates how many bytes need to be skipped to get to the next list item. This scheme applies to several other NtQuerySystemInformation() subfunctions as well, except for some rare cases in which the link member specifies an absolute offset rather than a relative one.

  • + Share This
  • 🔖 Save To Your Account

Related Resources

There are currently no related titles. Please check back later.