Bear::See GDI/User Object usage of all processes
Description:
This program displays for every process under Windows NT:
  • the usage of all GDI Objects [hDC, hRegion, hBitmap, hPalette, hFont, hBrush]
  • the usage of all User Objects [hWnd, hMenu, hCursor, SetWindowsHookEx, SetTimer and some other stuff].
  • the handle count.

    This program displays under Windows 98:
  • the usage of all GDI Objects [hDC, hRegion, hBitmap, hPalette, hFont, hBrush].
  • the usage of GDI, System and User Resources.

    Details:
    To get the shown information I'm using several different functions:

  • gdi32.dll:GdiQueryTable()
  • usable on Windows NT 4 up to Windows XP
  • user32.dll:GetGuiResources()
  • usable on Windows 2000 and higher
  • kernel32.dll:GetProcessHandleCount()
  • usable on Windows XP SP1 and higher
  • ntdll.dll:NtQuerySystemInformation()
  • usable on Windows NT 4 up to Windows XP
  • user32.dll:QueryUserCounters()
  • usable on Windows 2000 up to Windows XP
  • gdi32.dll:GetObjectType()
  • usable on Windows 95/98 only
  • rsrc32.dll:MyGetFreeSystemResources32()    
  • usable on Windows 95/98 only
    Some details about the used GDI Objects method for Windows NT:

    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;  
    } GDI_TABLE_ENTRY_STRUCT;
    #pragma pack()

    typedef GDI_TABLE_ENTRY_STRUCT *(WINAPI *GDI_QUERY_TABLE_FUNCTION)(void);


    Some details about the used User Objects method for Windows NT:

    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.

    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
    • 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).

    Windows XP:

    Windows 7:

    Windows 98:

    © by ß

    run_to_sz@gmx.net