如何将DLL注入Adobe Reader X.

时间:2011-06-10 11:29:32

标签: winapi automation adobe-reader setwindowshookex

我需要将一个DLL注入到Adobe Reader X中,该DLL读取发送到滚动条的事件(即使它被隐藏)。我需要这样做才能找到我所在文档的哪个页面。

我尝试使用win32挂钩API挂钩一个dll,我给桌面上的所有进程提供一个CBT挂钩,并监听Adobe Reader X窗口的创建,然后用我的滚动条挂钩挂钩这个窗口。

问题是我从未在Adobe Reader X上放置滚动条挂钩,创建窗口或窗口时,我们不会为这些窗口激活消息。我如何获得这些消息以及如何挂钩到Adobe Reader X?

#define WIN32_LEAN_AND_MEAN  
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "pdfviewlib.h"
#include <sstream>

#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<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<MAX_PDFOBJS; i++)
    {
        if(pdfviewobj[i].state==PDF_CLOSED)
        {
            id=i;
            break;
        }
    }
    if(id<0)
    {
        DEBUG("OpenPDF: Too many PDFs\n");
        return -1;
    }
    if (pdfviewobj[id].state == PDF_STARTED) 
    {
        DEBUG("RERUN WHEN PDF_STARTED\n");
        return -1;
    }
    memset(&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->dwProcessId;
    pdfviewobj[id].dwThreadId = pi->dwThreadId;
    pdfviewobj[id].hThread = pi->hThread;
    pdfviewobj[id].hProcess = pi->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 > 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, &hkey)!=ERROR_SUCCESS)            
            return FALSE;   
    dwtype = REG_SZ;
    dwsize = (DWORD)strsize;
    lresult = RegQueryValueEx(hkey, NULL, NULL, &dwtype, (LPBYTE)pdfviewerpath, &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(&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 < 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<MAX_PDFOBJS; i++)
            {
                if(pdfviewobj[i].dwThreadId==windowthread)
                {
                    id=i;
                    break;
                }
            }
            if(id>=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->lpcs->hwndParent = pdfviewobj[id].hParentWnd;
                }
                if((pdfviewobj[id].hWnd!=NULL)&&(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->hwnd,NULL);
    int id=-1;
    for(int i=0; i<MAX_PDFOBJS; i++)
    {
        if(pdfviewobj[i].dwThreadId==windowthread)
        {
            id=i;
            hook = pdfviewobj[id].hook;
            break;
        }
    }
    if((id>=0)&&(nCode==HC_ACTION))
    {
        DEBUG("CBT HC_ACTION\n");
        if(cwp->message==SBM_SETSCROLLINFO)
        {
            DEBUG("CBT SBM_SETSCROLLINFO\n");
            SCROLLINFO *scrInf;
            scrInf = (SCROLLINFO *)cwp->lParam;
            pdfviewobj[id].currentSlide = scrInf->nPos;             
        }
        if((pdfviewobj[id].state != PDF_CLOSED)&&(cwp->message==WM_CLOSE||cwp->message==WM_QUIT)){
            pdfviewobj[id].state = PDF_CLOSING;
        }
    }
    return CallNextHookEx(hook,nCode,wParam,lParam); 
}

如果你需要它,那就是标题

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

1 个答案:

答案 0 :(得分:2)

Adob​​e Reader通常以受保护模式运行。 (请参阅编辑/首选项/安全性(增强)。取消选中“启动时启用保护模式”复选框。

重新启动阅读器,看看您是否收到了消息。你应该。问题是用户界面权限隔离(UIPI)不允许许多Windows消息跨越以不同完整性级别(低/中/高)运行的进程之间的进程边界。您应该可以通过ChangeWindowMessageFilterEx()更改Windows消息过滤器。

我目前遇到Adobe Reader Xi的问题,其中ChangeWindowsMessageFilter和ChangeWindowMessageFilterEx似乎没有改变Adobe读取器在挂钩过程中向全局钩子接收器发送消息的行为。我已将noteapad.exe复制到notepad2.exe并将其完整性级别降低到低位:icacls notepad2.exe / setintegritylevel low  (从提升的cmd提示符运行(即以管理员身份运行))。当我这样做时,我的挂钩工作正常(使用ChangeWindowMessageFilterEx()),但仍然没有得到来自Adobe的挂钩消息。

另外,Reader是32位的,所以请确保你从32位挂钩过程挂钩,否则你也不会看到消息。