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 "initguid.h" 20 21 #include "vbscript.h" 22 #include "objsafe.h" 23 #include "mshtmhst.h" 24 #include "rpcproxy.h" 25 #include "vbscript_classes.h" 26 #include "vbsglobal.h" 27 #include "vbsregexp55.h" 28 29 #include "wine/debug.h" 30 31 WINE_DEFAULT_DEBUG_CHANNEL(vbscript); 32 WINE_DECLARE_DEBUG_CHANNEL(heap); 33 34 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); 35 36 static HINSTANCE vbscript_hinstance; 37 38 static ITypeLib *typelib; 39 static ITypeInfo *typeinfos[LAST_tid]; 40 41 static REFIID tid_ids[] = { 42 #define XDIID(iface) &DIID_ ## iface, 43 TID_LIST 44 #undef XDIID 45 }; 46 47 HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) 48 { 49 HRESULT hres; 50 51 if (!typelib) { 52 ITypeLib *tl; 53 54 static const WCHAR vbscript_dll1W[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','1',0}; 55 56 hres = LoadTypeLib(vbscript_dll1W, &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 } 65 66 if(!typeinfos[tid]) { 67 ITypeInfo *ti; 68 69 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti); 70 if(FAILED(hres)) { 71 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres); 72 return hres; 73 } 74 75 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL)) 76 ITypeInfo_Release(ti); 77 } 78 79 *typeinfo = typeinfos[tid]; 80 return S_OK; 81 } 82 83 static void release_typelib(void) 84 { 85 unsigned i; 86 87 if(!typelib) 88 return; 89 90 for(i=0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++) { 91 if(typeinfos[i]) 92 ITypeInfo_Release(typeinfos[i]); 93 } 94 95 ITypeLib_Release(typelib); 96 } 97 98 #define MIN_BLOCK_SIZE 128 99 #define ARENA_FREE_FILLER 0xaa 100 101 static inline DWORD block_size(DWORD block) 102 { 103 return MIN_BLOCK_SIZE << block; 104 } 105 106 void heap_pool_init(heap_pool_t *heap) 107 { 108 memset(heap, 0, sizeof(*heap)); 109 list_init(&heap->custom_blocks); 110 } 111 112 void *heap_pool_alloc(heap_pool_t *heap, size_t size) 113 { 114 struct list *list; 115 void *tmp; 116 117 size = (size+3)&~3; 118 119 if(!heap->block_cnt) { 120 if(!heap->blocks) { 121 heap->blocks = heap_alloc(sizeof(void*)); 122 if(!heap->blocks) 123 return NULL; 124 } 125 126 tmp = heap_alloc(block_size(0)); 127 if(!tmp) 128 return NULL; 129 130 heap->blocks[0] = tmp; 131 heap->block_cnt = 1; 132 } 133 134 if(heap->offset + size <= block_size(heap->last_block)) { 135 tmp = ((BYTE*)heap->blocks[heap->last_block])+heap->offset; 136 heap->offset += size; 137 return tmp; 138 } 139 140 if(size <= block_size(heap->last_block+1)) { 141 if(heap->last_block+1 == heap->block_cnt) { 142 tmp = heap_realloc(heap->blocks, (heap->block_cnt+1)*sizeof(void*)); 143 if(!tmp) 144 return NULL; 145 146 heap->blocks = tmp; 147 heap->blocks[heap->block_cnt] = heap_alloc(block_size(heap->block_cnt)); 148 if(!heap->blocks[heap->block_cnt]) 149 return NULL; 150 151 heap->block_cnt++; 152 } 153 154 heap->last_block++; 155 heap->offset = size; 156 return heap->blocks[heap->last_block]; 157 } 158 159 list = heap_alloc(size + sizeof(struct list)); 160 if(!list) 161 return NULL; 162 163 list_add_head(&heap->custom_blocks, list); 164 return list+1; 165 } 166 167 void *heap_pool_grow(heap_pool_t *heap, void *mem, DWORD size, DWORD inc) 168 { 169 void *ret; 170 171 if(mem == (BYTE*)heap->blocks[heap->last_block] + heap->offset-size 172 && heap->offset+inc < block_size(heap->last_block)) { 173 heap->offset += inc; 174 return mem; 175 } 176 177 ret = heap_pool_alloc(heap, size+inc); 178 if(ret) /* FIXME: avoid copying for custom blocks */ 179 memcpy(ret, mem, size); 180 return ret; 181 } 182 183 void heap_pool_clear(heap_pool_t *heap) 184 { 185 struct list *tmp; 186 187 if(!heap) 188 return; 189 190 while((tmp = list_next(&heap->custom_blocks, &heap->custom_blocks))) { 191 list_remove(tmp); 192 heap_free(tmp); 193 } 194 195 if(WARN_ON(heap)) { 196 DWORD i; 197 198 for(i=0; i < heap->block_cnt; i++) 199 memset(heap->blocks[i], ARENA_FREE_FILLER, block_size(i)); 200 } 201 202 heap->last_block = heap->offset = 0; 203 heap->mark = FALSE; 204 } 205 206 void heap_pool_free(heap_pool_t *heap) 207 { 208 DWORD i; 209 210 heap_pool_clear(heap); 211 212 for(i=0; i < heap->block_cnt; i++) 213 heap_free(heap->blocks[i]); 214 heap_free(heap->blocks); 215 216 heap_pool_init(heap); 217 } 218 219 heap_pool_t *heap_pool_mark(heap_pool_t *heap) 220 { 221 if(heap->mark) 222 return NULL; 223 224 heap->mark = TRUE; 225 return heap; 226 } 227 228 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) 229 { 230 *ppv = NULL; 231 232 if(IsEqualGUID(&IID_IUnknown, riid)) { 233 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); 234 *ppv = iface; 235 }else if(IsEqualGUID(&IID_IClassFactory, riid)) { 236 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); 237 *ppv = iface; 238 } 239 240 if(*ppv) { 241 IUnknown_AddRef((IUnknown*)*ppv); 242 return S_OK; 243 } 244 245 FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv); 246 return E_NOINTERFACE; 247 } 248 249 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) 250 { 251 TRACE("(%p)\n", iface); 252 return 2; 253 } 254 255 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) 256 { 257 TRACE("(%p)\n", iface); 258 return 1; 259 } 260 261 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) 262 { 263 TRACE("(%p)->(%x)\n", iface, fLock); 264 return S_OK; 265 } 266 267 static const IClassFactoryVtbl VBScriptFactoryVtbl = { 268 ClassFactory_QueryInterface, 269 ClassFactory_AddRef, 270 ClassFactory_Release, 271 VBScriptFactory_CreateInstance, 272 ClassFactory_LockServer 273 }; 274 275 static IClassFactory VBScriptFactory = { &VBScriptFactoryVtbl }; 276 277 static const IClassFactoryVtbl VBScriptRegExpFactoryVtbl = { 278 ClassFactory_QueryInterface, 279 ClassFactory_AddRef, 280 ClassFactory_Release, 281 VBScriptRegExpFactory_CreateInstance, 282 ClassFactory_LockServer 283 }; 284 285 static IClassFactory VBScriptRegExpFactory = { &VBScriptRegExpFactoryVtbl }; 286 287 /****************************************************************** 288 * DllMain (vbscript.@) 289 */ 290 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) 291 { 292 TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpv); 293 294 switch(fdwReason) 295 { 296 case DLL_WINE_PREATTACH: 297 return FALSE; /* prefer native version */ 298 case DLL_PROCESS_ATTACH: 299 DisableThreadLibraryCalls(hInstDLL); 300 vbscript_hinstance = hInstDLL; 301 break; 302 case DLL_PROCESS_DETACH: 303 if (lpv) break; 304 release_typelib(); 305 release_regexp_typelib(); 306 } 307 308 return TRUE; 309 } 310 311 /*********************************************************************** 312 * DllGetClassObject (vbscript.@) 313 */ 314 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 315 { 316 if(IsEqualGUID(&CLSID_VBScript, rclsid)) { 317 TRACE("(CLSID_VBScript %s %p)\n", debugstr_guid(riid), ppv); 318 return IClassFactory_QueryInterface(&VBScriptFactory, riid, ppv); 319 }else if(IsEqualGUID(&CLSID_VBScriptRegExp, rclsid)) { 320 TRACE("(CLSID_VBScriptRegExp %s %p)\n", debugstr_guid(riid), ppv); 321 return IClassFactory_QueryInterface(&VBScriptRegExpFactory, riid, ppv); 322 } 323 324 FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 325 return CLASS_E_CLASSNOTAVAILABLE; 326 } 327 328 /*********************************************************************** 329 * DllCanUnloadNow (vbscript.@) 330 */ 331 HRESULT WINAPI DllCanUnloadNow(void) 332 { 333 return S_FALSE; 334 } 335 336 /*********************************************************************** 337 * DllRegisterServer (vbscript.@) 338 */ 339 HRESULT WINAPI DllRegisterServer(void) 340 { 341 TRACE("()\n"); 342 return __wine_register_resources(vbscript_hinstance); 343 } 344 345 /*********************************************************************** 346 * DllUnregisterServer (vbscript.@) 347 */ 348 HRESULT WINAPI DllUnregisterServer(void) 349 { 350 TRACE("()\n"); 351 return __wine_unregister_resources(vbscript_hinstance); 352 } 353