// addin.hpp
// (c)
// 1 IInitDone.
// COM .
#pragma once
#pragma pack(push, 8)
#include <comdef.h>
struct __declspec(uuid("ab634001-f13d-11d0-a459-004095e1daea"))
IInitDone : IUnknown
{
STDMETHOD(Init)(IDispatch *pConnection) = 0;
STDMETHOD(Done)() = 0;
STDMETHOD(GetInfo)(SAFEARRAY **pInfo) = 0;
};
struct __declspec(uuid("ab634002-f13d-11d0-a459-004095e1daea"))
IPropertyProfile : IPropertyBag
{
STDMETHOD(RegisterProfileAs)(BSTR bstrProfileName) = 0;
};
struct __declspec(uuid("ab634004-f13d-11d0-a459-004095e1daea"))
IAsyncEvent : IUnknown
{
STDMETHOD(SetEventBufferDepth)(long lDepth) = 0;
STDMETHOD(GetEventBufferDepth)(long *plDepth) = 0;
STDMETHOD(ExternalEvent)(BSTR bstrSource, BSTR bstrMessage, BSTR bstrData) = 0;
STDMETHOD(CleanBuffer)() = 0;
};
struct __declspec(uuid("ab634003-f13d-11d0-a459-004095e1daea"))
ILanguageExtender : IUnknown
{
STDMETHOD(RegisterExtensionAs)(BSTR *bstrExtensionName) = 0;
STDMETHOD(GetNProps)(long *plProps) = 0;
STDMETHOD(FindProp)(BSTR bstrPropName, long *plPropNum) = 0;
STDMETHOD(GetPropName)(long lPropNum, long lPropAlias, BSTR *pbstrPropName) = 0;
STDMETHOD(GetPropVal)(long lPropNum, VARIANT *pvarPropVal) = 0;
STDMETHOD(SetPropVal)(long lPropNum, VARIANT *varPropVal) = 0;
STDMETHOD(IsPropReadable)(long lPropNum, long *pboolPropRead) = 0;
STDMETHOD(IsPropWritable)(long lPropNum, long *pboolPropWrite) = 0;
STDMETHOD(GetNMethods)(long *plMethods ) = 0;
STDMETHOD(FindMethod)(BSTR bstrMethodName, long *plMethodNum) = 0;
STDMETHOD(GetMethodName)(long lMethodNum, long lMethodAlias, BSTR *pbstrMethodName) = 0;
STDMETHOD(GetNParams)(long lMethodNum, long *plParams) = 0;
STDMETHOD(GetParamDefValue)(long lMethodNum, long lParamNum, VARIANT *pvarParamDefValue) = 0;
STDMETHOD(HasRetVal)(long lMethodNum, long *pboolRetValue) = 0;
STDMETHOD(CallAsProc)(long lMethodNum, SAFEARRAY **paParams) = 0;
STDMETHOD(CallAsFunc)(long lMethodNum, VARIANT *pvarRetValue, SAFEARRAY **paParams) = 0;
};
struct __declspec(uuid("ab634005-f13d-11d0-a459-004095e1daea"))
IStatusLine : IUnknown
{
STDMETHOD(SetStatusLine)(BSTR bstrStatusLine) = 0;
STDMETHOD(ResetStatusLine)() = 0;
};
struct __declspec(uuid("efe19ea0-09e4-11d2-a601-008048da00de"))
IExtWndsSupport : IUnknown
{
STDMETHOD(GetAppMainFrame)(wireHWND *hwnd) = 0;
STDMETHOD(GetAppMDIFrame)(wireHWND *hwnd) = 0;
STDMETHOD(CreateAddInWindow)(
BSTR bstrProgID,
BSTR bstrWindowName,
long dwStyles,
long dwExStyles,
struct tagRECT *rctl,
long Flags,
wireHWND *pHwnd,
IDispatch **pDisp) = 0;
};
_COM_SMARTPTR_TYPEDEF(IInitDone, __uuidof(IInitDone));
_COM_SMARTPTR_TYPEDEF(IPropertyProfile, __uuidof(IPropertyProfile));
_COM_SMARTPTR_TYPEDEF(IAsyncEvent, __uuidof(IAsyncEvent));
_COM_SMARTPTR_TYPEDEF(ILanguageExtender, __uuidof(ILanguageExtender));
_COM_SMARTPTR_TYPEDEF(IStatusLine, __uuidof(IStatusLine));
_COM_SMARTPTR_TYPEDEF(IExtWndsSupport, __uuidof(IExtWndsSupport));
extern "C" const GUID __declspec(selectany) IID_IInitDone =
{0xab634001,0xf13d,0x11d0,{0xa4,0x59,0x00,0x40,0x95,0xe1,0xda,0xea}};
extern "C" const GUID __declspec(selectany) IID_IPropertyProfile =
{0xab634002,0xf13d,0x11d0,{0xa4,0x59,0x00,0x40,0x95,0xe1,0xda,0xea}};
extern "C" const GUID __declspec(selectany) IID_IAsyncEvent =
{0xab634004,0xf13d,0x11d0,{0xa4,0x59,0x00,0x40,0x95,0xe1,0xda,0xea}};
extern "C" const GUID __declspec(selectany) IID_ILanguageExtender =
{0xab634003,0xf13d,0x11d0,{0xa4,0x59,0x00,0x40,0x95,0xe1,0xda,0xea}};
extern "C" const GUID __declspec(selectany) IID_IStatusLine =
{0xab634005,0xf13d,0x11d0,{0xa4,0x59,0x00,0x40,0x95,0xe1,0xda,0xea}};
extern "C" const GUID __declspec(selectany) IID_IExtWndsSupport =
{0xefe19ea0,0x09e4,0x11d2,{0xa6,0x01,0x00,0x80,0x48,0xda,0x00,0xde}};
extern "C" const GUID __declspec(selectany) IID_IPropertyLink =
{0x52512a61,0x2a9d,0x11d1,{0xa4,0xd6,0x00,0x40,0x95,0xe1,0xda,0xea}};
#pragma pack(pop)
namespace addin{
//
namespace impl_trap{
//
// strFunc, strExporter .
// : . , ,
// hDll strFunc strExporter
static inline DWORD* GetThunkAddres(HINSTANCE hDll, LPCSTR strExporter, LPCSTR strFunc)
{
BYTE *pimage = reinterpret_cast<BYTE*>(hDll);
PIMAGE_OPTIONAL_HEADER ioh=reinterpret_cast<PIMAGE_OPTIONAL_HEADER>(pimage +
reinterpret_cast<PIMAGE_DOS_HEADER>(hDll)->e_lfanew + 4 + sizeof(IMAGE_FILE_HEADER));
PIMAGE_IMPORT_DESCRIPTOR iid=reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(pimage +
(ioh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
//
while(iid->Name) // 0
{
if(_strcmpi(reinterpret_cast<char*>(pimage + iid->Name), strExporter) ==0 )
break;
iid++;
}
PIMAGE_THUNK_DATA isd = reinterpret_cast<PIMAGE_THUNK_DATA>(pimage + iid->OriginalFirstThunk);
DWORD* pReal=reinterpret_cast<DWORD*>(pimage + iid->FirstThunk);
for(int i=0;;isd++, i++)
{
LPCSTR name=(LPCSTR)(pimage + (DWORD)((PIMAGE_IMPORT_BY_NAME)isd->u1.AddressOfData)->Name);
if(!_stricmp(name, strFunc))
return pReal+i;
}
}
static inline DWORD* GetThunkAddres(LPCSTR strImporter, LPCSTR strExporter, LPCSTR strFunc)
{
return GetThunkAddres(GetModuleHandle(strImporter), strExporter, strFunc);
}
struct trap_load_vk
{
static trap_load_vk*& GetTrap()
{
static trap_load_vk* pTrap;
return pTrap;
}
const IInitDone* pAddin;
const CLSID& pClsID;
DWORD dwOldCLSIDFromProgID;
DWORD* pOldCLSIDFromProgID;
DWORD dwOldCoCreateInstance;
DWORD* pOldCoCreateInstance;
static HRESULT STDAPICALLTYPE myCLSIDFromProgID(LPCOLESTR lpszProgID, LPCLSID pclsid)
{
*pclsid=GetTrap()->pClsID;
return S_OK;
}
static HRESULT STDAPICALLTYPE myCoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
DWORD dwClsContext, REFIID riid, LPVOID *ppv)
{
trap_load_vk* pTrap=GetTrap();
*ppv=const_cast<IInitDone*>(pTrap->pAddin);
delete pTrap;
return S_OK;
}
trap_load_vk(const IInitDone* pA, const CLSID& pCls):
pAddin(pA), pClsID(pCls), pOldCLSIDFromProgID(NULL), pOldCoCreateInstance(NULL)
{
GetTrap()=this;
HINSTANCE hSeven=GetModuleHandle("seven.dll");
pOldCLSIDFromProgID =GetThunkAddres(hSeven, "ole32.dll", "CLSIDFromProgID");
dwOldCLSIDFromProgID=*pOldCLSIDFromProgID;
pOldCoCreateInstance=GetThunkAddres(hSeven, "ole32.dll", "CoCreateInstance");
dwOldCoCreateInstance=*pOldCoCreateInstance;
//
DWORD op;
VirtualProtect(pOldCLSIDFromProgID, 4, PAGE_EXECUTE_READWRITE, &op);
VirtualProtect(pOldCoCreateInstance, 4, PAGE_EXECUTE_READWRITE, &op);
*pOldCLSIDFromProgID=reinterpret_cast<DWORD>(&myCLSIDFromProgID);
*pOldCoCreateInstance=reinterpret_cast<DWORD>(&myCoCreateInstance);
}
~trap_load_vk()
{
*pOldCoCreateInstance=dwOldCoCreateInstance;
*pOldCLSIDFromProgID=dwOldCLSIDFromProgID;
}
};
} // namespace impl_trap
/*
.
-
. 1,
COM .
GetAddin();
:
, :
BOOL InitAddin(IDispatch* pConnection);
void DoneAddin();
CLSID, __declspec(uuid(""))
COneAddinImpl<>
DllMain ,
OnProcessAttach, OnProcessDetach:
:
class _declspec(uuid("00cd947e-1f68-4ba6-a69f-990a8affd815")) CAddin_;
class CAddin_
{
protected:
BOOL InitAddin(IDispatch* pConn);
void DoneAddin();
public:
...
};
typedef addin::COneAddinImpl<CAddin_> CAddin;
extern "C"
int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if(dwReason == DLL_PROCESS_ATTACH)
CAddin::OnProcessAttach();
else if(dwReason == DLL_PROCESS_DETACH)
CAddin::OnProcessDetach();
return 1; // ok
}
:
class CAddin
{
protected:
BOOL InitAddin(IDispatch* pConn);
void DoneAddin();
public:
CAddin& GetAddin(){return addin::COneAddinImpl<CAddin>::GetAddin();}
...
};
class _declspec(uuid("00cd947e-1f68-4ba6-a69f-990a8affd815")) CAddin;
....
extern "C"
int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if(dwReason == DLL_PROCESS_ATTACH)
addin::COneAddinImpl<CAddin>::OnProcessAttach();
else if(dwReason == DLL_PROCESS_DETACH)
addin::COneAddinImpl<CAddin>::OnProcessDetach();
return 1; // ok
}
,
.
*/
template<typename T>
class COneAddinImpl : public T, public IInitDone
{
// ,
COneAddinImpl(){new impl_trap::trap_load_vk(this, __uuidof(T));}
protected:
// IUnknown
STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject)
{
if(riid==IID_IInitDone)
*ppvObject=static_cast<IInitDone*>(this);
else if(riid==IID_IUnknown)
*ppvObject=static_cast<IUnknown*>(this);
else
return E_NOINTERFACE;
return S_OK;
}
STDMETHOD_(ULONG, AddRef)(){return 1;}
STDMETHOD_(ULONG, Release)(){return 1;}
// IInitDone
STDMETHOD(Init)(IDispatch *pConnection)
{
return T::InitAddin(pConnection) ? S_OK : E_FAIL;
}
STDMETHOD(Done)()
{
T::DoneAddin();
return S_OK;
}
STDMETHOD(GetInfo)(SAFEARRAY **pInfo)
{
long lInd = 0;
VARIANT varVersion;
V_VT(&varVersion) = VT_I4;
V_I4(&varVersion) = 2000;
SafeArrayPutElement(*pInfo,&lInd,&varVersion);
return S_OK;
}
static COneAddinImpl<T>*& getptr(){static COneAddinImpl<T>* ptr;return ptr;}
public:
static void OnProcessAttach(){getptr()=new COneAddinImpl<T>;}
static void OnProcessDetach(){delete getptr();}
//
static COneAddinImpl<T>& GetAddin(){return *getptr();}
};
}// namespace addin