API Хук на функции объекта COM? - PullRequest
5 голосов
/ 12 сентября 2010

Приветствия StackOverflowians,

Как обнаружено здесь , в Windows 7 имеется ошибка, из-за которой событие DISPID_BEFORENAVIGATE2 не запускается для экземпляров Windows Explorer.Это событие позволяет уведомлять расширения оболочки, когда навигация вот-вот произойдет, и (что наиболее важно для меня) имеет возможность отменить навигацию.Я искал обходной путь в течение довольно долгого времени, и я думаю, что нашел его.Но я хотел бы получить некоторые мнения о том, насколько это безопасно.

В последнее время я много играл с перехватом API и уже использую его, чтобы перехватить несколько функций для моего расширения.Я заметил, что в IShellBrowser есть функция , которая управляет навигацией.Сначала я думал, что вы не можете подключить что-то подобное, но прочитав о макете COM-объекта , я понял, что это возможно, просто выбрав правильный указатель функции из виртуальной таблицы любого активного экземпляра.,Конечно же, это работает как сон.После того, как хук установлен, все переходы во всех окнах Проводника проходят через мою функцию обхода, и я могу решить, отклонять ли их, основываясь на их целевом pidl.

Так что мой вопрос, есть ли причина, по которой я долженНЕ делать это?Я никогда не слышал о перехватах API, используемых для перехвата функций COM-объектов.Есть ли обстоятельства, которые бы не сработали?Это опасно?(По крайней мере, больше, чем обычные перехваты API)

Соответствующий код следует.Я использую MinHook , минималистичную библиотеку перехвата, которая использует проверенный метод батутных функций.

typedef HRESULT (WINAPI *BROWSEOBJECT)(IShellBrowser*, PCUIDLIST_RELATIVE, UINT);
HRESULT WINAPI DetourBrowseObject(IShellBrowser* _this, PCUIDLIST_RELATIVE pidl, UINT wFlags);
BROWSEOBJECT fpBrowseObject = NULL;
BROWSEOBJECT ShellBrowser_BrowseObject = NULL;

bool Initialize() {
    if(MH_Initialize() != MH_OK) {
        return false;
    }

    // Get a reference to an existing IShellBrowser.  Any instance will do.
    // ShellBrowser enum code taken from The Old New Thing
    IShellWindows *psw;
    BOOL fFound = FALSE;
    if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_IShellWindows, (void**)&psw))) {
        VARIANT v;
        V_VT(&v) = VT_I4;
        IDispatch  *pdisp;
        for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK; V_I4(&v)++) {
            IWebBrowserApp *pwba;
            if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) {
                IServiceProvider *psp;
                if (SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) {
                    IShellBrowser *psb;
                    if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser,IID_IShellBrowser, (void**)&psb))) {
                        fFound = true;

                        // Grab the 11th entry in the VTable, which is BrowseObject
                        void** vtable = (*(void***)(psb));
                        ShellBrowser_BrowseObject = (BROWSEOBJECT)(vtable[11]);
                        psb->Release();
                    }
                    psp->Release();
                }
                pwba->Release();
            }
            pdisp->Release();
        }
        psw->Release();
    }

    if(fFound) {
        if(MH_CreateHook(ShellBrowser_BrowseObject, &DetourBrowseObject, reinterpret_cast<void**>(&fpBrowseObject)) != MH_OK) {
            return false;
        }
        if(MH_EnableHook(ShellBrowser_BrowseObject) != MH_OK) {
            return false;
        }
    }
    return true;
}

HRESULT WINAPI DetourBrowseObject(IShellBrowser* _this, PCUIDLIST_RELATIVE pidl, UINT wFlags) {
    if(NavigateIsOkay(pidl, wFlags)) {
        return fpBrowseObject(_this, pidl, wFlags);
    }
    else {
        return S_FALSE;
    }    
}

1 Ответ

2 голосов
/ 12 сентября 2010

Я никогда не слышал об использовании перехвата API перехватить функции COM-объекта.

Функции-члены COM-объектов на самом деле не так уж отличаются, и их можно подключить просто отлично, если вы будете придерживаться обычных правил подключения. Несколько лет назад мне пришлось подключить COM-компоненты проприетарного решения CRM, чтобы подключить его к серверу базы данных. Приложение работало нормально и работает довольно стабильно в течение нескольких лет.

...