新的 updateExplorer 未从我的 ContextMenuHandler 查询 IContextMenu 接口

问题描述 投票:0回答:0

我正在尝试从头开始创建 COM InprocServer,并通过显示一个简单的

MessageBox
来使示例 ContextMenuHandler for Explorer 工作。问题是,在查询
IShellExtInit
后(我实际上正确接收了所选的文件名,没有问题),资源管理器永远不会查询
IContextMenu
界面!我知道这一点,因为我在代码中使用了充足的调试
MessageBox
,以查看发生了什么。

我确信

IContextMenu
永远不会被查询。相反,资源管理器会在
IShellExtInit
之后查询这 2 个随机 GUID,每个查询 2 次:

{79EAC9EE-BAF9-11CE-8C82-0AA04BA9B}
{FC4801A3-2BA9-11CF-A229-0AA03D7352}
{79EAC9EE-BAF9-11CE-8C82-0AA04BA9B}
{FC4801A3-2BA9-11CF-A229-0AA03D7352}

我在任何地方都找不到这个 GUID。不在互联网上,不在注册表中,当然也不在

ShlGuid.h
中。这里的问题可能是什么原因造成的?

完整实现代码:

#include "exports.h"

#include <shellapi.h>
#include <shobjidl.h>
#include <objbase.h>
#include <objidl.h>
#include <shlguid.h>
//#include <winnls.h>

#pragma warning( disable : 4100 )



wchar_t dbbuf[1024];




// {9E5FC5BF-6040-4F4E-B2A8-B1E9B9927651}
static const GUID CLSID_DragAndDropHlink = { 0x9E5FC5BF, 0x6040, 0x4F4E, { 0xB2, 0xA8, 0xB1, 0xE9, 0xB9, 0x92, 0x76, 0x51 }};

class DragAndDropHlink :
    public IShellExtInit,
    public IContextMenu
{
public:
    DragAndDropHlink();
    ~DragAndDropHlink();

    // IUknown Implementation
    HRESULT QueryInterface(REFIID riid, void **ppo);
    ULONG AddRef();
    ULONG Release();

    // IShellExtInit Implementation
    HRESULT Initialize(LPCITEMIDLIST pfid, IDataObject *pdo, HKEY hk);

    // IContextMenu Implementation
    HRESULT GetCommandString(UINT_PTR cmd_id, UINT type, UINT *reserved, CHAR *name, UINT buff_s);
    HRESULT InvokeCommand(CMINVOKECOMMANDINFO *pici);
    HRESULT QueryContextMenu(HMENU menu, UINT menu_idx, UINT fst_cmd_id, UINT lst_cmd_id, UINT flags);

public:
    static ui64 objs_alive;

private:
    ULONG ref_c;
    wchar_t file_n[MAX_PATH];
};

ui64 DragAndDropHlink::objs_alive = 0;

DragAndDropHlink::DragAndDropHlink()
{
    ref_c = 1;
    ++objs_alive;
}

DragAndDropHlink::~DragAndDropHlink()
{
    --objs_alive;
}

HRESULT DragAndDropHlink::QueryInterface(REFIID riid, void **ppo)
{
    if(ppo == NULL)
    {
        return E_INVALIDARG;
    }

    *ppo = NULL;

    if(riid == IID_IUnknown     ||
        riid == IID_IShellExtInit   ||
        riid == IID_IContextMenu)
    {
        *ppo = (void *)this;
        AddRef();

        MessageBox(NULL, L"DragAndDropHlink", L"QueryInterfaceOK!!!", MB_OK);

        return S_OK;
    }



    wsprintf(dbbuf, L"{%X-%X-%X-%X%X-%X%X%X%X%X%X}", riid.Data1, riid.Data2, riid.Data3, riid.Data4[0],
        riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);

    ////////////////////////////////////// UNICODE
    //wchar_t buf[100];
    //wsprintf(buf, L"%d", id);

    SIZE_T l = wcslen(dbbuf) + 1;
    HGLOBAL hmem = GlobalAlloc(GMEM_MOVEABLE, l * sizeof(wchar_t));
    memcpy(GlobalLock(hmem), dbbuf, l * sizeof(wchar_t));
    GlobalUnlock(hmem);
    OpenClipboard(NULL);
    EmptyClipboard(); // Using this with OpenClipboard(NULL) should not work, but it does! Magick?
    SetClipboardData(CF_UNICODETEXT, hmem);
    CloseClipboard();

    //VirtualFree(big_buf, 0, MEM_RELEASE);
    /////////////////////////////////////////////////////////////////////////////////////////////////////////






    MessageBox(NULL, dbbuf, L"QueryInterfaceFAIL!!!", MB_OK);

    return E_NOINTERFACE;
}

inline ULONG DragAndDropHlink::AddRef()
{
    InterlockedIncrement(&ref_c);


    wsprintf(dbbuf, L"ref_c[%ld]", ref_c);
    MessageBox(NULL, dbbuf, L"DragAndDropHlink AddRef!!!", MB_OK);


    return ref_c;
}

inline ULONG DragAndDropHlink::Release()
{
    ULONG new_ref_c = InterlockedDecrement(&ref_c);

    wsprintf(dbbuf, L"ref_c[%ld]", ref_c);
    MessageBox(NULL, dbbuf, L"DragAndDropHlink Release!!!", MB_OK);

    if(ref_c == 0)
    {
        delete this;
    }

    return new_ref_c;
}

HRESULT DragAndDropHlink::Initialize(LPCITEMIDLIST pfid, IDataObject *pdo, HKEY hk)
{
    if(pdo == NULL)
    {
        return E_INVALIDARG;
    }

    MessageBox(NULL, L"DragAndDropHlink", L"Initialize!!!", MB_OK);

    STGMEDIUM med;
    FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    UINT cnt = 0;

    if(pdo->GetData(&fe, &med) == S_OK)
    {
        cnt = DragQueryFile((HDROP)med.hGlobal, (UINT)-1, NULL, 0);
        if(cnt > 0)
        {
            DragQueryFile((HDROP)med.hGlobal, 0, file_n, MAX_PATH);
        }

        ReleaseStgMedium(&med);
    }

    MessageBox(NULL, file_n, L"Initialize END!!!", MB_OK);

    //RegOpenKeyEx(hk, nullptr, 0, MAXIMUM_ALLOWED, &some_hkey_var);

    return S_OK;
}

HRESULT DragAndDropHlink::GetCommandString(UINT_PTR cmd_id, UINT type, UINT *reserved, CHAR *name, UINT buff_s)
{
    if(cmd_id != 0)
    {
        return E_INVALIDARG;
    }

    MessageBox(NULL, L"DragAndDropHlink", L"GetCommandString!!!", MB_OK);
    
    // Ignore the help string pleads
    return E_INVALIDARG;
}

HRESULT DragAndDropHlink::InvokeCommand(CMINVOKECOMMANDINFO *pici)
{
    MessageBox(NULL, L"DragAndDropHlink", L"InvokeCommandBEG!!!", MB_OK);
    
    ui64 verb = (ui64)pici->lpVerb;
    if((verb & 0xFFFFFFFF00000000) != 0)
    {
        return E_INVALIDARG;
    }

    MessageBox(NULL, L"DragAndDropHlink", L"InvokeCommand 173 line!!!", MB_OK);

    switch(verb)
    {
    case 0:
        MessageBox(pici->hwnd, file_n, L"BOOOO!!!", MB_OK);
        return S_OK;
    default:
        return E_INVALIDARG;
    }
}

HRESULT DragAndDropHlink::QueryContextMenu(HMENU menu, UINT menu_idx, UINT fst_cmd_id, UINT lst_cmd_id, UINT flags)
{
    if(flags & CMF_DEFAULTONLY)
    {
        return 0;
    }

    MessageBox(NULL, L"NONSENSE!", L"QueryContextMenu!!!", MB_OK);

    InsertMenu(menu, menu_idx, MF_BYPOSITION, fst_cmd_id, L"MSGBOX SHOvER!");
    return 1;
}




class ComObjectFactory : public IClassFactory
{
public:
    ComObjectFactory();
    ~ComObjectFactory();

    // IUknown Implementation
    HRESULT QueryInterface(REFIID riid, void **ppo);
    ULONG AddRef();
    ULONG Release();

    // IClassFactory Implementation
    HRESULT CreateInstance(IUnknown *paggr, REFIID riid, void **ppo);
    HRESULT LockServer(BOOL lock);

public:
    static ui64 s_locks; // Server Locks count

private:
    ULONG ref_c;
};

ui64 ComObjectFactory::s_locks = 0;

ComObjectFactory::ComObjectFactory()
{
    ref_c = 1;
}

ComObjectFactory::~ComObjectFactory()
{
    // Do nothing
}

HRESULT ComObjectFactory::QueryInterface(REFIID riid, void **ppo)
{
    if(ppo == NULL)
    {
        return E_INVALIDARG;
    }

    MessageBox(NULL, L"NONSENSE!", L"ComObjectFactoryQueryInterface!!!", MB_OK);

    *ppo = NULL;

    if(riid == IID_IUnknown || riid == IID_IClassFactory)
    {
        *ppo = (void *)this;
        AddRef();
        return S_OK;
    }

    return E_NOINTERFACE;
}

inline ULONG ComObjectFactory::AddRef()
{
    InterlockedIncrement(&ref_c);
    MessageBox(NULL, L"NONSENSE!", L"ComObjectFactoryAddRef!!!", MB_OK);
    return ref_c;
}

inline ULONG ComObjectFactory::Release()
{
    ULONG new_ref_c = InterlockedDecrement(&ref_c);

    wsprintf(dbbuf, L"ref_c[%ld]", ref_c);
    MessageBox(NULL, dbbuf, L"ComObjectFactoryRelease!!!", MB_OK);
    if(ref_c == 0)
    {
        delete this;
    }

    return new_ref_c;
}

HRESULT ComObjectFactory::CreateInstance(IUnknown *paggr, REFIID riid, void **ppo)
{
    MessageBox(NULL, L"before CLASS_E_NOAGGREGATION!", L"CreateInstance!!!", MB_OK);
    
    if(paggr != NULL) // Ignore aggregates
    {
        return CLASS_E_NOAGGREGATION;
    }

    MessageBox(NULL, L"NONSENSE!", L"ComObjectFactoryCreateInstance!!!", MB_OK);

    DragAndDropHlink *dndhl = new DragAndDropHlink();
    if(dndhl == NULL)
    {
        return E_OUTOFMEMORY;
    }

    HRESULT res = dndhl->QueryInterface(riid, ppo);
    dndhl->Release();

    return res;
}

HRESULT ComObjectFactory::LockServer(BOOL lock)
{
    if(lock)
    {
        ++s_locks;
    }
    else
    {
        --s_locks;
    }

    MessageBox(NULL, L"NONSENSE!", L"ComObjectFactoryLockServer!!!", MB_OK);

    CoLockObjectExternal(this, lock, FALSE); // May be wrong =\

    return S_OK;
}




BOOL APIENTRY DllMain(
    _In_    HMODULE hm,         // "Handle" to "Module" in fact its base adress of DLL
    _In_    DWORD reason,       // Reason for calling this function by the OS
    _In_    LPVOID reserved)    // Dynamic/Statc link flag or FreeLibrary/Process term.
{
    switch(reason)
    {
    case DLL_PROCESS_ATTACH:
        //MessageBox(NULL, L"NONSENSE!", L"DLL_PROCESS_ATTACH!!!", MB_OK);
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    default:
        break;
    }
    return TRUE;
}

HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppo)
{
    wsprintf(dbbuf, L"riid[%ld]", riid);
    MessageBox(NULL, dbbuf, L"DllGetClassObject!!!", MB_OK);
    
    
    if(rclsid != CLSID_DragAndDropHlink)
    {
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    ComObjectFactory *f = new ComObjectFactory();
    if(f == NULL)
    {
        return E_OUTOFMEMORY;
    }

    HRESULT res = f->QueryInterface(riid, ppo);
    f->Release();

    wsprintf(dbbuf, L"res[%ld] ppo[%lX]", res, ppo);
    MessageBox(NULL, dbbuf, L"f->QueryInterface!!!", MB_OK);

    return res;
}

HRESULT DllCanUnloadNow()
{
    
    wsprintf(dbbuf, L"objs_alive[%ld]", DragAndDropHlink::objs_alive);
    MessageBox(NULL, dbbuf, L"DllCanUnloadNow!!!", MB_OK);
    
    return DragAndDropHlink::objs_alive == 0 ? S_OK : S_FALSE;
}

更新0:我刚刚设法在注册表中找到了神秘的GUID。

{79EAC9EE-BAF9-11CE-8C82-0AA04BA9B}
IInternetSecurityManager

{FC4801A3-2BA9-11CF-A229-0AA03D7352}
IObjectWithSite

但这根本没有任何意义。为什么文件管理器在插件中需要这个接口?

更新1:我检查了我的类实际查询了哪些接口,实际上,Explorer确实连续查询了

IContextMenu
接口2次,但是,奇怪的是,before调用
IShellExtInit
,这是一种反逻辑的。尽管如此,它永远不会调用
IContextMenu
中定义的实际方法,因此永远不会添加菜单项......这种情况变得越来越梦幻......

哦,我还“实现”了

IInternetSecurityManager
IObjectWithSite
,只需返回
E_INVALIDARG
并显示
MessageBox
,但资源管理器实际上从未从这个接口调用任何方法,所以它似乎不是
IContextMenu
问题。而且,在得到
IObjectWithSite
后,Explorer 再也没有要求过
IInternetSecurityManager

windows com explorer shell-extensions
© www.soinside.com 2019 - 2024. All rights reserved.