[TASKMGR]

- Use messages instead of events to notify the update threads
- Fixes a handle leak
- Fix some typos
- Patch by Carlo Bramini (carlo.bramix at libero dot it)

See issue #3104 for more details.

svn path=/trunk/; revision=48484
This commit is contained in:
Timo Kreuzer 2010-08-08 03:41:33 +00:00
parent 9caaf3d69c
commit 7dc11f26bf
12 changed files with 87 additions and 103 deletions

View file

@ -38,7 +38,6 @@ HWND hApplicationPageSwitchToButton; /* Application Switch To button
HWND hApplicationPageNewTaskButton; /* Application New Task button */ HWND hApplicationPageNewTaskButton; /* Application New Task button */
static int nApplicationPageWidth; static int nApplicationPageWidth;
static int nApplicationPageHeight; static int nApplicationPageHeight;
static HANDLE hApplicationPageEvent = NULL; /* When this event becomes signaled then we refresh the app list */
static BOOL bSortAscending = TRUE; static BOOL bSortAscending = TRUE;
DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter); DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter);
BOOL noApps; BOOL noApps;
@ -51,6 +50,11 @@ void ApplicationPageShowContextMenu2(void);
int CALLBACK ApplicationPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); int CALLBACK ApplicationPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
int ProcGetIndexByProcessId(DWORD dwProcessId); int ProcGetIndexByProcessId(DWORD dwProcessId);
#ifdef RUN_APPS_PAGE
static HANDLE hApplicationThread = NULL;
static DWORD dwApplicationThread;
#endif
#if 0 #if 0
void SwitchToThisWindow ( void SwitchToThisWindow (
HWND hWnd, /* Handle to the window that should be activated */ HWND hWnd, /* Handle to the window that should be activated */
@ -92,7 +96,6 @@ ApplicationPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
LV_COLUMN column; LV_COLUMN column;
WCHAR szTemp[256]; WCHAR szTemp[256];
int cx, cy; int cx, cy;
HANDLE hRefreshThread = NULL;
switch (message) { switch (message) {
case WM_INITDIALOG: case WM_INITDIALOG:
@ -132,15 +135,16 @@ ApplicationPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
UpdateApplicationListControlViewSetting(); UpdateApplicationListControlViewSetting();
/* Start our refresh thread */ /* Start our refresh thread */
hRefreshThread = CreateThread(NULL, 0, ApplicationPageRefreshThread, NULL, 0, NULL); #ifdef RUN_APPS_PAGE
hApplicationThread = CreateThread(NULL, 0, ApplicationPageRefreshThread, NULL, 0, &dwApplicationThread);
#endif
return TRUE; return TRUE;
case WM_DESTROY: case WM_DESTROY:
/* Close the event handle, this will make the */ /* Close refresh thread */
/* refresh thread exit when the wait fails */ #ifdef RUN_APPS_PAGE
CloseHandle(hApplicationPageEvent); EndLocalThread(&hApplicationThread, dwApplicationThread);
CloseHandle(hRefreshThread); #endif
break; break;
case WM_COMMAND: case WM_COMMAND:
@ -213,9 +217,11 @@ ApplicationPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
void RefreshApplicationPage(void) void RefreshApplicationPage(void)
{ {
#ifdef RUN_APPS_PAGE
/* Signal the event so that our refresh thread */ /* Signal the event so that our refresh thread */
/* will wake up and refresh the application page */ /* will wake up and refresh the application page */
SetEvent(hApplicationPageEvent); PostThreadMessage(dwApplicationThread, WM_TIMER, 0, 0);
#endif
} }
void UpdateApplicationListControlViewSetting(void) void UpdateApplicationListControlViewSetting(void)
@ -236,6 +242,7 @@ void UpdateApplicationListControlViewSetting(void)
DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter) DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter)
{ {
MSG msg;
INT i; INT i;
BOOL bItemRemoved = FALSE; BOOL bItemRemoved = FALSE;
LV_ITEM item; LV_ITEM item;
@ -243,30 +250,15 @@ DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter)
HIMAGELIST hImageListLarge; HIMAGELIST hImageListLarge;
HIMAGELIST hImageListSmall; HIMAGELIST hImageListSmall;
/* Create the event */
hApplicationPageEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
/* If we couldn't create the event then exit the thread */ /* If we couldn't create the event then exit the thread */
if (!hApplicationPageEvent)
return 0;
while (1) while (1)
{ {
DWORD dwWaitVal; /* Wait for an the event or application close */
if (GetMessage(&msg, NULL, 0, 0) <= 0)
/* Wait on the event */
dwWaitVal = WaitForSingleObject(hApplicationPageEvent, INFINITE);
/* If the wait failed then the event object must have been */
/* closed and the task manager is exiting so exit this thread */
if (dwWaitVal == WAIT_FAILED)
return 0; return 0;
if (dwWaitVal == WAIT_OBJECT_0) if (msg.message == WM_TIMER)
{ {
/* Reset our event */
ResetEvent(hApplicationPageEvent);
/* /*
* FIXME: * FIXME:
* *

View file

@ -1,7 +1,7 @@
/* /*
* ReactOS Task Manager * ReactOS Task Manager
* *
* debug.cpp * debug.c
* *
* Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org> * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
* 2005 Klemens Friedl <frik85@reactos.at> * 2005 Klemens Friedl <frik85@reactos.at>

View file

@ -1,7 +1,7 @@
/* /*
* ReactOS Task Manager * ReactOS Task Manager
* *
* endproc.cpp * endproc.c
* *
* Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org> * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
* 2005 Klemens Friedl <frik85@reactos.at> * 2005 Klemens Friedl <frik85@reactos.at>

View file

@ -1,7 +1,7 @@
/* /*
* ReactOS Task Manager * ReactOS Task Manager
* *
* graph.cpp * graph.c
* *
* Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org> * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
* *

View file

@ -1,7 +1,7 @@
/* /*
* ReactOS Task Manager * ReactOS Task Manager
* *
* GraphCtrl.cpp * graphctl.c
* *
* Copyright (C) 2002 Robert Dickenson <robd@reactos.org> * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
* *
@ -425,7 +425,7 @@ void GraphCtrl_DrawPoint(TGraphCtrl* this)
* note: the m_dcPlot covers the entire client * note: the m_dcPlot covers the entire client
* but we only shift bitmap that is the size * but we only shift bitmap that is the size
* of the plot rectangle * of the plot rectangle
* grab the right side of the plot (exluding m_nShiftPixels on the left) * grab the right side of the plot (excluding m_nShiftPixels on the left)
* move this grabbed bitmap to the left by m_nShiftPixels * move this grabbed bitmap to the left by m_nShiftPixels
*/ */
BitBlt(this->m_dcPlot, this->m_rectPlot.left, this->m_rectPlot.top+1, BitBlt(this->m_dcPlot, this->m_rectPlot.left, this->m_rectPlot.top+1,

View file

@ -1,7 +1,7 @@
/* /*
* ReactOS Task Manager * ReactOS Task Manager
* *
* GraphCtrl.h * graphctl.h
* *
* Copyright (C) 2002 Robert Dickenson <robd@reactos.org> * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
* *

View file

@ -1,7 +1,7 @@
/* /*
* ReactOS Task Manager * ReactOS Task Manager
* *
* optnmenu.cpp * optnmenu.c
* *
* Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org> * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
* *
@ -110,7 +110,7 @@ void TaskManager_OnOptionsShow16BitTasks(void)
/* /*
* FIXME: Currently this is useless because the * FIXME: Currently this is useless because the
* current implemetation doesn't list the 16-bit * current implementation doesn't list the 16-bit
* processes. I believe that would require querying * processes. I believe that would require querying
* each ntvdm.exe process for it's children. * each ntvdm.exe process for it's children.
*/ */

View file

@ -1,7 +1,7 @@
/* /*
* ReactOS Task Manager * ReactOS Task Manager
* *
* perfdata.cpp * perfdata.c
* *
* Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org> * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
* *

View file

@ -51,11 +51,14 @@ HWND hPerformancePageTotalsHandleCountEdit; /* Total Handles Edit Con
HWND hPerformancePageTotalsProcessCountEdit; /* Total Processes Edit Control */ HWND hPerformancePageTotalsProcessCountEdit; /* Total Processes Edit Control */
HWND hPerformancePageTotalsThreadCountEdit; /* Total Threads Edit Control */ HWND hPerformancePageTotalsThreadCountEdit; /* Total Threads Edit Control */
#ifdef RUN_PERF_PAGE
static HANDLE hPerformanceThread = NULL;
static DWORD dwPerformanceThread;
#endif
static int nPerformancePageWidth; static int nPerformancePageWidth;
static int nPerformancePageHeight; static int nPerformancePageHeight;
static int lastX, lastY; static int lastX, lastY;
static HANDLE hPerformancePageEvent = NULL; /* When this event becomes signaled then we refresh the performance page */
DWORD WINAPI PerformancePageRefreshThread(void *lpParameter); DWORD WINAPI PerformancePageRefreshThread(void *lpParameter);
void AdjustFrameSize(HWND hCntrl, HWND hDlg, int nXDifference, int nYDifference, int pos) void AdjustFrameSize(HWND hCntrl, HWND hDlg, int nXDifference, int nYDifference, int pos)
@ -94,12 +97,12 @@ void AdjustFrameSize(HWND hCntrl, HWND hDlg, int nXDifference, int nYDifference,
InvalidateRect(hCntrl, NULL, TRUE); InvalidateRect(hCntrl, NULL, TRUE);
} }
void AdjustControlPostion(HWND hCntrl, HWND hDlg, int nXDifference, int nYDifference) static void AdjustControlPostion(HWND hCntrl, HWND hDlg, int nXDifference, int nYDifference)
{ {
AdjustFrameSize(hCntrl, hDlg, nXDifference, nYDifference, 0); AdjustFrameSize(hCntrl, hDlg, nXDifference, nYDifference, 0);
} }
void AdjustCntrlPos(int ctrl_id, HWND hDlg, int nXDifference, int nYDifference) static void AdjustCntrlPos(int ctrl_id, HWND hDlg, int nXDifference, int nYDifference)
{ {
AdjustFrameSize(GetDlgItem(hDlg, ctrl_id), hDlg, nXDifference, nYDifference, 0); AdjustFrameSize(GetDlgItem(hDlg, ctrl_id), hDlg, nXDifference, nYDifference, 0);
} }
@ -110,9 +113,6 @@ PerformancePageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
RECT rc; RECT rc;
int nXDifference; int nXDifference;
int nYDifference; int nYDifference;
#ifdef RUN_PERF_PAGE
HANDLE hRefreshThread = NULL;
#endif
/* HDC hdc; */ /* HDC hdc; */
/* PAINTSTRUCT ps; */ /* PAINTSTRUCT ps; */
@ -121,7 +121,7 @@ PerformancePageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
GraphCtrl_Dispose(&PerformancePageCpuUsageHistoryGraph); GraphCtrl_Dispose(&PerformancePageCpuUsageHistoryGraph);
GraphCtrl_Dispose(&PerformancePageMemUsageHistoryGraph); GraphCtrl_Dispose(&PerformancePageMemUsageHistoryGraph);
#ifdef RUN_PERF_PAGE #ifdef RUN_PERF_PAGE
CloseHandle(hRefreshThread); EndLocalThread(&hPerformanceThread, dwPerformanceThread);
#endif #endif
break; break;
@ -192,7 +192,7 @@ PerformancePageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
GraphCtrl_SetPlotColor(&PerformancePageMemUsageHistoryGraph, 0, RGB(255, 255, 0)) ; GraphCtrl_SetPlotColor(&PerformancePageMemUsageHistoryGraph, 0, RGB(255, 255, 0)) ;
/* Start our refresh thread */ /* Start our refresh thread */
#ifdef RUN_PERF_PAGE #ifdef RUN_PERF_PAGE
hRefreshThread = CreateThread(NULL, 0, PerformancePageRefreshThread, NULL, 0, NULL); hPerformanceThread = CreateThread(NULL, 0, PerformancePageRefreshThread, NULL, 0, &dwPerformanceThread);
#endif #endif
/* /*
@ -303,9 +303,11 @@ PerformancePageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
void RefreshPerformancePage(void) void RefreshPerformancePage(void)
{ {
#ifdef RUN_PERF_PAGE
/* Signal the event so that our refresh thread */ /* Signal the event so that our refresh thread */
/* will wake up and refresh the performance page */ /* will wake up and refresh the performance page */
SetEvent(hPerformancePageEvent); PostThreadMessage(dwPerformanceThread, WM_TIMER, 0, 0);
#endif
} }
DWORD WINAPI PerformancePageRefreshThread(void *lpParameter) DWORD WINAPI PerformancePageRefreshThread(void *lpParameter)
@ -332,35 +334,21 @@ DWORD WINAPI PerformancePageRefreshThread(void *lpParameter)
WCHAR Text[260]; WCHAR Text[260];
WCHAR szMemUsage[256]; WCHAR szMemUsage[256];
/* Create the event */ MSG msg;
hPerformancePageEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
/* If we couldn't create the event then exit the thread */
if (!hPerformancePageEvent)
return 0;
LoadStringW(hInst, IDS_STATUS_MEMUSAGE, szMemUsage, 256); LoadStringW(hInst, IDS_STATUS_MEMUSAGE, szMemUsage, 256);
while (1) while (1)
{ {
DWORD dwWaitVal;
int nBarsUsed1; int nBarsUsed1;
int nBarsUsed2; int nBarsUsed2;
/* Wait on the event */ /* Wait for an the event or application close */
dwWaitVal = WaitForSingleObject(hPerformancePageEvent, INFINITE); if (GetMessage(&msg, NULL, 0, 0) <= 0)
/* If the wait failed then the event object must have been */
/* closed and the task manager is exiting so exit this thread */
if (dwWaitVal == WAIT_FAILED)
return 0; return 0;
if (dwWaitVal == WAIT_OBJECT_0) if (msg.message == WM_TIMER)
{ {
/* Reset our event */
ResetEvent(hPerformancePageEvent);
/* /*
* Update the commit charge info * Update the commit charge info
*/ */
@ -449,8 +437,6 @@ DWORD WINAPI PerformancePageRefreshThread(void *lpParameter)
PhysicalMemoryAvailable = PerfDataGetPhysicalMemoryAvailableK(); PhysicalMemoryAvailable = PerfDataGetPhysicalMemoryAvailableK();
nBarsUsed2 = PhysicalMemoryTotal ? ((PhysicalMemoryAvailable * 100) / PhysicalMemoryTotal) : 0; nBarsUsed2 = PhysicalMemoryTotal ? ((PhysicalMemoryAvailable * 100) / PhysicalMemoryTotal) : 0;
GraphCtrl_AppendPoint(&PerformancePageCpuUsageHistoryGraph, CpuUsage, CpuKernelUsage, 0.0, 0.0); GraphCtrl_AppendPoint(&PerformancePageCpuUsageHistoryGraph, CpuUsage, CpuKernelUsage, 0.0, 0.0);
GraphCtrl_AppendPoint(&PerformancePageMemUsageHistoryGraph, nBarsUsed1, nBarsUsed2, 0.0, 0.0); GraphCtrl_AppendPoint(&PerformancePageMemUsageHistoryGraph, nBarsUsed1, nBarsUsed2, 0.0, 0.0);
/* PerformancePageMemUsageHistoryGraph.SetRange(0.0, 100.0, 10) ; */ /* PerformancePageMemUsageHistoryGraph.SetRange(0.0, 100.0, 10) ; */
@ -458,7 +444,7 @@ DWORD WINAPI PerformancePageRefreshThread(void *lpParameter)
InvalidateRect(hPerformancePageCpuUsageHistoryGraph, NULL, FALSE); InvalidateRect(hPerformancePageCpuUsageHistoryGraph, NULL, FALSE);
} }
} }
return 0; return 0;
} }
void PerformancePage_OnViewShowKernelTimes(void) void PerformancePage_OnViewShowKernelTimes(void)

View file

@ -40,7 +40,10 @@ HWND hProcessPageShowAllProcessesButton;/* Process Show All Processes checkbox *
static int nProcessPageWidth; static int nProcessPageWidth;
static int nProcessPageHeight; static int nProcessPageHeight;
static HANDLE hProcessPageEvent = NULL; /* When this event becomes signaled then we refresh the process list */ #ifdef RUN_PROC_PAGE
static HANDLE hProcessThread = NULL;
static DWORD dwProcessThread;
#endif
int CALLBACK ProcessPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); int CALLBACK ProcessPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
void AddProcess(ULONG Index); void AddProcess(ULONG Index);
@ -104,7 +107,6 @@ ProcessPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
int nXDifference; int nXDifference;
int nYDifference; int nYDifference;
int cx, cy; int cx, cy;
HANDLE hRefreshThread = NULL;
switch (message) { switch (message) {
case WM_INITDIALOG: case WM_INITDIALOG:
@ -139,19 +141,19 @@ ProcessPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
*/ */
OldProcessListWndProc = (WNDPROC)(LONG_PTR) SetWindowLongPtrW(hProcessPageListCtrl, GWL_WNDPROC, (LONG_PTR)ProcessListWndProc); OldProcessListWndProc = (WNDPROC)(LONG_PTR) SetWindowLongPtrW(hProcessPageListCtrl, GWL_WNDPROC, (LONG_PTR)ProcessListWndProc);
#ifdef RUN_PROC_PAGE
/* Start our refresh thread */ /* Start our refresh thread */
hRefreshThread = CreateThread(NULL, 0, ProcessPageRefreshThread, NULL, 0, NULL); hProcessThread = CreateThread(NULL, 0, ProcessPageRefreshThread, NULL, 0, &dwProcessThread);
#endif
return TRUE; return TRUE;
case WM_DESTROY: case WM_DESTROY:
/* Close the event handle, this will make the */ /* Close the event handle, this will make the */
/* refresh thread exit when the wait fails */ /* refresh thread exit when the wait fails */
CloseHandle(hProcessPageEvent); #ifdef RUN_PROC_PAGE
CloseHandle(hRefreshThread); EndLocalThread(&hProcessThread, dwProcessThread);
#endif
SaveColumnSettings(); SaveColumnSettings();
break; break;
case WM_COMMAND: case WM_COMMAND:
@ -194,11 +196,9 @@ ProcessPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
cy = rc.top + nYDifference; cy = rc.top + nYDifference;
SetWindowPos(hProcessPageShowAllProcessesButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); SetWindowPos(hProcessPageShowAllProcessesButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
InvalidateRect(hProcessPageShowAllProcessesButton, NULL, TRUE); InvalidateRect(hProcessPageShowAllProcessesButton, NULL, TRUE);
break; break;
case WM_NOTIFY: case WM_NOTIFY:
ProcessPageOnNotify(wParam, lParam); ProcessPageOnNotify(wParam, lParam);
break; break;
} }
@ -372,9 +372,11 @@ void ProcessPageShowContextMenu(DWORD dwProcessId)
void RefreshProcessPage(void) void RefreshProcessPage(void)
{ {
#ifdef RUN_PROC_PAGE
/* Signal the event so that our refresh thread */ /* Signal the event so that our refresh thread */
/* will wake up and refresh the process page */ /* will wake up and refresh the process page */
SetEvent(hProcessPageEvent); PostThreadMessage(dwProcessThread, WM_TIMER, 0, 0);
#endif
} }
DWORD WINAPI ProcessPageRefreshThread(void *lpParameter) DWORD WINAPI ProcessPageRefreshThread(void *lpParameter)
@ -382,34 +384,19 @@ DWORD WINAPI ProcessPageRefreshThread(void *lpParameter)
ULONG OldProcessorUsage = 0; ULONG OldProcessorUsage = 0;
ULONG OldProcessCount = 0; ULONG OldProcessCount = 0;
WCHAR szCpuUsage[256], szProcesses[256]; WCHAR szCpuUsage[256], szProcesses[256];
MSG msg;
/* Create the event */
hProcessPageEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
/* If we couldn't create the event then exit the thread */
if (!hProcessPageEvent)
return 0;
LoadStringW(hInst, IDS_STATUS_CPUUSAGE, szCpuUsage, 256); LoadStringW(hInst, IDS_STATUS_CPUUSAGE, szCpuUsage, 256);
LoadStringW(hInst, IDS_STATUS_PROCESSES, szProcesses, 256); LoadStringW(hInst, IDS_STATUS_PROCESSES, szProcesses, 256);
while (1) { while (1) {
DWORD dwWaitVal; /* Wait for an the event or application close */
if (GetMessage(&msg, NULL, 0, 0) <= 0)
/* Wait on the event */
dwWaitVal = WaitForSingleObject(hProcessPageEvent, INFINITE);
/* If the wait failed then the event object must have been */
/* closed and the task manager is exiting so exit this thread */
if (dwWaitVal == WAIT_FAILED)
return 0; return 0;
if (dwWaitVal == WAIT_OBJECT_0) { if (msg.message == WM_TIMER) {
WCHAR text[260]; WCHAR text[260];
/* Reset our event */
ResetEvent(hProcessPageEvent);
UpdateProcesses(); UpdateProcesses();
if (IsWindowVisible(hProcessPage)) if (IsWindowVisible(hProcessPage))

View file

@ -1,7 +1,7 @@
/* /*
* ReactOS Task Manager * ReactOS Task Manager
* *
* TaskMgr.c : Defines the entry point for the application. * taskmgr.c : Defines the entry point for the application.
* *
* Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org> * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
* 2005 Klemens Friedl <frik85@reactos.at> * 2005 Klemens Friedl <frik85@reactos.at>
@ -856,11 +856,6 @@ void TaskManager_OnViewUpdateSpeed(DWORD dwSpeed)
SetUpdateSpeed(hMainWnd); SetUpdateSpeed(hMainWnd);
} }
void TaskManager_OnViewRefresh(void)
{
PostMessageW(hMainWnd, WM_TIMER, 0, 0);
}
void TaskManager_OnTabWndSelChange(void) void TaskManager_OnTabWndSelChange(void)
{ {
int i; int i;
@ -1012,3 +1007,27 @@ LPWSTR GetLastErrorText(LPWSTR lpszBuf, DWORD dwSize)
} }
return lpszBuf; return lpszBuf;
} }
DWORD EndLocalThread(HANDLE *hThread, DWORD dwThread)
{
DWORD dwExitCodeThread = 0;
if (*hThread != NULL) {
PostThreadMessage(dwThread,WM_QUIT,0,0);
for (;;) {
MSG msg;
if (WAIT_OBJECT_0 == WaitForSingleObject(*hThread, 500))
break;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
GetExitCodeThread(*hThread, &dwExitCodeThread);
CloseHandle(*hThread);
*hThread = NULL;
}
return dwExitCodeThread;
}

View file

@ -116,9 +116,9 @@ void TaskManager_OnEnterMenuLoop(HWND hWnd);
void TaskManager_OnExitMenuLoop(HWND hWnd); void TaskManager_OnExitMenuLoop(HWND hWnd);
void TaskManager_OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu); void TaskManager_OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu);
void TaskManager_OnViewUpdateSpeed(DWORD); void TaskManager_OnViewUpdateSpeed(DWORD);
void TaskManager_OnViewRefresh(void);
void TaskManager_OnTabWndSelChange(void); void TaskManager_OnTabWndSelChange(void);
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
DWORD EndLocalThread(HANDLE *hThread, DWORD dwThread);
#ifdef __cplusplus #ifdef __cplusplus
} }