經常上hf平臺,擠不進去自己想進去的房間,花了一天多時間研究了一下,因此有了以下的文章.
- /*
- witten by : [email protected] (applebomb)
- history : 2012/6/2 (ver 1)
- information : 一直在玩浩方DOTA IMBA, 總是進不了450人房間, 一氣之下花了時間研究
- 怎麼搞自動擠房間. 因此有了下面的程序
- 浩方版本: 5.8.1.516-20120528
- how to use : 打開電信 DOTA IMBA 房間, 運行程序進行自動擠房間
- attention!! : 花時間自己寫的同學注意兩點, 在這兩點上浪費了一天時間.
- 第一: WM_NOTIFY 的消息結構是發送給父窗口而非控件本身, 不過對於ListView控件
- 來說, 似乎用WM_NOTIFY發送雙擊動作結構體 不起作用
- { 如果有成功的同學請郵件告訴我方法, 謝謝! }
- 第二: 運行程序時候需要以Administrator身份, 否則用 GetLastError() = Access Denied
- how to do : step 1. 找出浩方窗口
- step 2. 找出登錄列表
- step 3. openProcess 浩方進程, 在裏面分配幾個獲取信息的變量
- step 4. 發送消息讓取得信息
- step 5. ReadProcessMemory 讀取 step4得到的信息
- step 6. 獲取房間在控件中的相對座標
- step 7. 發送信息點擊登陸房間
- step 8. 如果彈出 Type: "#32770", Name: "浩方電競平臺" 的窗口, 則登錄不成功
- step 9. 如果看不見登錄列表, 則登錄成功
- */
- #include <stdio.h>
- #include <Windows.h>
- #include <WinDef.h>
- #include <CommCtrl.h>
- #include <WinUser.h>
- /* funciton declare */
- BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam); /* 枚舉浩方主進程 */
- BOOL CALLBACK EnumChildWindowsProc(HWND hwnd, LPARAM lparam); /* 枚舉窗口子進程 */
- int main (int argc, const char *argv[])
- {
- ::EnumWindows((WNDENUMPROC)EnumWindowsProc, 0); // 查找浩方主進程
- getchar();
- return 0;
- }
- /*
- 查找浩方主進程
- */
- BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam)
- {
- char programName[256];
- ::GetWindowTextA(hwnd, programName, 256-1);
- if (strstr(programName, "浩方電競平臺")!=NULL)
- {
- printf ("Found main program window. \n");
- ::EnumChildWindows(hwnd, (WNDENUMPROC)EnumChildWindowsProc, 0); /* 找到主窗口, 枚舉找出ListView控件*/
- }
- return true;
- }
- /*
- 查找ListView控件
- */
- BOOL CALLBACK EnumChildWindowsProc(HWND hwnd, LPARAM lparam)
- {
- char hwndName[256];
- ::GetClassNameA(hwnd, hwndName, 256-1); //hwnd 正在枚舉的控件
- if (strcmp(hwndName,"SysListView32") == 0) {
- int nID = ::GetDlgCtrlID(hwnd);
- printf("nID : %d\n",nID);
- if (nID == 257) /*這裏我是找出ListView的控件ID = 257 (還有id = 340, 513, 12001 這三個沒有用)*/
- {
- int find = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0,0);
- //打開浩方進程
- DWORD ProcessID;
- HANDLE handle;
- ::GetWindowThreadProcessId(hwnd, &ProcessID);
- handle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, ProcessID);
- LVITEM *_lvi, lvi; /* 指向一條ListView 記錄*/
- WCHAR *_item, *_subitem; /* */
- WCHAR item[512], subitem[512];
- PPOINT ppoint;
- POINT pt;
- /* 在浩方進程分配獲取信息空間 */
- _lvi = (LVITEM*)VirtualAllocEx(handle, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
- _item = (WCHAR*)VirtualAllocEx(handle, NULL, 512, MEM_COMMIT, PAGE_READWRITE);
- _subitem = (WCHAR*)VirtualAllocEx(handle, NULL, 512, MEM_COMMIT, PAGE_READWRITE);
- ppoint = (PPOINT)VirtualAllocEx(handle, NULL, sizeof(POINT), MEM_COMMIT, PAGE_READWRITE);
- int roomindex = 0; /* 從0開始枚舉房間 */
- bool getinflag =false; /* 登陸成功標誌 */
- while (!getinflag)
- {
- lvi.iSubItem=0; /* Listview中第一項房間名 */
- lvi.cchTextMax=512; /*Number of TCHARs in the buffer pointed to by pszText, including the terminating NULL.*/
- lvi.pszText=(LPWSTR)_item; /* 將浩方進程裏面將要存放房間名稱的地址傳遞給lvi */
- WriteProcessMemory(handle, _lvi, &lvi, sizeof(LVITEM), NULL); /* 將定義好的lvi結構寫到上面在浩方分配的內存裏 */
- SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)roomindex, (LPARAM)_lvi); /* 發送消息將結果寫在 _item指定的內存裏*/
- lvi.iSubItem=1; /*人數*/
- lvi.pszText=(LPWSTR)_subitem;
- WriteProcessMemory(handle, _lvi, &lvi, sizeof(LVITEM), NULL);
- SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)roomindex, (LPARAM)_lvi);
- // 將浩方進程裏取得的結果讀回登陸器進程內存
- ReadProcessMemory(handle, _item, item, 512, NULL);
- ReadProcessMemory(handle, _subitem, subitem, 512, NULL);
- // 比較當前房間是否是需要進入的房間
- wchar_t *pRoomName = wcsstr(item, L"IMBA"); /* 電信 IMBA */
- wchar_t *pRoomCont = wcsstr(subitem, L"/450"); /* 450人 */
- if (pRoomName && pRoomCont){
- printf ("find the room."); //找到合適的房間, 嘗試登陸
- //選擇房間
- lvi.state = LVIS_SELECTED;
- lvi.stateMask = LVIS_SELECTED;
- WriteProcessMemory(handle, _lvi, &lvi, sizeof(LVITEM), NULL);
- ::SendMessage(hwnd, LVM_SETITEMSTATE, (WPARAM)roomindex, (LPARAM)_lvi );
- /* 取得房間一欄在浩方里面的相對位置, LVM_GETITEMPOSITION 消息比較簡單,
- 不需要用到WriteProcessMemory 寫入控制信息 */
- ::SendMessage(hwnd, LVM_GETITEMPOSITION, roomindex, (LPARAM)ppoint);
- ::ReadProcessMemory(handle, ppoint, &pt, sizeof(POINT), NULL);
- // 模擬雙擊房間, postmessage 直接返回, sendmessage 等待結果再返回
- PostMessage(hwnd, WM_LBUTTONDBLCLK, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
- // 檢查是彈出"人滿不能進入, 或者登陸上了房間"
- int waittime = 0; /* 超時從新嘗試另一個房間 */
- while(1)
- {
- /* 不能進入房間, 這裏參考了
- http://blog.csdn.net/courage3000/article/details/7526475 檢查代碼
- */
- HWND hRenMan = FindWindowA("#32770", "浩方電競平臺");
- if (hRenMan) {
- printf("fail to login in. find next room.\n");
- SendMessage(hRenMan, WM_CLOSE, 0, 0);
- break;
- }else{
- if (!IsWindowVisible(hwnd))
- {
- getinflag = true;
- break;
- } // !iswindowvisible
- } // if hRenMan
- waittime++; // 超時嘗試登陸另一個房間
- if (waittime > 10) break;
- Sleep(1000);
- } // while(1)
- } //if pRoomName && pRoomCont
- if (roomindex++ >= find) /*不能登陸成功重新嘗試*/
- roomindex =0;
- }
- VirtualFreeEx(handle, _lvi, 0, MEM_RELEASE); // 釋放內存
- VirtualFreeEx(handle, _item, 0, MEM_RELEASE);
- VirtualFreeEx(handle, _subitem, 0, MEM_RELEASE);
- VirtualFreeEx(handle, ppoint, 0, MEM_RELEASE);
- }
- }
- return true;
- }
- /*
- * subprogram : 用鼠標找出鼠標位置的子窗口句柄
- */
- void subprogram_findWNDbyMouse()
- {/*
- POINT pt;
- ::GetCursorPos(&pt);
- HWND wfp = ::WindowFromPoint(pt);
- if (wfp != NULL && ::GetParent(wfp) == hwnd)
- {
- printf ("mouse point at: %d, %d",pt.x,pt.y);
- printf ("mouse point: find window : ");
- char lpsubWinName[256], plsubWinText[256];
- ::GetClassNameA(wfp, lpsubWinName, 256 - 1);
- ::GetWindowTextA(wfp, plsubWinText, 256-1);
- printf (" %s %s\n", lpsubWinName, plsubWinText);
- }
- */
- }