vbscript: Added class properties compiler implementation.
[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 DEFINE_EXPECT(testobj_propget_d);
64 DEFINE_EXPECT(testobj_propget_i);
65 DEFINE_EXPECT(testobj_propput_d);
66 DEFINE_EXPECT(testobj_propput_i);
67
68 #define DISPID_GLOBAL_REPORTSUCCESS 1000
69 #define DISPID_GLOBAL_TRACE         1001
70 #define DISPID_GLOBAL_OK            1002
71 #define DISPID_GLOBAL_GETVT         1003
72 #define DISPID_GLOBAL_ISENGLANG     1004
73 #define DISPID_GLOBAL_VBVAR         1005
74 #define DISPID_GLOBAL_TESTOBJ       1006
75 #define DISPID_GLOBAL_ISNULLDISP    1007
76 #define DISPID_GLOBAL_TESTDISP      1008
77
78 #define DISPID_TESTOBJ_PROPGET      2000
79 #define DISPID_TESTOBJ_PROPPUT      2001
80
81 static const WCHAR testW[] = {'t','e','s','t',0};
82
83 static BOOL strict_dispid_check;
84 static const char *test_name = "(null)";
85
86 static BSTR a2bstr(const char *str)
87 {
88     BSTR ret;
89     int len;
90
91     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
92     ret = SysAllocStringLen(NULL, len-1);
93     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
94
95     return ret;
96 }
97
98 static int strcmp_wa(LPCWSTR strw, const char *stra)
99 {
100     CHAR buf[512];
101     WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), 0, 0);
102     return lstrcmpA(buf, stra);
103 }
104
105 static const char *vt2a(VARIANT *v)
106 {
107     if(V_VT(v) == (VT_BYREF|VT_VARIANT)) {
108         static char buf[64];
109         sprintf(buf, "%s*", vt2a(V_BYREF(v)));
110         return buf;
111     }
112
113     switch(V_VT(v)) {
114     case VT_EMPTY:
115         return "VT_EMPTY";
116     case VT_NULL:
117         return "VT_NULL";
118     case VT_I2:
119         return "VT_I2";
120     case VT_I4:
121         return "VT_I4";
122     case VT_R8:
123         return "VT_R8";
124     case VT_BSTR:
125         return "VT_BSTR";
126     case VT_DISPATCH:
127         return "VT_DISPATCH";
128     case VT_BOOL:
129         return "VT_BOOL";
130     case VT_ARRAY|VT_VARIANT:
131         return "VT_ARRAY|VT_VARIANT";
132     default:
133         ok(0, "unknown vt %d\n", V_VT(v));
134         return NULL;
135     }
136 }
137
138 /* Returns true if the user interface is in English. Note that this does not
139  * presume of the formatting of dates, numbers, etc.
140  */
141 static BOOL is_lang_english(void)
142 {
143     static HMODULE hkernel32 = NULL;
144     static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
145     static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
146
147     if (!hkernel32)
148     {
149         hkernel32 = GetModuleHandleA("kernel32.dll");
150         pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
151         pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
152     }
153     if (pGetThreadUILanguage)
154         return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
155     if (pGetUserDefaultUILanguage)
156         return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
157
158     return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
159 }
160
161 static void test_disp(IDispatch *disp)
162 {
163     DISPID id, public_func_id, public_sub_id;
164     DISPID named_args[5] = {DISPID_PROPERTYPUT};
165     VARIANT v, args[5];
166     DISPPARAMS dp = {args, named_args};
167     IDispatchEx *dispex;
168     EXCEPINFO ei = {0};
169     BSTR str;
170     HRESULT hres;
171
172     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
173     ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres);
174
175     str = a2bstr("publicFunction");
176     hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &public_func_id);
177     SysFreeString(str);
178     ok(hres == S_OK, "GetDispID(publicFunction) failed: %08x\n", hres);
179     ok(public_func_id != -1, "public_func_id = -1\n");
180
181     str = a2bstr("publicSub");
182     hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &public_sub_id);
183     SysFreeString(str);
184     ok(hres == S_OK, "GetDispID(publicSub) failed: %08x\n", hres);
185     ok(public_sub_id != -1, "public_func_id = -1\n");
186
187     dp.cArgs = dp.cNamedArgs = 0;
188     hres = IDispatchEx_InvokeEx(dispex, public_func_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL);
189     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
190     ok(V_VT(&v) == VT_I2, "V_VT(v) = %d\n", V_VT(&v));
191     ok(V_I2(&v) == 4, "V_I2(v) = %d\n", V_I2(&v));
192
193     dp.cArgs = dp.cNamedArgs = 0;
194     hres = IDispatchEx_InvokeEx(dispex, public_func_id, 0, DISPATCH_METHOD, &dp, &v, &ei, NULL);
195     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
196     ok(V_VT(&v) == VT_I2, "V_VT(v) = %d\n", V_VT(&v));
197     ok(V_I2(&v) == 4, "V_I2(v) = %d\n", V_I2(&v));
198
199     dp.cArgs = dp.cNamedArgs = 0;
200     hres = IDispatchEx_InvokeEx(dispex, public_sub_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL);
201     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
202     ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v));
203
204     dp.cArgs = dp.cNamedArgs = 0;
205     hres = IDispatchEx_InvokeEx(dispex, public_sub_id, 0, DISPATCH_METHOD, &dp, &v, &ei, NULL);
206     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
207     ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v));
208
209     str = a2bstr("privateSub");
210     hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &id);
211     SysFreeString(str);
212     ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(privateSub) failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres);
213     ok(id == -1, "id = %d\n", id);
214
215     str = a2bstr("dynprop");
216     hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive|fdexNameEnsure, &id);
217     ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(privateProp) failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres);
218     ok(id == -1, "id = %d\n", id);
219     hres = IDispatchEx_GetDispID(dispex, str, fdexNameEnsure, &id);
220     ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(privateProp) failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres);
221     ok(id == -1, "id = %d\n", id);
222     SysFreeString(str);
223
224     IDispatchEx_Release(dispex);
225 }
226
227 #define test_grfdex(a,b) _test_grfdex(__LINE__,a,b)
228 static void _test_grfdex(unsigned line, DWORD grfdex, DWORD expect)
229 {
230     ok_(__FILE__,line)(grfdex == expect, "grfdex = %x, expected %x\n", grfdex, expect);
231 }
232
233 static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
234 {
235     *ppv = NULL;
236
237     if(IsEqualGUID(riid, &IID_IUnknown)
238        || IsEqualGUID(riid, &IID_IDispatch)
239        || IsEqualGUID(riid, &IID_IDispatchEx))
240         *ppv = iface;
241     else
242         return E_NOINTERFACE;
243
244     return S_OK;
245 }
246
247 static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
248 {
249     return 2;
250 }
251
252 static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
253 {
254     return 1;
255 }
256
257 static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
258 {
259     ok(0, "unexpected call\n");
260     return E_NOTIMPL;
261 }
262
263 static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
264                                               LCID lcid, ITypeInfo **ppTInfo)
265 {
266     ok(0, "unexpected call\n");
267     return E_NOTIMPL;
268 }
269
270 static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
271                                                 LPOLESTR *rgszNames, UINT cNames,
272                                                 LCID lcid, DISPID *rgDispId)
273 {
274     ok(0, "unexpected call\n");
275     return E_NOTIMPL;
276 }
277
278 static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
279                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
280                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
281 {
282     ok(0, "unexpected call\n");
283     return E_NOTIMPL;
284 }
285
286 static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
287 {
288     ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex);
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
293 {
294     ok(0, "unexpected call\n");
295     return E_NOTIMPL;
296 }
297
298 static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
299 {
300     ok(0, "unexpected call\n");
301     return E_NOTIMPL;
302 }
303
304 static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
305 {
306     ok(0, "unexpected call\n");
307     return E_NOTIMPL;
308 }
309
310 static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
311 {
312     ok(0, "unexpected call\n");
313     return E_NOTIMPL;
314 }
315
316 static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
317 {
318     ok(0, "unexpected call\n");
319     return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI testObj_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
323 {
324     if(!strcmp_wa(bstrName, "propget")) {
325         CHECK_EXPECT(testobj_propget_d);
326         test_grfdex(grfdex, fdexNameCaseInsensitive);
327         *pid = DISPID_TESTOBJ_PROPGET;
328         return S_OK;
329     }
330     if(!strcmp_wa(bstrName, "propput")) {
331         CHECK_EXPECT(testobj_propput_d);
332         test_grfdex(grfdex, fdexNameCaseInsensitive);
333         *pid = DISPID_TESTOBJ_PROPPUT;
334         return S_OK;
335     }
336
337     ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName));
338     return DISP_E_UNKNOWNNAME;
339 }
340
341 static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
342         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
343 {
344     switch(id) {
345     case DISPID_TESTOBJ_PROPGET:
346         CHECK_EXPECT(testobj_propget_i);
347
348         ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags);
349         ok(pdp != NULL, "pdp == NULL\n");
350         ok(!pdp->rgvarg, "rgvarg == NULL\n");
351         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
352         ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs);
353         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
354         ok(pvarRes != NULL, "pvarRes == NULL\n");
355         ok(pei != NULL, "pei == NULL\n");
356
357         V_VT(pvarRes) = VT_I2;
358         V_I2(pvarRes) = 10;
359         return S_OK;
360     case DISPID_TESTOBJ_PROPPUT:
361         CHECK_EXPECT(testobj_propput_i);
362
363         ok(wFlags == DISPATCH_PROPERTYPUT, "wFlags = %x\n", wFlags);
364         ok(pdp != NULL, "pdp == NULL\n");
365         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
366         ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n");
367         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
368         ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
369         ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]);
370         ok(!pvarRes, "pvarRes != NULL\n");
371         ok(pei != NULL, "pei == NULL\n");
372
373         ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
374         ok(V_I2(pdp->rgvarg) == 1, "V_I2(psp->rgvargs) = %d\n", V_I2(pdp->rgvarg));
375         return S_OK;
376     }
377
378     ok(0, "unexpected call %d\n", id);
379     return E_FAIL;
380 }
381
382 static IDispatchExVtbl testObjVtbl = {
383     DispatchEx_QueryInterface,
384     DispatchEx_AddRef,
385     DispatchEx_Release,
386     DispatchEx_GetTypeInfoCount,
387     DispatchEx_GetTypeInfo,
388     DispatchEx_GetIDsOfNames,
389     DispatchEx_Invoke,
390     testObj_GetDispID,
391     testObj_InvokeEx,
392     DispatchEx_DeleteMemberByName,
393     DispatchEx_DeleteMemberByDispID,
394     DispatchEx_GetMemberProperties,
395     DispatchEx_GetMemberName,
396     DispatchEx_GetNextDispID,
397     DispatchEx_GetNameSpaceParent
398 };
399
400 static IDispatchEx testObj = { &testObjVtbl };
401
402 static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
403 {
404     if(!strcmp_wa(bstrName, "ok")) {
405         test_grfdex(grfdex, fdexNameCaseInsensitive);
406         *pid = DISPID_GLOBAL_OK;
407         return S_OK;
408     }
409     if(!strcmp_wa(bstrName, "trace")) {
410         test_grfdex(grfdex, fdexNameCaseInsensitive);
411         *pid = DISPID_GLOBAL_TRACE;
412         return S_OK;
413     }
414     if(!strcmp_wa(bstrName, "reportSuccess")) {
415         CHECK_EXPECT(global_success_d);
416         test_grfdex(grfdex, fdexNameCaseInsensitive);
417         *pid = DISPID_GLOBAL_REPORTSUCCESS;
418         return S_OK;
419     }
420     if(!strcmp_wa(bstrName, "getVT")) {
421         test_grfdex(grfdex, fdexNameCaseInsensitive);
422         *pid = DISPID_GLOBAL_GETVT;
423         return S_OK;
424     }
425     if(!strcmp_wa(bstrName, "isEnglishLang")) {
426         test_grfdex(grfdex, fdexNameCaseInsensitive);
427         *pid = DISPID_GLOBAL_ISENGLANG;
428         return S_OK;
429     }
430     if(!strcmp_wa(bstrName, "testObj")) {
431         test_grfdex(grfdex, fdexNameCaseInsensitive);
432         *pid = DISPID_GLOBAL_TESTOBJ;
433         return S_OK;
434     }
435     if(!strcmp_wa(bstrName, "vbvar")) {
436         CHECK_EXPECT(global_vbvar_d);
437         test_grfdex(grfdex, fdexNameCaseInsensitive);
438         *pid = DISPID_GLOBAL_VBVAR;
439         return S_OK;
440     }
441     if(!strcmp_wa(bstrName, "isNullDisp")) {
442         test_grfdex(grfdex, fdexNameCaseInsensitive);
443         *pid = DISPID_GLOBAL_ISNULLDISP;
444         return S_OK;
445     }
446     if(!strcmp_wa(bstrName, "testDisp")) {
447         test_grfdex(grfdex, fdexNameCaseInsensitive);
448         *pid = DISPID_GLOBAL_TESTDISP;
449         return S_OK;
450     }
451
452     if(strict_dispid_check && strcmp_wa(bstrName, "x"))
453         ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex);
454     return DISP_E_UNKNOWNNAME;
455 }
456
457 static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
458         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
459 {
460     switch(id) {
461     case DISPID_GLOBAL_OK: {
462         VARIANT *b;
463
464         ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags);
465         ok(pdp != NULL, "pdp == NULL\n");
466         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
467         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
468         ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs);
469         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
470         if(wFlags & INVOKE_PROPERTYGET)
471             ok(pvarRes != NULL, "pvarRes == NULL\n");
472         else
473             ok(!pvarRes, "pvarRes != NULL\n");
474         ok(pei != NULL, "pei == NULL\n");
475
476         ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
477
478         b = pdp->rgvarg+1;
479         if(V_VT(b) == (VT_BYREF|VT_VARIANT))
480             b = V_BYREF(b);
481
482         ok(V_VT(b) == VT_BOOL, "V_VT(b) = %d\n", V_VT(b));
483
484         ok(V_BOOL(b), "%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
485         return S_OK;
486     }
487
488      case DISPID_GLOBAL_TRACE:
489         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
490         ok(pdp != NULL, "pdp == NULL\n");
491         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
492         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
493         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
494         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
495         ok(!pvarRes, "pvarRes != NULL\n");
496         ok(pei != NULL, "pei == NULL\n");
497
498         ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
499         if(V_VT(pdp->rgvarg) == VT_BSTR)
500             trace("%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
501
502         return S_OK;
503
504     case DISPID_GLOBAL_REPORTSUCCESS:
505         CHECK_EXPECT(global_success_i);
506
507         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
508         ok(pdp != NULL, "pdp == NULL\n");
509         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
510         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
511         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
512         ok(!pvarRes, "pvarRes != NULL\n");
513         ok(pei != NULL, "pei == NULL\n");
514
515         return S_OK;
516
517     case DISPID_GLOBAL_GETVT:
518         ok(pdp != NULL, "pdp == NULL\n");
519         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
520         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
521         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
522         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
523         ok(pvarRes != NULL, "pvarRes == NULL\n");
524         ok(V_VT(pvarRes) ==  VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
525         ok(pei != NULL, "pei == NULL\n");
526
527         V_VT(pvarRes) = VT_BSTR;
528         V_BSTR(pvarRes) = a2bstr(vt2a(pdp->rgvarg));
529         return S_OK;
530
531     case DISPID_GLOBAL_ISENGLANG:
532         ok(wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags);
533         ok(pdp != NULL, "pdp == NULL\n");
534         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
535         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
536         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
537         ok(pvarRes != NULL, "pvarRes == NULL\n");
538         ok(pei != NULL, "pei == NULL\n");
539
540         V_VT(pvarRes) = VT_BOOL;
541         if(is_lang_english()) {
542             V_BOOL(pvarRes) = VARIANT_TRUE;
543         }else {
544             skip("Skipping some tests in non-English UIs\n");
545             V_BOOL(pvarRes) = VARIANT_FALSE;
546         }
547         return S_OK;
548
549     case DISPID_GLOBAL_VBVAR:
550         CHECK_EXPECT(global_vbvar_i);
551
552         ok(wFlags == DISPATCH_PROPERTYPUT, "wFlags = %x\n", wFlags);
553         ok(pdp != NULL, "pdp == NULL\n");
554         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
555         ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n");
556         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
557         ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
558         ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]);
559         ok(!pvarRes, "pvarRes != NULL\n");
560         ok(pei != NULL, "pei == NULL\n");
561
562         ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
563         ok(V_I2(pdp->rgvarg) == 3, "V_I2(psp->rgvargs) = %d\n", V_I2(pdp->rgvarg));
564         return S_OK;
565
566     case DISPID_GLOBAL_TESTOBJ:
567         ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags);
568
569         ok(pdp != NULL, "pdp == NULL\n");
570         ok(!pdp->rgvarg, "rgvarg == NULL\n");
571         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
572         ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs);
573         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
574         ok(pvarRes != NULL, "pvarRes == NULL\n");
575         ok(pei != NULL, "pei == NULL\n");
576
577         V_VT(pvarRes) = VT_DISPATCH;
578         V_DISPATCH(pvarRes) = (IDispatch*)&testObj;
579         return S_OK;
580
581     case DISPID_GLOBAL_ISNULLDISP: {
582         VARIANT *v;
583
584         ok(wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags);
585         ok(pdp != NULL, "pdp == NULL\n");
586         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
587         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
588         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
589         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
590         ok(pvarRes != NULL, "pvarRes == NULL\n");
591         ok(pei != NULL, "pei == NULL\n");
592
593         v = pdp->rgvarg;
594         if(V_VT(v) == (VT_VARIANT|VT_BYREF))
595             v = V_VARIANTREF(v);
596
597         ok(V_VT(v) == VT_DISPATCH, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
598         V_VT(pvarRes) = VT_BOOL;
599         V_BOOL(pvarRes) = V_DISPATCH(v) ? VARIANT_FALSE : VARIANT_TRUE;
600         return S_OK;
601     }
602
603     case DISPID_GLOBAL_TESTDISP:
604         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
605         ok(pdp != NULL, "pdp == NULL\n");
606         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
607         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
608         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
609         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
610         ok(!pvarRes, "pvarRes != NULL\n");
611         ok(pei != NULL, "pei == NULL\n");
612
613         ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
614         test_disp(V_DISPATCH(pdp->rgvarg));
615         return S_OK;
616     }
617
618     ok(0, "unexpected call %d\n", id);
619     return DISP_E_MEMBERNOTFOUND;
620 }
621
622 static IDispatchExVtbl GlobalVtbl = {
623     DispatchEx_QueryInterface,
624     DispatchEx_AddRef,
625     DispatchEx_Release,
626     DispatchEx_GetTypeInfoCount,
627     DispatchEx_GetTypeInfo,
628     DispatchEx_GetIDsOfNames,
629     DispatchEx_Invoke,
630     Global_GetDispID,
631     Global_InvokeEx,
632     DispatchEx_DeleteMemberByName,
633     DispatchEx_DeleteMemberByDispID,
634     DispatchEx_GetMemberProperties,
635     DispatchEx_GetMemberName,
636     DispatchEx_GetNextDispID,
637     DispatchEx_GetNameSpaceParent
638 };
639
640 static IDispatchEx Global = { &GlobalVtbl };
641
642 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
643 {
644     *ppv = NULL;
645
646     if(IsEqualGUID(&IID_IUnknown, riid))
647         *ppv = iface;
648     else if(IsEqualGUID(&IID_IActiveScriptSite, riid))
649         *ppv = iface;
650     else
651         return E_NOINTERFACE;
652
653     IUnknown_AddRef((IUnknown*)*ppv);
654     return S_OK;
655 }
656
657 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
658 {
659     return 2;
660 }
661
662 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
663 {
664     return 1;
665 }
666
667 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid)
668 {
669     *plcid = GetUserDefaultLCID();
670     return S_OK;
671 }
672
673 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName,
674         DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti)
675 {
676     ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "unexpected dwReturnMask %x\n", dwReturnMask);
677     ok(!ppti, "ppti != NULL\n");
678
679     if(strcmp_wa(pstrName, "test"))
680         ok(0, "unexpected pstrName %s\n", wine_dbgstr_w(pstrName));
681
682     *ppiunkItem = (IUnknown*)&Global;
683     return S_OK;
684 }
685
686 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion)
687 {
688     return E_NOTIMPL;
689 }
690
691 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface,
692         const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo)
693 {
694     return E_NOTIMPL;
695 }
696
697 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState)
698 {
699     return E_NOTIMPL;
700 }
701
702 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror)
703 {
704     return E_NOTIMPL;
705 }
706
707 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
708 {
709     return E_NOTIMPL;
710 }
711
712 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
713 {
714     return E_NOTIMPL;
715 }
716
717 #undef ACTSCPSITE_THIS
718
719 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = {
720     ActiveScriptSite_QueryInterface,
721     ActiveScriptSite_AddRef,
722     ActiveScriptSite_Release,
723     ActiveScriptSite_GetLCID,
724     ActiveScriptSite_GetItemInfo,
725     ActiveScriptSite_GetDocVersionString,
726     ActiveScriptSite_OnScriptTerminate,
727     ActiveScriptSite_OnStateChange,
728     ActiveScriptSite_OnScriptError,
729     ActiveScriptSite_OnEnterScript,
730     ActiveScriptSite_OnLeaveScript
731 };
732
733 static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl };
734
735 static IActiveScript *create_script(void)
736 {
737     IActiveScript *script;
738     HRESULT hres;
739
740     hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
741             &IID_IActiveScript, (void**)&script);
742     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
743
744     return script;
745 }
746
747 static HRESULT parse_script(DWORD flags, BSTR script_str)
748 {
749     IActiveScriptParse *parser;
750     IActiveScript *engine;
751     IDispatch *script_disp;
752     HRESULT hres;
753
754     engine = create_script();
755     if(!engine)
756         return S_OK;
757
758     hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser);
759     ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres);
760     if (FAILED(hres))
761     {
762         IActiveScript_Release(engine);
763         return hres;
764     }
765
766     hres = IActiveScriptParse64_InitNew(parser);
767     ok(hres == S_OK, "InitNew failed: %08x\n", hres);
768
769     hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite);
770     ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres);
771
772     hres = IActiveScript_AddNamedItem(engine, testW,
773             SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|flags);
774     ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres);
775
776     hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED);
777     ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres);
778
779     hres = IActiveScript_GetScriptDispatch(engine, NULL, &script_disp);
780     ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres);
781     ok(script_disp != NULL, "script_disp == NULL\n");
782     ok(script_disp != (IDispatch*)&Global, "script_disp == Global\n");
783
784     hres = IActiveScriptParse64_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
785
786     IDispatch_Release(script_disp);
787     IActiveScript_Release(engine);
788     IUnknown_Release(parser);
789
790     return hres;
791 }
792
793 static void parse_script_af(DWORD flags, const char *src)
794 {
795     BSTR tmp;
796     HRESULT hres;
797
798     tmp = a2bstr(src);
799     hres = parse_script(flags, tmp);
800     SysFreeString(tmp);
801     ok(hres == S_OK, "parse_script failed: %08x\n", hres);
802 }
803
804 static void parse_script_a(const char *src)
805 {
806     parse_script_af(SCRIPTITEM_GLOBALMEMBERS, src);
807 }
808
809 static BSTR get_script_from_file(const char *filename)
810 {
811     DWORD size, len;
812     HANDLE file, map;
813     const char *file_map;
814     BSTR ret;
815
816     file = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
817     if(file == INVALID_HANDLE_VALUE) {
818         trace("Could not open file: %u\n", GetLastError());
819         return NULL;
820     }
821
822     size = GetFileSize(file, NULL);
823
824     map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
825     CloseHandle(file);
826     if(map == INVALID_HANDLE_VALUE) {
827         trace("Could not create file mapping: %u\n", GetLastError());
828         return NULL;
829     }
830
831     file_map = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
832     CloseHandle(map);
833     if(!file_map) {
834         trace("MapViewOfFile failed: %u\n", GetLastError());
835         return NULL;
836     }
837
838     len = MultiByteToWideChar(CP_ACP, 0, file_map, size, NULL, 0);
839     ret = SysAllocStringLen(NULL, len);
840     MultiByteToWideChar(CP_ACP, 0, file_map, size, ret, len);
841
842     UnmapViewOfFile(file_map);
843
844     return ret;
845 }
846
847 static void run_from_file(const char *filename)
848 {
849     BSTR script_str;
850     HRESULT hres;
851
852     script_str = get_script_from_file(filename);
853     if(!script_str)
854         return;
855
856     strict_dispid_check = FALSE;
857     hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, script_str);
858     SysFreeString(script_str);
859     ok(hres == S_OK, "parse_script failed: %08x\n", hres);
860 }
861
862 static void run_from_res(const char *name)
863 {
864     const char *data;
865     DWORD size, len;
866     BSTR str;
867     HRSRC src;
868     HRESULT hres;
869
870     strict_dispid_check = FALSE;
871     test_name = name;
872
873     src = FindResourceA(NULL, name, (LPCSTR)40);
874     ok(src != NULL, "Could not find resource %s\n", name);
875
876     size = SizeofResource(NULL, src);
877     data = LoadResource(NULL, src);
878
879     len = MultiByteToWideChar(CP_ACP, 0, data, size, NULL, 0);
880     str = SysAllocStringLen(NULL, len);
881     MultiByteToWideChar(CP_ACP, 0, data, size, str, len);
882
883     SET_EXPECT(global_success_d);
884     SET_EXPECT(global_success_i);
885     hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, str);
886     CHECK_CALLED(global_success_d);
887     CHECK_CALLED(global_success_i);
888
889     ok(hres == S_OK, "parse_script failed: %08x\n", hres);
890     SysFreeString(str);
891 }
892
893 static void run_tests(void)
894 {
895     strict_dispid_check = TRUE;
896
897     parse_script_a("");
898     parse_script_a("' empty ;");
899
900     SET_EXPECT(global_success_d);
901     SET_EXPECT(global_success_i);
902     parse_script_a("reportSuccess");
903     CHECK_CALLED(global_success_d);
904     CHECK_CALLED(global_success_i);
905
906     SET_EXPECT(global_success_d);
907     SET_EXPECT(global_success_i);
908     parse_script_a("reportSuccess()");
909     CHECK_CALLED(global_success_d);
910     CHECK_CALLED(global_success_i);
911
912     SET_EXPECT(global_success_d);
913     SET_EXPECT(global_success_i);
914     parse_script_a("Call reportSuccess");
915     CHECK_CALLED(global_success_d);
916     CHECK_CALLED(global_success_i);
917
918     SET_EXPECT(global_vbvar_d);
919     SET_EXPECT(global_vbvar_i);
920     parse_script_a("Option Explicit\nvbvar = 3");
921     CHECK_CALLED(global_vbvar_d);
922     CHECK_CALLED(global_vbvar_i);
923
924     SET_EXPECT(global_vbvar_d);
925     SET_EXPECT(global_vbvar_i);
926     parse_script_a("Option Explicit\nvbvar() = 3");
927     CHECK_CALLED(global_vbvar_d);
928     CHECK_CALLED(global_vbvar_i);
929
930     SET_EXPECT(testobj_propget_d);
931     SET_EXPECT(testobj_propget_i);
932     parse_script_a("dim x\nx = testObj.propget");
933     CHECK_CALLED(testobj_propget_d);
934     CHECK_CALLED(testobj_propget_i);
935
936     SET_EXPECT(testobj_propput_d);
937     SET_EXPECT(testobj_propput_i);
938     parse_script_a("testObj.propput = 1");
939     CHECK_CALLED(testobj_propput_d);
940     CHECK_CALLED(testobj_propput_i);
941
942     run_from_res("lang.vbs");
943 }
944
945 static BOOL check_vbscript(void)
946 {
947     IActiveScript *vbscript;
948     HRESULT hres;
949
950     hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
951             &IID_IActiveScript, (void**)&vbscript);
952     if(SUCCEEDED(hres))
953         IActiveScript_Release(vbscript);
954
955     return hres == S_OK;
956 }
957
958 START_TEST(run)
959 {
960     int argc;
961     char **argv;
962
963     argc = winetest_get_mainargs(&argv);
964
965     CoInitialize(NULL);
966
967     if(!check_vbscript()) {
968         win_skip("Broken engine, probably too old\n");
969     }else if(argc > 2) {
970         run_from_file(argv[2]);
971     }else {
972         run_tests();
973     }
974
975     CoUninitialize();
976 }