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