// ImgBurnProg.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include #include #include #include #define maxLine 500 #define maxWndName 512 HANDLE hFileMap; LPSTR mData; int wndFound; char ProcessName[MAX_PATH] = "ImgBurn.exe"; char ProgWndName[] = "% - ImgBurn"; char DestWndName[] = "Destination"; char TextBuffer[maxLine]; DWORD IbPid = 0; DWORD BurnStatus; bool StopSearching; int CheckProcessName(DWORD processID, char *checkProcessName) { char processName[MAX_PATH]; // Get a handle to the process. HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); // Get the process name. if (NULL != hProcess) { HMODULE hMod; DWORD cbNeeded; if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) GetModuleBaseNameA(hProcess, hMod, processName, sizeof(processName)/sizeof(char)); } CloseHandle(hProcess); return !_strnicmp(processName, checkProcessName, MAX_PATH); } // call this function first to get the ImgBurn PID // that way we can search only windows owned by ImgBurn int GetImgBurnPid() { DWORD pProcessIds[1024], foundID = 0; DWORD pBytesReturned; if (!EnumProcesses(pProcessIds, sizeof(pProcessIds), &pBytesReturned)) return 0; DWORD numProcesses = pBytesReturned / sizeof(DWORD); for (int i = 0; i < numProcesses; i++) { if(pProcessIds[i] != 0) { if (CheckProcessName(pProcessIds[i], ProcessName)) { IbPid = pProcessIds[i]; break; } } } } // if lParam == 0 then copy the first available text // otherwise when we find text which matches what lparam points to and get the first text below that // the point was to get the text of the filename for the iso being created // so i searched for a dialog item named "Destination" and its first child is the filename // you really want to find the filename being burned, but I was testing by creating ISO files BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) { char buf[512]; char *foo = (char*)lParam; if (lParam == 0) { if (SendMessageTimeoutA(hwnd, WM_GETTEXT, sizeof(TextBuffer)/sizeof(char), (LPARAM)(void*)TextBuffer, SMTO_ABORTIFHUNG, 1000, 0)) { StopSearching = true; return 0; } } else if (SendMessageTimeoutA(hwnd, WM_GETTEXT, sizeof(buf)/sizeof(char), (LPARAM)(void*)buf, SMTO_ABORTIFHUNG, 1000, 0) && !strncmp(buf, (char*)lParam, 512)) { EnumChildWindows(hwnd, EnumChildProc, 0); return 0; } return 1; } // call this to see if the completed dialog is up (caaled from FindDoneWndProc() // should also be able to add checks for other messages like a failed burn // set BurnStatus to some unigue number for sucess, fail, etc and that number will be returned to mirc BOOL CALLBACK EnumChildGetSAtatusProc(HWND hwnd, LPARAM lParam) { char buf[512]; if (SendMessageTimeoutA(hwnd, WM_GETTEXT, sizeof(buf)/sizeof(char), (LPARAM)(void*)buf, SMTO_ABORTIFHUNG, 1000, 0)) { if (!strncmp(buf, "Operation Successfully Completed!", sizeof("Operation Successfully Completed!"))) { BurnStatus = 1; return 0; } } return 1; } // checks that the window is ImgBurn's then looks for the complete messagebox BOOL CALLBACK FindDoneWndProc(HWND hwnd, LPARAM lParam) { DWORD pid; if (GetWindowThreadProcessId(hwnd, &pid) && pid == IbPid) { EnumChildWindows(hwnd, EnumChildGetSAtatusProc, 0); // if not -1 then something changed BurnStatus, so we're done if (BurnStatus != -1) return 0; } return 1; } // find a child window with the name pointed to by lParam BOOL CALLBACK FindWndProc(HWND hwnd, LPARAM lParam) { DWORD pid; if (GetWindowThreadProcessId(hwnd, &pid) && pid == IbPid) { EnumChildWindows(hwnd, EnumChildProc, lParam); if (StopSearching == true) return 0; } return 1; } // looks for the progress window then copies the percentage number (without the '%') BOOL CALLBACK FindProgWndProc(HWND hwnd, LPARAM lParam) { char buf[512]; char *p; DWORD pid; if (GetWindowThreadProcessId(hwnd, &pid) && pid == IbPid) { if (SendMessageTimeoutA(hwnd, WM_GETTEXT, sizeof(buf)/sizeof(char), (LPARAM)(void*)buf, SMTO_ABORTIFHUNG, 1000, 0) && strstr(buf, ProgWndName)) { if (p = strchr(buf, L'%')) { *p = 0; strncpy((char*)lParam, buf, maxLine / sizeof(TCHAR)); } return 0; } } return 1; } extern "C" { void WINAPI LoadDll(void*) { //create file mapping hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,0,PAGE_READWRITE,0,4096,L"mIRC"); mData = (LPSTR)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0); } int WINAPI UnloadDll(int timeout) { if (!timeout) { //close file mapping UnmapViewOfFile(mData); CloseHandle(hFileMap); } return 0; } // these functions simply return a string which can be processed however the user wants // in an mirc script // $dll(imgburnprog.dll, getprogress,0) int WINAPI getprogress(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause) { if (GetImgBurnPid()) EnumWindows(FindProgWndProc, (LPARAM)(void*)data); return 3; } // $dll(imgburnprog.dll, getstatus,0) // we can't just wait until it says 100% because that window goes away // when the process is finished, so look for the message box that says // success/fail/whatever int WINAPI getstatus(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause) { BurnStatus = -1; if (!GetImgBurnPid()) return 3; EnumWindows(FindDoneWndProc, 0); _ltoa_s(BurnStatus, data, 4, 10); return 3; } // $dll(imgburnprog.dll, getfile,0) int WINAPI getfile(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause) { if (!GetImgBurnPid()) return 3; StopSearching = false; EnumWindows(FindWndProc, (LPARAM)(void*)"Source"); strncpy(data, TextBuffer, sizeof(TextBuffer)); return 3; } }