1 /* 2 * Copyright 2011 Hans Leidekker 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 #define COBJMACROS 19 20 #include <stdarg.h> 21 22 #include "windef.h" 23 #include "winbase.h" 24 #include "ole2.h" 25 #include "olectl.h" 26 #include "rpcproxy.h" 27 28 #include <initguid.h> 29 #include "scrrun.h" 30 #include "scrrun_private.h" 31 32 #include "wine/debug.h" 33 34 WINE_DEFAULT_DEBUG_CHANNEL(scrrun); 35 36 static HINSTANCE scrrun_instance; 37 38 static inline struct provideclassinfo *impl_from_IProvideClassInfo(IProvideClassInfo *iface) 39 { 40 return CONTAINING_RECORD(iface, struct provideclassinfo, IProvideClassInfo_iface); 41 } 42 43 typedef HRESULT (*fnCreateInstance)(LPVOID *ppObj); 44 45 static HRESULT WINAPI scrruncf_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv ) 46 { 47 *ppv = NULL; 48 49 if(IsEqualGUID(&IID_IUnknown, riid)) { 50 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); 51 *ppv = iface; 52 }else if(IsEqualGUID(&IID_IClassFactory, riid)) { 53 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); 54 *ppv = iface; 55 } 56 57 if(*ppv) { 58 IUnknown_AddRef((IUnknown*)*ppv); 59 return S_OK; 60 } 61 62 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv); 63 return E_NOINTERFACE; 64 } 65 66 static ULONG WINAPI scrruncf_AddRef(IClassFactory *iface ) 67 { 68 TRACE("(%p)\n", iface); 69 return 2; 70 } 71 72 static ULONG WINAPI scrruncf_Release(IClassFactory *iface ) 73 { 74 TRACE("(%p)\n", iface); 75 return 1; 76 } 77 78 static HRESULT WINAPI scrruncf_LockServer(IClassFactory *iface, BOOL fLock) 79 { 80 TRACE("(%p)->(%x)\n", iface, fLock); 81 return S_OK; 82 } 83 84 static const struct IClassFactoryVtbl scrruncf_vtbl = 85 { 86 scrruncf_QueryInterface, 87 scrruncf_AddRef, 88 scrruncf_Release, 89 FileSystem_CreateInstance, 90 scrruncf_LockServer 91 }; 92 93 static const struct IClassFactoryVtbl dictcf_vtbl = 94 { 95 scrruncf_QueryInterface, 96 scrruncf_AddRef, 97 scrruncf_Release, 98 Dictionary_CreateInstance, 99 scrruncf_LockServer 100 }; 101 102 static IClassFactory FileSystemFactory = { &scrruncf_vtbl }; 103 static IClassFactory DictionaryFactory = { &dictcf_vtbl }; 104 105 static ITypeLib *typelib; 106 static ITypeInfo *typeinfos[LAST_tid]; 107 108 static REFIID tid_ids[] = { 109 &IID_NULL, 110 &IID_IDictionary, 111 &IID_IDrive, 112 &IID_IDriveCollection, 113 &IID_IFile, 114 &IID_IFileCollection, 115 &IID_IFileSystem3, 116 &IID_IFolder, 117 &IID_IFolderCollection, 118 &IID_ITextStream 119 }; 120 121 static HRESULT load_typelib(void) 122 { 123 HRESULT hres; 124 ITypeLib *tl; 125 126 if(typelib) 127 return S_OK; 128 129 hres = LoadRegTypeLib(&LIBID_Scripting, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl); 130 if(FAILED(hres)) { 131 ERR("LoadRegTypeLib failed: %08x\n", hres); 132 return hres; 133 } 134 135 if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL)) 136 ITypeLib_Release(tl); 137 return hres; 138 } 139 140 static HRESULT get_typeinfo_of_guid(const GUID *guid, ITypeInfo **tinfo) 141 { 142 HRESULT hres; 143 144 if(FAILED(hres = load_typelib())) 145 return hres; 146 147 return ITypeLib_GetTypeInfoOfGuid(typelib, guid, tinfo); 148 } 149 150 HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) 151 { 152 HRESULT hres; 153 154 if (FAILED(hres = load_typelib())) 155 return hres; 156 157 if(!typeinfos[tid]) { 158 ITypeInfo *ti; 159 160 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti); 161 if(FAILED(hres)) { 162 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres); 163 return hres; 164 } 165 166 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL)) 167 ITypeInfo_Release(ti); 168 } 169 170 *typeinfo = typeinfos[tid]; 171 ITypeInfo_AddRef(typeinfos[tid]); 172 return S_OK; 173 } 174 175 static void release_typelib(void) 176 { 177 unsigned i; 178 179 if(!typelib) 180 return; 181 182 for (i = 0; i < ARRAY_SIZE(typeinfos); i++) 183 if(typeinfos[i]) 184 ITypeInfo_Release(typeinfos[i]); 185 186 ITypeLib_Release(typelib); 187 } 188 189 static HRESULT WINAPI provideclassinfo_QueryInterface(IProvideClassInfo *iface, REFIID riid, void **obj) 190 { 191 struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); 192 193 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); 194 195 if (IsEqualIID(riid, &IID_IProvideClassInfo)) { 196 *obj = iface; 197 IProvideClassInfo_AddRef(iface); 198 return S_OK; 199 } 200 else 201 return IUnknown_QueryInterface(This->outer, riid, obj); 202 } 203 204 static ULONG WINAPI provideclassinfo_AddRef(IProvideClassInfo *iface) 205 { 206 struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); 207 return IUnknown_AddRef(This->outer); 208 } 209 210 static ULONG WINAPI provideclassinfo_Release(IProvideClassInfo *iface) 211 { 212 struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); 213 return IUnknown_Release(This->outer); 214 } 215 216 static HRESULT WINAPI provideclassinfo_GetClassInfo(IProvideClassInfo *iface, ITypeInfo **ti) 217 { 218 struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); 219 220 TRACE("(%p)->(%p)\n", This, ti); 221 222 return get_typeinfo_of_guid(This->guid, ti); 223 } 224 225 static const IProvideClassInfoVtbl provideclassinfovtbl = { 226 provideclassinfo_QueryInterface, 227 provideclassinfo_AddRef, 228 provideclassinfo_Release, 229 provideclassinfo_GetClassInfo 230 }; 231 232 void init_classinfo(const GUID *guid, IUnknown *outer, struct provideclassinfo *classinfo) 233 { 234 classinfo->IProvideClassInfo_iface.lpVtbl = &provideclassinfovtbl; 235 classinfo->outer = outer; 236 classinfo->guid = guid; 237 } 238 239 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) 240 { 241 TRACE("%p, %u, %p\n", hinst, reason, reserved); 242 243 switch (reason) 244 { 245 case DLL_WINE_PREATTACH: 246 return FALSE; /* prefer native version */ 247 case DLL_PROCESS_ATTACH: 248 DisableThreadLibraryCalls( hinst ); 249 scrrun_instance = hinst; 250 break; 251 case DLL_PROCESS_DETACH: 252 if (reserved) break; 253 release_typelib(); 254 break; 255 } 256 return TRUE; 257 } 258 259 /*********************************************************************** 260 * DllRegisterServer (scrrun.@) 261 */ 262 HRESULT WINAPI DllRegisterServer(void) 263 { 264 TRACE("()\n"); 265 return __wine_register_resources(scrrun_instance); 266 } 267 268 /*********************************************************************** 269 * DllUnregisterServer (scrrun.@) 270 */ 271 HRESULT WINAPI DllUnregisterServer(void) 272 { 273 TRACE("()\n"); 274 return __wine_unregister_resources(scrrun_instance); 275 } 276 277 /*********************************************************************** 278 * DllGetClassObject (scrrun.@) 279 */ 280 281 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) 282 { 283 if(IsEqualGUID(&CLSID_FileSystemObject, rclsid)) { 284 TRACE("(CLSID_FileSystemObject %s %p)\n", debugstr_guid(riid), ppv); 285 return IClassFactory_QueryInterface(&FileSystemFactory, riid, ppv); 286 } 287 else if(IsEqualGUID(&CLSID_Dictionary, rclsid)) { 288 TRACE("(CLSID_Dictionary %s %p)\n", debugstr_guid(riid), ppv); 289 return IClassFactory_QueryInterface(&DictionaryFactory, riid, ppv); 290 } 291 292 FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 293 return CLASS_E_CLASSNOTAVAILABLE; 294 } 295 296 /*********************************************************************** 297 * DllCanUnloadNow (scrrun.@) 298 */ 299 HRESULT WINAPI DllCanUnloadNow(void) 300 { 301 return S_FALSE; 302 } 303