// 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 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;
}
}