[TASKMGR] Fix number formatting to respect NLS Number format settings (#4657)

TaskMgr currently does not respect local NLS settings and forces 3 digits + comma (US convention) formatting.
Fix this with a direct reuse of SH_FormatInteger() as already implemented in other places
(dll/win32/shell32/dialogs/filedefext.cpp ...)

- Removal of CommaSeparateNumberString() and replace with SH_FormatInteger().
- PerfDataGetText(): Use a switch structure.  Return TRUE iftext could be retrieved; FALSE if not.

Co-authored-by: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Co-authored-by: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
This commit is contained in:
Kyle Katarn 2022-09-04 19:10:11 +02:00 committed by GitHub
parent 15b54c4123
commit 15a0f7adb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 185 additions and 143 deletions

View file

@ -14,6 +14,7 @@
#include <windef.h> #include <windef.h>
#include <winbase.h> #include <winbase.h>
#include <wingdi.h> #include <wingdi.h>
#include <winnls.h>
#include <winuser.h> #include <winuser.h>
#include <winreg.h> #include <winreg.h>
#include <commctrl.h> #include <commctrl.h>

View file

@ -58,7 +58,6 @@ void AddProcess(ULONG Index);
void UpdateProcesses(); void UpdateProcesses();
void gethmsfromlargeint(LARGE_INTEGER largeint, DWORD *dwHours, DWORD *dwMinutes, DWORD *dwSeconds); void gethmsfromlargeint(LARGE_INTEGER largeint, DWORD *dwHours, DWORD *dwMinutes, DWORD *dwSeconds);
void ProcessPageOnNotify(WPARAM wParam, LPARAM lParam); void ProcessPageOnNotify(WPARAM wParam, LPARAM lParam);
void CommaSeparateNumberString(LPWSTR strNumber, ULONG nMaxCount);
void ProcessPageShowContextMenu(DWORD dwProcessId); void ProcessPageShowContextMenu(DWORD dwProcessId);
BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount); BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount);
DWORD WINAPI ProcessPageRefreshThread(void *lpParameter); DWORD WINAPI ProcessPageRefreshThread(void *lpParameter);
@ -324,20 +323,68 @@ void ProcessPageOnNotify(WPARAM wParam, LPARAM lParam)
} }
} }
void CommaSeparateNumberString(LPWSTR strNumber, ULONG nMaxCount) /*
* Adapted from SH_FormatInteger in dll/win32/shell32/dialogs/filedefext.cpp.
*/
UINT
SH_FormatInteger(
_In_ LONGLONG Num,
_Out_writes_z_(cchResultMax) LPWSTR pwszResult,
_In_ UINT cchResultMax)
{ {
WCHAR temp[260]; NUMBERFMTW nf;
UINT i, j, k; INT i;
INT cchGrouping, cchResult;
WCHAR wszNumber[24];
WCHAR wszDecimalSep[8], wszThousandSep[8];
WCHAR wszGrouping[12];
for (i=0,j=0; i<(wcslen(strNumber) % 3); i++, j++) /* Print the number in uniform mode */
temp[j] = strNumber[i]; StringCchPrintfW(wszNumber, _countof(wszNumber), L"%I64u", Num);
for (k=0; i<wcslen(strNumber); i++,j++,k++) {
if ((k % 3 == 0) && (j > 0)) /* Get system strings for decimal and thousand separators */
temp[j++] = L','; GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, wszDecimalSep, _countof(wszDecimalSep));
temp[j] = strNumber[i]; GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, wszThousandSep, _countof(wszThousandSep));
/* Initialize format for printing the number in bytes */
ZeroMemory(&nf, sizeof(nf));
nf.lpDecimalSep = wszDecimalSep;
nf.lpThousandSep = wszThousandSep;
/* Get system string for groups separator */
cchGrouping = GetLocaleInfoW(LOCALE_USER_DEFAULT,
LOCALE_SGROUPING,
wszGrouping,
_countof(wszGrouping));
/* Convert grouping specs from string to integer */
for (i = 0; i < cchGrouping; i++)
{
WCHAR wch = wszGrouping[i];
if (wch >= L'0' && wch <= L'9')
nf.Grouping = nf.Grouping * 10 + (wch - L'0');
else if (wch != L';')
break;
} }
temp[j] = L'\0';
wcsncpy(strNumber, temp, nMaxCount); if ((nf.Grouping % 10) == 0)
nf.Grouping /= 10;
else
nf.Grouping *= 10;
/* Format the number */
cchResult = GetNumberFormatW(LOCALE_USER_DEFAULT,
0,
wszNumber,
&nf,
pwszResult,
cchResultMax);
if (!cchResult)
return 0;
/* GetNumberFormatW returns number of characters including UNICODE_NULL */
return cchResult - 1;
} }
void ProcessPageShowContextMenu(DWORD dwProcessId) void ProcessPageShowContextMenu(DWORD dwProcessId)
@ -561,140 +608,134 @@ void AddProcess(ULONG Index)
BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount) BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount)
{ {
IO_COUNTERS iocounters; IO_COUNTERS iocounters;
LARGE_INTEGER time;
if (ColumnDataHints[ColumnIndex] == COLUMN_IMAGENAME) switch (ColumnDataHints[ColumnIndex])
PerfDataGetImageName(Index, lpText, nMaxCount);
if (ColumnDataHints[ColumnIndex] == COLUMN_PID)
wsprintfW(lpText, L"%lu", PerfDataGetProcessId(Index));
if (ColumnDataHints[ColumnIndex] == COLUMN_USERNAME)
PerfDataGetUserName(Index, lpText, nMaxCount);
if (ColumnDataHints[ColumnIndex] == COLUMN_COMMANDLINE)
PerfDataGetCommandLine(Index, lpText, nMaxCount);
if (ColumnDataHints[ColumnIndex] == COLUMN_SESSIONID)
wsprintfW(lpText, L"%lu", PerfDataGetSessionId(Index));
if (ColumnDataHints[ColumnIndex] == COLUMN_CPUUSAGE)
wsprintfW(lpText, L"%02lu", PerfDataGetCPUUsage(Index));
if (ColumnDataHints[ColumnIndex] == COLUMN_CPUTIME)
{ {
DWORD dwHours; case COLUMN_IMAGENAME:
DWORD dwMinutes; PerfDataGetImageName(Index, lpText, nMaxCount);
DWORD dwSeconds; return TRUE;
time = PerfDataGetCPUTime(Index); case COLUMN_PID:
gethmsfromlargeint(time, &dwHours, &dwMinutes, &dwSeconds); StringCchPrintfW(lpText, nMaxCount, L"%lu", PerfDataGetProcessId(Index));
wsprintfW(lpText, L"%lu:%02lu:%02lu", dwHours, dwMinutes, dwSeconds); return TRUE;
}
if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGE) case COLUMN_USERNAME:
{ PerfDataGetUserName(Index, lpText, nMaxCount);
wsprintfW(lpText, L"%lu", PerfDataGetWorkingSetSizeBytes(Index) / 1024); return TRUE;
CommaSeparateNumberString(lpText, nMaxCount);
wcscat(lpText, L" K"); case COLUMN_COMMANDLINE:
} PerfDataGetCommandLine(Index, lpText, nMaxCount);
if (ColumnDataHints[ColumnIndex] == COLUMN_PEAKMEMORYUSAGE) return TRUE;
{
wsprintfW(lpText, L"%lu", PerfDataGetPeakWorkingSetSizeBytes(Index) / 1024); case COLUMN_SESSIONID:
CommaSeparateNumberString(lpText, nMaxCount); StringCchPrintfW(lpText, nMaxCount, L"%lu", PerfDataGetSessionId(Index));
wcscat(lpText, L" K"); return TRUE;
}
if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGEDELTA) case COLUMN_CPUUSAGE:
{ StringCchPrintfW(lpText, nMaxCount, L"%02lu", PerfDataGetCPUUsage(Index));
wsprintfW(lpText, L"%lu", PerfDataGetWorkingSetSizeDelta(Index) / 1024); return TRUE;
CommaSeparateNumberString(lpText, nMaxCount);
wcscat(lpText, L" K"); case COLUMN_CPUTIME:
} {
if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTS) LARGE_INTEGER time;
{ DWORD dwHours;
wsprintfW(lpText, L"%lu", PerfDataGetPageFaultCount(Index)); DWORD dwMinutes;
CommaSeparateNumberString(lpText, nMaxCount); DWORD dwSeconds;
}
if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTSDELTA) time = PerfDataGetCPUTime(Index);
{ gethmsfromlargeint(time, &dwHours, &dwMinutes, &dwSeconds);
wsprintfW(lpText, L"%lu", PerfDataGetPageFaultCountDelta(Index)); StringCchPrintfW(lpText, nMaxCount, L"%lu:%02lu:%02lu", dwHours, dwMinutes, dwSeconds);
CommaSeparateNumberString(lpText, nMaxCount); return TRUE;
} }
if (ColumnDataHints[ColumnIndex] == COLUMN_VIRTUALMEMORYSIZE)
{ case COLUMN_MEMORYUSAGE:
wsprintfW(lpText, L"%lu", PerfDataGetVirtualMemorySizeBytes(Index) / 1024); SH_FormatInteger(PerfDataGetWorkingSetSizeBytes(Index) / 1024, lpText, nMaxCount);
CommaSeparateNumberString(lpText, nMaxCount); StringCchCatW(lpText, nMaxCount, L" K");
wcscat(lpText, L" K"); return TRUE;
}
if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEDPOOL) case COLUMN_PEAKMEMORYUSAGE:
{ SH_FormatInteger(PerfDataGetPeakWorkingSetSizeBytes(Index) / 1024, lpText, nMaxCount);
wsprintfW(lpText, L"%lu", PerfDataGetPagedPoolUsagePages(Index) / 1024); StringCchCatW(lpText, nMaxCount, L" K");
CommaSeparateNumberString(lpText, nMaxCount); return TRUE;
wcscat(lpText, L" K");
} case COLUMN_MEMORYUSAGEDELTA:
if (ColumnDataHints[ColumnIndex] == COLUMN_NONPAGEDPOOL) SH_FormatInteger(PerfDataGetWorkingSetSizeDelta(Index) / 1024, lpText, nMaxCount);
{ StringCchCatW(lpText, nMaxCount, L" K");
wsprintfW(lpText, L"%lu", PerfDataGetNonPagedPoolUsagePages(Index) / 1024); return TRUE;
CommaSeparateNumberString(lpText, nMaxCount);
wcscat(lpText, L" K"); case COLUMN_PAGEFAULTS:
} SH_FormatInteger(PerfDataGetPageFaultCount(Index), lpText, nMaxCount);
if (ColumnDataHints[ColumnIndex] == COLUMN_BASEPRIORITY) return TRUE;
wsprintfW(lpText, L"%lu", PerfDataGetBasePriority(Index));
if (ColumnDataHints[ColumnIndex] == COLUMN_HANDLECOUNT) case COLUMN_PAGEFAULTSDELTA:
{ SH_FormatInteger(PerfDataGetPageFaultCountDelta(Index), lpText, nMaxCount);
wsprintfW(lpText, L"%lu", PerfDataGetHandleCount(Index)); return TRUE;
CommaSeparateNumberString(lpText, nMaxCount);
} case COLUMN_VIRTUALMEMORYSIZE:
if (ColumnDataHints[ColumnIndex] == COLUMN_THREADCOUNT) SH_FormatInteger(PerfDataGetVirtualMemorySizeBytes(Index) / 1024, lpText, nMaxCount);
{ StringCchCatW(lpText, nMaxCount, L" K");
wsprintfW(lpText, L"%lu", PerfDataGetThreadCount(Index)); return TRUE;
CommaSeparateNumberString(lpText, nMaxCount);
} case COLUMN_PAGEDPOOL:
if (ColumnDataHints[ColumnIndex] == COLUMN_USEROBJECTS) SH_FormatInteger(PerfDataGetPagedPoolUsagePages(Index) / 1024, lpText, nMaxCount);
{ StringCchCatW(lpText, nMaxCount, L" K");
wsprintfW(lpText, L"%lu", PerfDataGetUSERObjectCount(Index)); return TRUE;
CommaSeparateNumberString(lpText, nMaxCount);
} case COLUMN_NONPAGEDPOOL:
if (ColumnDataHints[ColumnIndex] == COLUMN_GDIOBJECTS) SH_FormatInteger(PerfDataGetNonPagedPoolUsagePages(Index) / 1024, lpText, nMaxCount);
{ StringCchCatW(lpText, nMaxCount, L" K");
wsprintfW(lpText, L"%lu", PerfDataGetGDIObjectCount(Index)); return TRUE;
CommaSeparateNumberString(lpText, nMaxCount);
} case COLUMN_BASEPRIORITY:
if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADS) StringCchPrintfW(lpText, nMaxCount, L"%lu", PerfDataGetBasePriority(Index));
{ return TRUE;
PerfDataGetIOCounters(Index, &iocounters);
/* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.ReadOperationCount); */ case COLUMN_HANDLECOUNT:
_ui64tow(iocounters.ReadOperationCount, lpText, 10); SH_FormatInteger(PerfDataGetHandleCount(Index), lpText, nMaxCount);
CommaSeparateNumberString(lpText, nMaxCount); return TRUE;
}
if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITES) case COLUMN_THREADCOUNT:
{ SH_FormatInteger(PerfDataGetThreadCount(Index), lpText, nMaxCount);
PerfDataGetIOCounters(Index, &iocounters); return TRUE;
/* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.WriteOperationCount); */
_ui64tow(iocounters.WriteOperationCount, lpText, 10); case COLUMN_USEROBJECTS:
CommaSeparateNumberString(lpText, nMaxCount); SH_FormatInteger(PerfDataGetUSERObjectCount(Index), lpText, nMaxCount);
} return TRUE;
if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHER)
{ case COLUMN_GDIOBJECTS:
PerfDataGetIOCounters(Index, &iocounters); SH_FormatInteger(PerfDataGetGDIObjectCount(Index), lpText, nMaxCount);
/* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.OtherOperationCount); */ return TRUE;
_ui64tow(iocounters.OtherOperationCount, lpText, 10);
CommaSeparateNumberString(lpText, nMaxCount); case COLUMN_IOREADS:
} PerfDataGetIOCounters(Index, &iocounters);
if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADBYTES) SH_FormatInteger(iocounters.ReadOperationCount, lpText, nMaxCount);
{ return TRUE;
PerfDataGetIOCounters(Index, &iocounters);
/* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.ReadTransferCount); */ case COLUMN_IOWRITES:
_ui64tow(iocounters.ReadTransferCount, lpText, 10); PerfDataGetIOCounters(Index, &iocounters);
CommaSeparateNumberString(lpText, nMaxCount); SH_FormatInteger(iocounters.WriteOperationCount, lpText, nMaxCount);
} return TRUE;
if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITEBYTES)
{ case COLUMN_IOOTHER:
PerfDataGetIOCounters(Index, &iocounters); PerfDataGetIOCounters(Index, &iocounters);
/* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.WriteTransferCount); */ SH_FormatInteger(iocounters.OtherOperationCount, lpText, nMaxCount);
_ui64tow(iocounters.WriteTransferCount, lpText, 10); return TRUE;
CommaSeparateNumberString(lpText, nMaxCount);
} case COLUMN_IOREADBYTES:
if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHERBYTES) PerfDataGetIOCounters(Index, &iocounters);
{ SH_FormatInteger(iocounters.ReadTransferCount, lpText, nMaxCount);
PerfDataGetIOCounters(Index, &iocounters); return TRUE;
/* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.OtherTransferCount); */
_ui64tow(iocounters.OtherTransferCount, lpText, 10); case COLUMN_IOWRITEBYTES:
CommaSeparateNumberString(lpText, nMaxCount); PerfDataGetIOCounters(Index, &iocounters);
SH_FormatInteger(iocounters.WriteTransferCount, lpText, nMaxCount);
return TRUE;
case COLUMN_IOOTHERBYTES:
PerfDataGetIOCounters(Index, &iocounters);
SH_FormatInteger(iocounters.OtherTransferCount, lpText, nMaxCount);
return TRUE;
} }
return FALSE; return FALSE;