From 4e60ac4ca3a51ea2a06d96d273d049df7405714e Mon Sep 17 00:00:00 2001 From: cxl Date: Thu, 14 Jan 2021 13:03:01 +0000 Subject: [PATCH] Ole moved to archive git-svn-id: svn://ultimatepp.org/upp/trunk@15668 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- {examples => archive}/OleCalc/OleCalc.upp | 0 {examples => archive}/OleCalc/calc.cpp | 0 {examples => archive}/OleCalc/calc.def | 0 {examples => archive}/OleCalc/calc.idl | 0 {examples => archive}/OleCalc/calc.lay | 0 {examples => archive}/OleCalc/calc.rc | 0 {examples => archive}/OleCalc/calc.tlb | 0 {examples => archive}/OleCalc/calc_idl.cpp | 0 {examples => archive}/OleCalc/calc_idl.h | 0 {examples => archive}/OleCalc/calc_p.c | 0 {examples => archive}/OleCalc/dlldata.c | 0 {uppsrc => archive/uppsrc}/Ole/Copying | 0 {uppsrc => archive/uppsrc}/Ole/Ctrl/Ctrl.upp | 2 +- {uppsrc => archive/uppsrc}/Ole/Ctrl/OleCtrl.h | 1658 +++++------ .../uppsrc}/Ole/Ctrl/control.cpp | 2418 ++++++++--------- {uppsrc => archive/uppsrc}/Ole/Ctrl/ocx.def | 14 +- .../uppsrc}/Ole/Ctrl/selftest.cpp | 50 +- {uppsrc => archive/uppsrc}/Ole/Ctrl/util.cpp | 1482 +++++----- {uppsrc => archive/uppsrc}/Ole/Ole.h | 54 +- {uppsrc => archive/uppsrc}/Ole/Ole.upp | 0 .../uppsrc}/Ole/srcdoc.tpp/all.i | 6 +- .../uppsrc}/Ole/srcdoc.tpp/ocx_en-us.tpp | 0 {uppsrc => archive/uppsrc}/Ole/util.cpp | 910 +++---- {uppsrc => archive/uppsrc}/Ole/util.h | 654 ++--- 24 files changed, 3624 insertions(+), 3624 deletions(-) rename {examples => archive}/OleCalc/OleCalc.upp (100%) rename {examples => archive}/OleCalc/calc.cpp (100%) rename {examples => archive}/OleCalc/calc.def (100%) rename {examples => archive}/OleCalc/calc.idl (100%) rename {examples => archive}/OleCalc/calc.lay (100%) rename {examples => archive}/OleCalc/calc.rc (100%) rename {examples => archive}/OleCalc/calc.tlb (100%) rename {examples => archive}/OleCalc/calc_idl.cpp (100%) rename {examples => archive}/OleCalc/calc_idl.h (100%) rename {examples => archive}/OleCalc/calc_p.c (100%) rename {examples => archive}/OleCalc/dlldata.c (100%) rename {uppsrc => archive/uppsrc}/Ole/Copying (100%) rename {uppsrc => archive/uppsrc}/Ole/Ctrl/Ctrl.upp (99%) rename {uppsrc => archive/uppsrc}/Ole/Ctrl/OleCtrl.h (96%) rename {uppsrc => archive/uppsrc}/Ole/Ctrl/control.cpp (96%) rename {uppsrc => archive/uppsrc}/Ole/Ctrl/ocx.def (95%) rename {uppsrc => archive/uppsrc}/Ole/Ctrl/selftest.cpp (94%) rename {uppsrc => archive/uppsrc}/Ole/Ctrl/util.cpp (96%) rename {uppsrc => archive/uppsrc}/Ole/Ole.h (94%) rename {uppsrc => archive/uppsrc}/Ole/Ole.upp (100%) rename {uppsrc => archive/uppsrc}/Ole/srcdoc.tpp/all.i (94%) rename {uppsrc => archive/uppsrc}/Ole/srcdoc.tpp/ocx_en-us.tpp (100%) rename {uppsrc => archive/uppsrc}/Ole/util.cpp (95%) rename {uppsrc => archive/uppsrc}/Ole/util.h (97%) diff --git a/examples/OleCalc/OleCalc.upp b/archive/OleCalc/OleCalc.upp similarity index 100% rename from examples/OleCalc/OleCalc.upp rename to archive/OleCalc/OleCalc.upp diff --git a/examples/OleCalc/calc.cpp b/archive/OleCalc/calc.cpp similarity index 100% rename from examples/OleCalc/calc.cpp rename to archive/OleCalc/calc.cpp diff --git a/examples/OleCalc/calc.def b/archive/OleCalc/calc.def similarity index 100% rename from examples/OleCalc/calc.def rename to archive/OleCalc/calc.def diff --git a/examples/OleCalc/calc.idl b/archive/OleCalc/calc.idl similarity index 100% rename from examples/OleCalc/calc.idl rename to archive/OleCalc/calc.idl diff --git a/examples/OleCalc/calc.lay b/archive/OleCalc/calc.lay similarity index 100% rename from examples/OleCalc/calc.lay rename to archive/OleCalc/calc.lay diff --git a/examples/OleCalc/calc.rc b/archive/OleCalc/calc.rc similarity index 100% rename from examples/OleCalc/calc.rc rename to archive/OleCalc/calc.rc diff --git a/examples/OleCalc/calc.tlb b/archive/OleCalc/calc.tlb similarity index 100% rename from examples/OleCalc/calc.tlb rename to archive/OleCalc/calc.tlb diff --git a/examples/OleCalc/calc_idl.cpp b/archive/OleCalc/calc_idl.cpp similarity index 100% rename from examples/OleCalc/calc_idl.cpp rename to archive/OleCalc/calc_idl.cpp diff --git a/examples/OleCalc/calc_idl.h b/archive/OleCalc/calc_idl.h similarity index 100% rename from examples/OleCalc/calc_idl.h rename to archive/OleCalc/calc_idl.h diff --git a/examples/OleCalc/calc_p.c b/archive/OleCalc/calc_p.c similarity index 100% rename from examples/OleCalc/calc_p.c rename to archive/OleCalc/calc_p.c diff --git a/examples/OleCalc/dlldata.c b/archive/OleCalc/dlldata.c similarity index 100% rename from examples/OleCalc/dlldata.c rename to archive/OleCalc/dlldata.c diff --git a/uppsrc/Ole/Copying b/archive/uppsrc/Ole/Copying similarity index 100% rename from uppsrc/Ole/Copying rename to archive/uppsrc/Ole/Copying diff --git a/uppsrc/Ole/Ctrl/Ctrl.upp b/archive/uppsrc/Ole/Ctrl/Ctrl.upp similarity index 99% rename from uppsrc/Ole/Ctrl/Ctrl.upp rename to archive/uppsrc/Ole/Ctrl/Ctrl.upp index 59351f438..c9310a621 100644 --- a/uppsrc/Ole/Ctrl/Ctrl.upp +++ b/archive/uppsrc/Ole/Ctrl/Ctrl.upp @@ -11,7 +11,7 @@ file ocx.def; custom() "idl", - "midl /newtlb $(!/I) /h \"$(DIR)/$(TITLE)_idl.h\" /iid \"$(DIR)/$(TITLE" + "midl /newtlb $(!/I) /h \"$(DIR)/$(TITLE)_idl.h\" /iid \"$(DIR)/$(TITLE" ")_idl.cpp\" /tlb \"$(DIR)/$(TITLE).tlb\" \"$(PATH)\"\r\n", "$(DIR)/$(TITLE)_idl.h\r\n$(DIR)/$(TITLE).tlb\r\n"; diff --git a/uppsrc/Ole/Ctrl/OleCtrl.h b/archive/uppsrc/Ole/Ctrl/OleCtrl.h similarity index 96% rename from uppsrc/Ole/Ctrl/OleCtrl.h rename to archive/uppsrc/Ole/Ctrl/OleCtrl.h index dd5d069de..452d66319 100644 --- a/uppsrc/Ole/Ctrl/OleCtrl.h +++ b/archive/uppsrc/Ole/Ctrl/OleCtrl.h @@ -1,829 +1,829 @@ -#ifndef _Ole_Ctrl_OleCtrl_h_ -#define _Ole_Ctrl_OleCtrl_h_ - -#include -#include - -namespace Upp { - -#define OCXLOG RLOG // redefine to RLOG if you want logs in retail versions - -#ifdef _DEBUG -#define LOG_SYSOCXS 1 // 1 = log system calls (DllCanUnloadNow, DllGetClassObject) -#define LOG_METHODS 1 // 1 = log method calls -#define LOG_CREATES 1 // 1 = log instance creations & destructions -#define LOG_QUERIES 2 // 1 = log failed QueryInterface's -// // 2 = log all QueryInterface's -// // 3 = dump interface map whenever Query fails -#define LOG_PERSIST 1 // 1 = log saves / loads -#define LOG_RESULTS 2 // 1 = log error results -// // 2 = log all results -#define LOG_ADDREFS 1 // 1 = log AddRef's / Releases -#define LOG_INVOKES 1 // 1 = log IDispatch::Invoke -#else -#define LOG_SYSOCXS 1 -#define LOG_METHODS 0 -#define LOG_CREATES 0 -#define LOG_QUERIES 0 -#define LOG_PERSIST 0 -#define LOG_RESULTS 0 -#define LOG_ADDREFS 0 -#define LOG_INVOKES 0 -#endif - -#if LOG_SYSOCXS >= 1 -#define LOGSYSOCX(x) OCXLOG(x) -#else -#define LOGSYSOCX(x) -#endif - -#if LOG_METHODS >= 1 -#define LOGMETHOD(x) OCXLOG(x) -#else -#define LOGMETHOD(x) -#endif - -#if LOG_CREATES >= 1 -#define LOGCREATE(x) OCXLOG(x) -#else -#define LOGCREATE(x) -#endif - -#if LOG_QUERIES >= 1 -#define LOGQUERY(x) OCXLOG(x) -#else -#define LOGQUERY(x) -#endif - -#if LOG_PERSIST >= 1 -#define LOGPERSIST(x) OCXLOG(x) -#else -#define LOGPERSIST(x) -#endif - -#if LOG_RESULTS >= 2 -#define LOGRESULT(x) LogResult((x)) -#elif LOG_RESULTS >= 1 -#define LOGRESULT(x) LogError((x)) -#else -#define LOGRESULT(x) (x) -#endif - -#if LOG_INVOKES >= 1 -#define LOGINVOKE(x) OCXLOG(x) -#else -#define LOGINVOKE(x) -#endif - -typedef void (*InitProc)(); -InitProc& LateInitProc(); -InitProc& LateExitProc(); - -void DoLateInit(); -void DoLateExit(); - -#define OCX_APP_MAIN \ -void _DllMainAppInit(); \ -\ -static void _DllMainLateExit() \ -{ \ - RLOGBLOCK("_DllMainLateExit"); \ - Ctrl::ExitWin32(); \ -} \ -\ -static void _DllMainLateInit() \ -{ \ - RLOGBLOCK("_DllMainLateInit"); \ - RLOG("Ctrl::InitWin32"); \ - Ctrl::InitWin32(AppGetHandle()); \ - RLOG("AppInitEnvironment"); \ - AppInitEnvironment__(); \ - RLOG("DllMainAppInit"); \ - _DllMainAppInit(); \ - LateExitProc() = &_DllMainLateExit; \ -} \ -\ -BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpReserved) \ -{ \ - if(fdwReason == DLL_PROCESS_ATTACH) { \ - AppSetHandle(hinstDll); \ - } \ - RLOG("DllMain(" << FormatIntHex(hinstDll) << ", reason = " << (int)fdwReason << ")"); \ - if(fdwReason == DLL_PROCESS_ATTACH) { \ - LateInitProc() = &_DllMainLateInit; \ - } \ - else if(fdwReason == DLL_PROCESS_DETACH) { \ - DoLateExit(); \ - } \ - RLOG("//DllMain(" << FormatIntHex(hinstDll) << ", reason = " << (int)fdwReason << ")"); \ - return true; \ -} \ -\ -void _DllMainAppInit() - -/* -_variant_t ValueToVariant(const Value& v); -Value DispatchToValue(IDispatch *disp); -Value UnknownToValue(IUnknown *unk); -void ReturnVariant(VARIANT *var, const Value& v); -HRESULT CheckReturnString(BSTR *bstr, const String& s); -Color PackColor(long rgb); -long UnpackColor(Color c); -HRESULT CheckReturnColor(long *ptr, Color c); -*/ - -#define std_method HRESULT STDMETHODCALLTYPE -#define void_method void STDMETHODCALLTYPE - -class OcxTypeInfo; - -typedef VectorMap InterfaceMap; - -inline void AddInterfaceRaw(InterfaceMap& map, const Guid& guid, IUnknown *iface) -{ - map.Add(guid, iface); -} - -template -inline void AddInterface(InterfaceMap& map, const Guid& guid, T *iface) -{ - AddInterfaceRaw(map, guid, iface); -} - -#define PARENT_INTERFACE(clss, base) \ -template <> \ -inline void AddInterface(InterfaceMap& map, const Guid& guid, clss *iface) \ -{ \ - AddInterfaceRaw(map, guid, iface); \ - AddInterface(map, __uuidof(base), iface); \ -} - -PARENT_INTERFACE(IProvideClassInfo2, IProvideClassInfo) -PARENT_INTERFACE(IViewObject2, IViewObject) -PARENT_INTERFACE(IViewObjectEx, IViewObject2) -PARENT_INTERFACE(IOleInPlaceObject, IOleWindow) -PARENT_INTERFACE(IOleInPlaceObjectWindowless, IOleInPlaceObject) -PARENT_INTERFACE(IOleInPlaceActiveObject, IOleWindow) -PARENT_INTERFACE(IPersistStorage, IPersist) -PARENT_INTERFACE(IPersistStream, IPersist) -PARENT_INTERFACE(IPersistFile, IPersist) -PARENT_INTERFACE(IClassFactory2, IClassFactory) - -class OcxObject -{ - friend class OcxTypeInfo; - -public: - OcxObject(); - - template - void AddInterface(const Guid& guid, T *iface) { UPP::AddInterface(interface_map, guid, iface); } - template - void AddInterface(T *iface) { UPP::AddInterface(interface_map, __uuidof(T), iface); } - - IUnknown *OuterUnknown() { return outer_unknown ? outer_unknown : &inner_unknown; } - IUnknown *InnerUnknown() { return &inner_unknown; } - - HRESULT InternalQueryInterface(const GUID& iid, void **ppv); - HRESULT ExternalQueryInterface(const GUID& iid, void **ppv); - - static HRESULT RawGetTypeInfo(IRef& dispatch_info, unsigned tinfo, LCID lcid, ITypeInfo **ppinfo); - static HRESULT RawGetIDsOfNames(IRef& dispatch_info, REFIID riid, OLECHAR **names, unsigned cnames, LCID lcid, DISPID *dispid); - static HRESULT RawInvoke(IRef& dispatch_info, IDispatch *disp, DISPID dispid, word flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, unsigned *arg_err); - - static const char *GetObjectName() { return ""; } // programmatic object name (synthetic = .) - static const char *GetObjectHelp() { return ""; } // user-visible object name (synthetic = (CONTROL ? " Control " | " Object ") -// static GUID GetDispatchGUID() { return __uuidof(0); } // default ingoing dispatch interface - static GUID GetEventGUID() { return __uuidof(0); } // default outgoing dispatch interface - - enum - { - VERSION = 0, - CONTROL = 0, // override with 1 to make a control class - }; - - virtual int InternalAddRef() = 0; - virtual int InternalRelease() = 0; - - int ExternalAddRef(); - int ExternalRelease(); - -protected: - class OcxInnerUnknown : public IUnknown { - public: - OcxInnerUnknown() : owner(0) {} - ULONG STDMETHODCALLTYPE AddRef() { return owner->InternalAddRef(); } - ULONG STDMETHODCALLTYPE Release() { return owner->InternalRelease(); } - STDMETHOD(QueryInterface)(REFIID iid, void **ppv) { return owner->InternalQueryInterface(iid, ppv); } - - public: - OcxObject *owner; - }; - - OcxTypeInfo *ocx_info; - IUnknown *outer_unknown; - InterfaceMap interface_map; - OcxInnerUnknown inner_unknown; -}; - -template -class Interface : public I, virtual public OcxObject -{ -public: - Interface() { AddInterface(this); } -}; - -template -class DispatchInterface : public Interface -{ -public: - DispatchInterface() { AddInterface(__uuidof(I), this); AddInterface(this); } -// static GUID GetDispatchGUID() { return __uuidof(I); } - - // IDispatch - - STDMETHOD(GetTypeInfoCount)(unsigned *pctinfo); - STDMETHOD(GetTypeInfo)(unsigned tinfo, LCID lcid, ITypeInfo **ppinfo); - STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR **names, unsigned cnames, LCID lcid, DISPID *dispid); - STDMETHOD(Invoke)(DISPID dispid, REFIID riid, LCID lcid, word flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, unsigned *arg_err); - -protected: - void LoadTypeInfo() { ocx_info->GetDispatchTypeInfo(dispatch_info, __uuidof(I)); } - -protected: - IRef dispatch_info; -}; - -template -STDMETHODIMP DispatchInterface::GetTypeInfoCount(unsigned *pctinfo) -{ - if(!pctinfo) return E_POINTER; - *pctinfo = 1; - return S_OK; -} - -template -STDMETHODIMP DispatchInterface::GetTypeInfo(unsigned tinfo, LCID lcid, ITypeInfo **ppinfo) -{ - if(!ppinfo) return E_POINTER; - LoadTypeInfo(); - if(*ppinfo = ~dispatch_info) dispatch_info->AddRef(); - return S_OK; -} - -template -STDMETHODIMP DispatchInterface::GetIDsOfNames(REFIID riid, OLECHAR **names, unsigned cnames, LCID lcid, DISPID *dispid) -{ - LoadTypeInfo(); - return RawGetIDsOfNames(dispatch_info, riid, names, cnames, lcid, dispid); -} - -template -STDMETHODIMP DispatchInterface::Invoke(DISPID dispid, REFIID riid, LCID lcid, word flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, unsigned *arg_err) -{ - LoadTypeInfo(); - return RawInvoke(dispatch_info, static_cast(this), dispid, flags, params, result, excep, arg_err); -} - -class OcxProvideClassInfo : public Interface -{ -public: - // IProvideClassInfo - - STDMETHOD(GetClassInfo)(ITypeInfo **info); - - // IProvideClassInfo2 - - STDMETHOD(GetGUID)(dword guidkind, GUID *guid); -}; - -template -class OcxObjectWrapper : public T -{ -public: - OcxObjectWrapper() : refcount(0) {} - OcxObjectWrapper(OcxTypeInfo& _ocx_info) : refcount(0) { ocx_info = &_ocx_info; _ocx_info.object_count++; } - - static OcxObject *New() { return new OcxObjectWrapper(); } - static OcxObject *New(OcxTypeInfo& _ocx_info) { return new OcxObjectWrapper(_ocx_info); } - - virtual ULONG STDMETHODCALLTYPE AddRef() { return ExternalAddRef(); } - virtual ULONG STDMETHODCALLTYPE Release() { return ExternalRelease(); } - STDMETHOD(QueryInterface)(REFIID iid, void **ppv) { return ExternalQueryInterface(iid, ppv); } - - static String GetName(); - - virtual int InternalAddRef(); - virtual int InternalRelease(); - -private: - void Destroy(); - -private: - ULONG refcount; -}; - -template -int OcxObjectWrapper::InternalAddRef() -{ - ++refcount; -#if LOG_ADDREFS - RLOG(GetTypeName(typeid(*this)) << "::InternalAddRef(" << refcount << ")"); -#endif - return refcount; -} - -template -int OcxObjectWrapper::InternalRelease() -{ - int u = --refcount; -#if LOG_ADDREFS - RLOG(GetTypeName(typeid(*this)) << "::InternalRelease(" << refcount << ")"); -#endif - if(!u) - Destroy(); - return u; -} - -template -String OcxObjectWrapper::GetName() -{ - if(*T::GetObjectName()) - return T::GetObjectName(); - return GetTypeName(typeid(T)); -} - -template -void OcxObjectWrapper::Destroy() -{ - if(ocx_info) - { - ocx_info->object_count--; - LOGCREATE("\tdelete " << GetTypeName(typeid(T)) << ": " - << (int)ocx_info->object_count << " instances left in system"); - } - else - LOGCREATE("\tdelete " << GetTypeName(typeid(T))); - delete this; -} - -class OcxTypeInfo : public Interface -{ - friend class OcxTypeLib; - -public: - typedef OcxObject *(*New)(OcxTypeInfo& entry); - - OcxTypeInfo(const GUID& coclass_guid, /*const GUID& dispatch_guid,*/ const GUID& event_guid, - New new_fn, String name, const char* help = "", int ver = 0, - bool is_control = false); - - bool IsControl() const { return is_control; } - bool CanUnload() const; - - const Guid& GetCoClassGUID() const { return coclass_guid; } -// const Guid& GetDispatchGUID() const { return dispatch_guid; } - const Guid& GetEventGUID() const { return event_guid; } - - String GetName() const { return name; } - -// IRef GetDispatchTypeInfo(); - void GetDispatchTypeInfo(IRef& dest, Guid dispatch_iid); - IRef GetCoClassTypeInfo(); - - // IUnknown - - virtual int InternalAddRef() { return IncRef(); } - virtual int InternalRelease() { return DecRef(); } - virtual ULONG STDMETHODCALLTYPE AddRef() { return IncRef(); } - virtual ULONG STDMETHODCALLTYPE Release() { return DecRef(); } - STDMETHOD(QueryInterface)(REFIID iid, void **ppv) { return ExternalQueryInterface(iid, ppv); } - - // IClassFactory - - STDMETHOD(CreateInstance)(IUnknown *outer, REFIID iid, void **object); - STDMETHOD(LockServer)(BOOL lock); - - STDMETHOD(GetLicInfo)(/* [out] */ LICINFO *pLicInfo); - STDMETHOD(RequestLicKey)(/* [in] */ DWORD dwReserved, /* [out] */ BSTR *pBstrKey); - - STDMETHOD(CreateInstanceLic)( - /* [in] */ IUnknown *pUnkOuter, - /* [in] */ IUnknown *pUnkReserved, - /* [in] */ REFIID riid, - /* [in] */ BSTR bstrKey, - /* [iid_is][out] */ PVOID *ppvObj); - -public: - long object_count; // managed object count - IRef coclass_info; // coclass type info -// IRef dispatch_info; // ingoing dispatch interface type info - CriticalSection critical; // critical section used for initializations - -private: - int IncRef(); - int DecRef(); - -private: - Guid coclass_guid; // coclass GUID - Guid dispatch_guid; // GUID of default ingoing dispatch interface - Guid event_guid; // GUID of default outgoing dispatch interface - New new_fn; // constructor - String name; // programmatic object name - .. by default - const char *help; // user-visible object name - (" Control " | " Object ") by default - int ver; // 0 = use main library version - bool is_control; // false = generic object, true = insertable control - - long refcount; // AddRef/Release counter - Atomic lock_count; // LockServer lock count - -#ifndef _USRDLL - dword registration; // for CoRevokeClassObject -#endif -}; - -class OcxTypeLib -{ -public: - static OcxTypeLib& Get(); - - OcxTypeLib& Name(String name) { lib_name = name; return *this; } - String GetName() const { return lib_name; } - OcxTypeLib& DisplayName(String dn) { display_name = dn; return *this; } - String GetDisplayName() const { return display_name; } - String GetLibName() const; - OcxTypeLib& UsesLibrary(String name) { uses_libraries.GetAdd(name); return *this; } - - OcxTypeLib& Version(int _ver) { lib_ver = _ver; return *this; } - int GetVersion() const { return lib_ver; } - - HRESULT Register(); - HRESULT Unregister(); - HRESULT GetFactory(REFCLSID clsid, REFIID iid, void **ppv); - bool CanUnload() const; -#ifndef _USRDLL - HRESULT RegisterObjects(); // call CoRegisterClassObject for each object - void RevokeObjects(); // call CoRevokeClassObject -#endif - - void Add(OcxTypeInfo& entry) { objects.FindAdd(entry.coclass_guid, &entry); } - void AddInit(void (*fn)()) { ocx_init.Add(fn); } - - IRef GetTypeInfo(const Guid& guid); - - IRef& GetTypeLib(); - IRef& operator -> () { return GetTypeLib(); } - -public: - IRef typelib; - CriticalSection critical; - -private: - OcxTypeLib(); - -private: - VectorMap objects; - Vector ocx_init; - String lib_name; - String display_name; - int lib_ver; - VectorMap > uses_libraries; -}; - -struct OcxInit { OcxInit(void (*fn)()) { OcxTypeLib::Get().AddInit(fn); } }; -#define OCX_INIT(fn) static OcxInit MK__s = fn; - -#define OCX_OBJECT(type) \ - static OcxTypeInfo MK__s( \ - __uuidof(type), /* coclass GUID */ \ - /*type::GetDispatchGUID(),*/ /* default ingoing dispatch interface GUID */ \ - type::GetEventGUID(), /* default outgoing dispatch interface GUID */ \ - OcxObjectWrapper::New, /* constructor */ \ - OcxObjectWrapper::GetName(), /* name */ \ - type::GetObjectHelp(), /* help */ \ - type::VERSION, /* version */ \ - type::CONTROL); /* control object */ - -#define OCX_NEWOBJECT(type) \ - OCX_OBJECT(type) \ - static IRef COMBINE(OcxNew_, type)() { return new OcxObjectWrapper(MK__s); } - -#ifndef _USRDLL -bool ExeRegisterServer(); -bool ExeUnregisterServer(); -void ExeRunServer(); -#endif - -Size ToHiMetric(Size pixel_size); -Size FromHiMetric(Size himetric_size); -Rect GetWindow(HDC hdc); -Rect GetViewport(HDC hdc); - -LPOLESTR AllocString(String s); - -template -class SinkMap : public VectorMap -{ -public: - typedef VectorMap Base; - SinkMap() : next_sink_id(0) {} - dword Add(const T& object) { Base::Add(++next_sink_id, object); return next_sink_id; } - bool Remove(dword id) { int i = Find(id); return (i >= 0 ? (Base::Remove(i), true) : false); } - -private: - dword next_sink_id; -}; - -//template OleType; - -class OcxControl : public Ctrl, - public Interface, - public Interface, - public Interface, - public Interface, - public Interface, - public Interface, - public Interface, - public Interface, - public Interface, - public OcxProvideClassInfo -{ -public: - OcxControl(); - virtual ~OcxControl(); - - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); - bool Open(HWND parent); - virtual void Serialize(Stream& stream); - void SerializePos(Stream& stream); - - virtual bool IsOcxChild(); - - using Ctrl::GetRect; - using Ctrl::SetData; - using Ctrl::GetData; - - // IOleObject - - STDMETHOD(SetClientSite)(IOleClientSite *site); - STDMETHOD(GetClientSite)(IOleClientSite **res); - STDMETHOD(SetHostNames)(LPCOLESTR app_name, LPCOLESTR doc_name); - STDMETHOD(Close)(dword save_option); - STDMETHOD(SetMoniker)(dword which, IMoniker *moniker); - STDMETHOD(GetMoniker)(dword assign, dword which, IMoniker **moniker); - STDMETHOD(InitFromData)(IDataObject *data, BOOL creation, dword); - STDMETHOD(GetClipboardData)(dword, IDataObject **data); - STDMETHOD(DoVerb)(long verb, MSG *msg, IOleClientSite *active_site, long index, HWND hwnd, const RECT *rc); - STDMETHOD(EnumVerbs)(IEnumOLEVERB **verbs); - STDMETHOD(Update)(); - STDMETHOD(IsUpToDate)(); - STDMETHOD(GetUserClassID)(GUID *guid); - STDMETHOD(GetUserType)(dword form, LPOLESTR *type); - STDMETHOD(SetExtent)(dword aspect, SIZEL *size); - STDMETHOD(GetExtent)(dword aspect, SIZEL *size); - STDMETHOD(Advise)(IAdviseSink *sink, dword *connection); - STDMETHOD(Unadvise)(dword connection); - STDMETHOD(EnumAdvise)(IEnumSTATDATA **sink_enum); - STDMETHOD(GetMiscStatus)(dword aspect, dword *status); - STDMETHOD(SetColorScheme)(LOGPALETTE *logpal); - - // IPersistStorage - - STDMETHOD(GetClassID)(GUID *guid); - STDMETHOD(IsDirty)(); // IPersistStreamInit as well - STDMETHOD(InitNew)(IStorage *stg); - STDMETHOD(Load)(IStorage *stg); - STDMETHOD(Save)(IStorage *stg, BOOL same_as_load); - STDMETHOD(SaveCompleted)(IStorage *stg); - STDMETHOD(HandsOffStorage)(); - - // IPersistStreamInit - - STDMETHOD(Load)(IStream *stream); - STDMETHOD(Save)(IStream *stream, BOOL clear_dirty); - STDMETHOD(GetSizeMax)(ULARGE_INTEGER *size); - STDMETHOD(InitNew)(); - - // IDataObject - - STDMETHOD(GetData)(FORMATETC *format, STGMEDIUM *medium); - STDMETHOD(GetDataHere)(FORMATETC *format, STGMEDIUM *medium); - STDMETHOD(QueryGetData)(FORMATETC *format); - STDMETHOD(GetCanonicalFormatEtc)(FORMATETC *in, FORMATETC *out); - STDMETHOD(SetData)(FORMATETC *format, STGMEDIUM *medium, BOOL free); - STDMETHOD(EnumFormatEtc)(dword dir, IEnumFORMATETC **enumerator); - STDMETHOD(DAdvise)(FORMATETC *format, dword advf, IAdviseSink *sink, dword *connection); - STDMETHOD(DUnadvise)(dword connection); - STDMETHOD(EnumDAdvise)(IEnumSTATDATA **enumerator); - - // IViewObject - - STDMETHOD(Draw)(DWORD aspect, LONG index, void *aspectinfo, - DVTARGETDEVICE *device, HDC target, HDC draw, - const RECTL *bounds, const RECTL *wbounds, - BOOL (STDMETHODCALLTYPE *progress)(ULONG_PTR dwContinue), ULONG_PTR arg); - STDMETHOD(GetColorSet)(dword aspect, long index, void *aspectinfo, - DVTARGETDEVICE *device, HDC target, LOGPALETTE **palette); - STDMETHOD(Freeze)(dword aspect, long index, void *aspectinfo, - dword *freeze_key); - STDMETHOD(Unfreeze)(dword freeze_key); - STDMETHOD(SetAdvise)(dword aspect, dword advf, IAdviseSink *sink); - STDMETHOD(GetAdvise)(dword *aspect, dword *advf, IAdviseSink **sink); - - // IViewObject2 - - STDMETHOD(GetExtent)(dword aspect, long index, DVTARGETDEVICE *device, SIZEL *size); - - // IViewObjectEx - - STDMETHOD(GetRect)(dword aspect, RECTL *rc); - STDMETHOD(GetViewStatus)(dword *status); - STDMETHOD(QueryHitPoint)(dword aspect, const RECT *bounds, POINT pos, long close_hint, dword *result); - STDMETHOD(QueryHitRect)(dword aspect, const RECT *bounds, const RECT *, long close_hint, dword *result); - STDMETHOD(GetNaturalExtent)(dword aspect, long index, DVTARGETDEVICE *ptd, HDC tdc, DVEXTENTINFO *extinfo, SIZEL *psize); - - // IOleWindow - - STDMETHOD(GetWindow)(HWND *hwnd); - STDMETHOD(ContextSensitiveHelp)(BOOL enter_mode); - - // IOleInPlaceObject - - STDMETHOD(InPlaceDeactivate)(); - STDMETHOD(UIDeactivate)(); - STDMETHOD(SetObjectRects)(const RECT *pos, const RECT *clip); - STDMETHOD(ReactivateAndUndo)(); - - // IOleInPlaceActiveObject - - STDMETHOD(TranslateAccelerator)(MSG *msg); - STDMETHOD(OnFrameWindowActivate)(BOOL activate); - STDMETHOD(OnDocWindowActivate)(BOOL activate); - STDMETHOD(ResizeBorder)(const RECT *border, IOleInPlaceUIWindow *ui, BOOL frame); - STDMETHOD(EnableModeless)(BOOL enable); - - // IOleControl - - STDMETHOD(GetControlInfo)(CONTROLINFO *cinfo); - STDMETHOD(OnMnemonic)(MSG *msg); - STDMETHOD(OnAmbientPropertyChange)(DISPID dispid); - STDMETHOD(FreezeEvents)(BOOL freeze); - - // IPointerInactive - - STDMETHOD(GetActivationPolicy)(DWORD *pdwPolicy); - STDMETHOD(OnInactiveMouseMove)(LPCRECT pRectBounds, LONG x, LONG y, DWORD grfKeyState); - STDMETHOD(OnInactiveSetCursor)(LPCRECT pRectBounds, LONG x, LONG y, DWORD dwMouseMsg, BOOL fSetAlways); - - // default verb - - virtual HRESULT DoVerbPrimary(); - virtual HRESULT DoVerbShow(); - virtual HRESULT DoVerbInPlaceActivate(); - virtual HRESULT DoVerbUIActivate(); - virtual HRESULT DoVerbOpen(); - virtual HRESULT DoVerbHide(); - virtual HRESULT DoVerbDiscardUndo(); - virtual HRESULT DoVerbProperties(); - - // various helpers - - bool IsClosed() const { return status == CLOSED; } -// bool IsForged() const { return status == FORGED; } - bool IsActive() const { return status >= ACTIVE; } - bool IsUIActive() const { return status == UIACTIVE; } - - void RefreshSink(); - - enum { CONTROL = 1 }; - -protected: - void UpdateControlRect(); - HRESULT ShowControl(bool ui_activate); - void SetActiveObject(bool set); - - void TimerThread(); - -protected: - static const WCHAR data_stream_name[]; // default data stream - - enum STATE { CLOSED, /* FORGED, */ ACTIVE, UIACTIVE }; - -// Thread timer_thread; - IRef client_site; - IRef in_place_site; - SinkMap< IRef > advise_sinks; - dword view_sink_aspect; - dword view_sink_advf; - IRef view_sink; - Rect ctrl_rect; - Size extent_size; - STATE status; -// WPARAM ncmm_wParam; -// LPARAM ncmm_lParam; - bool stream_inited; - bool timer_shutdown; -}; - -class OcxRunnableControl : public OcxControl, public Interface -{ -public: - OcxRunnableControl() {} - - // IRunnableObject - - STDMETHOD(GetRunningClass)(GUID *clsid); - STDMETHOD(Run)(LPBC ctx); - BOOL STDMETHODCALLTYPE IsRunning(); - STDMETHOD(LockRunning)(BOOL lock, BOOL last_unlock_closes); - STDMETHOD(SetContainedObject)(BOOL contained); -}; - -/* -struct CtrlHook : public Ctrl -{ -public: - void _CreateChild() { Ctrl::CreateChild(); } -}; -*/ - -class OcxConnectionPoint : public Interface -{ -public: - OcxConnectionPoint() {} - - void SetEventGUID(const Guid& g) { guid = g; } - void SetContainer(IConnectionPointContainer *cont) { container = cont; } - void FireEvent(int method_id, const Vector& values); - - STDMETHOD(GetConnectionInterface)(IID *iid); - STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC); - STDMETHOD(Advise)(IUnknown *ptr, DWORD *cookie); - STDMETHOD(Unadvise)(DWORD cookie); - STDMETHOD(EnumConnections)(IEnumConnections **enum_conn); - - class Enumerator : public Interface - { - public: - Enumerator() {} - - void Attach(OcxConnectionPoint *pt) { point = IRef(pt); index = 0; } - - STDMETHOD(Next)(unsigned long count, CONNECTDATA *data, unsigned long *fetched); - STDMETHOD(Skip)(unsigned long connections); - STDMETHOD(Reset)(); - STDMETHOD(Clone)(IEnumConnections **enum_conn); - - private: - IRef point; - int index; - }; - - friend class Enumerator; - -public: - Guid guid; - -protected: - IConnectionPointContainer *container; - VectorMap > conn_map; - Vector free_id; -}; - -class OcxConnectionPointContainer : public Interface -{ -public: - OcxConnectionPointContainer(); - - void AddConnectionPoint(OcxConnectionPoint *conn) { point_map.GetAdd(conn -> guid) = conn; conn -> SetContainer(this); } - - STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum); - STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint **ppCP); - -private: - class Enumerator : public Interface - { - public: - Enumerator() {} - - void Attach(OcxConnectionPointContainer *pt) { point = pt; index = 0; } - - STDMETHOD(Next)(unsigned long count, IConnectionPoint **rgpcn, unsigned long *fetched); - STDMETHOD(Skip)(unsigned long connections); - STDMETHOD(Reset)(); - STDMETHOD(Clone)(IEnumConnectionPoints **enum_conn); - - private: - IRef point; - int index; - }; - - friend class Enumerator; - -private: - VectorMap point_map; -}; - -} - -#endif +#ifndef _Ole_Ctrl_OleCtrl_h_ +#define _Ole_Ctrl_OleCtrl_h_ + +#include +#include + +namespace Upp { + +#define OCXLOG RLOG // redefine to RLOG if you want logs in retail versions + +#ifdef _DEBUG +#define LOG_SYSOCXS 1 // 1 = log system calls (DllCanUnloadNow, DllGetClassObject) +#define LOG_METHODS 1 // 1 = log method calls +#define LOG_CREATES 1 // 1 = log instance creations & destructions +#define LOG_QUERIES 2 // 1 = log failed QueryInterface's +// // 2 = log all QueryInterface's +// // 3 = dump interface map whenever Query fails +#define LOG_PERSIST 1 // 1 = log saves / loads +#define LOG_RESULTS 2 // 1 = log error results +// // 2 = log all results +#define LOG_ADDREFS 1 // 1 = log AddRef's / Releases +#define LOG_INVOKES 1 // 1 = log IDispatch::Invoke +#else +#define LOG_SYSOCXS 1 +#define LOG_METHODS 0 +#define LOG_CREATES 0 +#define LOG_QUERIES 0 +#define LOG_PERSIST 0 +#define LOG_RESULTS 0 +#define LOG_ADDREFS 0 +#define LOG_INVOKES 0 +#endif + +#if LOG_SYSOCXS >= 1 +#define LOGSYSOCX(x) OCXLOG(x) +#else +#define LOGSYSOCX(x) +#endif + +#if LOG_METHODS >= 1 +#define LOGMETHOD(x) OCXLOG(x) +#else +#define LOGMETHOD(x) +#endif + +#if LOG_CREATES >= 1 +#define LOGCREATE(x) OCXLOG(x) +#else +#define LOGCREATE(x) +#endif + +#if LOG_QUERIES >= 1 +#define LOGQUERY(x) OCXLOG(x) +#else +#define LOGQUERY(x) +#endif + +#if LOG_PERSIST >= 1 +#define LOGPERSIST(x) OCXLOG(x) +#else +#define LOGPERSIST(x) +#endif + +#if LOG_RESULTS >= 2 +#define LOGRESULT(x) LogResult((x)) +#elif LOG_RESULTS >= 1 +#define LOGRESULT(x) LogError((x)) +#else +#define LOGRESULT(x) (x) +#endif + +#if LOG_INVOKES >= 1 +#define LOGINVOKE(x) OCXLOG(x) +#else +#define LOGINVOKE(x) +#endif + +typedef void (*InitProc)(); +InitProc& LateInitProc(); +InitProc& LateExitProc(); + +void DoLateInit(); +void DoLateExit(); + +#define OCX_APP_MAIN \ +void _DllMainAppInit(); \ +\ +static void _DllMainLateExit() \ +{ \ + RLOGBLOCK("_DllMainLateExit"); \ + Ctrl::ExitWin32(); \ +} \ +\ +static void _DllMainLateInit() \ +{ \ + RLOGBLOCK("_DllMainLateInit"); \ + RLOG("Ctrl::InitWin32"); \ + Ctrl::InitWin32(AppGetHandle()); \ + RLOG("AppInitEnvironment"); \ + AppInitEnvironment__(); \ + RLOG("DllMainAppInit"); \ + _DllMainAppInit(); \ + LateExitProc() = &_DllMainLateExit; \ +} \ +\ +BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpReserved) \ +{ \ + if(fdwReason == DLL_PROCESS_ATTACH) { \ + AppSetHandle(hinstDll); \ + } \ + RLOG("DllMain(" << FormatIntHex(hinstDll) << ", reason = " << (int)fdwReason << ")"); \ + if(fdwReason == DLL_PROCESS_ATTACH) { \ + LateInitProc() = &_DllMainLateInit; \ + } \ + else if(fdwReason == DLL_PROCESS_DETACH) { \ + DoLateExit(); \ + } \ + RLOG("//DllMain(" << FormatIntHex(hinstDll) << ", reason = " << (int)fdwReason << ")"); \ + return true; \ +} \ +\ +void _DllMainAppInit() + +/* +_variant_t ValueToVariant(const Value& v); +Value DispatchToValue(IDispatch *disp); +Value UnknownToValue(IUnknown *unk); +void ReturnVariant(VARIANT *var, const Value& v); +HRESULT CheckReturnString(BSTR *bstr, const String& s); +Color PackColor(long rgb); +long UnpackColor(Color c); +HRESULT CheckReturnColor(long *ptr, Color c); +*/ + +#define std_method HRESULT STDMETHODCALLTYPE +#define void_method void STDMETHODCALLTYPE + +class OcxTypeInfo; + +typedef VectorMap InterfaceMap; + +inline void AddInterfaceRaw(InterfaceMap& map, const Guid& guid, IUnknown *iface) +{ + map.Add(guid, iface); +} + +template +inline void AddInterface(InterfaceMap& map, const Guid& guid, T *iface) +{ + AddInterfaceRaw(map, guid, iface); +} + +#define PARENT_INTERFACE(clss, base) \ +template <> \ +inline void AddInterface(InterfaceMap& map, const Guid& guid, clss *iface) \ +{ \ + AddInterfaceRaw(map, guid, iface); \ + AddInterface(map, __uuidof(base), iface); \ +} + +PARENT_INTERFACE(IProvideClassInfo2, IProvideClassInfo) +PARENT_INTERFACE(IViewObject2, IViewObject) +PARENT_INTERFACE(IViewObjectEx, IViewObject2) +PARENT_INTERFACE(IOleInPlaceObject, IOleWindow) +PARENT_INTERFACE(IOleInPlaceObjectWindowless, IOleInPlaceObject) +PARENT_INTERFACE(IOleInPlaceActiveObject, IOleWindow) +PARENT_INTERFACE(IPersistStorage, IPersist) +PARENT_INTERFACE(IPersistStream, IPersist) +PARENT_INTERFACE(IPersistFile, IPersist) +PARENT_INTERFACE(IClassFactory2, IClassFactory) + +class OcxObject +{ + friend class OcxTypeInfo; + +public: + OcxObject(); + + template + void AddInterface(const Guid& guid, T *iface) { UPP::AddInterface(interface_map, guid, iface); } + template + void AddInterface(T *iface) { UPP::AddInterface(interface_map, __uuidof(T), iface); } + + IUnknown *OuterUnknown() { return outer_unknown ? outer_unknown : &inner_unknown; } + IUnknown *InnerUnknown() { return &inner_unknown; } + + HRESULT InternalQueryInterface(const GUID& iid, void **ppv); + HRESULT ExternalQueryInterface(const GUID& iid, void **ppv); + + static HRESULT RawGetTypeInfo(IRef& dispatch_info, unsigned tinfo, LCID lcid, ITypeInfo **ppinfo); + static HRESULT RawGetIDsOfNames(IRef& dispatch_info, REFIID riid, OLECHAR **names, unsigned cnames, LCID lcid, DISPID *dispid); + static HRESULT RawInvoke(IRef& dispatch_info, IDispatch *disp, DISPID dispid, word flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, unsigned *arg_err); + + static const char *GetObjectName() { return ""; } // programmatic object name (synthetic = .) + static const char *GetObjectHelp() { return ""; } // user-visible object name (synthetic = (CONTROL ? " Control " | " Object ") +// static GUID GetDispatchGUID() { return __uuidof(0); } // default ingoing dispatch interface + static GUID GetEventGUID() { return __uuidof(0); } // default outgoing dispatch interface + + enum + { + VERSION = 0, + CONTROL = 0, // override with 1 to make a control class + }; + + virtual int InternalAddRef() = 0; + virtual int InternalRelease() = 0; + + int ExternalAddRef(); + int ExternalRelease(); + +protected: + class OcxInnerUnknown : public IUnknown { + public: + OcxInnerUnknown() : owner(0) {} + ULONG STDMETHODCALLTYPE AddRef() { return owner->InternalAddRef(); } + ULONG STDMETHODCALLTYPE Release() { return owner->InternalRelease(); } + STDMETHOD(QueryInterface)(REFIID iid, void **ppv) { return owner->InternalQueryInterface(iid, ppv); } + + public: + OcxObject *owner; + }; + + OcxTypeInfo *ocx_info; + IUnknown *outer_unknown; + InterfaceMap interface_map; + OcxInnerUnknown inner_unknown; +}; + +template +class Interface : public I, virtual public OcxObject +{ +public: + Interface() { AddInterface(this); } +}; + +template +class DispatchInterface : public Interface +{ +public: + DispatchInterface() { AddInterface(__uuidof(I), this); AddInterface(this); } +// static GUID GetDispatchGUID() { return __uuidof(I); } + + // IDispatch + + STDMETHOD(GetTypeInfoCount)(unsigned *pctinfo); + STDMETHOD(GetTypeInfo)(unsigned tinfo, LCID lcid, ITypeInfo **ppinfo); + STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR **names, unsigned cnames, LCID lcid, DISPID *dispid); + STDMETHOD(Invoke)(DISPID dispid, REFIID riid, LCID lcid, word flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, unsigned *arg_err); + +protected: + void LoadTypeInfo() { ocx_info->GetDispatchTypeInfo(dispatch_info, __uuidof(I)); } + +protected: + IRef dispatch_info; +}; + +template +STDMETHODIMP DispatchInterface::GetTypeInfoCount(unsigned *pctinfo) +{ + if(!pctinfo) return E_POINTER; + *pctinfo = 1; + return S_OK; +} + +template +STDMETHODIMP DispatchInterface::GetTypeInfo(unsigned tinfo, LCID lcid, ITypeInfo **ppinfo) +{ + if(!ppinfo) return E_POINTER; + LoadTypeInfo(); + if(*ppinfo = ~dispatch_info) dispatch_info->AddRef(); + return S_OK; +} + +template +STDMETHODIMP DispatchInterface::GetIDsOfNames(REFIID riid, OLECHAR **names, unsigned cnames, LCID lcid, DISPID *dispid) +{ + LoadTypeInfo(); + return RawGetIDsOfNames(dispatch_info, riid, names, cnames, lcid, dispid); +} + +template +STDMETHODIMP DispatchInterface::Invoke(DISPID dispid, REFIID riid, LCID lcid, word flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, unsigned *arg_err) +{ + LoadTypeInfo(); + return RawInvoke(dispatch_info, static_cast(this), dispid, flags, params, result, excep, arg_err); +} + +class OcxProvideClassInfo : public Interface +{ +public: + // IProvideClassInfo + + STDMETHOD(GetClassInfo)(ITypeInfo **info); + + // IProvideClassInfo2 + + STDMETHOD(GetGUID)(dword guidkind, GUID *guid); +}; + +template +class OcxObjectWrapper : public T +{ +public: + OcxObjectWrapper() : refcount(0) {} + OcxObjectWrapper(OcxTypeInfo& _ocx_info) : refcount(0) { ocx_info = &_ocx_info; _ocx_info.object_count++; } + + static OcxObject *New() { return new OcxObjectWrapper(); } + static OcxObject *New(OcxTypeInfo& _ocx_info) { return new OcxObjectWrapper(_ocx_info); } + + virtual ULONG STDMETHODCALLTYPE AddRef() { return ExternalAddRef(); } + virtual ULONG STDMETHODCALLTYPE Release() { return ExternalRelease(); } + STDMETHOD(QueryInterface)(REFIID iid, void **ppv) { return ExternalQueryInterface(iid, ppv); } + + static String GetName(); + + virtual int InternalAddRef(); + virtual int InternalRelease(); + +private: + void Destroy(); + +private: + ULONG refcount; +}; + +template +int OcxObjectWrapper::InternalAddRef() +{ + ++refcount; +#if LOG_ADDREFS + RLOG(GetTypeName(typeid(*this)) << "::InternalAddRef(" << refcount << ")"); +#endif + return refcount; +} + +template +int OcxObjectWrapper::InternalRelease() +{ + int u = --refcount; +#if LOG_ADDREFS + RLOG(GetTypeName(typeid(*this)) << "::InternalRelease(" << refcount << ")"); +#endif + if(!u) + Destroy(); + return u; +} + +template +String OcxObjectWrapper::GetName() +{ + if(*T::GetObjectName()) + return T::GetObjectName(); + return GetTypeName(typeid(T)); +} + +template +void OcxObjectWrapper::Destroy() +{ + if(ocx_info) + { + ocx_info->object_count--; + LOGCREATE("\tdelete " << GetTypeName(typeid(T)) << ": " + << (int)ocx_info->object_count << " instances left in system"); + } + else + LOGCREATE("\tdelete " << GetTypeName(typeid(T))); + delete this; +} + +class OcxTypeInfo : public Interface +{ + friend class OcxTypeLib; + +public: + typedef OcxObject *(*New)(OcxTypeInfo& entry); + + OcxTypeInfo(const GUID& coclass_guid, /*const GUID& dispatch_guid,*/ const GUID& event_guid, + New new_fn, String name, const char* help = "", int ver = 0, + bool is_control = false); + + bool IsControl() const { return is_control; } + bool CanUnload() const; + + const Guid& GetCoClassGUID() const { return coclass_guid; } +// const Guid& GetDispatchGUID() const { return dispatch_guid; } + const Guid& GetEventGUID() const { return event_guid; } + + String GetName() const { return name; } + +// IRef GetDispatchTypeInfo(); + void GetDispatchTypeInfo(IRef& dest, Guid dispatch_iid); + IRef GetCoClassTypeInfo(); + + // IUnknown + + virtual int InternalAddRef() { return IncRef(); } + virtual int InternalRelease() { return DecRef(); } + virtual ULONG STDMETHODCALLTYPE AddRef() { return IncRef(); } + virtual ULONG STDMETHODCALLTYPE Release() { return DecRef(); } + STDMETHOD(QueryInterface)(REFIID iid, void **ppv) { return ExternalQueryInterface(iid, ppv); } + + // IClassFactory + + STDMETHOD(CreateInstance)(IUnknown *outer, REFIID iid, void **object); + STDMETHOD(LockServer)(BOOL lock); + + STDMETHOD(GetLicInfo)(/* [out] */ LICINFO *pLicInfo); + STDMETHOD(RequestLicKey)(/* [in] */ DWORD dwReserved, /* [out] */ BSTR *pBstrKey); + + STDMETHOD(CreateInstanceLic)( + /* [in] */ IUnknown *pUnkOuter, + /* [in] */ IUnknown *pUnkReserved, + /* [in] */ REFIID riid, + /* [in] */ BSTR bstrKey, + /* [iid_is][out] */ PVOID *ppvObj); + +public: + long object_count; // managed object count + IRef coclass_info; // coclass type info +// IRef dispatch_info; // ingoing dispatch interface type info + CriticalSection critical; // critical section used for initializations + +private: + int IncRef(); + int DecRef(); + +private: + Guid coclass_guid; // coclass GUID + Guid dispatch_guid; // GUID of default ingoing dispatch interface + Guid event_guid; // GUID of default outgoing dispatch interface + New new_fn; // constructor + String name; // programmatic object name - .. by default + const char *help; // user-visible object name - (" Control " | " Object ") by default + int ver; // 0 = use main library version + bool is_control; // false = generic object, true = insertable control + + long refcount; // AddRef/Release counter + Atomic lock_count; // LockServer lock count + +#ifndef _USRDLL + dword registration; // for CoRevokeClassObject +#endif +}; + +class OcxTypeLib +{ +public: + static OcxTypeLib& Get(); + + OcxTypeLib& Name(String name) { lib_name = name; return *this; } + String GetName() const { return lib_name; } + OcxTypeLib& DisplayName(String dn) { display_name = dn; return *this; } + String GetDisplayName() const { return display_name; } + String GetLibName() const; + OcxTypeLib& UsesLibrary(String name) { uses_libraries.GetAdd(name); return *this; } + + OcxTypeLib& Version(int _ver) { lib_ver = _ver; return *this; } + int GetVersion() const { return lib_ver; } + + HRESULT Register(); + HRESULT Unregister(); + HRESULT GetFactory(REFCLSID clsid, REFIID iid, void **ppv); + bool CanUnload() const; +#ifndef _USRDLL + HRESULT RegisterObjects(); // call CoRegisterClassObject for each object + void RevokeObjects(); // call CoRevokeClassObject +#endif + + void Add(OcxTypeInfo& entry) { objects.FindAdd(entry.coclass_guid, &entry); } + void AddInit(void (*fn)()) { ocx_init.Add(fn); } + + IRef GetTypeInfo(const Guid& guid); + + IRef& GetTypeLib(); + IRef& operator -> () { return GetTypeLib(); } + +public: + IRef typelib; + CriticalSection critical; + +private: + OcxTypeLib(); + +private: + VectorMap objects; + Vector ocx_init; + String lib_name; + String display_name; + int lib_ver; + VectorMap > uses_libraries; +}; + +struct OcxInit { OcxInit(void (*fn)()) { OcxTypeLib::Get().AddInit(fn); } }; +#define OCX_INIT(fn) static OcxInit MK__s = fn; + +#define OCX_OBJECT(type) \ + static OcxTypeInfo MK__s( \ + __uuidof(type), /* coclass GUID */ \ + /*type::GetDispatchGUID(),*/ /* default ingoing dispatch interface GUID */ \ + type::GetEventGUID(), /* default outgoing dispatch interface GUID */ \ + OcxObjectWrapper::New, /* constructor */ \ + OcxObjectWrapper::GetName(), /* name */ \ + type::GetObjectHelp(), /* help */ \ + type::VERSION, /* version */ \ + type::CONTROL); /* control object */ + +#define OCX_NEWOBJECT(type) \ + OCX_OBJECT(type) \ + static IRef COMBINE(OcxNew_, type)() { return new OcxObjectWrapper(MK__s); } + +#ifndef _USRDLL +bool ExeRegisterServer(); +bool ExeUnregisterServer(); +void ExeRunServer(); +#endif + +Size ToHiMetric(Size pixel_size); +Size FromHiMetric(Size himetric_size); +Rect GetWindow(HDC hdc); +Rect GetViewport(HDC hdc); + +LPOLESTR AllocString(String s); + +template +class SinkMap : public VectorMap +{ +public: + typedef VectorMap Base; + SinkMap() : next_sink_id(0) {} + dword Add(const T& object) { Base::Add(++next_sink_id, object); return next_sink_id; } + bool Remove(dword id) { int i = Find(id); return (i >= 0 ? (Base::Remove(i), true) : false); } + +private: + dword next_sink_id; +}; + +//template OleType; + +class OcxControl : public Ctrl, + public Interface, + public Interface, + public Interface, + public Interface, + public Interface, + public Interface, + public Interface, + public Interface, + public Interface, + public OcxProvideClassInfo +{ +public: + OcxControl(); + virtual ~OcxControl(); + + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + bool Open(HWND parent); + virtual void Serialize(Stream& stream); + void SerializePos(Stream& stream); + + virtual bool IsOcxChild(); + + using Ctrl::GetRect; + using Ctrl::SetData; + using Ctrl::GetData; + + // IOleObject + + STDMETHOD(SetClientSite)(IOleClientSite *site); + STDMETHOD(GetClientSite)(IOleClientSite **res); + STDMETHOD(SetHostNames)(LPCOLESTR app_name, LPCOLESTR doc_name); + STDMETHOD(Close)(dword save_option); + STDMETHOD(SetMoniker)(dword which, IMoniker *moniker); + STDMETHOD(GetMoniker)(dword assign, dword which, IMoniker **moniker); + STDMETHOD(InitFromData)(IDataObject *data, BOOL creation, dword); + STDMETHOD(GetClipboardData)(dword, IDataObject **data); + STDMETHOD(DoVerb)(long verb, MSG *msg, IOleClientSite *active_site, long index, HWND hwnd, const RECT *rc); + STDMETHOD(EnumVerbs)(IEnumOLEVERB **verbs); + STDMETHOD(Update)(); + STDMETHOD(IsUpToDate)(); + STDMETHOD(GetUserClassID)(GUID *guid); + STDMETHOD(GetUserType)(dword form, LPOLESTR *type); + STDMETHOD(SetExtent)(dword aspect, SIZEL *size); + STDMETHOD(GetExtent)(dword aspect, SIZEL *size); + STDMETHOD(Advise)(IAdviseSink *sink, dword *connection); + STDMETHOD(Unadvise)(dword connection); + STDMETHOD(EnumAdvise)(IEnumSTATDATA **sink_enum); + STDMETHOD(GetMiscStatus)(dword aspect, dword *status); + STDMETHOD(SetColorScheme)(LOGPALETTE *logpal); + + // IPersistStorage + + STDMETHOD(GetClassID)(GUID *guid); + STDMETHOD(IsDirty)(); // IPersistStreamInit as well + STDMETHOD(InitNew)(IStorage *stg); + STDMETHOD(Load)(IStorage *stg); + STDMETHOD(Save)(IStorage *stg, BOOL same_as_load); + STDMETHOD(SaveCompleted)(IStorage *stg); + STDMETHOD(HandsOffStorage)(); + + // IPersistStreamInit + + STDMETHOD(Load)(IStream *stream); + STDMETHOD(Save)(IStream *stream, BOOL clear_dirty); + STDMETHOD(GetSizeMax)(ULARGE_INTEGER *size); + STDMETHOD(InitNew)(); + + // IDataObject + + STDMETHOD(GetData)(FORMATETC *format, STGMEDIUM *medium); + STDMETHOD(GetDataHere)(FORMATETC *format, STGMEDIUM *medium); + STDMETHOD(QueryGetData)(FORMATETC *format); + STDMETHOD(GetCanonicalFormatEtc)(FORMATETC *in, FORMATETC *out); + STDMETHOD(SetData)(FORMATETC *format, STGMEDIUM *medium, BOOL free); + STDMETHOD(EnumFormatEtc)(dword dir, IEnumFORMATETC **enumerator); + STDMETHOD(DAdvise)(FORMATETC *format, dword advf, IAdviseSink *sink, dword *connection); + STDMETHOD(DUnadvise)(dword connection); + STDMETHOD(EnumDAdvise)(IEnumSTATDATA **enumerator); + + // IViewObject + + STDMETHOD(Draw)(DWORD aspect, LONG index, void *aspectinfo, + DVTARGETDEVICE *device, HDC target, HDC draw, + const RECTL *bounds, const RECTL *wbounds, + BOOL (STDMETHODCALLTYPE *progress)(ULONG_PTR dwContinue), ULONG_PTR arg); + STDMETHOD(GetColorSet)(dword aspect, long index, void *aspectinfo, + DVTARGETDEVICE *device, HDC target, LOGPALETTE **palette); + STDMETHOD(Freeze)(dword aspect, long index, void *aspectinfo, + dword *freeze_key); + STDMETHOD(Unfreeze)(dword freeze_key); + STDMETHOD(SetAdvise)(dword aspect, dword advf, IAdviseSink *sink); + STDMETHOD(GetAdvise)(dword *aspect, dword *advf, IAdviseSink **sink); + + // IViewObject2 + + STDMETHOD(GetExtent)(dword aspect, long index, DVTARGETDEVICE *device, SIZEL *size); + + // IViewObjectEx + + STDMETHOD(GetRect)(dword aspect, RECTL *rc); + STDMETHOD(GetViewStatus)(dword *status); + STDMETHOD(QueryHitPoint)(dword aspect, const RECT *bounds, POINT pos, long close_hint, dword *result); + STDMETHOD(QueryHitRect)(dword aspect, const RECT *bounds, const RECT *, long close_hint, dword *result); + STDMETHOD(GetNaturalExtent)(dword aspect, long index, DVTARGETDEVICE *ptd, HDC tdc, DVEXTENTINFO *extinfo, SIZEL *psize); + + // IOleWindow + + STDMETHOD(GetWindow)(HWND *hwnd); + STDMETHOD(ContextSensitiveHelp)(BOOL enter_mode); + + // IOleInPlaceObject + + STDMETHOD(InPlaceDeactivate)(); + STDMETHOD(UIDeactivate)(); + STDMETHOD(SetObjectRects)(const RECT *pos, const RECT *clip); + STDMETHOD(ReactivateAndUndo)(); + + // IOleInPlaceActiveObject + + STDMETHOD(TranslateAccelerator)(MSG *msg); + STDMETHOD(OnFrameWindowActivate)(BOOL activate); + STDMETHOD(OnDocWindowActivate)(BOOL activate); + STDMETHOD(ResizeBorder)(const RECT *border, IOleInPlaceUIWindow *ui, BOOL frame); + STDMETHOD(EnableModeless)(BOOL enable); + + // IOleControl + + STDMETHOD(GetControlInfo)(CONTROLINFO *cinfo); + STDMETHOD(OnMnemonic)(MSG *msg); + STDMETHOD(OnAmbientPropertyChange)(DISPID dispid); + STDMETHOD(FreezeEvents)(BOOL freeze); + + // IPointerInactive + + STDMETHOD(GetActivationPolicy)(DWORD *pdwPolicy); + STDMETHOD(OnInactiveMouseMove)(LPCRECT pRectBounds, LONG x, LONG y, DWORD grfKeyState); + STDMETHOD(OnInactiveSetCursor)(LPCRECT pRectBounds, LONG x, LONG y, DWORD dwMouseMsg, BOOL fSetAlways); + + // default verb + + virtual HRESULT DoVerbPrimary(); + virtual HRESULT DoVerbShow(); + virtual HRESULT DoVerbInPlaceActivate(); + virtual HRESULT DoVerbUIActivate(); + virtual HRESULT DoVerbOpen(); + virtual HRESULT DoVerbHide(); + virtual HRESULT DoVerbDiscardUndo(); + virtual HRESULT DoVerbProperties(); + + // various helpers + + bool IsClosed() const { return status == CLOSED; } +// bool IsForged() const { return status == FORGED; } + bool IsActive() const { return status >= ACTIVE; } + bool IsUIActive() const { return status == UIACTIVE; } + + void RefreshSink(); + + enum { CONTROL = 1 }; + +protected: + void UpdateControlRect(); + HRESULT ShowControl(bool ui_activate); + void SetActiveObject(bool set); + + void TimerThread(); + +protected: + static const WCHAR data_stream_name[]; // default data stream + + enum STATE { CLOSED, /* FORGED, */ ACTIVE, UIACTIVE }; + +// Thread timer_thread; + IRef client_site; + IRef in_place_site; + SinkMap< IRef > advise_sinks; + dword view_sink_aspect; + dword view_sink_advf; + IRef view_sink; + Rect ctrl_rect; + Size extent_size; + STATE status; +// WPARAM ncmm_wParam; +// LPARAM ncmm_lParam; + bool stream_inited; + bool timer_shutdown; +}; + +class OcxRunnableControl : public OcxControl, public Interface +{ +public: + OcxRunnableControl() {} + + // IRunnableObject + + STDMETHOD(GetRunningClass)(GUID *clsid); + STDMETHOD(Run)(LPBC ctx); + BOOL STDMETHODCALLTYPE IsRunning(); + STDMETHOD(LockRunning)(BOOL lock, BOOL last_unlock_closes); + STDMETHOD(SetContainedObject)(BOOL contained); +}; + +/* +struct CtrlHook : public Ctrl +{ +public: + void _CreateChild() { Ctrl::CreateChild(); } +}; +*/ + +class OcxConnectionPoint : public Interface +{ +public: + OcxConnectionPoint() {} + + void SetEventGUID(const Guid& g) { guid = g; } + void SetContainer(IConnectionPointContainer *cont) { container = cont; } + void FireEvent(int method_id, const Vector& values); + + STDMETHOD(GetConnectionInterface)(IID *iid); + STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC); + STDMETHOD(Advise)(IUnknown *ptr, DWORD *cookie); + STDMETHOD(Unadvise)(DWORD cookie); + STDMETHOD(EnumConnections)(IEnumConnections **enum_conn); + + class Enumerator : public Interface + { + public: + Enumerator() {} + + void Attach(OcxConnectionPoint *pt) { point = IRef(pt); index = 0; } + + STDMETHOD(Next)(unsigned long count, CONNECTDATA *data, unsigned long *fetched); + STDMETHOD(Skip)(unsigned long connections); + STDMETHOD(Reset)(); + STDMETHOD(Clone)(IEnumConnections **enum_conn); + + private: + IRef point; + int index; + }; + + friend class Enumerator; + +public: + Guid guid; + +protected: + IConnectionPointContainer *container; + VectorMap > conn_map; + Vector free_id; +}; + +class OcxConnectionPointContainer : public Interface +{ +public: + OcxConnectionPointContainer(); + + void AddConnectionPoint(OcxConnectionPoint *conn) { point_map.GetAdd(conn -> guid) = conn; conn -> SetContainer(this); } + + STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum); + STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint **ppCP); + +private: + class Enumerator : public Interface + { + public: + Enumerator() {} + + void Attach(OcxConnectionPointContainer *pt) { point = pt; index = 0; } + + STDMETHOD(Next)(unsigned long count, IConnectionPoint **rgpcn, unsigned long *fetched); + STDMETHOD(Skip)(unsigned long connections); + STDMETHOD(Reset)(); + STDMETHOD(Clone)(IEnumConnectionPoints **enum_conn); + + private: + IRef point; + int index; + }; + + friend class Enumerator; + +private: + VectorMap point_map; +}; + +} + +#endif diff --git a/uppsrc/Ole/Ctrl/control.cpp b/archive/uppsrc/Ole/Ctrl/control.cpp similarity index 96% rename from uppsrc/Ole/Ctrl/control.cpp rename to archive/uppsrc/Ole/Ctrl/control.cpp index a9f7ffa8d..6430b2c41 100644 --- a/uppsrc/Ole/Ctrl/control.cpp +++ b/archive/uppsrc/Ole/Ctrl/control.cpp @@ -1,1209 +1,1209 @@ -#include - -#ifdef PLATFORM_WIN32 - -namespace Upp { - -LPOLESTR AllocString(String s) -{ - LPOLESTR p = reinterpret_cast(CoTaskMemAlloc(sizeof(OLECHAR) * (s.GetLength() + 1))), d = p; - const char *f = s; - while(*d++ = *f++) - ; - return p; -} - -OcxControl::OcxControl() -{ - ActiveX(); - view_sink_aspect = DVASPECT_CONTENT; - view_sink_advf = 0; - status = CLOSED; - stream_inited = false; - timer_shutdown = false; - extent_size = GetStdSize(); -} - -OcxControl::~OcxControl() -{ - LOGMETHOD("OcxControl::~OcxControl"); -} - -bool OcxControl::IsOcxChild() -{ - return true; -} - -LRESULT OcxControl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - LOGMETHOD("OcxControl::WindowProc"); -// RLOG("message = " << FormatIntHex(message) << ", wParam = " << FormatIntHex(wParam) << ", lParam = " << FormatIntHex(lParam)); - if(message == WM_GETDLGCODE) - return DLGC_WANTALLKEYS | DLGC_WANTARROWS | DLGC_WANTMESSAGE; - LRESULT res = Ctrl::WindowProc(message, wParam, lParam); - return res; -} - -bool OcxControl::Open(HWND parent) // parent = 0 - create forged control -{ - LOGMETHOD("OcxControl::Open"); -// if(!IsForged()) - ctrl_rect = GetRect(); - if(IsOpen()) - Ctrl::Close(); - if(parent && IsChild()) - Remove(); - status = CLOSED; - -// noproc = true; -// visible |= !parent; - Rect rc = ctrl_rect; - if(IsNull(rc)) - rc = Rect(0, 0, 0, 0); - if(!parent) - { // move window away from screen in forged mode - rc.Offset(-30000 - rc.left, -30000 - rc.top); - SetRect(rc); - } -// view.SetRectEmpty(); - - Create(parent, (IsEnabled() ? 0 : WS_DISABLED) | (parent ? WS_CHILD : WS_POPUP) | WS_VISIBLE, - (parent ? 0 : WS_EX_TOOLWINDOW), false, SW_HIDE, false); - - Show(); - -/* wnd = &stdwnd; - fullrefresh = false; - dword style = parent ? WS_CHILD : WS_POPUP, exstyle = WS_EX_TOOLWINDOW; - if(!enabled) style |= WS_DISABLED; - noproc = true; - visible |= !parent; - Rect rc = GetRect(); - if(!parent) - { // move window away from screen in forged mode - rc.OffsetRect(-30000 - rc.left, -30000 - rc.top); - SetRect(rc); - } - view.SetRectEmpty(); - wnd->CreateEx(exstyle, CtrlWindowClass(), -#ifdef _DEBUG - Name(), -#else - NULL, -#endif - style, - rc.left, rc.top, rc.Width(), rc.Height(), - parent ? parent : 0, 0, 0); - - if(!wnd->m_hWnd) - return false; - - type = POPUP; - noproc = false; - - for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) - reinterpret_cast(q)->_CreateChild(); - - if(visible) - ShowWindow(GetHWND(), SW_SHOWNA); -// SetMnemonic((byte) hotchar); - - RefreshLayout(); - RefreshPos(); - Refresh(); - CancelMode(); - CreateInit(); - move = true; -*/ - status = ACTIVE; //(parent ? ACTIVE : FORGED); - return true; -} - -void OcxControl::Serialize(Stream& stream) -{ - int version = 1; - SerializePos(stream); -} - -void OcxControl::SerializePos(Stream& stream) -{ - int version = 1; - stream / version; - Rect rc; - if(stream.IsStoring()) - rc = GetRect(); - stream % rc; - if(stream.IsLoading()) - SetRect(rc); -} - -const WCHAR OcxControl::data_stream_name[] = L"data"; - -HRESULT OcxControl::SetClientSite(IOleClientSite *site) -{ - LOGMETHOD("IOleObject::SetClientSite()"); - in_place_site = site; - client_site = site; - if(GetRect().IsEmpty()) { - LOG("Setting up default control rect..."); - SetRect(GetStdSize()); - } - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetClientSite(IOleClientSite **res) -{ - LOGMETHOD("IOleObject::GetClientSite"); - if(*res = ~client_site) - client_site->AddRef(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::SetHostNames(LPCOLESTR app_name, LPCOLESTR doc_name) -{ - LOGMETHOD("IOleObject::SetHostNames"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::Close(dword save_option) -{ - LOGMETHOD("IOleObject::Close"); - InPlaceDeactivate(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::SetMoniker(dword which, IMoniker *moniker) -{ - LOGMETHOD("IOleObject::SetMoniker"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetMoniker(dword assign, dword which, IMoniker **moniker) -{ - LOGMETHOD("IOleObject::GetMoniker"); - *moniker = 0; - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::InitFromData(IDataObject *data, BOOL creation, dword) -{ - LOGMETHOD("IOleObject::InitFromData"); - return LOGRESULT(S_FALSE); -} - -HRESULT OcxControl::GetClipboardData(dword, IDataObject **data) -{ - LOGMETHOD("IOleObject::GetClipboardData"); - *data = 0; - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::DoVerb(long verb, MSG *msg, IOleClientSite *active_site, - long index, HWND parent, const RECT *rc) -{ - LOGMETHOD("IOleObject::DoVerb"); - switch(verb) - { - case OLEIVERB_PRIMARY: return DoVerbPrimary(); - case OLEIVERB_SHOW: return DoVerbShow(); - case OLEIVERB_INPLACEACTIVATE: return DoVerbInPlaceActivate(); - case OLEIVERB_UIACTIVATE: return DoVerbUIActivate(); - case OLEIVERB_HIDE: return DoVerbHide(); - case OLEIVERB_OPEN: return DoVerbOpen(); - case OLEIVERB_DISCARDUNDOSTATE: return DoVerbDiscardUndo(); - case OLEIVERB_PROPERTIES: return DoVerbProperties(); - default: return OLEOBJ_S_INVALIDVERB; - } -} - -HRESULT OcxControl::EnumVerbs(IEnumOLEVERB **verbs) -{ - LOGMETHOD("IOleObject::EnumVerbs"); - *verbs = 0; - return LOGRESULT(OLEOBJ_E_NOVERBS); -} - -HRESULT OcxControl::Update() -{ - LOGMETHOD("IOleObject::Update"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::IsUpToDate() -{ - LOGMETHOD("IOleObject::IsUpToDate"); - return LOGRESULT(MK_E_UNAVAILABLE); -} - -HRESULT OcxControl::GetUserClassID(GUID *guid) -{ - LOGMETHOD("IOleObject::GetUserClassID"); - ASSERT(ocx_info); - *guid = ocx_info->GetCoClassGUID(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetUserType(dword form, LPOLESTR *type) -{ -// __asm int 3 - LOGMETHOD("IOleObject::GetUserType"); - ASSERT(ocx_info); - *type = AllocString(ocx_info->GetName()); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::SetExtent(dword aspect, SIZEL *hi_size) -{ - LOGMETHOD("IOleObject::SetExtent(" << hi_size->cx << ", " << hi_size->cy << ")"); - if(aspect == DVASPECT_CONTENT) { - extent_size = min(FromHiMetric(*hi_size), GetMaxSize()); - OCXLOG("Ctrl size = " << extent_size); - SetRect(Rect(GetRect().TopLeft(), extent_size)); - } - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetExtent(dword aspect, SIZEL *size) -{ - LOGMETHOD("IOleObject::GetExtent"); - if(aspect == DVASPECT_CONTENT) { - *size = ToHiMetric(extent_size); - return LOGRESULT(S_OK); - } - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::Advise(IAdviseSink *sink, dword *connection) -{ - LOGMETHOD("IOleObject::Advise"); - if(!sink || !connection) - return E_INVALIDARG; - *connection = advise_sinks.Add(sink); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::Unadvise(dword connection) -{ - LOGMETHOD("IOleObject::Unadvise"); - return LOGRESULT(advise_sinks.Remove(connection) ? S_OK : E_INVALIDARG); -} - -HRESULT OcxControl::EnumAdvise(IEnumSTATDATA **sink_enum) -{ - LOGMETHOD("IOleObject::EnumAdvise"); - *sink_enum = 0; - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::GetMiscStatus(dword aspect, dword *st) -{ - LOGMETHOD("IOleObject::GetMiscStatus"); - *st = OLEMISC_RECOMPOSEONRESIZE - | OLEMISC_INSIDEOUT - | OLEMISC_ACTIVATEWHENVISIBLE; - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::SetColorScheme(LOGPALETTE *logpal) -{ - LOGMETHOD("IOleObject::SetColorScheme"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetClassID(GUID *guid) -{ - LOGMETHOD("IPersist::GetClassID"); - ASSERT(ocx_info); - *guid = ocx_info->GetCoClassGUID(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::IsDirty() -{ - LOGMETHOD("IPersistStorage::IsDirty"); - return LOGRESULT(IsModified() ? S_OK : S_FALSE); -} - -HRESULT OcxControl::InitNew(IStorage *stg) -{ - LOGMETHOD("IPersistStorage::InitNew"); - if(!stg) - return LOGRESULT(E_INVALIDARG); - HRESULT hr; - IStreamPtr stream; - if(FAILED(hr = stg->CreateStream(data_stream_name, - STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream))) - return LOGRESULT(hr); - return InitNew(); // call IPersistStream::InitNew -} - -HRESULT OcxControl::Load(IStorage *stg) -{ - LOGMETHOD("IPersistStorage::Load"); - if(!stg) - return LOGRESULT(E_INVALIDARG); - HRESULT hr; - IStreamPtr stream; - if(FAILED(hr = stg->OpenStream(data_stream_name, 0, - STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stream))) - return LOGRESULT(hr); - return Load(stream); // delegate load to IPersistStream::Load -} - -HRESULT OcxControl::Save(IStorage *stg, BOOL same_as_load) -{ - LOGMETHOD("IPersistStorage::Save(" << (same_as_load ? "same as load" : "full save") << ')'); - if(!stg) - return LOGRESULT(E_INVALIDARG); - HRESULT hr; -#if LOG_PERSIST >= 1 - STATSTG stat; - Zero(stat); - if(FAILED(hr = stg->Stat(&stat, STATFLAG_NONAME))) - return LOGRESULT(hr); - OCXLOG(NFormat("Storage flags = %08x\r\n", (int)stat.grfMode)); - OCXLOG("CLSID = " << GetCoClassName(stat.clsid) << " - " << Format(stat.clsid)); -#endif - IStreamPtr stream; - if(FAILED(hr = stg->CreateStream(data_stream_name, - STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream))) - return LOGRESULT(hr); - - if(FAILED(hr = Save(stream, true))) - return hr; - -#if LOG_PERSIST >= 1 - ULARGE_INTEGER ul; - if(FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_END, &ul))) - return hr; - OCXLOG("- stream size = " << ul.LowPart); -#endif - - return S_OK; -} - -HRESULT OcxControl::SaveCompleted(IStorage *stg) -{ - LOGMETHOD("IPersistStorage::SaveCompleted"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::HandsOffStorage() -{ - LOGMETHOD("IPersistStorage::HandsOffStorage"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::Load(IStream *stream) -{ - LOGMETHOD("IPersistStreamInit::Load"); - if(stream_inited) - return LOGRESULT(E_UNEXPECTED); -#if LOG_PERSIST >= 1 - ULARGE_INTEGER old_pos, len; - HRESULT hr; - if(FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_CUR, &old_pos)) - || FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_END, &len)) - || FAILED(hr = stream->Seek(reinterpret_cast(old_pos), STREAM_SEEK_SET, 0))) - return hr; - OCXLOG("- stream size = " << len.LowPart); -#endif - OleStream os(stream); - if(!os.IsOpen() || os.IsError()) - { - LOGPERSIST("- internal error creating OleStream"); - return LOGRESULT(E_FAIL); - } - os.SetLoading(); - Serialize(os); - ClearModify(); - os.Close(); - stream_inited = true; - if(os.IsError()) - return LOGRESULT(os.GetError() >= 0 ? os.GetError() : E_FAIL); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::Save(IStream *stream, BOOL clear_dirty) -{ - LOGMETHOD("IPersistStreamInit::Save"); - OleStream os(stream); - if(!os.IsOpen() || os.IsError()) - { - LOGPERSIST("- internal error creating OleStream"); - return LOGRESULT(E_FAIL); - } - os.SetStoring(); - Serialize(os); - os.Close(); - if(os.IsError()) - return LOGRESULT(os.GetError() >= 0 ? os.GetError() : E_FAIL); - if(clear_dirty) - ClearModify(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetSizeMax(ULARGE_INTEGER *size) -{ - LOGMETHOD("IPersistStreamInit::GetSizeMax"); - if(!size) - return LOGRESULT(E_INVALIDARG); - SizeStream ss; - Serialize(ss); - *size = AsULarge(ss.GetSize()); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::InitNew() -{ - LOGMETHOD("IPersistStreamInit::InitNew"); - if(stream_inited) - return LOGRESULT(E_UNEXPECTED); - SetRect(Rect(Point(0, 0), GetStdSize())); - SetData(Value()); // default clear algorithm - ClearModify(); - stream_inited = true; - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetData(FORMATETC *format, STGMEDIUM *medium) -{ - LOGMETHOD("IDataObject::GetData"); - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::GetDataHere(FORMATETC *format, STGMEDIUM *medium) -{ - LOGMETHOD("IDataObject::GetDataHere"); - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::QueryGetData(FORMATETC *format) -{ - LOGMETHOD("IDataObject::QueryGetData"); - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::GetCanonicalFormatEtc(FORMATETC *in, FORMATETC *out) -{ - LOGMETHOD("IDataObject::GetCanonicalFormatEtc"); - *out = *in; - out->ptd = 0; - return LOGRESULT(DATA_S_SAMEFORMATETC); -} - -HRESULT OcxControl::SetData(FORMATETC *format, STGMEDIUM *medium, BOOL free) -{ - LOGMETHOD("IDataObject::SetData"); - if(free) - ReleaseStgMedium(medium); - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::EnumFormatEtc(dword dir, IEnumFORMATETC **enumerator) -{ - LOGMETHOD("IDataObject::EnumFormatEtc"); - *enumerator = 0; - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::DAdvise(FORMATETC *format, dword advf, IAdviseSink *sink, dword *connection) -{ - LOGMETHOD("IDataObject::DAdvise"); - *connection = advise_sinks.Add(sink); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::DUnadvise(dword connection) -{ - LOGMETHOD("IDataObject::DUnadvise"); - return LOGRESULT(advise_sinks.Remove(connection) ? S_OK : E_FAIL); -} - -HRESULT OcxControl::EnumDAdvise(IEnumSTATDATA **enumerator) -{ - LOGMETHOD("IDataObject::EnumDAdvise"); - *enumerator = 0; - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::Draw(DWORD aspect, LONG index, void *aspectinfo, - DVTARGETDEVICE *device, HDC target, HDC draw_dc, - const RECTL *bounds, const RECTL *wbounds, - BOOL (STDMETHODCALLTYPE *progress)(ULONG_PTR dwContinue), ULONG_PTR arg) -{ - LOGMETHOD("IViewObject::Draw"); - if(aspect != DVASPECT_CONTENT) - return DV_E_DVASPECT; -// if(IsClosed() && !CreateControl(0)) // create forged control to make paint routines work -// return E_FAIL; - Rect rc(GetSize()); - if(bounds) - { - rc.left = bounds->left; - rc.top = bounds->top; - rc.right = bounds->right; - rc.bottom = bounds->bottom; - LPtoDP(draw_dc, reinterpret_cast(&rc), 2); - } -// if(IsForged()) -// SetCtrlRect(rc); - - Point worg, vorg; - Size wext, vext; - SetWindowOrgEx(draw_dc, 0, 0, worg); - SetWindowExtEx(draw_dc, 1, 1, wext); - SetViewportOrgEx(draw_dc, 0, 0, vorg); - SetViewportExtEx(draw_dc, 1, 1, vext); - int old_mode = SetMapMode(draw_dc, MM_TEXT); - - SystemDraw draw(draw_dc); - draw.Offset(rc.TopLeft()); - DrawCtrl(draw); - draw.End(); - - SetMapMode(draw_dc, old_mode); - SetWindowOrgEx(draw_dc, worg.x, worg.y, 0); - SetWindowExtEx(draw_dc, wext.cx, wext.cy, 0); - SetViewportOrgEx(draw_dc, vorg.x, vorg.y, 0); - SetViewportExtEx(draw_dc, vext.cx, vext.cy, 0); - -// DUMP(GetMapMode(draw_dc)); -// DUMP(::GetWindow(draw_dc)); -// DUMP(GetViewport(draw_dc)); -// ::Draw draw(draw_dc); -// draw.DrawRect(rc, Yellow); -// draw.Clipoff(rc); -// CtrlPaint(draw); -// draw.End(); - - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetColorSet(dword aspect, long index, void *aspectinfo, - DVTARGETDEVICE *device, HDC target, LOGPALETTE **palette) -{ - LOGMETHOD("IViewObject::GetColorSet"); - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::Freeze(dword aspect, long index, void *aspectinfo, dword *freeze_key) -{ - LOGMETHOD("IViewObject::Freeze"); - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::Unfreeze(dword freeze_key) -{ - LOGMETHOD("IViewObject::Unfreeze"); - return LOGRESULT(E_NOTIMPL); -} - -HRESULT OcxControl::SetAdvise(dword aspect, dword advf, IAdviseSink *sink) -{ - LOGMETHOD("IViewObject::SetAdvise(aspect = " << aspect << ", advf = " << advf << ")"); - view_sink_aspect = aspect; - view_sink_advf = advf; - view_sink = sink; - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetAdvise(dword *aspect, dword *advf, IAdviseSink **sink) -{ - LOGMETHOD("IViewObject::GetAdvise"); - if(aspect) *aspect = view_sink_aspect; - if(advf) *advf = view_sink_advf; - if(sink && (*sink = ~view_sink)) - (**sink).AddRef(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetExtent(dword aspect, long index, DVTARGETDEVICE *device, SIZEL *size) -{ - LOGMETHOD("IViewObject2::GetExtent"); - *size = GetRect().Size(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetRect(dword aspect, RECTL *rc) -{ - LOGMETHOD("IViewObjectEx::GetRect(aspect = " << aspect << ")"); - if(aspect != DVASPECT_CONTENT) - return E_NOTIMPL; - if(!rc) - return E_INVALIDARG; - *rc = ToRectL(GetRect()); - return S_OK; -} - -HRESULT OcxControl::GetViewStatus(dword *status) -{ - LOGMETHOD("IViewObjectEx::GetViewStatus"); - *status = (IsTransparent() ? 0 : DVASPECT_OPAQUE); - return S_OK; -} - -HRESULT OcxControl::QueryHitPoint(dword aspect, const RECT *bounds, POINT pos, long close_hint, dword *result) -{ - LOGMETHOD("IViewObjectEx::QueryHitPoint"); - if(!result) - return E_INVALIDARG; - if(aspect != DVASPECT_CONTENT) - return E_FAIL; - *result = PtInRect(bounds, pos) ? HITRESULT_HIT : HITRESULT_OUTSIDE; - return S_OK; -} - -HRESULT OcxControl::QueryHitRect(dword aspect, const RECT *bounds, const RECT *rc, long close_hint, dword *result) -{ - LOGMETHOD("IViewObjectEx::QueryHitRect"); - if(!result) - return E_INVALIDARG; - if(aspect != DVASPECT_CONTENT) - return E_FAIL; - *result = Rect(*bounds).Contains(Rect(*rc)) ? HITRESULT_HIT : HITRESULT_OUTSIDE; - return S_OK; -} - -HRESULT OcxControl::GetNaturalExtent(dword aspect, long index, DVTARGETDEVICE *ptd, HDC tdc, DVEXTENTINFO *extinfo, SIZEL *psize) -{ - LOGMETHOD("IViewObjectEx::GetNaturalExtent"); - if(aspect != DVASPECT_CONTENT) - return E_FAIL; - if(psize) - *psize = GetRect().Size(); - return S_OK; -} - -HRESULT OcxControl::GetWindow(HWND *hwnd) -{ - LOGMETHOD("IOleWindow::GetWindow"); - if(!hwnd) - return LOGRESULT(E_INVALIDARG); - return LOGRESULT((*hwnd = GetHWND()) ? S_OK : E_FAIL); -} - -HRESULT OcxControl::ContextSensitiveHelp(BOOL enter_mode) -{ - LOGMETHOD("IOleWindow::ContextSensitiveHelp"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::InPlaceDeactivate() -{ - LOGMETHOD("IOleInPlaceObject::InPlaceDeactivate"); - if(!IsActive()) - return LOGRESULT(S_OK); - UIDeactivate(); - if(!!in_place_site) - in_place_site->OnInPlaceDeactivate(); - if(IsOpen() && !IsChild()) - Ctrl::Close(); - in_place_site.Clear(); - client_site.Clear(); - status = CLOSED; - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::UIDeactivate() -{ - LOGMETHOD("IOleInPlaceObject::UIDeactivate"); - - if(!IsUIActive()) - return LOGRESULT(S_OK); // no work needed when not UI active - - if(!in_place_site) - return LOGRESULT(E_FAIL); - - SetActiveObject(false); - return LOGRESULT(in_place_site->OnUIDeactivate(false)); -} - -HRESULT OcxControl::SetObjectRects(const RECT *pos, const RECT *clip) -{ - LOGMETHOD("IOleInPlaceObject::SetObjectRects(pos = " << Rect(*pos) << ", clip = " << Rect(*clip) << ")"); - if(!pos || !clip) - return LOGRESULT(E_INVALIDARG); - Rect rc(Point(pos->left, pos->top), extent_size); - OCXLOG("-> Ctrl rc = " << rc << " (extent size = " << extent_size << ")"); - SetRect(rc); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::ReactivateAndUndo() -{ - LOGMETHOD("IOleInPlaceObject::ReactivateAndUndo"); - if(!IsActive()) - return OLE_E_NOT_INPLACEACTIVE; - return DoVerbUIActivate(); -} - -HRESULT OcxControl::TranslateAccelerator(MSG *msg) -{ - LOGMETHOD("IOleInPlaceObject::TranslateAccelerator"); - dword keycode = 0; - if(msg->message == WM_KEYDOWN) - keycode = KEYtoK((dword)msg->wParam); - else if(msg->message == WM_KEYUP) - keycode = KEYtoK((dword)msg->wParam) | K_KEYUP; - else if(msg->message == WM_SYSKEYDOWN && (msg->lParam & 0x20000000)) - keycode = KEYtoK((dword)msg->wParam); - else if(msg->message == WM_SYSKEYUP && (msg->lParam & 0x20000000)) - keycode = KEYtoK((dword)msg->wParam) | K_KEYUP; - else if(msg->message == WM_CHAR) - keycode = (dword)msg->wParam; - if(keycode == 0 || !IsActive() || !IsEnabled() || !IsVisible()) - return LOGRESULT(S_FALSE); - - return LOGRESULT(HotKey(keycode) ? S_OK : S_FALSE); -} - -HRESULT OcxControl::OnFrameWindowActivate(BOOL activate) -{ - LOGMETHOD("IOleInPlaceObject::OnFrameWindowActivate"); - Refresh(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::OnDocWindowActivate(BOOL activate) -{ - LOGMETHOD("IOleInPlaceObject::OnDocWindowActivate"); - Refresh(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::ResizeBorder(const RECT *border, IOleInPlaceUIWindow *ui, BOOL frame) -{ - LOGMETHOD("IOleInPlaceObject::ResizeBorder"); - Refresh(); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::EnableModeless(BOOL enable) -{ - LOGMETHOD("IOleInPlaceObject::EnableModeless"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::GetControlInfo(CONTROLINFO *cinfo) -{ - LOGMETHOD("IOleControl::GetControlInfo"); - if(!cinfo) - return LOGRESULT(E_INVALIDARG); - cinfo->hAccel = 0; - cinfo->cAccel = 0; - cinfo->dwFlags = 0; // by default eat neither Return nor Escape - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::OnMnemonic(MSG *msg) -{ - LOGMETHOD("IOleControl::OnMnemonic"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::OnAmbientPropertyChange(DISPID dispid) -{ - LOGMETHOD("IOleControl::OnAmbientPropertyChange"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::FreezeEvents(BOOL freeze) -{ - LOGMETHOD("IOleControl::FreezeEvents(" << (freeze ? "on" : "off") << ")"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::DoVerbPrimary() -{ - LOGMETHOD("DoVerbPrimary"); - return LOGRESULT(ShowControl(true)); -} - -HRESULT OcxControl::DoVerbShow() -{ - LOGMETHOD("DoVerbShow"); - return LOGRESULT(ShowControl(false)); -} - -HRESULT OcxControl::ShowControl(bool ui_activate) -{ - LOGMETHOD("OcxControl::ShowControl(" << (ui_activate ? "UI activate" : "") << ")"); - - if(!in_place_site) - return LOGRESULT(E_FAIL); - - HRESULT hr; - - if(!IsActive()) - { - HWND parent = 0; - - if((hr = in_place_site->CanInPlaceActivate()) != S_OK - || FAILED(hr = in_place_site->OnInPlaceActivate()) - || FAILED(hr = in_place_site->GetWindow(&parent))) - return LOGRESULT(hr); - - if(!parent || !::IsWindow(parent)) - return E_FAIL; - - UpdateControlRect(); - - if(!Open(parent)) - return LOGRESULT(E_FAIL); - - Show(); - Enable(); - -// todo: fire view change -// if(view_sink) -// { -// view_sink->OnViewChange(DVASPECT_CONTENT, -1); -// if(view_sink_advf & ADVF_ONLYONCE) -// view_sink = 0; -// } -// - } - - if(ui_activate && !IsUIActive() && SUCCEEDED(in_place_site->OnUIActivate())) - status = UIACTIVE; - - Show(); - Enable(); - if(!HasFocusDeep() && !SetWantFocus() && GetFirstChild()) - IterateFocusForward(GetFirstChild(), this); - SetActiveObject(true); - - return LOGRESULT(client_site->ShowObject()); -} - -HRESULT OcxControl::DoVerbInPlaceActivate() -{ - LOGMETHOD("DoVerbInPlaceActivate"); - return LOGRESULT(ShowControl(false)); -} - -HRESULT OcxControl::DoVerbUIActivate() -{ - LOGMETHOD("DoVerbUIActivate"); - return LOGRESULT(ShowControl(true)); -} - -HRESULT OcxControl::DoVerbHide() -{ - LOGMETHOD("DoVerbHide"); - Hide(); -// Close(false); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::DoVerbOpen() -{ - LOGMETHOD("DoVerbOpen"); - return LOGRESULT(ShowControl(false)); -} - -HRESULT OcxControl::DoVerbDiscardUndo() -{ - LOGMETHOD("DoVerbDiscardUndo"); - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::DoVerbProperties() -{ - LOGMETHOD("DoVerbProperties"); - return LOGRESULT(S_OK); -} - -void OcxControl::UpdateControlRect() -{ - LOGMETHOD("OcxControl::UpdateControlRect"); - - if(!in_place_site) - return; - - IOleInPlaceFramePtr frame; - IOleInPlaceUIWindowPtr ui_window; - OLEINPLACEFRAMEINFO frame_info = { sizeof(frame_info) }; - Rect rc, clip; - if(FAILED(in_place_site->GetWindowContext(&frame, &ui_window, rc, clip, &frame_info))) - return; - - OCXLOG("Control rect: " << rc << ", clip = " << clip); - SetRect(rc); -} - -void OcxControl::SetActiveObject(bool set) -{ - LOGMETHOD("OcxControl::SetActiveObject"); - if(!in_place_site) - return; - - IRef frame; - IRef ui_window; - OLEINPLACEFRAMEINFO frame_info = { sizeof(frame_info) }; - Rect rc, clip; - if(FAILED(in_place_site->GetWindowContext(frame.Set(), ui_window.Set(), rc, clip, &frame_info))) - return; - - if(!!frame) { - frame->SetActiveObject(set ? this : 0, 0); - if(set) - frame->SetBorderSpace(0); - } - if(!!ui_window) { - ui_window->SetActiveObject(set ? this : 0, 0); - if(set) - ui_window->SetBorderSpace(0); - } -} - -void OcxControl::RefreshSink() -{ - LOGMETHOD("OcxControl::RefreshSink"); - if(!!view_sink) - view_sink->OnViewChange(DVASPECT_CONTENT, -1); -} - -HRESULT OcxControl::GetActivationPolicy(DWORD *pdwPolicy) -{ - LOGMETHOD("IPointerInactive::GetActivationPolicy"); - *pdwPolicy = POINTERINACTIVE_ACTIVATEONENTRY; - return LOGRESULT(S_OK); -} - -HRESULT OcxControl::OnInactiveMouseMove(LPCRECT pRectBounds, LONG x, LONG y, DWORD grfKeyState) -{ - LOGMETHOD("IPointerInactive::OnInactiveMouseMove"); - return S_OK; -} - -HRESULT OcxControl::OnInactiveSetCursor(LPCRECT pRectBounds, LONG x, LONG y, DWORD dwMouseMsg, BOOL fSetAlways) -{ - LOGMETHOD("IPointerInactive::InactiveSetCursor"); - return S_OK; -} - -HRESULT OcxRunnableControl::GetRunningClass(GUID *clsid) -{ - LOGMETHOD("IRunnableObject::GetRunningClass"); - *clsid = __uuidof(0); - return LOGRESULT(E_UNEXPECTED); -} - -HRESULT OcxRunnableControl::Run(LPBC ctx) -{ - LOGMETHOD("IRunnableObject::Run"); - return LOGRESULT(S_OK); -} - -BOOL OcxRunnableControl::IsRunning() -{ - LOGMETHOD("IRunnableObject::IsRunning"); - return true; -} - -HRESULT OcxRunnableControl::LockRunning(BOOL lock, BOOL last_unlock_closes) -{ - LOGMETHOD("IRunnableObject::LockRunning"); - return LOGRESULT(S_OK); -} - -HRESULT OcxRunnableControl::SetContainedObject(BOOL contained) -{ - LOGMETHOD("IRunnableObject::SetContainedObject"); - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Next(unsigned long count, CONNECTDATA *data, unsigned long *fetched) -{ - LOGMETHOD("IConnectionPoint::IEnumConnections::Next(" << (int)count << ")"); - if(!point) - return LOGRESULT(E_FAIL); - if(count == 0 || !data || !fetched) - return LOGRESULT(E_INVALIDARG); - int avail = min(count, point->conn_map.GetCount() - index); - if(avail <= 0) - { - *fetched = 0; - return LOGRESULT(S_OK); - } - *fetched = avail; - while(--avail >= 0) - { - data->pUnk = point->conn_map[index].AddRef(); - data->dwCookie = point->conn_map.GetKey(index); - index++; - data++; - } - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Skip(unsigned long connections) -{ - LOGMETHOD("IConnectionPoint::IEnumConnections::Skip(" << (int)connections << ")"); - index += connections; - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Reset() -{ - LOGMETHOD("IConnectionPoint::IEnumConnections::Reset()"); - index = 0; - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Clone(IEnumConnections **enum_conn) -{ - LOGMETHOD("IConnectionPoint::IEnumConnections::Clone()"); - Enumerator *enumerator = new OcxObjectWrapper; - enumerator->Attach(~point); - *enum_conn = enumerator; - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::GetConnectionInterface(IID *iid) -{ - LOGMETHOD("IConnectionPoint::GetConnectionInterface()"); - *iid = guid; - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer **cpc) -{ - LOGMETHOD("IConnectionPoint::GetConnectionPointContainer()"); - *cpc = container; - if(container) - { - container->AddRef(); - return LOGRESULT(S_OK); - } - return LOGRESULT(E_FAIL); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Advise(IUnknown *ptr, DWORD *cookie) -{ - LOGMETHOD("IConnectionPoint::Advise()"); - IRef pif; - if(!cookie || !ptr || FAILED(ptr->QueryInterface(guid, pif.SetVoid()))) - return LOGRESULT(E_INVALIDARG); // required interface not found - *cookie = (free_id.IsEmpty() ? conn_map.GetCount() : free_id.Pop()); - conn_map.Add(*cookie) = pif; - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Unadvise(DWORD cookie) -{ - LOGMETHOD("IConnectionPoint::Unadvise(" << (int)cookie << ")"); - int p = conn_map.Find(cookie); - if(p < 0) - return LOGRESULT(E_INVALIDARG); - conn_map.Remove(p); - free_id.Add(cookie); - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPoint::EnumConnections(IEnumConnections **enum_conn) -{ - LOGMETHOD("IConnectionPoint::EnumConnections()"); - Enumerator *enumerator = new OcxObjectWrapper; - enumerator->Attach(this); - *enum_conn = enumerator; - return LOGRESULT(S_OK); -} - -void OcxConnectionPoint::FireEvent(int method_id, const Vector& values) -{ - LOGMETHOD("OcxConnectionPoint::FireEvent"); - int i, nargs = values.GetCount(); - Buffer args(nargs); - for(i = 0; i < nargs; i++) - { - VARIANTARG& out = args[i]; - out.vt = VT_EMPTY; - VariantCopy(&out, &ValueToVariant(values[nargs - i - 1])); - } - DISPPARAMS disp = { args, 0, (UINT)nargs, 0 }; - for(i = 0; i < conn_map.GetCount(); i++) - conn_map[i]->Invoke(method_id, IID_NULL, 0, DISPATCH_METHOD, &disp, NULL, NULL, NULL); - for(i = 0; i < nargs; i++) - VariantClear(&args[i]); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Next(unsigned long count, IConnectionPoint **data, unsigned long *fetched) -{ - LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Next(" << (int)count << ")"); - if(!point) - return LOGRESULT(E_FAIL); - if(count == 0 || !data || !fetched) - return LOGRESULT(E_INVALIDARG); - int avail = min(count, point->point_map.GetCount() - index); - if(avail <= 0) - { - *fetched = 0; - return LOGRESULT(S_OK); - } - *fetched = avail; - while(--avail >= 0) - { - *data = point->point_map[index]; - (*data)->AddRef(); - index++; - data++; - } - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Skip(unsigned long connections) -{ - LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Skip(" << (int)connections << ")"); - index += connections; - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Reset() -{ - LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Reset()"); - index = 0; - return LOGRESULT(S_OK); -} - -HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Clone(IEnumConnectionPoints **enum_conn) -{ - LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Clone()"); - Enumerator *enumerator = new OcxObjectWrapper; - enumerator->Attach(~point); - *enum_conn = enumerator; - return LOGRESULT(S_OK); -} - -OcxConnectionPointContainer::OcxConnectionPointContainer() -{ -} - -HRESULT OcxConnectionPointContainer::EnumConnectionPoints(IEnumConnectionPoints **ppEnum) -{ - LOGMETHOD("IConnectionPointContainer::EnumConnectionPoints()"); - Enumerator *enumerator = new OcxObjectWrapper; - enumerator->Attach(this); - *ppEnum = enumerator; - return LOGRESULT(S_OK); -} - -HRESULT OcxConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) -{ - Guid guid(riid); - LOGMETHOD("IConnectionPointContainer::FindConnectionPoint(" << guid << ", ppCP = " << FormatIntHex(ppCP) << ")"); - int i = point_map.Find(guid); - RLOG("point_map.Find(guid) = " << i); - if(i < 0) { - *ppCP = 0; - return LOGRESULT(CONNECT_E_NOCONNECTION); - } - (*ppCP = point_map[i])->AddRef(); - return LOGRESULT(S_OK); -} - -} - -#endif +#include + +#ifdef PLATFORM_WIN32 + +namespace Upp { + +LPOLESTR AllocString(String s) +{ + LPOLESTR p = reinterpret_cast(CoTaskMemAlloc(sizeof(OLECHAR) * (s.GetLength() + 1))), d = p; + const char *f = s; + while(*d++ = *f++) + ; + return p; +} + +OcxControl::OcxControl() +{ + ActiveX(); + view_sink_aspect = DVASPECT_CONTENT; + view_sink_advf = 0; + status = CLOSED; + stream_inited = false; + timer_shutdown = false; + extent_size = GetStdSize(); +} + +OcxControl::~OcxControl() +{ + LOGMETHOD("OcxControl::~OcxControl"); +} + +bool OcxControl::IsOcxChild() +{ + return true; +} + +LRESULT OcxControl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + LOGMETHOD("OcxControl::WindowProc"); +// RLOG("message = " << FormatIntHex(message) << ", wParam = " << FormatIntHex(wParam) << ", lParam = " << FormatIntHex(lParam)); + if(message == WM_GETDLGCODE) + return DLGC_WANTALLKEYS | DLGC_WANTARROWS | DLGC_WANTMESSAGE; + LRESULT res = Ctrl::WindowProc(message, wParam, lParam); + return res; +} + +bool OcxControl::Open(HWND parent) // parent = 0 - create forged control +{ + LOGMETHOD("OcxControl::Open"); +// if(!IsForged()) + ctrl_rect = GetRect(); + if(IsOpen()) + Ctrl::Close(); + if(parent && IsChild()) + Remove(); + status = CLOSED; + +// noproc = true; +// visible |= !parent; + Rect rc = ctrl_rect; + if(IsNull(rc)) + rc = Rect(0, 0, 0, 0); + if(!parent) + { // move window away from screen in forged mode + rc.Offset(-30000 - rc.left, -30000 - rc.top); + SetRect(rc); + } +// view.SetRectEmpty(); + + Create(parent, (IsEnabled() ? 0 : WS_DISABLED) | (parent ? WS_CHILD : WS_POPUP) | WS_VISIBLE, + (parent ? 0 : WS_EX_TOOLWINDOW), false, SW_HIDE, false); + + Show(); + +/* wnd = &stdwnd; + fullrefresh = false; + dword style = parent ? WS_CHILD : WS_POPUP, exstyle = WS_EX_TOOLWINDOW; + if(!enabled) style |= WS_DISABLED; + noproc = true; + visible |= !parent; + Rect rc = GetRect(); + if(!parent) + { // move window away from screen in forged mode + rc.OffsetRect(-30000 - rc.left, -30000 - rc.top); + SetRect(rc); + } + view.SetRectEmpty(); + wnd->CreateEx(exstyle, CtrlWindowClass(), +#ifdef _DEBUG + Name(), +#else + NULL, +#endif + style, + rc.left, rc.top, rc.Width(), rc.Height(), + parent ? parent : 0, 0, 0); + + if(!wnd->m_hWnd) + return false; + + type = POPUP; + noproc = false; + + for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) + reinterpret_cast(q)->_CreateChild(); + + if(visible) + ShowWindow(GetHWND(), SW_SHOWNA); +// SetMnemonic((byte) hotchar); + + RefreshLayout(); + RefreshPos(); + Refresh(); + CancelMode(); + CreateInit(); + move = true; +*/ + status = ACTIVE; //(parent ? ACTIVE : FORGED); + return true; +} + +void OcxControl::Serialize(Stream& stream) +{ + int version = 1; + SerializePos(stream); +} + +void OcxControl::SerializePos(Stream& stream) +{ + int version = 1; + stream / version; + Rect rc; + if(stream.IsStoring()) + rc = GetRect(); + stream % rc; + if(stream.IsLoading()) + SetRect(rc); +} + +const WCHAR OcxControl::data_stream_name[] = L"data"; + +HRESULT OcxControl::SetClientSite(IOleClientSite *site) +{ + LOGMETHOD("IOleObject::SetClientSite()"); + in_place_site = site; + client_site = site; + if(GetRect().IsEmpty()) { + LOG("Setting up default control rect..."); + SetRect(GetStdSize()); + } + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetClientSite(IOleClientSite **res) +{ + LOGMETHOD("IOleObject::GetClientSite"); + if(*res = ~client_site) + client_site->AddRef(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::SetHostNames(LPCOLESTR app_name, LPCOLESTR doc_name) +{ + LOGMETHOD("IOleObject::SetHostNames"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::Close(dword save_option) +{ + LOGMETHOD("IOleObject::Close"); + InPlaceDeactivate(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::SetMoniker(dword which, IMoniker *moniker) +{ + LOGMETHOD("IOleObject::SetMoniker"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetMoniker(dword assign, dword which, IMoniker **moniker) +{ + LOGMETHOD("IOleObject::GetMoniker"); + *moniker = 0; + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::InitFromData(IDataObject *data, BOOL creation, dword) +{ + LOGMETHOD("IOleObject::InitFromData"); + return LOGRESULT(S_FALSE); +} + +HRESULT OcxControl::GetClipboardData(dword, IDataObject **data) +{ + LOGMETHOD("IOleObject::GetClipboardData"); + *data = 0; + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::DoVerb(long verb, MSG *msg, IOleClientSite *active_site, + long index, HWND parent, const RECT *rc) +{ + LOGMETHOD("IOleObject::DoVerb"); + switch(verb) + { + case OLEIVERB_PRIMARY: return DoVerbPrimary(); + case OLEIVERB_SHOW: return DoVerbShow(); + case OLEIVERB_INPLACEACTIVATE: return DoVerbInPlaceActivate(); + case OLEIVERB_UIACTIVATE: return DoVerbUIActivate(); + case OLEIVERB_HIDE: return DoVerbHide(); + case OLEIVERB_OPEN: return DoVerbOpen(); + case OLEIVERB_DISCARDUNDOSTATE: return DoVerbDiscardUndo(); + case OLEIVERB_PROPERTIES: return DoVerbProperties(); + default: return OLEOBJ_S_INVALIDVERB; + } +} + +HRESULT OcxControl::EnumVerbs(IEnumOLEVERB **verbs) +{ + LOGMETHOD("IOleObject::EnumVerbs"); + *verbs = 0; + return LOGRESULT(OLEOBJ_E_NOVERBS); +} + +HRESULT OcxControl::Update() +{ + LOGMETHOD("IOleObject::Update"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::IsUpToDate() +{ + LOGMETHOD("IOleObject::IsUpToDate"); + return LOGRESULT(MK_E_UNAVAILABLE); +} + +HRESULT OcxControl::GetUserClassID(GUID *guid) +{ + LOGMETHOD("IOleObject::GetUserClassID"); + ASSERT(ocx_info); + *guid = ocx_info->GetCoClassGUID(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetUserType(dword form, LPOLESTR *type) +{ +// __asm int 3 + LOGMETHOD("IOleObject::GetUserType"); + ASSERT(ocx_info); + *type = AllocString(ocx_info->GetName()); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::SetExtent(dword aspect, SIZEL *hi_size) +{ + LOGMETHOD("IOleObject::SetExtent(" << hi_size->cx << ", " << hi_size->cy << ")"); + if(aspect == DVASPECT_CONTENT) { + extent_size = min(FromHiMetric(*hi_size), GetMaxSize()); + OCXLOG("Ctrl size = " << extent_size); + SetRect(Rect(GetRect().TopLeft(), extent_size)); + } + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetExtent(dword aspect, SIZEL *size) +{ + LOGMETHOD("IOleObject::GetExtent"); + if(aspect == DVASPECT_CONTENT) { + *size = ToHiMetric(extent_size); + return LOGRESULT(S_OK); + } + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::Advise(IAdviseSink *sink, dword *connection) +{ + LOGMETHOD("IOleObject::Advise"); + if(!sink || !connection) + return E_INVALIDARG; + *connection = advise_sinks.Add(sink); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::Unadvise(dword connection) +{ + LOGMETHOD("IOleObject::Unadvise"); + return LOGRESULT(advise_sinks.Remove(connection) ? S_OK : E_INVALIDARG); +} + +HRESULT OcxControl::EnumAdvise(IEnumSTATDATA **sink_enum) +{ + LOGMETHOD("IOleObject::EnumAdvise"); + *sink_enum = 0; + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::GetMiscStatus(dword aspect, dword *st) +{ + LOGMETHOD("IOleObject::GetMiscStatus"); + *st = OLEMISC_RECOMPOSEONRESIZE + | OLEMISC_INSIDEOUT + | OLEMISC_ACTIVATEWHENVISIBLE; + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::SetColorScheme(LOGPALETTE *logpal) +{ + LOGMETHOD("IOleObject::SetColorScheme"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetClassID(GUID *guid) +{ + LOGMETHOD("IPersist::GetClassID"); + ASSERT(ocx_info); + *guid = ocx_info->GetCoClassGUID(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::IsDirty() +{ + LOGMETHOD("IPersistStorage::IsDirty"); + return LOGRESULT(IsModified() ? S_OK : S_FALSE); +} + +HRESULT OcxControl::InitNew(IStorage *stg) +{ + LOGMETHOD("IPersistStorage::InitNew"); + if(!stg) + return LOGRESULT(E_INVALIDARG); + HRESULT hr; + IStreamPtr stream; + if(FAILED(hr = stg->CreateStream(data_stream_name, + STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream))) + return LOGRESULT(hr); + return InitNew(); // call IPersistStream::InitNew +} + +HRESULT OcxControl::Load(IStorage *stg) +{ + LOGMETHOD("IPersistStorage::Load"); + if(!stg) + return LOGRESULT(E_INVALIDARG); + HRESULT hr; + IStreamPtr stream; + if(FAILED(hr = stg->OpenStream(data_stream_name, 0, + STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stream))) + return LOGRESULT(hr); + return Load(stream); // delegate load to IPersistStream::Load +} + +HRESULT OcxControl::Save(IStorage *stg, BOOL same_as_load) +{ + LOGMETHOD("IPersistStorage::Save(" << (same_as_load ? "same as load" : "full save") << ')'); + if(!stg) + return LOGRESULT(E_INVALIDARG); + HRESULT hr; +#if LOG_PERSIST >= 1 + STATSTG stat; + Zero(stat); + if(FAILED(hr = stg->Stat(&stat, STATFLAG_NONAME))) + return LOGRESULT(hr); + OCXLOG(NFormat("Storage flags = %08x\r\n", (int)stat.grfMode)); + OCXLOG("CLSID = " << GetCoClassName(stat.clsid) << " - " << Format(stat.clsid)); +#endif + IStreamPtr stream; + if(FAILED(hr = stg->CreateStream(data_stream_name, + STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream))) + return LOGRESULT(hr); + + if(FAILED(hr = Save(stream, true))) + return hr; + +#if LOG_PERSIST >= 1 + ULARGE_INTEGER ul; + if(FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_END, &ul))) + return hr; + OCXLOG("- stream size = " << ul.LowPart); +#endif + + return S_OK; +} + +HRESULT OcxControl::SaveCompleted(IStorage *stg) +{ + LOGMETHOD("IPersistStorage::SaveCompleted"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::HandsOffStorage() +{ + LOGMETHOD("IPersistStorage::HandsOffStorage"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::Load(IStream *stream) +{ + LOGMETHOD("IPersistStreamInit::Load"); + if(stream_inited) + return LOGRESULT(E_UNEXPECTED); +#if LOG_PERSIST >= 1 + ULARGE_INTEGER old_pos, len; + HRESULT hr; + if(FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_CUR, &old_pos)) + || FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_END, &len)) + || FAILED(hr = stream->Seek(reinterpret_cast(old_pos), STREAM_SEEK_SET, 0))) + return hr; + OCXLOG("- stream size = " << len.LowPart); +#endif + OleStream os(stream); + if(!os.IsOpen() || os.IsError()) + { + LOGPERSIST("- internal error creating OleStream"); + return LOGRESULT(E_FAIL); + } + os.SetLoading(); + Serialize(os); + ClearModify(); + os.Close(); + stream_inited = true; + if(os.IsError()) + return LOGRESULT(os.GetError() >= 0 ? os.GetError() : E_FAIL); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::Save(IStream *stream, BOOL clear_dirty) +{ + LOGMETHOD("IPersistStreamInit::Save"); + OleStream os(stream); + if(!os.IsOpen() || os.IsError()) + { + LOGPERSIST("- internal error creating OleStream"); + return LOGRESULT(E_FAIL); + } + os.SetStoring(); + Serialize(os); + os.Close(); + if(os.IsError()) + return LOGRESULT(os.GetError() >= 0 ? os.GetError() : E_FAIL); + if(clear_dirty) + ClearModify(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetSizeMax(ULARGE_INTEGER *size) +{ + LOGMETHOD("IPersistStreamInit::GetSizeMax"); + if(!size) + return LOGRESULT(E_INVALIDARG); + SizeStream ss; + Serialize(ss); + *size = AsULarge(ss.GetSize()); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::InitNew() +{ + LOGMETHOD("IPersistStreamInit::InitNew"); + if(stream_inited) + return LOGRESULT(E_UNEXPECTED); + SetRect(Rect(Point(0, 0), GetStdSize())); + SetData(Value()); // default clear algorithm + ClearModify(); + stream_inited = true; + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetData(FORMATETC *format, STGMEDIUM *medium) +{ + LOGMETHOD("IDataObject::GetData"); + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::GetDataHere(FORMATETC *format, STGMEDIUM *medium) +{ + LOGMETHOD("IDataObject::GetDataHere"); + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::QueryGetData(FORMATETC *format) +{ + LOGMETHOD("IDataObject::QueryGetData"); + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::GetCanonicalFormatEtc(FORMATETC *in, FORMATETC *out) +{ + LOGMETHOD("IDataObject::GetCanonicalFormatEtc"); + *out = *in; + out->ptd = 0; + return LOGRESULT(DATA_S_SAMEFORMATETC); +} + +HRESULT OcxControl::SetData(FORMATETC *format, STGMEDIUM *medium, BOOL free) +{ + LOGMETHOD("IDataObject::SetData"); + if(free) + ReleaseStgMedium(medium); + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::EnumFormatEtc(dword dir, IEnumFORMATETC **enumerator) +{ + LOGMETHOD("IDataObject::EnumFormatEtc"); + *enumerator = 0; + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::DAdvise(FORMATETC *format, dword advf, IAdviseSink *sink, dword *connection) +{ + LOGMETHOD("IDataObject::DAdvise"); + *connection = advise_sinks.Add(sink); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::DUnadvise(dword connection) +{ + LOGMETHOD("IDataObject::DUnadvise"); + return LOGRESULT(advise_sinks.Remove(connection) ? S_OK : E_FAIL); +} + +HRESULT OcxControl::EnumDAdvise(IEnumSTATDATA **enumerator) +{ + LOGMETHOD("IDataObject::EnumDAdvise"); + *enumerator = 0; + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::Draw(DWORD aspect, LONG index, void *aspectinfo, + DVTARGETDEVICE *device, HDC target, HDC draw_dc, + const RECTL *bounds, const RECTL *wbounds, + BOOL (STDMETHODCALLTYPE *progress)(ULONG_PTR dwContinue), ULONG_PTR arg) +{ + LOGMETHOD("IViewObject::Draw"); + if(aspect != DVASPECT_CONTENT) + return DV_E_DVASPECT; +// if(IsClosed() && !CreateControl(0)) // create forged control to make paint routines work +// return E_FAIL; + Rect rc(GetSize()); + if(bounds) + { + rc.left = bounds->left; + rc.top = bounds->top; + rc.right = bounds->right; + rc.bottom = bounds->bottom; + LPtoDP(draw_dc, reinterpret_cast(&rc), 2); + } +// if(IsForged()) +// SetCtrlRect(rc); + + Point worg, vorg; + Size wext, vext; + SetWindowOrgEx(draw_dc, 0, 0, worg); + SetWindowExtEx(draw_dc, 1, 1, wext); + SetViewportOrgEx(draw_dc, 0, 0, vorg); + SetViewportExtEx(draw_dc, 1, 1, vext); + int old_mode = SetMapMode(draw_dc, MM_TEXT); + + SystemDraw draw(draw_dc); + draw.Offset(rc.TopLeft()); + DrawCtrl(draw); + draw.End(); + + SetMapMode(draw_dc, old_mode); + SetWindowOrgEx(draw_dc, worg.x, worg.y, 0); + SetWindowExtEx(draw_dc, wext.cx, wext.cy, 0); + SetViewportOrgEx(draw_dc, vorg.x, vorg.y, 0); + SetViewportExtEx(draw_dc, vext.cx, vext.cy, 0); + +// DUMP(GetMapMode(draw_dc)); +// DUMP(::GetWindow(draw_dc)); +// DUMP(GetViewport(draw_dc)); +// ::Draw draw(draw_dc); +// draw.DrawRect(rc, Yellow); +// draw.Clipoff(rc); +// CtrlPaint(draw); +// draw.End(); + + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetColorSet(dword aspect, long index, void *aspectinfo, + DVTARGETDEVICE *device, HDC target, LOGPALETTE **palette) +{ + LOGMETHOD("IViewObject::GetColorSet"); + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::Freeze(dword aspect, long index, void *aspectinfo, dword *freeze_key) +{ + LOGMETHOD("IViewObject::Freeze"); + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::Unfreeze(dword freeze_key) +{ + LOGMETHOD("IViewObject::Unfreeze"); + return LOGRESULT(E_NOTIMPL); +} + +HRESULT OcxControl::SetAdvise(dword aspect, dword advf, IAdviseSink *sink) +{ + LOGMETHOD("IViewObject::SetAdvise(aspect = " << aspect << ", advf = " << advf << ")"); + view_sink_aspect = aspect; + view_sink_advf = advf; + view_sink = sink; + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetAdvise(dword *aspect, dword *advf, IAdviseSink **sink) +{ + LOGMETHOD("IViewObject::GetAdvise"); + if(aspect) *aspect = view_sink_aspect; + if(advf) *advf = view_sink_advf; + if(sink && (*sink = ~view_sink)) + (**sink).AddRef(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetExtent(dword aspect, long index, DVTARGETDEVICE *device, SIZEL *size) +{ + LOGMETHOD("IViewObject2::GetExtent"); + *size = GetRect().Size(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetRect(dword aspect, RECTL *rc) +{ + LOGMETHOD("IViewObjectEx::GetRect(aspect = " << aspect << ")"); + if(aspect != DVASPECT_CONTENT) + return E_NOTIMPL; + if(!rc) + return E_INVALIDARG; + *rc = ToRectL(GetRect()); + return S_OK; +} + +HRESULT OcxControl::GetViewStatus(dword *status) +{ + LOGMETHOD("IViewObjectEx::GetViewStatus"); + *status = (IsTransparent() ? 0 : DVASPECT_OPAQUE); + return S_OK; +} + +HRESULT OcxControl::QueryHitPoint(dword aspect, const RECT *bounds, POINT pos, long close_hint, dword *result) +{ + LOGMETHOD("IViewObjectEx::QueryHitPoint"); + if(!result) + return E_INVALIDARG; + if(aspect != DVASPECT_CONTENT) + return E_FAIL; + *result = PtInRect(bounds, pos) ? HITRESULT_HIT : HITRESULT_OUTSIDE; + return S_OK; +} + +HRESULT OcxControl::QueryHitRect(dword aspect, const RECT *bounds, const RECT *rc, long close_hint, dword *result) +{ + LOGMETHOD("IViewObjectEx::QueryHitRect"); + if(!result) + return E_INVALIDARG; + if(aspect != DVASPECT_CONTENT) + return E_FAIL; + *result = Rect(*bounds).Contains(Rect(*rc)) ? HITRESULT_HIT : HITRESULT_OUTSIDE; + return S_OK; +} + +HRESULT OcxControl::GetNaturalExtent(dword aspect, long index, DVTARGETDEVICE *ptd, HDC tdc, DVEXTENTINFO *extinfo, SIZEL *psize) +{ + LOGMETHOD("IViewObjectEx::GetNaturalExtent"); + if(aspect != DVASPECT_CONTENT) + return E_FAIL; + if(psize) + *psize = GetRect().Size(); + return S_OK; +} + +HRESULT OcxControl::GetWindow(HWND *hwnd) +{ + LOGMETHOD("IOleWindow::GetWindow"); + if(!hwnd) + return LOGRESULT(E_INVALIDARG); + return LOGRESULT((*hwnd = GetHWND()) ? S_OK : E_FAIL); +} + +HRESULT OcxControl::ContextSensitiveHelp(BOOL enter_mode) +{ + LOGMETHOD("IOleWindow::ContextSensitiveHelp"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::InPlaceDeactivate() +{ + LOGMETHOD("IOleInPlaceObject::InPlaceDeactivate"); + if(!IsActive()) + return LOGRESULT(S_OK); + UIDeactivate(); + if(!!in_place_site) + in_place_site->OnInPlaceDeactivate(); + if(IsOpen() && !IsChild()) + Ctrl::Close(); + in_place_site.Clear(); + client_site.Clear(); + status = CLOSED; + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::UIDeactivate() +{ + LOGMETHOD("IOleInPlaceObject::UIDeactivate"); + + if(!IsUIActive()) + return LOGRESULT(S_OK); // no work needed when not UI active + + if(!in_place_site) + return LOGRESULT(E_FAIL); + + SetActiveObject(false); + return LOGRESULT(in_place_site->OnUIDeactivate(false)); +} + +HRESULT OcxControl::SetObjectRects(const RECT *pos, const RECT *clip) +{ + LOGMETHOD("IOleInPlaceObject::SetObjectRects(pos = " << Rect(*pos) << ", clip = " << Rect(*clip) << ")"); + if(!pos || !clip) + return LOGRESULT(E_INVALIDARG); + Rect rc(Point(pos->left, pos->top), extent_size); + OCXLOG("-> Ctrl rc = " << rc << " (extent size = " << extent_size << ")"); + SetRect(rc); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::ReactivateAndUndo() +{ + LOGMETHOD("IOleInPlaceObject::ReactivateAndUndo"); + if(!IsActive()) + return OLE_E_NOT_INPLACEACTIVE; + return DoVerbUIActivate(); +} + +HRESULT OcxControl::TranslateAccelerator(MSG *msg) +{ + LOGMETHOD("IOleInPlaceObject::TranslateAccelerator"); + dword keycode = 0; + if(msg->message == WM_KEYDOWN) + keycode = KEYtoK((dword)msg->wParam); + else if(msg->message == WM_KEYUP) + keycode = KEYtoK((dword)msg->wParam) | K_KEYUP; + else if(msg->message == WM_SYSKEYDOWN && (msg->lParam & 0x20000000)) + keycode = KEYtoK((dword)msg->wParam); + else if(msg->message == WM_SYSKEYUP && (msg->lParam & 0x20000000)) + keycode = KEYtoK((dword)msg->wParam) | K_KEYUP; + else if(msg->message == WM_CHAR) + keycode = (dword)msg->wParam; + if(keycode == 0 || !IsActive() || !IsEnabled() || !IsVisible()) + return LOGRESULT(S_FALSE); + + return LOGRESULT(HotKey(keycode) ? S_OK : S_FALSE); +} + +HRESULT OcxControl::OnFrameWindowActivate(BOOL activate) +{ + LOGMETHOD("IOleInPlaceObject::OnFrameWindowActivate"); + Refresh(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::OnDocWindowActivate(BOOL activate) +{ + LOGMETHOD("IOleInPlaceObject::OnDocWindowActivate"); + Refresh(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::ResizeBorder(const RECT *border, IOleInPlaceUIWindow *ui, BOOL frame) +{ + LOGMETHOD("IOleInPlaceObject::ResizeBorder"); + Refresh(); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::EnableModeless(BOOL enable) +{ + LOGMETHOD("IOleInPlaceObject::EnableModeless"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::GetControlInfo(CONTROLINFO *cinfo) +{ + LOGMETHOD("IOleControl::GetControlInfo"); + if(!cinfo) + return LOGRESULT(E_INVALIDARG); + cinfo->hAccel = 0; + cinfo->cAccel = 0; + cinfo->dwFlags = 0; // by default eat neither Return nor Escape + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::OnMnemonic(MSG *msg) +{ + LOGMETHOD("IOleControl::OnMnemonic"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::OnAmbientPropertyChange(DISPID dispid) +{ + LOGMETHOD("IOleControl::OnAmbientPropertyChange"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::FreezeEvents(BOOL freeze) +{ + LOGMETHOD("IOleControl::FreezeEvents(" << (freeze ? "on" : "off") << ")"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::DoVerbPrimary() +{ + LOGMETHOD("DoVerbPrimary"); + return LOGRESULT(ShowControl(true)); +} + +HRESULT OcxControl::DoVerbShow() +{ + LOGMETHOD("DoVerbShow"); + return LOGRESULT(ShowControl(false)); +} + +HRESULT OcxControl::ShowControl(bool ui_activate) +{ + LOGMETHOD("OcxControl::ShowControl(" << (ui_activate ? "UI activate" : "") << ")"); + + if(!in_place_site) + return LOGRESULT(E_FAIL); + + HRESULT hr; + + if(!IsActive()) + { + HWND parent = 0; + + if((hr = in_place_site->CanInPlaceActivate()) != S_OK + || FAILED(hr = in_place_site->OnInPlaceActivate()) + || FAILED(hr = in_place_site->GetWindow(&parent))) + return LOGRESULT(hr); + + if(!parent || !::IsWindow(parent)) + return E_FAIL; + + UpdateControlRect(); + + if(!Open(parent)) + return LOGRESULT(E_FAIL); + + Show(); + Enable(); + +// todo: fire view change +// if(view_sink) +// { +// view_sink->OnViewChange(DVASPECT_CONTENT, -1); +// if(view_sink_advf & ADVF_ONLYONCE) +// view_sink = 0; +// } +// + } + + if(ui_activate && !IsUIActive() && SUCCEEDED(in_place_site->OnUIActivate())) + status = UIACTIVE; + + Show(); + Enable(); + if(!HasFocusDeep() && !SetWantFocus() && GetFirstChild()) + IterateFocusForward(GetFirstChild(), this); + SetActiveObject(true); + + return LOGRESULT(client_site->ShowObject()); +} + +HRESULT OcxControl::DoVerbInPlaceActivate() +{ + LOGMETHOD("DoVerbInPlaceActivate"); + return LOGRESULT(ShowControl(false)); +} + +HRESULT OcxControl::DoVerbUIActivate() +{ + LOGMETHOD("DoVerbUIActivate"); + return LOGRESULT(ShowControl(true)); +} + +HRESULT OcxControl::DoVerbHide() +{ + LOGMETHOD("DoVerbHide"); + Hide(); +// Close(false); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::DoVerbOpen() +{ + LOGMETHOD("DoVerbOpen"); + return LOGRESULT(ShowControl(false)); +} + +HRESULT OcxControl::DoVerbDiscardUndo() +{ + LOGMETHOD("DoVerbDiscardUndo"); + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::DoVerbProperties() +{ + LOGMETHOD("DoVerbProperties"); + return LOGRESULT(S_OK); +} + +void OcxControl::UpdateControlRect() +{ + LOGMETHOD("OcxControl::UpdateControlRect"); + + if(!in_place_site) + return; + + IOleInPlaceFramePtr frame; + IOleInPlaceUIWindowPtr ui_window; + OLEINPLACEFRAMEINFO frame_info = { sizeof(frame_info) }; + Rect rc, clip; + if(FAILED(in_place_site->GetWindowContext(&frame, &ui_window, rc, clip, &frame_info))) + return; + + OCXLOG("Control rect: " << rc << ", clip = " << clip); + SetRect(rc); +} + +void OcxControl::SetActiveObject(bool set) +{ + LOGMETHOD("OcxControl::SetActiveObject"); + if(!in_place_site) + return; + + IRef frame; + IRef ui_window; + OLEINPLACEFRAMEINFO frame_info = { sizeof(frame_info) }; + Rect rc, clip; + if(FAILED(in_place_site->GetWindowContext(frame.Set(), ui_window.Set(), rc, clip, &frame_info))) + return; + + if(!!frame) { + frame->SetActiveObject(set ? this : 0, 0); + if(set) + frame->SetBorderSpace(0); + } + if(!!ui_window) { + ui_window->SetActiveObject(set ? this : 0, 0); + if(set) + ui_window->SetBorderSpace(0); + } +} + +void OcxControl::RefreshSink() +{ + LOGMETHOD("OcxControl::RefreshSink"); + if(!!view_sink) + view_sink->OnViewChange(DVASPECT_CONTENT, -1); +} + +HRESULT OcxControl::GetActivationPolicy(DWORD *pdwPolicy) +{ + LOGMETHOD("IPointerInactive::GetActivationPolicy"); + *pdwPolicy = POINTERINACTIVE_ACTIVATEONENTRY; + return LOGRESULT(S_OK); +} + +HRESULT OcxControl::OnInactiveMouseMove(LPCRECT pRectBounds, LONG x, LONG y, DWORD grfKeyState) +{ + LOGMETHOD("IPointerInactive::OnInactiveMouseMove"); + return S_OK; +} + +HRESULT OcxControl::OnInactiveSetCursor(LPCRECT pRectBounds, LONG x, LONG y, DWORD dwMouseMsg, BOOL fSetAlways) +{ + LOGMETHOD("IPointerInactive::InactiveSetCursor"); + return S_OK; +} + +HRESULT OcxRunnableControl::GetRunningClass(GUID *clsid) +{ + LOGMETHOD("IRunnableObject::GetRunningClass"); + *clsid = __uuidof(0); + return LOGRESULT(E_UNEXPECTED); +} + +HRESULT OcxRunnableControl::Run(LPBC ctx) +{ + LOGMETHOD("IRunnableObject::Run"); + return LOGRESULT(S_OK); +} + +BOOL OcxRunnableControl::IsRunning() +{ + LOGMETHOD("IRunnableObject::IsRunning"); + return true; +} + +HRESULT OcxRunnableControl::LockRunning(BOOL lock, BOOL last_unlock_closes) +{ + LOGMETHOD("IRunnableObject::LockRunning"); + return LOGRESULT(S_OK); +} + +HRESULT OcxRunnableControl::SetContainedObject(BOOL contained) +{ + LOGMETHOD("IRunnableObject::SetContainedObject"); + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Next(unsigned long count, CONNECTDATA *data, unsigned long *fetched) +{ + LOGMETHOD("IConnectionPoint::IEnumConnections::Next(" << (int)count << ")"); + if(!point) + return LOGRESULT(E_FAIL); + if(count == 0 || !data || !fetched) + return LOGRESULT(E_INVALIDARG); + int avail = min(count, point->conn_map.GetCount() - index); + if(avail <= 0) + { + *fetched = 0; + return LOGRESULT(S_OK); + } + *fetched = avail; + while(--avail >= 0) + { + data->pUnk = point->conn_map[index].AddRef(); + data->dwCookie = point->conn_map.GetKey(index); + index++; + data++; + } + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Skip(unsigned long connections) +{ + LOGMETHOD("IConnectionPoint::IEnumConnections::Skip(" << (int)connections << ")"); + index += connections; + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Reset() +{ + LOGMETHOD("IConnectionPoint::IEnumConnections::Reset()"); + index = 0; + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Clone(IEnumConnections **enum_conn) +{ + LOGMETHOD("IConnectionPoint::IEnumConnections::Clone()"); + Enumerator *enumerator = new OcxObjectWrapper; + enumerator->Attach(~point); + *enum_conn = enumerator; + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::GetConnectionInterface(IID *iid) +{ + LOGMETHOD("IConnectionPoint::GetConnectionInterface()"); + *iid = guid; + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer **cpc) +{ + LOGMETHOD("IConnectionPoint::GetConnectionPointContainer()"); + *cpc = container; + if(container) + { + container->AddRef(); + return LOGRESULT(S_OK); + } + return LOGRESULT(E_FAIL); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Advise(IUnknown *ptr, DWORD *cookie) +{ + LOGMETHOD("IConnectionPoint::Advise()"); + IRef pif; + if(!cookie || !ptr || FAILED(ptr->QueryInterface(guid, pif.SetVoid()))) + return LOGRESULT(E_INVALIDARG); // required interface not found + *cookie = (free_id.IsEmpty() ? conn_map.GetCount() : free_id.Pop()); + conn_map.Add(*cookie) = pif; + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Unadvise(DWORD cookie) +{ + LOGMETHOD("IConnectionPoint::Unadvise(" << (int)cookie << ")"); + int p = conn_map.Find(cookie); + if(p < 0) + return LOGRESULT(E_INVALIDARG); + conn_map.Remove(p); + free_id.Add(cookie); + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPoint::EnumConnections(IEnumConnections **enum_conn) +{ + LOGMETHOD("IConnectionPoint::EnumConnections()"); + Enumerator *enumerator = new OcxObjectWrapper; + enumerator->Attach(this); + *enum_conn = enumerator; + return LOGRESULT(S_OK); +} + +void OcxConnectionPoint::FireEvent(int method_id, const Vector& values) +{ + LOGMETHOD("OcxConnectionPoint::FireEvent"); + int i, nargs = values.GetCount(); + Buffer args(nargs); + for(i = 0; i < nargs; i++) + { + VARIANTARG& out = args[i]; + out.vt = VT_EMPTY; + VariantCopy(&out, &ValueToVariant(values[nargs - i - 1])); + } + DISPPARAMS disp = { args, 0, (UINT)nargs, 0 }; + for(i = 0; i < conn_map.GetCount(); i++) + conn_map[i]->Invoke(method_id, IID_NULL, 0, DISPATCH_METHOD, &disp, NULL, NULL, NULL); + for(i = 0; i < nargs; i++) + VariantClear(&args[i]); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Next(unsigned long count, IConnectionPoint **data, unsigned long *fetched) +{ + LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Next(" << (int)count << ")"); + if(!point) + return LOGRESULT(E_FAIL); + if(count == 0 || !data || !fetched) + return LOGRESULT(E_INVALIDARG); + int avail = min(count, point->point_map.GetCount() - index); + if(avail <= 0) + { + *fetched = 0; + return LOGRESULT(S_OK); + } + *fetched = avail; + while(--avail >= 0) + { + *data = point->point_map[index]; + (*data)->AddRef(); + index++; + data++; + } + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Skip(unsigned long connections) +{ + LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Skip(" << (int)connections << ")"); + index += connections; + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Reset() +{ + LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Reset()"); + index = 0; + return LOGRESULT(S_OK); +} + +HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Clone(IEnumConnectionPoints **enum_conn) +{ + LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Clone()"); + Enumerator *enumerator = new OcxObjectWrapper; + enumerator->Attach(~point); + *enum_conn = enumerator; + return LOGRESULT(S_OK); +} + +OcxConnectionPointContainer::OcxConnectionPointContainer() +{ +} + +HRESULT OcxConnectionPointContainer::EnumConnectionPoints(IEnumConnectionPoints **ppEnum) +{ + LOGMETHOD("IConnectionPointContainer::EnumConnectionPoints()"); + Enumerator *enumerator = new OcxObjectWrapper; + enumerator->Attach(this); + *ppEnum = enumerator; + return LOGRESULT(S_OK); +} + +HRESULT OcxConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) +{ + Guid guid(riid); + LOGMETHOD("IConnectionPointContainer::FindConnectionPoint(" << guid << ", ppCP = " << FormatIntHex(ppCP) << ")"); + int i = point_map.Find(guid); + RLOG("point_map.Find(guid) = " << i); + if(i < 0) { + *ppCP = 0; + return LOGRESULT(CONNECT_E_NOCONNECTION); + } + (*ppCP = point_map[i])->AddRef(); + return LOGRESULT(S_OK); +} + +} + +#endif diff --git a/uppsrc/Ole/Ctrl/ocx.def b/archive/uppsrc/Ole/Ctrl/ocx.def similarity index 95% rename from uppsrc/Ole/Ctrl/ocx.def rename to archive/uppsrc/Ole/Ctrl/ocx.def index 6f15a241b..83490bc4a 100644 --- a/uppsrc/Ole/Ctrl/ocx.def +++ b/archive/uppsrc/Ole/Ctrl/ocx.def @@ -1,7 +1,7 @@ -LIBRARY "test.ocx" - -EXPORTS - DllCanUnloadNow PRIVATE - DllGetClassObject PRIVATE - DllRegisterServer PRIVATE - DllUnregisterServer PRIVATE +LIBRARY "test.ocx" + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE diff --git a/uppsrc/Ole/Ctrl/selftest.cpp b/archive/uppsrc/Ole/Ctrl/selftest.cpp similarity index 94% rename from uppsrc/Ole/Ctrl/selftest.cpp rename to archive/uppsrc/Ole/Ctrl/selftest.cpp index 6c5e358b9..7ff8cbb5a 100644 --- a/uppsrc/Ole/Ctrl/selftest.cpp +++ b/archive/uppsrc/Ole/Ctrl/selftest.cpp @@ -1,25 +1,25 @@ -#include - -#ifdef flagMAIN - -BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpReserved) -{ - switch(fdwReason) { - case DLL_PROCESS_ATTACH: { - Ctrl::InitWin32(hinstDll); - AppInitEnvironment__(); - break; - } - case DLL_PROCESS_DETACH: { - Ctrl::CloseTopCtrls(); - break; - } - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - break; - } - return true; -} - -#endif +#include + +#ifdef flagMAIN + +BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpReserved) +{ + switch(fdwReason) { + case DLL_PROCESS_ATTACH: { + Ctrl::InitWin32(hinstDll); + AppInitEnvironment__(); + break; + } + case DLL_PROCESS_DETACH: { + Ctrl::CloseTopCtrls(); + break; + } + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + } + return true; +} + +#endif diff --git a/uppsrc/Ole/Ctrl/util.cpp b/archive/uppsrc/Ole/Ctrl/util.cpp similarity index 96% rename from uppsrc/Ole/Ctrl/util.cpp rename to archive/uppsrc/Ole/Ctrl/util.cpp index 4419b89b8..079cda4c8 100644 --- a/uppsrc/Ole/Ctrl/util.cpp +++ b/archive/uppsrc/Ole/Ctrl/util.cpp @@ -1,741 +1,741 @@ -#include - -#ifdef PLATFORM_WIN32 - -#define LDUMP(x) -#define LLOG(x) - -namespace Upp { - -enum { HIMETRIC_INCH = 2540 }; // HIMETRIC units per inch - -SystemDraw& ScreenInfo(); - -Size ToHiMetric(Size pixel_size) -{ - static Size logdpi = ScreenInfo().GetSizeCaps(LOGPIXELSX, LOGPIXELSY); - return Size( - iscaleceil(pixel_size.cx, HIMETRIC_INCH, logdpi.cx), - iscaleceil(pixel_size.cy, HIMETRIC_INCH, logdpi.cy)); -} - -Size FromHiMetric(Size himetric_size) -{ - static Size logdpi = ScreenInfo().GetSizeCaps(LOGPIXELSX, LOGPIXELSY); - return Size( - iscalefloor(himetric_size.cx, logdpi.cx, HIMETRIC_INCH), - iscalefloor(himetric_size.cy, logdpi.cy, HIMETRIC_INCH)); -} - -Rect GetWindow(HDC hdc) -{ - Point pt; - Size sz; - GetWindowOrgEx(hdc, pt); - GetWindowExtEx(hdc, sz); - return Rect(pt, sz); -} - -Rect GetViewport(HDC hdc) -{ - Point pt; - Size sz; - GetViewportOrgEx(hdc, pt); - GetViewportExtEx(hdc, sz); - return Rect(pt, sz); -} - -OcxObject::OcxObject() -: ocx_info(0) -{ - inner_unknown.owner = this; - outer_unknown = NULL; -} - -int OcxObject::ExternalAddRef() -{ - if(outer_unknown) { - int res = outer_unknown->AddRef(); -#if LOG_ADDREFS - OCXLOG("OcxObject::ExternalAddRef -> outer(" << FormatIntHex(outer_unknown) << ") -> " << res); -#endif - return res; - } - return InternalAddRef(); -} - -int OcxObject::ExternalRelease() -{ - if(outer_unknown) { - int res = outer_unknown->Release(); -#if LOG_ADDREFS - // note: this might have been destructed by this time - OCXLOG("OcxObject::ExternalRelease -> outer(" << FormatIntHex(outer_unknown) << ") -> " << res); -#endif - return res; - } - return InternalRelease(); -} - -HRESULT OcxObject::ExternalQueryInterface(const GUID& iid, void **ppv) -{ - if(outer_unknown) { - HRESULT hr = outer_unknown->QueryInterface(iid, ppv); -#if LOG_QUERIES >= 2 - OCXLOG("OcxObject::ExternalQueryInterface(" << GetInterfaceName(iid) << ") -> outer(" << FormatIntHex(outer_unknown) << ") -> " << FormatIntHex(hr)); -#endif - return hr; - } - return InternalQueryInterface(iid, ppv); -} - -HRESULT OcxObject::InternalQueryInterface(const GUID& iid, void **ppv) -{ -#if LOG_QUERIES >= 2 - OCXLOG("OcxObject::InternalQueryInterface -> " << GetInterfaceName(iid)); -#endif - int i; - IUnknown *punk; - if(iid == IID_IUnknown) - punk = static_cast(&inner_unknown); - else if((i = interface_map.Find(iid)) >= 0) - punk = interface_map[i]; - else { - *ppv = 0; -#if LOG_QUERIES >= 1 - String name; - if(ocx_info) - name = ocx_info->GetName(); - else - name = ""; -#endif - LOGQUERY("\t\tcast ERROR: " << name << " -> "<< GetInterfaceName(iid) << ", " << Guid(iid)); -#if LOG_QUERIES >= 3 - OCXLOG("\tGUID = " << Format(iid)); - for(int i = 0; i < interface_map.GetCount(); i++) { - const GUID& imid = interface_map.GetKey(i); - String n = GetInterfaceName(imid); - if(n.GetLength() < 30) - n.Cat(' ', 30 - n.GetLength()); - OCXLOG("\t\t\t" << n << " - " << Format(imid)); - } -#endif - return E_NOINTERFACE; - } - punk->AddRef(); - *ppv = punk; -#if LOG_QUERIES >= 2 - String name; - if(ocx_info) - name = ocx_info->GetName(); - else - name = ""; - OCXLOG("\t\tcast OK: " << name << " -> " << GetInterfaceName(iid)); -#endif - return S_OK; -} - -HRESULT OcxObject::RawGetTypeInfo(IRef& typeinfo, unsigned tinfo, LCID lcid, ITypeInfo **ppinfo) -{ - if(tinfo != 0) - return DISP_E_BADINDEX; - if(!typeinfo) - return E_FAIL; - // currently ignore lcid - *ppinfo = typeinfo.AddRef(); - return S_OK; -} - -HRESULT OcxObject::RawGetIDsOfNames(IRef& typeinfo, REFIID riid, OLECHAR **names, unsigned cnames, LCID lcid, DISPID *dispid) -{ - if(!typeinfo) - return E_FAIL; - return typeinfo->GetIDsOfNames(names, cnames, dispid); -} - -HRESULT OcxObject::RawInvoke(IRef& typeinfo, IDispatch *dispatch, DISPID dispid, word flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, unsigned *arg_err) -{ - LOGINVOKE("IDispatch::Invoke"); - if(dispid == 0) { // convert object to dispatch value - if(!result) return E_INVALIDARG; - result->vt = VT_DISPATCH; - result->pdispVal = dispatch; - if(dispatch) dispatch->AddRef(); - return S_OK; - } - if(!typeinfo) { - LOG("dispid = " << FormatIntHex(dispid) << ": typeinfo = NULL"); - return E_FAIL; - } -#if LOG_INVOKES >= 1 - BSTR names[1] = { NULL }; - unsigned count = 0; - typeinfo->GetNames(dispid, names, 1, &count); - String name; - if(names[0]) - name = BSTRToString(names[0]); - else - name = FormatIntHex(dispid); - switch(flags) { - case DISPATCH_METHOD: name << " - method"; break; - case DISPATCH_PROPERTYGET: name << " - propget"; break; - case DISPATCH_PROPERTYPUT: name << " - propput"; break; - case DISPATCH_PROPERTYPUTREF: name << " - propputref"; break; - } - LOG("Member name: " << name); -#endif - if(!typeinfo) - return E_FAIL; - TYPEATTR *attr; - typeinfo->GetTypeAttr(&attr); - LOGINVOKE("GetTypeInfo: typekind = " << (int)attr->typekind); -// HRESULT res = typeinfo->Invoke(dispatch, dispid, flags, params, result, excep, arg_err); - HRESULT res = DispInvoke(dispatch, ~typeinfo, dispid, flags, params, result, excep, arg_err); - if(FAILED(res)) { - LLOG("failure: dispid = " << (int)dispid << ", #args = " << (int)params->cArgs - << ", #named args = " << (int)params->cNamedArgs << ", return " << FormatIntHex(result)); - for(int i = 0; i < (int)params->cArgs; i++) { - LLOG("arg[" << i << "] (vt = " << (int)params->rgvarg[i].vt << "): " << StdFormat(AsValue(params->rgvarg[i]))); - } - LLOG("#funcs = " << attr->cFuncs); - for(int i = 0; i < attr->cFuncs; i++) { - FUNCDESC *func; - typeinfo->GetFuncDesc(i, &func); - LLOG("memid = " << func->memid << ", cParams " << func->cParams - << ", cParamsOpt = " << func->cParamsOpt << ", cScodes " << func->cScodes - << ", funckind = " << (int)func->funckind << ", invkind " << (int)func->invkind - << ", flags = " << FormatIntHex(func->wFuncFlags)); - - typeinfo->ReleaseFuncDesc(func); - } - } - typeinfo->ReleaseTypeAttr(attr); - LOGINVOKE("//IDispatch::Invoke"); - return LOGRESULT(res); -} - -HRESULT OcxProvideClassInfo::GetClassInfo(ITypeInfo **info) -{ - if(!info) return E_INVALIDARG; - if(!ocx_info) { - *info = NULL; - return E_POINTER; - } - *info = ocx_info->GetCoClassTypeInfo().AddRef(); - return S_OK; -} - -HRESULT OcxProvideClassInfo::GetGUID(dword guidkind, GUID *guid) -{ - if(!guid) - return E_POINTER; - if(!ocx_info) { - *guid = __uuidof(0); - return E_NOTIMPL; - } - if(guidkind == GUIDKIND_DEFAULT_SOURCE_DISP_IID) { - *guid = ~ocx_info->GetEventGUID(); - return ocx_info->GetEventGUID().IsEmpty() ? E_UNEXPECTED : S_OK; - } - return E_INVALIDARG; -} - -OcxTypeInfo::OcxTypeInfo(const GUID& coclass_guid, /*const GUID& dispatch_guid,*/ const GUID& event_guid, - New new_fn, String name, const char* help, int ver, bool is_control) -: coclass_guid(coclass_guid), /*dispatch_guid(dispatch_guid),*/ event_guid(event_guid) -, new_fn(new_fn), name(name), help(help), ver(ver), is_control(is_control) -, object_count(0) -, refcount(1) -, lock_count(0) -#ifndef _USRDLL -, registration(0) -#endif -{ - LLOG("OcxTypeInfo ctr (" << name << ", " << Guid(coclass_guid) << ")"); - OcxTypeLib::Get().Add(*this); -} - -bool OcxTypeInfo::CanUnload() const -{ - LLOG("OcxTypeInfo::CanUnload(" << name << ", " << Guid(coclass_guid) << ")"); - LDUMP(object_count); - LDUMP(refcount); - return object_count == 0 && refcount <= 2 && lock_count <= 0; -} - -int OcxTypeInfo::IncRef() -{ - int res = InterlockedIncrement(&refcount); - LLOG("OcxTypeInfo::IncRef(" << name << " -> " << res << ")"); - return res; -} - -int OcxTypeInfo::DecRef() -{ - int res = InterlockedDecrement(&refcount); - LLOG("OcxTypeInfo::DecRef(" << name << " -> " << res << ")"); - VERIFY(res > 0); // if this throws, the factory has been over-released - return res; -} - -GLOBAL_VAR(InitProc, LateInitProc); -GLOBAL_VAR(InitProc, LateExitProc); -static bool inited = false; - -void DoLateInit() -{ - if(!inited) { - INTERLOCKED - if(!inited) { - inited = true; - if(LateInitProc()) - LateInitProc()(); - } - } -} - -void DoLateExit() -{ - if(inited) { - INTERLOCKED - if(inited) { - inited = false; - if(LateExitProc()) - LateExitProc()(); - } - } -} - -HRESULT OcxTypeInfo::CreateInstance(IUnknown *outer, REFIID iid, void **object) -{ - LLOG("OcxTypeInfo::CreateInstance(" << name << ", iid = " << Guid(iid) << ", outer = " << FormatIntHex(outer) << ")"); - if(outer && iid != IID_IUnknown) - return CLASS_E_NOAGGREGATION; - try { - DoLateInit(); - OcxObject *ocxobj = new_fn(*this); - LOGCREATE("\tnew " << name << ": " << object_count << " instances in system"); - if(outer) - ocxobj->outer_unknown = outer; - HRESULT hr = ocxobj->InternalQueryInterface(iid, object); - LOGCREATE("//OcxTypeInfo::CreateInstance -> " << FormatIntHex(hr)); - return hr; - } - catch(Exc e) { - LLOG("OcxTypeInfo::CreateInstance error: " << e); - return E_OUTOFMEMORY; - } - catch(...) { - return E_OUTOFMEMORY; - } -} - -HRESULT OcxTypeInfo::LockServer(BOOL lock) -{ - LLOG("OcxTypeInfo::LockServer(" << name << ", " << lock << ")"); - if(lock) - AtomicInc(lock_count); - else - VERIFY(AtomicDec(lock_count) >= 0); // over-unlock check - return S_OK; -} - -HRESULT OcxTypeInfo::GetLicInfo(/* [out] */ LICINFO *pLicInfo) -{ - LLOG("OcxTypeInfo::GetLicInfo(" << name << ")"); - if(!pLicInfo) - return E_INVALIDARG; - pLicInfo->fLicVerified = TRUE; - pLicInfo->fRuntimeKeyAvail = 0; - return S_OK; -} - -HRESULT OcxTypeInfo::RequestLicKey(/* [in] */ DWORD dwReserved, /* [out] */ BSTR *pBstrKey) -{ - LLOG("OcxTypeInfo::RequestLicKey(" << name << ")"); - if(!pBstrKey) return E_INVALIDARG; - *pBstrKey = 0; - return S_OK; -} - -HRESULT OcxTypeInfo::CreateInstanceLic( - /* [in] */ IUnknown *pUnkOuter, - /* [in] */ IUnknown *pUnkReserved, - /* [in] */ REFIID riid, - /* [in] */ BSTR bstrKey, - /* [iid_is][out] */ PVOID *ppvObj) -{ - LLOG("OcxTypeInfo::CreateInstanceLic(" << name << ")"); - return CreateInstance(pUnkOuter, riid, ppvObj); -} - -void OcxTypeInfo::GetDispatchTypeInfo(IRef& dest, Guid dispatch_iid) -{ - if(!dest) { - CriticalSection::Lock lock(critical); - if(!dest) - dest = OcxTypeLib::Get().GetTypeInfo(dispatch_iid); - } -} - -IRef OcxTypeInfo::GetCoClassTypeInfo() -{ - if(!coclass_info && !coclass_guid.IsEmpty()) { // oportunity lock used to initialize type info - critical.Enter(); - if(!coclass_info) - coclass_info = OcxTypeLib::Get().GetTypeInfo(coclass_guid); - critical.Leave(); - } - return coclass_info; -} - -OcxTypeLib::OcxTypeLib() -: lib_ver(1) -{ - CoInitialize(0); -} - -OcxTypeLib& OcxTypeLib::Get() -{ - static OcxTypeLib ocx; - return ocx; -} - -String OcxTypeLib::GetLibName() const -{ - if(!IsNull(lib_name)) - return lib_name; - String s = ToLower(GetFileTitle(GetModuleFileName())); - if(!IsNull(s)) - s.Set(0, ToUpper(s[0])); - return s; -} - -bool OcxTypeLib::CanUnload() const -{ - for(int i = 0; i < objects.GetCount(); i++) - if(!objects[i]->CanUnload()) { - OCXLOG("OcxTypeLib::CanUnload failed for " << objects[i]->GetName()); - return false; - } - OCXLOG("OcxTypeLib::CanUnload succeeded"); - return true; -} - -IRef OcxTypeLib::GetTypeInfo(const Guid& guid) -{ - IRef outinfo; - HRESULT hr = GetTypeLib()->GetTypeInfoOfGuid(guid, outinfo.Set()); - if(FAILED(hr)) { - LOGSYSOCX("OcxTypeLib::GetTypeInfo(" << guid << ") -> hr = " << FormatIntHex(hr)); - for(int i = 0; i < uses_libraries.GetCount(); i++) { - if(!uses_libraries[i]) { - String libname = uses_libraries.GetKey(i); - WString wlibname = libname.ToWString(); - hr = LoadTypeLib(wlibname, uses_libraries[i].Set()); - if(!uses_libraries[i]) { - LOGSYSOCX("LoadTypeLib(" << libname << ") -> hr = " << FormatIntHex(hr)); - } - else { - LOGSYSOCX("LoadTypeLib(" << uses_libraries.GetKey(i) << ") -> succeeded"); - if(IsFullPath(libname)) { - hr = RegisterTypeLib(~uses_libraries[i], const_cast(~wlibname), NULL); - LOGSYSOCX("RegisterTypeLib(" << libname << ") -> hr = " << FormatIntHex(hr)); - } - } - } - if(!!uses_libraries[i]) { - hr = uses_libraries[i]->GetTypeInfoOfGuid(guid, outinfo.Set()); - if(!!outinfo) - return outinfo; - LOGSYSOCX("GetTypeInfoOfGuid(" << uses_libraries.GetKey(i) << ") -> hr = " << FormatIntHex(hr)); - } - } - } - return outinfo; -} - -HRESULT OcxTypeLib::Register() -{ - String modname = GetModuleFileName(); - String lib_name = GetLibName(); - LOGSYSOCX("Registering library \"" << modname << '\"'); - - HRESULT hr; - IRef& typelib = GetTypeLib(); - if(!typelib) - return SELFREG_E_TYPELIB; - TLIBATTR *attr; - if(FAILED(hr = typelib->GetLibAttr(&attr))) - return hr; - String lib_guid = Guid(attr->guid); - typelib->ReleaseTLibAttr(attr); - - for(int i = 0; i < objects.GetCount(); i++) { - const OcxTypeInfo& entry = *objects[i]; - String progID = lib_name; - String verID = progID << '.' << entry.name; - verID << '.' << (entry.ver ? entry.ver : lib_ver); - String guid = entry.coclass_guid; - LOGSYSOCX("Registering object " << verID << ", CLSID = " << guid); - String clss_key = "CLSID\\" + guid; -#ifdef _USRDLL - String server = clss_key + "\\InprocServer32"; -#endif - String version; - version << lib_ver << '.' << entry.ver; - String help = entry.help; - if(IsNull(help)) { - if(!IsNull(display_name)) - help << display_name << ' '; - help << entry.name << (entry.IsControl() ? " Control " : " Object ") << version; - } - DeleteWinReg(verID, HKEY_CLASSES_ROOT); - DeleteWinReg(progID, HKEY_CLASSES_ROOT); - DeleteWinReg(clss_key, HKEY_CLASSES_ROOT); - if(!SetWinRegString(help, NULL, verID, HKEY_CLASSES_ROOT) - || !SetWinRegString(guid, NULL, verID + "\\CLSID", HKEY_CLASSES_ROOT) - || !SetWinRegString(help, NULL, progID, HKEY_CLASSES_ROOT) - || !SetWinRegString(guid, NULL, progID + "\\CLSID", HKEY_CLASSES_ROOT) - || !SetWinRegString(help, NULL, clss_key, HKEY_CLASSES_ROOT) - || !SetWinRegString(verID, NULL, clss_key + "\\ProgID", HKEY_CLASSES_ROOT) - || !SetWinRegString(progID, NULL, clss_key + "\\VersionIndependentProgID", HKEY_CLASSES_ROOT) - || !SetWinRegString(lib_guid, NULL, clss_key + "\\TypeLib", HKEY_CLASSES_ROOT) -#ifdef _USRDLL - || !SetWinRegString(modname, NULL, server, HKEY_CLASSES_ROOT) - || !SetWinRegString("Apartment", "ThreadingModel", server, HKEY_CLASSES_ROOT) -#else - || !SetWinRegString(modname, NULL, clss_key + "\\LocalServer32", HKEY_CLASSES_ROOT) - || !SetWinRegString(modname, NULL, clss_key + "\\LocalServer", HKEY_CLASSES_ROOT) - || !SetWinRegString("ole32.dll", NULL, clss_key + "\\InprocHandler32", HKEY_CLASSES_ROOT) - || !SetWinRegString("ole2.dll", NULL, clss_key + "\\InprocHandler", HKEY_CLASSES_ROOT) -#endif - || !SetWinRegString(version, NULL, clss_key + "\\Version", HKEY_CLASSES_ROOT)) - return REGDB_E_WRITEREGDB; - if(entry.IsControl()) { - if(!SetWinRegString("", NULL, clss_key + "\\Control", HKEY_CLASSES_ROOT) - || !SetWinRegString(modname + ", 1", NULL, clss_key + "\\ToolboxBitmap32", HKEY_CLASSES_ROOT) - || !SetWinRegString("", NULL, verID + "\\Insertable", HKEY_CLASSES_ROOT) - || !SetWinRegString("", NULL, progID + "\\Insertable", HKEY_CLASSES_ROOT) - || !SetWinRegString("", NULL, clss_key + "\\Insertable", HKEY_CLASSES_ROOT)) - return REGDB_E_WRITEREGDB; - } - } - -// UniStr ulib = modname; - OleBstr ulib(modname); - if(FAILED(hr = RegisterTypeLib(~typelib, (wchar_t *)~ulib, ~ulib))) - return hr; - return S_OK; -} - -HRESULT OcxTypeLib::Unregister() -{ - String lib = GetModuleFileName(); - String lib_name = GetLibName(); - LOGSYSOCX("Unregistering library \"" << lib << '\"'); - for(int i = 0; i < objects.GetCount(); i++) { - const OcxTypeInfo& entry = *objects[i]; - String progID = lib_name; - String verID = progID << '.' << entry.name; - verID << '.' << (entry.ver ? entry.ver : lib_ver); - DeleteWinReg(verID, HKEY_CLASSES_ROOT); - DeleteWinReg(progID, HKEY_CLASSES_ROOT); - DeleteWinReg("CLSID\\" + String(entry.coclass_guid), HKEY_CLASSES_ROOT); - DeleteWinReg("SOFTWARE\\Classes\\" + verID, HKEY_LOCAL_MACHINE); - } - - IRef& typelib = GetTypeLib(); - if(!typelib) - return SELFREG_E_TYPELIB; - TLIBATTR *attr; - HRESULT hr; - if(FAILED(hr = typelib->GetLibAttr(&attr))) - return hr; - hr = UnRegisterTypeLib(attr->guid, - attr->wMajorVerNum, attr->wMinorVerNum, - attr->lcid, attr->syskind); - typelib->ReleaseTLibAttr(attr); - return hr; -} - -#ifndef _USRDLL -HRESULT OcxTypeLib::RegisterObjects() -{ - for(int i = 0; i < objects.GetCount(); i++) { - OcxTypeInfo& entry = *objects[i]; - HRESULT hr; - if(FAILED(hr = CoRegisterClassObject(entry.GetCoClassGUID(), &entry, - CLSCTX_SERVER, REGCLS_MULTIPLEUSE, &entry.registration))) { - RevokeObjects(); - return hr; - } - } - return S_OK; -} -#endif - -#ifndef _USRDLL -void OcxTypeLib::RevokeObjects() -{ - for(int i = 0; i < objects.GetCount(); i++) { - OcxTypeInfo& entry = *objects[i]; - if(entry.registration) { - CoRevokeClassObject(entry.registration); - entry.registration = 0; - } - } -} -#endif - -HRESULT OcxTypeLib::GetFactory(REFCLSID rclsid, REFIID iid, void **ppv) -{ - Guid clsid = rclsid; - LOGSYSOCX("OcxTypeLib::GetFactory(clsid = " << clsid << ", iid = " << Guid(iid) << ")"); - LLOG("#ocx_init = " << ocx_init.GetCount()); - - for(int i = 0; i < ocx_init.GetCount(); i++) - ocx_init[i](); - ocx_init.Clear(); - - LLOG("#objects = " << objects.GetCount()); - for(int i = 0; i < objects.GetCount(); i++) - LLOG("object[" << i << "] = " << Guid(objects.GetKey(i))); - - *ppv = 0; - int f = objects.Find(clsid); - if(f < 0) - return CLASS_E_CLASSNOTAVAILABLE; - OcxTypeInfo *entry = objects[f]; - HRESULT res = entry->QueryInterface(iid, ppv); - LOGSYSOCX("//OcxTypeLib::GetFactory -> " << FormatIntHex(res)); - return res; -} - -IRef& OcxTypeLib::GetTypeLib() -{ - if(!typelib) { // opportunity lock used to initialize type library info - critical.Enter(); - if(!typelib) { - WString tlibname = GetModuleFileName().ToWString(); - HRESULT hr = LoadTypeLib(tlibname, typelib.Set()); - LOGSYSOCX("LoadTypeLib(" << tlibname << ") -> " << FormatIntHex(~typelib) << ", hr = " << FormatIntHex(hr)); - if(!!typelib) { - hr = RegisterTypeLib(~typelib, const_cast(~tlibname), NULL); - LOGSYSOCX("RegisterTypeLib -> hr = " << FormatIntHex(hr)); - } - } - critical.Leave(); - } - return typelib; -} - -#ifdef _USRDLL -STDAPI DllCanUnloadNow() -{ - LOGSYSOCX("DllCanUnloadNow"); -// DoLateInit(); - return (OcxTypeLib::Get().CanUnload() ? S_OK : S_FALSE); -} -#endif - -#ifdef _USRDLL -STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) -{ - LOGSYSOCX("DllGetClassObject, riid = " << Guid(riid)); - HRESULT res = OcxTypeLib::Get().GetFactory(rclsid, riid, ppv); - LOGSYSOCX("//DllGetClassObject -> " << FormatIntHex(res, 8) << ", ppv = " << FormatIntHex(*ppv)); - return res; -} -#endif - -#ifdef _USRDLL -STDAPI DllRegisterServer() -{ - LOGSYSOCX("DllRegisterServer"); - try { - DoLateInit(); - HRESULT hr = OcxTypeLib::Get().Register(); - if(SUCCEEDED(hr)) - LOGSYSOCX("-> succeeded"); - else - LOGSYSOCX("-> failed: " << GetErrorMessage(hr)); - return hr; - } - catch(_com_error e) { - LOGSYSOCX(e.Error()); - return e.Error(); - } -} -#endif - -#ifdef _USRDLL -STDAPI DllUnregisterServer() -{ - LOGSYSOCX("DllUnregisterServer"); - try { - DoLateInit(); - HRESULT hr = OcxTypeLib::Get().Unregister(); - LOGSYSOCX((SUCCEEDED(hr) ? "-> succeeded" : "-> failed")); - return hr; - } - catch(_com_error e) { - LOGSYSOCX(e.Error()); - return e.Error(); - } -} -#endif - -#ifndef _USRDLL -bool ExeRegisterServer() -{ - LOGSYSOCX("ExeRegisterServer"); - HRESULT hr = OcxTypeLib::Get().Register(); - if(FAILED(hr)) - LOGSYSOCX("-> error: " << GetErrorMessage(hr)); - return SUCCEEDED(hr); -} -#endif - -#ifndef _USRDLL -bool ExeUnregisterServer() -{ - LOGSYSOCX("ExeRegisterServer"); - HRESULT hr = OcxTypeLib::Get().Unregister(); - if(FAILED(hr)) - LOGSYSOCX("-> error: " << GetErrorMessage(hr)); - return SUCCEEDED(hr); -} -#endif - -#ifndef _USRDLL -void ExeRunServer() -{ - LOGSYSOCX("ExeRunServer"); -// PromptOK("Running server!"); - HRESULT hr; - if(FAILED(hr = OcxTypeLib::Get().RegisterObjects())) { - LOGSYSOCX("-> registration error: " << GetErrorMessage(hr)); - return; - } - LOGSYSOCX("-> registration OK"); - - int ms = msecs(); - bool quit = false; - while(!quit) { - if(msecs(ms) >= 2000) { - if(OcxTypeLib::Get().CanUnload()) - break; - ms = msecs(); - } - if(!Ctrl::ProcessEvents(&quit)) - Sleep(10); - } - LOGSYSOCX("end of message loop"); - OcxTypeLib::Get().RevokeObjects(); -} -#endif - -} - -#endif +#include + +#ifdef PLATFORM_WIN32 + +#define LDUMP(x) +#define LLOG(x) + +namespace Upp { + +enum { HIMETRIC_INCH = 2540 }; // HIMETRIC units per inch + +SystemDraw& ScreenInfo(); + +Size ToHiMetric(Size pixel_size) +{ + static Size logdpi = ScreenInfo().GetSizeCaps(LOGPIXELSX, LOGPIXELSY); + return Size( + iscaleceil(pixel_size.cx, HIMETRIC_INCH, logdpi.cx), + iscaleceil(pixel_size.cy, HIMETRIC_INCH, logdpi.cy)); +} + +Size FromHiMetric(Size himetric_size) +{ + static Size logdpi = ScreenInfo().GetSizeCaps(LOGPIXELSX, LOGPIXELSY); + return Size( + iscalefloor(himetric_size.cx, logdpi.cx, HIMETRIC_INCH), + iscalefloor(himetric_size.cy, logdpi.cy, HIMETRIC_INCH)); +} + +Rect GetWindow(HDC hdc) +{ + Point pt; + Size sz; + GetWindowOrgEx(hdc, pt); + GetWindowExtEx(hdc, sz); + return Rect(pt, sz); +} + +Rect GetViewport(HDC hdc) +{ + Point pt; + Size sz; + GetViewportOrgEx(hdc, pt); + GetViewportExtEx(hdc, sz); + return Rect(pt, sz); +} + +OcxObject::OcxObject() +: ocx_info(0) +{ + inner_unknown.owner = this; + outer_unknown = NULL; +} + +int OcxObject::ExternalAddRef() +{ + if(outer_unknown) { + int res = outer_unknown->AddRef(); +#if LOG_ADDREFS + OCXLOG("OcxObject::ExternalAddRef -> outer(" << FormatIntHex(outer_unknown) << ") -> " << res); +#endif + return res; + } + return InternalAddRef(); +} + +int OcxObject::ExternalRelease() +{ + if(outer_unknown) { + int res = outer_unknown->Release(); +#if LOG_ADDREFS + // note: this might have been destructed by this time + OCXLOG("OcxObject::ExternalRelease -> outer(" << FormatIntHex(outer_unknown) << ") -> " << res); +#endif + return res; + } + return InternalRelease(); +} + +HRESULT OcxObject::ExternalQueryInterface(const GUID& iid, void **ppv) +{ + if(outer_unknown) { + HRESULT hr = outer_unknown->QueryInterface(iid, ppv); +#if LOG_QUERIES >= 2 + OCXLOG("OcxObject::ExternalQueryInterface(" << GetInterfaceName(iid) << ") -> outer(" << FormatIntHex(outer_unknown) << ") -> " << FormatIntHex(hr)); +#endif + return hr; + } + return InternalQueryInterface(iid, ppv); +} + +HRESULT OcxObject::InternalQueryInterface(const GUID& iid, void **ppv) +{ +#if LOG_QUERIES >= 2 + OCXLOG("OcxObject::InternalQueryInterface -> " << GetInterfaceName(iid)); +#endif + int i; + IUnknown *punk; + if(iid == IID_IUnknown) + punk = static_cast(&inner_unknown); + else if((i = interface_map.Find(iid)) >= 0) + punk = interface_map[i]; + else { + *ppv = 0; +#if LOG_QUERIES >= 1 + String name; + if(ocx_info) + name = ocx_info->GetName(); + else + name = ""; +#endif + LOGQUERY("\t\tcast ERROR: " << name << " -> "<< GetInterfaceName(iid) << ", " << Guid(iid)); +#if LOG_QUERIES >= 3 + OCXLOG("\tGUID = " << Format(iid)); + for(int i = 0; i < interface_map.GetCount(); i++) { + const GUID& imid = interface_map.GetKey(i); + String n = GetInterfaceName(imid); + if(n.GetLength() < 30) + n.Cat(' ', 30 - n.GetLength()); + OCXLOG("\t\t\t" << n << " - " << Format(imid)); + } +#endif + return E_NOINTERFACE; + } + punk->AddRef(); + *ppv = punk; +#if LOG_QUERIES >= 2 + String name; + if(ocx_info) + name = ocx_info->GetName(); + else + name = ""; + OCXLOG("\t\tcast OK: " << name << " -> " << GetInterfaceName(iid)); +#endif + return S_OK; +} + +HRESULT OcxObject::RawGetTypeInfo(IRef& typeinfo, unsigned tinfo, LCID lcid, ITypeInfo **ppinfo) +{ + if(tinfo != 0) + return DISP_E_BADINDEX; + if(!typeinfo) + return E_FAIL; + // currently ignore lcid + *ppinfo = typeinfo.AddRef(); + return S_OK; +} + +HRESULT OcxObject::RawGetIDsOfNames(IRef& typeinfo, REFIID riid, OLECHAR **names, unsigned cnames, LCID lcid, DISPID *dispid) +{ + if(!typeinfo) + return E_FAIL; + return typeinfo->GetIDsOfNames(names, cnames, dispid); +} + +HRESULT OcxObject::RawInvoke(IRef& typeinfo, IDispatch *dispatch, DISPID dispid, word flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, unsigned *arg_err) +{ + LOGINVOKE("IDispatch::Invoke"); + if(dispid == 0) { // convert object to dispatch value + if(!result) return E_INVALIDARG; + result->vt = VT_DISPATCH; + result->pdispVal = dispatch; + if(dispatch) dispatch->AddRef(); + return S_OK; + } + if(!typeinfo) { + LOG("dispid = " << FormatIntHex(dispid) << ": typeinfo = NULL"); + return E_FAIL; + } +#if LOG_INVOKES >= 1 + BSTR names[1] = { NULL }; + unsigned count = 0; + typeinfo->GetNames(dispid, names, 1, &count); + String name; + if(names[0]) + name = BSTRToString(names[0]); + else + name = FormatIntHex(dispid); + switch(flags) { + case DISPATCH_METHOD: name << " - method"; break; + case DISPATCH_PROPERTYGET: name << " - propget"; break; + case DISPATCH_PROPERTYPUT: name << " - propput"; break; + case DISPATCH_PROPERTYPUTREF: name << " - propputref"; break; + } + LOG("Member name: " << name); +#endif + if(!typeinfo) + return E_FAIL; + TYPEATTR *attr; + typeinfo->GetTypeAttr(&attr); + LOGINVOKE("GetTypeInfo: typekind = " << (int)attr->typekind); +// HRESULT res = typeinfo->Invoke(dispatch, dispid, flags, params, result, excep, arg_err); + HRESULT res = DispInvoke(dispatch, ~typeinfo, dispid, flags, params, result, excep, arg_err); + if(FAILED(res)) { + LLOG("failure: dispid = " << (int)dispid << ", #args = " << (int)params->cArgs + << ", #named args = " << (int)params->cNamedArgs << ", return " << FormatIntHex(result)); + for(int i = 0; i < (int)params->cArgs; i++) { + LLOG("arg[" << i << "] (vt = " << (int)params->rgvarg[i].vt << "): " << StdFormat(AsValue(params->rgvarg[i]))); + } + LLOG("#funcs = " << attr->cFuncs); + for(int i = 0; i < attr->cFuncs; i++) { + FUNCDESC *func; + typeinfo->GetFuncDesc(i, &func); + LLOG("memid = " << func->memid << ", cParams " << func->cParams + << ", cParamsOpt = " << func->cParamsOpt << ", cScodes " << func->cScodes + << ", funckind = " << (int)func->funckind << ", invkind " << (int)func->invkind + << ", flags = " << FormatIntHex(func->wFuncFlags)); + + typeinfo->ReleaseFuncDesc(func); + } + } + typeinfo->ReleaseTypeAttr(attr); + LOGINVOKE("//IDispatch::Invoke"); + return LOGRESULT(res); +} + +HRESULT OcxProvideClassInfo::GetClassInfo(ITypeInfo **info) +{ + if(!info) return E_INVALIDARG; + if(!ocx_info) { + *info = NULL; + return E_POINTER; + } + *info = ocx_info->GetCoClassTypeInfo().AddRef(); + return S_OK; +} + +HRESULT OcxProvideClassInfo::GetGUID(dword guidkind, GUID *guid) +{ + if(!guid) + return E_POINTER; + if(!ocx_info) { + *guid = __uuidof(0); + return E_NOTIMPL; + } + if(guidkind == GUIDKIND_DEFAULT_SOURCE_DISP_IID) { + *guid = ~ocx_info->GetEventGUID(); + return ocx_info->GetEventGUID().IsEmpty() ? E_UNEXPECTED : S_OK; + } + return E_INVALIDARG; +} + +OcxTypeInfo::OcxTypeInfo(const GUID& coclass_guid, /*const GUID& dispatch_guid,*/ const GUID& event_guid, + New new_fn, String name, const char* help, int ver, bool is_control) +: coclass_guid(coclass_guid), /*dispatch_guid(dispatch_guid),*/ event_guid(event_guid) +, new_fn(new_fn), name(name), help(help), ver(ver), is_control(is_control) +, object_count(0) +, refcount(1) +, lock_count(0) +#ifndef _USRDLL +, registration(0) +#endif +{ + LLOG("OcxTypeInfo ctr (" << name << ", " << Guid(coclass_guid) << ")"); + OcxTypeLib::Get().Add(*this); +} + +bool OcxTypeInfo::CanUnload() const +{ + LLOG("OcxTypeInfo::CanUnload(" << name << ", " << Guid(coclass_guid) << ")"); + LDUMP(object_count); + LDUMP(refcount); + return object_count == 0 && refcount <= 2 && lock_count <= 0; +} + +int OcxTypeInfo::IncRef() +{ + int res = InterlockedIncrement(&refcount); + LLOG("OcxTypeInfo::IncRef(" << name << " -> " << res << ")"); + return res; +} + +int OcxTypeInfo::DecRef() +{ + int res = InterlockedDecrement(&refcount); + LLOG("OcxTypeInfo::DecRef(" << name << " -> " << res << ")"); + VERIFY(res > 0); // if this throws, the factory has been over-released + return res; +} + +GLOBAL_VAR(InitProc, LateInitProc); +GLOBAL_VAR(InitProc, LateExitProc); +static bool inited = false; + +void DoLateInit() +{ + if(!inited) { + INTERLOCKED + if(!inited) { + inited = true; + if(LateInitProc()) + LateInitProc()(); + } + } +} + +void DoLateExit() +{ + if(inited) { + INTERLOCKED + if(inited) { + inited = false; + if(LateExitProc()) + LateExitProc()(); + } + } +} + +HRESULT OcxTypeInfo::CreateInstance(IUnknown *outer, REFIID iid, void **object) +{ + LLOG("OcxTypeInfo::CreateInstance(" << name << ", iid = " << Guid(iid) << ", outer = " << FormatIntHex(outer) << ")"); + if(outer && iid != IID_IUnknown) + return CLASS_E_NOAGGREGATION; + try { + DoLateInit(); + OcxObject *ocxobj = new_fn(*this); + LOGCREATE("\tnew " << name << ": " << object_count << " instances in system"); + if(outer) + ocxobj->outer_unknown = outer; + HRESULT hr = ocxobj->InternalQueryInterface(iid, object); + LOGCREATE("//OcxTypeInfo::CreateInstance -> " << FormatIntHex(hr)); + return hr; + } + catch(Exc e) { + LLOG("OcxTypeInfo::CreateInstance error: " << e); + return E_OUTOFMEMORY; + } + catch(...) { + return E_OUTOFMEMORY; + } +} + +HRESULT OcxTypeInfo::LockServer(BOOL lock) +{ + LLOG("OcxTypeInfo::LockServer(" << name << ", " << lock << ")"); + if(lock) + AtomicInc(lock_count); + else + VERIFY(AtomicDec(lock_count) >= 0); // over-unlock check + return S_OK; +} + +HRESULT OcxTypeInfo::GetLicInfo(/* [out] */ LICINFO *pLicInfo) +{ + LLOG("OcxTypeInfo::GetLicInfo(" << name << ")"); + if(!pLicInfo) + return E_INVALIDARG; + pLicInfo->fLicVerified = TRUE; + pLicInfo->fRuntimeKeyAvail = 0; + return S_OK; +} + +HRESULT OcxTypeInfo::RequestLicKey(/* [in] */ DWORD dwReserved, /* [out] */ BSTR *pBstrKey) +{ + LLOG("OcxTypeInfo::RequestLicKey(" << name << ")"); + if(!pBstrKey) return E_INVALIDARG; + *pBstrKey = 0; + return S_OK; +} + +HRESULT OcxTypeInfo::CreateInstanceLic( + /* [in] */ IUnknown *pUnkOuter, + /* [in] */ IUnknown *pUnkReserved, + /* [in] */ REFIID riid, + /* [in] */ BSTR bstrKey, + /* [iid_is][out] */ PVOID *ppvObj) +{ + LLOG("OcxTypeInfo::CreateInstanceLic(" << name << ")"); + return CreateInstance(pUnkOuter, riid, ppvObj); +} + +void OcxTypeInfo::GetDispatchTypeInfo(IRef& dest, Guid dispatch_iid) +{ + if(!dest) { + CriticalSection::Lock lock(critical); + if(!dest) + dest = OcxTypeLib::Get().GetTypeInfo(dispatch_iid); + } +} + +IRef OcxTypeInfo::GetCoClassTypeInfo() +{ + if(!coclass_info && !coclass_guid.IsEmpty()) { // oportunity lock used to initialize type info + critical.Enter(); + if(!coclass_info) + coclass_info = OcxTypeLib::Get().GetTypeInfo(coclass_guid); + critical.Leave(); + } + return coclass_info; +} + +OcxTypeLib::OcxTypeLib() +: lib_ver(1) +{ + CoInitialize(0); +} + +OcxTypeLib& OcxTypeLib::Get() +{ + static OcxTypeLib ocx; + return ocx; +} + +String OcxTypeLib::GetLibName() const +{ + if(!IsNull(lib_name)) + return lib_name; + String s = ToLower(GetFileTitle(GetModuleFileName())); + if(!IsNull(s)) + s.Set(0, ToUpper(s[0])); + return s; +} + +bool OcxTypeLib::CanUnload() const +{ + for(int i = 0; i < objects.GetCount(); i++) + if(!objects[i]->CanUnload()) { + OCXLOG("OcxTypeLib::CanUnload failed for " << objects[i]->GetName()); + return false; + } + OCXLOG("OcxTypeLib::CanUnload succeeded"); + return true; +} + +IRef OcxTypeLib::GetTypeInfo(const Guid& guid) +{ + IRef outinfo; + HRESULT hr = GetTypeLib()->GetTypeInfoOfGuid(guid, outinfo.Set()); + if(FAILED(hr)) { + LOGSYSOCX("OcxTypeLib::GetTypeInfo(" << guid << ") -> hr = " << FormatIntHex(hr)); + for(int i = 0; i < uses_libraries.GetCount(); i++) { + if(!uses_libraries[i]) { + String libname = uses_libraries.GetKey(i); + WString wlibname = libname.ToWString(); + hr = LoadTypeLib(wlibname, uses_libraries[i].Set()); + if(!uses_libraries[i]) { + LOGSYSOCX("LoadTypeLib(" << libname << ") -> hr = " << FormatIntHex(hr)); + } + else { + LOGSYSOCX("LoadTypeLib(" << uses_libraries.GetKey(i) << ") -> succeeded"); + if(IsFullPath(libname)) { + hr = RegisterTypeLib(~uses_libraries[i], const_cast(~wlibname), NULL); + LOGSYSOCX("RegisterTypeLib(" << libname << ") -> hr = " << FormatIntHex(hr)); + } + } + } + if(!!uses_libraries[i]) { + hr = uses_libraries[i]->GetTypeInfoOfGuid(guid, outinfo.Set()); + if(!!outinfo) + return outinfo; + LOGSYSOCX("GetTypeInfoOfGuid(" << uses_libraries.GetKey(i) << ") -> hr = " << FormatIntHex(hr)); + } + } + } + return outinfo; +} + +HRESULT OcxTypeLib::Register() +{ + String modname = GetModuleFileName(); + String lib_name = GetLibName(); + LOGSYSOCX("Registering library \"" << modname << '\"'); + + HRESULT hr; + IRef& typelib = GetTypeLib(); + if(!typelib) + return SELFREG_E_TYPELIB; + TLIBATTR *attr; + if(FAILED(hr = typelib->GetLibAttr(&attr))) + return hr; + String lib_guid = Guid(attr->guid); + typelib->ReleaseTLibAttr(attr); + + for(int i = 0; i < objects.GetCount(); i++) { + const OcxTypeInfo& entry = *objects[i]; + String progID = lib_name; + String verID = progID << '.' << entry.name; + verID << '.' << (entry.ver ? entry.ver : lib_ver); + String guid = entry.coclass_guid; + LOGSYSOCX("Registering object " << verID << ", CLSID = " << guid); + String clss_key = "CLSID\\" + guid; +#ifdef _USRDLL + String server = clss_key + "\\InprocServer32"; +#endif + String version; + version << lib_ver << '.' << entry.ver; + String help = entry.help; + if(IsNull(help)) { + if(!IsNull(display_name)) + help << display_name << ' '; + help << entry.name << (entry.IsControl() ? " Control " : " Object ") << version; + } + DeleteWinReg(verID, HKEY_CLASSES_ROOT); + DeleteWinReg(progID, HKEY_CLASSES_ROOT); + DeleteWinReg(clss_key, HKEY_CLASSES_ROOT); + if(!SetWinRegString(help, NULL, verID, HKEY_CLASSES_ROOT) + || !SetWinRegString(guid, NULL, verID + "\\CLSID", HKEY_CLASSES_ROOT) + || !SetWinRegString(help, NULL, progID, HKEY_CLASSES_ROOT) + || !SetWinRegString(guid, NULL, progID + "\\CLSID", HKEY_CLASSES_ROOT) + || !SetWinRegString(help, NULL, clss_key, HKEY_CLASSES_ROOT) + || !SetWinRegString(verID, NULL, clss_key + "\\ProgID", HKEY_CLASSES_ROOT) + || !SetWinRegString(progID, NULL, clss_key + "\\VersionIndependentProgID", HKEY_CLASSES_ROOT) + || !SetWinRegString(lib_guid, NULL, clss_key + "\\TypeLib", HKEY_CLASSES_ROOT) +#ifdef _USRDLL + || !SetWinRegString(modname, NULL, server, HKEY_CLASSES_ROOT) + || !SetWinRegString("Apartment", "ThreadingModel", server, HKEY_CLASSES_ROOT) +#else + || !SetWinRegString(modname, NULL, clss_key + "\\LocalServer32", HKEY_CLASSES_ROOT) + || !SetWinRegString(modname, NULL, clss_key + "\\LocalServer", HKEY_CLASSES_ROOT) + || !SetWinRegString("ole32.dll", NULL, clss_key + "\\InprocHandler32", HKEY_CLASSES_ROOT) + || !SetWinRegString("ole2.dll", NULL, clss_key + "\\InprocHandler", HKEY_CLASSES_ROOT) +#endif + || !SetWinRegString(version, NULL, clss_key + "\\Version", HKEY_CLASSES_ROOT)) + return REGDB_E_WRITEREGDB; + if(entry.IsControl()) { + if(!SetWinRegString("", NULL, clss_key + "\\Control", HKEY_CLASSES_ROOT) + || !SetWinRegString(modname + ", 1", NULL, clss_key + "\\ToolboxBitmap32", HKEY_CLASSES_ROOT) + || !SetWinRegString("", NULL, verID + "\\Insertable", HKEY_CLASSES_ROOT) + || !SetWinRegString("", NULL, progID + "\\Insertable", HKEY_CLASSES_ROOT) + || !SetWinRegString("", NULL, clss_key + "\\Insertable", HKEY_CLASSES_ROOT)) + return REGDB_E_WRITEREGDB; + } + } + +// UniStr ulib = modname; + OleBstr ulib(modname); + if(FAILED(hr = RegisterTypeLib(~typelib, (wchar_t *)~ulib, ~ulib))) + return hr; + return S_OK; +} + +HRESULT OcxTypeLib::Unregister() +{ + String lib = GetModuleFileName(); + String lib_name = GetLibName(); + LOGSYSOCX("Unregistering library \"" << lib << '\"'); + for(int i = 0; i < objects.GetCount(); i++) { + const OcxTypeInfo& entry = *objects[i]; + String progID = lib_name; + String verID = progID << '.' << entry.name; + verID << '.' << (entry.ver ? entry.ver : lib_ver); + DeleteWinReg(verID, HKEY_CLASSES_ROOT); + DeleteWinReg(progID, HKEY_CLASSES_ROOT); + DeleteWinReg("CLSID\\" + String(entry.coclass_guid), HKEY_CLASSES_ROOT); + DeleteWinReg("SOFTWARE\\Classes\\" + verID, HKEY_LOCAL_MACHINE); + } + + IRef& typelib = GetTypeLib(); + if(!typelib) + return SELFREG_E_TYPELIB; + TLIBATTR *attr; + HRESULT hr; + if(FAILED(hr = typelib->GetLibAttr(&attr))) + return hr; + hr = UnRegisterTypeLib(attr->guid, + attr->wMajorVerNum, attr->wMinorVerNum, + attr->lcid, attr->syskind); + typelib->ReleaseTLibAttr(attr); + return hr; +} + +#ifndef _USRDLL +HRESULT OcxTypeLib::RegisterObjects() +{ + for(int i = 0; i < objects.GetCount(); i++) { + OcxTypeInfo& entry = *objects[i]; + HRESULT hr; + if(FAILED(hr = CoRegisterClassObject(entry.GetCoClassGUID(), &entry, + CLSCTX_SERVER, REGCLS_MULTIPLEUSE, &entry.registration))) { + RevokeObjects(); + return hr; + } + } + return S_OK; +} +#endif + +#ifndef _USRDLL +void OcxTypeLib::RevokeObjects() +{ + for(int i = 0; i < objects.GetCount(); i++) { + OcxTypeInfo& entry = *objects[i]; + if(entry.registration) { + CoRevokeClassObject(entry.registration); + entry.registration = 0; + } + } +} +#endif + +HRESULT OcxTypeLib::GetFactory(REFCLSID rclsid, REFIID iid, void **ppv) +{ + Guid clsid = rclsid; + LOGSYSOCX("OcxTypeLib::GetFactory(clsid = " << clsid << ", iid = " << Guid(iid) << ")"); + LLOG("#ocx_init = " << ocx_init.GetCount()); + + for(int i = 0; i < ocx_init.GetCount(); i++) + ocx_init[i](); + ocx_init.Clear(); + + LLOG("#objects = " << objects.GetCount()); + for(int i = 0; i < objects.GetCount(); i++) + LLOG("object[" << i << "] = " << Guid(objects.GetKey(i))); + + *ppv = 0; + int f = objects.Find(clsid); + if(f < 0) + return CLASS_E_CLASSNOTAVAILABLE; + OcxTypeInfo *entry = objects[f]; + HRESULT res = entry->QueryInterface(iid, ppv); + LOGSYSOCX("//OcxTypeLib::GetFactory -> " << FormatIntHex(res)); + return res; +} + +IRef& OcxTypeLib::GetTypeLib() +{ + if(!typelib) { // opportunity lock used to initialize type library info + critical.Enter(); + if(!typelib) { + WString tlibname = GetModuleFileName().ToWString(); + HRESULT hr = LoadTypeLib(tlibname, typelib.Set()); + LOGSYSOCX("LoadTypeLib(" << tlibname << ") -> " << FormatIntHex(~typelib) << ", hr = " << FormatIntHex(hr)); + if(!!typelib) { + hr = RegisterTypeLib(~typelib, const_cast(~tlibname), NULL); + LOGSYSOCX("RegisterTypeLib -> hr = " << FormatIntHex(hr)); + } + } + critical.Leave(); + } + return typelib; +} + +#ifdef _USRDLL +STDAPI DllCanUnloadNow() +{ + LOGSYSOCX("DllCanUnloadNow"); +// DoLateInit(); + return (OcxTypeLib::Get().CanUnload() ? S_OK : S_FALSE); +} +#endif + +#ifdef _USRDLL +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) +{ + LOGSYSOCX("DllGetClassObject, riid = " << Guid(riid)); + HRESULT res = OcxTypeLib::Get().GetFactory(rclsid, riid, ppv); + LOGSYSOCX("//DllGetClassObject -> " << FormatIntHex(res, 8) << ", ppv = " << FormatIntHex(*ppv)); + return res; +} +#endif + +#ifdef _USRDLL +STDAPI DllRegisterServer() +{ + LOGSYSOCX("DllRegisterServer"); + try { + DoLateInit(); + HRESULT hr = OcxTypeLib::Get().Register(); + if(SUCCEEDED(hr)) + LOGSYSOCX("-> succeeded"); + else + LOGSYSOCX("-> failed: " << GetErrorMessage(hr)); + return hr; + } + catch(_com_error e) { + LOGSYSOCX(e.Error()); + return e.Error(); + } +} +#endif + +#ifdef _USRDLL +STDAPI DllUnregisterServer() +{ + LOGSYSOCX("DllUnregisterServer"); + try { + DoLateInit(); + HRESULT hr = OcxTypeLib::Get().Unregister(); + LOGSYSOCX((SUCCEEDED(hr) ? "-> succeeded" : "-> failed")); + return hr; + } + catch(_com_error e) { + LOGSYSOCX(e.Error()); + return e.Error(); + } +} +#endif + +#ifndef _USRDLL +bool ExeRegisterServer() +{ + LOGSYSOCX("ExeRegisterServer"); + HRESULT hr = OcxTypeLib::Get().Register(); + if(FAILED(hr)) + LOGSYSOCX("-> error: " << GetErrorMessage(hr)); + return SUCCEEDED(hr); +} +#endif + +#ifndef _USRDLL +bool ExeUnregisterServer() +{ + LOGSYSOCX("ExeRegisterServer"); + HRESULT hr = OcxTypeLib::Get().Unregister(); + if(FAILED(hr)) + LOGSYSOCX("-> error: " << GetErrorMessage(hr)); + return SUCCEEDED(hr); +} +#endif + +#ifndef _USRDLL +void ExeRunServer() +{ + LOGSYSOCX("ExeRunServer"); +// PromptOK("Running server!"); + HRESULT hr; + if(FAILED(hr = OcxTypeLib::Get().RegisterObjects())) { + LOGSYSOCX("-> registration error: " << GetErrorMessage(hr)); + return; + } + LOGSYSOCX("-> registration OK"); + + int ms = msecs(); + bool quit = false; + while(!quit) { + if(msecs(ms) >= 2000) { + if(OcxTypeLib::Get().CanUnload()) + break; + ms = msecs(); + } + if(!Ctrl::ProcessEvents(&quit)) + Sleep(10); + } + LOGSYSOCX("end of message loop"); + OcxTypeLib::Get().RevokeObjects(); +} +#endif + +} + +#endif diff --git a/uppsrc/Ole/Ole.h b/archive/uppsrc/Ole/Ole.h similarity index 94% rename from uppsrc/Ole/Ole.h rename to archive/uppsrc/Ole/Ole.h index 6a2d23008..fdca0be78 100644 --- a/uppsrc/Ole/Ole.h +++ b/archive/uppsrc/Ole/Ole.h @@ -1,27 +1,27 @@ -#ifndef OLE_H -#define OLE_H - -#include - -#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE) && defined(COMPILER_MSC) - -#define Ptr Ptr_ -#define StdFont StdFont_ -#define Font Font_ -#define Picture Picture_ -#define byte win32_byte_ // RpcNdr defines byte -> class with Upp::byte -#define CY win32_CY_ -#include -#include -#undef Ptr -#undef StdFont -#undef Font -#undef Picture -#undef byte -#undef CY - -#endif - -#include "util.h" - -#endif//OLE_H +#ifndef OLE_H +#define OLE_H + +#include + +#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE) && defined(COMPILER_MSC) + +#define Ptr Ptr_ +#define StdFont StdFont_ +#define Font Font_ +#define Picture Picture_ +#define byte win32_byte_ // RpcNdr defines byte -> class with Upp::byte +#define CY win32_CY_ +#include +#include +#undef Ptr +#undef StdFont +#undef Font +#undef Picture +#undef byte +#undef CY + +#endif + +#include "util.h" + +#endif//OLE_H diff --git a/uppsrc/Ole/Ole.upp b/archive/uppsrc/Ole/Ole.upp similarity index 100% rename from uppsrc/Ole/Ole.upp rename to archive/uppsrc/Ole/Ole.upp diff --git a/uppsrc/Ole/srcdoc.tpp/all.i b/archive/uppsrc/Ole/srcdoc.tpp/all.i similarity index 94% rename from uppsrc/Ole/srcdoc.tpp/all.i rename to archive/uppsrc/Ole/srcdoc.tpp/all.i index 500ab39c8..694f8e996 100644 --- a/uppsrc/Ole/srcdoc.tpp/all.i +++ b/archive/uppsrc/Ole/srcdoc.tpp/all.i @@ -1,3 +1,3 @@ -TOPIC("ocx_en-us") -#include "ocx_en-us.tpp" -END_TOPIC +TOPIC("ocx_en-us") +#include "ocx_en-us.tpp" +END_TOPIC diff --git a/uppsrc/Ole/srcdoc.tpp/ocx_en-us.tpp b/archive/uppsrc/Ole/srcdoc.tpp/ocx_en-us.tpp similarity index 100% rename from uppsrc/Ole/srcdoc.tpp/ocx_en-us.tpp rename to archive/uppsrc/Ole/srcdoc.tpp/ocx_en-us.tpp diff --git a/uppsrc/Ole/util.cpp b/archive/uppsrc/Ole/util.cpp similarity index 95% rename from uppsrc/Ole/util.cpp rename to archive/uppsrc/Ole/util.cpp index c9b1a4eff..eddd91201 100644 --- a/uppsrc/Ole/util.cpp +++ b/archive/uppsrc/Ole/util.cpp @@ -1,455 +1,455 @@ -#include "Ole.h" - -#if defined(PLATFORM_WIN32) && defined(COMPILER_MSC) - -namespace Upp { - -////////////////////////////////////////////////////////////////////// -// GUID - -GUID GetCoClassGUID(const char *name, bool prog_id) -{ - OleBstr uni = String(name); - GUID guid; - Zero(guid); - if(prog_id && *name != '{') - CLSIDFromProgID(~uni, &guid); - else - CLSIDFromString(~uni, &guid); - return guid; -} - -hash_t GetHashValue(const GUID& guid) { - const dword *p = reinterpret_cast(&guid); - return CombineHash(p[0], p[1], p[2], p[3]); -} - -String Format(const GUID& guid) { - String result; - wchar_t buffer[128]; - int length; - if((length = StringFromGUID2(guid, buffer, __countof(buffer))) > 0) - result = AsString(buffer, length - 1); - return result; -} - -String CFormat(const GUID& guid) { - String value = Format("{ 0x%08x, 0x%04x, 0x%04x, { ", (int)guid.Data1, (int)guid.Data2, (int)guid.Data3); - for(int i = 0; i < 8; i++) - value << Format("0x%02x, ", guid.Data4[i]); - return value << "} }"; -} - -String GetInterfaceName(const GUID& guid) { - if(IsNull(Guid(guid))) - return Null; - String goo = Format(guid); - return Nvl(GetWinRegString(NULL, "Interface\\" + goo, HKEY_CLASSES_ROOT), goo); -} - -String GetCoClassName(const GUID& guid) { - if(IsNull(Guid(guid))) - return Null; - String goo = Format(guid); - return Nvl(GetWinRegString(NULL, "CLSID\\" + goo + "\\ProgID", HKEY_CLASSES_ROOT), goo); -} - -String GetDisplayName(const GUID& guid) { - if(IsNull(Guid(guid))) - return Null; - String goo = Format(guid); - return Nvl(GetWinRegString(NULL, "CLSID\\" + goo, HKEY_CLASSES_ROOT), goo); -} - -bool Guid::IsNullInstance() const -{ - const dword *p = reinterpret_cast(&guid); - return (p[0] | p[1] | p[2] | p[3]) == 0; -} - - -////////////////////////////////////////////////////////////////////// -// VARIANT - -Value AsValue(const VARIANT& variant) -{ - switch(variant.vt) { - case VT_ERROR: return ErrorValue(GetErrorMessage(variant.scode)); - case VT_EMPTY: return Value(); // void - case VT_NULL: return Null; - - case VT_BOOL: - case VT_UI1: return (int)variant.bVal; - case VT_I2: return (int)variant.iVal; - case VT_I4: return (int)variant.lVal; - - case VT_R4: return variant.fltVal; - case VT_R8: return variant.dblVal; - - case VT_CY: return GetCurrency(variant.cyVal); - - case VT_DATE: return FromDATE(variant.date); - - case VT_BSTR: return BSTRToWString(variant.bstrVal); - - case VT_DECIMAL: { - const DECIMAL& d = variant.decVal; - double h = (d.Lo32 + d.Mid32 * (65536.0 * 65536.0)) * pow(0.1, d.scale); - return d.sign ? -h : h; - } - - case VT_ARRAY | VT_UI1: { - int nelem = variant.parray->rgsabound[0].cElements; - void *bits = 0; - if(SUCCEEDED(SafeArrayAccessData(variant.parray, &bits)) && bits) { - String out((const char *)bits, nelem); - SafeArrayUnaccessData(variant.parray); - return out; - } - break; - } - } - return ErrorValue(Format("Unknown variant type %d", variant.vt)); -} - -OleVariant AsVariant(Value value) { - OleVariant out(VT_NULL); - if(value.IsNull()) - return out; - switch(value.GetType()) { - case BOOL_V: out.vt = VT_UI1; out.bVal = (byte)(int)value; break; - case INT_V: out.vt = VT_I4; out.lVal = (int)value; break; - case DOUBLE_V: out.vt = VT_R8; out.dblVal = value; break; - case STRING_V: out.vt = VT_BSTR; out.bstrVal = StringToBSTR(value); break; - case WSTRING_V: out.vt = VT_BSTR; out.bstrVal = WStringToBSTR(value); break; - case DATE_V: - case TIME_V: out.vt = VT_DATE; out.date = ToDATE((Time)value); - // todo: VALUEARRAY_V ?? - default: break; - } - return out; -} - -double GetCurrency(const win32_CY_& currency) { - return (currency.Hi * (65536.0 * 65536.0) + currency.Lo) / 10000.0; -} - -OleVariant ValueToVariant(Value v) -{ - if(IsTypeRaw< IRef >(v)) - { - OleVariant out(VT_DISPATCH); - IRef disp = ValueTo< IRef >(v); - if(!!disp) disp -> AddRef(); - out.pdispVal = ~disp; - return out; - } - if(IsTypeRaw< IRef >(v)) - { - OleVariant out(VT_UNKNOWN); - IRef unk = ValueTo< IRef >(v); - if(!!unk) unk -> AddRef(); - out.punkVal = ~unk; - return out; - } - return AsVariant(v); -} - -void ReturnVariant(VARIANT *var, const Value& v) -{ - *var = AsVariant(v); -} - -////////////////////////////////////////////////////////////////////// -// BSTR - -String BSTRToString(BSTR bstr) -{ - int l; - if(!bstr || !(l = SysStringLen(bstr))) - return Null; - byte cs = GetDefaultCharset(); - if(cs == CHARSET_UTF8) - return ToUtf8(TWchar(bstr)); - StringBuffer out(l); - FromUnicode(out, TWchar(bstr), l, cs); - return out; -} - -BSTR StringToBSTR(String s) -{ - int len = s.GetLength(); - if(len == 0) - return NULL; - byte cs = GetDefaultCharset(); - if(cs == CHARSET_UTF8) - return WStringToBSTR(FromUtf8(s)); - BSTR bstr = SysAllocStringLen(NULL, len); - ToUnicode(TWchar(bstr), s, len, cs); - return bstr; -} - -void ReturnString(BSTR *dest, String s) -{ - if(*dest) - SysFreeString(*dest); - *dest = StringToBSTR(s); -} - -HRESULT CheckReturnString(BSTR *bstr, String s) -{ - if(!bstr) return E_INVALIDARG; - ReturnString(bstr, s); - return S_OK; -} - -void ReturnWString(BSTR *dest, WString s) -{ - if(*dest) - SysFreeString(*dest); - *dest = WStringToBSTR(s); -} - -HRESULT CheckReturnWString(BSTR *bstr, WString s) -{ - if(!bstr) return E_INVALIDARG; - ReturnWString(bstr, s); - return S_OK; -} - -static ValueArray SAFEARRAYToValueArrayPart(SAFEARRAY *array, long *indices, int dim_index) -{ - Vector dim_array; - int nelem = array->rgsabound[dim_index].cElements; - dim_array.SetCount(nelem); - for(int e = 0; e < nelem; e++) { - indices[dim_index] = e; - if(dim_index > 0) - dim_array[e] = SAFEARRAYToValueArrayPart(array, indices, dim_index - 1); - else { - OleVariant var; - HRESULT hr = SafeArrayGetElement(array, indices, &var); - if(SUCCEEDED(hr)) - dim_array[e] = AsValue(var); - else { - String dims; - for(int i = 0; i < dim_index; i++) - dims << (i ? ", " : "") << indices[i]; - dim_array[e] = ErrorValue(NFormat("SafeArrayGetElement(%s): error %08lx", dims, hr)); - } - } - } - return ValueArray(pick(dim_array)); -} - -ValueArray SAFEARRAYToValueArray(SAFEARRAY *array) -{ - int ndims = array->cDims; - Vector indices; - indices.SetCount(ndims, -1); - return SAFEARRAYToValueArrayPart(array, indices.Begin(), ndims - 1); -} - -Vector SAFEARRAYToWStringVector(SAFEARRAY *array) -{ - Vector out; - out.SetCount(array->rgsabound[0].cElements); - Vector indices; - indices.SetCount(array->cDims, 0); - for(int i = 0; i < out.GetCount(); i++) { - OleBstr s; - indices[0] = i; - HRESULT hr = SafeArrayGetElement(array, indices.Begin(), s.Set()); - out[i] = s; - } - return out; -} - -SAFEARRAY *ToSAFEARRAY(const ValueArray& varray) -{ - SAFEARRAY *a = SafeArrayCreateVector(VT_VARIANT, 0, varray.GetCount()); - if(!a) - return NULL; - for(long index = 0; index < varray.GetCount(); index++) { - OleVariant var = AsVariant(varray[(int)index]); - SafeArrayPutElement(a, &index, &var); - } - return a; -} - -SAFEARRAY *ToSAFEARRAY(const Vector& vstr) -{ - SAFEARRAY *a = SafeArrayCreateVector(VT_BSTR, 0, vstr.GetCount()); - if(!a) - return NULL; - for(long index = 0; index < vstr.GetCount(); index++) { - OleBstr var = vstr[(int)index]; - SafeArrayPutElement(a, &index, ~var); - } - return a; -} - -////////////////////////////////////////////////////////////////////// -// special types - -Color PackColor(long rgb) -{ - if(rgb < 0) - return Null; - return Color((rgb >> 16) & 255, (rgb >> 8) & 255, (rgb >> 0) & 255); -} - -long UnpackColor(Color c) -{ - if(IsNull(c)) - return -1; - return (c.GetR() << 16) | (c.GetG() << 8) | (c.GetB() << 0); -} - -HRESULT CheckReturnColor(long *ptr, Color c) -{ - if(!ptr) - return E_INVALIDARG; - *ptr = UnpackColor(c); - return S_OK; -} - -////////////////////////////////////////////////////////////////////// -// errors - -OleExc::OleExc(HRESULT hresult) -: Exc(NFormat("COM[%08x]: %s", (int)hresult, GetErrorMessage(hresult))) -, hresult(hresult) -{ -} - -OleExc::OleExc(HRESULT hresult, const char *text) -: Exc(NFormat("COM[%08x]: %s: %s", (int)hresult, GetErrorMessage(hresult), text)) -, hresult(hresult) -{ - LOG("OleExc::OleExc " << *this); -} - -HRESULT LogResult(HRESULT hr) -{ - LOGF("<= return 0x%08x: %s\r\n", hr, GetErrorMessage(hr)); - return hr; -} - -HRESULT LogError(HRESULT hr) -{ - if(FAILED(hr)) - LogResult(hr); - return hr; -} - -////////////////////////////////////////////////////////////////////// -// interfaces - -Value DispatchToValue(IDispatch *disp) -{ - return RawPickToValue(IRef(disp)); -} - -Value UnknownToValue(IUnknown *unk) -{ - return RawPickToValue(IRef(unk)); -} - -////////////////////////////////////////////////////////////////////// -// OleStream:: - -OleStream::OleStream(IUnknown *stream) -{ - Open(stream); -} - -bool OleStream::Open(IUnknown *stream) -{ - Close(); - if(!stream) - return false; - if(FAILED(stream -> QueryInterface(IID_IStream, (void **)&istream))) - return false; - STATSTG stat; - Zero(stat); -// HRESULT statres = istream -> Stat(&stat, STATFLAG_NONAME); - int mode = READWRITE; -// if(SUCCEEDED(statres) && (stat.grfMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_READ) -// mode = READ; - - ULARGE_INTEGER pos = AsULarge(0), len; - HRESULT hr; - if(FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_CUR, &pos)) - || FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_END, &len))) - SetError(hr); - current_offset = len.QuadPart; - OpenInit(mode, len.QuadPart); - Seek(pos.QuadPart); - return true; -} - -void OleStream::Close() -{ - if(!(bool)istream) - return; - int64 pos = GetPos(); - Flush(); - HRESULT hr; - if(FAILED(hr = istream -> Seek(AsLarge(pos), STREAM_SEEK_SET, 0))) - SetError(hr); - istream = 0; -} - -void OleStream::SetStreamSize(dword size) -{ - ASSERT((bool)istream && (GetStyle() & STRM_WRITE)); - HRESULT hr; - if(FAILED(hr = istream -> SetSize(AsULarge(size)))) - SetError(hr); - ULARGE_INTEGER pos = AsULarge(0); - if(FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_CUR, &pos))) - SetError(hr); - current_offset = pos.LowPart; -} - -dword OleStream::Read(int64 at, void *ptr, dword size) -{ - ASSERT((bool)istream && (GetStyle() & STRM_READ)); - RawSeek(at); - dword done = 0; - HRESULT hr; - if(FAILED(hr = istream -> Read(ptr, size, &done))) - SetError(hr); - else - current_offset += done; - return done; -} - -void OleStream::Write(int64 at, const void *data, dword size) -{ - ASSERT((bool)istream && (GetStyle() & STRM_WRITE)); - RawSeek(at); - dword done = 0; - HRESULT hr; - if(FAILED(hr = istream -> Write(data, size, &done)) || done != size) - SetError(hr); - current_offset += done; -} - -void OleStream::RawSeek(int64 pos) -{ - if(current_offset == pos) - return; - ULARGE_INTEGER new_pos = AsULarge(pos); - HRESULT hr; - if(FAILED(hr = istream -> Seek(AsLarge(pos), STREAM_SEEK_SET, &new_pos))) - SetError(hr); - pos = new_pos.LowPart; -} - -////////////////////////////////////////////////////////////////////// - -} - -#endif +#include "Ole.h" + +#if defined(PLATFORM_WIN32) && defined(COMPILER_MSC) + +namespace Upp { + +////////////////////////////////////////////////////////////////////// +// GUID + +GUID GetCoClassGUID(const char *name, bool prog_id) +{ + OleBstr uni = String(name); + GUID guid; + Zero(guid); + if(prog_id && *name != '{') + CLSIDFromProgID(~uni, &guid); + else + CLSIDFromString(~uni, &guid); + return guid; +} + +hash_t GetHashValue(const GUID& guid) { + const dword *p = reinterpret_cast(&guid); + return CombineHash(p[0], p[1], p[2], p[3]); +} + +String Format(const GUID& guid) { + String result; + wchar_t buffer[128]; + int length; + if((length = StringFromGUID2(guid, buffer, __countof(buffer))) > 0) + result = AsString(buffer, length - 1); + return result; +} + +String CFormat(const GUID& guid) { + String value = Format("{ 0x%08x, 0x%04x, 0x%04x, { ", (int)guid.Data1, (int)guid.Data2, (int)guid.Data3); + for(int i = 0; i < 8; i++) + value << Format("0x%02x, ", guid.Data4[i]); + return value << "} }"; +} + +String GetInterfaceName(const GUID& guid) { + if(IsNull(Guid(guid))) + return Null; + String goo = Format(guid); + return Nvl(GetWinRegString(NULL, "Interface\\" + goo, HKEY_CLASSES_ROOT), goo); +} + +String GetCoClassName(const GUID& guid) { + if(IsNull(Guid(guid))) + return Null; + String goo = Format(guid); + return Nvl(GetWinRegString(NULL, "CLSID\\" + goo + "\\ProgID", HKEY_CLASSES_ROOT), goo); +} + +String GetDisplayName(const GUID& guid) { + if(IsNull(Guid(guid))) + return Null; + String goo = Format(guid); + return Nvl(GetWinRegString(NULL, "CLSID\\" + goo, HKEY_CLASSES_ROOT), goo); +} + +bool Guid::IsNullInstance() const +{ + const dword *p = reinterpret_cast(&guid); + return (p[0] | p[1] | p[2] | p[3]) == 0; +} + + +////////////////////////////////////////////////////////////////////// +// VARIANT + +Value AsValue(const VARIANT& variant) +{ + switch(variant.vt) { + case VT_ERROR: return ErrorValue(GetErrorMessage(variant.scode)); + case VT_EMPTY: return Value(); // void + case VT_NULL: return Null; + + case VT_BOOL: + case VT_UI1: return (int)variant.bVal; + case VT_I2: return (int)variant.iVal; + case VT_I4: return (int)variant.lVal; + + case VT_R4: return variant.fltVal; + case VT_R8: return variant.dblVal; + + case VT_CY: return GetCurrency(variant.cyVal); + + case VT_DATE: return FromDATE(variant.date); + + case VT_BSTR: return BSTRToWString(variant.bstrVal); + + case VT_DECIMAL: { + const DECIMAL& d = variant.decVal; + double h = (d.Lo32 + d.Mid32 * (65536.0 * 65536.0)) * pow(0.1, d.scale); + return d.sign ? -h : h; + } + + case VT_ARRAY | VT_UI1: { + int nelem = variant.parray->rgsabound[0].cElements; + void *bits = 0; + if(SUCCEEDED(SafeArrayAccessData(variant.parray, &bits)) && bits) { + String out((const char *)bits, nelem); + SafeArrayUnaccessData(variant.parray); + return out; + } + break; + } + } + return ErrorValue(Format("Unknown variant type %d", variant.vt)); +} + +OleVariant AsVariant(Value value) { + OleVariant out(VT_NULL); + if(value.IsNull()) + return out; + switch(value.GetType()) { + case BOOL_V: out.vt = VT_UI1; out.bVal = (byte)(int)value; break; + case INT_V: out.vt = VT_I4; out.lVal = (int)value; break; + case DOUBLE_V: out.vt = VT_R8; out.dblVal = value; break; + case STRING_V: out.vt = VT_BSTR; out.bstrVal = StringToBSTR(value); break; + case WSTRING_V: out.vt = VT_BSTR; out.bstrVal = WStringToBSTR(value); break; + case DATE_V: + case TIME_V: out.vt = VT_DATE; out.date = ToDATE((Time)value); + // todo: VALUEARRAY_V ?? + default: break; + } + return out; +} + +double GetCurrency(const win32_CY_& currency) { + return (currency.Hi * (65536.0 * 65536.0) + currency.Lo) / 10000.0; +} + +OleVariant ValueToVariant(Value v) +{ + if(IsTypeRaw< IRef >(v)) + { + OleVariant out(VT_DISPATCH); + IRef disp = ValueTo< IRef >(v); + if(!!disp) disp -> AddRef(); + out.pdispVal = ~disp; + return out; + } + if(IsTypeRaw< IRef >(v)) + { + OleVariant out(VT_UNKNOWN); + IRef unk = ValueTo< IRef >(v); + if(!!unk) unk -> AddRef(); + out.punkVal = ~unk; + return out; + } + return AsVariant(v); +} + +void ReturnVariant(VARIANT *var, const Value& v) +{ + *var = AsVariant(v); +} + +////////////////////////////////////////////////////////////////////// +// BSTR + +String BSTRToString(BSTR bstr) +{ + int l; + if(!bstr || !(l = SysStringLen(bstr))) + return Null; + byte cs = GetDefaultCharset(); + if(cs == CHARSET_UTF8) + return ToUtf8(TWchar(bstr)); + StringBuffer out(l); + FromUnicode(out, TWchar(bstr), l, cs); + return out; +} + +BSTR StringToBSTR(String s) +{ + int len = s.GetLength(); + if(len == 0) + return NULL; + byte cs = GetDefaultCharset(); + if(cs == CHARSET_UTF8) + return WStringToBSTR(FromUtf8(s)); + BSTR bstr = SysAllocStringLen(NULL, len); + ToUnicode(TWchar(bstr), s, len, cs); + return bstr; +} + +void ReturnString(BSTR *dest, String s) +{ + if(*dest) + SysFreeString(*dest); + *dest = StringToBSTR(s); +} + +HRESULT CheckReturnString(BSTR *bstr, String s) +{ + if(!bstr) return E_INVALIDARG; + ReturnString(bstr, s); + return S_OK; +} + +void ReturnWString(BSTR *dest, WString s) +{ + if(*dest) + SysFreeString(*dest); + *dest = WStringToBSTR(s); +} + +HRESULT CheckReturnWString(BSTR *bstr, WString s) +{ + if(!bstr) return E_INVALIDARG; + ReturnWString(bstr, s); + return S_OK; +} + +static ValueArray SAFEARRAYToValueArrayPart(SAFEARRAY *array, long *indices, int dim_index) +{ + Vector dim_array; + int nelem = array->rgsabound[dim_index].cElements; + dim_array.SetCount(nelem); + for(int e = 0; e < nelem; e++) { + indices[dim_index] = e; + if(dim_index > 0) + dim_array[e] = SAFEARRAYToValueArrayPart(array, indices, dim_index - 1); + else { + OleVariant var; + HRESULT hr = SafeArrayGetElement(array, indices, &var); + if(SUCCEEDED(hr)) + dim_array[e] = AsValue(var); + else { + String dims; + for(int i = 0; i < dim_index; i++) + dims << (i ? ", " : "") << indices[i]; + dim_array[e] = ErrorValue(NFormat("SafeArrayGetElement(%s): error %08lx", dims, hr)); + } + } + } + return ValueArray(pick(dim_array)); +} + +ValueArray SAFEARRAYToValueArray(SAFEARRAY *array) +{ + int ndims = array->cDims; + Vector indices; + indices.SetCount(ndims, -1); + return SAFEARRAYToValueArrayPart(array, indices.Begin(), ndims - 1); +} + +Vector SAFEARRAYToWStringVector(SAFEARRAY *array) +{ + Vector out; + out.SetCount(array->rgsabound[0].cElements); + Vector indices; + indices.SetCount(array->cDims, 0); + for(int i = 0; i < out.GetCount(); i++) { + OleBstr s; + indices[0] = i; + HRESULT hr = SafeArrayGetElement(array, indices.Begin(), s.Set()); + out[i] = s; + } + return out; +} + +SAFEARRAY *ToSAFEARRAY(const ValueArray& varray) +{ + SAFEARRAY *a = SafeArrayCreateVector(VT_VARIANT, 0, varray.GetCount()); + if(!a) + return NULL; + for(long index = 0; index < varray.GetCount(); index++) { + OleVariant var = AsVariant(varray[(int)index]); + SafeArrayPutElement(a, &index, &var); + } + return a; +} + +SAFEARRAY *ToSAFEARRAY(const Vector& vstr) +{ + SAFEARRAY *a = SafeArrayCreateVector(VT_BSTR, 0, vstr.GetCount()); + if(!a) + return NULL; + for(long index = 0; index < vstr.GetCount(); index++) { + OleBstr var = vstr[(int)index]; + SafeArrayPutElement(a, &index, ~var); + } + return a; +} + +////////////////////////////////////////////////////////////////////// +// special types + +Color PackColor(long rgb) +{ + if(rgb < 0) + return Null; + return Color((rgb >> 16) & 255, (rgb >> 8) & 255, (rgb >> 0) & 255); +} + +long UnpackColor(Color c) +{ + if(IsNull(c)) + return -1; + return (c.GetR() << 16) | (c.GetG() << 8) | (c.GetB() << 0); +} + +HRESULT CheckReturnColor(long *ptr, Color c) +{ + if(!ptr) + return E_INVALIDARG; + *ptr = UnpackColor(c); + return S_OK; +} + +////////////////////////////////////////////////////////////////////// +// errors + +OleExc::OleExc(HRESULT hresult) +: Exc(NFormat("COM[%08x]: %s", (int)hresult, GetErrorMessage(hresult))) +, hresult(hresult) +{ +} + +OleExc::OleExc(HRESULT hresult, const char *text) +: Exc(NFormat("COM[%08x]: %s: %s", (int)hresult, GetErrorMessage(hresult), text)) +, hresult(hresult) +{ + LOG("OleExc::OleExc " << *this); +} + +HRESULT LogResult(HRESULT hr) +{ + LOGF("<= return 0x%08x: %s\r\n", hr, GetErrorMessage(hr)); + return hr; +} + +HRESULT LogError(HRESULT hr) +{ + if(FAILED(hr)) + LogResult(hr); + return hr; +} + +////////////////////////////////////////////////////////////////////// +// interfaces + +Value DispatchToValue(IDispatch *disp) +{ + return RawPickToValue(IRef(disp)); +} + +Value UnknownToValue(IUnknown *unk) +{ + return RawPickToValue(IRef(unk)); +} + +////////////////////////////////////////////////////////////////////// +// OleStream:: + +OleStream::OleStream(IUnknown *stream) +{ + Open(stream); +} + +bool OleStream::Open(IUnknown *stream) +{ + Close(); + if(!stream) + return false; + if(FAILED(stream -> QueryInterface(IID_IStream, (void **)&istream))) + return false; + STATSTG stat; + Zero(stat); +// HRESULT statres = istream -> Stat(&stat, STATFLAG_NONAME); + int mode = READWRITE; +// if(SUCCEEDED(statres) && (stat.grfMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_READ) +// mode = READ; + + ULARGE_INTEGER pos = AsULarge(0), len; + HRESULT hr; + if(FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_CUR, &pos)) + || FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_END, &len))) + SetError(hr); + current_offset = len.QuadPart; + OpenInit(mode, len.QuadPart); + Seek(pos.QuadPart); + return true; +} + +void OleStream::Close() +{ + if(!(bool)istream) + return; + int64 pos = GetPos(); + Flush(); + HRESULT hr; + if(FAILED(hr = istream -> Seek(AsLarge(pos), STREAM_SEEK_SET, 0))) + SetError(hr); + istream = 0; +} + +void OleStream::SetStreamSize(dword size) +{ + ASSERT((bool)istream && (GetStyle() & STRM_WRITE)); + HRESULT hr; + if(FAILED(hr = istream -> SetSize(AsULarge(size)))) + SetError(hr); + ULARGE_INTEGER pos = AsULarge(0); + if(FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_CUR, &pos))) + SetError(hr); + current_offset = pos.LowPart; +} + +dword OleStream::Read(int64 at, void *ptr, dword size) +{ + ASSERT((bool)istream && (GetStyle() & STRM_READ)); + RawSeek(at); + dword done = 0; + HRESULT hr; + if(FAILED(hr = istream -> Read(ptr, size, &done))) + SetError(hr); + else + current_offset += done; + return done; +} + +void OleStream::Write(int64 at, const void *data, dword size) +{ + ASSERT((bool)istream && (GetStyle() & STRM_WRITE)); + RawSeek(at); + dword done = 0; + HRESULT hr; + if(FAILED(hr = istream -> Write(data, size, &done)) || done != size) + SetError(hr); + current_offset += done; +} + +void OleStream::RawSeek(int64 pos) +{ + if(current_offset == pos) + return; + ULARGE_INTEGER new_pos = AsULarge(pos); + HRESULT hr; + if(FAILED(hr = istream -> Seek(AsLarge(pos), STREAM_SEEK_SET, &new_pos))) + SetError(hr); + pos = new_pos.LowPart; +} + +////////////////////////////////////////////////////////////////////// + +} + +#endif diff --git a/uppsrc/Ole/util.h b/archive/uppsrc/Ole/util.h similarity index 97% rename from uppsrc/Ole/util.h rename to archive/uppsrc/Ole/util.h index 412df8aeb..73271ef96 100644 --- a/uppsrc/Ole/util.h +++ b/archive/uppsrc/Ole/util.h @@ -1,327 +1,327 @@ -#if defined(PLATFORM_WIN32) && defined(COMPILER_MSC) - -namespace Upp { - -#ifdef COMPILER_MSC -typedef __int64 longlong_t; -#define LL_(x) COMBINE(x, i64) -#else -typedef long long longlong_t; -#define LL_(x) COMBINE(x, LL) -#endif//COMPILER - -inline void OleInit() { CoInitialize(NULL); } - -inline const wchar_t *WcharT(const wchar *w) { return (const wchar_t *)w; } -inline wchar_t *WcharT(wchar *w) { return (wchar_t *)w; } -inline const wchar *TWchar(const wchar_t *w) { return (const wchar *)w; } -inline wchar *TWchar(wchar_t *w) { return (wchar *)w; } - -template -class OleBuffer -{ -public: - OleBuffer(T *ptr = 0) : ptr(ptr) {} - ~OleBuffer() { Clear(); } - - void Clear() { if(ptr) { CoTaskMemFree(ptr); ptr = 0; } } - T **Set() { Clear(); return &ptr; } - - operator T * () { return ptr; } - operator const T * () const { return ptr; } - -private: - T *ptr; -}; - -hash_t GetHashValue(const GUID& guid); -String Format(const GUID& guid); -String CFormat(const GUID& guid); -inline void Serialize(Stream& stream, GUID& guid) { stream.SerializeRaw((byte *)&guid, sizeof(GUID)); } -String GetInterfaceName(const GUID& guid); -String GetCoClassName(const GUID& guid); -String GetDisplayName(const GUID& guid); -GUID GetCoClassGUID(const char *name, bool prog_id = true); - -class Guid : public ValueType > -{ -public: - Guid(const Nuller& = Null) { Clear(); } - Guid(const char *text, bool prid = true) { guid = GetCoClassGUID(text, prid); } - Guid(const GUID& guid_) : guid(guid_) {} - Guid(const Guid& guid_) : guid(guid_.guid) {} - Guid(IDispatchPtr& dispatch); // dynamic GUID of a dispatch object - Guid(Value v) { *this = ValueTo(v); } - - operator Value () const { return RichValue(*this); } - operator const GUID& () const { return guid; } - operator GUID& () { return guid; } - const GUID& operator ~() const { return guid; } - - Guid& operator = (const GUID& _guid) { guid = _guid; return *this; } - - bool IsNullInstance() const; - bool IsEmpty() const { return IsNullInstance(); } - void Clear() { Zero(guid); } - - operator String () const { return UPP::Format(guid); } - String CFormat() const { return UPP::CFormat(guid); } - - void Serialize(Stream& stream) { UPP::Serialize(stream, guid); } - -private: - GUID guid; -}; - -template <> -inline hash_t GetHashValue(const Guid& guid) { return GetHashValue(~guid); } -template <> -inline String AsString(const GUID& guid) { return Format(guid); } -template <> -inline String AsString(const Guid& guid) { return Format(~guid); } - -inline bool operator == (const Guid& a, const Guid& b) { return ~a == ~b; } -inline bool operator != (const Guid& a, const Guid& b) { return ~a != ~b; } - -class OleExc : public Exc -{ -public: - OleExc(HRESULT hresult); - OleExc(HRESULT hresult, const char *text); - -public: - HRESULT hresult; -}; - -HRESULT LogResult(HRESULT hr); -HRESULT LogError(HRESULT hr); - -inline void OleVerify(HRESULT hr) { if(FAILED(hr)) throw OleExc(hr); } -inline void OleVerify(HRESULT hr, const char *text) { if(FAILED(hr)) throw OleExc(hr, text); } - -#define OLE_VERIFY(c) OleVerify(c, #c) - -class OleVariant : public VARIANT -{ -public: - OleVariant(int vtype = VT_EMPTY) { VariantInit(this); vt = vtype; } - OleVariant(const OleVariant& o) { VariantInit(this); VariantCopy(this, const_cast(&o)); } - ~OleVariant() { VariantClear(this); } - OleVariant(const VARIANT& var) { VariantInit(this); VariantCopy(this, const_cast(&var)); } - - OleVariant& operator = (const OleVariant& var) { if(this != &var) { VariantClear(this); VariantCopy(this, const_cast((VARIANT *)&var)); } return *this; } - - VARIANT operator ~ () const { VARIANT v; VariantInit(&v); VariantCopy(&v, const_cast(this)); return v; } -}; - -Value AsValue(const VARIANT& variant); -OleVariant AsVariant(Value value); - -//inline ULARGE_INTEGER AsULarge(dword value) { ULARGE_INTEGER i; i.QuadPart = value; return i; } -//inline LARGE_INTEGER AsLarge(int value) { LARGE_INTEGER i; i.QuadPart = value; return i; } -inline ULARGE_INTEGER AsULarge(int64 value) { ULARGE_INTEGER i; i.QuadPart = value; return i; } -inline LARGE_INTEGER AsLarge(int64 value) { LARGE_INTEGER i; i.QuadPart = value; return i; } - -double GetCurrency(const win32_CY_& currency); -inline DATE ToDATE(Date date) { return date - Date(1899, 12, 30); } -inline DATE ToDATE(Time time) { return (time - Time(1899, 12, 30)) / 86400.0; } -inline Time FromDATE(DATE date) { return Time(1899, 12, 30) + (int64)floor(date * 86400.0 + 0.5); } - -OleVariant ValueToVariant(Value v); -void ReturnVariant(VARIANT *var, Value v); - -inline WString BSTRToWString(BSTR bstr) { return WString((wchar *)bstr, SysStringLen(bstr)); } -inline BSTR WStringToBSTR(WString w) { return SysAllocStringLen((BSTR)~w, w.GetLength()); } -String BSTRToString(BSTR bstr); -BSTR StringToBSTR(String s); - -void ReturnString(BSTR *dest, String s); -HRESULT CheckReturnString(BSTR *bstr, String s); -void ReturnWString(BSTR *dest, WString s); -HRESULT CheckReturnWString(BSTR *bstr, WString s); - -ValueArray SAFEARRAYToValueArray(SAFEARRAY *array); -Vector SAFEARRAYToWStringVector(SAFEARRAY *array); -SAFEARRAY *ToSAFEARRAY(const ValueArray& varray); -SAFEARRAY *ToSAFEARRAY(const Vector& varray); -void ReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array); -void ReturnSAFEARRAY(SAFEARRAY *dest, const Vector& array); -HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array); -HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const Vector& array); - -class OleSafeArray { -public: - OleSafeArray() : array(NULL) {} - OleSafeArray(const ValueArray& va) { array = ToSAFEARRAY(va); } - OleSafeArray(const Vector& vs) { array = ToSAFEARRAY(vs); } - OleSafeArray(const OleSafeArray& a) { array = NULL; if(a.array) OleVerify(SafeArrayCopy(a.array, &array)); } - ~OleSafeArray() { if(array) SafeArrayDestroy(array); } - - operator ValueArray () const { return SAFEARRAYToValueArray(array); } - operator Vector () const { return SAFEARRAYToWStringVector(array); } - SAFEARRAY *operator ~ () const { return array; } - -private: - SAFEARRAY *array; -}; - -class OleBstr -{ -public: - OleBstr(const Nuller& = Null) : bstr(NULL) {} - OleBstr(WString w) : bstr(WStringToBSTR(w)) {} - OleBstr(String s) : bstr(StringToBSTR(s)) {} - ~OleBstr() { if(bstr) SysFreeString(bstr); } - - void Clear() { if(bstr) { SysFreeString(bstr); bstr = NULL; } } - BSTR *Set() { Clear(); return &bstr; } - - operator WString () const { return BSTRToWString(bstr); } - operator String () const { return BSTRToString(bstr); } - String ToString() const { return BSTRToString(bstr); } -// operator BSTR () const { return bstr; } - BSTR operator ~ () const { return bstr; } - int GetLength() const { return SysStringLen(bstr); } - -private: - BSTR bstr; -}; - -inline const RECTL& ToRectL(const Rect& rc) { return reinterpret_cast(rc); } -inline const Rect& ToRect(const RECTL& rc) { return reinterpret_cast(rc); } - -Color PackColor(long rgb); -long UnpackColor(Color c); -HRESULT CheckReturnColor(long *ptr, Color c); - -template -class IRefBase : Moveable< IRefBase > -{ -public: - IRefBase(T *ptr = NULL) : ptr(ptr) { if(ptr) ptr->AddRef(); } - IRefBase(const IRefBase& i) { if(ptr = i.ptr) ptr->AddRef(); } - ~IRefBase() { if(ptr) ptr->Release(); } - - static GUID GetIID() { return __uuidof(T); } - - HRESULT Create(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) - { return CoCreateInstance(clsid, NULL, flags, GetIID(), (void **)Set()); } - - void Clear() { if(ptr) { ptr->Release(); ptr = 0; } } - - T *operator->() const { ASSERT(ptr); return ptr; } - T& operator * () const { ASSERT(ptr); return *ptr; } - T *operator ~ () const { return ptr; } - - T **Set() { Clear(); return &ptr; } - IUnknown **SetUnk() { Clear(); return (IUnknown **)&ptr; } - void **SetVoid() { Clear(); return (void **)&ptr; } - void Set(T *p) { T *old = ptr; if(ptr = p) ptr->AddRef(); if(old) old->Release(); } - - bool operator !() const { return !ptr; } - - T *AddRef() { if(ptr) ptr->AddRef(); return ptr; } - T *Detach() { T *out = ptr; ptr = 0; return out; } - T *operator - () { return Detach(); } - -protected: - mutable T *ptr; -}; - -template -class IRef : public Moveable< IRef, IRefBase > -{ -public: - IRef() {} - IRef(IUnknown *u) { if(u) OleVerify(u->QueryInterface(__uuidof(T), (void **)&ptr)); } - IRef(T *t) { if(ptr = t) ptr->AddRef(); } - IRef(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) { OleVerify(Create(clsid, flags)); } - IRef(const IRef& x) : Moveable< IRef, IRefBase >(x) {} - explicit IRef(const VARIANT& v) - { - ptr = NULL; - if(v.vt == VT_DISPATCH) - OleVerify(v.pdispVal->QueryInterface(__uuidof(T), (void **)&ptr)); - else if(v.vt == VT_UNKNOWN) - OleVerify(v.punkVal->QueryInterface(__uuidof(T), (void **)&ptr)); - else - { - ASSERT(v.vt == VT_EMPTY || v.vt == VT_NULL); - } - } - - IRef& operator = (const IRef& x) { Set(x.ptr); return *this; } -}; - -template <> -class IRef : public IRefBase -{ -public: - IRef() {} - IRef(IUnknown *u) : IRefBase(u) {} - IRef(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) { OleVerify(Create(clsid, flags)); } - IRef(const IRef& x) : IRefBase(x.ptr) {} - - IRef& operator = (const IRef& x) { Set(x.ptr); return *this; } -}; - -Value DispatchToValue(IDispatch *disp); -Value UnknownToValue(IUnknown *unk); - -template -OleVariant DispVar(I& iface) -{ - IRef disp = iface; - OleVariant out(VT_DISPATCH); - if(!!disp) disp->AddRef(); - out.pdispVal = ~disp; - return out; -} - -template -struct OleType : Moveable< OleType > -{ - friend T *Ptr(T& t) { return reinterpret_cast(&reinterpret_cast(t)); } - friend T& Deref(T *t) { return reinterpret_cast(*reinterpret_cast(t)); } - friend void Destroy(T& t) { t.~T(); } - friend T& Construct(T& t) { return Deref(new(Ptr(t)) T); } - friend void CopyConstruct(T& t, T& x) { new(Ptr(t)) T(x); } - friend void DeepCopyConstruct(T& t, const T& x) { new(Ptr(t)) T(x); } -}; - -template -inline HRESULT QueryInterface(T& src, U& dest, const GUID& guid) -{ - return src->QueryInterface(guid, (void **)dest.Set()); -} - -template -inline HRESULT QueryInterface(T& src, U& dest) -{ - return QueryInterface(src, dest, dest.GetIID()); -} - -class OleStream : public BlockStream -{ -public: - OleStream(IUnknown *stream = 0); - - bool Open(IUnknown *stream); - virtual void Close(); - virtual bool IsOpen() const { return istream; } - -protected: - virtual void SetStreamSize(dword size); - virtual dword Read(int64 at, void *ptr, dword size); - virtual void Write(int64 at, const void *data, dword size); - - void RawSeek(int64 pos); - -protected: - IStreamPtr istream; - int64 current_offset; -}; - -} - -#endif +#if defined(PLATFORM_WIN32) && defined(COMPILER_MSC) + +namespace Upp { + +#ifdef COMPILER_MSC +typedef __int64 longlong_t; +#define LL_(x) COMBINE(x, i64) +#else +typedef long long longlong_t; +#define LL_(x) COMBINE(x, LL) +#endif//COMPILER + +inline void OleInit() { CoInitialize(NULL); } + +inline const wchar_t *WcharT(const wchar *w) { return (const wchar_t *)w; } +inline wchar_t *WcharT(wchar *w) { return (wchar_t *)w; } +inline const wchar *TWchar(const wchar_t *w) { return (const wchar *)w; } +inline wchar *TWchar(wchar_t *w) { return (wchar *)w; } + +template +class OleBuffer +{ +public: + OleBuffer(T *ptr = 0) : ptr(ptr) {} + ~OleBuffer() { Clear(); } + + void Clear() { if(ptr) { CoTaskMemFree(ptr); ptr = 0; } } + T **Set() { Clear(); return &ptr; } + + operator T * () { return ptr; } + operator const T * () const { return ptr; } + +private: + T *ptr; +}; + +hash_t GetHashValue(const GUID& guid); +String Format(const GUID& guid); +String CFormat(const GUID& guid); +inline void Serialize(Stream& stream, GUID& guid) { stream.SerializeRaw((byte *)&guid, sizeof(GUID)); } +String GetInterfaceName(const GUID& guid); +String GetCoClassName(const GUID& guid); +String GetDisplayName(const GUID& guid); +GUID GetCoClassGUID(const char *name, bool prog_id = true); + +class Guid : public ValueType > +{ +public: + Guid(const Nuller& = Null) { Clear(); } + Guid(const char *text, bool prid = true) { guid = GetCoClassGUID(text, prid); } + Guid(const GUID& guid_) : guid(guid_) {} + Guid(const Guid& guid_) : guid(guid_.guid) {} + Guid(IDispatchPtr& dispatch); // dynamic GUID of a dispatch object + Guid(Value v) { *this = ValueTo(v); } + + operator Value () const { return RichValue(*this); } + operator const GUID& () const { return guid; } + operator GUID& () { return guid; } + const GUID& operator ~() const { return guid; } + + Guid& operator = (const GUID& _guid) { guid = _guid; return *this; } + + bool IsNullInstance() const; + bool IsEmpty() const { return IsNullInstance(); } + void Clear() { Zero(guid); } + + operator String () const { return UPP::Format(guid); } + String CFormat() const { return UPP::CFormat(guid); } + + void Serialize(Stream& stream) { UPP::Serialize(stream, guid); } + +private: + GUID guid; +}; + +template <> +inline hash_t GetHashValue(const Guid& guid) { return GetHashValue(~guid); } +template <> +inline String AsString(const GUID& guid) { return Format(guid); } +template <> +inline String AsString(const Guid& guid) { return Format(~guid); } + +inline bool operator == (const Guid& a, const Guid& b) { return ~a == ~b; } +inline bool operator != (const Guid& a, const Guid& b) { return ~a != ~b; } + +class OleExc : public Exc +{ +public: + OleExc(HRESULT hresult); + OleExc(HRESULT hresult, const char *text); + +public: + HRESULT hresult; +}; + +HRESULT LogResult(HRESULT hr); +HRESULT LogError(HRESULT hr); + +inline void OleVerify(HRESULT hr) { if(FAILED(hr)) throw OleExc(hr); } +inline void OleVerify(HRESULT hr, const char *text) { if(FAILED(hr)) throw OleExc(hr, text); } + +#define OLE_VERIFY(c) OleVerify(c, #c) + +class OleVariant : public VARIANT +{ +public: + OleVariant(int vtype = VT_EMPTY) { VariantInit(this); vt = vtype; } + OleVariant(const OleVariant& o) { VariantInit(this); VariantCopy(this, const_cast(&o)); } + ~OleVariant() { VariantClear(this); } + OleVariant(const VARIANT& var) { VariantInit(this); VariantCopy(this, const_cast(&var)); } + + OleVariant& operator = (const OleVariant& var) { if(this != &var) { VariantClear(this); VariantCopy(this, const_cast((VARIANT *)&var)); } return *this; } + + VARIANT operator ~ () const { VARIANT v; VariantInit(&v); VariantCopy(&v, const_cast(this)); return v; } +}; + +Value AsValue(const VARIANT& variant); +OleVariant AsVariant(Value value); + +//inline ULARGE_INTEGER AsULarge(dword value) { ULARGE_INTEGER i; i.QuadPart = value; return i; } +//inline LARGE_INTEGER AsLarge(int value) { LARGE_INTEGER i; i.QuadPart = value; return i; } +inline ULARGE_INTEGER AsULarge(int64 value) { ULARGE_INTEGER i; i.QuadPart = value; return i; } +inline LARGE_INTEGER AsLarge(int64 value) { LARGE_INTEGER i; i.QuadPart = value; return i; } + +double GetCurrency(const win32_CY_& currency); +inline DATE ToDATE(Date date) { return date - Date(1899, 12, 30); } +inline DATE ToDATE(Time time) { return (time - Time(1899, 12, 30)) / 86400.0; } +inline Time FromDATE(DATE date) { return Time(1899, 12, 30) + (int64)floor(date * 86400.0 + 0.5); } + +OleVariant ValueToVariant(Value v); +void ReturnVariant(VARIANT *var, Value v); + +inline WString BSTRToWString(BSTR bstr) { return WString((wchar *)bstr, SysStringLen(bstr)); } +inline BSTR WStringToBSTR(WString w) { return SysAllocStringLen((BSTR)~w, w.GetLength()); } +String BSTRToString(BSTR bstr); +BSTR StringToBSTR(String s); + +void ReturnString(BSTR *dest, String s); +HRESULT CheckReturnString(BSTR *bstr, String s); +void ReturnWString(BSTR *dest, WString s); +HRESULT CheckReturnWString(BSTR *bstr, WString s); + +ValueArray SAFEARRAYToValueArray(SAFEARRAY *array); +Vector SAFEARRAYToWStringVector(SAFEARRAY *array); +SAFEARRAY *ToSAFEARRAY(const ValueArray& varray); +SAFEARRAY *ToSAFEARRAY(const Vector& varray); +void ReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array); +void ReturnSAFEARRAY(SAFEARRAY *dest, const Vector& array); +HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array); +HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const Vector& array); + +class OleSafeArray { +public: + OleSafeArray() : array(NULL) {} + OleSafeArray(const ValueArray& va) { array = ToSAFEARRAY(va); } + OleSafeArray(const Vector& vs) { array = ToSAFEARRAY(vs); } + OleSafeArray(const OleSafeArray& a) { array = NULL; if(a.array) OleVerify(SafeArrayCopy(a.array, &array)); } + ~OleSafeArray() { if(array) SafeArrayDestroy(array); } + + operator ValueArray () const { return SAFEARRAYToValueArray(array); } + operator Vector () const { return SAFEARRAYToWStringVector(array); } + SAFEARRAY *operator ~ () const { return array; } + +private: + SAFEARRAY *array; +}; + +class OleBstr +{ +public: + OleBstr(const Nuller& = Null) : bstr(NULL) {} + OleBstr(WString w) : bstr(WStringToBSTR(w)) {} + OleBstr(String s) : bstr(StringToBSTR(s)) {} + ~OleBstr() { if(bstr) SysFreeString(bstr); } + + void Clear() { if(bstr) { SysFreeString(bstr); bstr = NULL; } } + BSTR *Set() { Clear(); return &bstr; } + + operator WString () const { return BSTRToWString(bstr); } + operator String () const { return BSTRToString(bstr); } + String ToString() const { return BSTRToString(bstr); } +// operator BSTR () const { return bstr; } + BSTR operator ~ () const { return bstr; } + int GetLength() const { return SysStringLen(bstr); } + +private: + BSTR bstr; +}; + +inline const RECTL& ToRectL(const Rect& rc) { return reinterpret_cast(rc); } +inline const Rect& ToRect(const RECTL& rc) { return reinterpret_cast(rc); } + +Color PackColor(long rgb); +long UnpackColor(Color c); +HRESULT CheckReturnColor(long *ptr, Color c); + +template +class IRefBase : Moveable< IRefBase > +{ +public: + IRefBase(T *ptr = NULL) : ptr(ptr) { if(ptr) ptr->AddRef(); } + IRefBase(const IRefBase& i) { if(ptr = i.ptr) ptr->AddRef(); } + ~IRefBase() { if(ptr) ptr->Release(); } + + static GUID GetIID() { return __uuidof(T); } + + HRESULT Create(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) + { return CoCreateInstance(clsid, NULL, flags, GetIID(), (void **)Set()); } + + void Clear() { if(ptr) { ptr->Release(); ptr = 0; } } + + T *operator->() const { ASSERT(ptr); return ptr; } + T& operator * () const { ASSERT(ptr); return *ptr; } + T *operator ~ () const { return ptr; } + + T **Set() { Clear(); return &ptr; } + IUnknown **SetUnk() { Clear(); return (IUnknown **)&ptr; } + void **SetVoid() { Clear(); return (void **)&ptr; } + void Set(T *p) { T *old = ptr; if(ptr = p) ptr->AddRef(); if(old) old->Release(); } + + bool operator !() const { return !ptr; } + + T *AddRef() { if(ptr) ptr->AddRef(); return ptr; } + T *Detach() { T *out = ptr; ptr = 0; return out; } + T *operator - () { return Detach(); } + +protected: + mutable T *ptr; +}; + +template +class IRef : public Moveable< IRef, IRefBase > +{ +public: + IRef() {} + IRef(IUnknown *u) { if(u) OleVerify(u->QueryInterface(__uuidof(T), (void **)&ptr)); } + IRef(T *t) { if(ptr = t) ptr->AddRef(); } + IRef(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) { OleVerify(Create(clsid, flags)); } + IRef(const IRef& x) : Moveable< IRef, IRefBase >(x) {} + explicit IRef(const VARIANT& v) + { + ptr = NULL; + if(v.vt == VT_DISPATCH) + OleVerify(v.pdispVal->QueryInterface(__uuidof(T), (void **)&ptr)); + else if(v.vt == VT_UNKNOWN) + OleVerify(v.punkVal->QueryInterface(__uuidof(T), (void **)&ptr)); + else + { + ASSERT(v.vt == VT_EMPTY || v.vt == VT_NULL); + } + } + + IRef& operator = (const IRef& x) { Set(x.ptr); return *this; } +}; + +template <> +class IRef : public IRefBase +{ +public: + IRef() {} + IRef(IUnknown *u) : IRefBase(u) {} + IRef(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) { OleVerify(Create(clsid, flags)); } + IRef(const IRef& x) : IRefBase(x.ptr) {} + + IRef& operator = (const IRef& x) { Set(x.ptr); return *this; } +}; + +Value DispatchToValue(IDispatch *disp); +Value UnknownToValue(IUnknown *unk); + +template +OleVariant DispVar(I& iface) +{ + IRef disp = iface; + OleVariant out(VT_DISPATCH); + if(!!disp) disp->AddRef(); + out.pdispVal = ~disp; + return out; +} + +template +struct OleType : Moveable< OleType > +{ + friend T *Ptr(T& t) { return reinterpret_cast(&reinterpret_cast(t)); } + friend T& Deref(T *t) { return reinterpret_cast(*reinterpret_cast(t)); } + friend void Destroy(T& t) { t.~T(); } + friend T& Construct(T& t) { return Deref(new(Ptr(t)) T); } + friend void CopyConstruct(T& t, T& x) { new(Ptr(t)) T(x); } + friend void DeepCopyConstruct(T& t, const T& x) { new(Ptr(t)) T(x); } +}; + +template +inline HRESULT QueryInterface(T& src, U& dest, const GUID& guid) +{ + return src->QueryInterface(guid, (void **)dest.Set()); +} + +template +inline HRESULT QueryInterface(T& src, U& dest) +{ + return QueryInterface(src, dest, dest.GetIID()); +} + +class OleStream : public BlockStream +{ +public: + OleStream(IUnknown *stream = 0); + + bool Open(IUnknown *stream); + virtual void Close(); + virtual bool IsOpen() const { return istream; } + +protected: + virtual void SetStreamSize(dword size); + virtual dword Read(int64 at, void *ptr, dword size); + virtual void Write(int64 at, const void *data, dword size); + + void RawSeek(int64 pos); + +protected: + IStreamPtr istream; + int64 current_offset; +}; + +} + +#endif