mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 14:16:09 -06:00
740 lines
20 KiB
C++
740 lines
20 KiB
C++
#include <Ole/Ctrl/OleCtrl.h>
|
|
|
|
#ifdef PLATFORM_WIN32
|
|
|
|
NAMESPACE_UPP
|
|
|
|
enum { HIMETRIC_INCH = 2540 }; // HIMETRIC units per inch
|
|
|
|
Draw& 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<IUnknown *>(&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 = "<unknown object>";
|
|
#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 = "<unknown object>";
|
|
OCXLOG("\t\tcast OK: " << name << " -> " << GetInterfaceName(iid));
|
|
#endif
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT OcxObject::RawGetTypeInfo(IRef<ITypeInfo>& 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<ITypeInfo>& 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<ITypeInfo>& 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)) {
|
|
RLOG("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++) {
|
|
RLOG("arg[" << i << "] (vt = " << (int)params->rgvarg[i].vt << "): " << StdFormat(AsValue(params->rgvarg[i])));
|
|
}
|
|
RLOG("#funcs = " << attr->cFuncs);
|
|
for(int i = 0; i < attr->cFuncs; i++) {
|
|
FUNCDESC *func;
|
|
typeinfo->GetFuncDesc(i, &func);
|
|
RLOG("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
|
|
{
|
|
RLOG("OcxTypeInfo ctr (" << name << ", " << Guid(coclass_guid) << ")");
|
|
OcxTypeLib::Get().Add(*this);
|
|
}
|
|
|
|
bool OcxTypeInfo::CanUnload() const
|
|
{
|
|
RLOG("OcxTypeInfo::CanUnload(" << name << ", " << Guid(coclass_guid) << ")");
|
|
RDUMP(object_count);
|
|
RDUMP(refcount);
|
|
RDUMP(lock_count);
|
|
return object_count == 0 && refcount <= 1 && lock_count <= 0;
|
|
}
|
|
|
|
int OcxTypeInfo::IncRef()
|
|
{
|
|
int res = InterlockedIncrement(&refcount);
|
|
RLOG("OcxTypeInfo::IncRef(" << name << " -> " << res << ")");
|
|
return res;
|
|
}
|
|
|
|
int OcxTypeInfo::DecRef()
|
|
{
|
|
int res = InterlockedDecrement(&refcount);
|
|
RLOG("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)
|
|
{
|
|
RLOG("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) {
|
|
RLOG("OcxTypeInfo::CreateInstance error: " << e);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
catch(...) {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
HRESULT OcxTypeInfo::LockServer(BOOL lock)
|
|
{
|
|
RLOG("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)
|
|
{
|
|
RLOG("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)
|
|
{
|
|
RLOG("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)
|
|
{
|
|
RLOG("OcxTypeInfo::CreateInstanceLic(" << name << ")");
|
|
return CreateInstance(pUnkOuter, riid, ppvObj);
|
|
}
|
|
|
|
void OcxTypeInfo::GetDispatchTypeInfo(IRef<ITypeInfo>& dest, Guid dispatch_iid)
|
|
{
|
|
if(!dest) {
|
|
CriticalSection::Lock lock(critical);
|
|
if(!dest)
|
|
dest = OcxTypeLib::Get().GetTypeInfo(dispatch_iid);
|
|
}
|
|
}
|
|
|
|
IRef<ITypeInfo> 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<ITypeInfo> OcxTypeLib::GetTypeInfo(const Guid& guid)
|
|
{
|
|
IRef<ITypeInfo> 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<OLECHAR *>(~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<ITypeLib>& 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<ITypeLib>& 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) << ")");
|
|
RLOG("#ocx_init = " << ocx_init.GetCount());
|
|
|
|
for(int i = 0; i < ocx_init.GetCount(); i++)
|
|
ocx_init[i]();
|
|
ocx_init.Clear();
|
|
|
|
RLOG("#objects = " << objects.GetCount());
|
|
for(int i = 0; i < objects.GetCount(); i++)
|
|
RLOG("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<ITypeLib>& 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<OLECHAR *>(~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");
|
|
|
|
MSG msg;
|
|
while(GetMessage(&msg, 0, 0, 0)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
LOGSYSOCX("end of message loop");
|
|
}
|
|
#endif
|
|
*/
|
|
|
|
END_UPP_NAMESPACE
|
|
|
|
#endif
|