Share via

How to hook the ItaskbarList4 class?

Cesar 0 Reputation points
2024-05-06T09:48:17.41+00:00

I'm trying to customize the taskbar buttons, for this i'm hooking the ItaskbarList4 class using Detours, however, the functions on MyTaskbarList isn't getting called, trying to figure out what's wrong:

inline HRESULT(WINAPI* CoCreateInstance_O)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID* ppv) = CoCreateInstance;

class MyTaskbarList : public ITaskbarList4 {
public:
    MyTaskbarList(ITaskbarList4* original) : m_original(original) {}
    // IUnknown methods
    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override {
        if (riid == __uuidof(IUnknown) || riid == __uuidof(ITaskbarList4)) {
            *ppvObject = static_cast<ITaskbarList4*>(this);
            AddRef();
            return S_OK;
        }
        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }
    ULONG STDMETHODCALLTYPE AddRef() override {
        return InterlockedIncrement(&m_refCount);
    }
    ULONG STDMETHODCALLTYPE Release() override {
        ULONG refCount = InterlockedDecrement(&m_refCount);
        if (refCount == 0) {
            delete this;
        }
        return refCount;
    }
    HRESULT STDMETHODCALLTYPE HrInit() override {
        return m_original->HrInit();
    }
    HRESULT STDMETHODCALLTYPE AddTab(HWND hwnd) override {
        return m_original->AddTab(hwnd);
    }
    HRESULT STDMETHODCALLTYPE DeleteTab(HWND hwnd) override {
        return m_original->DeleteTab(hwnd);
    }
    HRESULT STDMETHODCALLTYPE ActivateTab(HWND hwnd) override {
        return m_original->ActivateTab(hwnd);
    }
    HRESULT STDMETHODCALLTYPE SetActiveAlt(HWND hwnd) override {
        return m_original->SetActiveAlt(hwnd);
    }
    HRESULT STDMETHODCALLTYPE MarkFullscreenWindow(HWND hwnd, BOOL fFullscreen) override {
        return m_original->MarkFullscreenWindow(hwnd, fFullscreen);
    }
    HRESULT STDMETHODCALLTYPE SetProgressValue(HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) override {
        return m_original->SetProgressValue(hwnd, ullCompleted, ullTotal);
    }
    HRESULT STDMETHODCALLTYPE SetProgressState(HWND hwnd, TBPFLAG tbpFlags) override {
        return m_original->SetProgressState(hwnd, tbpFlags);
    }
    HRESULT STDMETHODCALLTYPE RegisterTab(HWND hwndTab, HWND hwndMDI) override {
        OutputDebugStringW(L"RegisterTab");
        return m_original->RegisterTab(hwndTab, hwndMDI);
    }
    HRESULT STDMETHODCALLTYPE UnregisterTab(HWND hwndTab) override {
        return m_original->UnregisterTab(hwndTab);
    }
    HRESULT STDMETHODCALLTYPE SetTabOrder(HWND hwndTab, HWND hwndInsertBefore) override {
        return m_original->SetTabOrder(hwndTab, hwndInsertBefore);
    }
    HRESULT STDMETHODCALLTYPE SetTabActive(HWND hwndTab, HWND hwndMDI, DWORD dwReserved) override {
        return m_original->SetTabActive(hwndTab, hwndMDI, dwReserved);
    }
    HRESULT STDMETHODCALLTYPE ThumbBarAddButtons(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) override {
        return m_original->ThumbBarAddButtons(hwnd, cButtons, pButton);
    }
    HRESULT STDMETHODCALLTYPE ThumbBarUpdateButtons(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) override {
        return m_original->ThumbBarUpdateButtons(hwnd, cButtons, pButton);
    }
    HRESULT STDMETHODCALLTYPE ThumbBarSetImageList(HWND hwnd, HIMAGELIST himl) override {
        return m_original->ThumbBarSetImageList(hwnd, himl);
    }
    HRESULT STDMETHODCALLTYPE SetOverlayIcon(HWND hwnd, HICON hIcon, LPCWSTR pszDescription) override {
        return m_original->SetOverlayIcon(hwnd, hIcon, pszDescription);
    }
    HRESULT STDMETHODCALLTYPE SetThumbnailTooltip(HWND hwnd, LPCWSTR pszTip) override {
        return m_original->SetThumbnailTooltip(hwnd, pszTip);
    }
    HRESULT STDMETHODCALLTYPE SetThumbnailClip(HWND hwnd, RECT* prcClip) override {
        return m_original->SetThumbnailClip(hwnd, prcClip);
    }
    HRESULT STDMETHODCALLTYPE SetTabProperties(HWND hwndTab, STPFLAG stpFlags) override {
        return m_original->SetTabProperties(hwndTab, stpFlags);
    }
private:
    ITaskbarList4* m_original;
    LONG m_refCount;
};



HRESULT WINAPI CoCreateInstance_H(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID* ppv)
{
    if (rclsid == CLSID_TaskbarList)
    {
        if (riid == IID_ITaskbarList4)
        {
            ITaskbarList4* original;
            HRESULT hr = CoCreateInstance_O(rclsid, pUnkOuter, dwClsContext, riid, (void**)&original);
            OutputDebugStringW(L"CoCreateInstance_H");
            if (SUCCEEDED(hr))
            {
                *ppv = new MyTaskbarList(original);
                OutputDebugStringW(L"success");
            }
            return hr;
        }
    }
	return CoCreateInstance_O(rclsid, pUnkOuter, dwClsContext, riid, ppv);
}
#include "stdafx.h"
#include "Detours.h"
#pragma comment(lib, "detours.lib")
BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        {
            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            DetourAttach(&(PVOID&)CoCreateInstance_O, CoCreateInstance_H);
        }
    }
    return TRUE;
}
Developer technologies | C++
Developer technologies | C++

A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.


2 answers

Sort by: Most helpful
  1. RLWA32 52,571 Reputation points
    2024-05-09T11:09:41.1566667+00:00

    I used Microsoft's TabThumbnails sample to demonstrate using an activation filter to intercept CLSID_TaskbarList creation to instantiate a wrapper object.

    Instantiate the COM object that implements IActivationFilter and register it -

    TabApp

    Results showing the COM interception while the sample application runs -

    ActivationFilter

    Was this answer helpful?

    0 comments No comments

  2. RLWA32 52,571 Reputation points
    2024-05-08T14:12:40.3366667+00:00

    There are other ways of intercepting COM interfaces and their methods besides Detours. For example, registering a process activation filter using the CoRegisterActivationFilter function could cause COM to instantiate your wrapper object when processing CoCreateInstance for CLSID_TaskbarList.

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.