Reactos
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
31WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
32WINE_DECLARE_DEBUG_CHANNEL(heap);
33
34DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
35
36static HINSTANCE vbscript_hinstance;
37
38BSTR 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
45BSTR 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
56static inline DWORD block_size(DWORD block)
57{
58 return MIN_BLOCK_SIZE << block;
59}
60
61void heap_pool_init(heap_pool_t *heap)
62{
63 memset(heap, 0, sizeof(*heap));
64 list_init(&heap->custom_blocks);
65}
66
67void *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
122void *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
138void 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
161void 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
174heap_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
183static 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
204static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
205{
206 TRACE("(%p)\n", iface);
207 return 2;
208}
209
210static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
211{
212 TRACE("(%p)\n", iface);
213 return 1;
214}
215
216static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
217{
218 TRACE("(%p)->(%x)\n", iface, fLock);
219 return S_OK;
220}
221
222static const IClassFactoryVtbl VBScriptFactoryVtbl = {
223 ClassFactory_QueryInterface,
224 ClassFactory_AddRef,
225 ClassFactory_Release,
226 VBScriptFactory_CreateInstance,
227 ClassFactory_LockServer
228};
229
230static IClassFactory VBScriptFactory = { &VBScriptFactoryVtbl };
231
232static const IClassFactoryVtbl VBScriptRegExpFactoryVtbl = {
233 ClassFactory_QueryInterface,
234 ClassFactory_AddRef,
235 ClassFactory_Release,
236 VBScriptRegExpFactory_CreateInstance,
237 ClassFactory_LockServer
238};
239
240static IClassFactory VBScriptRegExpFactory = { &VBScriptRegExpFactoryVtbl };
241
242/******************************************************************
243 * DllMain (vbscript.@)
244 */
245BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
246{
247 TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpv);
248
249 switch(fdwReason)
250 {
251#ifndef __REACTOS__
252 case DLL_WINE_PREATTACH:
253 return FALSE; /* prefer native version */
254#endif
255 case DLL_PROCESS_ATTACH:
256 DisableThreadLibraryCalls(hInstDLL);
257 vbscript_hinstance = hInstDLL;
258 break;
259 case DLL_PROCESS_DETACH:
260 if (lpv) break;
261 release_regexp_typelib();
262 }
263
264 return TRUE;
265}
266
267/***********************************************************************
268 * DllGetClassObject (vbscript.@)
269 */
270HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
271{
272 if(IsEqualGUID(&CLSID_VBScript, rclsid)) {
273 TRACE("(CLSID_VBScript %s %p)\n", debugstr_guid(riid), ppv);
274 return IClassFactory_QueryInterface(&VBScriptFactory, riid, ppv);
275 }else if(IsEqualGUID(&CLSID_VBScriptRegExp, rclsid)) {
276 TRACE("(CLSID_VBScriptRegExp %s %p)\n", debugstr_guid(riid), ppv);
277 return IClassFactory_QueryInterface(&VBScriptRegExpFactory, riid, ppv);
278 }
279
280 FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
281 return CLASS_E_CLASSNOTAVAILABLE;
282}
283
284/***********************************************************************
285 * DllCanUnloadNow (vbscript.@)
286 */
287HRESULT WINAPI DllCanUnloadNow(void)
288{
289 return S_FALSE;
290}
291
292/***********************************************************************
293 * DllRegisterServer (vbscript.@)
294 */
295HRESULT WINAPI DllRegisterServer(void)
296{
297 TRACE("()\n");
298 return __wine_register_resources(vbscript_hinstance);
299}
300
301/***********************************************************************
302 * DllUnregisterServer (vbscript.@)
303 */
304HRESULT WINAPI DllUnregisterServer(void)
305{
306 TRACE("()\n");
307 return __wine_unregister_resources(vbscript_hinstance);
308}