Track down GDI and User handle leaks. You can identify which application leaks GDI/User handles. In the details view, you can see all the properties of the handles. For bitmaps, icons and cursors you see and save the real image.
On 32 and 64 Bit versions of Windows 10, Windows 8.1, Windows 8, Windows 7, Vista, Server 2012, Server 2008, Server 2003, XP, 2000 and NT4, Bear displays the usage of
All GDI Objects [hDC, hRegion, hBitmap, hPalette, hFont, hBrush]
All User Objects [hWnd, hMenu, hCursor, SetWindowsHookEx, SetTimer and some other stuff]
Handles
Memory pages count and size [LoadLibrary() and LoadLibraryEx(LOAD_LIBRARY_AS_DATAFILE)]
On Windows 98 and Windows 95, Bear displays the usage of
All GDI Objects [hDC, hRegion, hBitmap, hPalette, hFont, hBrush]
GDI, System and User Resources
Handle Details
A double click on a process opens the details view. Each GDI/User object is shown with a description. Make a right click onto Bitmaps, Icons and Cursors to save them.Delta
Changes are displayed in green and red to easily spot the differences.Logging
Enable logging to a CSV file to trace changes over time.If a specified handle count limit is reached, a notification can be send. Using Email, PubNub.com or logfile.
You don’t need to have a paypal account in order to make a donation.
Install using package managers:
winget install --id the-sz.Bear -e --forcecontent_copychoco install bear.portable -y --ignore-checksumcontent_copy
Supported Operating Systems:
Command line options:
/refresh <1000> | Refresh rate in milliseconds |
/log <file name> | Log file name |
/details <pid> | Show details for given pid |
/exportList <file.xml> | Export details handle list and exit, use in combination with /details |
Details:
I’m using several different functions to get the information:
gdi32.dll GdiQueryTable() | usable on Windows NT 4 up to Windows XP |
PEB->GdiSharedHandleTable | usable on Windows NT 4 and higher |
user32.dll gSharedInfo->aheList / HANDLEENTRY | usable on Windows NT 4 and higher |
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 and higher |
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 |
kernel32.dll VirtualQueryEx() | usable on Windows NT 4 and higher |
Some details about the used GDI Objects method:
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.#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); /* (wHandleType & 0x1F) HGDIOBJ 0x01 hDC 0x04 hRegion 0x05 hBitmap 0x08 hPalette 0x0A hFont 0x10 hBrush all other unknown */
Some details about the used User Objects method:
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. */