// ThreadCtlPerf.cpp : main source file for ThreadCtlPerf.exe // #include "stdafx.h" #include #include #include #include #include "resource.h" #include "ThreadCtlPerfView.h" #include "aboutdlg.h" #include "MainFrm.h" const UINT knMAX_THREADS = 20; HMODULE g_hPSAPI = NULL; // Process memory counters struct. PROCESS_MEMORY_COUNTERS g_ProcessMem; // Initial process memory stuff PROCESS_MEMORY_COUNTERS g_ProcessMemInit; // Function pointer to GetProcessMemoryInfo. PFNGETPROCESSMEMORYINFO g_lpfnGetProcessMemoryInfo = NULL; __int64 g_liFreq = 0; __int64 g_liLast = 0; CAppModule _Module; class CThreadCtlPerfThreadManager { public: // thread init param struct _RunData { LPTSTR lpstrCmdLine; int nCmdShow; }; // thread proc static DWORD WINAPI RunThread(LPVOID lpData) { CMessageLoop theLoop; _Module.AddMessageLoop(&theLoop); _RunData* pData = (_RunData*)lpData; CMainFrame wndFrame; if(wndFrame.CreateEx() == NULL) { ATLTRACE(_T("Frame window creation failed!\n")); return 0; } wndFrame.ShowWindow(pData->nCmdShow); ::SetForegroundWindow(wndFrame); // Win95 needs this delete pData; int nRet = theLoop.Run(); _Module.RemoveMessageLoop(); return nRet; } DWORD m_dwCount; HANDLE m_arrThreadHandles[MAXIMUM_WAIT_OBJECTS - 1]; CThreadCtlPerfThreadManager() : m_dwCount(0) { } // Operations DWORD AddThread(LPTSTR lpstrCmdLine, int nCmdShow) { if(m_dwCount == (MAXIMUM_WAIT_OBJECTS - 1)) { ::MessageBox(NULL, _T("ERROR: Cannot create ANY MORE threads!!!"), _T("ThreadCtlPerf"), MB_OK); return 0; } _RunData* pData = new _RunData; pData->lpstrCmdLine = lpstrCmdLine; pData->nCmdShow = nCmdShow; DWORD dwThreadID; HANDLE hThread = ::CreateThread(NULL, 0, RunThread, pData, 0, &dwThreadID); if(hThread == NULL) { ::MessageBox(NULL, _T("ERROR: Cannot create thread!!!"), _T("ThreadCtlPerf"), MB_OK); return 0; } m_arrThreadHandles[m_dwCount] = hThread; m_dwCount++; return dwThreadID; } void RemoveThread(DWORD dwIndex) { ::CloseHandle(m_arrThreadHandles[dwIndex]); if(dwIndex != (m_dwCount - 1)) m_arrThreadHandles[dwIndex] = m_arrThreadHandles[m_dwCount - 1]; m_dwCount--; } int Run(LPTSTR lpstrCmdLine, int nCmdShow) { MSG msg; // force message queue to be created ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); (g_lpfnGetProcessMemoryInfo)(GetCurrentProcess(), &g_ProcessMemInit, sizeof(g_ProcessMem)); ::QueryPerformanceFrequency( (LARGE_INTEGER*) &g_liFreq); ::QueryPerformanceCounter( (LARGE_INTEGER*) &g_liLast); UINT nMaxThreads = 0; nMaxThreads = wcstol(lpstrCmdLine, 0, 10); if (nMaxThreads == 0) nMaxThreads = knMAX_THREADS; AddThread(lpstrCmdLine, nCmdShow); int nRet = m_dwCount; DWORD dwRet; while(m_dwCount > 0) { dwRet = ::MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles, FALSE, INFINITE, QS_ALLINPUT); if(dwRet == 0xFFFFFFFF) ::MessageBox(NULL, _T("ERROR: Wait for multiple objects failed!!!"), _T("ThreadCtlPerf"), MB_OK); else if(dwRet >= WAIT_OBJECT_0 && dwRet <= (WAIT_OBJECT_0 + m_dwCount - 1)) RemoveThread(dwRet - WAIT_OBJECT_0); else if(dwRet == (WAIT_OBJECT_0 + m_dwCount)) { ::GetMessage(&msg, NULL, 0, 0); if(msg.message == WM_USER && m_dwCount < nMaxThreads) AddThread(_T(""), SW_SHOWNORMAL); else if(msg.message == WM_USER + 1) m_dwCount = 0; else ::MessageBeep((UINT)-1); } else ::MessageBeep((UINT)-1); } return nRet; } }; int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { HRESULT hRes = ::CoInitialize(NULL); // If you are running on NT 4.0 or higher you can use the following call instead to // make the EXE free threaded. This means that calls come in on a random RPC thread. // HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); ATLASSERT(SUCCEEDED(hRes)); #if (_WIN32_IE >= 0x0300) INITCOMMONCONTROLSEX iccx; iccx.dwSize = sizeof(iccx); //iccx.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES; iccx.dwICC = 0x3FFF; BOOL bRet = ::InitCommonControlsEx(&iccx); bRet; ATLASSERT(bRet); #else ::InitCommonControls(); #endif hRes = _Module.Init(NULL, hInstance); ATLASSERT(SUCCEEDED(hRes)); g_hPSAPI = ::LoadLibrary(_T("PSAPI.DLL")); int nRet = -1; if (g_hPSAPI) { // Load the function: g_lpfnGetProcessMemoryInfo = (PFNGETPROCESSMEMORYINFO)::GetProcAddress(g_hPSAPI, "GetProcessMemoryInfo"); if (NULL != g_lpfnGetProcessMemoryInfo) { CThreadCtlPerfThreadManager mgr; nRet = mgr.Run(lpstrCmdLine, nCmdShow); } ::FreeLibrary(g_hPSAPI); } _Module.Term(); ::CoUninitialize(); return nRet; }