Undocumented structures in Delphi
Undocumented or poorly-documented Windows structures translated to Delphi
If you’ve ever tried to do any Delphi system-level programming, you’ll understand what this page is all about. If you’re looking for the documented structures and APIs, Project JEDI’s API lib is the place to start.
NtQuerySystemInformation
Like all ntdll.dll APIs, this one doesn’t show up in standard MS headers either. It also tends to show up even less in Delphi source code…
function NtQuerySystemInformation(SystemInformationClass:DWORD; SystemInformation:pointer; SystemInformationLength:DWORD; ReturnLength:PDWORD):cardinal; stdcall; external 'ntdll';
UNICODE_STRING
Ubiquitous Windows device driver structure, but not defined in Delphi.
PUNICODE_STRING = ^UNICODE_STRING; UNICODE_STRING = packed record Length: Word; MaximumLength: Word; Buffer: PWideChar; end;
SYSTEM_PROCESS_INFORMATION, VM_COUNTERS, IO_COUNTERS and SYSTEM_THREAD
SYSTEM_PROCESS_INFORMATION is used by NtQuerySystemInformation with SystemInformation set to SystemProcessInformation (5); the latter three are members of SYSTEM_PROCESS_INFORMATION.
VM_COUNTERS = packed record PeakVirtualSize: DWORD; VirtualSize: DWORD; PageFaultCount: DWORD; PeakWorkingSetSize: DWORD; WorkingSetSize: DWORD; QuotaPeakPagedPoolUsage: DWORD; QuotaPagedPoolUsage: DWORD; QuotaPeakNonPagedPoolUsage: DWORD; QuotaNonPagedPoolUsage: DWORD; PageFileUsage: DWORD; PeakPageFileUsage: DWORD; end; IO_COUNTERS = packed record ReadOperationCount: LARGE_INTEGER; WriteOperationCount: LARGE_INTEGER; OtherOperationCount: LARGE_INTEGER; ReadTransferCount: LARGE_INTEGER; // I/O Read Bytes in Process Explorer WriteTransferCount: LARGE_INTEGER; // I/O Write Bytes in Process Explorer OtherTransferCount: LARGE_INTEGER; // I/O Other Bytes in Process Explorer end; SYSTEM_THREAD = packed record KernelTime: LARGE_INTEGER; UserTime: LARGE_INTEGER; CreateTime: LARGE_INTEGER; WaitTime: DWORD; StartAddress: DWORD; // starting address of the thread UniqueProcess: DWORD; // process ID (PID) UniqueThread: DWORD; // thread ID (TID) Priority: integer; // current priority BasePriority: DWORD; // initial priority ContextSwitchCount: DWORD; State: integer; // thead state: active (<5), waiting (5) WaitReason: integer; // waiting reason (5 = suspended) Reserved1:DWORD; end; PSYSTEM_PROCESS_INFORMATION = ^SYSTEM_PROCESS_INFORMATION; SYSTEM_PROCESS_INFORMATION = packed record NextEntryOffset: DWORD; NumberOfThreads: DWORD; Reserved1: array [0..5] of DWORD; CreateTime: FILETIME; UserTime: FILETIME; KernelTime: FILETIME; ModuleName: UNICODE_STRING; // full image path name BasePriority: integer; ProcessID: DWORD; InheritedFromProcessId: DWORD; // parent PID HandleCount: DWORD; Reserved2: array[0..1] of DWORD; VirtualMemoryCounters: VM_COUNTERS; PrivatePageCount: DWORD; IoCounters: IO_COUNTERS; ThreadInfo: array[0..0] of SYSTEM_THREAD; end;
The latter two are wrongfully documented on undocumented.ntinternals.net here and here, respectively: SYSTEM_PROCESS_INFORMATION has the members VirtualMemoryCounters and PrivatePageCount in the wrong order, while SYSTEM_THREAD is missing the last DWORD.
OBJECT_ATTRIBUTES
This structure is used by the native API instead of plain string names for all objects (files, registry keys etc.).
POBJECT_ATTRIBUTES = ^OBJECT_ATTRIBUTES; OBJECT_ATTRIBUTES = packed record Length: Cardinal; RootDirectory: THandle; ObjectName: PUNICODE_STRING; Attributes: Cardinal; SecurityDescriptor: Pointer; SecurityQualityOfService: Pointer; end;