engine/engine/client/sys_axfte.cpp

887 lines
22 KiB
C++

#include "quakedef.h"
#ifdef _WIN32
#include "sys_plugfte.h"
#include <windows.h>
#include <objsafe.h> /*IObjectSafety*/
#include <mshtmdid.h> /*DISPID_SECURITYCTX*/
#include <olectl.h> /*common dispid values*/
#ifndef DISPID_READYSTATE
/*my oldctl.h is too old*/
#define DISPID_READYSTATE -525
#endif
#ifndef __IOleInPlaceObjectWindowless_INTERFACE_DEFINED__
/*mshtmdid.h didn't declare this, so fall back*/
#define IID_IOleInPlaceObjectWindowless IID_IOleInPlaceObject
#define IOleInPlaceObjectWindowless IOleInPlaceObject
#endif
#ifndef __IOleInPlaceSiteWindowless_INTERFACE_DEFINED__
#define IOleInPlaceSiteWindowless IOleInPlaceSite
#define IID_IOleInPlaceSiteWindowless IID_IOleInPlaceSite
#endif
const GUID axfte_iid = {0x7d676c9f, 0xfb84, 0x40b6, {0xb3, 0xff, 0xe1, 0x08, 0x31, 0x55, 0x7e, 0xeb}};
#define axfte_iid_str "7d676c9f-fb84-40b6-b3ff-e10831557eeb"
extern "C"
{
extern HINSTANCE global_hInstance;
}
#ifdef _MSC_VER
#pragma warning(disable:4584) /*shush now*/
#endif
class axfte : public IDispatch, public IClassFactory, public IObjectSafety,
public IOleObject, public IOleInPlaceObjectWindowless, public IViewObject, public IPersistPropertyBag2
{
private:
unsigned int ref;
IUnknown *site;
struct context *plug;
const struct plugfuncs *funcs;
HWND phwnd;
static const struct browserfuncs axbrowserfuncs;
public:
axfte()
{
ref = 0;
site = NULL;
phwnd = NULL;
funcs = Plug_GetFuncs(PLUG_APIVER);
plug = funcs->CreateContext(this, &axbrowserfuncs);
}
~axfte()
{
funcs->DestroyContext(plug);
if (site)
site->Release();
site = NULL;
}
static void statuschanged(void *arg)
{
//potentially comes from another thread
//axfte *fte = (axfte*)arg;
InvalidateRect(NULL, NULL, FALSE);
}
/*IUnknown*/
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject)
{
*ppvObject = NULL;
if (riid == IID_IUnknown)
{
*ppvObject = (IUnknown*)(IDispatch*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
else if (riid == IID_IDispatch)
{
*ppvObject = (IDispatch*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
else if (riid == IID_IClassFactory)
{
*ppvObject = (IClassFactory*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
else if (riid == IID_IObjectSafety)
{
*ppvObject = (IObjectSafety*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
/* else if (riid == IID_IPersistPropertyBag2)
{
*ppvObject = (IPersistPropertyBag2*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}*/
else if (riid == IID_IOleObject)
{
*ppvObject = (IOleObject*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
else if (riid == IID_IOleInPlaceObject)
{
*ppvObject = (IOleInPlaceObject*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
else if (riid == IID_IOleInPlaceObjectWindowless)
{
*ppvObject = (IOleInPlaceObjectWindowless*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
else if (riid == IID_IOleWindow)
{
*ppvObject = (IOleWindow*)(IOleInPlaceObject*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
else if (riid == IID_IOleInPlaceObject)
{
*ppvObject = (IOleInPlaceObject*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
else if (riid == IID_IViewObject)
{
*ppvObject = (IViewObject*)this;
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
virtual ULONG STDMETHODCALLTYPE AddRef( void)
{
return ++ref;
}
virtual ULONG STDMETHODCALLTYPE Release( void)
{
if (ref == 1)
{
delete this;
return 0;
}
return --ref;
}
/*IDispatch*/
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
/* [out] */ UINT *pctinfo)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ ITypeInfo **ppTInfo)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(
/* [in] */ REFIID riid,
/* [size_is][in] */ LPOLESTR *rgszNames,
/* [in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID *rgDispId)
{
char tmp[1024];
HRESULT ret = S_OK;
UINT i;
int prop;
for (i = 0; i < cNames; i++)
{
wcstombs(tmp, rgszNames[i], sizeof(tmp));
prop = funcs->FindProp(plug, tmp);
if (prop >= 0)
{
rgDispId[i] = prop;
}
else if (!stricmp(tmp, "unselectable"))
rgDispId[i] = 5001;
else
{
rgDispId[i] = DISPID_UNKNOWN;
ret = DISP_E_UNKNOWNNAME;
}
}
return ret;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke(
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS *pDispParams,
/* [out] */ VARIANT *pVarResult,
/* [out] */ EXCEPINFO *pExcepInfo,
/* [out] */ UINT *puArgErr)
{
if(wFlags & DISPATCH_METHOD)
{
MessageBox(NULL, "", "invoke method!", 0);
return DISP_E_MEMBERNOTFOUND;
}
else if (wFlags & DISPATCH_PROPERTYGET)
{
VariantClear(pVarResult);
switch(dispIdMember)
{
case DISPID_READYSTATE:
pVarResult->vt = VT_INT;
pVarResult->intVal = READYSTATE_COMPLETE;
break;
case DISPID_ENABLED:
return DISP_E_MEMBERNOTFOUND;
case DISPID_SECURITYCTX:
return DISP_E_MEMBERNOTFOUND;
default:
if (dispIdMember >= 0 && dispIdMember < 1000)
{
const char *tmpa;
wchar_t tmpw[1024];
if (funcs->GetFloat(plug, dispIdMember, &pVarResult->fltVal))
pVarResult->vt = VT_R4;
else if (funcs->GetInteger(plug, dispIdMember, &pVarResult->intVal))
pVarResult->vt = VT_I4;
else if (funcs->GetString(plug, dispIdMember, &tmpa))
{
mbstowcs(tmpw, tmpa, sizeof(tmpw)/sizeof(tmpw[0]));
funcs->GotString(tmpa);
pVarResult->vt = VT_BSTR;
pVarResult->bstrVal = SysAllocString(tmpw);
}
else
return DISP_E_MEMBERNOTFOUND;
}
else
{
char tmp[1024];
sprintf(tmp, "DISPATCH_PROPERTYGET dispIdMember=%i", (unsigned int)dispIdMember);
OutputDebugStringA(tmp);
return DISP_E_MEMBERNOTFOUND;
}
}
}
else if (wFlags & DISPATCH_PROPERTYPUT)
{
if (dispIdMember >= 0 && dispIdMember < 1000)
{
VARIANT *v = &pDispParams->rgvarg[0];
switch(v->vt)
{
case VT_R4:
funcs->SetFloat(plug, dispIdMember, v->fltVal);
break;
case VT_R8:
funcs->SetFloat(plug, dispIdMember, v->dblVal);
break;
case VT_INT:
case VT_I4:
funcs->SetInteger(plug, dispIdMember, v->intVal);
break;
case VT_BSTR:
funcs->SetWString(plug, dispIdMember, v->bstrVal);
break;
default:
return DISP_E_TYPEMISMATCH;
}
return S_OK;
}
else
{
char tmp[1024];
sprintf(tmp, "DISPATCH_PROPERTYPUT dispIdMember=%i", (unsigned int)dispIdMember);
OutputDebugStringA(tmp);
return DISP_E_MEMBERNOTFOUND;
}
}
else if (wFlags & DISPATCH_PROPERTYPUTREF)
{
char tmp[1024];
sprintf(tmp, "DISPATCH_PROPERTYPUTREF dispIdMember=%i", (unsigned int)dispIdMember);
OutputDebugStringA(tmp);
return DISP_E_MEMBERNOTFOUND;
}
else
return DISP_E_MEMBERNOTFOUND;
return S_OK;
}
/*IClassFactory*/
virtual /* [local] */ HRESULT STDMETHODCALLTYPE CreateInstance(
/* [unique][in] */ IUnknown *pUnkOuter,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject)
{
HRESULT res;
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
axfte *newaxfte = new axfte();
res = newaxfte->QueryInterface(riid, ppvObject);
if (!*ppvObject)
delete newaxfte;
return res;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE LockServer(
/* [in] */ BOOL fLock)
{
return S_OK;
}
/*IObjectSafety*/
virtual HRESULT STDMETHODCALLTYPE GetInterfaceSafetyOptions(
/* [in] */ REFIID riid,
/* [out] */ DWORD *pdwSupportedOptions,
/* [out] */ DWORD *pdwEnabledOptions)
{
*pdwSupportedOptions = *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE SetInterfaceSafetyOptions(
/* [in] */ REFIID riid,
/* [in] */ DWORD dwOptionSetMask,
/* [in] */ DWORD dwEnabledOptions)
{
return S_OK;
}
/*IOleWindow*/
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetWindow(
/* [out] */ HWND *phwnd)
{
*phwnd = NULL;
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(
/* [in] */ BOOL fEnterMode)
{
return E_NOTIMPL;
}
/*IOleInPlaceObject*/
virtual HRESULT STDMETHODCALLTYPE InPlaceDeactivate( void)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE UIDeactivate( void)
{
return E_NOTIMPL;
}
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetObjectRects(
/* [in] */ LPCRECT lprcPosRect,
/* [in] */ LPCRECT lprcClipRect)
{
if (phwnd)
funcs->ChangeWindow(plug, phwnd, lprcPosRect->left, lprcPosRect->top, lprcPosRect->right - lprcPosRect->left, lprcPosRect->bottom - lprcPosRect->top);
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE ReactivateAndUndo( void)
{
return E_NOTIMPL;
}
/*IOleObject*/
virtual HRESULT STDMETHODCALLTYPE SetClientSite(
/* [unique][in] */ IOleClientSite *pClientSite)
{
IUnknown *osite = site;
site = pClientSite;
if (site)
site->AddRef();
IOleInPlaceSiteWindowless *oipc;
if (site)
if (!FAILED(site->QueryInterface(IID_IOleInPlaceSiteWindowless, (void**)&oipc)))
{
IOleInPlaceFrame *pframe;
IOleInPlaceUIWindow *pdoc;
RECT posrect;
RECT cliprect;
OLEINPLACEFRAMEINFO frameinfo;
memset(&frameinfo, 0, sizeof(frameinfo));
frameinfo.cb = sizeof(frameinfo);
oipc->GetWindowContext(&pframe, &pdoc, &posrect, &cliprect, &frameinfo);
if (pframe) pframe->Release();
if (pdoc) pdoc->Release();
phwnd = frameinfo.hwndFrame;
oipc->Release();
}
if (osite)
osite->Release();
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE GetClientSite(
/* [out] */ IOleClientSite **ppClientSite)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE SetHostNames(
/* [in] */ LPCOLESTR szContainerApp,
/* [unique][in] */ LPCOLESTR szContainerObj)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Close(
/* [in] */ DWORD dwSaveOption)
{
funcs->SetInteger(plug, funcs->FindProp(plug, "running"), 0);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE SetMoniker(
/* [in] */ DWORD dwWhichMoniker,
/* [unique][in] */ IMoniker *pmk)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetMoniker(
/* [in] */ DWORD dwAssign,
/* [in] */ DWORD dwWhichMoniker,
/* [out] */ IMoniker **ppmk)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE InitFromData(
/* [unique][in] */ IDataObject *pDataObject,
/* [in] */ BOOL fCreation,
/* [in] */ DWORD dwReserved)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetClipboardData(
/* [in] */ DWORD dwReserved,
/* [out] */ IDataObject **ppDataObject)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE DoVerb(
/* [in] */ LONG iVerb,
/* [unique][in] */ LPMSG lpmsg,
/* [unique][in] */ IOleClientSite *pActiveSite,
/* [in] */ LONG lindex,
/* [in] */ HWND hwndParent,
/* [unique][in] */ LPCRECT lprcPosRect)
{
switch(iVerb)
{
case OLEIVERB_INPLACEACTIVATE:
IOleInPlaceSiteWindowless *oipc;
if (!FAILED(pActiveSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void**)&oipc)))
{
IOleInPlaceFrame *pframe;
IOleInPlaceUIWindow *pdoc;
RECT posrect;
RECT cliprect;
OLEINPLACEFRAMEINFO frameinfo;
memset(&frameinfo, 0, sizeof(frameinfo));
frameinfo.cb = sizeof(frameinfo);
oipc->GetWindowContext(&pframe, &pdoc, &posrect, &cliprect, &frameinfo);
if (pframe) pframe->Release();
if (pdoc) pdoc->Release();
phwnd = frameinfo.hwndFrame;
funcs->ChangeWindow(plug, frameinfo.hwndFrame, lprcPosRect->left, lprcPosRect->top, lprcPosRect->right - lprcPosRect->left, lprcPosRect->bottom - lprcPosRect->top);
#ifndef __IOleInPlaceSiteWindowless_INTERFACE_DEFINED__
oipc->OnInPlaceActivate();
#else
oipc->OnInPlaceActivateEx(NULL, 1);
#endif
oipc->Release();
}
break;
}
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE EnumVerbs(
/* [out] */ IEnumOLEVERB **ppEnumOleVerb)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Update( void)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE IsUpToDate( void)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetUserClassID(
/* [out] */ CLSID *pClsid)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetUserType(
/* [in] */ DWORD dwFormOfType,
/* [out] */ LPOLESTR *pszUserType)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE SetExtent(
/* [in] */ DWORD dwDrawAspect,
/* [in] */ SIZEL *psizel)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetExtent(
/* [in] */ DWORD dwDrawAspect,
/* [out] */ SIZEL *psizel)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Advise(
/* [unique][in] */ IAdviseSink *pAdvSink,
/* [out] */ DWORD *pdwConnection)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Unadvise(
/* [in] */ DWORD dwConnection)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE EnumAdvise(
/* [out] */ IEnumSTATDATA **ppenumAdvise)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetMiscStatus(
/* [in] */ DWORD dwAspect,
/* [out] */ DWORD *pdwStatus)
{
*pdwStatus = OLEMISC_RECOMPOSEONRESIZE;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE SetColorScheme(
/* [in] */ LOGPALETTE *pLogpal)
{
return E_NOTIMPL;
}
/*IViewObject*/
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Draw(
/* [in] */ DWORD dwDrawAspect,
/* [in] */ LONG lindex,
/* [unique][in] */ void *pvAspect,
/* [unique][in] */ DVTARGETDEVICE *ptd,
/* [in] */ HDC hdcTargetDev,
/* [in] */ HDC hdcDraw,
/* [in] */ LPCRECTL lprcBounds,
/* [unique][in] */ LPCRECTL lprcWBounds,
/* [in] */ BOOL ( STDMETHODCALLTYPE *pfnContinue )(
ULONG_PTR dwContinue),
/* [in] */ ULONG_PTR dwContinue)
{
struct contextpublic *pub = (struct contextpublic*)plug;
int width, height;
HBITMAP bmp = (HBITMAP)funcs->GetSplashBack(plug, hdcDraw, &width, &height);
if (bmp)
{
HDC memDC;
RECT irect;
irect.left = lprcBounds->left;
irect.right = lprcBounds->right;
irect.top = lprcBounds->top;
irect.bottom = lprcBounds->bottom;
memDC = CreateCompatibleDC(hdcDraw);
SelectObject(memDC, bmp);
StretchBlt(hdcDraw, irect.left, irect.top, irect.right-irect.left,irect.bottom-irect.top, memDC, 0, 0, width, height, SRCCOPY);
SelectObject(memDC, NULL);
DeleteDC(memDC);
funcs->ReleaseSplashBack(plug, bmp);
}
if (*pub->statusmessage)
{
SetBkMode(hdcDraw, TRANSPARENT);
TextOutA(hdcDraw, 0, 0, pub->statusmessage, strlen(pub->statusmessage));
}
return S_OK;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetColorSet(
/* [in] */ DWORD dwDrawAspect,
/* [in] */ LONG lindex,
/* [unique][in] */ void *pvAspect,
/* [unique][in] */ DVTARGETDEVICE *ptd,
/* [in] */ HDC hicTargetDev,
/* [out] */ LOGPALETTE **ppColorSet)
{
return E_NOTIMPL;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Freeze(
/* [in] */ DWORD dwDrawAspect,
/* [in] */ LONG lindex,
/* [unique][in] */ void *pvAspect,
/* [out] */ DWORD *pdwFreeze)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Unfreeze(
/* [in] */ DWORD dwFreeze)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE SetAdvise(
/* [in] */ DWORD aspects,
/* [in] */ DWORD advf,
/* [unique][in] */ IAdviseSink *pAdvSink)
{
return E_NOTIMPL;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetAdvise(
/* [unique][out] */ DWORD *pAspects,
/* [unique][out] */ DWORD *pAdvf,
/* [out] */ IAdviseSink **ppAdvSink)
{
return E_NOTIMPL;
}
/*IOleInPlaceObjectWindowless*/
virtual HRESULT STDMETHODCALLTYPE OnWindowMessage(
/* [in] */ UINT msg,
/* [in] */ WPARAM wParam,
/* [in] */ LPARAM lParam,
/* [out] */ LRESULT *plResult)
{
switch(msg)
{
case WM_LBUTTONDOWN:
funcs->SetInteger(plug, funcs->FindProp(plug, "running"), 1);
return S_OK;
default:
return E_NOTIMPL;
}
}
virtual HRESULT STDMETHODCALLTYPE GetDropTarget(
/* [out] */ IDropTarget **ppDropTarget)
{
return E_NOTIMPL;
}
/*IPersist*/
virtual HRESULT STDMETHODCALLTYPE GetClassID(
/* [out] */ CLSID *pClassID)
{
return E_NOTIMPL;
}
/*IPersistPropertyBag2*/
virtual HRESULT STDMETHODCALLTYPE InitNew( void)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Load(
/* [in] */ IPropertyBag2 *pPropBag,
/* [in] */ IErrorLog *pErrLog)
{
PROPBAG2 prop[] =
{
{PROPBAG2_TYPE_DATA, VT_BSTR, 0, 0, (WCHAR *)L"splash", {0}},
{PROPBAG2_TYPE_DATA, VT_BSTR, 0, 0, (WCHAR *)L"game", {0}},
{PROPBAG2_TYPE_DATA, VT_BSTR, 0, 0, (WCHAR *)L"dataDownload", {0}}
};
VARIANT val[sizeof(prop)/sizeof(prop[0])];
HRESULT res[sizeof(prop)/sizeof(prop[0])];
memset(val, 0, sizeof(val));
pPropBag->Read(sizeof(prop)/sizeof(prop[0]), prop, NULL, val, res);
funcs->SetWString(plug, funcs->FindProp(plug, "splash"), val[0].bstrVal);
funcs->SetWString(plug, funcs->FindProp(plug, "game"), val[1].bstrVal);
funcs->SetWString(plug, funcs->FindProp(plug, "dataDownload"), val[2].bstrVal);
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Save(
/* [in] */ IPropertyBag2 *pPropBag,
/* [in] */ BOOL fClearDirty,
/* [in] */ BOOL fSaveAllProperties)
{
/*we don't actually save anything*/
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE IsDirty( void)
{
return E_NOTIMPL;
}
};
const struct browserfuncs axfte::axbrowserfuncs = {NULL, axfte::statuschanged};
extern "C"
{
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
*ppv = NULL;
if (rclsid == axfte_iid)
{
HRESULT res;
axfte *newaxfte = new axfte();
res = newaxfte->QueryInterface(riid, ppv);
if (!*ppv)
delete newaxfte;
return res;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
HRESULT WINAPI DllCanUnloadNow(void)
{
return S_OK;
}
struct
{
const char *key;
const char *value;
} regkeys[] =
{
{"Software\\Classes\\FTE.FTEPlug\\", "FTEPlug Class"},
{"Software\\Classes\\FTE.FTEPlug\\CurVer\\", "FTE.FTEPlug.1"},
{"Software\\Classes\\FTE.FTEPlug.1\\", "FTEPlug Class"},
{"Software\\Classes\\FTE.FTEPlug.1\\CLSID\\", "{"axfte_iid_str"}"},
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\", ""},
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\InprocHandler32\\", "ole32.dll"},
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\InprocServer32\\", "***DLLNAME***"},
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\InprocServer32\\ThreadingModel", "Apartment"},
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\Programmable\\", ""},
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\VersionIndependentProgID\\", "FTE.FTEPlug"},
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\ProgID\\", "FTE.FTEPlug.1.0"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Description", ENGINEWEBSITE},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\GeckoVersion", "1.00"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Path", "***DLLNAME***"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\ProductName", FULLENGINENAME},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Vendor", DISTRIBUTIONLONG},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Version", "***VERSION***"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\MimeTypes\\application/x-fteplugin\\Description", "FTE Game Engine Plugin"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\MimeTypes\\application/x-ftemanifest\\Description", "FTE Game File Manifest Listing"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\MimeTypes\\application/x-qtv\\Description", "QuakeTV Stream Information File"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\MimeTypes\\application/x-qtv\\Suffixes", "qtv"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Suffixes\\qtv", ""},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Suffixes\\mvd", ""},
{NULL}
};
HRESULT WINAPI DllRegisterServer(void)
{
char binaryname[1024];
char tmp[1024];
GetModuleFileName(global_hInstance, binaryname, sizeof(binaryname));
HKEY h;
bool allusers = false;
int i;
const char *ls;
for (i = 0; regkeys[i].key; i++)
{
ls = strrchr(regkeys[i].key, '\\') + 1;
memcpy(tmp, regkeys[i].key, ls - regkeys[i].key);
tmp[ls - regkeys[i].key] = 0;
if (RegCreateKeyExA(allusers?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, tmp, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &h, NULL))
continue;
if (!strcmp(regkeys[i].value, "***DLLNAME***"))
RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)binaryname, strlen(binaryname));
else if (!strcmp(regkeys[i].value, "***VERSION***"))
{
char s[128];
#ifdef OFFICIAL_RELEASE
Q_snprintfz(s, sizeof(s), "%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
#elif defined(SVNREVISION)
Q_snprintfz(s, sizeof(s), "%s SVN %s", DISTRIBUTION, STRINGIFY(SVNREVISION));
#else
Q_snprintfz(s, sizeof(s), "%s build %s", DISTRIBUTION, __DATE__);
#endif
RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)s, strlen(s));
}
else
RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)regkeys[i].value, strlen(regkeys[i].value));
RegCloseKey(h);
}
return S_OK;
}
HRESULT WINAPI DllUnregisterServer(void)
{
int i;
bool allusers = false;
const char *ls;
char tmp[1024];
HKEY h;
for (i = 0; regkeys[i].key; i++)
{
}
/*go backwards*/
for (i--; i>=0; i--)
{
ls = strrchr(regkeys[i].key, '\\') + 1;
memcpy(tmp, regkeys[i].key, ls - regkeys[i].key);
tmp[ls - regkeys[i].key] = 0;
if (*ls)
{
h = NULL;
if (!RegOpenKeyEx(allusers?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, tmp, 0, KEY_SET_VALUE, &h))
{
RegDeleteValue(h, ls);
RegCloseKey(h);
}
}
else
RegDeleteKey(allusers?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, tmp);
}
return S_OK;
}
}//externC
#endif