Add Custom Banner to Namespace Extension

366 views Asked by At

Windows explorer has the ability to show a custom banner when doing a search and indexing is disabled:

Explorer indexing not running image

I would like to display a similar banner in a custom namespace extension with a custom message and custom link handler. Is there an namespace extension interface I can implement that will allow me to provide this functionality? I have searched for various terms in the namespace extension documentation , but I can't figure out the correct terms to use.

1

There are 1 answers

0
bho3538 On BEST ANSWER

That feature is not documented by Microsft. And i found how to show information bar from namespace extension.

Picture

First you need declare 3 undocumented interface

IInfobarHost

MIDL_INTERFACE("e38fe0f3-3db0-47ee-a314-25cf7f4bf521")
IInfoBarHost : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE Inform(IInfoBarMessage* msg) = 0;
    virtual HRESULT STDMETHODCALLTYPE CancelInform(GUID guid) = 0;
};

IInfobarMessage

MIDL_INTERFACE("819d1334-9d74-4254-9ac8-dc745ebc5386")
IInfoBarMessage : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE GetMessageID(GUID* guid,INT* intVal) = 0;
    virtual HRESULT STDMETHODCALLTYPE GetMessageW(LPWSTR* message) = 0;
    virtual HRESULT STDMETHODCALLTYPE CreateMenu(HMENU* pMwnu) = 0;
    virtual HRESULT STDMETHODCALLTYPE HandleMenu(HWND hwnd,int intVal) = 0;
};

IBrowserProgressSessionProvider

MIDL_INTERFACE("18140CBD-AA23-4384-A38D-6A8D3E2BE505")
IBrowserProgressSessionProvider : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE BeginSession() = 0; //Unknown
    virtual HRESULT STDMETHODCALLTYPE EndSession() = 0;//Unknown
    virtual HRESULT STDMETHODCALLTYPE GetCurrentSession(PDWORD sessionId) = 0;
    virtual HRESULT STDMETHODCALLTYPE ActivateSession() = 0;//Unknown
};

IID_IInfoBarHost : e38fe0f3-3db0-47ee-a314-25cf7f4bf521
IID_IBrowserProgressConnection : 20174539-B2C7-4EC7-970B-04201F9CDBAD
IID_IBrowserProgressAggregator : 5EA8EEC4-C34B-4DE0-9B56-0E15FD8C8F80
IID_IBrowserProgressSessionProvider : 18140CBD-AA23-4384-A38D-6A8D3E2BE505

2.Create one class and implement IInfoBarMessage.
GetMessageID(GUID* guid,INT* pIntVal)
Get Infobar guid. Generate own random guid for current infobar message.

HRESULT STDMETHODCALLTYPE CInfoBarMessageImpl::GetMessageID(GUID* guid, INT* intVal) {
    //Our InformationBar GUID (generated in constructor)
    *guid = this->guid;
    return S_OK;
}

GetMessageW(LPWSTR* message)
Get InformationBar message
allocate memory and copy unicode string to parameter (using CoTaskMemAlloc)

HRESULT STDMETHODCALLTYPE CInfoBarMessageImpl::GetMessageW(LPWSTR* message) {
    if (!this->message) { //message set at constructor or set at our own initialize function
        return E_FAIL;
    }
    *message = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (this->messageLen + 1));
    wcscpy_s(*message, this->messageLen + 1, this->message);
    return S_OK;
}
  1. Get IServiceProvider from ShellView(IShellView) and Get IBrowserProgressSessionProvider interface to get dwCookie value.
    After that , Get IBrowserProgressConnection From GIT(GlobalInterfaceTable) using ‘dwCookie’ from ‘GetCurrentSession’ and Get IInfoBarHost interface From BrowserProgressConnection
//CInfobarManger is own class (does not implement anyone)
void CInfoBarManager::ShowInfoBar(IShellView* shview) {
    HRESULT hr;
    DWORD dwCookie = 0;

    if (!this->sprovider) {
        hr = shview->QueryInterface(IID_IServiceProvider, (PVOID*)&sprovider);
        if (FAILED(hr)) {
            goto escapeArea;
        }
    }

    if (!this->sessionProvider) {
        hr = this->sprovider->QueryService(IID_IBrowserProgressAggregator, IID_IBrowserProgressSessionProvider, (PVOID*)&this->sessionProvider);
        if (FAILED(hr)) {
            goto escapeArea;
        }
    }

    hr = sessionProvider->GetCurrentSession(&dwCookie);
    if (FAILED(hr)) {
        goto escapeArea;
    }

    //Get GIT
    if (!this->git) {
        hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER,
            IID_IGlobalInterfaceTable, (PVOID*)&this->git);
        if (FAILED(hr)) {
            goto escapeArea;
        }
    }

    hr = this->git->GetInterfaceFromGlobal(dwCookie, IID_IBrowserProgressConnecion, (PVOID*)&this->browserProgress);
    if (hr == S_OK) {
        hr = this->browserProgress->QueryInterface(IID_IInfoBarHost, (PVOID*)&this->host);
        if (hr == S_OK) {
            //Call Relase in explorer inside
            this->infoMsg->AddRef();
            this->host->Inform(this->infoMsg);
        }
    }
escapeArea:
    return;
}
  1. Show Infobar at MessageSFVCB if uMsg is 17 (onrefresh) or other place if you want.
//in MessageSFVCB
else if (uMsg == 17) { //OnRefresh
    if (!this->infobar) {
        this->infobar = new CInfoBarManager();
        infobar->InitializeSimple(L"NSE Information Bar Message");
    }
    infobar->ShowInfoBar(this->shview); //IShellView
}

sample codes : https://github.com/bho3538/NSEInformationBar