winex11: Use NtUserBuildHwndList for has_owned_popup implementation.
[wine.git] / dlls / vbscript / global.c
blobab06db87624907da4876da21c25742b7d8a00278
1 /*
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
19 #include <assert.h>
20 #include <math.h>
22 #include "vbscript.h"
23 #include "vbscript_defs.h"
25 #include "mshtmhst.h"
26 #include "objsafe.h"
27 #include "wchar.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}};
40 #define BP_GET 1
41 #define BP_GETPUT 2
43 typedef struct {
44 UINT16 len;
45 WCHAR buf[7];
46 } string_constant_t;
48 struct _builtin_prop_t {
49 const WCHAR *name;
50 HRESULT (*proc)(BuiltinDisp*,VARIANT*,unsigned,VARIANT*);
51 DWORD flags;
52 unsigned min_args;
53 UINT_PTR max_args;
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;
71 }else {
72 if(!IsEqualGUID(riid, &IID_IDispatchEx))
73 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
74 *ppv = NULL;
75 return E_NOINTERFACE;
78 IUnknown_AddRef((IUnknown*)*ppv);
79 return S_OK;
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);
89 return 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);
99 if(!ref) {
100 assert(!This->ctx);
101 heap_free(This);
104 return 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);
111 *pctinfo = 0;
112 return S_OK;
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;
125 int r;
127 while(min <= max) {
128 i = (min + max) / 2;
129 r = wcsicmp(disp->members[i].name, name);
130 if(!r) {
131 *id = i;
132 return S_OK;
134 if(r < 0)
135 min = i+1;
136 else
137 max = i-1;
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);
148 unsigned i;
149 HRESULT hres;
151 TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid), names, name_cnt, lcid, ids);
153 if(!This->ctx) {
154 FIXME("NULL context\n");
155 return E_UNEXPECTED;
158 for(i = 0; i < name_cnt; i++) {
159 hres = get_builtin_id(This, names[i], &ids[i]);
160 if(FAILED(hres))
161 return hres;
164 return S_OK;
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;
173 unsigned argn, i;
174 HRESULT hres;
176 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This, id, debugstr_guid(riid), lcid, flags, dp, res, ei, err);
178 if(!This->ctx) {
179 FIXME("NULL context\n");
180 return E_UNEXPECTED;
183 if(id >= This->member_cnt || (!This->members[id].proc && !This->members[id].flags))
184 return DISP_E_MEMBERNOTFOUND;
185 prop = This->members + id;
187 switch(flags) {
188 case DISPATCH_PROPERTYGET:
189 if(!(prop->flags & (BP_GET|BP_GETPUT))) {
190 FIXME("property does not support DISPATCH_PROPERTYGET\n");
191 return E_FAIL;
193 break;
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;
197 switch(vt) {
198 case VT_I2:
199 V_VT(res) = VT_I2;
200 V_I2(res) = val;
201 break;
202 case VT_I4:
203 V_VT(res) = VT_I4;
204 V_I4(res) = val;
205 break;
206 case VT_BSTR: {
207 const string_constant_t *str = (const string_constant_t*)prop->max_args;
208 BSTR ret;
210 ret = SysAllocStringLen(str->buf, str->len);
211 if(!ret)
212 return E_OUTOFMEMORY;
214 V_VT(res) = VT_BSTR;
215 V_BSTR(res) = ret;
216 break;
218 DEFAULT_UNREACHABLE;
220 return S_OK;
222 break;
223 case DISPATCH_METHOD:
224 if(prop->flags & (BP_GET|BP_GETPUT)) {
225 FIXME("Call on property\n");
226 return E_FAIL;
228 break;
229 case DISPATCH_PROPERTYPUT:
230 if(!(prop->flags & BP_GETPUT)) {
231 FIXME("property does not support DISPATCH_PROPERTYPUT\n");
232 return E_FAIL;
235 FIXME("call put\n");
236 return E_NOTIMPL;
237 default:
238 FIXME("unsupported flags %x\n", flags);
239 return E_NOTIMPL;
242 argn = arg_cnt(dp);
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)) {
250 args = args_buf;
251 }else {
252 args = heap_alloc(argn * sizeof(*args));
253 if(!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);
260 else
261 args[i] = dp->rgvarg[dp->cArgs-i-1];
264 hres = prop->proc(This, args, dp->cArgs, res);
265 if(args != args_buf)
266 heap_free(args);
267 return hres;
270 static const IDispatchVtbl BuiltinDispVtbl = {
271 Builtin_QueryInterface,
272 Builtin_AddRef,
273 Builtin_Release,
274 Builtin_GetTypeInfoCount,
275 Builtin_GetTypeInfo,
276 Builtin_GetIDsOfNames,
277 Builtin_Invoke
280 static HRESULT create_builtin_dispatch(script_ctx_t *ctx, const builtin_prop_t *members, size_t member_cnt, BuiltinDisp **ret)
282 BuiltinDisp *disp;
284 if(!(disp = heap_alloc(sizeof(*disp))))
285 return E_OUTOFMEMORY;
287 disp->IDispatch_iface.lpVtbl = &BuiltinDispVtbl;
288 disp->ref = 1;
289 disp->members = members;
290 disp->member_cnt = member_cnt;
291 disp->ctx = ctx;
293 *ret = disp;
294 return S_OK;
297 static IInternetHostSecurityManager *get_sec_mgr(script_ctx_t *ctx)
299 IInternetHostSecurityManager *secmgr;
300 IServiceProvider *sp;
301 HRESULT hres;
303 if(!ctx->site)
304 return NULL;
306 if(ctx->secmgr)
307 return ctx->secmgr;
309 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp);
310 if(FAILED(hres))
311 return NULL;
313 hres = IServiceProvider_QueryService(sp, &SID_SInternetHostSecurityManager, &IID_IInternetHostSecurityManager,
314 (void**)&secmgr);
315 IServiceProvider_Release(sp);
316 if(FAILED(hres))
317 return NULL;
319 return ctx->secmgr = secmgr;
322 static HRESULT return_string(VARIANT *res, const WCHAR *str)
324 BSTR ret;
326 if(!res)
327 return S_OK;
329 ret = SysAllocString(str);
330 if(!ret)
331 return E_OUTOFMEMORY;
333 V_VT(res) = VT_BSTR;
334 V_BSTR(res) = ret;
335 return S_OK;
338 static HRESULT return_bstr(VARIANT *res, BSTR str)
340 if(res) {
341 V_VT(res) = VT_BSTR;
342 V_BSTR(res) = str;
343 }else {
344 SysFreeString(str);
346 return S_OK;
349 static HRESULT return_bool(VARIANT *res, BOOL val)
351 if(res) {
352 V_VT(res) = VT_BOOL;
353 V_BOOL(res) = val ? VARIANT_TRUE : VARIANT_FALSE;
355 return S_OK;
358 static HRESULT return_short(VARIANT *res, short val)
360 if(res) {
361 V_VT(res) = VT_I2;
362 V_I2(res) = val;
365 return S_OK;
368 static HRESULT return_int(VARIANT *res, int val)
370 if(res) {
371 V_VT(res) = VT_I4;
372 V_I4(res) = val;
375 return S_OK;
378 static inline HRESULT return_double(VARIANT *res, double val)
380 if(res) {
381 V_VT(res) = VT_R8;
382 V_R8(res) = val;
385 return S_OK;
388 static inline HRESULT return_float(VARIANT *res, float val)
390 if(res) {
391 V_VT(res) = VT_R4;
392 V_R4(res) = val;
395 return S_OK;
398 static inline HRESULT return_null(VARIANT *res)
400 if(res)
401 V_VT(res) = VT_NULL;
402 return S_OK;
405 static inline HRESULT return_date(VARIANT *res, double date)
407 if(res) {
408 V_VT(res) = VT_DATE;
409 V_DATE(res) = date;
411 return S_OK;
414 HRESULT to_int(VARIANT *v, int *ret)
416 VARIANT r;
417 HRESULT hres;
419 V_VT(&r) = VT_EMPTY;
420 hres = VariantChangeType(&r, v, 0, VT_I4);
421 if(FAILED(hres))
422 return hres;
424 *ret = V_I4(&r);
425 return S_OK;
428 static HRESULT to_double(VARIANT *v, double *ret)
430 VARIANT dst;
431 HRESULT hres;
433 V_VT(&dst) = VT_EMPTY;
434 hres = VariantChangeType(&dst, v, 0, VT_R8);
435 if(FAILED(hres))
436 return hres;
438 *ret = V_R8(&dst);
439 return S_OK;
442 static HRESULT to_string(VARIANT *v, BSTR *ret)
444 VARIANT dst;
445 HRESULT hres;
447 V_VT(&dst) = VT_EMPTY;
448 hres = VariantChangeType(&dst, v, VARIANT_LOCALBOOL, VT_BSTR);
449 if(FAILED(hres))
450 return hres;
452 *ret = V_BSTR(&dst);
453 return S_OK;
456 static HRESULT to_system_time(VARIANT *v, SYSTEMTIME *st)
458 VARIANT date;
459 HRESULT hres;
461 V_VT(&date) = VT_EMPTY;
462 hres = VariantChangeType(&date, v, 0, VT_DATE);
463 if(FAILED(hres))
464 return hres;
466 return VariantTimeToSystemTime(V_DATE(&date), st);
469 static HRESULT set_object_site(script_ctx_t *ctx, IUnknown *obj)
471 IObjectWithSite *obj_site;
472 IUnknown *ax_site;
473 HRESULT hres;
475 hres = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (void**)&obj_site);
476 if(FAILED(hres))
477 return S_OK;
479 ax_site = create_ax_site(ctx);
480 if(ax_site) {
481 hres = IObjectWithSite_SetSite(obj_site, ax_site);
482 IUnknown_Release(ax_site);
484 else
485 hres = E_OUTOFMEMORY;
486 IObjectWithSite_Release(obj_site);
487 return hres;
490 static IUnknown *create_object(script_ctx_t *ctx, const WCHAR *progid)
492 IInternetHostSecurityManager *secmgr = NULL;
493 struct CONFIRMSAFETY cs;
494 IClassFactoryEx *cfex;
495 IClassFactory *cf;
496 DWORD policy_size;
497 BYTE *bpolicy;
498 IUnknown *obj;
499 DWORD policy;
500 GUID guid;
501 HRESULT hres;
503 hres = CLSIDFromProgID(progid, &guid);
504 if(FAILED(hres))
505 return NULL;
507 TRACE("GUID %s\n", debugstr_guid(&guid));
509 if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
510 secmgr = get_sec_mgr(ctx);
511 if(!secmgr)
512 return NULL;
514 policy = 0;
515 hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN,
516 (BYTE*)&policy, sizeof(policy), (BYTE*)&guid, sizeof(GUID), 0, 0);
517 if(FAILED(hres) || policy != URLPOLICY_ALLOW)
518 return NULL;
521 hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
522 if(FAILED(hres))
523 return NULL;
525 hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
526 if(SUCCEEDED(hres)) {
527 FIXME("Use IClassFactoryEx\n");
528 IClassFactoryEx_Release(cfex);
531 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
532 if(FAILED(hres))
533 return NULL;
535 if(secmgr) {
536 cs.clsid = guid;
537 cs.pUnk = obj;
538 cs.dwFlags = 0;
539 hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
540 &bpolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
541 if(SUCCEEDED(hres)) {
542 policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW;
543 CoTaskMemFree(bpolicy);
546 if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
547 IUnknown_Release(obj);
548 return NULL;
552 hres = set_object_site(ctx, obj);
553 if(FAILED(hres)) {
554 IUnknown_Release(obj);
555 return NULL;
558 return obj;
561 static HRESULT show_msgbox(script_ctx_t *ctx, BSTR prompt, unsigned type, BSTR orig_title, VARIANT *res)
563 SCRIPTUICHANDLING uic_handling = SCRIPTUICHANDLING_ALLOW;
564 IActiveScriptSiteUIControl *ui_control;
565 IActiveScriptSiteWindow *acts_window;
566 WCHAR *title_buf = NULL;
567 const WCHAR *title;
568 HWND hwnd = NULL;
569 int ret = 0;
570 HRESULT hres;
572 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteUIControl, (void**)&ui_control);
573 if(SUCCEEDED(hres)) {
574 hres = IActiveScriptSiteUIControl_GetUIBehavior(ui_control, SCRIPTUICITEM_MSGBOX, &uic_handling);
575 IActiveScriptSiteUIControl_Release(ui_control);
576 if(FAILED(hres))
577 uic_handling = SCRIPTUICHANDLING_ALLOW;
580 switch(uic_handling) {
581 case SCRIPTUICHANDLING_ALLOW:
582 break;
583 case SCRIPTUICHANDLING_NOUIDEFAULT:
584 return return_short(res, 0);
585 default:
586 FIXME("blocked\n");
587 return E_FAIL;
590 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteWindow, (void**)&acts_window);
591 if(FAILED(hres)) {
592 FIXME("No IActiveScriptSiteWindow\n");
593 return hres;
596 if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
597 if(orig_title && *orig_title) {
598 WCHAR *ptr;
600 title = title_buf = heap_alloc(sizeof(L"VBScript") + (lstrlenW(orig_title)+2)*sizeof(WCHAR));
601 if(!title)
602 return E_OUTOFMEMORY;
604 memcpy(title_buf, L"VBScript", sizeof(L"VBScript"));
605 ptr = title_buf + ARRAY_SIZE(L"VBScript")-1;
607 *ptr++ = ':';
608 *ptr++ = ' ';
609 lstrcpyW(ptr, orig_title);
610 }else {
611 title = L"VBScript";
613 }else {
614 title = orig_title ? orig_title : L"";
617 hres = IActiveScriptSiteWindow_GetWindow(acts_window, &hwnd);
618 if(SUCCEEDED(hres)) {
619 hres = IActiveScriptSiteWindow_EnableModeless(acts_window, FALSE);
620 if(SUCCEEDED(hres)) {
621 ret = MessageBoxW(hwnd, prompt, title, type);
622 hres = IActiveScriptSiteWindow_EnableModeless(acts_window, TRUE);
626 heap_free(title_buf);
627 IActiveScriptSiteWindow_Release(acts_window);
628 if(FAILED(hres)) {
629 FIXME("failed: %08lx\n", hres);
630 return hres;
633 return return_short(res, ret);
636 static HRESULT Global_CCur(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
638 VARIANT v;
639 HRESULT hres;
641 TRACE("%s\n", debugstr_variant(arg));
643 assert(args_cnt == 1);
645 V_VT(&v) = VT_EMPTY;
646 hres = VariantChangeType(&v, arg, 0, VT_CY);
647 if(FAILED(hres))
648 return hres;
650 if(!res) {
651 VariantClear(&v);
652 return DISP_E_BADVARTYPE;
655 *res = v;
656 return S_OK;
659 static HRESULT Global_CInt(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
661 VARIANT v;
662 HRESULT hres;
664 TRACE("%s\n", debugstr_variant(arg));
666 assert(args_cnt == 1);
668 V_VT(&v) = VT_EMPTY;
669 hres = VariantChangeType(&v, arg, 0, VT_I2);
670 if(FAILED(hres))
671 return hres;
673 if(!res)
674 return DISP_E_BADVARTYPE;
675 else {
676 *res = v;
677 return S_OK;
681 static HRESULT Global_CLng(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
683 int i;
684 HRESULT hres;
686 TRACE("%s\n", debugstr_variant(arg));
688 assert(args_cnt == 1);
690 hres = to_int(arg, &i);
691 if(FAILED(hres))
692 return hres;
693 if(!res)
694 return DISP_E_BADVARTYPE;
696 return return_int(res, i);
699 static HRESULT Global_CBool(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
701 VARIANT v;
702 HRESULT hres;
704 TRACE("%s\n", debugstr_variant(arg));
706 assert(args_cnt == 1);
708 V_VT(&v) = VT_EMPTY;
709 hres = VariantChangeType(&v, arg, VARIANT_LOCALBOOL, VT_BOOL);
710 if(FAILED(hres))
711 return hres;
713 if(res)
714 *res = v;
715 else
716 VariantClear(&v);
717 return S_OK;
720 static HRESULT Global_CByte(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
722 VARIANT v;
723 HRESULT hres;
725 TRACE("%s\n", debugstr_variant(arg));
727 assert(args_cnt == 1);
729 V_VT(&v) = VT_EMPTY;
730 hres = VariantChangeType(&v, arg, VARIANT_LOCALBOOL, VT_UI1);
731 if(FAILED(hres))
732 return hres;
734 if(!res) {
735 VariantClear(&v);
736 return DISP_E_BADVARTYPE;
739 *res = v;
740 return S_OK;
743 static HRESULT Global_CDate(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
745 FIXME("\n");
746 return E_NOTIMPL;
749 static HRESULT Global_CDbl(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
751 VARIANT v;
752 HRESULT hres;
754 TRACE("%s\n", debugstr_variant(arg));
756 assert(args_cnt == 1);
758 V_VT(&v) = VT_EMPTY;
759 hres = VariantChangeType(&v, arg, 0, VT_R8);
760 if(FAILED(hres))
761 return hres;
763 if(!res)
764 return DISP_E_BADVARTYPE;
765 else {
766 *res = v;
767 return S_OK;
771 static HRESULT Global_CSng(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
773 VARIANT v;
774 HRESULT hres;
776 TRACE("%s\n", debugstr_variant(arg));
778 assert(args_cnt == 1);
780 V_VT(&v) = VT_EMPTY;
781 hres = VariantChangeType(&v, arg, 0, VT_R4);
782 if(FAILED(hres))
783 return hres;
785 if(!res)
786 return DISP_E_BADVARTYPE;
788 *res = v;
789 return S_OK;
792 static HRESULT Global_CStr(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
794 BSTR str;
795 HRESULT hres;
797 TRACE("%s\n", debugstr_variant(arg));
799 if(V_VT(arg) == VT_NULL)
800 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
802 hres = to_string(arg, &str);
803 if(FAILED(hres))
804 return hres;
806 return return_bstr(res, str);
809 static inline WCHAR hex_char(unsigned n)
811 return n < 10 ? '0'+n : 'A'+n-10;
814 static HRESULT Global_Hex(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
816 WCHAR buf[17], *ptr;
817 DWORD n;
818 HRESULT hres;
819 int ret;
821 TRACE("%s\n", debugstr_variant(arg));
823 switch(V_VT(arg)) {
824 case VT_I2:
825 n = (WORD)V_I2(arg);
826 break;
827 case VT_NULL:
828 if(res)
829 V_VT(res) = VT_NULL;
830 return S_OK;
831 default:
832 hres = to_int(arg, &ret);
833 if(FAILED(hres))
834 return hres;
835 else
836 n = ret;
839 buf[16] = 0;
840 ptr = buf+15;
842 if(n) {
843 do {
844 *ptr-- = hex_char(n & 0xf);
845 n >>= 4;
846 }while(n);
847 ptr++;
848 }else {
849 *ptr = '0';
852 return return_string(res, ptr);
855 static HRESULT Global_Oct(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
857 HRESULT hres;
858 WCHAR buf[23], *ptr;
859 DWORD n;
860 int ret;
862 TRACE("%s\n", debugstr_variant(arg));
864 switch(V_VT(arg)) {
865 case VT_I2:
866 n = (WORD)V_I2(arg);
867 break;
868 case VT_NULL:
869 if(res)
870 V_VT(res) = VT_NULL;
871 return S_OK;
872 default:
873 hres = to_int(arg, &ret);
874 if(FAILED(hres))
875 return hres;
876 else
877 n = ret;
880 buf[22] = 0;
881 ptr = buf + 21;
883 if(n) {
884 do {
885 *ptr-- = '0' + (n & 0x7);
886 n >>= 3;
887 }while(n);
888 ptr++;
889 }else {
890 *ptr = '0';
893 return return_string(res, ptr);
896 static HRESULT Global_VarType(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
898 VARTYPE vt;
900 TRACE("(%s)\n", debugstr_variant(arg));
902 assert(args_cnt == 1);
904 vt = V_VT(arg) & ~VT_BYREF;
905 if(vt & ~(VT_TYPEMASK | VT_ARRAY)) {
906 FIXME("not supported %s\n", debugstr_variant(arg));
907 return E_NOTIMPL;
910 return return_short(res, vt);
913 static HRESULT Global_IsDate(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
915 FIXME("\n");
916 return E_NOTIMPL;
919 static HRESULT Global_IsEmpty(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
921 TRACE("(%s)\n", debugstr_variant(arg));
923 assert(args_cnt == 1);
925 if(res) {
926 V_VT(res) = VT_BOOL;
927 V_BOOL(res) = V_VT(arg) == VT_EMPTY ? VARIANT_TRUE : VARIANT_FALSE;
929 return S_OK;
932 static HRESULT Global_IsNull(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
934 TRACE("(%s)\n", debugstr_variant(arg));
936 assert(args_cnt == 1);
938 if(res) {
939 V_VT(res) = VT_BOOL;
940 V_BOOL(res) = V_VT(arg) == VT_NULL ? VARIANT_TRUE : VARIANT_FALSE;
942 return S_OK;
945 static HRESULT Global_IsNumeric(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
947 HRESULT hres;
948 double d;
950 TRACE("(%s)\n", debugstr_variant(arg));
952 assert(args_cnt == 1);
954 hres = to_double(arg, &d);
956 return return_bool(res, SUCCEEDED(hres));
959 static HRESULT Global_IsArray(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
961 TRACE("(%s)\n", debugstr_variant(arg));
963 assert(args_cnt == 1);
965 return return_bool(res, V_ISARRAY(arg));
968 static HRESULT Global_IsObject(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
970 TRACE("(%s)\n", debugstr_variant(arg));
972 assert(args_cnt == 1);
974 if(res) {
975 V_VT(res) = VT_BOOL;
976 V_BOOL(res) = V_VT(arg) == VT_DISPATCH ? VARIANT_TRUE : VARIANT_FALSE;
978 return S_OK;
981 static HRESULT Global_Atn(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
983 HRESULT hres;
984 double d;
986 hres = to_double(arg, &d);
987 if(FAILED(hres))
988 return hres;
990 return return_double(res, atan(d));
993 static HRESULT Global_Cos(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
995 HRESULT hres;
996 double d;
998 hres = to_double(arg, &d);
999 if(FAILED(hres))
1000 return hres;
1002 return return_double(res, cos(d));
1005 static HRESULT Global_Sin(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1007 HRESULT hres;
1008 double d;
1010 hres = to_double(arg, &d);
1011 if(FAILED(hres))
1012 return hres;
1014 return return_double(res, sin(d));
1017 static HRESULT Global_Tan(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1019 HRESULT hres;
1020 double d;
1022 hres = to_double(arg, &d);
1023 if(FAILED(hres))
1024 return hres;
1026 return return_double(res, tan(d));
1029 static HRESULT Global_Exp(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1031 HRESULT hres;
1032 double d;
1034 hres = to_double(arg, &d);
1035 if(FAILED(hres))
1036 return hres;
1038 return return_double(res, exp(d));
1041 static HRESULT Global_Log(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1043 HRESULT hres;
1044 double d;
1046 hres = to_double(arg, &d);
1047 if(FAILED(hres))
1048 return hres;
1050 if(d <= 0)
1051 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1052 else
1053 return return_double(res, log(d));
1056 static HRESULT Global_Sqr(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1058 HRESULT hres;
1059 double d;
1061 hres = to_double(arg, &d);
1062 if(FAILED(hres))
1063 return hres;
1065 if(d < 0)
1066 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1067 else
1068 return return_double(res, sqrt(d));
1071 static HRESULT Global_Randomize(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1073 FIXME("\n");
1074 return E_NOTIMPL;
1077 static HRESULT Global_Rnd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1079 FIXME("\n");
1080 return E_NOTIMPL;
1083 static HRESULT Global_Timer(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1085 SYSTEMTIME lt;
1086 double sec;
1088 GetLocalTime(&lt);
1089 sec = lt.wHour * 3600 + lt.wMinute * 60 + lt.wSecond + lt.wMilliseconds / 1000.0;
1090 return return_float(res, sec);
1094 static HRESULT Global_LBound(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1096 SAFEARRAY *sa;
1097 HRESULT hres;
1098 LONG ubound;
1099 int dim;
1101 assert(args_cnt == 1 || args_cnt == 2);
1103 TRACE("%s %s\n", debugstr_variant(arg), args_cnt == 2 ? debugstr_variant(arg + 1) : "1");
1105 switch(V_VT(arg)) {
1106 case VT_VARIANT|VT_ARRAY:
1107 sa = V_ARRAY(arg);
1108 break;
1109 case VT_VARIANT|VT_ARRAY|VT_BYREF:
1110 sa = *V_ARRAYREF(arg);
1111 break;
1112 default:
1113 FIXME("arg %s not supported\n", debugstr_variant(arg));
1114 return E_NOTIMPL;
1117 if(args_cnt == 2) {
1118 hres = to_int(arg + 1, &dim);
1119 if(FAILED(hres))
1120 return hres;
1121 }else {
1122 dim = 1;
1125 hres = SafeArrayGetLBound(sa, dim, &ubound);
1126 if(FAILED(hres))
1127 return hres;
1129 return return_int(res, ubound);
1132 static HRESULT Global_UBound(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1134 SAFEARRAY *sa;
1135 HRESULT hres;
1136 LONG ubound;
1137 int dim;
1139 assert(args_cnt == 1 || args_cnt == 2);
1141 TRACE("%s %s\n", debugstr_variant(arg), args_cnt == 2 ? debugstr_variant(arg + 1) : "1");
1143 switch(V_VT(arg)) {
1144 case VT_VARIANT|VT_ARRAY:
1145 sa = V_ARRAY(arg);
1146 break;
1147 case VT_VARIANT|VT_ARRAY|VT_BYREF:
1148 sa = *V_ARRAYREF(arg);
1149 break;
1150 default:
1151 FIXME("arg %s not supported\n", debugstr_variant(arg));
1152 return E_NOTIMPL;
1155 if(args_cnt == 2) {
1156 hres = to_int(arg + 1, &dim);
1157 if(FAILED(hres))
1158 return hres;
1159 }else {
1160 dim = 1;
1163 hres = SafeArrayGetUBound(sa, dim, &ubound);
1164 if(FAILED(hres))
1165 return hres;
1167 return return_int(res, ubound);
1170 static HRESULT Global_RGB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1172 HRESULT hres;
1173 int i, color[3];
1175 TRACE("%s %s %s\n", debugstr_variant(arg), debugstr_variant(arg + 1), debugstr_variant(arg + 2));
1177 assert(args_cnt == 3);
1179 for(i = 0; i < 3; i++) {
1180 hres = to_int(arg + i, color + i);
1181 if(FAILED(hres))
1182 return hres;
1183 if(color[i] > 255)
1184 color[i] = 255;
1185 if(color[i] < 0)
1186 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1189 return return_int(res, RGB(color[0], color[1], color[2]));
1192 static HRESULT Global_Len(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1194 DWORD len;
1195 HRESULT hres;
1197 TRACE("%s\n", debugstr_variant(arg));
1199 if(V_VT(arg) == VT_NULL)
1200 return return_null(res);
1202 if(V_VT(arg) != VT_BSTR) {
1203 BSTR str;
1205 hres = to_string(arg, &str);
1206 if(FAILED(hres))
1207 return hres;
1209 len = SysStringLen(str);
1210 SysFreeString(str);
1211 }else {
1212 len = SysStringLen(V_BSTR(arg));
1215 return return_int(res, len);
1218 static HRESULT Global_LenB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1220 FIXME("\n");
1221 return E_NOTIMPL;
1224 static HRESULT Global_Left(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1226 BSTR str, ret, conv_str = NULL;
1227 int len, str_len;
1228 HRESULT hres;
1230 TRACE("(%s %s)\n", debugstr_variant(args+1), debugstr_variant(args));
1232 if(V_VT(args) == VT_BSTR) {
1233 str = V_BSTR(args);
1234 }else {
1235 hres = to_string(args, &conv_str);
1236 if(FAILED(hres))
1237 return hres;
1238 str = conv_str;
1241 hres = to_int(args+1, &len);
1242 if(FAILED(hres))
1243 return hres;
1245 if(len < 0) {
1246 FIXME("len = %d\n", len);
1247 return E_FAIL;
1250 str_len = SysStringLen(str);
1251 if(len > str_len)
1252 len = str_len;
1254 ret = SysAllocStringLen(str, len);
1255 SysFreeString(conv_str);
1256 if(!ret)
1257 return E_OUTOFMEMORY;
1259 return return_bstr(res, ret);
1262 static HRESULT Global_LeftB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1264 FIXME("\n");
1265 return E_NOTIMPL;
1268 static HRESULT Global_Right(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1270 BSTR str, ret, conv_str = NULL;
1271 int len, str_len;
1272 HRESULT hres;
1274 TRACE("(%s %s)\n", debugstr_variant(args), debugstr_variant(args+1));
1276 if(V_VT(args+1) == VT_BSTR) {
1277 str = V_BSTR(args);
1278 }else {
1279 hres = to_string(args, &conv_str);
1280 if(FAILED(hres))
1281 return hres;
1282 str = conv_str;
1285 hres = to_int(args+1, &len);
1286 if(FAILED(hres))
1287 return hres;
1289 if(len < 0) {
1290 FIXME("len = %d\n", len);
1291 return E_FAIL;
1294 str_len = SysStringLen(str);
1295 if(len > str_len)
1296 len = str_len;
1298 ret = SysAllocStringLen(str+str_len-len, len);
1299 SysFreeString(conv_str);
1300 if(!ret)
1301 return E_OUTOFMEMORY;
1303 return return_bstr(res, ret);
1306 static HRESULT Global_RightB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1308 FIXME("\n");
1309 return E_NOTIMPL;
1312 static HRESULT Global_Mid(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1314 int len = -1, start, str_len;
1315 BSTR str;
1316 HRESULT hres;
1318 TRACE("(%s %s ...)\n", debugstr_variant(args), debugstr_variant(args+1));
1320 assert(args_cnt == 2 || args_cnt == 3);
1322 if(V_VT(args) != VT_BSTR) {
1323 FIXME("args[0] = %s\n", debugstr_variant(args));
1324 return E_NOTIMPL;
1327 str = V_BSTR(args);
1329 hres = to_int(args+1, &start);
1330 if(FAILED(hres))
1331 return hres;
1333 if(args_cnt == 3) {
1334 hres = to_int(args+2, &len);
1335 if(FAILED(hres))
1336 return hres;
1338 if(len < 0) {
1339 FIXME("len = %d\n", len);
1340 return E_FAIL;
1345 str_len = SysStringLen(str);
1346 start--;
1347 if(start > str_len)
1348 start = str_len;
1350 if(len == -1)
1351 len = str_len-start;
1352 else if(len > str_len-start)
1353 len = str_len-start;
1355 if(res) {
1356 V_VT(res) = VT_BSTR;
1357 V_BSTR(res) = SysAllocStringLen(str+start, len);
1358 if(!V_BSTR(res))
1359 return E_OUTOFMEMORY;
1362 return S_OK;
1365 static HRESULT Global_MidB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1367 FIXME("\n");
1368 return E_NOTIMPL;
1371 static HRESULT Global_StrComp(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1373 BSTR left, right;
1374 int mode, ret;
1375 HRESULT hres;
1376 short val;
1378 TRACE("(%s %s ...)\n", debugstr_variant(args), debugstr_variant(args+1));
1380 assert(args_cnt == 2 || args_cnt == 3);
1382 if (args_cnt == 3) {
1383 hres = to_int(args+2, &mode);
1384 if(FAILED(hres))
1385 return hres;
1387 if (mode != 0 && mode != 1) {
1388 FIXME("unknown compare mode = %d\n", mode);
1389 return E_FAIL;
1392 else
1393 mode = 0;
1395 hres = to_string(args, &left);
1396 if(FAILED(hres))
1397 return hres;
1399 hres = to_string(args+1, &right);
1400 if(FAILED(hres))
1402 SysFreeString(left);
1403 return hres;
1406 ret = mode ? wcsicmp(left, right) : wcscmp(left, right);
1407 val = ret < 0 ? -1 : (ret > 0 ? 1 : 0);
1409 SysFreeString(left);
1410 SysFreeString(right);
1411 return return_short(res, val);
1414 static HRESULT Global_LCase(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1416 BSTR str;
1417 HRESULT hres;
1419 TRACE("%s\n", debugstr_variant(arg));
1421 if(V_VT(arg) == VT_NULL) {
1422 if(res)
1423 V_VT(res) = VT_NULL;
1424 return S_OK;
1427 hres = to_string(arg, &str);
1428 if(FAILED(hres))
1429 return hres;
1431 if(res) {
1432 WCHAR *ptr;
1434 for(ptr = str; *ptr; ptr++)
1435 *ptr = towlower(*ptr);
1437 V_VT(res) = VT_BSTR;
1438 V_BSTR(res) = str;
1439 }else {
1440 SysFreeString(str);
1442 return S_OK;
1445 static HRESULT Global_UCase(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1447 BSTR str;
1448 HRESULT hres;
1450 TRACE("%s\n", debugstr_variant(arg));
1452 if(V_VT(arg) == VT_NULL) {
1453 if(res)
1454 V_VT(res) = VT_NULL;
1455 return S_OK;
1458 hres = to_string(arg, &str);
1459 if(FAILED(hres))
1460 return hres;
1462 if(res) {
1463 WCHAR *ptr;
1465 for(ptr = str; *ptr; ptr++)
1466 *ptr = towupper(*ptr);
1468 V_VT(res) = VT_BSTR;
1469 V_BSTR(res) = str;
1470 }else {
1471 SysFreeString(str);
1473 return S_OK;
1476 static HRESULT Global_LTrim(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1478 BSTR str, conv_str = NULL;
1479 WCHAR *ptr;
1480 HRESULT hres;
1482 TRACE("%s\n", debugstr_variant(arg));
1484 if(V_VT(arg) == VT_BSTR) {
1485 str = V_BSTR(arg);
1486 }else {
1487 hres = to_string(arg, &conv_str);
1488 if(FAILED(hres))
1489 return hres;
1490 str = conv_str;
1493 for(ptr = str; *ptr && iswspace(*ptr); ptr++);
1495 str = SysAllocString(ptr);
1496 SysFreeString(conv_str);
1497 if(!str)
1498 return E_OUTOFMEMORY;
1500 return return_bstr(res, str);
1503 static HRESULT Global_RTrim(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1505 BSTR str, conv_str = NULL;
1506 WCHAR *ptr;
1507 HRESULT hres;
1509 TRACE("%s\n", debugstr_variant(arg));
1511 if(V_VT(arg) == VT_BSTR) {
1512 str = V_BSTR(arg);
1513 }else {
1514 hres = to_string(arg, &conv_str);
1515 if(FAILED(hres))
1516 return hres;
1517 str = conv_str;
1520 for(ptr = str+SysStringLen(str); ptr-1 > str && iswspace(*(ptr-1)); ptr--);
1522 str = SysAllocStringLen(str, ptr-str);
1523 SysFreeString(conv_str);
1524 if(!str)
1525 return E_OUTOFMEMORY;
1527 return return_bstr(res, str);
1530 static HRESULT Global_Trim(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1532 BSTR str, conv_str = NULL;
1533 WCHAR *begin_ptr, *end_ptr;
1534 HRESULT hres;
1536 TRACE("%s\n", debugstr_variant(arg));
1538 if(V_VT(arg) == VT_BSTR) {
1539 str = V_BSTR(arg);
1540 }else {
1541 hres = to_string(arg, &conv_str);
1542 if(FAILED(hres))
1543 return hres;
1544 str = conv_str;
1547 for(begin_ptr = str; *begin_ptr && iswspace(*begin_ptr); begin_ptr++);
1548 for(end_ptr = str+SysStringLen(str); end_ptr-1 > begin_ptr && iswspace(*(end_ptr-1)); end_ptr--);
1550 str = SysAllocStringLen(begin_ptr, end_ptr-begin_ptr);
1551 SysFreeString(conv_str);
1552 if(!str)
1553 return E_OUTOFMEMORY;
1555 return return_bstr(res, str);
1558 static HRESULT Global_Space(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1560 BSTR str;
1561 int n, i;
1562 HRESULT hres;
1564 TRACE("%s\n", debugstr_variant(arg));
1566 hres = to_int(arg, &n);
1567 if(FAILED(hres))
1568 return hres;
1570 if(n < 0) {
1571 FIXME("n = %d\n", n);
1572 return E_NOTIMPL;
1575 if(!res)
1576 return S_OK;
1578 str = SysAllocStringLen(NULL, n);
1579 if(!str)
1580 return E_OUTOFMEMORY;
1582 for(i=0; i<n; i++)
1583 str[i] = ' ';
1585 V_VT(res) = VT_BSTR;
1586 V_BSTR(res) = str;
1587 return S_OK;
1590 static HRESULT Global_String(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1592 WCHAR ch;
1593 int cnt;
1594 HRESULT hres;
1596 TRACE("%s %s\n", debugstr_variant(args), debugstr_variant(args + 1));
1598 hres = to_int(args, &cnt);
1599 if(FAILED(hres))
1600 return hres;
1601 if(cnt < 0)
1602 return E_INVALIDARG;
1604 if(V_VT(args + 1) != VT_BSTR) {
1605 FIXME("Unsupported argument %s\n", debugstr_variant(args+1));
1606 return E_NOTIMPL;
1608 if(!SysStringLen(V_BSTR(args + 1)))
1609 return E_INVALIDARG;
1610 ch = V_BSTR(args + 1)[0];
1612 if(res) {
1613 BSTR str = SysAllocStringLen(NULL, cnt);
1614 if(!str)
1615 return E_OUTOFMEMORY;
1616 wmemset(str, ch, cnt);
1617 V_VT(res) = VT_BSTR;
1618 V_BSTR(res) = str;
1620 return S_OK;
1623 static HRESULT Global_InStr(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1625 VARIANT *startv, *str1v, *str2v;
1626 BSTR str1, str2;
1627 int ret = -1, start = 0, mode = 0;
1628 HRESULT hres;
1630 TRACE("args_cnt=%u\n", args_cnt);
1632 assert(2 <= args_cnt && args_cnt <= 4);
1634 switch(args_cnt) {
1635 case 2:
1636 startv = NULL;
1637 str1v = args;
1638 str2v = args+1;
1639 break;
1640 case 3:
1641 startv = args;
1642 str1v = args+1;
1643 str2v = args+2;
1644 break;
1645 case 4:
1646 startv = args;
1647 str1v = args+1;
1648 str2v = args+2;
1650 if(V_VT(args+3) == VT_NULL)
1651 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1653 hres = to_int(args+3, &mode);
1654 if(FAILED(hres))
1655 return hres;
1657 if (mode != 0 && mode != 1)
1658 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1660 break;
1661 DEFAULT_UNREACHABLE;
1664 if(startv) {
1665 if(V_VT(startv) == VT_NULL)
1666 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1668 hres = to_int(startv, &start);
1669 if(FAILED(hres))
1670 return hres;
1671 if(--start < 0)
1672 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1675 if(V_VT(str1v) == VT_NULL || V_VT(str2v) == VT_NULL)
1676 return return_null(res);
1678 if(V_VT(str1v) != VT_BSTR) {
1679 hres = to_string(str1v, &str1);
1680 if(FAILED(hres))
1681 return hres;
1683 else
1684 str1 = V_BSTR(str1v);
1686 if(V_VT(str2v) != VT_BSTR) {
1687 hres = to_string(str2v, &str2);
1688 if(FAILED(hres)){
1689 if(V_VT(str1v) != VT_BSTR)
1690 SysFreeString(str1);
1691 return hres;
1694 else
1695 str2 = V_BSTR(str2v);
1697 if(start < SysStringLen(str1)) {
1698 ret = FindStringOrdinal(FIND_FROMSTART, str1 + start, SysStringLen(str1)-start,
1699 str2, SysStringLen(str2), mode);
1702 if(V_VT(str1v) != VT_BSTR)
1703 SysFreeString(str1);
1704 if(V_VT(str2v) != VT_BSTR)
1705 SysFreeString(str2);
1706 return return_int(res, ++ret ? ret+start : 0);
1709 static HRESULT Global_InStrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1711 FIXME("\n");
1712 return E_NOTIMPL;
1715 static HRESULT Global_AscB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1717 FIXME("\n");
1718 return E_NOTIMPL;
1721 static HRESULT Global_ChrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1723 FIXME("\n");
1724 return E_NOTIMPL;
1727 static HRESULT Global_Asc(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1729 BSTR conv_str = NULL, str;
1730 HRESULT hres = S_OK;
1732 TRACE("(%s)\n", debugstr_variant(arg));
1734 switch(V_VT(arg)) {
1735 case VT_NULL:
1736 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1737 case VT_EMPTY:
1738 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1739 case VT_BSTR:
1740 str = V_BSTR(arg);
1741 break;
1742 default:
1743 hres = to_string(arg, &conv_str);
1744 if(FAILED(hres))
1745 return hres;
1746 str = conv_str;
1749 if(!SysStringLen(str))
1750 hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1751 else {
1752 unsigned char buf[2];
1753 short val = 0;
1754 int n = WideCharToMultiByte(CP_ACP, 0, str, 1, (char*)buf, sizeof(buf), NULL, NULL);
1755 switch(n) {
1756 case 1:
1757 val = buf[0];
1758 break;
1759 case 2:
1760 val = (buf[0] << 8) | buf[1];
1761 break;
1762 default:
1763 WARN("Failed to convert %x\n", *str);
1764 hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1766 if(SUCCEEDED(hres))
1767 hres = return_short(res, val);
1770 SysFreeString(conv_str);
1771 return hres;
1774 /* The function supports only single-byte and double-byte character sets. It
1775 * ignores language specified by IActiveScriptSite::GetLCID. The argument needs
1776 * to be in range of short or unsigned short. */
1777 static HRESULT Global_Chr(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1779 int cp, c, len = 0;
1780 CPINFO cpi;
1781 WCHAR ch;
1782 char buf[2];
1783 HRESULT hres;
1785 TRACE("%s\n", debugstr_variant(arg));
1787 hres = to_int(arg, &c);
1788 if(FAILED(hres))
1789 return hres;
1791 cp = GetACP();
1792 if(!GetCPInfo(cp, &cpi))
1793 cpi.MaxCharSize = 1;
1795 if((c!=(short)c && c!=(unsigned short)c) ||
1796 (unsigned short)c>=(cpi.MaxCharSize>1 ? 0x10000 : 0x100)) {
1797 WARN("invalid arg %d\n", c);
1798 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1801 if(c>>8)
1802 buf[len++] = c>>8;
1803 if(!len || IsDBCSLeadByteEx(cp, buf[0]))
1804 buf[len++] = c;
1805 if(!MultiByteToWideChar(CP_ACP, 0, buf, len, &ch, 1)) {
1806 WARN("invalid arg %d, cp %d\n", c, cp);
1807 return E_FAIL;
1810 if(res) {
1811 V_VT(res) = VT_BSTR;
1812 V_BSTR(res) = SysAllocStringLen(&ch, 1);
1813 if(!V_BSTR(res))
1814 return E_OUTOFMEMORY;
1816 return S_OK;
1819 static HRESULT Global_AscW(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1821 FIXME("\n");
1822 return E_NOTIMPL;
1825 static HRESULT Global_ChrW(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1827 FIXME("\n");
1828 return E_NOTIMPL;
1831 static HRESULT Global_Abs(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1833 HRESULT hres;
1834 VARIANT dst;
1836 TRACE("(%s)\n", debugstr_variant(arg));
1838 assert(args_cnt == 1);
1840 hres = VarAbs(arg, &dst);
1841 if(FAILED(hres))
1842 return hres;
1844 if (res)
1845 *res = dst;
1846 else
1847 VariantClear(&dst);
1849 return S_OK;
1852 static HRESULT Global_Fix(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1854 HRESULT hres;
1855 VARIANT dst;
1857 TRACE("(%s)\n", debugstr_variant(arg));
1859 assert(args_cnt == 1);
1861 hres = VarFix(arg, &dst);
1862 if(FAILED(hres))
1863 return hres;
1865 if (res)
1866 *res = dst;
1867 else
1868 VariantClear(&dst);
1870 return S_OK;
1873 static HRESULT Global_Int(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1875 HRESULT hres;
1876 VARIANT dst;
1878 TRACE("(%s)\n", debugstr_variant(arg));
1880 assert(args_cnt == 1);
1882 hres = VarInt(arg, &dst);
1883 if(FAILED(hres))
1884 return hres;
1886 if (res)
1887 *res = dst;
1888 else
1889 VariantClear(&dst);
1891 return S_OK;
1894 static HRESULT Global_Sgn(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1896 double v;
1897 short val;
1898 HRESULT hres;
1900 TRACE("(%s)\n", debugstr_variant(arg));
1902 assert(args_cnt == 1);
1904 if(V_VT(arg) == VT_NULL)
1905 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1907 hres = to_double(arg, &v);
1908 if (FAILED(hres))
1909 return hres;
1911 val = v == 0 ? 0 : (v > 0 ? 1 : -1);
1912 return return_short(res, val);
1915 static HRESULT Global_Now(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1917 SYSTEMTIME lt;
1918 double date;
1920 TRACE("\n");
1922 GetLocalTime(&lt);
1923 SystemTimeToVariantTime(&lt, &date);
1924 return return_date(res, date);
1927 static HRESULT Global_Date(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1929 SYSTEMTIME lt;
1930 UDATE ud;
1931 DATE date;
1932 HRESULT hres;
1934 TRACE("\n");
1936 GetLocalTime(&lt);
1937 ud.st = lt;
1938 ud.wDayOfYear = 0;
1939 hres = VarDateFromUdateEx(&ud, 0, VAR_DATEVALUEONLY, &date);
1940 if(FAILED(hres))
1941 return hres;
1942 return return_date(res, date);
1945 static HRESULT Global_Time(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1947 SYSTEMTIME lt;
1948 UDATE ud;
1949 DATE time;
1950 HRESULT hres;
1952 TRACE("\n");
1954 GetLocalTime(&lt);
1955 ud.st = lt;
1956 ud.wDayOfYear = 0;
1957 hres = VarDateFromUdateEx(&ud, 0, VAR_TIMEVALUEONLY, &time);
1958 if(FAILED(hres))
1959 return hres;
1960 return return_date(res, time);
1963 static HRESULT Global_Day(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1965 SYSTEMTIME st;
1966 HRESULT hres;
1968 TRACE("(%s)\n", debugstr_variant(arg));
1970 hres = to_system_time(arg, &st);
1971 return FAILED(hres) ? hres : return_short(res, st.wDay);
1974 static HRESULT Global_Month(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1976 SYSTEMTIME st;
1977 HRESULT hres;
1979 TRACE("(%s)\n", debugstr_variant(arg));
1981 hres = to_system_time(arg, &st);
1982 return FAILED(hres) ? hres : return_short(res, st.wMonth);
1985 static HRESULT Global_Weekday(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1987 FIXME("\n");
1988 return E_NOTIMPL;
1991 static HRESULT Global_Year(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1993 SYSTEMTIME st;
1994 HRESULT hres;
1996 TRACE("(%s)\n", debugstr_variant(arg));
1998 hres = to_system_time(arg, &st);
1999 return FAILED(hres) ? hres : return_short(res, st.wYear);
2002 static HRESULT Global_Hour(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2004 SYSTEMTIME st;
2005 HRESULT hres;
2007 TRACE("(%s)\n", debugstr_variant(arg));
2009 hres = to_system_time(arg, &st);
2010 return FAILED(hres) ? hres : return_short(res, st.wHour);
2013 static HRESULT Global_Minute(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2015 SYSTEMTIME st;
2016 HRESULT hres;
2018 TRACE("(%s)\n", debugstr_variant(arg));
2020 hres = to_system_time(arg, &st);
2021 return FAILED(hres) ? hres : return_short(res, st.wMinute);
2024 static HRESULT Global_Second(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2026 SYSTEMTIME st;
2027 HRESULT hres;
2029 TRACE("(%s)\n", debugstr_variant(arg));
2031 hres = to_system_time(arg, &st);
2032 return FAILED(hres) ? hres : return_short(res, st.wSecond);
2035 static HRESULT Global_DateValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2037 FIXME("\n");
2038 return E_NOTIMPL;
2041 static HRESULT Global_TimeValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2043 FIXME("\n");
2044 return E_NOTIMPL;
2047 static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2049 FIXME("\n");
2050 return E_NOTIMPL;
2053 static HRESULT Global_TimeSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2055 FIXME("\n");
2056 return E_NOTIMPL;
2059 static HRESULT Global_InputBox(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2061 FIXME("\n");
2062 return E_NOTIMPL;
2065 static HRESULT Global_MsgBox(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2067 BSTR prompt, title = NULL;
2068 int type = MB_OK;
2069 HRESULT hres;
2071 TRACE("\n");
2073 assert(1 <= args_cnt && args_cnt <= 5);
2075 hres = to_string(args, &prompt);
2076 if(FAILED(hres))
2077 return hres;
2079 if(args_cnt > 1)
2080 hres = to_int(args+1, &type);
2082 if(SUCCEEDED(hres) && args_cnt > 2)
2083 hres = to_string(args+2, &title);
2085 if(SUCCEEDED(hres) && args_cnt > 3) {
2086 FIXME("unsupported arg_cnt %d\n", args_cnt);
2087 hres = E_NOTIMPL;
2090 if(SUCCEEDED(hres))
2091 hres = show_msgbox(This->ctx, prompt, type, title, res);
2093 SysFreeString(prompt);
2094 SysFreeString(title);
2095 return hres;
2098 static HRESULT Global_CreateObject(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2100 IUnknown *obj;
2101 HRESULT hres;
2103 TRACE("(%s)\n", debugstr_variant(arg));
2105 if(V_VT(arg) != VT_BSTR) {
2106 FIXME("non-bstr arg\n");
2107 return E_INVALIDARG;
2110 obj = create_object(This->ctx, V_BSTR(arg));
2111 if(!obj)
2112 return VB_E_CANNOT_CREATE_OBJ;
2114 if(res) {
2115 hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&V_DISPATCH(res));
2116 if(FAILED(hres))
2117 return hres;
2119 V_VT(res) = VT_DISPATCH;
2122 IUnknown_Release(obj);
2123 return S_OK;
2126 static HRESULT Global_GetObject(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2128 IBindCtx *bind_ctx;
2129 IUnknown *obj_unk;
2130 IDispatch *disp;
2131 ULONG eaten = 0;
2132 IMoniker *mon;
2133 HRESULT hres;
2135 TRACE("%s %s\n", args_cnt ? debugstr_variant(args) : "", args_cnt > 1 ? debugstr_variant(args+1) : "");
2137 if(args_cnt != 1 || V_VT(args) != VT_BSTR) {
2138 FIXME("unsupported args\n");
2139 return E_NOTIMPL;
2142 if(This->ctx->safeopt & (INTERFACE_USES_SECURITY_MANAGER|INTERFACESAFE_FOR_UNTRUSTED_DATA)) {
2143 WARN("blocked in current safety mode\n");
2144 return VB_E_CANNOT_CREATE_OBJ;
2147 hres = CreateBindCtx(0, &bind_ctx);
2148 if(FAILED(hres))
2149 return hres;
2151 hres = MkParseDisplayName(bind_ctx, V_BSTR(args), &eaten, &mon);
2152 if(SUCCEEDED(hres)) {
2153 hres = IMoniker_BindToObject(mon, bind_ctx, NULL, &IID_IUnknown, (void**)&obj_unk);
2154 IMoniker_Release(mon);
2155 }else {
2156 hres = MK_E_SYNTAX;
2158 IBindCtx_Release(bind_ctx);
2159 if(FAILED(hres))
2160 return hres;
2162 hres = set_object_site(This->ctx, obj_unk);
2163 if(FAILED(hres)) {
2164 IUnknown_Release(obj_unk);
2165 return hres;
2168 hres = IUnknown_QueryInterface(obj_unk, &IID_IDispatch, (void**)&disp);
2169 if(SUCCEEDED(hres)) {
2170 if(res) {
2171 V_VT(res) = VT_DISPATCH;
2172 V_DISPATCH(res) = disp;
2173 }else {
2174 IDispatch_Release(disp);
2176 }else {
2177 FIXME("object does not support IDispatch\n");
2180 return hres;
2183 static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2185 FIXME("\n");
2186 return E_NOTIMPL;
2189 static HRESULT Global_DateDiff(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2191 FIXME("\n");
2192 return E_NOTIMPL;
2195 static HRESULT Global_DatePart(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2197 FIXME("\n");
2198 return E_NOTIMPL;
2201 static HRESULT Global_TypeName(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2203 TRACE("(%s)\n", debugstr_variant(arg));
2205 assert(args_cnt == 1);
2207 if (V_ISARRAY(arg))
2208 return return_string(res, L"Variant()");
2210 switch(V_VT(arg)) {
2211 case VT_UI1:
2212 return return_string(res, L"Byte");
2213 case VT_I2:
2214 return return_string(res, L"Integer");
2215 case VT_I4:
2216 return return_string(res, L"Long");
2217 case VT_R4:
2218 return return_string(res, L"Single");
2219 case VT_R8:
2220 return return_string(res, L"Double");
2221 case VT_CY:
2222 return return_string(res, L"Currency");
2223 case VT_DECIMAL:
2224 return return_string(res, L"Decimal");
2225 case VT_DATE:
2226 return return_string(res, L"Date");
2227 case VT_BSTR:
2228 return return_string(res, L"String");
2229 case VT_BOOL:
2230 return return_string(res, L"Boolean");
2231 case VT_EMPTY:
2232 return return_string(res, L"Empty");
2233 case VT_NULL:
2234 return return_string(res, L"Null");
2235 default:
2236 FIXME("arg %s not supported\n", debugstr_variant(arg));
2237 return E_NOTIMPL;
2241 static HRESULT Global_Array(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2243 SAFEARRAYBOUND bounds;
2244 SAFEARRAY *sa;
2245 VARIANT *data;
2246 HRESULT hres;
2247 unsigned i;
2249 TRACE("arg_cnt=%u\n", args_cnt);
2251 bounds.lLbound = 0;
2252 bounds.cElements = args_cnt;
2253 sa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
2254 if(!sa)
2255 return E_OUTOFMEMORY;
2257 hres = SafeArrayAccessData(sa, (void**)&data);
2258 if(FAILED(hres)) {
2259 SafeArrayDestroy(sa);
2260 return hres;
2263 for(i=0; i<args_cnt; i++) {
2264 hres = VariantCopyInd(data+i, arg+i);
2265 if(FAILED(hres)) {
2266 SafeArrayUnaccessData(sa);
2267 SafeArrayDestroy(sa);
2268 return hres;
2271 SafeArrayUnaccessData(sa);
2273 if(res) {
2274 V_VT(res) = VT_ARRAY|VT_VARIANT;
2275 V_ARRAY(res) = sa;
2276 }else {
2277 SafeArrayDestroy(sa);
2280 return S_OK;
2283 static HRESULT Global_Erase(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2285 FIXME("\n");
2286 return E_NOTIMPL;
2289 static HRESULT Global_Filter(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2291 FIXME("\n");
2292 return E_NOTIMPL;
2295 static HRESULT Global_Join(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2297 FIXME("\n");
2298 return E_NOTIMPL;
2301 static HRESULT Global_Split(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2303 BSTR str, string, delimiter = NULL;
2304 int count, max, mode, len, start, end, ret, delimiterlen = 1;
2305 int i,*indices = NULL, indices_max = 8;
2306 SAFEARRAYBOUND bounds;
2307 SAFEARRAY *sa = NULL;
2308 VARIANT *data, var;
2309 HRESULT hres = S_OK;
2311 TRACE("%s %u...\n", debugstr_variant(args), args_cnt);
2313 assert(1 <= args_cnt && args_cnt <= 4);
2315 if(V_VT(args) == VT_NULL || (args_cnt > 1 && V_VT(args+1) == VT_NULL) || (args_cnt > 2 && V_VT(args+2) == VT_NULL)
2316 || (args_cnt == 4 && V_VT(args+3) == VT_NULL))
2317 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
2319 if(V_VT(args) != VT_BSTR) {
2320 hres = to_string(args, &string);
2321 if(FAILED(hres))
2322 return hres;
2323 }else {
2324 string = V_BSTR(args);
2327 if(args_cnt > 1) {
2328 if(V_VT(args+1) != VT_BSTR) {
2329 hres = to_string(args+1, &delimiter);
2330 if(FAILED(hres))
2331 goto error;
2332 }else {
2333 delimiter = V_BSTR(args+1);
2335 delimiterlen = SysStringLen(delimiter);
2338 if(args_cnt > 2) {
2339 hres = to_int(args+2, &max);
2340 if(FAILED(hres))
2341 goto error;
2342 if (max < -1) {
2343 hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
2344 goto error;
2346 }else {
2347 max = -1;
2350 if(args_cnt == 4) {
2351 hres = to_int(args+3, &mode);
2352 if(FAILED(hres))
2353 goto error;
2354 if (mode != 0 && mode != 1) {
2355 hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
2356 goto error;
2358 }else {
2359 mode = 0;
2362 start = 0;
2364 len = SysStringLen(string);
2365 count = 0;
2367 indices = heap_alloc( indices_max * sizeof(int));
2368 if(!indices) {
2369 hres = E_OUTOFMEMORY;
2370 goto error;
2373 while(1) {
2374 ret = -1;
2375 if (delimiterlen) {
2376 ret = FindStringOrdinal(FIND_FROMSTART, string + start, len - start,
2377 delimiter ? delimiter : L" ", delimiterlen, mode);
2380 if (ret == -1) {
2381 end = len;
2382 }else {
2383 end = start + ret;
2386 if (count == indices_max) {
2387 indices_max *= 2;
2388 indices = heap_realloc( indices, indices_max * sizeof(int));
2389 if(!indices) {
2390 hres = E_OUTOFMEMORY;
2391 goto error;
2394 indices[count++] = end;
2396 if (ret == -1 || count == max) break;
2397 start = start + ret + delimiterlen;
2398 if (start > len) break;
2401 bounds.lLbound = 0;
2402 bounds.cElements = count;
2403 sa = SafeArrayCreate( VT_VARIANT, 1, &bounds);
2404 if (!sa) {
2405 hres = E_OUTOFMEMORY;
2406 goto error;
2408 hres = SafeArrayAccessData(sa, (void**)&data);
2409 if(FAILED(hres)) {
2410 goto error;
2413 start = 0;
2414 for (i = 0; i < count; i++) {
2415 str = SysAllocStringLen(string + start, indices[i] - start);
2416 if (!str) {
2417 hres = E_OUTOFMEMORY;
2418 break;
2420 V_VT(&var) = VT_BSTR;
2421 V_BSTR(&var) = str;
2423 hres = VariantCopyInd(data+i, &var);
2424 if(FAILED(hres)) {
2425 SafeArrayUnaccessData(sa);
2426 goto error;
2428 start = indices[i]+delimiterlen;
2430 SafeArrayUnaccessData(sa);
2432 error:
2433 if(SUCCEEDED(hres) && res) {
2434 V_VT(res) = VT_ARRAY|VT_VARIANT;
2435 V_ARRAY(res) = sa;
2436 }else {
2437 SafeArrayDestroy(sa);
2440 heap_free(indices);
2441 if(V_VT(args) != VT_BSTR)
2442 SysFreeString(string);
2443 if(args_cnt > 1 && V_VT(args+1) != VT_BSTR)
2444 SysFreeString(delimiter);
2445 return hres;
2448 static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2450 BSTR string, find = NULL, replace = NULL, ret;
2451 int from = 1, cnt = -1, mode = 0;
2452 HRESULT hres = S_OK;
2454 TRACE("%s %s %s %u...\n", debugstr_variant(args), debugstr_variant(args+1), debugstr_variant(args+2), args_cnt);
2456 assert(3 <= args_cnt && args_cnt <= 6);
2458 if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (V_VT(args+2) == VT_NULL)
2459 || (args_cnt >= 4 && V_VT(args+3) == VT_NULL) || (args_cnt >= 5 && V_VT(args+4) == VT_NULL)
2460 || (args_cnt == 6 && V_VT(args+5) == VT_NULL))
2461 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
2464 if(V_VT(args) != VT_BSTR) {
2465 hres = to_string(args, &string);
2466 if(FAILED(hres))
2467 return hres;
2468 }else {
2469 string = V_BSTR(args);
2472 if(V_VT(args+1) != VT_BSTR) {
2473 hres = to_string(args+1, &find);
2474 if(FAILED(hres))
2475 goto error;
2476 }else {
2477 find = V_BSTR(args+1);
2480 if(V_VT(args+2) != VT_BSTR) {
2481 hres = to_string(args+2, &replace);
2482 if(FAILED(hres))
2483 goto error;
2484 }else {
2485 replace = V_BSTR(args+2);
2488 if(args_cnt >= 4) {
2489 hres = to_int(args+3, &from);
2490 if(FAILED(hres))
2491 goto error;
2492 if(from < 1) {
2493 hres = E_INVALIDARG;
2494 goto error;
2498 if(args_cnt >= 5) {
2499 hres = to_int(args+4, &cnt);
2500 if(FAILED(hres))
2501 goto error;
2502 if(cnt < -1) {
2503 hres = E_INVALIDARG;
2504 goto error;
2508 if(args_cnt == 6) {
2509 hres = to_int(args+5, &mode);
2510 if(FAILED(hres))
2511 goto error;
2512 if (mode != 0 && mode != 1) {
2513 hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
2514 goto error;
2518 ret = string_replace(string, find, replace, from - 1, cnt, mode);
2519 if(!ret) {
2520 hres = E_OUTOFMEMORY;
2521 }else if(res) {
2522 V_VT(res) = VT_BSTR;
2523 V_BSTR(res) = ret;
2524 }else {
2525 SysFreeString(ret);
2528 error:
2529 if(V_VT(args) != VT_BSTR)
2530 SysFreeString(string);
2531 if(V_VT(args+1) != VT_BSTR)
2532 SysFreeString(find);
2533 if(V_VT(args+2) != VT_BSTR)
2534 SysFreeString(replace);
2535 return hres;
2538 static HRESULT Global_StrReverse(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2540 WCHAR *ptr1, *ptr2, ch;
2541 BSTR ret;
2542 HRESULT hres;
2544 TRACE("%s\n", debugstr_variant(arg));
2546 hres = to_string(arg, &ret);
2547 if(FAILED(hres))
2548 return hres;
2550 ptr1 = ret;
2551 ptr2 = ret + SysStringLen(ret)-1;
2552 while(ptr1 < ptr2) {
2553 ch = *ptr1;
2554 *ptr1++ = *ptr2;
2555 *ptr2-- = ch;
2558 return return_bstr(res, ret);
2561 static HRESULT Global_InStrRev(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2563 int start = -1, ret = -1, mode = 0;
2564 BSTR str1, str2;
2565 size_t len1, len2;
2566 HRESULT hres;
2568 TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args), debugstr_variant(args+1), args_cnt);
2570 assert(2 <= args_cnt && args_cnt <= 4);
2572 if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL)
2573 || (args_cnt == 4 && V_VT(args+3) == VT_NULL))
2574 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
2576 if(args_cnt == 4) {
2577 hres = to_int(args+3, &mode);
2578 if(FAILED(hres))
2579 return hres;
2580 if (mode != 0 && mode != 1)
2581 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
2584 if(args_cnt >= 3) {
2585 hres = to_int(args+2, &start);
2586 if(FAILED(hres))
2587 return hres;
2588 if(!start || start < -1)
2589 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
2592 if(V_VT(args) != VT_BSTR) {
2593 hres = to_string(args, &str1);
2594 if(FAILED(hres))
2595 return hres;
2597 else
2598 str1 = V_BSTR(args);
2600 if(V_VT(args+1) != VT_BSTR) {
2601 hres = to_string(args+1, &str2);
2602 if(FAILED(hres)) {
2603 if(V_VT(args) != VT_BSTR)
2604 SysFreeString(str1);
2605 return hres;
2608 else
2609 str2 = V_BSTR(args+1);
2611 len1 = SysStringLen(str1);
2612 if(!len1) {
2613 ret = 0;
2614 goto end;
2617 if(start == -1)
2618 start = len1;
2620 len2 = SysStringLen(str2);
2621 if(!len2) {
2622 ret = start;
2623 goto end;
2626 if(start >= len2 && start <= len1) {
2627 ret = FindStringOrdinal(FIND_FROMEND, str1, start,
2628 str2, len2, mode);
2630 ret++;
2632 end:
2633 if(V_VT(args) != VT_BSTR)
2634 SysFreeString(str1);
2635 if(V_VT(args+1) != VT_BSTR)
2636 SysFreeString(str2);
2637 return return_int(res, ret);
2640 static HRESULT Global_LoadPicture(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2642 FIXME("\n");
2643 return E_NOTIMPL;
2646 static HRESULT Global_ScriptEngine(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2648 TRACE("%s\n", debugstr_variant(arg));
2650 assert(args_cnt == 0);
2652 return return_string(res, L"VBScript");
2655 static HRESULT Global_ScriptEngineMajorVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2657 TRACE("%s\n", debugstr_variant(arg));
2659 assert(args_cnt == 0);
2661 return return_int(res, VBSCRIPT_MAJOR_VERSION);
2664 static HRESULT Global_ScriptEngineMinorVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2666 TRACE("%s\n", debugstr_variant(arg));
2668 assert(args_cnt == 0);
2670 return return_int(res, VBSCRIPT_MINOR_VERSION);
2673 static HRESULT Global_ScriptEngineBuildVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2675 TRACE("%s\n", debugstr_variant(arg));
2677 assert(args_cnt == 0);
2679 return return_int(res, VBSCRIPT_BUILD_VERSION);
2682 static HRESULT Global_FormatNumber(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2684 FIXME("\n");
2685 return E_NOTIMPL;
2688 static HRESULT Global_FormatCurrency(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2690 FIXME("\n");
2691 return E_NOTIMPL;
2694 static HRESULT Global_FormatPercent(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2696 FIXME("\n");
2697 return E_NOTIMPL;
2700 static HRESULT Global_FormatDateTime(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2702 FIXME("\n");
2703 return E_NOTIMPL;
2706 static HRESULT Global_WeekdayName(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2708 int weekday, first_day = 1, abbrev = 0;
2709 BSTR ret;
2710 HRESULT hres;
2712 TRACE("\n");
2714 assert(1 <= args_cnt && args_cnt <= 3);
2716 hres = to_int(args, &weekday);
2717 if(FAILED(hres))
2718 return hres;
2720 if(args_cnt > 1) {
2721 hres = to_int(args+1, &abbrev);
2722 if(FAILED(hres))
2723 return hres;
2725 if(args_cnt == 3) {
2726 hres = to_int(args+2, &first_day);
2727 if(FAILED(hres))
2728 return hres;
2732 hres = VarWeekdayName(weekday, abbrev, first_day, 0, &ret);
2733 if(FAILED(hres))
2734 return hres;
2736 return return_bstr(res, ret);
2739 static HRESULT Global_MonthName(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2741 int month, abbrev = 0;
2742 BSTR ret;
2743 HRESULT hres;
2745 TRACE("\n");
2747 assert(args_cnt == 1 || args_cnt == 2);
2749 hres = to_int(args, &month);
2750 if(FAILED(hres))
2751 return hres;
2753 if(args_cnt == 2) {
2754 hres = to_int(args+1, &abbrev);
2755 if(FAILED(hres))
2756 return hres;
2759 hres = VarMonthName(month, abbrev, 0, &ret);
2760 if(FAILED(hres))
2761 return hres;
2763 return return_bstr(res, ret);
2766 static HRESULT Global_Round(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2768 double n;
2769 HRESULT hres;
2771 TRACE("%s\n", debugstr_variant(arg));
2773 if(!res)
2774 return S_OK;
2776 switch(V_VT(arg)) {
2777 case VT_I2:
2778 case VT_I4:
2779 case VT_BOOL:
2780 *res = *arg;
2781 return S_OK;
2782 case VT_R8:
2783 n = V_R8(arg);
2784 break;
2785 default:
2786 hres = to_double(arg, &n);
2787 if(FAILED(hres))
2788 return hres;
2791 return return_double(res, round(n));
2794 static HRESULT Global_Escape(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2796 FIXME("\n");
2797 return E_NOTIMPL;
2800 static HRESULT Global_Unescape(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2802 FIXME("\n");
2803 return E_NOTIMPL;
2806 static HRESULT Global_Eval(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2808 FIXME("\n");
2809 return E_NOTIMPL;
2812 static HRESULT Global_Execute(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2814 FIXME("\n");
2815 return E_NOTIMPL;
2818 static HRESULT Global_ExecuteGlobal(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2820 FIXME("\n");
2821 return E_NOTIMPL;
2824 static HRESULT Global_GetRef(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2826 FIXME("\n");
2827 return E_NOTIMPL;
2830 static HRESULT Global_Err(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2832 TRACE("\n");
2834 if(args_cnt) {
2835 FIXME("Setter not supported\n");
2836 return E_NOTIMPL;
2839 V_VT(res) = VT_DISPATCH;
2840 V_DISPATCH(res) = &This->ctx->err_obj->IDispatch_iface;
2841 IDispatch_AddRef(V_DISPATCH(res));
2842 return S_OK;
2845 static const string_constant_t vbCr = {1, {'\r'}};
2846 static const string_constant_t vbCrLf = {2, {'\r','\n'}};
2847 static const string_constant_t vbNewLine = {2, {'\r','\n'}};
2848 static const string_constant_t vbFormFeed = {1, {0xc}};
2849 static const string_constant_t vbLf = {1, {'\n'}};
2850 static const string_constant_t vbNullChar = {1};
2851 static const string_constant_t vbNullString = {0};
2852 static const string_constant_t vbTab = {1, {'\t'}};
2853 static const string_constant_t vbVerticalTab = {1, {0xb}};
2855 static const builtin_prop_t global_props[] = {
2856 {NULL}, /* no default value */
2857 {L"Abs", Global_Abs, 0, 1},
2858 {L"Array", Global_Array, 0, 0, MAXDWORD},
2859 {L"Asc", Global_Asc, 0, 1},
2860 {L"AscB", Global_AscB, 0, 1},
2861 {L"AscW", Global_AscW, 0, 1},
2862 {L"Atn", Global_Atn, 0, 1},
2863 {L"CBool", Global_CBool, 0, 1},
2864 {L"CByte", Global_CByte, 0, 1},
2865 {L"CCur", Global_CCur, 0, 1},
2866 {L"CDate", Global_CDate, 0, 1},
2867 {L"CDbl", Global_CDbl, 0, 1},
2868 {L"Chr", Global_Chr, 0, 1},
2869 {L"ChrB", Global_ChrB, 0, 1},
2870 {L"ChrW", Global_ChrW, 0, 1},
2871 {L"CInt", Global_CInt, 0, 1},
2872 {L"CLng", Global_CLng, 0, 1},
2873 {L"Cos", Global_Cos, 0, 1},
2874 {L"CreateObject", Global_CreateObject, 0, 1},
2875 {L"CSng", Global_CSng, 0, 1},
2876 {L"CStr", Global_CStr, 0, 1},
2877 {L"Date", Global_Date, 0, 0},
2878 {L"DateAdd", Global_DateAdd, 0, 3},
2879 {L"DateDiff", Global_DateDiff, 0, 3, 5},
2880 {L"DatePart", Global_DatePart, 0, 2, 4},
2881 {L"DateSerial", Global_DateSerial, 0, 3},
2882 {L"DateValue", Global_DateValue, 0, 1},
2883 {L"Day", Global_Day, 0, 1},
2884 {L"Erase", Global_Erase, 0, 1},
2885 {L"Err", Global_Err, BP_GETPUT},
2886 {L"Escape", Global_Escape, 0, 1},
2887 {L"Eval", Global_Eval, 0, 1},
2888 {L"Execute", Global_Execute, 0, 1},
2889 {L"ExecuteGlobal", Global_ExecuteGlobal, 0, 1},
2890 {L"Exp", Global_Exp, 0, 1},
2891 {L"Filter", Global_Filter, 0, 2, 4},
2892 {L"Fix", Global_Fix, 0, 1},
2893 {L"FormatCurrency", Global_FormatCurrency, 0, 1, 5},
2894 {L"FormatDateTime", Global_FormatDateTime, 0, 1, 2},
2895 {L"FormatNumber", Global_FormatNumber, 0, 1, 5},
2896 {L"FormatPercent", Global_FormatPercent, 0, 1, 5},
2897 {L"GetObject", Global_GetObject, 0, 0, 2},
2898 {L"GetRef", Global_GetRef, 0, 1},
2899 {L"Hex", Global_Hex, 0, 1},
2900 {L"Hour", Global_Hour, 0, 1},
2901 {L"InputBox", Global_InputBox, 0, 1, 7},
2902 {L"InStr", Global_InStr, 0, 2, 4},
2903 {L"InStrB", Global_InStrB, 0, 3, 4},
2904 {L"InStrRev", Global_InStrRev, 0, 2, 4},
2905 {L"Int", Global_Int, 0, 1},
2906 {L"IsArray", Global_IsArray, 0, 1},
2907 {L"IsDate", Global_IsDate, 0, 1},
2908 {L"IsEmpty", Global_IsEmpty, 0, 1},
2909 {L"IsNull", Global_IsNull, 0, 1},
2910 {L"IsNumeric", Global_IsNumeric, 0, 1},
2911 {L"IsObject", Global_IsObject, 0, 1},
2912 {L"Join", Global_Join, 0, 1, 2},
2913 {L"LBound", Global_LBound, 0, 1, 2},
2914 {L"LCase", Global_LCase, 0, 1},
2915 {L"Left", Global_Left, 0, 2},
2916 {L"LeftB", Global_LeftB, 0, 2},
2917 {L"Len", Global_Len, 0, 1},
2918 {L"LenB", Global_LenB, 0, 1},
2919 {L"LoadPicture", Global_LoadPicture, 0, 1},
2920 {L"Log", Global_Log, 0, 1},
2921 {L"LTrim", Global_LTrim, 0, 1},
2922 {L"Mid", Global_Mid, 0, 2, 3},
2923 {L"MidB", Global_MidB, 0, 2, 3},
2924 {L"Minute", Global_Minute, 0, 1},
2925 {L"Month", Global_Month, 0, 1},
2926 {L"MonthName", Global_MonthName, 0, 1, 2},
2927 {L"MsgBox", Global_MsgBox, 0, 1, 5},
2928 {L"Now", Global_Now, 0, 0},
2929 {L"Oct", Global_Oct, 0, 1},
2930 {L"Randomize", Global_Randomize, 0, 1},
2931 {L"Replace", Global_Replace, 0, 3, 6},
2932 {L"RGB", Global_RGB, 0, 3},
2933 {L"Right", Global_Right, 0, 2},
2934 {L"RightB", Global_RightB, 0, 2},
2935 {L"Rnd", Global_Rnd, 0, 1},
2936 {L"Round", Global_Round, 0, 1, 2},
2937 {L"RTrim", Global_RTrim, 0, 1},
2938 {L"ScriptEngine", Global_ScriptEngine, 0, 0},
2939 {L"ScriptEngineBuildVersion", Global_ScriptEngineBuildVersion, 0, 0},
2940 {L"ScriptEngineMajorVersion", Global_ScriptEngineMajorVersion, 0, 0},
2941 {L"ScriptEngineMinorVersion", Global_ScriptEngineMinorVersion, 0, 0},
2942 {L"Second", Global_Second, 0, 1},
2943 {L"Sgn", Global_Sgn, 0, 1},
2944 {L"Sin", Global_Sin, 0, 1},
2945 {L"Space", Global_Space, 0, 1},
2946 {L"Split", Global_Split, 0, 1, 4},
2947 {L"Sqr", Global_Sqr, 0, 1},
2948 {L"StrComp", Global_StrComp, 0, 2, 3},
2949 {L"String", Global_String, 0, 0, 2},
2950 {L"StrReverse", Global_StrReverse, 0, 1},
2951 {L"Tan", Global_Tan, 0, 1},
2952 {L"Time", Global_Time, 0, 0},
2953 {L"Timer", Global_Timer, 0, 0},
2954 {L"TimeSerial", Global_TimeSerial, 0, 3},
2955 {L"TimeValue", Global_TimeValue, 0, 1},
2956 {L"Trim", Global_Trim, 0, 1},
2957 {L"TypeName", Global_TypeName, 0, 1},
2958 {L"UBound", Global_UBound, 0, 1, 2},
2959 {L"UCase", Global_UCase, 0, 1},
2960 {L"Unescape", Global_Unescape, 0, 1},
2961 {L"VarType", Global_VarType, 0, 1},
2962 {L"vbAbort", NULL, BP_GET, VT_I2, IDABORT},
2963 {L"vbAbortRetryIgnore", NULL, BP_GET, VT_I2, MB_ABORTRETRYIGNORE},
2964 {L"vbApplicationModal", NULL, BP_GET, VT_I2, MB_APPLMODAL},
2965 {L"vbArray", NULL, BP_GET, VT_I2, VT_ARRAY},
2966 {L"vbBinaryCompare", NULL, BP_GET, VT_I2, 0},
2967 {L"vbBlack", NULL, BP_GET, VT_I4, 0x000000},
2968 {L"vbBlue", NULL, BP_GET, VT_I4, 0xff0000},
2969 {L"vbBoolean", NULL, BP_GET, VT_I2, VT_BOOL},
2970 {L"vbByte", NULL, BP_GET, VT_I2, VT_UI1},
2971 {L"vbCancel", NULL, BP_GET, VT_I2, IDCANCEL},
2972 {L"vbCr", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCr},
2973 {L"vbCritical", NULL, BP_GET, VT_I2, MB_ICONHAND},
2974 {L"vbCrLf", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCrLf},
2975 {L"vbCurrency", NULL, BP_GET, VT_I2, VT_CY},
2976 {L"vbCyan", NULL, BP_GET, VT_I4, 0xffff00},
2977 {L"vbDatabaseCompare", NULL, BP_GET, VT_I2, 2},
2978 {L"vbDataObject", NULL, BP_GET, VT_I2, VT_UNKNOWN},
2979 {L"vbDate", NULL, BP_GET, VT_I2, VT_DATE},
2980 {L"vbDecimal", NULL, BP_GET, VT_I2, VT_DECIMAL},
2981 {L"vbDefaultButton1", NULL, BP_GET, VT_I2, MB_DEFBUTTON1},
2982 {L"vbDefaultButton2", NULL, BP_GET, VT_I2, MB_DEFBUTTON2},
2983 {L"vbDefaultButton3", NULL, BP_GET, VT_I2, MB_DEFBUTTON3},
2984 {L"vbDefaultButton4", NULL, BP_GET, VT_I2, MB_DEFBUTTON4},
2985 {L"vbDouble", NULL, BP_GET, VT_I2, VT_R8},
2986 {L"vbEmpty", NULL, BP_GET, VT_I2, VT_EMPTY},
2987 {L"vbError", NULL, BP_GET, VT_I2, VT_ERROR},
2988 {L"vbExclamation", NULL, BP_GET, VT_I2, MB_ICONEXCLAMATION},
2989 {L"vbFalse", NULL, BP_GET, VT_I2, VARIANT_FALSE},
2990 {L"vbFirstFourDays", NULL, BP_GET, VT_I2, 2},
2991 {L"vbFirstFullWeek", NULL, BP_GET, VT_I2, 3},
2992 {L"vbFirstJan1", NULL, BP_GET, VT_I2, 1},
2993 {L"vbFormFeed", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbFormFeed},
2994 {L"vbFriday", NULL, BP_GET, VT_I2, 6},
2995 {L"vbGeneralDate", NULL, BP_GET, VT_I2, 0},
2996 {L"vbGreen", NULL, BP_GET, VT_I4, 0x00ff00},
2997 {L"vbIgnore", NULL, BP_GET, VT_I2, IDIGNORE},
2998 {L"vbInformation", NULL, BP_GET, VT_I2, MB_ICONASTERISK},
2999 {L"vbInteger", NULL, BP_GET, VT_I2, VT_I2},
3000 {L"vbLf", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbLf},
3001 {L"vbLong", NULL, BP_GET, VT_I2, VT_I4},
3002 {L"vbLongDate", NULL, BP_GET, VT_I2, 1},
3003 {L"vbLongTime", NULL, BP_GET, VT_I2, 3},
3004 {L"vbMagenta", NULL, BP_GET, VT_I4, 0xff00ff},
3005 {L"vbMonday", NULL, BP_GET, VT_I2, 2},
3006 {L"vbMsgBoxHelpButton", NULL, BP_GET, VT_I4, MB_HELP},
3007 {L"vbMsgBoxRight", NULL, BP_GET, VT_I4, MB_RIGHT},
3008 {L"vbMsgBoxRtlReading", NULL, BP_GET, VT_I4, MB_RTLREADING},
3009 {L"vbMsgBoxSetForeground", NULL, BP_GET, VT_I4, MB_SETFOREGROUND},
3010 {L"vbNewLine", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNewLine},
3011 {L"vbNo", NULL, BP_GET, VT_I2, IDNO},
3012 {L"vbNull", NULL, BP_GET, VT_I2, VT_NULL},
3013 {L"vbNullChar", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullChar},
3014 {L"vbNullString", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullString},
3015 {L"vbObject", NULL, BP_GET, VT_I2, VT_DISPATCH},
3016 {L"vbObjectError", NULL, BP_GET, VT_I4, 0x80040000},
3017 {L"vbOK", NULL, BP_GET, VT_I2, IDOK},
3018 {L"vbOKCancel", NULL, BP_GET, VT_I2, MB_OKCANCEL},
3019 {L"vbOKOnly", NULL, BP_GET, VT_I2, MB_OK},
3020 {L"vbQuestion", NULL, BP_GET, VT_I2, MB_ICONQUESTION},
3021 {L"vbRed", NULL, BP_GET, VT_I4, 0x0000ff},
3022 {L"vbRetry", NULL, BP_GET, VT_I2, IDRETRY},
3023 {L"vbRetryCancel", NULL, BP_GET, VT_I2, MB_RETRYCANCEL},
3024 {L"vbSaturday", NULL, BP_GET, VT_I2, 7},
3025 {L"vbShortDate", NULL, BP_GET, VT_I2, 2},
3026 {L"vbShortTime", NULL, BP_GET, VT_I2, 4},
3027 {L"vbSingle", NULL, BP_GET, VT_I2, VT_R4},
3028 {L"vbString", NULL, BP_GET, VT_I2, VT_BSTR},
3029 {L"vbSunday", NULL, BP_GET, VT_I2, 1},
3030 {L"vbSystemModal", NULL, BP_GET, VT_I2, MB_SYSTEMMODAL},
3031 {L"vbTab", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbTab},
3032 {L"vbTextCompare", NULL, BP_GET, VT_I2, 1},
3033 {L"vbThursday", NULL, BP_GET, VT_I2, 5},
3034 {L"vbTrue", NULL, BP_GET, VT_I2, VARIANT_TRUE},
3035 {L"vbTuesday", NULL, BP_GET, VT_I2, 3},
3036 {L"vbUseDefault", NULL, BP_GET, VT_I2, -2},
3037 {L"vbUseSystem", NULL, BP_GET, VT_I2, 0},
3038 {L"vbUseSystemDayOfWeek", NULL, BP_GET, VT_I2, 0},
3039 {L"vbVariant", NULL, BP_GET, VT_I2, VT_VARIANT},
3040 {L"vbVerticalTab", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbVerticalTab},
3041 {L"vbWednesday", NULL, BP_GET, VT_I2, 4},
3042 {L"vbWhite", NULL, BP_GET, VT_I4, 0xffffff},
3043 {L"vbYellow", NULL, BP_GET, VT_I4, 0x00ffff},
3044 {L"vbYes", NULL, BP_GET, VT_I2, IDYES},
3045 {L"vbYesNo", NULL, BP_GET, VT_I2, MB_YESNO},
3046 {L"vbYesNoCancel", NULL, BP_GET, VT_I2, MB_YESNOCANCEL},
3047 {L"Weekday", Global_Weekday, 0, 1, 2},
3048 {L"WeekdayName", Global_WeekdayName, 0, 1, 3},
3049 {L"Year", Global_Year, 0, 1}
3052 static HRESULT err_string_prop(BSTR *prop, VARIANT *args, unsigned args_cnt, VARIANT *res)
3054 BSTR str;
3055 HRESULT hres;
3057 if(!args_cnt)
3058 return return_string(res, *prop ? *prop : L"");
3060 hres = to_string(args, &str);
3061 if(FAILED(hres))
3062 return hres;
3064 SysFreeString(*prop);
3065 *prop = str;
3066 return S_OK;
3069 static HRESULT Err_Description(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
3071 TRACE("\n");
3072 return err_string_prop(&This->ctx->ei.bstrDescription, args, args_cnt, res);
3075 static HRESULT Err_HelpContext(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
3077 TRACE("\n");
3079 if(args_cnt) {
3080 FIXME("setter not implemented\n");
3081 return E_NOTIMPL;
3084 return return_int(res, This->ctx->ei.dwHelpContext);
3087 static HRESULT Err_HelpFile(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
3089 TRACE("\n");
3090 return err_string_prop(&This->ctx->ei.bstrHelpFile, args, args_cnt, res);
3093 static HRESULT Err_Number(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
3095 HRESULT hres;
3097 TRACE("\n");
3099 if(args_cnt) {
3100 FIXME("setter not implemented\n");
3101 return E_NOTIMPL;
3104 hres = This->ctx->ei.scode;
3105 return return_int(res, HRESULT_FACILITY(hres) == FACILITY_VBS ? HRESULT_CODE(hres) : hres);
3108 static HRESULT Err_Source(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
3110 TRACE("\n");
3111 return err_string_prop(&This->ctx->ei.bstrSource, args, args_cnt, res);
3114 static HRESULT Err_Clear(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
3116 TRACE("\n");
3118 clear_ei(&This->ctx->ei);
3119 return S_OK;
3122 static HRESULT Err_Raise(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
3124 BSTR source = NULL, description = NULL, helpfile = NULL;
3125 int code, helpcontext = 0;
3126 HRESULT hres, error;
3128 TRACE("%s %u...\n", debugstr_variant(args), args_cnt);
3130 hres = to_int(args, &code);
3131 if(FAILED(hres))
3132 return hres;
3133 if(code == 0 || code > 0xffff)
3134 return E_INVALIDARG;
3136 if(args_cnt >= 2)
3137 hres = to_string(args + 1, &source);
3138 if(args_cnt >= 3 && SUCCEEDED(hres))
3139 hres = to_string(args + 2, &description);
3140 if(args_cnt >= 4 && SUCCEEDED(hres))
3141 hres = to_string(args + 3, &helpfile);
3142 if(args_cnt >= 5 && SUCCEEDED(hres))
3143 hres = to_int(args + 4, &helpcontext);
3145 if(SUCCEEDED(hres)) {
3146 script_ctx_t *ctx = This->ctx;
3148 error = (code & ~0xffff) ? map_hres(code) : MAKE_VBSERROR(code);
3150 if(source) {
3151 SysFreeString(ctx->ei.bstrSource);
3152 ctx->ei.bstrSource = source;
3154 if(!ctx->ei.bstrSource)
3155 ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR);
3156 if(description) {
3157 SysFreeString(ctx->ei.bstrDescription);
3158 ctx->ei.bstrDescription = description;
3160 if(!ctx->ei.bstrDescription)
3161 ctx->ei.bstrDescription = get_vbscript_error_string(error);
3162 if(helpfile) {
3163 SysFreeString(ctx->ei.bstrHelpFile);
3164 ctx->ei.bstrHelpFile = helpfile;
3166 if(args_cnt >= 5)
3167 ctx->ei.dwHelpContext = helpcontext;
3169 ctx->ei.scode = error;
3170 hres = SCRIPT_E_RECORDED;
3171 }else {
3172 SysFreeString(source);
3173 SysFreeString(description);
3174 SysFreeString(helpfile);
3177 return hres;
3180 static const builtin_prop_t err_props[] = {
3181 {NULL, Err_Number, BP_GETPUT},
3182 {L"Clear", Err_Clear},
3183 {L"Description", Err_Description, BP_GETPUT},
3184 {L"HelpContext", Err_HelpContext, BP_GETPUT},
3185 {L"HelpFile", Err_HelpFile, BP_GETPUT},
3186 {L"Number", Err_Number, BP_GETPUT},
3187 {L"Raise", Err_Raise, 0, 1, 5},
3188 {L"Source", Err_Source, BP_GETPUT}
3191 void detach_global_objects(script_ctx_t *ctx)
3193 if(ctx->err_obj) {
3194 ctx->err_obj->ctx = NULL;
3195 IDispatch_Release(&ctx->err_obj->IDispatch_iface);
3196 ctx->err_obj = NULL;
3199 if(ctx->global_obj) {
3200 ctx->global_obj->ctx = NULL;
3201 IDispatch_Release(&ctx->global_obj->IDispatch_iface);
3202 ctx->global_obj = NULL;
3206 HRESULT init_global(script_ctx_t *ctx)
3208 HRESULT hres;
3210 hres = create_builtin_dispatch(ctx, global_props, ARRAY_SIZE(global_props), &ctx->global_obj);
3211 if(FAILED(hres))
3212 return hres;
3214 return create_builtin_dispatch(ctx, err_props, ARRAY_SIZE(err_props), &ctx->err_obj);