2 * Copyright 2011 Jacek Caban for CodeWeavers
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.
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.
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
28 #include "wine/test.h"
30 extern const CLSID CLSID_VBScript
;
32 #define DEFINE_EXPECT(func) \
33 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
35 #define SET_EXPECT(func) \
36 expect_ ## func = TRUE
38 #define SET_CALLED(func) \
39 called_ ## func = TRUE
41 #define CHECK_EXPECT2(func) \
43 ok(expect_ ##func, "unexpected call " #func "\n"); \
44 called_ ## func = TRUE; \
47 #define CHECK_EXPECT(func) \
49 CHECK_EXPECT2(func); \
50 expect_ ## func = FALSE; \
53 #define CHECK_CALLED(func) \
55 ok(called_ ## func, "expected " #func "\n"); \
56 expect_ ## func = called_ ## func = FALSE; \
59 DEFINE_EXPECT(global_success_d
);
60 DEFINE_EXPECT(global_success_i
);
62 #define DISPID_GLOBAL_REPORTSUCCESS 1000
63 #define DISPID_GLOBAL_TRACE 1001
64 #define DISPID_GLOBAL_OK 1002
65 #define DISPID_GLOBAL_GETVT 1003
66 #define DISPID_GLOBAL_ISENGLOC 1004
68 static const WCHAR testW
[] = {'t','e','s','t',0};
70 static BOOL strict_dispid_check
;
71 static const char *test_name
= "(null)";
73 static BSTR
a2bstr(const char *str
)
78 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
79 ret
= SysAllocStringLen(NULL
, len
-1);
80 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
85 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
88 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), 0, 0);
89 return lstrcmpA(buf
, stra
);
92 static const char *vt2a(VARIANT
*v
)
94 if(V_VT(v
) == (VT_BYREF
|VT_VARIANT
)) {
96 sprintf(buf
, "%s*", vt2a(V_BYREF(v
)));
114 return "VT_DISPATCH";
117 case VT_ARRAY
|VT_VARIANT
:
118 return "VT_ARRAY|VT_VARIANT";
120 ok(0, "unknown vt %d\n", V_VT(v
));
125 static BOOL
is_english(void)
127 return PRIMARYLANGID(GetSystemDefaultLangID()) == LANG_ENGLISH
128 && PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH
;
131 #define test_grfdex(a,b) _test_grfdex(__LINE__,a,b)
132 static void _test_grfdex(unsigned line
, DWORD grfdex
, DWORD expect
)
134 ok_(__FILE__
,line
)(grfdex
== expect
, "grfdex = %x, expected %x\n", grfdex
, expect
);
137 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
141 if(IsEqualGUID(riid
, &IID_IUnknown
)
142 || IsEqualGUID(riid
, &IID_IDispatch
)
143 || IsEqualGUID(riid
, &IID_IDispatchEx
))
146 return E_NOINTERFACE
;
151 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
156 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
161 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
163 ok(0, "unexpected call\n");
167 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
,
168 LCID lcid
, ITypeInfo
**ppTInfo
)
170 ok(0, "unexpected call\n");
174 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
175 LPOLESTR
*rgszNames
, UINT cNames
,
176 LCID lcid
, DISPID
*rgDispId
)
178 ok(0, "unexpected call\n");
182 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
183 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
184 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
186 ok(0, "unexpected call\n");
190 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
192 ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName
), grfdex
);
196 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
198 ok(0, "unexpected call\n");
202 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
204 ok(0, "unexpected call\n");
208 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
210 ok(0, "unexpected call\n");
214 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
216 ok(0, "unexpected call\n");
220 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
222 ok(0, "unexpected call\n");
227 static HRESULT WINAPI
Global_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
229 if(!strcmp_wa(bstrName
, "ok")) {
230 test_grfdex(grfdex
, fdexNameCaseInsensitive
);
231 *pid
= DISPID_GLOBAL_OK
;
234 if(!strcmp_wa(bstrName
, "trace")) {
235 test_grfdex(grfdex
, fdexNameCaseInsensitive
);
236 *pid
= DISPID_GLOBAL_TRACE
;
239 if(!strcmp_wa(bstrName
, "reportSuccess")) {
240 CHECK_EXPECT(global_success_d
);
241 test_grfdex(grfdex
, fdexNameCaseInsensitive
);
242 *pid
= DISPID_GLOBAL_REPORTSUCCESS
;
245 if(!strcmp_wa(bstrName
, "getVT")) {
246 test_grfdex(grfdex
, fdexNameCaseInsensitive
);
247 *pid
= DISPID_GLOBAL_GETVT
;
250 if(!strcmp_wa(bstrName
, "isEnglishLocale")) {
251 test_grfdex(grfdex
, fdexNameCaseInsensitive
);
252 *pid
= DISPID_GLOBAL_ISENGLOC
;
256 if(strict_dispid_check
&& strcmp_wa(bstrName
, "x"))
257 ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName
), grfdex
);
258 return DISP_E_UNKNOWNNAME
;
261 static HRESULT WINAPI
Global_InvokeEx(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
262 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
265 case DISPID_GLOBAL_OK
: {
268 ok(wFlags
== INVOKE_FUNC
|| wFlags
== (INVOKE_FUNC
|INVOKE_PROPERTYGET
), "wFlags = %x\n", wFlags
);
269 ok(pdp
!= NULL
, "pdp == NULL\n");
270 ok(pdp
->rgvarg
!= NULL
, "rgvarg == NULL\n");
271 ok(!pdp
->rgdispidNamedArgs
, "rgdispidNamedArgs != NULL\n");
272 ok(pdp
->cArgs
== 2, "cArgs = %d\n", pdp
->cArgs
);
273 ok(!pdp
->cNamedArgs
, "cNamedArgs = %d\n", pdp
->cNamedArgs
);
274 if(wFlags
& INVOKE_PROPERTYGET
)
275 ok(pvarRes
!= NULL
, "pvarRes == NULL\n");
277 ok(!pvarRes
, "pvarRes != NULL\n");
278 ok(pei
!= NULL
, "pei == NULL\n");
280 ok(V_VT(pdp
->rgvarg
) == VT_BSTR
, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp
->rgvarg
));
283 if(V_VT(b
) == (VT_BYREF
|VT_VARIANT
))
286 ok(V_VT(b
) == VT_BOOL
, "V_VT(b) = %d\n", V_VT(b
));
288 ok(V_BOOL(b
), "%s: %s\n", test_name
, wine_dbgstr_w(V_BSTR(pdp
->rgvarg
)));
292 case DISPID_GLOBAL_TRACE
:
293 ok(wFlags
== INVOKE_FUNC
, "wFlags = %x\n", wFlags
);
294 ok(pdp
!= NULL
, "pdp == NULL\n");
295 ok(pdp
->rgvarg
!= NULL
, "rgvarg == NULL\n");
296 ok(!pdp
->rgdispidNamedArgs
, "rgdispidNamedArgs != NULL\n");
297 ok(pdp
->cArgs
== 1, "cArgs = %d\n", pdp
->cArgs
);
298 ok(!pdp
->cNamedArgs
, "cNamedArgs = %d\n", pdp
->cNamedArgs
);
299 ok(!pvarRes
, "pvarRes != NULL\n");
300 ok(pei
!= NULL
, "pei == NULL\n");
302 ok(V_VT(pdp
->rgvarg
) == VT_BSTR
, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp
->rgvarg
));
303 if(V_VT(pdp
->rgvarg
) == VT_BSTR
)
304 trace("%s: %s\n", test_name
, wine_dbgstr_w(V_BSTR(pdp
->rgvarg
)));
308 case DISPID_GLOBAL_REPORTSUCCESS
:
309 CHECK_EXPECT(global_success_i
);
311 ok(wFlags
== INVOKE_FUNC
, "wFlags = %x\n", wFlags
);
312 ok(pdp
!= NULL
, "pdp == NULL\n");
313 ok(!pdp
->rgdispidNamedArgs
, "rgdispidNamedArgs != NULL\n");
314 ok(pdp
->cArgs
== 0, "cArgs = %d\n", pdp
->cArgs
);
315 ok(!pdp
->cNamedArgs
, "cNamedArgs = %d\n", pdp
->cNamedArgs
);
316 ok(!pvarRes
, "pvarRes != NULL\n");
317 ok(pei
!= NULL
, "pei == NULL\n");
321 case DISPID_GLOBAL_GETVT
:
322 ok(pdp
!= NULL
, "pdp == NULL\n");
323 ok(pdp
->rgvarg
!= NULL
, "rgvarg == NULL\n");
324 ok(!pdp
->rgdispidNamedArgs
, "rgdispidNamedArgs != NULL\n");
325 ok(pdp
->cArgs
== 1, "cArgs = %d\n", pdp
->cArgs
);
326 ok(!pdp
->cNamedArgs
, "cNamedArgs = %d\n", pdp
->cNamedArgs
);
327 ok(pvarRes
!= NULL
, "pvarRes == NULL\n");
328 ok(V_VT(pvarRes
) == VT_EMPTY
, "V_VT(pvarRes) = %d\n", V_VT(pvarRes
));
329 ok(pei
!= NULL
, "pei == NULL\n");
331 V_VT(pvarRes
) = VT_BSTR
;
332 V_BSTR(pvarRes
) = a2bstr(vt2a(pdp
->rgvarg
));
335 case DISPID_GLOBAL_ISENGLOC
:
336 ok(wFlags
== (INVOKE_FUNC
|INVOKE_PROPERTYGET
), "wFlags = %x\n", wFlags
);
337 ok(pdp
!= NULL
, "pdp == NULL\n");
338 ok(!pdp
->rgdispidNamedArgs
, "rgdispidNamedArgs != NULL\n");
339 ok(pdp
->cArgs
== 0, "cArgs = %d\n", pdp
->cArgs
);
340 ok(!pdp
->cNamedArgs
, "cNamedArgs = %d\n", pdp
->cNamedArgs
);
341 ok(pvarRes
!= NULL
, "pvarRes == NULL\n");
342 ok(pei
!= NULL
, "pei == NULL\n");
344 V_VT(pvarRes
) = VT_BOOL
;
346 V_BOOL(pvarRes
) = VARIANT_TRUE
;
348 skip("Skipping some test in non-English locale\n");
349 V_BOOL(pvarRes
) = VARIANT_FALSE
;
355 ok(0, "unexpected call %d\n", id
);
356 return DISP_E_MEMBERNOTFOUND
;
359 static IDispatchExVtbl GlobalVtbl
= {
360 DispatchEx_QueryInterface
,
363 DispatchEx_GetTypeInfoCount
,
364 DispatchEx_GetTypeInfo
,
365 DispatchEx_GetIDsOfNames
,
369 DispatchEx_DeleteMemberByName
,
370 DispatchEx_DeleteMemberByDispID
,
371 DispatchEx_GetMemberProperties
,
372 DispatchEx_GetMemberName
,
373 DispatchEx_GetNextDispID
,
374 DispatchEx_GetNameSpaceParent
377 static IDispatchEx Global
= { &GlobalVtbl
};
379 static HRESULT WINAPI
ActiveScriptSite_QueryInterface(IActiveScriptSite
*iface
, REFIID riid
, void **ppv
)
383 if(IsEqualGUID(&IID_IUnknown
, riid
))
385 else if(IsEqualGUID(&IID_IActiveScriptSite
, riid
))
388 return E_NOINTERFACE
;
390 IUnknown_AddRef((IUnknown
*)*ppv
);
394 static ULONG WINAPI
ActiveScriptSite_AddRef(IActiveScriptSite
*iface
)
399 static ULONG WINAPI
ActiveScriptSite_Release(IActiveScriptSite
*iface
)
404 static HRESULT WINAPI
ActiveScriptSite_GetLCID(IActiveScriptSite
*iface
, LCID
*plcid
)
406 *plcid
= GetUserDefaultLCID();
410 static HRESULT WINAPI
ActiveScriptSite_GetItemInfo(IActiveScriptSite
*iface
, LPCOLESTR pstrName
,
411 DWORD dwReturnMask
, IUnknown
**ppiunkItem
, ITypeInfo
**ppti
)
413 ok(dwReturnMask
== SCRIPTINFO_IUNKNOWN
, "unexpected dwReturnMask %x\n", dwReturnMask
);
414 ok(!ppti
, "ppti != NULL\n");
416 if(strcmp_wa(pstrName
, "test"))
417 ok(0, "unexpected pstrName %s\n", wine_dbgstr_w(pstrName
));
419 *ppiunkItem
= (IUnknown
*)&Global
;
423 static HRESULT WINAPI
ActiveScriptSite_GetDocVersionString(IActiveScriptSite
*iface
, BSTR
*pbstrVersion
)
428 static HRESULT WINAPI
ActiveScriptSite_OnScriptTerminate(IActiveScriptSite
*iface
,
429 const VARIANT
*pvarResult
, const EXCEPINFO
*pexcepinfo
)
434 static HRESULT WINAPI
ActiveScriptSite_OnStateChange(IActiveScriptSite
*iface
, SCRIPTSTATE ssScriptState
)
439 static HRESULT WINAPI
ActiveScriptSite_OnScriptError(IActiveScriptSite
*iface
, IActiveScriptError
*pscripterror
)
444 static HRESULT WINAPI
ActiveScriptSite_OnEnterScript(IActiveScriptSite
*iface
)
449 static HRESULT WINAPI
ActiveScriptSite_OnLeaveScript(IActiveScriptSite
*iface
)
454 #undef ACTSCPSITE_THIS
456 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl
= {
457 ActiveScriptSite_QueryInterface
,
458 ActiveScriptSite_AddRef
,
459 ActiveScriptSite_Release
,
460 ActiveScriptSite_GetLCID
,
461 ActiveScriptSite_GetItemInfo
,
462 ActiveScriptSite_GetDocVersionString
,
463 ActiveScriptSite_OnScriptTerminate
,
464 ActiveScriptSite_OnStateChange
,
465 ActiveScriptSite_OnScriptError
,
466 ActiveScriptSite_OnEnterScript
,
467 ActiveScriptSite_OnLeaveScript
470 static IActiveScriptSite ActiveScriptSite
= { &ActiveScriptSiteVtbl
};
472 static IActiveScript
*create_script(void)
474 IActiveScript
*script
;
477 hres
= CoCreateInstance(&CLSID_VBScript
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
478 &IID_IActiveScript
, (void**)&script
);
479 ok(hres
== S_OK
, "CoCreateInstance failed: %08x\n", hres
);
484 static HRESULT
parse_script(DWORD flags
, BSTR script_str
)
486 IActiveScriptParse
*parser
;
487 IActiveScript
*engine
;
488 IDispatch
*script_disp
;
491 engine
= create_script();
495 hres
= IActiveScript_QueryInterface(engine
, &IID_IActiveScriptParse
, (void**)&parser
);
496 ok(hres
== S_OK
, "Could not get IActiveScriptParse: %08x\n", hres
);
499 IActiveScript_Release(engine
);
503 hres
= IActiveScriptParse64_InitNew(parser
);
504 ok(hres
== S_OK
, "InitNew failed: %08x\n", hres
);
506 hres
= IActiveScript_SetScriptSite(engine
, &ActiveScriptSite
);
507 ok(hres
== S_OK
, "SetScriptSite failed: %08x\n", hres
);
509 hres
= IActiveScript_AddNamedItem(engine
, testW
,
510 SCRIPTITEM_ISVISIBLE
|SCRIPTITEM_ISSOURCE
|flags
);
511 ok(hres
== S_OK
, "AddNamedItem failed: %08x\n", hres
);
513 hres
= IActiveScript_SetScriptState(engine
, SCRIPTSTATE_STARTED
);
514 ok(hres
== S_OK
, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres
);
516 hres
= IActiveScript_GetScriptDispatch(engine
, NULL
, &script_disp
);
517 ok(hres
== S_OK
, "GetScriptDispatch failed: %08x\n", hres
);
518 ok(script_disp
!= NULL
, "script_disp == NULL\n");
519 ok(script_disp
!= (IDispatch
*)&Global
, "script_disp == Global\n");
521 hres
= IActiveScriptParse64_ParseScriptText(parser
, script_str
, NULL
, NULL
, NULL
, 0, 0, 0, NULL
, NULL
);
523 IDispatch_Release(script_disp
);
524 IActiveScript_Release(engine
);
525 IUnknown_Release(parser
);
530 static void parse_script_af(DWORD flags
, const char *src
)
536 hres
= parse_script(flags
, tmp
);
538 ok(hres
== S_OK
, "parse_script failed: %08x\n", hres
);
541 static void parse_script_a(const char *src
)
543 parse_script_af(SCRIPTITEM_GLOBALMEMBERS
, src
);
546 static BSTR
get_script_from_file(const char *filename
)
550 const char *file_map
;
553 file
= CreateFileA(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_READONLY
, NULL
);
554 if(file
== INVALID_HANDLE_VALUE
) {
555 trace("Could not open file: %u\n", GetLastError());
559 size
= GetFileSize(file
, NULL
);
561 map
= CreateFileMapping(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
563 if(map
== INVALID_HANDLE_VALUE
) {
564 trace("Could not create file mapping: %u\n", GetLastError());
568 file_map
= MapViewOfFile(map
, FILE_MAP_READ
, 0, 0, 0);
571 trace("MapViewOfFile failed: %u\n", GetLastError());
575 len
= MultiByteToWideChar(CP_ACP
, 0, file_map
, size
, NULL
, 0);
576 ret
= SysAllocStringLen(NULL
, len
);
577 MultiByteToWideChar(CP_ACP
, 0, file_map
, size
, ret
, len
);
579 UnmapViewOfFile(file_map
);
584 static void run_from_file(const char *filename
)
589 script_str
= get_script_from_file(filename
);
593 strict_dispid_check
= FALSE
;
594 hres
= parse_script(SCRIPTITEM_GLOBALMEMBERS
, script_str
);
595 SysFreeString(script_str
);
596 ok(hres
== S_OK
, "parse_script failed: %08x\n", hres
);
599 static void run_from_res(const char *name
)
607 strict_dispid_check
= FALSE
;
610 src
= FindResourceA(NULL
, name
, (LPCSTR
)40);
611 ok(src
!= NULL
, "Could not find resource %s\n", name
);
613 size
= SizeofResource(NULL
, src
);
614 data
= LoadResource(NULL
, src
);
616 len
= MultiByteToWideChar(CP_ACP
, 0, data
, size
, NULL
, 0);
617 str
= SysAllocStringLen(NULL
, len
);
618 MultiByteToWideChar(CP_ACP
, 0, data
, size
, str
, len
);
620 SET_EXPECT(global_success_d
);
621 SET_EXPECT(global_success_i
);
622 hres
= parse_script(SCRIPTITEM_GLOBALMEMBERS
, str
);
623 CHECK_CALLED(global_success_d
);
624 CHECK_CALLED(global_success_i
);
626 ok(hres
== S_OK
, "parse_script failed: %08x\n", hres
);
630 static void run_tests(void)
632 strict_dispid_check
= TRUE
;
635 parse_script_a("' empty ;");
637 SET_EXPECT(global_success_d
);
638 SET_EXPECT(global_success_i
);
639 parse_script_a("reportSuccess");
640 CHECK_CALLED(global_success_d
);
641 CHECK_CALLED(global_success_i
);
643 SET_EXPECT(global_success_d
);
644 SET_EXPECT(global_success_i
);
645 parse_script_a("reportSuccess()");
646 CHECK_CALLED(global_success_d
);
647 CHECK_CALLED(global_success_i
);
649 SET_EXPECT(global_success_d
);
650 SET_EXPECT(global_success_i
);
651 parse_script_a("Call reportSuccess");
652 CHECK_CALLED(global_success_d
);
653 CHECK_CALLED(global_success_i
);
655 run_from_res("lang.vbs");
658 static BOOL
check_vbscript(void)
660 IActiveScript
*vbscript
;
663 hres
= CoCreateInstance(&CLSID_VBScript
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
664 &IID_IActiveScript
, (void**)&vbscript
);
666 IActiveScript_Release(vbscript
);
676 argc
= winetest_get_mainargs(&argv
);
680 if(!check_vbscript()) {
681 win_skip("Broken engine, probably too old\n");
683 run_from_file(argv
[2]);