1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the GNU General Public License version 2 ("the License").
3 // You may not use this file except in compliance with the License.
6 // A simple DLL to invoke xwt.exe and pass it any arguments found in the <object/> tag
18 // Globals ////////////////////////////////////////////////////////////////////////
22 #define CLSID_STRING_SIZE 39
24 const char XWT_friendlyName[] = "XWT ActiveX Control (build " BUILDID ")";
25 const char XWT_versionIndependantProgramID[] = "XWT.ActiveX";
26 const char XWT_programID[] = "XWT.ActiveX (build " BUILDID ")";
27 extern "C" const CLSID XWT_clsid = CLSID_STRUCT;
28 static HMODULE g_hModule = NULL; //DLL handle
33 // Superclasses ////////////////////////////////////////////////////////////////////////
35 // Option bit definitions for IObjectSafety:
36 #define INTERFACESAFE_FOR_UNTRUSTED_CALLER 0x00000001 // Caller of interface may be untrusted
37 #define INTERFACESAFE_FOR_UNTRUSTED_DATA 0x00000002 // Data passed into interface may be untrusted
39 // {CB5BDC81-93C1-11cf-8F20-00805F2CD064}
40 //DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f, 0x20, 0x0, 0x80, 0x5f, 0x2c, 0xd0, 0x64);
41 extern "C" const CLSID IID_IObjectSafety;
43 interface IObjectSafety : public IUnknown {
45 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions) = 0;
46 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) = 0;
49 interface IShoeHorn : IPersistPropertyBag, IObjectSafety { };
53 // Entry Points ////////////////////////////////////////////////////////////////////////
55 // to get mingw to stop nagging me
56 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { }
58 // determines whether or not the DLL can be unloaded; always allow this since we don't do too much
59 STDAPI __declspec(dllexport) DllCanUnloadNow(void) { return S_OK; }
61 extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID /*lpReserved*/) {
62 if (dwReason == DLL_PROCESS_ATTACH) g_hModule = (HINSTANCE)hModule;
68 // Other ///////////////////////////////////////////////////////////////////////////////////
70 // simple assert() replacement that pops open a message box if there are errors
71 void check(int val, char* message) {
73 MessageBox (NULL, message, "XWT Critical Abort", MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL | MB_SETFOREGROUND);
78 void clsidToString(const CLSID& clsid, char* str, int length) {
79 check(length >= CLSID_STRING_SIZE, "clsidToString(): string too short");
80 LPOLESTR wide_str = NULL;
81 HRESULT hr = StringFromCLSID(clsid, &wide_str);
82 check(SUCCEEDED(hr), "StringFromCLSID() failed in clsidToString()");
83 wcstombs(str, wide_str, length);
84 CoTaskMemFree(wide_str);
87 void setRegistryKey(const char* key, const char* subkey, const char* value) {
93 strcat(keyBuf, subkey );
95 long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, keyBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
97 check(RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value, strlen(value) + 1) == ERROR_SUCCESS,
98 "RegSetValueEx() failed in setRegistryKey()");
102 void deleteRegistryKey(HKEY parent, const char* target) {
104 RegOpenKeyEx(parent, target, 0, KEY_ALL_ACCESS, &hKeyChild);
106 // Iterate over children, deleting them
110 while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == S_OK) {
111 deleteRegistryKey(hKeyChild, szBuffer);
115 RegCloseKey(hKeyChild);
116 RegDeleteKey(parent, target);
119 STDAPI __declspec(dllexport) DllRegisterServer(void) {
120 char moduleName[512];
121 HRESULT result = GetModuleFileName(g_hModule, moduleName, sizeof(moduleName)/sizeof(char));
122 check(result, "GetModuleFileName() failed in RegisterServer()");
124 char clsidString[CLSID_STRING_SIZE];
125 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
129 strcpy(key, "CLSID\\");
130 strcat(key, clsidString);
132 setRegistryKey(key, NULL, XWT_friendlyName);
133 setRegistryKey(key, "InprocServer32", moduleName);
134 setRegistryKey(key, "ProgID", XWT_programID);
135 setRegistryKey(key, "VersionIndependentProgID", XWT_versionIndependantProgramID);
136 setRegistryKey(XWT_versionIndependantProgramID, NULL, XWT_friendlyName);
137 setRegistryKey(XWT_versionIndependantProgramID, "CLSID", clsidString);
138 setRegistryKey(XWT_versionIndependantProgramID, "CurVer", XWT_programID);
139 setRegistryKey(XWT_programID, NULL, XWT_friendlyName);
140 setRegistryKey(XWT_programID, "CLSID", clsidString);
144 STDAPI __declspec(dllexport) DllUnregisterServer(void) {
145 char clsidString[CLSID_STRING_SIZE];
146 clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
150 strcpy(key, "CLSID\\");
151 strcat(key, clsidString);
153 deleteRegistryKey(HKEY_CLASSES_ROOT, key);
154 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_versionIndependantProgramID);
155 deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_programID);
161 // ShoeHorn //////////////////////////////////////////////////////////////////////////////////
163 class ShoeHorn : public IShoeHorn {
165 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
166 if(iid == IID_IUnknown) *ppv = static_cast<IShoeHorn*>(this);
167 else if(iid == XWT_clsid) *ppv = static_cast<IShoeHorn*>(this);
168 else if(iid == IID_IPersistPropertyBag) *ppv = static_cast<IPersistPropertyBag*>(this);
169 else if(iid == IID_IObjectSafety) *ppv = static_cast<IObjectSafety*>(this);
170 else { *ppv = NULL; return E_NOINTERFACE; }
171 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
174 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
175 virtual ULONG __stdcall Release() {
176 if(InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; }
179 virtual HRESULT __stdcall GetClassID(CLSID*) { return S_OK; }
180 virtual HRESULT __stdcall InitNew() { return S_OK; }
181 virtual HRESULT __stdcall Save(IPropertyBag*, int, int) { return S_OK; }
182 virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD pdwSupportedOptions, DWORD pdwEnabledOptions) { return S_OK; }
183 virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD* pdwSupportedOptions, DWORD* pdwEnabledOptions) {
184 if (pdwSupportedOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
185 if (pdwEnabledOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
189 virtual HRESULT __stdcall Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog) {
197 MultiByteToWideChar(CP_ACP, 0, "xwar", -1, wc, 100);
198 pPropBag->Read(wc, &v, pErrorLog);
199 check(WideCharToMultiByte(CP_ACP, 0, v.bstrVal, -1, url, 100, NULL, NULL),
200 "WideCharToMultiByte() failed in ShoeHorn::Load()");
203 LONG result = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ActiveX Cache", &hkey);
204 check(result == ERROR_SUCCESS, "RegOpenKey() failed in ShoeHorn::Load()");
206 // iterate over all the activex cache locations until we find ourselves
207 for(int i=0; i<9; i++) {
216 result = RegQueryValueEx(hkey, which, NULL, &type, (BYTE*)buf, &buflen);
217 if (result != ERROR_SUCCESS)
219 check(0, "RegQueryValueEx() failed in ShoeHorn::Load()");
226 for(int i=0; i<200; i++) cmdline[i] = '\0';
227 strncpy(cmdline, buf, 200);
228 strncpy(cmdline + strlen(cmdline), "\\xwt-" BUILDID ".exe", 200 - strlen(cmdline));
229 strncpy(cmdline + strlen(cmdline), " ", 200 - strlen(cmdline));
230 strncpy(cmdline + strlen(cmdline), url, 200 - strlen(cmdline));
232 PROCESS_INFORMATION pInfo;
234 sInfo.cb = sizeof(STARTUPINFO);
235 sInfo.lpReserved = NULL;
236 sInfo.lpReserved2 = NULL;
237 sInfo.cbReserved2 = 0;
238 sInfo.lpDesktop = NULL;
239 sInfo.lpTitle = NULL;
243 sInfo.dwFillAttribute = 0;
244 sInfo.wShowWindow = SW_SHOW;
245 BOOL b = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo);
249 check(0, "unable to locate xwt-" BUILDID ".exe in ActiveX cache folders");
252 ShoeHorn() : m_cRef(1) { };
254 private: long m_cRef;
260 // ClassFactory //////////////////////////////////////////////////////////////////////////
262 class ClassFactory : public IClassFactory {
264 virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
265 if(iid == IID_IUnknown) *ppv = static_cast<IClassFactory*>(this);
266 else if(iid == IID_IClassFactory) *ppv = static_cast<IClassFactory*>(this);
269 return E_NOINTERFACE;
271 reinterpret_cast<IUnknown*>(*ppv)->AddRef();
275 ClassFactory() : m_cRef(1) { }
277 virtual HRESULT __stdcall LockServer(BOOL bLock) { return S_OK; }
278 virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
279 virtual ULONG __stdcall Release() {
280 if(InterlockedDecrement(&m_cRef) == 0) {
287 virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) {
288 if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
289 ShoeHorn* s = new ShoeHorn;
290 if(s == NULL) return E_OUTOFMEMORY;
291 HRESULT hr = s->QueryInterface(iid, ppv);
296 private: long m_cRef;
300 extern "C" __stdcall HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) {
301 if(clsid != XWT_clsid) return CLASS_E_CLASSNOTAVAILABLE;
302 ClassFactory* pFactory = new ClassFactory;
303 if(pFactory == NULL) return E_OUTOFMEMORY;
304 HRESULT hr = pFactory->QueryInterface(iid, ppv);