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
get_vbscript_string(int id)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
get_vbscript_error_string(HRESULT error)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
block_size(DWORD block)56 static inline DWORD block_size(DWORD block)
57 {
58 return MIN_BLOCK_SIZE << block;
59 }
60
heap_pool_init(heap_pool_t * heap)61 void heap_pool_init(heap_pool_t *heap)
62 {
63 memset(heap, 0, sizeof(*heap));
64 list_init(&heap->custom_blocks);
65 }
66
heap_pool_alloc(heap_pool_t * heap,size_t size)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
heap_pool_grow(heap_pool_t * heap,void * mem,DWORD size,DWORD inc)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
heap_pool_clear(heap_pool_t * heap)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
heap_pool_free(heap_pool_t * heap)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
heap_pool_mark(heap_pool_t * heap)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
ClassFactory_QueryInterface(IClassFactory * iface,REFIID riid,void ** ppv)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
ClassFactory_AddRef(IClassFactory * iface)204 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
205 {
206 TRACE("(%p)\n", iface);
207 return 2;
208 }
209
ClassFactory_Release(IClassFactory * iface)210 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
211 {
212 TRACE("(%p)\n", iface);
213 return 1;
214 }
215
ClassFactory_LockServer(IClassFactory * iface,BOOL fLock)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 */
DllMain(HINSTANCE hInstDLL,DWORD fdwReason,LPVOID lpv)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 */
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)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 */
DllCanUnloadNow(void)285 HRESULT WINAPI DllCanUnloadNow(void)
286 {
287 return S_FALSE;
288 }
289
290 /***********************************************************************
291 * DllRegisterServer (vbscript.@)
292 */
DllRegisterServer(void)293 HRESULT WINAPI DllRegisterServer(void)
294 {
295 TRACE("()\n");
296 return __wine_register_resources(vbscript_hinstance);
297 }
298
299 /***********************************************************************
300 * DllUnregisterServer (vbscript.@)
301 */
DllUnregisterServer(void)302 HRESULT WINAPI DllUnregisterServer(void)
303 {
304 TRACE("()\n");
305 return __wine_unregister_resources(vbscript_hinstance);
306 }
307