xref: /reactos/dll/win32/vbscript/vbscript_main.c (revision c7bba39a)
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