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