diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index b0f8732b0ee..3a0e9630d87 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -56,7 +56,8 @@ typedef enum _USER_OBJECT_TYPE otHidData, otDeviceInfo, otTouchInput, - otGestureInfo + otGestureInfo, + USER_HANDLE_TYPE_COUNT } USER_OBJECT_TYPE; typedef enum _USERTHREADINFOCLASS diff --git a/reactos/win32ss/user/ntuser/main.c b/reactos/win32ss/user/ntuser/main.c index 6b9a5ed0ce1..92217d6a9e2 100644 --- a/reactos/win32ss/user/ntuser/main.c +++ b/reactos/win32ss/user/ntuser/main.c @@ -26,6 +26,7 @@ PSERVERINFO gpsi = NULL; // Global User Server Information. SHORT gusLanguageID; PPROCESSINFO ppiScrnSaver; +PPROCESSINFO gppiList = NULL; extern ULONG_PTR Win32kSSDT[]; extern UCHAR Win32kSSPT[]; @@ -55,7 +56,7 @@ APIENTRY Win32kProcessCallback(struct _EPROCESS *Process, BOOLEAN Create) { - PPROCESSINFO ppiCurrent; + PPROCESSINFO ppiCurrent, *pppi; DECLARE_RETURN(NTSTATUS); ASSERT(Process->Peb); @@ -160,6 +161,10 @@ Win32kProcessCallback(struct _EPROCESS *Process, ASSERT(ppiCurrent->pPoolDcAttr); ASSERT(ppiCurrent->pPoolBrushAttr); ASSERT(ppiCurrent->pPoolRgnAttr); + + /* Add the process to the global list */ + ppiCurrent->ppiNext = gppiList; + gppiList = ppiCurrent; } else { @@ -212,11 +217,25 @@ Win32kProcessCallback(struct _EPROCESS *Process, if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL; + pppi = &gppiList; + while (*pppi != NULL && *pppi != ppiCurrent) + pppi = &(*pppi)->ppiNext; + + ASSERT(*pppi == ppiCurrent); + + *pppi = ppiCurrent->ppiNext; + TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent); /* Ftee the PROCESSINFO */ PsSetProcessWin32Process(Process, NULL); ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO); +#if DBG + if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL)) + { + DbgUserDumpHandleTable(); + } +#endif } RETURN( STATUS_SUCCESS); diff --git a/reactos/win32ss/user/ntuser/ntuser.h b/reactos/win32ss/user/ntuser/ntuser.h index b45a2d0843b..aab3ba3249e 100644 --- a/reactos/win32ss/user/ntuser/ntuser.h +++ b/reactos/win32ss/user/ntuser/ntuser.h @@ -12,6 +12,7 @@ extern BOOL gbInitialized; extern PSERVERINFO gpsi; extern PTHREADINFO gptiCurrent; +extern PPROCESSINFO gppiList; extern PPROCESSINFO ppiScrnSaver; extern PPROCESSINFO gppiInputProvider; diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index fdb318d081f..8117363417b 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -12,6 +12,66 @@ DBG_DEFAULT_CHANNEL(UserObj); //int usedHandles=0; PUSER_HANDLE_TABLE gHandleTable = NULL; +#if DBG + +void DbgUserDumpHandleTable() +{ + int HandleCounts[USER_HANDLE_TYPE_COUNT]; + PPROCESSINFO ppiList; + int i; + PWCHAR TypeNames[] = {L"Free",L"Window",L"Menu", L"CursorIcon", L"SMWP", L"Hook", L"ClipBoardData", L"CallProc", + L"Accel", L"DDEaccess", L"DDEconv", L"DDExact", L"Monitor", L"KBDlayout", L"KBDfile", + L"Event", L"Timer", L"InputContext", L"HidData", L"DeviceInfo", L"TouchInput",L"GestureInfo"}; + + ERR("Total handles count: %d\n", gpsi->cHandleEntries); + + memset(HandleCounts, 0, sizeof(HandleCounts)); + + /* First of all count the number of handles per tpe */ + ppiList = gppiList; + while (ppiList) + { + ERR("Process %s (%d) handles count: %d\n\t", ppiList->peProcess->ImageFileName, ppiList->peProcess->UniqueProcessId, ppiList->UserHandleCount); + + for (i = 1 ;i < USER_HANDLE_TYPE_COUNT; i++) + { + HandleCounts[i] += ppiList->DbgHandleCount[i]; + + DbgPrint("%S: %d, ", TypeNames[i], ppiList->DbgHandleCount[i]); + if (i % 6 == 0) + DbgPrint("\n\t"); + } + DbgPrint("\n"); + + ppiList = ppiList->ppiNext; + } + + /* Print total type counts */ + ERR("Total handles of the running processes: \n\t"); + for (i = 1 ;i < USER_HANDLE_TYPE_COUNT; i++) + { + DbgPrint("%S: %d, ", TypeNames[i], HandleCounts[i]); + if (i % 6 == 0) + DbgPrint("\n\t"); + } + DbgPrint("\n"); + + /* Now count the handle counts that are allocated from the handle table */ + memset(HandleCounts, 0, sizeof(HandleCounts)); + for (i = 0; i < gHandleTable->nb_handles; i++) + HandleCounts[gHandleTable->handles[i].type]++; + + ERR("Total handles count allocated: \n\t"); + for (i = 1 ;i < USER_HANDLE_TYPE_COUNT; i++) + { + DbgPrint("%S: %d, ", TypeNames[i], HandleCounts[i]); + if (i % 6 == 0) + DbgPrint("\n\t"); + } + DbgPrint("\n"); +} + +#endif PUSER_HANDLE_ENTRY handle_to_entry(PUSER_HANDLE_TABLE ht, HANDLE handle ) { @@ -51,55 +111,12 @@ __inline static PUSER_HANDLE_ENTRY alloc_user_entry(PUSER_HANDLE_TABLE ht) if (ht->nb_handles >= ht->allocated_handles) /* Need to grow the array */ { -/**/ - int i, iFree = 0, iWindow = 0, iMenu = 0, iCursorIcon = 0, - iHook = 0, iCallProc = 0, iAccel = 0, iMonitor = 0, iTimer = 0, iEvent = 0, iSMWP = 0; - /**/ - ERR("Out of user handles! Used -> %i, NM_Handle -> %d\n", gpsi->cHandleEntries, ht->nb_handles); -//#if 0 - for(i = 0; i < ht->nb_handles; i++) - { - switch (ht->handles[i].type) - { - case otFree: // Should be zero. - iFree++; - break; - case otWindow: - iWindow++; - break; - case otMenu: - iMenu++; - break; - case otCursorIcon: - iCursorIcon++; - break; - case otHook: - iHook++; - break; - case otCallProc: - iCallProc++; - break; - case otAccel: - iAccel++; - break; - case otMonitor: - iMonitor++; - break; - case otTimer: - iTimer++; - break; - case otEvent: - iEvent++; - break; - case otSMWP: - iSMWP++; - default: - break; - } - } - ERR("Handle Count by Type:\n Free = %d Window = %d Menu = %d CursorIcon = %d Hook = %d\n CallProc = %d Accel = %d Monitor = %d Timer = %d Event = %d SMWP = %d\n", - iFree, iWindow, iMenu, iCursorIcon, iHook, iCallProc, iAccel, iMonitor, iTimer, iEvent, iSMWP ); -//#endif + ERR("Out of user handles! Used -> %i, NM_Handle -> %d\n", gpsi->cHandleEntries, ht->nb_handles); + +#if DBG + DbgUserDumpHandleTable(); +#endif + return NULL; #if 0 PUSER_HANDLE_ENTRY new_handles; @@ -138,6 +155,11 @@ __inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY { PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); void *ret; + +#if DBG + ppi->DbgHandleCount[entry->type]--; +#endif + ret = entry->ptr; entry->ptr = ht->freelist; entry->type = 0; @@ -339,6 +361,10 @@ UserCreateObject( PUSER_HANDLE_TABLE ht, return NULL; } +#if DBG + ppi->DbgHandleCount[type]++; +#endif + RtlZeroMemory(Object, size); switch (type) diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index eabc6558616..cad7ce2e0df 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -39,6 +39,7 @@ PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, USER_OBJECT_TYPE); BOOL FASTCALL UserCreateHandleTable(VOID); BOOL FASTCALL UserObjectInDestroy(HANDLE); +void DbgUserDumpHandleTable(); static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry) diff --git a/reactos/win32ss/user/ntuser/win32.h b/reactos/win32ss/user/ntuser/win32.h index a6290e62b81..4bec70a8772 100644 --- a/reactos/win32ss/user/ntuser/win32.h +++ b/reactos/win32ss/user/ntuser/win32.h @@ -195,6 +195,7 @@ typedef struct _PROCESSINFO PTHREADINFO ptiList; PTHREADINFO ptiMainThread; struct _DESKTOP* rpdeskStartup; + PPROCESSINFO ppiNext; PCLS pclsPrivateList; PCLS pclsPublicList; INT cThreads; @@ -224,6 +225,7 @@ typedef struct _PROCESSINFO #if DBG BYTE DbgChannelLevel[DbgChCount]; + DWORD DbgHandleCount[USER_HANDLE_TYPE_COUNT]; #endif } PROCESSINFO; diff --git a/reactos/win32ss/user/ntuser/win32kdebug.h b/reactos/win32ss/user/ntuser/win32kdebug.h index 83de71a8314..d26c4c18796 100644 --- a/reactos/win32ss/user/ntuser/win32kdebug.h +++ b/reactos/win32ss/user/ntuser/win32kdebug.h @@ -125,7 +125,7 @@ #define DBG_ENABLE_CHANNEL(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] |= level) #define DBG_DISABLE_CHANNEL(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] &= ~level) - #define DBG_IS_CHANNEL_ENABLED(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] & level) + #define DBG_IS_CHANNEL_ENABLED(ppi,ch,level) (((ppi)->DbgChannelLevel[ch] & level) == level) #define DBG_PRINT(ppi,ch,level,fmt, ...) do { \ if((level == ERR_LEVEL) || (ppi && DBG_IS_CHANNEL_ENABLED(ppi,ch,level))) \