www.pudn.com > ntshell.rar > console.cpp


// console.cpp : main source file for console.exe 
// 
 
#include "stdafx.h" 
#include "resource.h" 
#include "common.h" 
 
#include "ntshell.h" 
#include "consoleView.h" 
#include "aboutdlg.h" 
#include "maindlg.h" 
#include "MainFrm.h" 
 
CAppModule _Module; 
 
class CConsoleThreadManager 
{ 
public: 
	// thread init param 
	struct _RunData 
	{ 
		LPTSTR lpstrCmdLine; 
		int nCmdShow; 
		int nWndClass; 
		LPVOID lpParam; 
	}; 
 
	// thread proc 
	static DWORD WINAPI RunThread(LPVOID lpData) 
	{ 
		CMessageLoop theLoop; 
		_Module.AddMessageLoop(&theLoop); 
 
		_RunData* pData = (_RunData*)lpData; 
 
		CMainDlg *wndMain = NULL; 
		CMainFrame *wndFrame = NULL; 
 
		switch (pData->nWndClass) 
		{ 
		case 0: 
			{ 
				wndMain = new CMainDlg(); 
 
				if(wndMain == NULL || wndMain->Create(NULL, (LPARAM)pData->lpParam) == NULL) 
				{ 
					ATLTRACE(_T("Frame window creation failed!\n")); 
					delete wndMain; 
					return 0; 
				} 
 
				wndMain->ShowWindow(pData->nCmdShow); 
				::SetForegroundWindow(*wndMain);	// Win95 needs this 
			} 
			break; 
		case 1: 
			{ 
				wndFrame = new CMainFrame(); 
 
				if(wndFrame == NULL || wndFrame->CreateEx(NULL, NULL, 0, 0, pData->lpParam) == NULL) 
				{ 
					ATLTRACE(_T("Frame window creation failed!\n")); 
					delete wndFrame; 
					return 0; 
				} 
 
				wndFrame->ShowWindow(pData->nCmdShow); 
				::SetForegroundWindow(*wndFrame);	// Win95 needs this 
			} 
			break; 
		} 
 
		delete pData; 
 
		int nRet = theLoop.Run(); 
 
		_Module.RemoveMessageLoop(); 
 
		delete wndMain; 
		delete wndFrame; 
 
		return nRet; 
	} 
 
	DWORD m_dwCount; 
	HANDLE m_arrThreadHandles[MAXIMUM_WAIT_OBJECTS - 1]; 
 
	CConsoleThreadManager() : m_dwCount(0) 
	{ } 
 
// Operations 
	DWORD AddThread(LPTSTR lpstrCmdLine, int nCmdShow, int nWndClass, LPVOID lpParam) 
	{ 
		if(m_dwCount == (MAXIMUM_WAIT_OBJECTS - 1)) 
		{ 
			::MessageBox(NULL, _T("ERROR: Cannot create ANY MORE threads!!!"), _T("console"), MB_OK); 
			return 0; 
		} 
 
		_RunData* pData = new _RunData; 
		pData->lpstrCmdLine = lpstrCmdLine; 
		pData->nCmdShow = nCmdShow; 
		pData->nWndClass = nWndClass; 
		pData->lpParam = lpParam; 
 
		DWORD dwThreadID; 
		HANDLE hThread = ::CreateThread(NULL, 0, RunThread, pData, 0, &dwThreadID); 
		if(hThread == NULL) 
		{ 
			::MessageBox(NULL, _T("ERROR: Cannot create thread!!!"), _T("console"), 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); 
 
		AddThread(lpstrCmdLine, nCmdShow, 0, NULL); 
 
		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("console"), 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) 
					AddThread("", SW_SHOWNORMAL, 1, (LPVOID)msg.lParam); 
				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)); 
 
    WSADATA wsa; 
 
	if (WSAStartup(MAKEWORD(2, 0), &wsa) != 0) 
	{ 
		ATLASSERT("ÔØÈëWINSOCKʧ°Ü"); 
		return -1; 
	} 
 
	// this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used 
	::DefWindowProc(NULL, 0, 0, 0L); 
 
	AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);	// add flags to support other controls 
 
	hRes = _Module.Init(NULL, hInstance); 
	ATLASSERT(SUCCEEDED(hRes)); 
 
	int nRet = 0; 
	// BLOCK: Run application 
	{ 
		CConsoleThreadManager mgr; 
		nRet = mgr.Run(lpstrCmdLine, nCmdShow); 
	} 
 
	_Module.Term(); 
	::CoUninitialize(); 
	WSACleanup(); 
 
	return nRet; 
}