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
23 #include "vbscript_defs.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(vbscript
);
33 #define VB_E_CANNOT_CREATE_OBJ 0x800a01ad
34 #define VB_E_MK_PARSE_ERROR 0x800a01b0
36 /* Defined as extern in urlmon.idl, but not exported by uuid.lib */
37 const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY
=
38 {0x10200490,0xfa38,0x11d0,{0xac,0x0e,0x00,0xa0,0xc9,0xf,0xff,0xc0}};
48 struct _builtin_prop_t
{
50 HRESULT (*proc
)(BuiltinDisp
*,VARIANT
*,unsigned,VARIANT
*);
56 static inline BuiltinDisp
*impl_from_IDispatch(IDispatch
*iface
)
58 return CONTAINING_RECORD(iface
, BuiltinDisp
, IDispatch_iface
);
61 static HRESULT WINAPI
Builtin_QueryInterface(IDispatch
*iface
, REFIID riid
, void **ppv
)
63 BuiltinDisp
*This
= impl_from_IDispatch(iface
);
65 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
66 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
67 *ppv
= &This
->IDispatch_iface
;
68 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
69 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
70 *ppv
= &This
->IDispatch_iface
;
72 if(!IsEqualGUID(riid
, &IID_IDispatchEx
))
73 WARN("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
78 IUnknown_AddRef((IUnknown
*)*ppv
);
82 static ULONG WINAPI
Builtin_AddRef(IDispatch
*iface
)
84 BuiltinDisp
*This
= impl_from_IDispatch(iface
);
85 LONG ref
= InterlockedIncrement(&This
->ref
);
87 TRACE("(%p) ref=%ld\n", This
, ref
);
92 static ULONG WINAPI
Builtin_Release(IDispatch
*iface
)
94 BuiltinDisp
*This
= impl_from_IDispatch(iface
);
95 LONG ref
= InterlockedDecrement(&This
->ref
);
97 TRACE("(%p) ref=%ld\n", This
, ref
);
107 static HRESULT WINAPI
Builtin_GetTypeInfoCount(IDispatch
*iface
, UINT
*pctinfo
)
109 BuiltinDisp
*This
= impl_from_IDispatch(iface
);
110 TRACE("(%p)->(%p)\n", This
, pctinfo
);
115 static HRESULT WINAPI
Builtin_GetTypeInfo(IDispatch
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
117 BuiltinDisp
*This
= impl_from_IDispatch(iface
);
118 TRACE("(%p)->(%u %lu %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
119 return DISP_E_BADINDEX
;
122 HRESULT
get_builtin_id(BuiltinDisp
*disp
, const WCHAR
*name
, DISPID
*id
)
124 size_t min
= 1, max
= disp
->member_cnt
- 1, i
;
129 r
= wcsicmp(disp
->members
[i
].name
, name
);
140 return DISP_E_MEMBERNOTFOUND
;
144 static HRESULT WINAPI
Builtin_GetIDsOfNames(IDispatch
*iface
, REFIID riid
, LPOLESTR
*names
, UINT name_cnt
,
145 LCID lcid
, DISPID
*ids
)
147 BuiltinDisp
*This
= impl_from_IDispatch(iface
);
151 TRACE("(%p)->(%s %p %u %lu %p)\n", This
, debugstr_guid(riid
), names
, name_cnt
, lcid
, ids
);
154 FIXME("NULL context\n");
158 for(i
= 0; i
< name_cnt
; i
++) {
159 hres
= get_builtin_id(This
, names
[i
], &ids
[i
]);
167 static HRESULT WINAPI
Builtin_Invoke(IDispatch
*iface
, DISPID id
, REFIID riid
, LCID lcid
, WORD flags
,
168 DISPPARAMS
*dp
, VARIANT
*res
, EXCEPINFO
*ei
, UINT
*err
)
170 BuiltinDisp
*This
= impl_from_IDispatch(iface
);
171 const builtin_prop_t
*prop
;
172 VARIANT args_buf
[8], *args
;
176 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This
, id
, debugstr_guid(riid
), lcid
, flags
, dp
, res
, ei
, err
);
179 FIXME("NULL context\n");
183 if(id
>= This
->member_cnt
|| (!This
->members
[id
].proc
&& !This
->members
[id
].flags
))
184 return DISP_E_MEMBERNOTFOUND
;
185 prop
= This
->members
+ id
;
188 case DISPATCH_PROPERTYGET
:
189 if(!(prop
->flags
& (BP_GET
|BP_GETPUT
))) {
190 FIXME("property does not support DISPATCH_PROPERTYGET\n");
194 case DISPATCH_PROPERTYGET
|DISPATCH_METHOD
:
195 if(!prop
->proc
&& prop
->flags
== BP_GET
) {
196 const int vt
= prop
->min_args
, val
= prop
->max_args
;
207 const string_constant_t
*str
= (const string_constant_t
*)prop
->max_args
;
210 ret
= SysAllocStringLen(str
->buf
, str
->len
);
212 return E_OUTOFMEMORY
;
223 case DISPATCH_METHOD
:
224 if(prop
->flags
& (BP_GET
|BP_GETPUT
)) {
225 FIXME("Call on property\n");
229 case DISPATCH_PROPERTYPUT
:
230 if(!(prop
->flags
& BP_GETPUT
)) {
231 FIXME("property does not support DISPATCH_PROPERTYPUT\n");
238 FIXME("unsupported flags %x\n", flags
);
244 if(argn
< prop
->min_args
|| argn
> (prop
->max_args
? prop
->max_args
: prop
->min_args
)) {
245 WARN("invalid number of arguments\n");
246 return MAKE_VBSERROR(VBSE_FUNC_ARITY_MISMATCH
);
249 if(argn
<= ARRAY_SIZE(args_buf
)) {
252 args
= malloc(argn
* sizeof(*args
));
254 return E_OUTOFMEMORY
;
257 for(i
=0; i
< argn
; i
++) {
258 if(V_VT(dp
->rgvarg
+dp
->cArgs
-i
-1) == (VT_BYREF
|VT_VARIANT
))
259 args
[i
] = *V_VARIANTREF(dp
->rgvarg
+dp
->cArgs
-i
-1);
261 args
[i
] = dp
->rgvarg
[dp
->cArgs
-i
-1];
264 hres
= prop
->proc(This
, args
, dp
->cArgs
, res
);
270 static const IDispatchVtbl BuiltinDispVtbl
= {
271 Builtin_QueryInterface
,
274 Builtin_GetTypeInfoCount
,
276 Builtin_GetIDsOfNames
,
280 static HRESULT
create_builtin_dispatch(script_ctx_t
*ctx
, const builtin_prop_t
*members
, size_t member_cnt
, BuiltinDisp
**ret
)
284 if(!(disp
= malloc(sizeof(*disp
))))
285 return E_OUTOFMEMORY
;
287 disp
->IDispatch_iface
.lpVtbl
= &BuiltinDispVtbl
;
289 disp
->members
= members
;
290 disp
->member_cnt
= member_cnt
;
297 static IInternetHostSecurityManager
*get_sec_mgr(script_ctx_t
*ctx
)
299 IInternetHostSecurityManager
*secmgr
;
300 IServiceProvider
*sp
;
309 hres
= IActiveScriptSite_QueryInterface(ctx
->site
, &IID_IServiceProvider
, (void**)&sp
);
313 hres
= IServiceProvider_QueryService(sp
, &SID_SInternetHostSecurityManager
, &IID_IInternetHostSecurityManager
,
315 IServiceProvider_Release(sp
);
319 return ctx
->secmgr
= secmgr
;
322 static HRESULT
return_string(VARIANT
*res
, const WCHAR
*str
)
329 ret
= SysAllocString(str
);
331 return E_OUTOFMEMORY
;
338 static HRESULT
return_bstr(VARIANT
*res
, BSTR str
)
349 static HRESULT
return_bool(VARIANT
*res
, BOOL val
)
353 V_BOOL(res
) = val
? VARIANT_TRUE
: VARIANT_FALSE
;
358 static HRESULT
return_short(VARIANT
*res
, short val
)
368 static HRESULT
return_int(VARIANT
*res
, int val
)
378 static inline HRESULT
return_double(VARIANT
*res
, double val
)
388 static inline HRESULT
return_float(VARIANT
*res
, float val
)
398 static inline HRESULT
return_null(VARIANT
*res
)
405 static inline HRESULT
return_date(VARIANT
*res
, double date
)
414 HRESULT
to_int(VARIANT
*v
, int *ret
)
420 hres
= VariantChangeType(&r
, v
, 0, VT_I4
);
428 static HRESULT
to_double(VARIANT
*v
, double *ret
)
433 V_VT(&dst
) = VT_EMPTY
;
434 hres
= VariantChangeType(&dst
, v
, 0, VT_R8
);
442 static HRESULT
to_float(VARIANT
*v
, float *ret
)
447 V_VT(&dst
) = VT_EMPTY
;
448 hres
= VariantChangeType(&dst
, v
, 0, VT_R4
);
456 static HRESULT
to_string(VARIANT
*v
, BSTR
*ret
)
461 V_VT(&dst
) = VT_EMPTY
;
462 hres
= VariantChangeType(&dst
, v
, VARIANT_LOCALBOOL
, VT_BSTR
);
470 static HRESULT
to_system_time(VARIANT
*v
, SYSTEMTIME
*st
)
475 V_VT(&date
) = VT_EMPTY
;
476 hres
= VariantChangeType(&date
, v
, 0, VT_DATE
);
480 return VariantTimeToSystemTime(V_DATE(&date
), st
);
483 static HRESULT
set_object_site(script_ctx_t
*ctx
, IUnknown
*obj
)
485 IObjectWithSite
*obj_site
;
489 hres
= IUnknown_QueryInterface(obj
, &IID_IObjectWithSite
, (void**)&obj_site
);
493 ax_site
= create_ax_site(ctx
);
495 hres
= IObjectWithSite_SetSite(obj_site
, ax_site
);
496 IUnknown_Release(ax_site
);
499 hres
= E_OUTOFMEMORY
;
500 IObjectWithSite_Release(obj_site
);
504 static IUnknown
*create_object(script_ctx_t
*ctx
, const WCHAR
*progid
)
506 IInternetHostSecurityManager
*secmgr
= NULL
;
507 struct CONFIRMSAFETY cs
;
508 IClassFactoryEx
*cfex
;
517 hres
= CLSIDFromProgID(progid
, &guid
);
521 TRACE("GUID %s\n", debugstr_guid(&guid
));
523 if(ctx
->safeopt
& INTERFACE_USES_SECURITY_MANAGER
) {
524 secmgr
= get_sec_mgr(ctx
);
529 hres
= IInternetHostSecurityManager_ProcessUrlAction(secmgr
, URLACTION_ACTIVEX_RUN
,
530 (BYTE
*)&policy
, sizeof(policy
), (BYTE
*)&guid
, sizeof(GUID
), 0, 0);
531 if(FAILED(hres
) || policy
!= URLPOLICY_ALLOW
)
535 hres
= CoGetClassObject(&guid
, CLSCTX_INPROC_SERVER
|CLSCTX_LOCAL_SERVER
, NULL
, &IID_IClassFactory
, (void**)&cf
);
539 hres
= IClassFactory_QueryInterface(cf
, &IID_IClassFactoryEx
, (void**)&cfex
);
540 if(SUCCEEDED(hres
)) {
541 FIXME("Use IClassFactoryEx\n");
542 IClassFactoryEx_Release(cfex
);
545 hres
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void**)&obj
);
553 hres
= IInternetHostSecurityManager_QueryCustomPolicy(secmgr
, &GUID_CUSTOM_CONFIRMOBJECTSAFETY
,
554 &bpolicy
, &policy_size
, (BYTE
*)&cs
, sizeof(cs
), 0);
555 if(SUCCEEDED(hres
)) {
556 policy
= policy_size
>= sizeof(DWORD
) ? *(DWORD
*)bpolicy
: URLPOLICY_DISALLOW
;
557 CoTaskMemFree(bpolicy
);
560 if(FAILED(hres
) || policy
!= URLPOLICY_ALLOW
) {
561 IUnknown_Release(obj
);
566 hres
= set_object_site(ctx
, obj
);
568 IUnknown_Release(obj
);
575 static HRESULT
show_msgbox(script_ctx_t
*ctx
, BSTR prompt
, unsigned type
, BSTR orig_title
, VARIANT
*res
)
577 SCRIPTUICHANDLING uic_handling
= SCRIPTUICHANDLING_ALLOW
;
578 IActiveScriptSiteUIControl
*ui_control
;
579 IActiveScriptSiteWindow
*acts_window
;
580 WCHAR
*title_buf
= NULL
;
586 hres
= IActiveScriptSite_QueryInterface(ctx
->site
, &IID_IActiveScriptSiteUIControl
, (void**)&ui_control
);
587 if(SUCCEEDED(hres
)) {
588 hres
= IActiveScriptSiteUIControl_GetUIBehavior(ui_control
, SCRIPTUICITEM_MSGBOX
, &uic_handling
);
589 IActiveScriptSiteUIControl_Release(ui_control
);
591 uic_handling
= SCRIPTUICHANDLING_ALLOW
;
594 switch(uic_handling
) {
595 case SCRIPTUICHANDLING_ALLOW
:
597 case SCRIPTUICHANDLING_NOUIDEFAULT
:
598 return return_short(res
, 0);
604 hres
= IActiveScriptSite_QueryInterface(ctx
->site
, &IID_IActiveScriptSiteWindow
, (void**)&acts_window
);
606 FIXME("No IActiveScriptSiteWindow\n");
610 if(ctx
->safeopt
& INTERFACE_USES_SECURITY_MANAGER
) {
611 if(orig_title
&& *orig_title
) {
614 title
= title_buf
= malloc(sizeof(L
"VBScript") + (lstrlenW(orig_title
)+2)*sizeof(WCHAR
));
616 return E_OUTOFMEMORY
;
618 memcpy(title_buf
, L
"VBScript", sizeof(L
"VBScript"));
619 ptr
= title_buf
+ ARRAY_SIZE(L
"VBScript")-1;
623 lstrcpyW(ptr
, orig_title
);
628 title
= orig_title
? orig_title
: L
"";
631 hres
= IActiveScriptSiteWindow_GetWindow(acts_window
, &hwnd
);
632 if(SUCCEEDED(hres
)) {
633 hres
= IActiveScriptSiteWindow_EnableModeless(acts_window
, FALSE
);
634 if(SUCCEEDED(hres
)) {
635 ret
= MessageBoxW(hwnd
, prompt
, title
, type
);
636 hres
= IActiveScriptSiteWindow_EnableModeless(acts_window
, TRUE
);
641 IActiveScriptSiteWindow_Release(acts_window
);
643 FIXME("failed: %08lx\n", hres
);
647 return return_short(res
, ret
);
650 static HRESULT
Global_CCur(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
655 TRACE("%s\n", debugstr_variant(arg
));
657 assert(args_cnt
== 1);
660 hres
= VariantChangeType(&v
, arg
, 0, VT_CY
);
666 return DISP_E_BADVARTYPE
;
673 static HRESULT
Global_CInt(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
678 TRACE("%s\n", debugstr_variant(arg
));
680 assert(args_cnt
== 1);
683 hres
= VariantChangeType(&v
, arg
, 0, VT_I2
);
688 return DISP_E_BADVARTYPE
;
695 static HRESULT
Global_CLng(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
700 TRACE("%s\n", debugstr_variant(arg
));
702 assert(args_cnt
== 1);
704 hres
= to_int(arg
, &i
);
708 return DISP_E_BADVARTYPE
;
710 return return_int(res
, i
);
713 static HRESULT
Global_CBool(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
718 TRACE("%s\n", debugstr_variant(arg
));
720 assert(args_cnt
== 1);
723 hres
= VariantChangeType(&v
, arg
, VARIANT_LOCALBOOL
, VT_BOOL
);
734 static HRESULT
Global_CByte(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
739 TRACE("%s\n", debugstr_variant(arg
));
741 assert(args_cnt
== 1);
744 hres
= VariantChangeType(&v
, arg
, VARIANT_LOCALBOOL
, VT_UI1
);
750 return DISP_E_BADVARTYPE
;
757 static HRESULT
Global_CDate(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
762 TRACE("%s\n", debugstr_variant(arg
));
764 assert(args_cnt
== 1);
766 if(V_VT(arg
) == VT_NULL
)
767 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
770 hres
= VariantChangeType(&v
, arg
, 0, VT_DATE
);
772 hres
= VariantChangeType(&v
, arg
, 0, VT_R8
);
775 hres
= VariantChangeType(&v
, &v
, 0, VT_DATE
);
781 return DISP_E_BADVARTYPE
;
786 static HRESULT
Global_CDbl(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
791 TRACE("%s\n", debugstr_variant(arg
));
793 assert(args_cnt
== 1);
796 hres
= VariantChangeType(&v
, arg
, 0, VT_R8
);
801 return DISP_E_BADVARTYPE
;
808 static HRESULT
Global_CSng(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
813 TRACE("%s\n", debugstr_variant(arg
));
815 assert(args_cnt
== 1);
818 hres
= VariantChangeType(&v
, arg
, 0, VT_R4
);
823 return DISP_E_BADVARTYPE
;
829 static HRESULT
Global_CStr(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
834 TRACE("%s\n", debugstr_variant(arg
));
836 if(V_VT(arg
) == VT_NULL
)
837 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
839 hres
= to_string(arg
, &str
);
843 return return_bstr(res
, str
);
846 static inline WCHAR
hex_char(unsigned n
)
848 return n
< 10 ? '0'+n
: 'A'+n
-10;
851 static HRESULT
Global_Hex(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
858 TRACE("%s\n", debugstr_variant(arg
));
865 return return_null(res
);
867 hres
= to_int(arg
, &ret
);
879 *ptr
-- = hex_char(n
& 0xf);
887 return return_string(res
, ptr
);
890 static HRESULT
Global_Oct(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
897 TRACE("%s\n", debugstr_variant(arg
));
904 return return_null(res
);
906 hres
= to_int(arg
, &ret
);
918 *ptr
-- = '0' + (n
& 0x7);
926 return return_string(res
, ptr
);
929 static HRESULT
Global_VarType(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
933 TRACE("(%s)\n", debugstr_variant(arg
));
935 assert(args_cnt
== 1);
937 vt
= V_VT(arg
) & ~VT_BYREF
;
938 if(vt
& ~(VT_TYPEMASK
| VT_ARRAY
)) {
939 FIXME("not supported %s\n", debugstr_variant(arg
));
943 return return_short(res
, vt
);
946 static HRESULT
Global_IsDate(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
948 TRACE("%s\n", debugstr_variant(arg
));
950 return return_bool(res
, V_VT(arg
) == VT_DATE
);
953 static HRESULT
Global_IsEmpty(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
955 TRACE("(%s)\n", debugstr_variant(arg
));
957 assert(args_cnt
== 1);
958 return return_bool(res
, V_VT(arg
) == VT_EMPTY
);
961 static HRESULT
Global_IsNull(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
963 TRACE("(%s)\n", debugstr_variant(arg
));
965 assert(args_cnt
== 1);
967 return return_bool(res
, V_VT(arg
) == VT_NULL
);
970 static HRESULT
Global_IsNumeric(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
975 TRACE("(%s)\n", debugstr_variant(arg
));
977 assert(args_cnt
== 1);
979 hres
= to_double(arg
, &d
);
981 return return_bool(res
, SUCCEEDED(hres
));
984 static HRESULT
Global_IsArray(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
986 TRACE("(%s)\n", debugstr_variant(arg
));
988 assert(args_cnt
== 1);
990 return return_bool(res
, V_ISARRAY(arg
));
993 static HRESULT
Global_IsObject(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
995 TRACE("(%s)\n", debugstr_variant(arg
));
997 assert(args_cnt
== 1);
999 return return_bool(res
, V_VT(arg
) == VT_DISPATCH
);
1002 static HRESULT
Global_Atn(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1007 hres
= to_double(arg
, &d
);
1011 return return_double(res
, atan(d
));
1014 static HRESULT
Global_Cos(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1019 hres
= to_double(arg
, &d
);
1023 return return_double(res
, cos(d
));
1026 static HRESULT
Global_Sin(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1031 hres
= to_double(arg
, &d
);
1035 return return_double(res
, sin(d
));
1038 static HRESULT
Global_Tan(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1043 hres
= to_double(arg
, &d
);
1047 return return_double(res
, tan(d
));
1050 static HRESULT
Global_Exp(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1055 hres
= to_double(arg
, &d
);
1059 return return_double(res
, exp(d
));
1062 static HRESULT
Global_Log(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1067 hres
= to_double(arg
, &d
);
1072 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1074 return return_double(res
, log(d
));
1077 static HRESULT
Global_Sqr(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1082 hres
= to_double(arg
, &d
);
1087 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1089 return return_double(res
, sqrt(d
));
1092 static unsigned int get_next_rnd(int value
)
1094 return (value
* 0x43fd43fd + 0xc39ec3) & 0xffffff;
1097 static HRESULT
Global_Randomize(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1107 assert(args_cnt
== 0 || args_cnt
== 1);
1108 if (args_cnt
== 1) {
1109 hres
= to_double(arg
, &dtoi
.d
);
1114 dtoi
.d
= GetTickCount() * 0.001;
1117 seed
^= (seed
>> 16);
1118 seed
= ((seed
& 0xffff) << 8) | (This
->ctx
->script_obj
->rnd
& 0xff);
1119 This
->ctx
->script_obj
->rnd
= seed
;
1121 return res
? DISP_E_TYPEMISMATCH
: S_OK
;
1124 static HRESULT
Global_Rnd(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1126 static const float modulus
= 16777216.0f
;
1131 assert(args_cnt
== 0 || args_cnt
== 1);
1133 value
= This
->ctx
->script_obj
->rnd
;
1136 hres
= to_float(arg
, &f
);
1142 value
= *(unsigned int *)&f
;
1143 This
->ctx
->script_obj
->rnd
= value
= get_next_rnd(value
+ (value
>> 24));
1146 value
= This
->ctx
->script_obj
->rnd
;
1148 This
->ctx
->script_obj
->rnd
= value
= get_next_rnd(value
);
1152 This
->ctx
->script_obj
->rnd
= value
= get_next_rnd(value
);
1155 return return_float(res
, (float)value
/ modulus
);
1158 static HRESULT
Global_Timer(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1164 sec
= lt
.wHour
* 3600 + lt
.wMinute
* 60 + lt
.wSecond
+ lt
.wMilliseconds
/ 1000.0;
1165 return return_float(res
, sec
);
1169 static HRESULT
Global_LBound(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1176 assert(args_cnt
== 1 || args_cnt
== 2);
1178 TRACE("%s %s\n", debugstr_variant(arg
), args_cnt
== 2 ? debugstr_variant(arg
+ 1) : "1");
1181 case VT_VARIANT
|VT_ARRAY
:
1184 case VT_VARIANT
|VT_ARRAY
|VT_BYREF
:
1185 sa
= *V_ARRAYREF(arg
);
1189 return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
1191 FIXME("arg %s not supported\n", debugstr_variant(arg
));
1196 hres
= to_int(arg
+ 1, &dim
);
1203 hres
= SafeArrayGetLBound(sa
, dim
, &lbound
);
1207 return return_int(res
, lbound
);
1210 static HRESULT
Global_UBound(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1217 assert(args_cnt
== 1 || args_cnt
== 2);
1219 TRACE("%s %s\n", debugstr_variant(arg
), args_cnt
== 2 ? debugstr_variant(arg
+ 1) : "1");
1222 case VT_VARIANT
|VT_ARRAY
:
1225 case VT_VARIANT
|VT_ARRAY
|VT_BYREF
:
1226 sa
= *V_ARRAYREF(arg
);
1230 return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
1232 FIXME("arg %s not supported\n", debugstr_variant(arg
));
1237 hres
= to_int(arg
+ 1, &dim
);
1244 hres
= SafeArrayGetUBound(sa
, dim
, &ubound
);
1248 return return_int(res
, ubound
);
1251 static HRESULT
Global_RGB(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1256 TRACE("%s %s %s\n", debugstr_variant(arg
), debugstr_variant(arg
+ 1), debugstr_variant(arg
+ 2));
1258 assert(args_cnt
== 3);
1260 for(i
= 0; i
< 3; i
++) {
1261 hres
= to_int(arg
+ i
, color
+ i
);
1267 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1270 return return_int(res
, RGB(color
[0], color
[1], color
[2]));
1273 static HRESULT
Global_Len(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1278 TRACE("%s\n", debugstr_variant(arg
));
1280 if(V_VT(arg
) == VT_NULL
)
1281 return return_null(res
);
1283 if(V_VT(arg
) != VT_BSTR
) {
1286 hres
= to_string(arg
, &str
);
1290 len
= SysStringLen(str
);
1293 len
= SysStringLen(V_BSTR(arg
));
1296 return return_int(res
, len
);
1299 static HRESULT
Global_LenB(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1305 static HRESULT
Global_Left(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
1307 BSTR str
, ret
, conv_str
= NULL
;
1311 TRACE("(%s %s)\n", debugstr_variant(args
+1), debugstr_variant(args
));
1313 if(V_VT(args
) == VT_BSTR
) {
1316 hres
= to_string(args
, &conv_str
);
1322 hres
= to_int(args
+1, &len
);
1327 FIXME("len = %d\n", len
);
1331 str_len
= SysStringLen(str
);
1335 ret
= SysAllocStringLen(str
, len
);
1336 SysFreeString(conv_str
);
1338 return E_OUTOFMEMORY
;
1340 return return_bstr(res
, ret
);
1343 static HRESULT
Global_LeftB(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1349 static HRESULT
Global_Right(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
1351 BSTR str
, ret
, conv_str
= NULL
;
1355 TRACE("(%s %s)\n", debugstr_variant(args
), debugstr_variant(args
+1));
1357 if(V_VT(args
+1) == VT_NULL
)
1358 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
1360 hres
= to_int(args
+1, &len
);
1365 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1367 if(V_VT(args
) == VT_NULL
)
1368 return return_null(res
);
1370 if(V_VT(args
) == VT_BSTR
) {
1373 hres
= to_string(args
, &conv_str
);
1379 str_len
= SysStringLen(str
);
1383 ret
= SysAllocStringLen(str
+str_len
-len
, len
);
1384 SysFreeString(conv_str
);
1386 return E_OUTOFMEMORY
;
1388 return return_bstr(res
, ret
);
1391 static HRESULT
Global_RightB(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1397 static HRESULT
Global_Mid(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
1399 int len
= -1, start
, str_len
;
1400 BSTR str
, conv_str
= NULL
;
1403 TRACE("(%s %s ...)\n", debugstr_variant(args
), debugstr_variant(args
+1));
1405 assert(args_cnt
== 2 || args_cnt
== 3);
1407 if(V_VT(args
) == VT_EMPTY
)
1408 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1410 if(V_VT(args
+1) == VT_NULL
|| (args_cnt
== 3 && V_VT(args
+2) == VT_NULL
))
1411 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
1413 if(V_VT(args
+1) == VT_EMPTY
)
1414 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1416 hres
= to_int(args
+1, &start
);
1421 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1424 if(V_VT(args
+2) == VT_EMPTY
)
1425 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1427 hres
= to_int(args
+2, &len
);
1432 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1435 if(V_VT(args
) == VT_BSTR
) {
1438 hres
= to_string(args
, &conv_str
);
1444 str_len
= SysStringLen(str
);
1450 len
= str_len
-start
;
1451 else if(len
> str_len
-start
)
1452 len
= str_len
-start
;
1455 V_VT(res
) = VT_BSTR
;
1456 V_BSTR(res
) = SysAllocStringLen(str
+start
, len
);
1458 hres
= E_OUTOFMEMORY
;
1461 SysFreeString(conv_str
);
1466 static HRESULT
Global_MidB(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1472 static HRESULT
Global_StrComp(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
1479 TRACE("(%s %s ...)\n", debugstr_variant(args
), debugstr_variant(args
+1));
1481 assert(args_cnt
== 2 || args_cnt
== 3);
1483 if (args_cnt
== 3) {
1484 hres
= to_int(args
+2, &mode
);
1488 if (mode
!= 0 && mode
!= 1) {
1489 FIXME("unknown compare mode = %d\n", mode
);
1496 hres
= to_string(args
, &left
);
1500 hres
= to_string(args
+1, &right
);
1503 SysFreeString(left
);
1507 ret
= mode
? wcsicmp(left
, right
) : wcscmp(left
, right
);
1508 val
= ret
< 0 ? -1 : (ret
> 0 ? 1 : 0);
1510 SysFreeString(left
);
1511 SysFreeString(right
);
1512 return return_short(res
, val
);
1515 static HRESULT
Global_LCase(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1520 TRACE("%s\n", debugstr_variant(arg
));
1522 if(V_VT(arg
) == VT_NULL
) {
1523 return return_null(res
);
1526 hres
= to_string(arg
, &str
);
1533 for(ptr
= str
; *ptr
; ptr
++)
1534 *ptr
= towlower(*ptr
);
1536 V_VT(res
) = VT_BSTR
;
1544 static HRESULT
Global_UCase(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1549 TRACE("%s\n", debugstr_variant(arg
));
1551 if(V_VT(arg
) == VT_NULL
) {
1552 return return_null(res
);
1555 hres
= to_string(arg
, &str
);
1562 for(ptr
= str
; *ptr
; ptr
++)
1563 *ptr
= towupper(*ptr
);
1565 V_VT(res
) = VT_BSTR
;
1573 static HRESULT
Global_LTrim(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1575 BSTR str
, conv_str
= NULL
;
1579 TRACE("%s\n", debugstr_variant(arg
));
1581 if(V_VT(arg
) == VT_BSTR
) {
1584 hres
= to_string(arg
, &conv_str
);
1590 for(ptr
= str
; *ptr
&& iswspace(*ptr
); ptr
++);
1592 str
= SysAllocString(ptr
);
1593 SysFreeString(conv_str
);
1595 return E_OUTOFMEMORY
;
1597 return return_bstr(res
, str
);
1600 static HRESULT
Global_RTrim(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1602 BSTR str
, conv_str
= NULL
;
1606 TRACE("%s\n", debugstr_variant(arg
));
1608 if(V_VT(arg
) == VT_BSTR
) {
1611 hres
= to_string(arg
, &conv_str
);
1617 for(ptr
= str
+SysStringLen(str
); ptr
-1 > str
&& iswspace(*(ptr
-1)); ptr
--);
1619 str
= SysAllocStringLen(str
, ptr
-str
);
1620 SysFreeString(conv_str
);
1622 return E_OUTOFMEMORY
;
1624 return return_bstr(res
, str
);
1627 static HRESULT
Global_Trim(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1629 BSTR str
, conv_str
= NULL
;
1630 WCHAR
*begin_ptr
, *end_ptr
;
1633 TRACE("%s\n", debugstr_variant(arg
));
1635 if(V_VT(arg
) == VT_BSTR
) {
1638 hres
= to_string(arg
, &conv_str
);
1644 for(begin_ptr
= str
; *begin_ptr
&& iswspace(*begin_ptr
); begin_ptr
++);
1645 for(end_ptr
= str
+SysStringLen(str
); end_ptr
-1 > begin_ptr
&& iswspace(*(end_ptr
-1)); end_ptr
--);
1647 str
= SysAllocStringLen(begin_ptr
, end_ptr
-begin_ptr
);
1648 SysFreeString(conv_str
);
1650 return E_OUTOFMEMORY
;
1652 return return_bstr(res
, str
);
1655 static HRESULT
Global_Space(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1661 TRACE("%s\n", debugstr_variant(arg
));
1663 assert(args_cnt
== 1);
1665 if(V_VT(arg
) == VT_NULL
)
1666 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
1668 hres
= to_int(arg
, &n
);
1673 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1678 str
= SysAllocStringLen(NULL
, n
);
1680 return E_OUTOFMEMORY
;
1685 V_VT(res
) = VT_BSTR
;
1690 static HRESULT
Global_String(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
1696 TRACE("%s %s\n", debugstr_variant(args
), debugstr_variant(args
+ 1));
1698 hres
= to_int(args
, &cnt
);
1702 return E_INVALIDARG
;
1704 if(V_VT(args
+ 1) != VT_BSTR
) {
1705 FIXME("Unsupported argument %s\n", debugstr_variant(args
+1));
1708 if(!SysStringLen(V_BSTR(args
+ 1)))
1709 return E_INVALIDARG
;
1710 ch
= V_BSTR(args
+ 1)[0];
1713 BSTR str
= SysAllocStringLen(NULL
, cnt
);
1715 return E_OUTOFMEMORY
;
1716 wmemset(str
, ch
, cnt
);
1717 V_VT(res
) = VT_BSTR
;
1723 static HRESULT
Global_InStr(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
1725 VARIANT
*startv
, *str1v
, *str2v
;
1727 int ret
= -1, start
= 0, mode
= 0;
1730 TRACE("args_cnt=%u\n", args_cnt
);
1732 assert(2 <= args_cnt
&& args_cnt
<= 4);
1750 if(V_VT(args
+3) == VT_NULL
)
1751 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
1753 hres
= to_int(args
+3, &mode
);
1757 if (mode
!= 0 && mode
!= 1)
1758 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1761 DEFAULT_UNREACHABLE
;
1765 if(V_VT(startv
) == VT_NULL
)
1766 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
1768 hres
= to_int(startv
, &start
);
1772 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1775 if(V_VT(str1v
) == VT_NULL
|| V_VT(str2v
) == VT_NULL
)
1776 return return_null(res
);
1778 if(V_VT(str1v
) != VT_BSTR
) {
1779 hres
= to_string(str1v
, &str1
);
1784 str1
= V_BSTR(str1v
);
1786 if(V_VT(str2v
) != VT_BSTR
) {
1787 hres
= to_string(str2v
, &str2
);
1789 if(V_VT(str1v
) != VT_BSTR
)
1790 SysFreeString(str1
);
1795 str2
= V_BSTR(str2v
);
1797 if(start
< SysStringLen(str1
)) {
1798 ret
= FindStringOrdinal(FIND_FROMSTART
, str1
+ start
, SysStringLen(str1
)-start
,
1799 str2
, SysStringLen(str2
), mode
);
1802 if(V_VT(str1v
) != VT_BSTR
)
1803 SysFreeString(str1
);
1804 if(V_VT(str2v
) != VT_BSTR
)
1805 SysFreeString(str2
);
1806 return return_int(res
, ++ret
? ret
+start
: 0);
1809 static HRESULT
Global_InStrB(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1815 static HRESULT
Global_AscB(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1821 static HRESULT
Global_ChrB(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1827 static HRESULT
Global_Asc(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1829 BSTR conv_str
= NULL
, str
;
1830 HRESULT hres
= S_OK
;
1832 TRACE("(%s)\n", debugstr_variant(arg
));
1836 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
1838 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1843 hres
= to_string(arg
, &conv_str
);
1849 if(!SysStringLen(str
))
1850 hres
= MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1851 else if (This
->ctx
->codepage
== CP_UTF8
)
1852 hres
= return_short(res
, *str
);
1854 unsigned char buf
[2];
1856 int n
= WideCharToMultiByte(This
->ctx
->codepage
, 0, str
, 1, (char*)buf
, sizeof(buf
), NULL
, NULL
);
1862 val
= (buf
[0] << 8) | buf
[1];
1865 WARN("Failed to convert %x\n", *str
);
1866 hres
= MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1869 hres
= return_short(res
, val
);
1872 SysFreeString(conv_str
);
1876 static HRESULT
Global_Chr(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1884 TRACE("%s\n", debugstr_variant(arg
));
1886 hres
= to_int(arg
, &c
);
1890 cp
= This
->ctx
->codepage
;
1891 if(!GetCPInfo(cp
, &cpi
))
1892 cpi
.MaxCharSize
= 1;
1894 if((c
!=(short)c
&& c
!=(unsigned short)c
) ||
1895 (unsigned short)c
>=(cpi
.MaxCharSize
>1 ? 0x10000 : 0x100)) {
1896 WARN("invalid arg %d\n", c
);
1897 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
1908 if(!len
|| IsDBCSLeadByteEx(cp
, buf
[0]))
1910 if(!MultiByteToWideChar(cp
, 0, buf
, len
, &ch
, 1)) {
1911 WARN("invalid arg %d, cp %d\n", c
, cp
);
1917 V_VT(res
) = VT_BSTR
;
1918 V_BSTR(res
) = SysAllocStringLen(&ch
, 1);
1920 return E_OUTOFMEMORY
;
1925 static HRESULT
Global_AscW(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1931 static HRESULT
Global_ChrW(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1937 static HRESULT
Global_Abs(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1942 TRACE("(%s)\n", debugstr_variant(arg
));
1944 assert(args_cnt
== 1);
1946 hres
= VarAbs(arg
, &dst
);
1958 static HRESULT
Global_Fix(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1963 TRACE("(%s)\n", debugstr_variant(arg
));
1965 assert(args_cnt
== 1);
1967 hres
= VarFix(arg
, &dst
);
1979 static HRESULT
Global_Int(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
1984 TRACE("(%s)\n", debugstr_variant(arg
));
1986 assert(args_cnt
== 1);
1988 hres
= VarInt(arg
, &dst
);
2000 static HRESULT
Global_Sgn(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2006 TRACE("(%s)\n", debugstr_variant(arg
));
2008 assert(args_cnt
== 1);
2010 if(V_VT(arg
) == VT_NULL
)
2011 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2013 hres
= to_double(arg
, &v
);
2017 val
= v
== 0 ? 0 : (v
> 0 ? 1 : -1);
2018 return return_short(res
, val
);
2021 static HRESULT
Global_Now(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2029 SystemTimeToVariantTime(<
, &date
);
2030 return return_date(res
, date
);
2033 static HRESULT
Global_Date(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2045 hres
= VarDateFromUdateEx(&ud
, 0, VAR_DATEVALUEONLY
, &date
);
2048 return return_date(res
, date
);
2051 static HRESULT
Global_Time(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2063 hres
= VarDateFromUdateEx(&ud
, 0, VAR_TIMEVALUEONLY
, &time
);
2066 return return_date(res
, time
);
2069 static HRESULT
Global_Day(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2074 TRACE("(%s)\n", debugstr_variant(arg
));
2076 hres
= to_system_time(arg
, &st
);
2077 return FAILED(hres
) ? hres
: return_short(res
, st
.wDay
);
2080 static HRESULT
Global_Month(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2085 TRACE("(%s)\n", debugstr_variant(arg
));
2087 hres
= to_system_time(arg
, &st
);
2088 return FAILED(hres
) ? hres
: return_short(res
, st
.wMonth
);
2091 static HRESULT
Global_Weekday(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2093 HRESULT hres
= S_OK
;
2097 TRACE("(%s)\n", debugstr_variant(args
));
2099 assert(args_cnt
== 1 || args_cnt
== 2);
2101 /* [vbSunday = 1, vbSaturday = 7] -> wDayOfWeek [0, 6] */
2104 if (V_VT(args
+ 1) == VT_NULL
)
2105 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2107 hres
= to_int(args
+ 1, &first_day
);
2108 if (SUCCEEDED(hres
))
2112 /* vbUseSystemDayOfWeek */
2113 GetLocaleInfoW(This
->ctx
->lcid
, LOCALE_RETURN_NUMBER
| LOCALE_IFIRSTDAYOFWEEK
, (LPWSTR
)&first_day
,
2114 sizeof(first_day
) / sizeof(WCHAR
));
2115 first_day
= (first_day
+ 1) % 7;
2117 else if (first_day
>= 1 && first_day
<= 7)
2122 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
2129 if (V_VT(args
) == VT_NULL
)
2130 return return_null(res
);
2132 if (FAILED(hres
= to_system_time(args
, &st
))) return hres
;
2134 return return_short(res
, 1 + (7 - first_day
+ st
.wDayOfWeek
) % 7);
2137 static HRESULT
Global_Year(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2142 TRACE("(%s)\n", debugstr_variant(arg
));
2144 hres
= to_system_time(arg
, &st
);
2145 return FAILED(hres
) ? hres
: return_short(res
, st
.wYear
);
2148 static HRESULT
Global_Hour(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2153 TRACE("(%s)\n", debugstr_variant(arg
));
2155 hres
= to_system_time(arg
, &st
);
2156 return FAILED(hres
) ? hres
: return_short(res
, st
.wHour
);
2159 static HRESULT
Global_Minute(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2164 TRACE("(%s)\n", debugstr_variant(arg
));
2166 hres
= to_system_time(arg
, &st
);
2167 return FAILED(hres
) ? hres
: return_short(res
, st
.wMinute
);
2170 static HRESULT
Global_Second(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2175 TRACE("(%s)\n", debugstr_variant(arg
));
2177 hres
= to_system_time(arg
, &st
);
2178 return FAILED(hres
) ? hres
: return_short(res
, st
.wSecond
);
2181 static HRESULT
Global_SetLocale(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2187 static HRESULT
Global_DateValue(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2193 static HRESULT
Global_TimeValue(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2199 static HRESULT
Global_DateSerial(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2201 int year
, month
, day
;
2208 assert(args_cnt
== 3);
2210 if (V_VT(args
) == VT_NULL
|| V_VT(args
+ 1) == VT_NULL
|| V_VT(args
+ 2) == VT_NULL
)
2211 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2213 hres
= to_int(args
, &year
);
2214 if (SUCCEEDED(hres
))
2215 hres
= to_int(args
+ 1, &month
);
2216 if (SUCCEEDED(hres
))
2217 hres
= to_int(args
+ 2, &day
);
2219 if (SUCCEEDED(hres
))
2222 ud
.st
.wMonth
= month
;
2224 hres
= VarDateFromUdateEx(&ud
, 0, 0, &date
);
2227 if (SUCCEEDED(hres
))
2228 hres
= return_date(res
, date
);
2233 static HRESULT
Global_TimeSerial(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2235 int hour
, minute
, second
;
2242 assert(args_cnt
== 3);
2244 if (V_VT(args
) == VT_NULL
|| V_VT(args
+ 1) == VT_NULL
|| V_VT(args
+ 2) == VT_NULL
)
2245 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2247 hres
= to_int(args
, &hour
);
2248 if (SUCCEEDED(hres
))
2249 hres
= to_int(args
+ 1, &minute
);
2250 if (SUCCEEDED(hres
))
2251 hres
= to_int(args
+ 2, &second
);
2253 if (SUCCEEDED(hres
))
2259 ud
.st
.wMinute
= minute
;
2260 ud
.st
.wSecond
= second
;
2261 hres
= VarDateFromUdateEx(&ud
, 0, 0, &date
);
2264 if (SUCCEEDED(hres
))
2265 hres
= return_date(res
, date
);
2270 static HRESULT
Global_InputBox(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2276 static HRESULT
Global_MsgBox(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2278 BSTR prompt
, title
= NULL
;
2284 assert(1 <= args_cnt
&& args_cnt
<= 5);
2286 hres
= to_string(args
, &prompt
);
2291 hres
= to_int(args
+1, &type
);
2293 if(SUCCEEDED(hres
) && args_cnt
> 2)
2294 hres
= to_string(args
+2, &title
);
2296 if(SUCCEEDED(hres
) && args_cnt
> 3) {
2297 FIXME("unsupported arg_cnt %d\n", args_cnt
);
2302 hres
= show_msgbox(This
->ctx
, prompt
, type
, title
, res
);
2304 SysFreeString(prompt
);
2305 SysFreeString(title
);
2309 static HRESULT
Global_CreateObject(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2314 TRACE("(%s)\n", debugstr_variant(arg
));
2316 if(V_VT(arg
) != VT_BSTR
) {
2317 FIXME("non-bstr arg\n");
2318 return E_INVALIDARG
;
2321 obj
= create_object(This
->ctx
, V_BSTR(arg
));
2323 return VB_E_CANNOT_CREATE_OBJ
;
2326 hres
= IUnknown_QueryInterface(obj
, &IID_IDispatch
, (void**)&V_DISPATCH(res
));
2330 V_VT(res
) = VT_DISPATCH
;
2333 IUnknown_Release(obj
);
2337 static HRESULT
Global_GetObject(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2346 TRACE("%s %s\n", args_cnt
? debugstr_variant(args
) : "", args_cnt
> 1 ? debugstr_variant(args
+1) : "");
2348 if(args_cnt
!= 1 || V_VT(args
) != VT_BSTR
) {
2349 FIXME("unsupported args\n");
2353 if(This
->ctx
->safeopt
& (INTERFACE_USES_SECURITY_MANAGER
|INTERFACESAFE_FOR_UNTRUSTED_DATA
)) {
2354 WARN("blocked in current safety mode\n");
2355 return VB_E_CANNOT_CREATE_OBJ
;
2358 hres
= CreateBindCtx(0, &bind_ctx
);
2362 hres
= MkParseDisplayName(bind_ctx
, V_BSTR(args
), &eaten
, &mon
);
2363 if(SUCCEEDED(hres
)) {
2364 hres
= IMoniker_BindToObject(mon
, bind_ctx
, NULL
, &IID_IUnknown
, (void**)&obj_unk
);
2365 IMoniker_Release(mon
);
2369 IBindCtx_Release(bind_ctx
);
2373 hres
= set_object_site(This
->ctx
, obj_unk
);
2375 IUnknown_Release(obj_unk
);
2379 hres
= IUnknown_QueryInterface(obj_unk
, &IID_IDispatch
, (void**)&disp
);
2380 if(SUCCEEDED(hres
)) {
2382 V_VT(res
) = VT_DISPATCH
;
2383 V_DISPATCH(res
) = disp
;
2385 IDispatch_Release(disp
);
2388 FIXME("object does not support IDispatch\n");
2394 static HRESULT
Global_DateAdd(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2396 BSTR interval
= NULL
;
2404 assert(args_cnt
== 3);
2406 if (V_VT(args
) == VT_NULL
|| V_VT(args
+ 1) == VT_NULL
)
2407 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2409 if (V_VT(args
+ 2) == VT_NULL
)
2410 return return_null(res
);
2412 hres
= to_string(args
, &interval
);
2413 if (SUCCEEDED(hres
))
2414 hres
= to_int(args
+ 1, &count
);
2415 if (SUCCEEDED(hres
))
2416 hres
= to_system_time(args
+ 2, &ud
.st
);
2417 if (SUCCEEDED(hres
))
2419 if (!wcsicmp(interval
, L
"yyyy"))
2420 ud
.st
.wYear
+= count
;
2421 else if (!wcsicmp(interval
, L
"q"))
2422 ud
.st
.wMonth
+= 3 * count
;
2423 else if (!wcsicmp(interval
, L
"m"))
2424 ud
.st
.wMonth
+= count
;
2425 else if (!wcsicmp(interval
, L
"y")
2426 || !wcsicmp(interval
, L
"d")
2427 || !wcsicmp(interval
, L
"w"))
2429 ud
.st
.wDay
+= count
;
2431 else if (!wcsicmp(interval
, L
"ww"))
2432 ud
.st
.wDay
+= 7 * count
;
2433 else if (!wcsicmp(interval
, L
"h"))
2434 ud
.st
.wHour
+= count
;
2435 else if (!wcsicmp(interval
, L
"n"))
2436 ud
.st
.wMinute
+= count
;
2437 else if (!wcsicmp(interval
, L
"s"))
2438 ud
.st
.wSecond
+= count
;
2441 WARN("Unrecognized interval %s.\n", debugstr_w(interval
));
2442 hres
= MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
2446 SysFreeString(interval
);
2448 if (SUCCEEDED(hres
))
2449 hres
= VarDateFromUdateEx(&ud
, 0, 0, &date
);
2451 if (SUCCEEDED(hres
))
2452 hres
= return_date(res
, date
);
2457 static HRESULT
Global_DateDiff(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2463 static HRESULT
Global_DatePart(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2469 static HRESULT
Global_TypeName(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2471 ITypeInfo
*typeinfo
;
2475 TRACE("(%s)\n", debugstr_variant(arg
));
2477 assert(args_cnt
== 1);
2480 return return_string(res
, L
"Variant()");
2484 return return_string(res
, L
"Byte");
2486 return return_string(res
, L
"Integer");
2488 return return_string(res
, L
"Long");
2490 return return_string(res
, L
"Single");
2492 return return_string(res
, L
"Double");
2494 return return_string(res
, L
"Currency");
2496 return return_string(res
, L
"Decimal");
2498 return return_string(res
, L
"Date");
2500 return return_string(res
, L
"String");
2502 return return_string(res
, L
"Boolean");
2504 return return_string(res
, L
"Empty");
2506 return return_string(res
, L
"Null");
2508 if (!V_DISPATCH(arg
))
2509 return return_string(res
, L
"Nothing");
2510 if (SUCCEEDED(IDispatch_GetTypeInfo(V_DISPATCH(arg
), 0, GetUserDefaultLCID(), &typeinfo
)))
2512 hres
= ITypeInfo_GetDocumentation(typeinfo
, MEMBERID_NIL
, &name
, NULL
, NULL
, NULL
);
2513 ITypeInfo_Release(typeinfo
);
2515 if (SUCCEEDED(hres
) && name
&& *name
)
2516 return return_bstr(res
, name
);
2518 SysFreeString(name
);
2520 return return_string(res
, L
"Object");
2522 FIXME("arg %s not supported\n", debugstr_variant(arg
));
2527 static HRESULT
Global_Array(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2529 SAFEARRAYBOUND bounds
;
2535 TRACE("arg_cnt=%u\n", args_cnt
);
2538 bounds
.cElements
= args_cnt
;
2539 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bounds
);
2541 return E_OUTOFMEMORY
;
2543 hres
= SafeArrayAccessData(sa
, (void**)&data
);
2545 SafeArrayDestroy(sa
);
2549 for(i
=0; i
<args_cnt
; i
++) {
2550 hres
= VariantCopyInd(data
+i
, arg
+i
);
2552 SafeArrayUnaccessData(sa
);
2553 SafeArrayDestroy(sa
);
2557 SafeArrayUnaccessData(sa
);
2560 V_VT(res
) = VT_ARRAY
|VT_VARIANT
;
2563 SafeArrayDestroy(sa
);
2569 static HRESULT
Global_Erase(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2575 static HRESULT
Global_Filter(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2581 static HRESULT
Global_Join(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2587 static HRESULT
Global_Split(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2589 BSTR string
, delimiter
= NULL
;
2590 int count
, max
, mode
, len
, start
, end
, ret
, delimiterlen
= 1;
2591 int i
, *indices
= NULL
, *new_indices
, indices_max
= 8;
2592 SAFEARRAYBOUND bounds
;
2593 SAFEARRAY
*sa
= NULL
;
2595 HRESULT hres
= S_OK
;
2597 TRACE("%s %u...\n", debugstr_variant(args
), args_cnt
);
2599 assert(1 <= args_cnt
&& args_cnt
<= 4);
2601 if(V_VT(args
) == VT_NULL
|| (args_cnt
> 1 && V_VT(args
+1) == VT_NULL
) || (args_cnt
> 2 && V_VT(args
+2) == VT_NULL
)
2602 || (args_cnt
== 4 && V_VT(args
+3) == VT_NULL
))
2603 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2605 if(V_VT(args
) != VT_BSTR
) {
2606 hres
= to_string(args
, &string
);
2610 string
= V_BSTR(args
);
2614 if(V_VT(args
+1) != VT_BSTR
) {
2615 hres
= to_string(args
+1, &delimiter
);
2619 delimiter
= V_BSTR(args
+1);
2621 delimiterlen
= SysStringLen(delimiter
);
2625 hres
= to_int(args
+2, &max
);
2629 hres
= MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
2637 hres
= to_int(args
+3, &mode
);
2640 if (mode
!= 0 && mode
!= 1) {
2641 hres
= MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
2650 len
= SysStringLen(string
);
2653 indices
= malloc( indices_max
* sizeof(int));
2655 hres
= E_OUTOFMEMORY
;
2662 ret
= FindStringOrdinal(FIND_FROMSTART
, string
+ start
, len
- start
,
2663 delimiter
? delimiter
: L
" ", delimiterlen
, mode
);
2672 if (count
== indices_max
) {
2673 new_indices
= realloc(indices
, indices_max
* 2 * sizeof(int));
2675 hres
= E_OUTOFMEMORY
;
2678 indices
= new_indices
;
2681 indices
[count
++] = end
;
2683 if (ret
== -1 || count
== max
) break;
2684 start
= start
+ ret
+ delimiterlen
;
2685 if (start
> len
) break;
2689 bounds
.cElements
= count
;
2690 sa
= SafeArrayCreate( VT_VARIANT
, 1, &bounds
);
2692 hres
= E_OUTOFMEMORY
;
2695 hres
= SafeArrayAccessData(sa
, (void**)&data
);
2701 for (i
= 0; i
< count
; i
++) {
2702 V_VT(&data
[i
]) = VT_BSTR
;
2703 V_BSTR(&data
[i
]) = SysAllocStringLen(string
+ start
, indices
[i
] - start
);
2705 if (!V_BSTR(&data
[i
])) {
2706 hres
= E_OUTOFMEMORY
;
2709 start
= indices
[i
]+delimiterlen
;
2711 SafeArrayUnaccessData(sa
);
2714 if(SUCCEEDED(hres
) && res
) {
2715 V_VT(res
) = VT_ARRAY
|VT_VARIANT
;
2718 SafeArrayDestroy(sa
);
2722 if(V_VT(args
) != VT_BSTR
)
2723 SysFreeString(string
);
2724 if(args_cnt
> 1 && V_VT(args
+1) != VT_BSTR
)
2725 SysFreeString(delimiter
);
2729 static HRESULT
Global_Replace(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2731 BSTR string
, find
= NULL
, replace
= NULL
, ret
;
2732 int from
= 1, cnt
= -1, mode
= 0;
2733 HRESULT hres
= S_OK
;
2735 TRACE("%s %s %s %u...\n", debugstr_variant(args
), debugstr_variant(args
+1), debugstr_variant(args
+2), args_cnt
);
2737 assert(3 <= args_cnt
&& args_cnt
<= 6);
2739 if(V_VT(args
) == VT_NULL
|| V_VT(args
+1) == VT_NULL
|| (V_VT(args
+2) == VT_NULL
)
2740 || (args_cnt
>= 4 && V_VT(args
+3) == VT_NULL
) || (args_cnt
>= 5 && V_VT(args
+4) == VT_NULL
)
2741 || (args_cnt
== 6 && V_VT(args
+5) == VT_NULL
))
2742 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2745 if(V_VT(args
) != VT_BSTR
) {
2746 hres
= to_string(args
, &string
);
2750 string
= V_BSTR(args
);
2753 if(V_VT(args
+1) != VT_BSTR
) {
2754 hres
= to_string(args
+1, &find
);
2758 find
= V_BSTR(args
+1);
2761 if(V_VT(args
+2) != VT_BSTR
) {
2762 hres
= to_string(args
+2, &replace
);
2766 replace
= V_BSTR(args
+2);
2770 hres
= to_int(args
+3, &from
);
2774 hres
= E_INVALIDARG
;
2780 hres
= to_int(args
+4, &cnt
);
2784 hres
= E_INVALIDARG
;
2790 hres
= to_int(args
+5, &mode
);
2793 if (mode
!= 0 && mode
!= 1) {
2794 hres
= MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
2799 ret
= string_replace(string
, find
, replace
, from
- 1, cnt
, mode
);
2801 hres
= E_OUTOFMEMORY
;
2803 V_VT(res
) = VT_BSTR
;
2810 if(V_VT(args
) != VT_BSTR
)
2811 SysFreeString(string
);
2812 if(V_VT(args
+1) != VT_BSTR
)
2813 SysFreeString(find
);
2814 if(V_VT(args
+2) != VT_BSTR
)
2815 SysFreeString(replace
);
2819 static HRESULT
Global_StrReverse(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2821 WCHAR
*ptr1
, *ptr2
, ch
;
2825 TRACE("%s\n", debugstr_variant(arg
));
2827 hres
= to_string(arg
, &ret
);
2832 ptr2
= ret
+ SysStringLen(ret
)-1;
2833 while(ptr1
< ptr2
) {
2839 return return_bstr(res
, ret
);
2842 static HRESULT
Global_InStrRev(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2844 int start
= -1, ret
= -1, mode
= 0;
2849 TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args
), debugstr_variant(args
+1), args_cnt
);
2851 assert(2 <= args_cnt
&& args_cnt
<= 4);
2853 if(V_VT(args
) == VT_NULL
|| V_VT(args
+1) == VT_NULL
|| (args_cnt
> 2 && V_VT(args
+2) == VT_NULL
)
2854 || (args_cnt
== 4 && V_VT(args
+3) == VT_NULL
))
2855 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2858 hres
= to_int(args
+3, &mode
);
2861 if (mode
!= 0 && mode
!= 1)
2862 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
2866 hres
= to_int(args
+2, &start
);
2869 if(!start
|| start
< -1)
2870 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL
);
2873 if(V_VT(args
) != VT_BSTR
) {
2874 hres
= to_string(args
, &str1
);
2879 str1
= V_BSTR(args
);
2881 if(V_VT(args
+1) != VT_BSTR
) {
2882 hres
= to_string(args
+1, &str2
);
2884 if(V_VT(args
) != VT_BSTR
)
2885 SysFreeString(str1
);
2890 str2
= V_BSTR(args
+1);
2892 len1
= SysStringLen(str1
);
2901 len2
= SysStringLen(str2
);
2907 if(start
>= len2
&& start
<= len1
) {
2908 ret
= FindStringOrdinal(FIND_FROMEND
, str1
, start
,
2914 if(V_VT(args
) != VT_BSTR
)
2915 SysFreeString(str1
);
2916 if(V_VT(args
+1) != VT_BSTR
)
2917 SysFreeString(str2
);
2918 return return_int(res
, ret
);
2921 static HRESULT
Global_LoadPicture(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2927 static HRESULT
Global_ScriptEngine(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2929 TRACE("%s\n", debugstr_variant(arg
));
2931 assert(args_cnt
== 0);
2933 return return_string(res
, L
"VBScript");
2936 static HRESULT
Global_ScriptEngineMajorVersion(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2938 TRACE("%s\n", debugstr_variant(arg
));
2940 assert(args_cnt
== 0);
2942 return return_int(res
, VBSCRIPT_MAJOR_VERSION
);
2945 static HRESULT
Global_ScriptEngineMinorVersion(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2947 TRACE("%s\n", debugstr_variant(arg
));
2949 assert(args_cnt
== 0);
2951 return return_int(res
, VBSCRIPT_MINOR_VERSION
);
2954 static HRESULT
Global_ScriptEngineBuildVersion(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
2956 TRACE("%s\n", debugstr_variant(arg
));
2958 assert(args_cnt
== 0);
2960 return return_int(res
, VBSCRIPT_BUILD_VERSION
);
2963 static HRESULT
Global_FormatNumber(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
2969 int num_dig
, inc_lead
, use_parens
, group
;
2972 } int_args
= { .s
.num_dig
= -1, .s
.inc_lead
= -2, .s
.use_parens
= -2, .s
.group
= -2 };
2979 assert(1 <= args_cnt
&& args_cnt
<= 5);
2981 for (i
= 1; i
< args_cnt
; ++i
)
2983 if (V_VT(args
+i
) == VT_ERROR
) continue;
2984 if (V_VT(args
+i
) == VT_NULL
) return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
2985 if (FAILED(hres
= to_int(args
+i
, &int_args
.val
[i
-1]))) return hres
;
2988 hres
= VarFormatNumber(args
, int_args
.s
.num_dig
, int_args
.s
.inc_lead
, int_args
.s
.use_parens
,
2989 int_args
.s
.group
, 0, &str
);
2990 if (FAILED(hres
)) return hres
;
2992 return return_bstr(res
, str
);
2995 static HRESULT
Global_FormatCurrency(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3001 int num_dig
, inc_lead
, use_parens
, group
;
3004 } int_args
= { .s
.num_dig
= -1, .s
.inc_lead
= -2, .s
.use_parens
= -2, .s
.group
= -2 };
3011 assert(1 <= args_cnt
&& args_cnt
<= 5);
3013 for (i
= 1; i
< args_cnt
; ++i
)
3015 if (V_VT(args
+i
) == VT_ERROR
) continue;
3016 if (V_VT(args
+i
) == VT_NULL
) return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
3017 if (FAILED(hres
= to_int(args
+i
, &int_args
.val
[i
-1]))) return hres
;
3020 hres
= VarFormatCurrency(args
, int_args
.s
.num_dig
, int_args
.s
.inc_lead
, int_args
.s
.use_parens
,
3021 int_args
.s
.group
, 0, &str
);
3022 if (FAILED(hres
)) return hres
;
3024 return return_bstr(res
, str
);
3027 static HRESULT
Global_FormatPercent(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3033 int num_dig
, inc_lead
, use_parens
, group
;
3036 } int_args
= { .s
.num_dig
= -1, .s
.inc_lead
= -2, .s
.use_parens
= -2, .s
.group
= -2 };
3043 assert(1 <= args_cnt
&& args_cnt
<= 5);
3045 for (i
= 1; i
< args_cnt
; ++i
)
3047 if (V_VT(args
+i
) == VT_ERROR
) continue;
3048 if (V_VT(args
+i
) == VT_NULL
) return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
3049 if (FAILED(hres
= to_int(args
+i
, &int_args
.val
[i
-1]))) return hres
;
3052 hres
= VarFormatPercent(args
, int_args
.s
.num_dig
, int_args
.s
.inc_lead
, int_args
.s
.use_parens
,
3053 int_args
.s
.group
, 0, &str
);
3054 if (FAILED(hres
)) return hres
;
3056 return return_bstr(res
, str
);
3059 static HRESULT
Global_GetLocale(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3065 static HRESULT
Global_FormatDateTime(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3073 assert(1 <= args_cnt
&& args_cnt
<= 2);
3075 if (V_VT(args
) == VT_NULL
)
3076 return MAKE_VBSERROR(VBSE_TYPE_MISMATCH
);
3080 if (V_VT(args
+1) == VT_NULL
) return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
3081 if (V_VT(args
+1) != VT_ERROR
)
3083 if (FAILED(hres
= to_int(args
+1, &format
))) return hres
;
3087 hres
= VarFormatDateTime(args
, format
, 0, &str
);
3088 if (FAILED(hres
)) return hres
;
3090 return return_bstr(res
, str
);
3093 static HRESULT
Global_WeekdayName(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3095 int weekday
, first_day
= 1, abbrev
= 0;
3101 assert(1 <= args_cnt
&& args_cnt
<= 3);
3103 hres
= to_int(args
, &weekday
);
3108 hres
= to_int(args
+1, &abbrev
);
3113 hres
= to_int(args
+2, &first_day
);
3119 hres
= VarWeekdayName(weekday
, abbrev
, first_day
, 0, &ret
);
3123 return return_bstr(res
, ret
);
3126 static HRESULT
Global_MonthName(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3128 int month
, abbrev
= 0;
3134 assert(args_cnt
== 1 || args_cnt
== 2);
3136 if(V_VT(args
) == VT_NULL
|| (args_cnt
== 2 && V_VT(args
+1) == VT_NULL
))
3137 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE
);
3139 hres
= to_int(args
, &month
);
3144 hres
= to_int(args
+1, &abbrev
);
3149 hres
= VarMonthName(month
, abbrev
, 0, &ret
);
3153 return return_bstr(res
, ret
);
3156 static HRESULT
Global_Round(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3158 int decimal_places
= 0;
3162 TRACE("%s %s\n", debugstr_variant(args
), args_cnt
== 2 ? debugstr_variant(args
+ 1) : "0");
3164 assert(args_cnt
== 1 || args_cnt
== 2);
3170 if (V_VT(args
+ 1) != VT_ERROR
) {
3171 hres
= to_int(args
+ 1, &decimal_places
);
3177 switch(V_VT(args
)) {
3187 hres
= to_double(args
, &d
);
3192 hres
= VarR8Round(d
, decimal_places
, &d
);
3196 return return_double(res
, d
);
3199 static HRESULT
Global_Escape(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
3205 static HRESULT
Global_Unescape(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
3211 static HRESULT
Global_Eval(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
3217 static HRESULT
Global_Execute(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
3223 static HRESULT
Global_ExecuteGlobal(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
3229 static HRESULT
Global_GetRef(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
3235 static HRESULT
Global_Err(BuiltinDisp
*This
, VARIANT
*arg
, unsigned args_cnt
, VARIANT
*res
)
3240 FIXME("Setter not supported\n");
3244 V_VT(res
) = VT_DISPATCH
;
3245 V_DISPATCH(res
) = &This
->ctx
->err_obj
->IDispatch_iface
;
3246 IDispatch_AddRef(V_DISPATCH(res
));
3250 static const string_constant_t vbCr
= {1, {'\r'}};
3251 static const string_constant_t vbCrLf
= {2, {'\r','\n'}};
3252 static const string_constant_t vbNewLine
= {2, {'\r','\n'}};
3253 static const string_constant_t vbFormFeed
= {1, {0xc}};
3254 static const string_constant_t vbLf
= {1, {'\n'}};
3255 static const string_constant_t vbNullChar
= {1};
3256 static const string_constant_t vbNullString
= {0};
3257 static const string_constant_t vbTab
= {1, {'\t'}};
3258 static const string_constant_t vbVerticalTab
= {1, {0xb}};
3260 static const builtin_prop_t global_props
[] = {
3261 {NULL
}, /* no default value */
3262 {L
"Abs", Global_Abs
, 0, 1},
3263 {L
"Array", Global_Array
, 0, 0, MAXDWORD
},
3264 {L
"Asc", Global_Asc
, 0, 1},
3265 {L
"AscB", Global_AscB
, 0, 1},
3266 {L
"AscW", Global_AscW
, 0, 1},
3267 {L
"Atn", Global_Atn
, 0, 1},
3268 {L
"CBool", Global_CBool
, 0, 1},
3269 {L
"CByte", Global_CByte
, 0, 1},
3270 {L
"CCur", Global_CCur
, 0, 1},
3271 {L
"CDate", Global_CDate
, 0, 1},
3272 {L
"CDbl", Global_CDbl
, 0, 1},
3273 {L
"Chr", Global_Chr
, 0, 1},
3274 {L
"ChrB", Global_ChrB
, 0, 1},
3275 {L
"ChrW", Global_ChrW
, 0, 1},
3276 {L
"CInt", Global_CInt
, 0, 1},
3277 {L
"CLng", Global_CLng
, 0, 1},
3278 {L
"Cos", Global_Cos
, 0, 1},
3279 {L
"CreateObject", Global_CreateObject
, 0, 1},
3280 {L
"CSng", Global_CSng
, 0, 1},
3281 {L
"CStr", Global_CStr
, 0, 1},
3282 {L
"Date", Global_Date
, 0, 0},
3283 {L
"DateAdd", Global_DateAdd
, 0, 3},
3284 {L
"DateDiff", Global_DateDiff
, 0, 3, 5},
3285 {L
"DatePart", Global_DatePart
, 0, 2, 4},
3286 {L
"DateSerial", Global_DateSerial
, 0, 3},
3287 {L
"DateValue", Global_DateValue
, 0, 1},
3288 {L
"Day", Global_Day
, 0, 1},
3289 {L
"Erase", Global_Erase
, 0, 1},
3290 {L
"Err", Global_Err
, BP_GETPUT
},
3291 {L
"Escape", Global_Escape
, 0, 1},
3292 {L
"Eval", Global_Eval
, 0, 1},
3293 {L
"Execute", Global_Execute
, 0, 1},
3294 {L
"ExecuteGlobal", Global_ExecuteGlobal
, 0, 1},
3295 {L
"Exp", Global_Exp
, 0, 1},
3296 {L
"Filter", Global_Filter
, 0, 2, 4},
3297 {L
"Fix", Global_Fix
, 0, 1},
3298 {L
"FormatCurrency", Global_FormatCurrency
, 0, 1, 5},
3299 {L
"FormatDateTime", Global_FormatDateTime
, 0, 1, 2},
3300 {L
"FormatNumber", Global_FormatNumber
, 0, 1, 5},
3301 {L
"FormatPercent", Global_FormatPercent
, 0, 1, 5},
3302 {L
"GetLocale", Global_GetLocale
, 0, 0},
3303 {L
"GetObject", Global_GetObject
, 0, 0, 2},
3304 {L
"GetRef", Global_GetRef
, 0, 1},
3305 {L
"Hex", Global_Hex
, 0, 1},
3306 {L
"Hour", Global_Hour
, 0, 1},
3307 {L
"InputBox", Global_InputBox
, 0, 1, 7},
3308 {L
"InStr", Global_InStr
, 0, 2, 4},
3309 {L
"InStrB", Global_InStrB
, 0, 3, 4},
3310 {L
"InStrRev", Global_InStrRev
, 0, 2, 4},
3311 {L
"Int", Global_Int
, 0, 1},
3312 {L
"IsArray", Global_IsArray
, 0, 1},
3313 {L
"IsDate", Global_IsDate
, 0, 1},
3314 {L
"IsEmpty", Global_IsEmpty
, 0, 1},
3315 {L
"IsNull", Global_IsNull
, 0, 1},
3316 {L
"IsNumeric", Global_IsNumeric
, 0, 1},
3317 {L
"IsObject", Global_IsObject
, 0, 1},
3318 {L
"Join", Global_Join
, 0, 1, 2},
3319 {L
"LBound", Global_LBound
, 0, 1, 2},
3320 {L
"LCase", Global_LCase
, 0, 1},
3321 {L
"Left", Global_Left
, 0, 2},
3322 {L
"LeftB", Global_LeftB
, 0, 2},
3323 {L
"Len", Global_Len
, 0, 1},
3324 {L
"LenB", Global_LenB
, 0, 1},
3325 {L
"LoadPicture", Global_LoadPicture
, 0, 1},
3326 {L
"Log", Global_Log
, 0, 1},
3327 {L
"LTrim", Global_LTrim
, 0, 1},
3328 {L
"Mid", Global_Mid
, 0, 2, 3},
3329 {L
"MidB", Global_MidB
, 0, 2, 3},
3330 {L
"Minute", Global_Minute
, 0, 1},
3331 {L
"Month", Global_Month
, 0, 1},
3332 {L
"MonthName", Global_MonthName
, 0, 1, 2},
3333 {L
"MsgBox", Global_MsgBox
, 0, 1, 5},
3334 {L
"Now", Global_Now
, 0, 0},
3335 {L
"Oct", Global_Oct
, 0, 1},
3336 {L
"Randomize", Global_Randomize
, 0, 0, 1},
3337 {L
"Replace", Global_Replace
, 0, 3, 6},
3338 {L
"RGB", Global_RGB
, 0, 3},
3339 {L
"Right", Global_Right
, 0, 2},
3340 {L
"RightB", Global_RightB
, 0, 2},
3341 {L
"Rnd", Global_Rnd
, 0, 0, 1},
3342 {L
"Round", Global_Round
, 0, 1, 2},
3343 {L
"RTrim", Global_RTrim
, 0, 1},
3344 {L
"ScriptEngine", Global_ScriptEngine
, 0, 0},
3345 {L
"ScriptEngineBuildVersion", Global_ScriptEngineBuildVersion
, 0, 0},
3346 {L
"ScriptEngineMajorVersion", Global_ScriptEngineMajorVersion
, 0, 0},
3347 {L
"ScriptEngineMinorVersion", Global_ScriptEngineMinorVersion
, 0, 0},
3348 {L
"Second", Global_Second
, 0, 1},
3349 {L
"SetLocale", Global_SetLocale
, 0, 0, 1},
3350 {L
"Sgn", Global_Sgn
, 0, 1},
3351 {L
"Sin", Global_Sin
, 0, 1},
3352 {L
"Space", Global_Space
, 0, 1},
3353 {L
"Split", Global_Split
, 0, 1, 4},
3354 {L
"Sqr", Global_Sqr
, 0, 1},
3355 {L
"StrComp", Global_StrComp
, 0, 2, 3},
3356 {L
"String", Global_String
, 0, 0, 2},
3357 {L
"StrReverse", Global_StrReverse
, 0, 1},
3358 {L
"Tan", Global_Tan
, 0, 1},
3359 {L
"Time", Global_Time
, 0, 0},
3360 {L
"Timer", Global_Timer
, 0, 0},
3361 {L
"TimeSerial", Global_TimeSerial
, 0, 3},
3362 {L
"TimeValue", Global_TimeValue
, 0, 1},
3363 {L
"Trim", Global_Trim
, 0, 1},
3364 {L
"TypeName", Global_TypeName
, 0, 1},
3365 {L
"UBound", Global_UBound
, 0, 1, 2},
3366 {L
"UCase", Global_UCase
, 0, 1},
3367 {L
"Unescape", Global_Unescape
, 0, 1},
3368 {L
"VarType", Global_VarType
, 0, 1},
3369 {L
"vbAbort", NULL
, BP_GET
, VT_I2
, IDABORT
},
3370 {L
"vbAbortRetryIgnore", NULL
, BP_GET
, VT_I2
, MB_ABORTRETRYIGNORE
},
3371 {L
"vbApplicationModal", NULL
, BP_GET
, VT_I2
, MB_APPLMODAL
},
3372 {L
"vbArray", NULL
, BP_GET
, VT_I2
, VT_ARRAY
},
3373 {L
"vbBinaryCompare", NULL
, BP_GET
, VT_I2
, 0},
3374 {L
"vbBlack", NULL
, BP_GET
, VT_I4
, 0x000000},
3375 {L
"vbBlue", NULL
, BP_GET
, VT_I4
, 0xff0000},
3376 {L
"vbBoolean", NULL
, BP_GET
, VT_I2
, VT_BOOL
},
3377 {L
"vbByte", NULL
, BP_GET
, VT_I2
, VT_UI1
},
3378 {L
"vbCancel", NULL
, BP_GET
, VT_I2
, IDCANCEL
},
3379 {L
"vbCr", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbCr
},
3380 {L
"vbCritical", NULL
, BP_GET
, VT_I2
, MB_ICONHAND
},
3381 {L
"vbCrLf", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbCrLf
},
3382 {L
"vbCurrency", NULL
, BP_GET
, VT_I2
, VT_CY
},
3383 {L
"vbCyan", NULL
, BP_GET
, VT_I4
, 0xffff00},
3384 {L
"vbDatabaseCompare", NULL
, BP_GET
, VT_I2
, 2},
3385 {L
"vbDataObject", NULL
, BP_GET
, VT_I2
, VT_UNKNOWN
},
3386 {L
"vbDate", NULL
, BP_GET
, VT_I2
, VT_DATE
},
3387 {L
"vbDecimal", NULL
, BP_GET
, VT_I2
, VT_DECIMAL
},
3388 {L
"vbDefaultButton1", NULL
, BP_GET
, VT_I2
, MB_DEFBUTTON1
},
3389 {L
"vbDefaultButton2", NULL
, BP_GET
, VT_I2
, MB_DEFBUTTON2
},
3390 {L
"vbDefaultButton3", NULL
, BP_GET
, VT_I2
, MB_DEFBUTTON3
},
3391 {L
"vbDefaultButton4", NULL
, BP_GET
, VT_I2
, MB_DEFBUTTON4
},
3392 {L
"vbDouble", NULL
, BP_GET
, VT_I2
, VT_R8
},
3393 {L
"vbEmpty", NULL
, BP_GET
, VT_I2
, VT_EMPTY
},
3394 {L
"vbError", NULL
, BP_GET
, VT_I2
, VT_ERROR
},
3395 {L
"vbExclamation", NULL
, BP_GET
, VT_I2
, MB_ICONEXCLAMATION
},
3396 {L
"vbFalse", NULL
, BP_GET
, VT_I2
, VARIANT_FALSE
},
3397 {L
"vbFirstFourDays", NULL
, BP_GET
, VT_I2
, 2},
3398 {L
"vbFirstFullWeek", NULL
, BP_GET
, VT_I2
, 3},
3399 {L
"vbFirstJan1", NULL
, BP_GET
, VT_I2
, 1},
3400 {L
"vbFormFeed", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbFormFeed
},
3401 {L
"vbFriday", NULL
, BP_GET
, VT_I2
, 6},
3402 {L
"vbGeneralDate", NULL
, BP_GET
, VT_I2
, 0},
3403 {L
"vbGreen", NULL
, BP_GET
, VT_I4
, 0x00ff00},
3404 {L
"vbIgnore", NULL
, BP_GET
, VT_I2
, IDIGNORE
},
3405 {L
"vbInformation", NULL
, BP_GET
, VT_I2
, MB_ICONASTERISK
},
3406 {L
"vbInteger", NULL
, BP_GET
, VT_I2
, VT_I2
},
3407 {L
"vbLf", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbLf
},
3408 {L
"vbLong", NULL
, BP_GET
, VT_I2
, VT_I4
},
3409 {L
"vbLongDate", NULL
, BP_GET
, VT_I2
, 1},
3410 {L
"vbLongTime", NULL
, BP_GET
, VT_I2
, 3},
3411 {L
"vbMagenta", NULL
, BP_GET
, VT_I4
, 0xff00ff},
3412 {L
"vbMonday", NULL
, BP_GET
, VT_I2
, 2},
3413 {L
"vbMsgBoxHelpButton", NULL
, BP_GET
, VT_I4
, MB_HELP
},
3414 {L
"vbMsgBoxRight", NULL
, BP_GET
, VT_I4
, MB_RIGHT
},
3415 {L
"vbMsgBoxRtlReading", NULL
, BP_GET
, VT_I4
, MB_RTLREADING
},
3416 {L
"vbMsgBoxSetForeground", NULL
, BP_GET
, VT_I4
, MB_SETFOREGROUND
},
3417 {L
"vbNewLine", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbNewLine
},
3418 {L
"vbNo", NULL
, BP_GET
, VT_I2
, IDNO
},
3419 {L
"vbNull", NULL
, BP_GET
, VT_I2
, VT_NULL
},
3420 {L
"vbNullChar", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbNullChar
},
3421 {L
"vbNullString", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbNullString
},
3422 {L
"vbObject", NULL
, BP_GET
, VT_I2
, VT_DISPATCH
},
3423 {L
"vbObjectError", NULL
, BP_GET
, VT_I4
, 0x80040000},
3424 {L
"vbOK", NULL
, BP_GET
, VT_I2
, IDOK
},
3425 {L
"vbOKCancel", NULL
, BP_GET
, VT_I2
, MB_OKCANCEL
},
3426 {L
"vbOKOnly", NULL
, BP_GET
, VT_I2
, MB_OK
},
3427 {L
"vbQuestion", NULL
, BP_GET
, VT_I2
, MB_ICONQUESTION
},
3428 {L
"vbRed", NULL
, BP_GET
, VT_I4
, 0x0000ff},
3429 {L
"vbRetry", NULL
, BP_GET
, VT_I2
, IDRETRY
},
3430 {L
"vbRetryCancel", NULL
, BP_GET
, VT_I2
, MB_RETRYCANCEL
},
3431 {L
"vbSaturday", NULL
, BP_GET
, VT_I2
, 7},
3432 {L
"vbShortDate", NULL
, BP_GET
, VT_I2
, 2},
3433 {L
"vbShortTime", NULL
, BP_GET
, VT_I2
, 4},
3434 {L
"vbSingle", NULL
, BP_GET
, VT_I2
, VT_R4
},
3435 {L
"vbString", NULL
, BP_GET
, VT_I2
, VT_BSTR
},
3436 {L
"vbSunday", NULL
, BP_GET
, VT_I2
, 1},
3437 {L
"vbSystemModal", NULL
, BP_GET
, VT_I2
, MB_SYSTEMMODAL
},
3438 {L
"vbTab", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbTab
},
3439 {L
"vbTextCompare", NULL
, BP_GET
, VT_I2
, 1},
3440 {L
"vbThursday", NULL
, BP_GET
, VT_I2
, 5},
3441 {L
"vbTrue", NULL
, BP_GET
, VT_I2
, VARIANT_TRUE
},
3442 {L
"vbTuesday", NULL
, BP_GET
, VT_I2
, 3},
3443 {L
"vbUseDefault", NULL
, BP_GET
, VT_I2
, -2},
3444 {L
"vbUseSystem", NULL
, BP_GET
, VT_I2
, 0},
3445 {L
"vbUseSystemDayOfWeek", NULL
, BP_GET
, VT_I2
, 0},
3446 {L
"vbVariant", NULL
, BP_GET
, VT_I2
, VT_VARIANT
},
3447 {L
"vbVerticalTab", NULL
, BP_GET
, VT_BSTR
, (UINT_PTR
)&vbVerticalTab
},
3448 {L
"vbWednesday", NULL
, BP_GET
, VT_I2
, 4},
3449 {L
"vbWhite", NULL
, BP_GET
, VT_I4
, 0xffffff},
3450 {L
"vbYellow", NULL
, BP_GET
, VT_I4
, 0x00ffff},
3451 {L
"vbYes", NULL
, BP_GET
, VT_I2
, IDYES
},
3452 {L
"vbYesNo", NULL
, BP_GET
, VT_I2
, MB_YESNO
},
3453 {L
"vbYesNoCancel", NULL
, BP_GET
, VT_I2
, MB_YESNOCANCEL
},
3454 {L
"Weekday", Global_Weekday
, 0, 1, 2},
3455 {L
"WeekdayName", Global_WeekdayName
, 0, 1, 3},
3456 {L
"Year", Global_Year
, 0, 1}
3459 static HRESULT
err_string_prop(BSTR
*prop
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3465 return return_string(res
, *prop
? *prop
: L
"");
3467 hres
= to_string(args
, &str
);
3471 SysFreeString(*prop
);
3476 static HRESULT
Err_Description(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3479 return err_string_prop(&This
->ctx
->ei
.bstrDescription
, args
, args_cnt
, res
);
3482 static HRESULT
Err_HelpContext(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3487 FIXME("setter not implemented\n");
3491 return return_int(res
, This
->ctx
->ei
.dwHelpContext
);
3494 static HRESULT
Err_HelpFile(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3497 return err_string_prop(&This
->ctx
->ei
.bstrHelpFile
, args
, args_cnt
, res
);
3500 static HRESULT
Err_Number(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3507 FIXME("setter not implemented\n");
3511 hres
= This
->ctx
->ei
.scode
;
3512 return return_int(res
, HRESULT_FACILITY(hres
) == FACILITY_VBS
? HRESULT_CODE(hres
) : hres
);
3515 static HRESULT
Err_Source(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3518 return err_string_prop(&This
->ctx
->ei
.bstrSource
, args
, args_cnt
, res
);
3521 static HRESULT
Err_Clear(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3525 clear_ei(&This
->ctx
->ei
);
3529 static HRESULT
Err_Raise(BuiltinDisp
*This
, VARIANT
*args
, unsigned args_cnt
, VARIANT
*res
)
3531 BSTR source
= NULL
, description
= NULL
, helpfile
= NULL
;
3532 int code
, helpcontext
= 0;
3535 TRACE("%s %u...\n", debugstr_variant(args
), args_cnt
);
3537 hres
= to_int(args
, &code
);
3540 if(code
== 0 || code
> 0xffff)
3541 return E_INVALIDARG
;
3544 hres
= to_string(args
+ 1, &source
);
3545 if(args_cnt
>= 3 && SUCCEEDED(hres
))
3546 hres
= to_string(args
+ 2, &description
);
3547 if(args_cnt
>= 4 && SUCCEEDED(hres
))
3548 hres
= to_string(args
+ 3, &helpfile
);
3549 if(args_cnt
>= 5 && SUCCEEDED(hres
))
3550 hres
= to_int(args
+ 4, &helpcontext
);
3552 if(SUCCEEDED(hres
)) {
3553 script_ctx_t
*ctx
= This
->ctx
;
3556 SysFreeString(ctx
->ei
.bstrSource
);
3557 ctx
->ei
.bstrSource
= source
;
3560 SysFreeString(ctx
->ei
.bstrDescription
);
3561 ctx
->ei
.bstrDescription
= description
;
3564 SysFreeString(ctx
->ei
.bstrHelpFile
);
3565 ctx
->ei
.bstrHelpFile
= helpfile
;
3568 ctx
->ei
.dwHelpContext
= helpcontext
;
3570 ctx
->ei
.scode
= (code
& ~0xffff) ? code
: MAKE_VBSERROR(code
);
3571 map_vbs_exception(&ctx
->ei
);
3573 hres
= SCRIPT_E_RECORDED
;
3575 SysFreeString(source
);
3576 SysFreeString(description
);
3577 SysFreeString(helpfile
);
3583 static const builtin_prop_t err_props
[] = {
3584 {NULL
, Err_Number
, BP_GETPUT
},
3585 {L
"Clear", Err_Clear
},
3586 {L
"Description", Err_Description
, BP_GETPUT
},
3587 {L
"HelpContext", Err_HelpContext
, BP_GETPUT
},
3588 {L
"HelpFile", Err_HelpFile
, BP_GETPUT
},
3589 {L
"Number", Err_Number
, BP_GETPUT
},
3590 {L
"Raise", Err_Raise
, 0, 1, 5},
3591 {L
"Source", Err_Source
, BP_GETPUT
}
3594 void detach_global_objects(script_ctx_t
*ctx
)
3597 ctx
->err_obj
->ctx
= NULL
;
3598 IDispatch_Release(&ctx
->err_obj
->IDispatch_iface
);
3599 ctx
->err_obj
= NULL
;
3602 if(ctx
->global_obj
) {
3603 ctx
->global_obj
->ctx
= NULL
;
3604 IDispatch_Release(&ctx
->global_obj
->IDispatch_iface
);
3605 ctx
->global_obj
= NULL
;
3609 HRESULT
init_global(script_ctx_t
*ctx
)
3613 hres
= create_builtin_dispatch(ctx
, global_props
, ARRAY_SIZE(global_props
), &ctx
->global_obj
);
3617 return create_builtin_dispatch(ctx
, err_props
, ARRAY_SIZE(err_props
), &ctx
->err_obj
);