addin.hpp at tip Вы: nobody
Вход

File sqlite1c/_1Common/addin.hpp from the latest check-in


// 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