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 BSTR get_vbscript_string(int id) 39 { 40 WCHAR buf[512]; 41 if(!LoadStringW(vbscript_hinstance, id, buf, ARRAY_SIZE(buf))) return NULL; 42 return SysAllocString(buf); 43 } 44 45 BSTR get_vbscript_error_string(HRESULT error) 46 { 47 BSTR ret; 48 if(HRESULT_FACILITY(error) != FACILITY_VBS || !(ret = get_vbscript_string(HRESULT_CODE(error)))) 49 ret = get_vbscript_string(VBS_UNKNOWN_RUNTIME_ERROR); 50 return ret; 51 } 52 53 #define MIN_BLOCK_SIZE 128 54 #define ARENA_FREE_FILLER 0xaa 55 56 static inline DWORD block_size(DWORD block) 57 { 58 return MIN_BLOCK_SIZE << block; 59 } 60 61 void heap_pool_init(heap_pool_t *heap) 62 { 63 memset(heap, 0, sizeof(*heap)); 64 list_init(&heap->custom_blocks); 65 } 66 67 void *heap_pool_alloc(heap_pool_t *heap, size_t size) 68 { 69 struct list *list; 70 void *tmp; 71 72 size = (size+3)&~3; 73 74 if(!heap->block_cnt) { 75 if(!heap->blocks) { 76 heap->blocks = heap_alloc(sizeof(void*)); 77 if(!heap->blocks) 78 return NULL; 79 } 80 81 tmp = heap_alloc(block_size(0)); 82 if(!tmp) 83 return NULL; 84 85 heap->blocks[0] = tmp; 86 heap->block_cnt = 1; 87 } 88 89 if(heap->offset + size <= block_size(heap->last_block)) { 90 tmp = ((BYTE*)heap->blocks[heap->last_block])+heap->offset; 91 heap->offset += size; 92 return tmp; 93 } 94 95 if(size <= block_size(heap->last_block+1)) { 96 if(heap->last_block+1 == heap->block_cnt) { 97 tmp = heap_realloc(heap->blocks, (heap->block_cnt+1)*sizeof(void*)); 98 if(!tmp) 99 return NULL; 100 101 heap->blocks = tmp; 102 heap->blocks[heap->block_cnt] = heap_alloc(block_size(heap->block_cnt)); 103 if(!heap->blocks[heap->block_cnt]) 104 return NULL; 105 106 heap->block_cnt++; 107 } 108 109 heap->last_block++; 110 heap->offset = size; 111 return heap->blocks[heap->last_block]; 112 } 113 114 list = heap_alloc(size + sizeof(struct list)); 115 if(!list) 116 return NULL; 117 118 list_add_head(&heap->custom_blocks, list); 119 return list+1; 120 } 121 122 void *heap_pool_grow(heap_pool_t *heap, void *mem, DWORD size, DWORD inc) 123 { 124 void *ret; 125 126 if(mem == (BYTE*)heap->blocks[heap->last_block] + heap->offset-size 127 && heap->offset+inc < block_size(heap->last_block)) { 128 heap->offset += inc; 129 return mem; 130 } 131 132 ret = heap_pool_alloc(heap, size+inc); 133 if(ret) /* FIXME: avoid copying for custom blocks */ 134 memcpy(ret, mem, size); 135 return ret; 136 } 137 138 void heap_pool_clear(heap_pool_t *heap) 139 { 140 struct list *tmp; 141 142 if(!heap) 143 return; 144 145 while((tmp = list_next(&heap->custom_blocks, &heap->custom_blocks))) { 146 list_remove(tmp); 147 heap_free(tmp); 148 } 149 150 if(WARN_ON(heap)) { 151 DWORD i; 152 153 for(i=0; i < heap->block_cnt; i++) 154 memset(heap->blocks[i], ARENA_FREE_FILLER, block_size(i)); 155 } 156 157 heap->last_block = heap->offset = 0; 158 heap->mark = FALSE; 159 } 160 161 void heap_pool_free(heap_pool_t *heap) 162 { 163 DWORD i; 164 165 heap_pool_clear(heap); 166 167 for(i=0; i < heap->block_cnt; i++) 168 heap_free(heap->blocks[i]); 169 heap_free(heap->blocks); 170 171 heap_pool_init(heap); 172 } 173 174 heap_pool_t *heap_pool_mark(heap_pool_t *heap) 175 { 176 if(heap->mark) 177 return NULL; 178 179 heap->mark = TRUE; 180 return heap; 181 } 182 183 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) 184 { 185 *ppv = NULL; 186 187 if(IsEqualGUID(&IID_IUnknown, riid)) { 188 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); 189 *ppv = iface; 190 }else if(IsEqualGUID(&IID_IClassFactory, riid)) { 191 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); 192 *ppv = iface; 193 } 194 195 if(*ppv) { 196 IUnknown_AddRef((IUnknown*)*ppv); 197 return S_OK; 198 } 199 200 FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv); 201 return E_NOINTERFACE; 202 } 203 204 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) 205 { 206 TRACE("(%p)\n", iface); 207 return 2; 208 } 209 210 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) 211 { 212 TRACE("(%p)\n", iface); 213 return 1; 214 } 215 216 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) 217 { 218 TRACE("(%p)->(%x)\n", iface, fLock); 219 return S_OK; 220 } 221 222 static const IClassFactoryVtbl VBScriptFactoryVtbl = { 223 ClassFactory_QueryInterface, 224 ClassFactory_AddRef, 225 ClassFactory_Release, 226 VBScriptFactory_CreateInstance, 227 ClassFactory_LockServer 228 }; 229 230 static IClassFactory VBScriptFactory = { &VBScriptFactoryVtbl }; 231 232 static const IClassFactoryVtbl VBScriptRegExpFactoryVtbl = { 233 ClassFactory_QueryInterface, 234 ClassFactory_AddRef, 235 ClassFactory_Release, 236 VBScriptRegExpFactory_CreateInstance, 237 ClassFactory_LockServer 238 }; 239 240 static IClassFactory VBScriptRegExpFactory = { &VBScriptRegExpFactoryVtbl }; 241 242 /****************************************************************** 243 * DllMain (vbscript.@) 244 */ 245 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) 246 { 247 TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpv); 248 249 switch(fdwReason) 250 { 251 case DLL_WINE_PREATTACH: 252 return FALSE; /* prefer native version */ 253 case DLL_PROCESS_ATTACH: 254 DisableThreadLibraryCalls(hInstDLL); 255 vbscript_hinstance = hInstDLL; 256 break; 257 case DLL_PROCESS_DETACH: 258 if (lpv) break; 259 release_regexp_typelib(); 260 } 261 262 return TRUE; 263 } 264 265 /*********************************************************************** 266 * DllGetClassObject (vbscript.@) 267 */ 268 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 269 { 270 if(IsEqualGUID(&CLSID_VBScript, rclsid)) { 271 TRACE("(CLSID_VBScript %s %p)\n", debugstr_guid(riid), ppv); 272 return IClassFactory_QueryInterface(&VBScriptFactory, riid, ppv); 273 }else if(IsEqualGUID(&CLSID_VBScriptRegExp, rclsid)) { 274 TRACE("(CLSID_VBScriptRegExp %s %p)\n", debugstr_guid(riid), ppv); 275 return IClassFactory_QueryInterface(&VBScriptRegExpFactory, riid, ppv); 276 } 277 278 FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 279 return CLASS_E_CLASSNOTAVAILABLE; 280 } 281 282 /*********************************************************************** 283 * DllCanUnloadNow (vbscript.@) 284 */ 285 HRESULT WINAPI DllCanUnloadNow(void) 286 { 287 return S_FALSE; 288 } 289 290 /*********************************************************************** 291 * DllRegisterServer (vbscript.@) 292 */ 293 HRESULT WINAPI DllRegisterServer(void) 294 { 295 TRACE("()\n"); 296 return __wine_register_resources(vbscript_hinstance); 297 } 298 299 /*********************************************************************** 300 * DllUnregisterServer (vbscript.@) 301 */ 302 HRESULT WINAPI DllUnregisterServer(void) 303 { 304 TRACE("()\n"); 305 return __wine_unregister_resources(vbscript_hinstance); 306 } 307