vbscript: Added assign statement tests.
[wine] / dlls / vbscript / tests / run.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 <stdio.h>
20
21 #define COBJMACROS
22 #define CONST_VTABLE
23
24 #include <ole2.h>
25 #include <dispex.h>
26 #include <activscp.h>
27
28 #include "wine/test.h"
29
30 extern const CLSID CLSID_VBScript;
31
32 #define DEFINE_EXPECT(func) \
33     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34
35 #define SET_EXPECT(func) \
36     expect_ ## func = TRUE
37
38 #define SET_CALLED(func) \
39     called_ ## func = TRUE
40
41 #define CHECK_EXPECT2(func) \
42     do { \
43         ok(expect_ ##func, "unexpected call " #func "\n"); \
44         called_ ## func = TRUE; \
45     }while(0)
46
47 #define CHECK_EXPECT(func) \
48     do { \
49         CHECK_EXPECT2(func); \
50         expect_ ## func = FALSE; \
51     }while(0)
52
53 #define CHECK_CALLED(func) \
54     do { \
55         ok(called_ ## func, "expected " #func "\n"); \
56         expect_ ## func = called_ ## func = FALSE; \
57     }while(0)
58
59 DEFINE_EXPECT(global_success_d);
60 DEFINE_EXPECT(global_success_i);
61 DEFINE_EXPECT(global_vbvar_d);
62 DEFINE_EXPECT(global_vbvar_i);
63
64 #define DISPID_GLOBAL_REPORTSUCCESS 1000
65 #define DISPID_GLOBAL_TRACE         1001
66 #define DISPID_GLOBAL_OK            1002
67 #define DISPID_GLOBAL_GETVT         1003
68 #define DISPID_GLOBAL_ISENGLOC      1004
69 #define DISPID_GLOBAL_VBVAR         1005
70
71 static const WCHAR testW[] = {'t','e','s','t',0};
72
73 static BOOL strict_dispid_check;
74 static const char *test_name = "(null)";
75
76 static BSTR a2bstr(const char *str)
77 {
78     BSTR ret;
79     int len;
80
81     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
82     ret = SysAllocStringLen(NULL, len-1);
83     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
84
85     return ret;
86 }
87
88 static int strcmp_wa(LPCWSTR strw, const char *stra)
89 {
90     CHAR buf[512];
91     WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), 0, 0);
92     return lstrcmpA(buf, stra);
93 }
94
95 static const char *vt2a(VARIANT *v)
96 {
97     if(V_VT(v) == (VT_BYREF|VT_VARIANT)) {
98         static char buf[64];
99         sprintf(buf, "%s*", vt2a(V_BYREF(v)));
100         return buf;
101     }
102
103     switch(V_VT(v)) {
104     case VT_EMPTY:
105         return "VT_EMPTY";
106     case VT_NULL:
107         return "VT_NULL";
108     case VT_I2:
109         return "VT_I2";
110     case VT_I4:
111         return "VT_I4";
112     case VT_R8:
113         return "VT_R8";
114     case VT_BSTR:
115         return "VT_BSTR";
116     case VT_DISPATCH:
117         return "VT_DISPATCH";
118     case VT_BOOL:
119         return "VT_BOOL";
120     case VT_ARRAY|VT_VARIANT:
121         return "VT_ARRAY|VT_VARIANT";
122     default:
123         ok(0, "unknown vt %d\n", V_VT(v));
124         return NULL;
125     }
126 }
127
128 static BOOL is_english(void)
129 {
130     return PRIMARYLANGID(GetSystemDefaultLangID()) == LANG_ENGLISH
131         && PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
132 }
133
134 #define test_grfdex(a,b) _test_grfdex(__LINE__,a,b)
135 static void _test_grfdex(unsigned line, DWORD grfdex, DWORD expect)
136 {
137     ok_(__FILE__,line)(grfdex == expect, "grfdex = %x, expected %x\n", grfdex, expect);
138 }
139
140 static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
141 {
142     *ppv = NULL;
143
144     if(IsEqualGUID(riid, &IID_IUnknown)
145        || IsEqualGUID(riid, &IID_IDispatch)
146        || IsEqualGUID(riid, &IID_IDispatchEx))
147         *ppv = iface;
148     else
149         return E_NOINTERFACE;
150
151     return S_OK;
152 }
153
154 static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
155 {
156     return 2;
157 }
158
159 static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
160 {
161     return 1;
162 }
163
164 static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
165 {
166     ok(0, "unexpected call\n");
167     return E_NOTIMPL;
168 }
169
170 static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
171                                               LCID lcid, ITypeInfo **ppTInfo)
172 {
173     ok(0, "unexpected call\n");
174     return E_NOTIMPL;
175 }
176
177 static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
178                                                 LPOLESTR *rgszNames, UINT cNames,
179                                                 LCID lcid, DISPID *rgDispId)
180 {
181     ok(0, "unexpected call\n");
182     return E_NOTIMPL;
183 }
184
185 static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
186                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
187                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
188 {
189     ok(0, "unexpected call\n");
190     return E_NOTIMPL;
191 }
192
193 static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
194 {
195     ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex);
196     return E_NOTIMPL;
197 }
198
199 static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
200 {
201     ok(0, "unexpected call\n");
202     return E_NOTIMPL;
203 }
204
205 static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
206 {
207     ok(0, "unexpected call\n");
208     return E_NOTIMPL;
209 }
210
211 static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
212 {
213     ok(0, "unexpected call\n");
214     return E_NOTIMPL;
215 }
216
217 static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
218 {
219     ok(0, "unexpected call\n");
220     return E_NOTIMPL;
221 }
222
223 static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
224 {
225     ok(0, "unexpected call\n");
226     return E_NOTIMPL;
227 }
228
229
230 static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
231 {
232     if(!strcmp_wa(bstrName, "ok")) {
233         test_grfdex(grfdex, fdexNameCaseInsensitive);
234         *pid = DISPID_GLOBAL_OK;
235         return S_OK;
236     }
237     if(!strcmp_wa(bstrName, "trace")) {
238         test_grfdex(grfdex, fdexNameCaseInsensitive);
239         *pid = DISPID_GLOBAL_TRACE;
240         return S_OK;
241     }
242     if(!strcmp_wa(bstrName, "reportSuccess")) {
243         CHECK_EXPECT(global_success_d);
244         test_grfdex(grfdex, fdexNameCaseInsensitive);
245         *pid = DISPID_GLOBAL_REPORTSUCCESS;
246         return S_OK;
247     }
248     if(!strcmp_wa(bstrName, "getVT")) {
249         test_grfdex(grfdex, fdexNameCaseInsensitive);
250         *pid = DISPID_GLOBAL_GETVT;
251         return S_OK;
252     }
253     if(!strcmp_wa(bstrName, "isEnglishLocale")) {
254         test_grfdex(grfdex, fdexNameCaseInsensitive);
255         *pid = DISPID_GLOBAL_ISENGLOC;
256         return S_OK;
257     }
258     if(!strcmp_wa(bstrName, "vbvar")) {
259         CHECK_EXPECT(global_vbvar_d);
260         test_grfdex(grfdex, fdexNameCaseInsensitive);
261         *pid = DISPID_GLOBAL_VBVAR;
262         return S_OK;
263     }
264
265     if(strict_dispid_check && strcmp_wa(bstrName, "x"))
266         ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex);
267     return DISP_E_UNKNOWNNAME;
268 }
269
270 static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
271         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
272 {
273     switch(id) {
274     case DISPID_GLOBAL_OK: {
275         VARIANT *b;
276
277         ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags);
278         ok(pdp != NULL, "pdp == NULL\n");
279         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
280         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
281         ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs);
282         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
283         if(wFlags & INVOKE_PROPERTYGET)
284             ok(pvarRes != NULL, "pvarRes == NULL\n");
285         else
286             ok(!pvarRes, "pvarRes != NULL\n");
287         ok(pei != NULL, "pei == NULL\n");
288
289         ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
290
291         b = pdp->rgvarg+1;
292         if(V_VT(b) == (VT_BYREF|VT_VARIANT))
293             b = V_BYREF(b);
294
295         ok(V_VT(b) == VT_BOOL, "V_VT(b) = %d\n", V_VT(b));
296
297         ok(V_BOOL(b), "%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
298         return S_OK;
299     }
300
301      case DISPID_GLOBAL_TRACE:
302         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
303         ok(pdp != NULL, "pdp == NULL\n");
304         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
305         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
306         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
307         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
308         ok(!pvarRes, "pvarRes != NULL\n");
309         ok(pei != NULL, "pei == NULL\n");
310
311         ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
312         if(V_VT(pdp->rgvarg) == VT_BSTR)
313             trace("%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
314
315         return S_OK;
316
317     case DISPID_GLOBAL_REPORTSUCCESS:
318         CHECK_EXPECT(global_success_i);
319
320         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
321         ok(pdp != NULL, "pdp == NULL\n");
322         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
323         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
324         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
325         ok(!pvarRes, "pvarRes != NULL\n");
326         ok(pei != NULL, "pei == NULL\n");
327
328         return S_OK;
329
330     case DISPID_GLOBAL_GETVT:
331          ok(pdp != NULL, "pdp == NULL\n");
332          ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
333          ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
334          ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
335          ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
336          ok(pvarRes != NULL, "pvarRes == NULL\n");
337          ok(V_VT(pvarRes) ==  VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
338          ok(pei != NULL, "pei == NULL\n");
339
340          V_VT(pvarRes) = VT_BSTR;
341          V_BSTR(pvarRes) = a2bstr(vt2a(pdp->rgvarg));
342          return S_OK;
343
344     case DISPID_GLOBAL_ISENGLOC:
345         ok(wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags);
346         ok(pdp != NULL, "pdp == NULL\n");
347         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
348         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
349         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
350         ok(pvarRes != NULL, "pvarRes == NULL\n");
351         ok(pei != NULL, "pei == NULL\n");
352
353         V_VT(pvarRes) = VT_BOOL;
354         if(is_english()) {
355             V_BOOL(pvarRes) = VARIANT_TRUE;
356         }else {
357             skip("Skipping some test in non-English locale\n");
358             V_BOOL(pvarRes) = VARIANT_FALSE;
359         }
360         return S_OK;
361
362     case DISPID_GLOBAL_VBVAR:
363         CHECK_EXPECT(global_vbvar_i);
364
365         ok(wFlags == DISPATCH_PROPERTYPUT, "wFlags = %x\n", wFlags);
366         ok(pdp != NULL, "pdp == NULL\n");
367         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
368         ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n");
369         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
370         ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
371         ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]);
372         ok(!pvarRes, "pvarRes != NULL\n");
373         ok(pei != NULL, "pei == NULL\n");
374
375         ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
376         ok(V_I2(pdp->rgvarg) == 3, "V_I2(psp->rgvargs) = %d\n", V_I2(pdp->rgvarg));
377
378         return S_OK;
379     }
380
381     ok(0, "unexpected call %d\n", id);
382     return DISP_E_MEMBERNOTFOUND;
383 }
384
385 static IDispatchExVtbl GlobalVtbl = {
386     DispatchEx_QueryInterface,
387     DispatchEx_AddRef,
388     DispatchEx_Release,
389     DispatchEx_GetTypeInfoCount,
390     DispatchEx_GetTypeInfo,
391     DispatchEx_GetIDsOfNames,
392     DispatchEx_Invoke,
393     Global_GetDispID,
394     Global_InvokeEx,
395     DispatchEx_DeleteMemberByName,
396     DispatchEx_DeleteMemberByDispID,
397     DispatchEx_GetMemberProperties,
398     DispatchEx_GetMemberName,
399     DispatchEx_GetNextDispID,
400     DispatchEx_GetNameSpaceParent
401 };
402
403 static IDispatchEx Global = { &GlobalVtbl };
404
405 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
406 {
407     *ppv = NULL;
408
409     if(IsEqualGUID(&IID_IUnknown, riid))
410         *ppv = iface;
411     else if(IsEqualGUID(&IID_IActiveScriptSite, riid))
412         *ppv = iface;
413     else
414         return E_NOINTERFACE;
415
416     IUnknown_AddRef((IUnknown*)*ppv);
417     return S_OK;
418 }
419
420 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
421 {
422     return 2;
423 }
424
425 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
426 {
427     return 1;
428 }
429
430 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid)
431 {
432     *plcid = GetUserDefaultLCID();
433     return S_OK;
434 }
435
436 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName,
437         DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti)
438 {
439     ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "unexpected dwReturnMask %x\n", dwReturnMask);
440     ok(!ppti, "ppti != NULL\n");
441
442     if(strcmp_wa(pstrName, "test"))
443         ok(0, "unexpected pstrName %s\n", wine_dbgstr_w(pstrName));
444
445     *ppiunkItem = (IUnknown*)&Global;
446     return S_OK;
447 }
448
449 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion)
450 {
451     return E_NOTIMPL;
452 }
453
454 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface,
455         const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo)
456 {
457     return E_NOTIMPL;
458 }
459
460 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState)
461 {
462     return E_NOTIMPL;
463 }
464
465 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror)
466 {
467     return E_NOTIMPL;
468 }
469
470 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
471 {
472     return E_NOTIMPL;
473 }
474
475 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
476 {
477     return E_NOTIMPL;
478 }
479
480 #undef ACTSCPSITE_THIS
481
482 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = {
483     ActiveScriptSite_QueryInterface,
484     ActiveScriptSite_AddRef,
485     ActiveScriptSite_Release,
486     ActiveScriptSite_GetLCID,
487     ActiveScriptSite_GetItemInfo,
488     ActiveScriptSite_GetDocVersionString,
489     ActiveScriptSite_OnScriptTerminate,
490     ActiveScriptSite_OnStateChange,
491     ActiveScriptSite_OnScriptError,
492     ActiveScriptSite_OnEnterScript,
493     ActiveScriptSite_OnLeaveScript
494 };
495
496 static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl };
497
498 static IActiveScript *create_script(void)
499 {
500     IActiveScript *script;
501     HRESULT hres;
502
503     hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
504             &IID_IActiveScript, (void**)&script);
505     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
506
507     return script;
508 }
509
510 static HRESULT parse_script(DWORD flags, BSTR script_str)
511 {
512     IActiveScriptParse *parser;
513     IActiveScript *engine;
514     IDispatch *script_disp;
515     HRESULT hres;
516
517     engine = create_script();
518     if(!engine)
519         return S_OK;
520
521     hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser);
522     ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres);
523     if (FAILED(hres))
524     {
525         IActiveScript_Release(engine);
526         return hres;
527     }
528
529     hres = IActiveScriptParse64_InitNew(parser);
530     ok(hres == S_OK, "InitNew failed: %08x\n", hres);
531
532     hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite);
533     ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres);
534
535     hres = IActiveScript_AddNamedItem(engine, testW,
536             SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|flags);
537     ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres);
538
539     hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED);
540     ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres);
541
542     hres = IActiveScript_GetScriptDispatch(engine, NULL, &script_disp);
543     ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres);
544     ok(script_disp != NULL, "script_disp == NULL\n");
545     ok(script_disp != (IDispatch*)&Global, "script_disp == Global\n");
546
547     hres = IActiveScriptParse64_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
548
549     IDispatch_Release(script_disp);
550     IActiveScript_Release(engine);
551     IUnknown_Release(parser);
552
553     return hres;
554 }
555
556 static void parse_script_af(DWORD flags, const char *src)
557 {
558     BSTR tmp;
559     HRESULT hres;
560
561     tmp = a2bstr(src);
562     hres = parse_script(flags, tmp);
563     SysFreeString(tmp);
564     ok(hres == S_OK, "parse_script failed: %08x\n", hres);
565 }
566
567 static void parse_script_a(const char *src)
568 {
569     parse_script_af(SCRIPTITEM_GLOBALMEMBERS, src);
570 }
571
572 static BSTR get_script_from_file(const char *filename)
573 {
574     DWORD size, len;
575     HANDLE file, map;
576     const char *file_map;
577     BSTR ret;
578
579     file = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
580     if(file == INVALID_HANDLE_VALUE) {
581         trace("Could not open file: %u\n", GetLastError());
582         return NULL;
583     }
584
585     size = GetFileSize(file, NULL);
586
587     map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
588     CloseHandle(file);
589     if(map == INVALID_HANDLE_VALUE) {
590         trace("Could not create file mapping: %u\n", GetLastError());
591         return NULL;
592     }
593
594     file_map = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
595     CloseHandle(map);
596     if(!file_map) {
597         trace("MapViewOfFile failed: %u\n", GetLastError());
598         return NULL;
599     }
600
601     len = MultiByteToWideChar(CP_ACP, 0, file_map, size, NULL, 0);
602     ret = SysAllocStringLen(NULL, len);
603     MultiByteToWideChar(CP_ACP, 0, file_map, size, ret, len);
604
605     UnmapViewOfFile(file_map);
606
607     return ret;
608 }
609
610 static void run_from_file(const char *filename)
611 {
612     BSTR script_str;
613     HRESULT hres;
614
615     script_str = get_script_from_file(filename);
616     if(!script_str)
617         return;
618
619     strict_dispid_check = FALSE;
620     hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, script_str);
621     SysFreeString(script_str);
622     ok(hres == S_OK, "parse_script failed: %08x\n", hres);
623 }
624
625 static void run_from_res(const char *name)
626 {
627     const char *data;
628     DWORD size, len;
629     BSTR str;
630     HRSRC src;
631     HRESULT hres;
632
633     strict_dispid_check = FALSE;
634     test_name = name;
635
636     src = FindResourceA(NULL, name, (LPCSTR)40);
637     ok(src != NULL, "Could not find resource %s\n", name);
638
639     size = SizeofResource(NULL, src);
640     data = LoadResource(NULL, src);
641
642     len = MultiByteToWideChar(CP_ACP, 0, data, size, NULL, 0);
643     str = SysAllocStringLen(NULL, len);
644     MultiByteToWideChar(CP_ACP, 0, data, size, str, len);
645
646     SET_EXPECT(global_success_d);
647     SET_EXPECT(global_success_i);
648     hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, str);
649     CHECK_CALLED(global_success_d);
650     CHECK_CALLED(global_success_i);
651
652     ok(hres == S_OK, "parse_script failed: %08x\n", hres);
653     SysFreeString(str);
654 }
655
656 static void run_tests(void)
657 {
658     strict_dispid_check = TRUE;
659
660     parse_script_a("");
661     parse_script_a("' empty ;");
662
663     SET_EXPECT(global_success_d);
664     SET_EXPECT(global_success_i);
665     parse_script_a("reportSuccess");
666     CHECK_CALLED(global_success_d);
667     CHECK_CALLED(global_success_i);
668
669     SET_EXPECT(global_success_d);
670     SET_EXPECT(global_success_i);
671     parse_script_a("reportSuccess()");
672     CHECK_CALLED(global_success_d);
673     CHECK_CALLED(global_success_i);
674
675     SET_EXPECT(global_success_d);
676     SET_EXPECT(global_success_i);
677     parse_script_a("Call reportSuccess");
678     CHECK_CALLED(global_success_d);
679     CHECK_CALLED(global_success_i);
680
681     SET_EXPECT(global_vbvar_d);
682     SET_EXPECT(global_vbvar_i);
683     parse_script_a("Option Explicit\nvbvar = 3");
684     CHECK_CALLED(global_vbvar_d);
685     CHECK_CALLED(global_vbvar_i);
686
687     SET_EXPECT(global_vbvar_d);
688     SET_EXPECT(global_vbvar_i);
689     parse_script_a("Option Explicit\nvbvar() = 3");
690     CHECK_CALLED(global_vbvar_d);
691     CHECK_CALLED(global_vbvar_i);
692
693     run_from_res("lang.vbs");
694 }
695
696 static BOOL check_vbscript(void)
697 {
698     IActiveScript *vbscript;
699     HRESULT hres;
700
701     hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
702             &IID_IActiveScript, (void**)&vbscript);
703     if(SUCCEEDED(hres))
704         IActiveScript_Release(vbscript);
705
706     return hres == S_OK;
707 }
708
709 START_TEST(run)
710 {
711     int argc;
712     char **argv;
713
714     argc = winetest_get_mainargs(&argv);
715
716     CoInitialize(NULL);
717
718     if(!check_vbscript()) {
719         win_skip("Broken engine, probably too old\n");
720     }else if(argc > 2) {
721         run_from_file(argv[2]);
722     }else {
723         run_tests();
724     }
725
726     CoUninitialize();
727 }