This program displays under Windows 98:
To get the shown information I'm using several different functions:
#define GDI_TABLE_MAX_ENTRIES 16384
// 16 bytes large
#pragma pack(1)
typedef struct
{
} GDI_TABLE_ENTRY_STRUCT;
#pragma pack()
typedef GDI_TABLE_ENTRY_STRUCT *(WINAPI *GDI_QUERY_TABLE_FUNCTION)(void);
usable on Windows NT 4 up to Windows XP | |
usable on Windows 2000 and higher | |
usable on Windows XP SP1 and higher | |
usable on Windows NT 4 up to Windows XP | |
usable on Windows 2000 up to Windows XP | |
usable on Windows 95/98 only | |
usable on Windows 95/98 only |
The function gdi32.dll:GdiQueryTable returns a pointer to a table with all GDI Objects currently present
in Windows. It can contain up to 16384 entries. On Windows NT4, member 'wProcessIdVersion4' contains the owner process id. On Windows 2000 and above, 'wProcessIdVersion5' contains the owner process id.
After masking 'wHandleType' with 0x1F you get the handle type.
wHandleType & 0x1F | HGDIOBJ | |
0x01 | hDC | |
0x04 | hRegion | |
0x05 | hBitmap | |
0x08 | hPalette | |
0x0A | hFont | |
0x10 | hBrush | |
all other | unknown |
#define GDI_TABLE_MAX_ENTRIES 16384
// 16 bytes large
#pragma pack(1)
typedef struct
{
DWORD | dwHandle; | // must be >0x80000000 | |
WORD | wProcessIdVersion5; | ||
WORD | wProcessIdVersion4; | ||
WORD | wUnknown; | ||
WORD | wHandleType; | // mask with 0x1F | |
DWORD | dwUnknown; |
#pragma pack()
typedef GDI_TABLE_ENTRY_STRUCT *(WINAPI *GDI_QUERY_TABLE_FUNCTION)(void);
The function user32.dll:QueryUserCounters fills an array with the counts of all user objects.
The real function name is NtUserQueryUserCounters(). This is a stub to the function _QueryUserHandles().
Please note SetTimer() and SetClipboardData() handles are always counted for pid 0 (Idle Process) because they are not owned by the process itself.
I'm using as pvIn only one process id. Therefore dwInSize is sizeof(DWORD). pvResult must point to an array which has the exact size for all possible User Object counts. Under Windows 2000 there are 18, under Windows XP 20. Therefore dwOutSize is 18*sizeof(DWORD) or 20*sizeof(DWORD).
Please note SetTimer() and SetClipboardData() handles are always counted for pid 0 (Idle Process) because they are not owned by the process itself.
typedef BOOL (__stdcall *QUERY_USER_COUNTERS)(IN DWORD dwQueryType,IN LPVOID pvIn,IN DWORD dwInSize,OUT LPVOID pvResult,IN DWORD dwOutSize);
#define QUERYUSER_TYPE_USER 0x01
#define QUERYUSER_TYPE_USER 0x01
- dwQueryType: QUERYUSER_TYPE_USER.
- pvIn: pointer to an array of process id DWORD's.
- dwInSize: size of process id array.
- pvResult: pointer to an array for the User Object count DWORD's
- dwOutSize: size of count array.
I'm using as pvIn only one process id. Therefore dwInSize is sizeof(DWORD). pvResult must point to an array which has the exact size for all possible User Object counts. Under Windows 2000 there are 18, under Windows XP 20. Therefore dwOutSize is 18*sizeof(DWORD) or 20*sizeof(DWORD).
© by ß |