// ImgBurnProg.cpp : Defines the exported functions for the DLL application.//#include "stdafx.h"#include <Strsafe.h>#include <Windows.h>#include <psapi.h>#include <stdlib.h>#define maxLine 500#define maxWndName 512HANDLE 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 ImgBurnint 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 filesBOOL 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 mircBOOL 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 messageboxBOOL 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 lParamBOOL 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; }}