1 /* 2 * Copyright 2011 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "wshom_private.h" 20 21 #include "initguid.h" 22 #include "wshom.h" 23 #include "rpcproxy.h" 24 25 #include "wine/debug.h" 26 27 WINE_DEFAULT_DEBUG_CHANNEL(wshom); 28 29 static HINSTANCE wshom_instance; 30 31 static inline struct provideclassinfo *impl_from_IProvideClassInfo(IProvideClassInfo *iface) 32 { 33 return CONTAINING_RECORD(iface, struct provideclassinfo, IProvideClassInfo_iface); 34 } 35 36 static ITypeLib *typelib; 37 static ITypeInfo *typeinfos[LAST_tid]; 38 39 static REFIID tid_ids[] = { 40 &IID_NULL, 41 &IID_IWshCollection, 42 &IID_IWshEnvironment, 43 &IID_IWshExec, 44 &IID_IWshShell3, 45 &IID_IWshShortcut 46 }; 47 48 static HRESULT load_typelib(void) 49 { 50 HRESULT hres; 51 ITypeLib *tl; 52 53 if(typelib) 54 return S_OK; 55 56 hres = LoadRegTypeLib(&LIBID_IWshRuntimeLibrary, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl); 57 if(FAILED(hres)) { 58 ERR("LoadRegTypeLib failed: %08x\n", hres); 59 return hres; 60 } 61 62 if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL)) 63 ITypeLib_Release(tl); 64 return hres; 65 } 66 67 static HRESULT get_typeinfo_of_guid(const GUID *guid, ITypeInfo **tinfo) 68 { 69 HRESULT hres; 70 71 if(FAILED(hres = load_typelib())) 72 return hres; 73 74 return ITypeLib_GetTypeInfoOfGuid(typelib, guid, tinfo); 75 } 76 77 HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) 78 { 79 HRESULT hres; 80 81 if (FAILED(hres = load_typelib())) 82 return hres; 83 84 if(!typeinfos[tid]) { 85 ITypeInfo *ti; 86 87 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti); 88 if(FAILED(hres)) { 89 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres); 90 return hres; 91 } 92 93 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL)) 94 ITypeInfo_Release(ti); 95 } 96 97 *typeinfo = typeinfos[tid]; 98 ITypeInfo_AddRef(*typeinfo); 99 return S_OK; 100 } 101 102 static 103 void release_typelib(void) 104 { 105 unsigned i; 106 107 if(!typelib) 108 return; 109 110 for(i = 0; i < ARRAY_SIZE(typeinfos); i++) 111 if(typeinfos[i]) 112 ITypeInfo_Release(typeinfos[i]); 113 114 ITypeLib_Release(typelib); 115 } 116 117 static HRESULT WINAPI provideclassinfo_QueryInterface(IProvideClassInfo *iface, REFIID riid, void **obj) 118 { 119 struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); 120 121 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); 122 123 if (IsEqualIID(riid, &IID_IProvideClassInfo)) { 124 *obj = iface; 125 IProvideClassInfo_AddRef(iface); 126 return S_OK; 127 } 128 else 129 return IUnknown_QueryInterface(This->outer, riid, obj); 130 } 131 132 static ULONG WINAPI provideclassinfo_AddRef(IProvideClassInfo *iface) 133 { 134 struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); 135 return IUnknown_AddRef(This->outer); 136 } 137 138 static ULONG WINAPI provideclassinfo_Release(IProvideClassInfo *iface) 139 { 140 struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); 141 return IUnknown_Release(This->outer); 142 } 143 144 static HRESULT WINAPI provideclassinfo_GetClassInfo(IProvideClassInfo *iface, ITypeInfo **ti) 145 { 146 struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); 147 148 TRACE("(%p)->(%p)\n", This, ti); 149 150 return get_typeinfo_of_guid(This->guid, ti); 151 } 152 153 static const IProvideClassInfoVtbl provideclassinfovtbl = { 154 provideclassinfo_QueryInterface, 155 provideclassinfo_AddRef, 156 provideclassinfo_Release, 157 provideclassinfo_GetClassInfo 158 }; 159 160 void init_classinfo(const GUID *guid, IUnknown *outer, struct provideclassinfo *classinfo) 161 { 162 classinfo->IProvideClassInfo_iface.lpVtbl = &provideclassinfovtbl; 163 classinfo->outer = outer; 164 classinfo->guid = guid; 165 } 166 167 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) 168 { 169 *ppv = NULL; 170 171 if(IsEqualGUID(&IID_IUnknown, riid)) { 172 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); 173 *ppv = iface; 174 }else if(IsEqualGUID(&IID_IClassFactory, riid)) { 175 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); 176 *ppv = iface; 177 } 178 179 if(*ppv) { 180 IUnknown_AddRef((IUnknown*)*ppv); 181 return S_OK; 182 } 183 184 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv); 185 return E_NOINTERFACE; 186 } 187 188 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) 189 { 190 TRACE("(%p)\n", iface); 191 return 2; 192 } 193 194 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) 195 { 196 TRACE("(%p)\n", iface); 197 return 1; 198 } 199 200 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) 201 { 202 TRACE("(%p)->(%x)\n", iface, fLock); 203 return S_OK; 204 } 205 206 static const IClassFactoryVtbl WshShellFactoryVtbl = { 207 ClassFactory_QueryInterface, 208 ClassFactory_AddRef, 209 ClassFactory_Release, 210 WshShellFactory_CreateInstance, 211 ClassFactory_LockServer 212 }; 213 214 static IClassFactory WshShellFactory = { &WshShellFactoryVtbl }; 215 216 /****************************************************************** 217 * DllMain (wshom.ocx.@) 218 */ 219 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) 220 { 221 TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpv); 222 223 switch(fdwReason) 224 { 225 case DLL_WINE_PREATTACH: 226 return FALSE; /* prefer native version */ 227 case DLL_PROCESS_ATTACH: 228 wshom_instance = hInstDLL; 229 DisableThreadLibraryCalls(wshom_instance); 230 break; 231 case DLL_PROCESS_DETACH: 232 if (lpv) break; 233 release_typelib(); 234 break; 235 } 236 237 return TRUE; 238 } 239 240 /*********************************************************************** 241 * DllGetClassObject (wshom.ocx.@) 242 */ 243 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 244 { 245 if(IsEqualGUID(&CLSID_WshShell, rclsid)) { 246 TRACE("(CLSID_WshShell %s %p)\n", debugstr_guid(riid), ppv); 247 return IClassFactory_QueryInterface(&WshShellFactory, riid, ppv); 248 } 249 250 FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 251 return CLASS_E_CLASSNOTAVAILABLE; 252 } 253 254 /*********************************************************************** 255 * DllCanUnloadNow (wshom.ocx.@) 256 */ 257 HRESULT WINAPI DllCanUnloadNow(void) 258 { 259 return S_FALSE; 260 } 261 262 /*********************************************************************** 263 * DllRegisterServer (wshom.ocx.@) 264 */ 265 HRESULT WINAPI DllRegisterServer(void) 266 { 267 TRACE("()\n"); 268 return __wine_register_resources(wshom_instance); 269 } 270 271 /*********************************************************************** 272 * DllUnregisterServer (wshom.ocx.@) 273 */ 274 HRESULT WINAPI DllUnregisterServer(void) 275 { 276 TRACE("()\n"); 277 return __wine_unregister_resources(wshom_instance); 278 } 279