1 // Copyright 2002 Adam Megacz, ALL RIGHTS RESERVED
4 // A simple DLL to invoke xwt.exe and pass it any arguments found in the <object/> tag
16 // Globals ////////////////////////////////////////////////////////////////////////
20 #define CLSID_STRING_SIZE 39
22 const char XWT_friendlyName[] = "XWT ActiveX Control (build " BUILDID ")";
23 const char XWT_versionIndependantProgramID[] = "XWT.ActiveX";
24 const char XWT_programID[] = "XWT.ActiveX (build " BUILDID ")";
25 extern "C" const CLSID XWT_clsid = CLSID_STRUCT;
26 static HMODULE g_hModule = NULL; //DLL handle
31 // Superclasses ////////////////////////////////////////////////////////////////////////
33 // Option bit definitions for IObjectSafety:
34 #define INTERFACESAFE_FOR_UNTRUSTED_CALLER 0x00000001 // Caller of interface may be untrusted
35 #define INTERFACESAFE_FOR_UNTRUSTED_DATA 0x00000002 // Data passed into interface may be untrusted
37 // {CB5BDC81-93C1-11cf-8F20-00805F2CD064}
38 //DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f, 0x20, 0x0, 0x80, 0x5f, 0x2c, 0xd0, 0x64);
39 extern "C" const CLSID IID_IObjectSafety;
41 interface IObjectSafety : public IUnknown {
43 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions) = 0;
44 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) = 0;
47 interface IShoeHorn : IPersistPropertyBag, IObjectSafety { };
51 // Entry Points ////////////////////////////////////////////////////////////////////////
53 // to get mingw to stop nagging me
54 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { }
56 // determines whether or not the DLL can be unloaded; always allow this since we don't do too much
57 STDAPI __declspec(dllexport) DllCanUnloadNow(void) { return S_OK; }
59 extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID /*lpReserved*/) {
60 if (dwReason == DLL_PROCESS_ATTACH) g_hModule = (HINSTANCE)hModule;
66 // Other ///////////////////////////////////////////////////////////////////////////////////
68 // simple assert() replacement that pops open a message box if there are errors
69 void check(int val, char* message) {
71 MessageBox (NULL, message, "XWT Critical Abort", MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL | MB_SETFOREGROUND);
76 void clsidToString(const CLSID& clsid, char* str, int length) {
77 check(length >= CLSID_STRING_SIZE, "clsidToString(): string too short");
78 LPOLESTR wide_str = NULL;
79 HRESULT hr = StringFromCLSID(clsid, &wide_str);
80 check(SUCCEEDED(hr), "StringFromCLSID() failed in clsidToString()");
81 wcstombs(str, wide_str, length);
82 CoTaskMemFree(wide_str);
85 void setRegistryKey(const char* key, const char* subkey, const char* value) {
91 strcat(keyBuf, subkey );
93 long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, keyBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
95 check(RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value, strlen(value) + 1) == ERROR_SUCCESS,
96 "RegSetValueEx() failed in setRegistryKey()");
100 void deleteRegistryKey(HKEY parent, const char* target) {
102 RegOpenKeyEx(parent, target, 0, KEY_ALL_ACCESS, &hKeyChild);
104 // Iterate over children, deleting them
108 while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == S_OK) {
109 deleteRegistryKey(hKeyChild, szBuffer);
113 RegCloseKey(hKeyChild);
114 RegDeleteKey(parent, target);
117 STDAPI __declspec(dllexport) DllRegisterServer(void) {
118 char moduleName[512];
119 HRESULT result = GetModuleFileName(g_hModule, moduleName, sizeof(moduleName)/sizeof(char));
120 check(result, "GetModuleFileName() failed in RegisterServer()");
122 char clsidString[CLSID_STRING_SIZE];
123 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
127 strcpy(key, "CLSID\\");
128 strcat(key, clsidString);
130 setRegistryKey(key, NULL, XWT_friendlyName);
131 setRegistryKey(key, "InprocServer32", moduleName);
132 setRegistryKey(key, "ProgID", XWT_programID);
133 setRegistryKey(key, "VersionIndependentProgID", XWT_versionIndependantProgramID);
134 setRegistryKey(XWT_versionIndependantProgramID, NULL, XWT_friendlyName);
135 setRegistryKey(XWT_versionIndependantProgramID, "CLSID", clsidString);
136 setRegistryKey(XWT_versionIndependantProgramID, "CurVer", XWT_programID);
137 setRegistryKey(XWT_programID, NULL, XWT_friendlyName);
138 setRegistryKey(XWT_programID, "CLSID", clsidString);
142 STDAPI __declspec(dllexport) DllUnregisterServer(void) {
143 char clsidString[CLSID_STRING_SIZE];
144 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
148 strcpy(key, "CLSID\\");
149 strcat(key, clsidString);
151 deleteRegistryKey(HKEY_CLASSES_ROOT, key);
152 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_versionIndependantProgramID);
153 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_programID);
159 // ShoeHorn //////////////////////////////////////////////////////////////////////////////////
161 class ShoeHorn : public IShoeHorn {
163 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
164 if(iid == IID_IUnknown) *ppv = static_cast<IShoeHorn*>(this);
165 else if(iid == XWT_clsid) *ppv = static_cast<IShoeHorn*>(this);
166 else if(iid == IID_IPersistPropertyBag) *ppv = static_cast<IPersistPropertyBag*>(this);
167 else if(iid == IID_IObjectSafety) *ppv = static_cast<IObjectSafety*>(this);
168 else { *ppv = NULL; return E_NOINTERFACE; }
169 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
172 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
173 virtual ULONG __stdcall Release() {
174 if(InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; }
177 virtual HRESULT __stdcall GetClassID(CLSID*) { return S_OK; }
178 virtual HRESULT __stdcall InitNew() { return S_OK; }
179 virtual HRESULT __stdcall Save(IPropertyBag*, int, int) { return S_OK; }
180 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD pdwSupportedOptions, DWORD pdwEnabledOptions) { return S_OK; }
181 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD* pdwSupportedOptions, DWORD* pdwEnabledOptions) {
182 if (pdwSupportedOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
183 if (pdwEnabledOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
187 virtual HRESULT __stdcall Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog) {
195 MultiByteToWideChar(CP_ACP, 0, "xwar", -1, wc, 100);
196 pPropBag->Read(wc, &v, pErrorLog);
197 check(WideCharToMultiByte(CP_ACP, 0, v.bstrVal, -1, url, 100, NULL, NULL),
198 "WideCharToMultiByte() failed in ShoeHorn::Load()");
201 LONG result = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ActiveX Cache", &hkey);
202 check(result == ERROR_SUCCESS, "RegOpenKey() failed in ShoeHorn::Load()");
204 // iterate over all the activex cache locations until we find ourselves
205 for(int i=0; i<9; i++) {
214 result = RegQueryValueEx(hkey, which, NULL, &type, (BYTE*)buf, &buflen);
215 if (result != ERROR_SUCCESS)
217 check(0, "RegQueryValueEx() failed in ShoeHorn::Load()");
224 for(int i=0; i<200; i++) cmdline[i] = '\0';
225 strncpy(cmdline, buf, 200);
226 strncpy(cmdline + strlen(cmdline), "\\xwt-" BUILDID ".exe", 200 - strlen(cmdline));
227 strncpy(cmdline + strlen(cmdline), " ", 200 - strlen(cmdline));
228 strncpy(cmdline + strlen(cmdline), url, 200 - strlen(cmdline));
230 PROCESS_INFORMATION pInfo;
232 sInfo.cb = sizeof(STARTUPINFO);
233 sInfo.lpReserved = NULL;
234 sInfo.lpReserved2 = NULL;
235 sInfo.cbReserved2 = 0;
236 sInfo.lpDesktop = NULL;
237 sInfo.lpTitle = NULL;
241 sInfo.dwFillAttribute = 0;
242 sInfo.wShowWindow = SW_SHOW;
243 BOOL b = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo);
247 check(0, "unable to locate xwt-" BUILDID ".exe in ActiveX cache folders");
250 ShoeHorn() : m_cRef(1) { };
252 private: long m_cRef;
258 // ClassFactory //////////////////////////////////////////////////////////////////////////
260 class ClassFactory : public IClassFactory {
262 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
263 if(iid == IID_IUnknown) *ppv = static_cast<IClassFactory*>(this);
264 else if(iid == IID_IClassFactory) *ppv = static_cast<IClassFactory*>(this);
267 return E_NOINTERFACE;
269 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
273 ClassFactory() : m_cRef(1) { }
275 virtual HRESULT __stdcall LockServer(BOOL bLock) { return S_OK; }
276 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
277 virtual ULONG __stdcall Release() {
278 if(InterlockedDecrement(&m_cRef) == 0) {
285 virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) {
286 if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
287 ShoeHorn* s = new ShoeHorn;
288 if(s == NULL) return E_OUTOFMEMORY;
289 HRESULT hr = s->QueryInterface(iid, ppv);
294 private: long m_cRef;
298 extern "C" __stdcall HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) {
299 if(clsid != XWT_clsid) return CLASS_E_CLASSNOTAVAILABLE;
300 ClassFactory* pFactory = new ClassFactory;
301 if(pFactory == NULL) return E_OUTOFMEMORY;
302 HRESULT hr = pFactory->QueryInterface(iid, ppv);