Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to inject a DLL into Adobe Reader X
    text
    copied!<p>I need to inject a DLL into Adobe Reader X that reads the events sent to the scrollbar (even if it is hidden). I need to do this to be able to find out what page of the document i am on.</p> <p>I have tried hooking a dll using the win32 hooking API, i give a CBT hook to all processes on the desktop and listen for the creation of the Adobe Reader X window, then hooking this window with my scrollbar hook. </p> <p>The problem is that i never get the scrollbar hook placed on Adobe Reader X, i dont get the create window or window activate messages for these windows when they are created. How do i get these messages and how do i hook into Adobe Reader X?</p> <pre><code>#define WIN32_LEAN_AND_MEAN #include &lt;windows.h&gt; #include &lt;string.h&gt; #include &lt;stdlib.h&gt; #include &lt;stdio.h&gt; #include &lt;time.h&gt; #include &lt;sys/types.h&gt; #include &lt;sys/stat.h&gt; #include "pdfviewlib.h" #include &lt;sstream&gt; #pragma data_seg(".PDFVIEWLIB") PDFVIEWOBJ pdfviewobj[MAX_PDFOBJS] = {NULL}; HHOOK globalhook = NULL; BOOL debug = TRUE; INT sSlide = 0; #pragma data_seg() #pragma comment(linker, "/SECTION:.PDFVIEWLIB,RWS") #define DEBUG(...) if(debug) printf(__VA_ARGS__) HINSTANCE hInstance = NULL; static int tAttach = 0; static int tDetach = 0; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { hInstance = (HINSTANCE)hModule; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: DEBUG("PROCESS_ATTACH\n"); break; case DLL_THREAD_ATTACH: DEBUG("THREAD_ATTACH %i\n",tAttach++); break; case DLL_THREAD_DETACH: DEBUG("THREAD_DETACH %i\n", tDetach++); break; case DLL_PROCESS_DETACH: // Clean up... hopefully there is only the one process attached? DEBUG("PROCESS_DETACH\n"); for(int i = 0; i&lt;MAX_PDFOBJS; i++) ClosePDF(i); break; } return TRUE; } DllExport void SetDebug(BOOL onoff) { printf("SetDebug\n"); debug = onoff; DEBUG("enabled\n"); } //Check if Acrobat Reader is installed DllExport BOOL CheckInstalled() { DEBUG("CheckInstalled\n"); char cmdline[MAX_PATH * 2]; return GetPDFViewerPath(cmdline, sizeof(cmdline)); } // Open the PDF DllExport int OpenPDF(char *filename, HWND hParentWnd, int startSlide) { STARTUPINFO * si = (STARTUPINFO *) malloc(sizeof(STARTUPINFO)); PROCESS_INFORMATION * pi = (PROCESS_INFORMATION*) malloc(sizeof(PROCESS_INFORMATION)); char cmdline[MAX_PATH * 2]; int id; sSlide = startSlide; DEBUG("OpenPDF start: %u", hParentWnd); //First check if Acrobat Reader is installed before continuing if(GetPDFViewerPath(cmdline, sizeof(cmdline))==FALSE) { DEBUG("OpenPDF: GetPDFTViewerPath failed\n"); return -1; } id = -1; for(int i = 0; i&lt;MAX_PDFOBJS; i++) { if(pdfviewobj[i].state==PDF_CLOSED) { id=i; break; } } if(id&lt;0) { DEBUG("OpenPDF: Too many PDFs\n"); return -1; } if (pdfviewobj[id].state == PDF_STARTED) { DEBUG("RERUN WHEN PDF_STARTED\n"); return -1; } memset(&amp;pdfviewobj[id], 0, sizeof(PDFVIEWOBJ)); strcpy_s(pdfviewobj[id].filename, MAX_PATH, filename); pdfviewobj[id].state = PDF_CLOSED; pdfviewobj[id].currentSlide = 0; pdfviewobj[id].hParentWnd = hParentWnd; pdfviewobj[id].hWnd = NULL; pdfviewobj[id].hWnd2 = NULL; strcat_s(cmdline, MAX_PATH * 2, "\\AcroRd32.exe /n /s /o"); strcat_s(cmdline, MAX_PATH * 2, " \""); strcat_s(cmdline, MAX_PATH * 2, filename); strcat_s(cmdline, MAX_PATH * 2, "\""); si = (STARTUPINFO *)memset(si, 0, sizeof(STARTUPINFO)); pi = (PROCESS_INFORMATION *)memset(pi, 0, sizeof(PROCESS_INFORMATION)); if(globalhook!=NULL){ UnhookWindowsHookEx(globalhook); DEBUG("Global unhooked\n"); globalhook = NULL; } //Set the global hook listening for Window Create/Window Activate messages globalhook = SetWindowsHookEx(WH_CBT,CbtProc,hInstance,NULL); if(globalhook==NULL) { DEBUG("OpenPDF: Global SetWindowsHookEx failed\n"); DEBUG("ERROR: %X\n", GetLastError()); globalhook = NULL; ClosePDF(id); return -1; } else DEBUG("GLOBAL HOOKED %X\n", globalhook); pdfviewobj[id].state = PDF_STARTED; Sleep(10); DEBUG(cmdline); //Run Acrobat Reader, PDF STATE SET TO STARTED if(!CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, 0, NULL, si, pi)) { DEBUG("OpenPDF: CreateProcess failed\n"); ClosePDF(id); return -1; } pdfviewobj[id].dwProcessId = pi-&gt;dwProcessId; pdfviewobj[id].dwThreadId = pi-&gt;dwThreadId; pdfviewobj[id].hThread = pi-&gt;hThread; pdfviewobj[id].hProcess = pi-&gt;hProcess; //WAIT FOR GLOBAL HOOK TO DETECT Acrobat Windows and set PDF STATE TO PDF_OPENED //For some reason the loops exits and PDFSTATE is PDF_CLOSED... while(pdfviewobj[id].state==PDF_STARTED) Sleep(50); DEBUG("PDFSTATE == CLOSED = %i \n", pdfviewobj[id].state==PDF_CLOSED); DEBUG("PDFSTATE == STARTED = %i \n", pdfviewobj[id].state==PDF_STARTED); DEBUG("PDFSTATE == OPENED = %i \n", pdfviewobj[id].state==PDF_OPENED); DEBUG("PDFSTATE == LOADED = %i \n", pdfviewobj[id].state==PDF_LOADED); if (sSlide &gt; 0){ GotoSlide(id, sSlide+1); } pdfviewobj[id].state = PDF_LOADED; DEBUG("OpenPDF Done: id=%i\n", id); return id; } // Get the path of Acrobat Reader X from the registry BOOL GetPDFViewerPath(char *pdfviewerpath, int strsize) { HKEY hkey; DWORD dwtype, dwsize; LRESULT lresult; DEBUG("GetPDFViewerPath: start\n"); if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Adobe\\Acrobat Reader\\9.0\\InstallPath", 0, KEY_READ, &amp;hkey)!=ERROR_SUCCESS) return FALSE; dwtype = REG_SZ; dwsize = (DWORD)strsize; lresult = RegQueryValueEx(hkey, NULL, NULL, &amp;dwtype, (LPBYTE)pdfviewerpath, &amp;dwsize ); RegCloseKey(hkey); if(lresult!=ERROR_SUCCESS) return FALSE; DEBUG("GetPDFViewerPath: exit ok \n"); return TRUE; } // Unhook the Windows hook void Unhook(int id) { DEBUG("Unhook: start %i\n", id); if(pdfviewobj[id].hook!=NULL) UnhookWindowsHookEx(pdfviewobj[id].hook); pdfviewobj[id].hook = NULL; DEBUG("Unhook: exit ok\n"); } // Close the Acrobat Reader, release resources DllExport void ClosePDF(int id) { DEBUG("ClosePDF: start %i\n", id); if (globalhook != NULL) { DEBUG("GLOBAL UNHOOKED %X\n", globalhook); UnhookWindowsHookEx(globalhook); globalhook = NULL; } else DEBUG("GLOBAL NOT UNHOOKED\n"); pdfviewobj[id].state = PDF_CLOSED; Unhook(id); if(pdfviewobj[id].hWnd==0) TerminateThread(pdfviewobj[id].hThread, 0); else PostMessage(pdfviewobj[id].hWnd, WM_CLOSE, 0, 0); CloseHandle(pdfviewobj[id].hThread); CloseHandle(pdfviewobj[id].hProcess); memset(&amp;pdfviewobj[id], 0, sizeof(PDFVIEWOBJ)); DEBUG("ClosePDF: exit ok\n"); return; } // Return the number of the slide currently viewing DllExport int GetCurrentSlide(int id) { DEBUG("GetCurrentSlide:%d\n", id); if(pdfviewobj[id].state==0) return -1; else return pdfviewobj[id].currentSlide; } // Take a step forwards through the show DllExport void NextStep(int id) { DEBUG("NextStep:%d\n", id); SetForegroundWindow(pdfviewobj[id].hWnd); SetFocus(pdfviewobj[id].hWnd); PostMessage(pdfviewobj[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, -WHEEL_DELTA), 0); } // Take a step backwards through the show DllExport void PrevStep(int id) { DEBUG("PrevStep:%d\n", id); SetForegroundWindow(pdfviewobj[id].hWnd); SetFocus(pdfviewobj[id].hWnd); PostMessage(pdfviewobj[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), 0); } // Go directly to a slide DllExport void GotoSlide(int id, int slideno) { //TODO: USE SETSCROLLINFO } // This hook is started with the AcroRd32.EXE process and waits for the WM_CREATEWND message. // Release the hook as soon as we're complete to free up resources LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam) { HHOOK hook = globalhook; DEBUG("HOOK: %X\n", hook); if (nCode &lt; 0) { return CallNextHookEx(hook, nCode, wParam, lParam); } else if(nCode==HCBT_CREATEWND) { DEBUG("CREATE WINDOW \n"); char csClassName[16]; char csCaptionName[16]; HWND hCurrWnd = (HWND)wParam; DWORD retProcId = NULL; GetClassName(hCurrWnd, csClassName, sizeof(csClassName)); GetWindowText(hCurrWnd, csCaptionName, sizeof(csCaptionName)); if((strcmp(csClassName, "AcrobatSDIWindow")==0) ||(strcmp(csClassName, "AVL_AVView")==0)) { DEBUG("%s found \n", csClassName); int id=-1; DWORD windowthread = GetWindowThreadProcessId(hCurrWnd,NULL); for(int i=0; i&lt;MAX_PDFOBJS; i++) { if(pdfviewobj[i].dwThreadId==windowthread) { id=i; break; } } if(id&gt;=0) { DEBUG("Matched threadid!\n"); if(strcmp(csClassName, "AVL_AVView")==0){ if (strcmp(csCaptionName, "AVPageView")==0){ pdfviewobj[id].hWnd2=hCurrWnd; } } else { pdfviewobj[id].hWnd=hCurrWnd; CBT_CREATEWND* cw = (CBT_CREATEWND*)lParam; if(pdfviewobj[id].hParentWnd!=NULL) cw-&gt;lpcs-&gt;hwndParent = pdfviewobj[id].hParentWnd; } if((pdfviewobj[id].hWnd!=NULL)&amp;&amp;(pdfviewobj[id].hWnd2!=NULL)) { pdfviewobj[id].hook = SetWindowsHookEx(WH_CALLWNDPROC,CwpProc,hInstance,pdfviewobj[id].dwThreadId); if (pdfviewobj[id].hook != NULL) { DEBUG("Global UNHOOKED %X\n", globalhook); UnhookWindowsHookEx(globalhook); globalhook=NULL; pdfviewobj[id].state = PDF_OPENED; } Sleep(10); } } } } return CallNextHookEx(hook,nCode,wParam,lParam); } LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam){ CWPSTRUCT *cwp; cwp = (CWPSTRUCT *)lParam; HHOOK hook = NULL; DWORD windowthread = GetWindowThreadProcessId(cwp-&gt;hwnd,NULL); int id=-1; for(int i=0; i&lt;MAX_PDFOBJS; i++) { if(pdfviewobj[i].dwThreadId==windowthread) { id=i; hook = pdfviewobj[id].hook; break; } } if((id&gt;=0)&amp;&amp;(nCode==HC_ACTION)) { DEBUG("CBT HC_ACTION\n"); if(cwp-&gt;message==SBM_SETSCROLLINFO) { DEBUG("CBT SBM_SETSCROLLINFO\n"); SCROLLINFO *scrInf; scrInf = (SCROLLINFO *)cwp-&gt;lParam; pdfviewobj[id].currentSlide = scrInf-&gt;nPos; } if((pdfviewobj[id].state != PDF_CLOSED)&amp;&amp;(cwp-&gt;message==WM_CLOSE||cwp-&gt;message==WM_QUIT)){ pdfviewobj[id].state = PDF_CLOSING; } } return CallNextHookEx(hook,nCode,wParam,lParam); } </code></pre> <p>heres the header if you need it</p> <pre><code>#define DllExport extern "C" __declspec( dllexport ) enum PDFVIEWSTATE { PDF_CLOSED, PDF_STARTED, PDF_OPENED, PDF_LOADED, PDF_CLOSING}; DllExport int OpenPDF(char *filename, HWND hParentWnd, int startSlide); DllExport BOOL CheckInstalled(); DllExport void ClosePDF(int id); DllExport int GetCurrentSlide(int id); DllExport void NextStep(int id); DllExport void PrevStep(int id); DllExport void GotoSlide(int id, int slideno); DllExport void SetDebug(BOOL onoff); LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam); BOOL GetPDFViewerPath(char *pdfviewerpath, int strsize); void Unhook(int id); //MAXUMUM NUMBER OF PDF-PROCESSES CURRENTLY SET TO ONE #define MAX_PDFOBJS 1 struct PDFVIEWOBJ { HHOOK hook; HWND hWnd; HWND hWnd2; HWND hParentWnd; HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; int currentSlide; char filename[MAX_PATH]; PDFVIEWSTATE state; }; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload