How to create a IconHandler used by the shell in c++?

别说谁变了你拦得住时间么 提交于 2019-12-25 04:14:40

问题


I tried to code an icon handler in c++ but i have some issues to do this. I followed the turoriel from codeproject

The difference with this tutorial is i wanna code my dll with an ATL project from the wizard of visual studio (2013). So i create a new ATL project and i had a COM +1 class to this project (this the code of the header).

The problem is it seams that my dll is attach but is detach right after.

I'll put some code and more explication bellow :

extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        _AtlModule.InitLibId();
        //_AtlModule.RegisterAppId();
    }

    return _AtlModule.DllMain(dwReason, lpReserved);;
}

This is my entry point of my dll. I did a lot of try and test on this entry point. I tried to write some log in function of the dwReason and this function is launch only when i compile. One time with the attribute DLL_PROCESS_ATTACH and an other time with the attribute DLL_PROCESS_DETACH. After that nothing seams to work even when i set my registry to call this dll in the IconHandler of my file.

I'll put my dllmain.h, my handler.h, my idl file and my rgs file. If you need more code to help me i'll put them later.

dllmain.h

class CQIIconDllModule : public ATL::CAtlDllModuleT< CQIIconDllModule >
{
public :
    DECLARE_LIBID(LIBID_QIIconDllLib)
    DECLARE_REGISTRY_APPID_RESOURCEID(IDR_QIHANDLER, "{7FFCD43D-9EB3-4F76-940C-98C333FB8A99}")
};

extern class CQIIconDllModule _AtlModule;

IconHandler.h

// QIHandler.h : Declaration of the CQIHandler

#pragma once
#include "resource.h"       // main symbols
#include <ShlObj.h>


#include "QIIconDll_i.h"



#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

using namespace ATL;


// CQIHandler

class ATL_NO_VTABLE CQIHandler :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CQIHandler, &CLSID_QIHandler>,
    public IQIHandler,
    public IPersistFile,
    public IExtractIcon
{
public:
    CQIHandler()
    {
    }

DECLARE_REGISTRY_RESOURCEID(IDR_QIHANDLER)

DECLARE_NOT_AGGREGATABLE(CQIHandler)

BEGIN_COM_MAP(CQIHandler)
    COM_INTERFACE_ENTRY(IQIHandler)
    COM_INTERFACE_ENTRY(IPersistFile)
    COM_INTERFACE_ENTRY(IExtractIcon)
END_COM_MAP()



    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }

public:
     // IPersistFile
    STDMETHODIMP GetClassID( CLSID* ) { return E_NOTIMPL; }
    STDMETHODIMP IsDirty() { return E_NOTIMPL; }
    STDMETHODIMP Save( LPCOLESTR, BOOL ) { return E_NOTIMPL; }
    STDMETHODIMP SaveCompleted( LPCOLESTR ) { return E_NOTIMPL; }
    STDMETHODIMP GetCurFile( LPOLESTR* ) { return E_NOTIMPL; }

    STDMETHODIMP Load( LPCOLESTR wszFile, DWORD )
        { 
        USES_CONVERSION;
        lstrcpyn ( m_szFilename, W2CT(wszFile), MAX_PATH );
        return S_OK;
        }

    // IExtractIcon
    STDMETHODIMP GetIconLocation( UINT uFlags, LPTSTR szIconFile, UINT cchMax,
                                  int* piIndex, UINT* pwFlags );
    STDMETHODIMP Extract( LPCTSTR pszFile, UINT nIconIndex, HICON* phiconLarge,
                          HICON* phiconSmall, UINT nIconSize );

protected:
    TCHAR     m_szFilename[MAX_PATH];   // Full path to the file in question.


};

OBJECT_ENTRY_AUTO(__uuidof(QIHandler), CQIHandler)

my idl file

// QIIconDll.idl : IDL source for QIIconDll
//

// This file will be processed by the MIDL tool to
// produce the type library (QIIconDll.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";

[
    object,
    uuid(a817e7a2-43fa-11d0-9e44-00aa00b6770a),
    dual,   
    pointer_default(unique)
]
interface IComponentRegistrar : IDispatch
{
    [id(1)] HRESULT Attach([in] BSTR bstrPath);
    [id(2)] HRESULT RegisterAll();
    [id(3)] HRESULT UnregisterAll();
    [id(4)] HRESULT GetComponents([out] SAFEARRAY(BSTR)* pbstrCLSIDs, [out] SAFEARRAY(BSTR)* pbstrDescriptions);
    [id(5)] HRESULT RegisterComponent([in] BSTR bstrCLSID);
    [id(6)] HRESULT UnregisterComponent([in] BSTR bstrCLSID);
};

[
    object,
    uuid(1A80BA8B-2932-4EB4-AA88-5216F92BBA33),
    pointer_default(unique)
]
interface IQIHandler : IUnknown{
};


[
    uuid(17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5),
    version(1.0),
    custom(a817e7a1-43fa-11d0-9e44-00aa00b6770a,"{D32D9690-E6A4-44D8-A949-5F39D35269F8}")
]
library QIIconDllLib
{
    importlib("stdole2.tlb");
    [
        uuid(D32D9690-E6A4-44D8-A949-5F39D35269F8)      
    ]
    coclass CompReg
    {
        [default] interface IComponentRegistrar;
    };
    [
        uuid(7FFCD43D-9EB3-4F76-940C-98C333FB8A99)      
    ]
    coclass QIHandler
    {
        [default] interface IQIHandler;
    };
};

rgs file :

HKCR
{
    NoRemove CLSID
    {
        ForceRemove {D32D9690-E6A4-44D8-A949-5F39D35269F8} = s 'CompReg Class'
        {
            InprocServer32 = s '%MODULE%'
            {
                val ThreadingModel = s 'Apartment'
            }
            TypeLib = s '{17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5}'
            Version = s '1.0'
        }
    }
}

rgs handler file :

HKCR
{
    NoRemove CLSID
    {
        ForceRemove {7FFCD43D-9EB3-4F76-940C-98C333FB8A99} = s 'QIHandler Class'
        {
            InprocServer32 = s '%MODULE%'
            {
                val ThreadingModel = s 'Apartment'
            }
            TypeLib = s '{17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5}'
            Version = s '1.0'
        }
    }


    NoRemove qifile
    {
        NoRemove DefaultIcon = s '%%1'
        NoRemove ShellEx
        {
            ForceRemove IconHandler = s '{7FFCD43D-9EB3-4F76-940C-98C333FB8A99}'
        }
    }
}

I hope i was clear in my explanation. If you need more information to response at my question just tell me i'll be fast with my answer. I'll thank you to take your time to help me.

Florian

EDIT :

See my test on my dllmain. cpp

    BOOL ret = false;
    FILE *file; 
    fopen_s(&file, "test.txt","a+"); /* apend file (add text to 
        a file or create a file if it does not exist.*/ 
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        fprintf(file,"%s","Initialize AtlModule\n"); /*writes*/ 
        _AtlModule.InitLibId();
        HRESULT hr = _AtlModule.RegisterAppId();
        if (SUCCEEDED(hr))
        {
            fprintf(file,"%s","Registrer app succeeded \n"); /*writes*/ 
            hr = _AtlModule.RegisterServer(TRUE, &CLSID_QIHandler);
            if (SUCCEEDED(hr))
            {
                fprintf(file,"%s","RegisterServer succeeded \n"); /*writes*/ 
                hr = _AtlModule.UpdateRegistryAppId(TRUE);
                if (SUCCEEDED(hr))
                {
                    fprintf(file,"%s","UpdateRegistryAppId succeeded \n"); /*writes*/ 
                    ret = true;
                }
            }
        }

    }
#ifdef _DEBUG
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        _AtlModule.UpdateRegistryAppId(FALSE);
        _AtlModule.Term();
    }//*/
#endif
    if (dwReason == DLL_PROCESS_DETACH && lpReserved != NULL)
    {
        ret = true;
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        fprintf(file,"%s","Execption ! \n"); /*writes*/ 
    }

    fclose(file); /*done!*/ 
    return ret;

The result in my test.txt :

Initialize AtlModule
Registrer app succeeded 
RegisterServer succeeded 
UpdateRegistryAppId succeeded 
Execption ! 

Sombody here have a idee ?


回答1:


I didn't found any solution to work my solution. So i write my handler in C# even if this is not the best way to do that because that call some native function.

I used the follow tutorial from code-project : NET-Shell-Extensions-Shell-Icon-Handlers

I hope this tutorial gonna help some people. If someone have the answer to my preview question i will be glad to know what i have to do.

Florian



来源:https://stackoverflow.com/questions/16952684/how-to-create-a-iconhandler-used-by-the-shell-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!