wined3d: Correctly destroy the adapter on format initialization failure in no3d mode.
[wine/zf.git] / dlls / vbscript / global.c
bloba4442960d9eb9cf023b8a26af6353f0f5c239277
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 static const WCHAR emptyW[] = {0};
41 static const WCHAR vbscriptW[] = {'V','B','S','c','r','i','p','t',0};
43 #define BP_GET 1
44 #define BP_GETPUT 2
46 typedef struct {
47 UINT16 len;
48 WCHAR buf[7];
49 } string_constant_t;
51 struct _builtin_prop_t {
52 const WCHAR *name;
53 HRESULT (*proc)(BuiltinDisp*,VARIANT*,unsigned,VARIANT*);
54 DWORD flags;
55 unsigned min_args;
56 UINT_PTR max_args;
59 static inline BuiltinDisp *impl_from_IDispatch(IDispatch *iface)
61 return CONTAINING_RECORD(iface, BuiltinDisp, IDispatch_iface);
64 static HRESULT WINAPI Builtin_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
66 BuiltinDisp *This = impl_from_IDispatch(iface);
68 if(IsEqualGUID(&IID_IUnknown, riid)) {
69 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
70 *ppv = &This->IDispatch_iface;
71 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
72 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
73 *ppv = &This->IDispatch_iface;
74 }else {
75 if(!IsEqualGUID(riid, &IID_IDispatchEx))
76 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
77 *ppv = NULL;
78 return E_NOINTERFACE;
81 IUnknown_AddRef((IUnknown*)*ppv);
82 return S_OK;
85 static ULONG WINAPI Builtin_AddRef(IDispatch *iface)
87 BuiltinDisp *This = impl_from_IDispatch(iface);
88 LONG ref = InterlockedIncrement(&This->ref);
90 TRACE("(%p) ref=%d\n", This, ref);
92 return ref;
95 static ULONG WINAPI Builtin_Release(IDispatch *iface)
97 BuiltinDisp *This = impl_from_IDispatch(iface);
98 LONG ref = InterlockedDecrement(&This->ref);
100 TRACE("(%p) ref=%d\n", This, ref);
102 if(!ref) {
103 assert(!This->ctx);
104 heap_free(This);
107 return ref;
110 static HRESULT WINAPI Builtin_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
112 BuiltinDisp *This = impl_from_IDispatch(iface);
113 TRACE("(%p)->(%p)\n", This, pctinfo);
114 *pctinfo = 0;
115 return S_OK;
118 static HRESULT WINAPI Builtin_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
120 BuiltinDisp *This = impl_from_IDispatch(iface);
121 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
122 return DISP_E_BADINDEX;
125 HRESULT get_builtin_id(BuiltinDisp *disp, const WCHAR *name, DISPID *id)
127 size_t min = 1, max = disp->member_cnt - 1, i;
128 int r;
130 while(min <= max) {
131 i = (min + max) / 2;
132 r = wcsicmp(disp->members[i].name, name);
133 if(!r) {
134 *id = i;
135 return S_OK;
137 if(r < 0)
138 min = i+1;
139 else
140 max = i-1;
143 return DISP_E_MEMBERNOTFOUND;
147 static HRESULT WINAPI Builtin_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *names, UINT name_cnt,
148 LCID lcid, DISPID *ids)
150 BuiltinDisp *This = impl_from_IDispatch(iface);
151 unsigned i;
152 HRESULT hres;
154 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), names, name_cnt, lcid, ids);
156 if(!This->ctx) {
157 FIXME("NULL context\n");
158 return E_UNEXPECTED;
161 for(i = 0; i < name_cnt; i++) {
162 hres = get_builtin_id(This, names[i], &ids[i]);
163 if(FAILED(hres))
164 return hres;
167 return S_OK;
170 static HRESULT WINAPI Builtin_Invoke(IDispatch *iface, DISPID id, REFIID riid, LCID lcid, WORD flags,
171 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, UINT *err)
173 BuiltinDisp *This = impl_from_IDispatch(iface);
174 const builtin_prop_t *prop;
175 VARIANT args_buf[8], *args;
176 unsigned argn, i;
177 HRESULT hres;
179 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, id, debugstr_guid(riid), lcid, flags, dp, res, ei, err);
181 if(!This->ctx) {
182 FIXME("NULL context\n");
183 return E_UNEXPECTED;
186 if(id >= This->member_cnt || (!This->members[id].proc && !This->members[id].flags))
187 return DISP_E_MEMBERNOTFOUND;
188 prop = This->members + id;
190 switch(flags) {
191 case DISPATCH_PROPERTYGET:
192 if(!(prop->flags & (BP_GET|BP_GETPUT))) {
193 FIXME("property does not support DISPATCH_PROPERTYGET\n");
194 return E_FAIL;
196 break;
197 case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
198 if(!prop->proc && prop->flags == BP_GET) {
199 const int vt = prop->min_args, val = prop->max_args;
200 switch(vt) {
201 case VT_I2:
202 V_VT(res) = VT_I2;
203 V_I2(res) = val;
204 break;
205 case VT_I4:
206 V_VT(res) = VT_I4;
207 V_I4(res) = val;
208 break;
209 case VT_BSTR: {
210 const string_constant_t *str = (const string_constant_t*)prop->max_args;
211 BSTR ret;
213 ret = SysAllocStringLen(str->buf, str->len);
214 if(!ret)
215 return E_OUTOFMEMORY;
217 V_VT(res) = VT_BSTR;
218 V_BSTR(res) = ret;
219 break;
221 DEFAULT_UNREACHABLE;
223 return S_OK;
225 break;
226 case DISPATCH_METHOD:
227 if(prop->flags & (BP_GET|BP_GETPUT)) {
228 FIXME("Call on property\n");
229 return E_FAIL;
231 break;
232 case DISPATCH_PROPERTYPUT:
233 if(!(prop->flags & BP_GETPUT)) {
234 FIXME("property does not support DISPATCH_PROPERTYPUT\n");
235 return E_FAIL;
238 FIXME("call put\n");
239 return E_NOTIMPL;
240 default:
241 FIXME("unsupported flags %x\n", flags);
242 return E_NOTIMPL;
245 argn = arg_cnt(dp);
247 if(argn < prop->min_args || argn > (prop->max_args ? prop->max_args : prop->min_args)) {
248 WARN("invalid number of arguments\n");
249 return MAKE_VBSERROR(VBSE_FUNC_ARITY_MISMATCH);
252 if(argn <= ARRAY_SIZE(args_buf)) {
253 args = args_buf;
254 }else {
255 args = heap_alloc(argn * sizeof(*args));
256 if(!args)
257 return E_OUTOFMEMORY;
260 for(i=0; i < argn; i++) {
261 if(V_VT(dp->rgvarg+dp->cArgs-i-1) == (VT_BYREF|VT_VARIANT))
262 args[i] = *V_VARIANTREF(dp->rgvarg+dp->cArgs-i-1);
263 else
264 args[i] = dp->rgvarg[dp->cArgs-i-1];
267 hres = prop->proc(This, args, dp->cArgs, res);
268 if(args != args_buf)
269 heap_free(args);
270 return hres;
273 static const IDispatchVtbl BuiltinDispVtbl = {
274 Builtin_QueryInterface,
275 Builtin_AddRef,
276 Builtin_Release,
277 Builtin_GetTypeInfoCount,
278 Builtin_GetTypeInfo,
279 Builtin_GetIDsOfNames,
280 Builtin_Invoke
283 static HRESULT create_builtin_dispatch(script_ctx_t *ctx, const builtin_prop_t *members, size_t member_cnt, BuiltinDisp **ret)
285 BuiltinDisp *disp;
287 if(!(disp = heap_alloc(sizeof(*disp))))
288 return E_OUTOFMEMORY;
290 disp->IDispatch_iface.lpVtbl = &BuiltinDispVtbl;
291 disp->ref = 1;
292 disp->members = members;
293 disp->member_cnt = member_cnt;
294 disp->ctx = ctx;
296 *ret = disp;
297 return S_OK;
300 static IInternetHostSecurityManager *get_sec_mgr(script_ctx_t *ctx)
302 IInternetHostSecurityManager *secmgr;
303 IServiceProvider *sp;
304 HRESULT hres;
306 if(!ctx->site)
307 return NULL;
309 if(ctx->secmgr)
310 return ctx->secmgr;
312 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp);
313 if(FAILED(hres))
314 return NULL;
316 hres = IServiceProvider_QueryService(sp, &SID_SInternetHostSecurityManager, &IID_IInternetHostSecurityManager,
317 (void**)&secmgr);
318 IServiceProvider_Release(sp);
319 if(FAILED(hres))
320 return NULL;
322 return ctx->secmgr = secmgr;
325 static HRESULT return_string(VARIANT *res, const WCHAR *str)
327 BSTR ret;
329 if(!res)
330 return S_OK;
332 ret = SysAllocString(str);
333 if(!ret)
334 return E_OUTOFMEMORY;
336 V_VT(res) = VT_BSTR;
337 V_BSTR(res) = ret;
338 return S_OK;
341 static HRESULT return_bstr(VARIANT *res, BSTR str)
343 if(res) {
344 V_VT(res) = VT_BSTR;
345 V_BSTR(res) = str;
346 }else {
347 SysFreeString(str);
349 return S_OK;
352 static HRESULT return_bool(VARIANT *res, BOOL val)
354 if(res) {
355 V_VT(res) = VT_BOOL;
356 V_BOOL(res) = val ? VARIANT_TRUE : VARIANT_FALSE;
358 return S_OK;
361 static HRESULT return_short(VARIANT *res, short val)
363 if(res) {
364 V_VT(res) = VT_I2;
365 V_I2(res) = val;
368 return S_OK;
371 static HRESULT return_int(VARIANT *res, int val)
373 if(res) {
374 V_VT(res) = VT_I4;
375 V_I4(res) = val;
378 return S_OK;
381 static inline HRESULT return_double(VARIANT *res, double val)
383 if(res) {
384 V_VT(res) = VT_R8;
385 V_R8(res) = val;
388 return S_OK;
391 static inline HRESULT return_float(VARIANT *res, float val)
393 if(res) {
394 V_VT(res) = VT_R4;
395 V_R4(res) = val;
398 return S_OK;
401 static inline HRESULT return_null(VARIANT *res)
403 if(res)
404 V_VT(res) = VT_NULL;
405 return S_OK;
408 static inline HRESULT return_date(VARIANT *res, double date)
410 if(res) {
411 V_VT(res) = VT_DATE;
412 V_DATE(res) = date;
414 return S_OK;
417 HRESULT to_int(VARIANT *v, int *ret)
419 VARIANT r;
420 HRESULT hres;
422 V_VT(&r) = VT_EMPTY;
423 hres = VariantChangeType(&r, v, 0, VT_I4);
424 if(FAILED(hres))
425 return hres;
427 *ret = V_I4(&r);
428 return S_OK;
431 static HRESULT to_double(VARIANT *v, double *ret)
433 VARIANT dst;
434 HRESULT hres;
436 V_VT(&dst) = VT_EMPTY;
437 hres = VariantChangeType(&dst, v, 0, VT_R8);
438 if(FAILED(hres))
439 return hres;
441 *ret = V_R8(&dst);
442 return S_OK;
445 static HRESULT to_string(VARIANT *v, BSTR *ret)
447 VARIANT dst;
448 HRESULT hres;
450 V_VT(&dst) = VT_EMPTY;
451 hres = VariantChangeType(&dst, v, VARIANT_LOCALBOOL, VT_BSTR);
452 if(FAILED(hres))
453 return hres;
455 *ret = V_BSTR(&dst);
456 return S_OK;
459 static HRESULT to_system_time(VARIANT *v, SYSTEMTIME *st)
461 VARIANT date;
462 HRESULT hres;
464 V_VT(&date) = VT_EMPTY;
465 hres = VariantChangeType(&date, v, 0, VT_DATE);
466 if(FAILED(hres))
467 return hres;
469 return VariantTimeToSystemTime(V_DATE(&date), st);
472 static HRESULT set_object_site(script_ctx_t *ctx, IUnknown *obj)
474 IObjectWithSite *obj_site;
475 IUnknown *ax_site;
476 HRESULT hres;
478 hres = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (void**)&obj_site);
479 if(FAILED(hres))
480 return S_OK;
482 ax_site = create_ax_site(ctx);
483 if(ax_site) {
484 hres = IObjectWithSite_SetSite(obj_site, ax_site);
485 IUnknown_Release(ax_site);
487 else
488 hres = E_OUTOFMEMORY;
489 IObjectWithSite_Release(obj_site);
490 return hres;
493 static IUnknown *create_object(script_ctx_t *ctx, const WCHAR *progid)
495 IInternetHostSecurityManager *secmgr = NULL;
496 struct CONFIRMSAFETY cs;
497 IClassFactoryEx *cfex;
498 IClassFactory *cf;
499 DWORD policy_size;
500 BYTE *bpolicy;
501 IUnknown *obj;
502 DWORD policy;
503 GUID guid;
504 HRESULT hres;
506 hres = CLSIDFromProgID(progid, &guid);
507 if(FAILED(hres))
508 return NULL;
510 TRACE("GUID %s\n", debugstr_guid(&guid));
512 if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
513 secmgr = get_sec_mgr(ctx);
514 if(!secmgr)
515 return NULL;
517 policy = 0;
518 hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN,
519 (BYTE*)&policy, sizeof(policy), (BYTE*)&guid, sizeof(GUID), 0, 0);
520 if(FAILED(hres) || policy != URLPOLICY_ALLOW)
521 return NULL;
524 hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
525 if(FAILED(hres))
526 return NULL;
528 hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
529 if(SUCCEEDED(hres)) {
530 FIXME("Use IClassFactoryEx\n");
531 IClassFactoryEx_Release(cfex);
534 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
535 if(FAILED(hres))
536 return NULL;
538 if(secmgr) {
539 cs.clsid = guid;
540 cs.pUnk = obj;
541 cs.dwFlags = 0;
542 hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
543 &bpolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
544 if(SUCCEEDED(hres)) {
545 policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW;
546 CoTaskMemFree(bpolicy);
549 if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
550 IUnknown_Release(obj);
551 return NULL;
555 hres = set_object_site(ctx, obj);
556 if(FAILED(hres)) {
557 IUnknown_Release(obj);
558 return NULL;
561 return obj;
564 static HRESULT show_msgbox(script_ctx_t *ctx, BSTR prompt, unsigned type, BSTR orig_title, VARIANT *res)
566 SCRIPTUICHANDLING uic_handling = SCRIPTUICHANDLING_ALLOW;
567 IActiveScriptSiteUIControl *ui_control;
568 IActiveScriptSiteWindow *acts_window;
569 WCHAR *title_buf = NULL;
570 const WCHAR *title;
571 HWND hwnd = NULL;
572 int ret = 0;
573 HRESULT hres;
575 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteUIControl, (void**)&ui_control);
576 if(SUCCEEDED(hres)) {
577 hres = IActiveScriptSiteUIControl_GetUIBehavior(ui_control, SCRIPTUICITEM_MSGBOX, &uic_handling);
578 IActiveScriptSiteUIControl_Release(ui_control);
579 if(FAILED(hres))
580 uic_handling = SCRIPTUICHANDLING_ALLOW;
583 switch(uic_handling) {
584 case SCRIPTUICHANDLING_ALLOW:
585 break;
586 case SCRIPTUICHANDLING_NOUIDEFAULT:
587 return return_short(res, 0);
588 default:
589 FIXME("blocked\n");
590 return E_FAIL;
593 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteWindow, (void**)&acts_window);
594 if(FAILED(hres)) {
595 FIXME("No IActiveScriptSiteWindow\n");
596 return hres;
599 if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
600 if(orig_title && *orig_title) {
601 WCHAR *ptr;
603 title = title_buf = heap_alloc(sizeof(vbscriptW) + (lstrlenW(orig_title)+2)*sizeof(WCHAR));
604 if(!title)
605 return E_OUTOFMEMORY;
607 memcpy(title_buf, vbscriptW, sizeof(vbscriptW));
608 ptr = title_buf + ARRAY_SIZE(vbscriptW)-1;
610 *ptr++ = ':';
611 *ptr++ = ' ';
612 lstrcpyW(ptr, orig_title);
613 }else {
614 title = vbscriptW;
616 }else {
617 title = orig_title ? orig_title : emptyW;
620 hres = IActiveScriptSiteWindow_GetWindow(acts_window, &hwnd);
621 if(SUCCEEDED(hres)) {
622 hres = IActiveScriptSiteWindow_EnableModeless(acts_window, FALSE);
623 if(SUCCEEDED(hres)) {
624 ret = MessageBoxW(hwnd, prompt, title, type);
625 hres = IActiveScriptSiteWindow_EnableModeless(acts_window, TRUE);
629 heap_free(title_buf);
630 IActiveScriptSiteWindow_Release(acts_window);
631 if(FAILED(hres)) {
632 FIXME("failed: %08x\n", hres);
633 return hres;
636 return return_short(res, ret);
639 static HRESULT Global_CCur(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
641 VARIANT v;
642 HRESULT hres;
644 TRACE("%s\n", debugstr_variant(arg));
646 assert(args_cnt == 1);
648 V_VT(&v) = VT_EMPTY;
649 hres = VariantChangeType(&v, arg, 0, VT_CY);
650 if(FAILED(hres))
651 return hres;
653 if(!res) {
654 VariantClear(&v);
655 return DISP_E_BADVARTYPE;
658 *res = v;
659 return S_OK;
662 static HRESULT Global_CInt(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
664 VARIANT v;
665 HRESULT hres;
667 TRACE("%s\n", debugstr_variant(arg));
669 assert(args_cnt == 1);
671 V_VT(&v) = VT_EMPTY;
672 hres = VariantChangeType(&v, arg, 0, VT_I2);
673 if(FAILED(hres))
674 return hres;
676 if(!res)
677 return DISP_E_BADVARTYPE;
678 else {
679 *res = v;
680 return S_OK;
684 static HRESULT Global_CLng(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
686 int i;
687 HRESULT hres;
689 TRACE("%s\n", debugstr_variant(arg));
691 assert(args_cnt == 1);
693 hres = to_int(arg, &i);
694 if(FAILED(hres))
695 return hres;
696 if(!res)
697 return DISP_E_BADVARTYPE;
699 return return_int(res, i);
702 static HRESULT Global_CBool(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
704 VARIANT v;
705 HRESULT hres;
707 TRACE("%s\n", debugstr_variant(arg));
709 assert(args_cnt == 1);
711 V_VT(&v) = VT_EMPTY;
712 hres = VariantChangeType(&v, arg, VARIANT_LOCALBOOL, VT_BOOL);
713 if(FAILED(hres))
714 return hres;
716 if(res)
717 *res = v;
718 else
719 VariantClear(&v);
720 return S_OK;
723 static HRESULT Global_CByte(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
725 VARIANT v;
726 HRESULT hres;
728 TRACE("%s\n", debugstr_variant(arg));
730 assert(args_cnt == 1);
732 V_VT(&v) = VT_EMPTY;
733 hres = VariantChangeType(&v, arg, VARIANT_LOCALBOOL, VT_UI1);
734 if(FAILED(hres))
735 return hres;
737 if(!res) {
738 VariantClear(&v);
739 return DISP_E_BADVARTYPE;
742 *res = v;
743 return S_OK;
746 static HRESULT Global_CDate(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
748 FIXME("\n");
749 return E_NOTIMPL;
752 static HRESULT Global_CDbl(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
754 VARIANT v;
755 HRESULT hres;
757 TRACE("%s\n", debugstr_variant(arg));
759 assert(args_cnt == 1);
761 V_VT(&v) = VT_EMPTY;
762 hres = VariantChangeType(&v, arg, 0, VT_R8);
763 if(FAILED(hres))
764 return hres;
766 if(!res)
767 return DISP_E_BADVARTYPE;
768 else {
769 *res = v;
770 return S_OK;
774 static HRESULT Global_CSng(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
776 VARIANT v;
777 HRESULT hres;
779 TRACE("%s\n", debugstr_variant(arg));
781 assert(args_cnt == 1);
783 V_VT(&v) = VT_EMPTY;
784 hres = VariantChangeType(&v, arg, 0, VT_R4);
785 if(FAILED(hres))
786 return hres;
788 if(!res)
789 return DISP_E_BADVARTYPE;
791 *res = v;
792 return S_OK;
795 static HRESULT Global_CStr(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
797 BSTR str;
798 HRESULT hres;
800 TRACE("%s\n", debugstr_variant(arg));
802 if(V_VT(arg) == VT_NULL)
803 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
805 hres = to_string(arg, &str);
806 if(FAILED(hres))
807 return hres;
809 return return_bstr(res, str);
812 static inline WCHAR hex_char(unsigned n)
814 return n < 10 ? '0'+n : 'A'+n-10;
817 static HRESULT Global_Hex(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
819 WCHAR buf[17], *ptr;
820 DWORD n;
821 HRESULT hres;
822 int ret;
824 TRACE("%s\n", debugstr_variant(arg));
826 switch(V_VT(arg)) {
827 case VT_I2:
828 n = (WORD)V_I2(arg);
829 break;
830 case VT_NULL:
831 if(res)
832 V_VT(res) = VT_NULL;
833 return S_OK;
834 default:
835 hres = to_int(arg, &ret);
836 if(FAILED(hres))
837 return hres;
838 else
839 n = ret;
842 buf[16] = 0;
843 ptr = buf+15;
845 if(n) {
846 do {
847 *ptr-- = hex_char(n & 0xf);
848 n >>= 4;
849 }while(n);
850 ptr++;
851 }else {
852 *ptr = '0';
855 return return_string(res, ptr);
858 static HRESULT Global_Oct(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
860 HRESULT hres;
861 WCHAR buf[23], *ptr;
862 DWORD n;
863 int ret;
865 TRACE("%s\n", debugstr_variant(arg));
867 switch(V_VT(arg)) {
868 case VT_I2:
869 n = (WORD)V_I2(arg);
870 break;
871 case VT_NULL:
872 if(res)
873 V_VT(res) = VT_NULL;
874 return S_OK;
875 default:
876 hres = to_int(arg, &ret);
877 if(FAILED(hres))
878 return hres;
879 else
880 n = ret;
883 buf[22] = 0;
884 ptr = buf + 21;
886 if(n) {
887 do {
888 *ptr-- = '0' + (n & 0x7);
889 n >>= 3;
890 }while(n);
891 ptr++;
892 }else {
893 *ptr = '0';
896 return return_string(res, ptr);
899 static HRESULT Global_VarType(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
901 VARTYPE vt;
903 TRACE("(%s)\n", debugstr_variant(arg));
905 assert(args_cnt == 1);
907 vt = V_VT(arg) & ~VT_BYREF;
908 if(vt & ~(VT_TYPEMASK | VT_ARRAY)) {
909 FIXME("not supported %s\n", debugstr_variant(arg));
910 return E_NOTIMPL;
913 return return_short(res, vt);
916 static HRESULT Global_IsDate(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
918 FIXME("\n");
919 return E_NOTIMPL;
922 static HRESULT Global_IsEmpty(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
924 TRACE("(%s)\n", debugstr_variant(arg));
926 assert(args_cnt == 1);
928 if(res) {
929 V_VT(res) = VT_BOOL;
930 V_BOOL(res) = V_VT(arg) == VT_EMPTY ? VARIANT_TRUE : VARIANT_FALSE;
932 return S_OK;
935 static HRESULT Global_IsNull(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
937 TRACE("(%s)\n", debugstr_variant(arg));
939 assert(args_cnt == 1);
941 if(res) {
942 V_VT(res) = VT_BOOL;
943 V_BOOL(res) = V_VT(arg) == VT_NULL ? VARIANT_TRUE : VARIANT_FALSE;
945 return S_OK;
948 static HRESULT Global_IsNumeric(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
950 HRESULT hres;
951 double d;
953 TRACE("(%s)\n", debugstr_variant(arg));
955 assert(args_cnt == 1);
957 hres = to_double(arg, &d);
959 return return_bool(res, SUCCEEDED(hres));
962 static HRESULT Global_IsArray(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
964 FIXME("\n");
965 return E_NOTIMPL;
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 start, ret;
1628 HRESULT hres;
1630 TRACE("\n");
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 FIXME("unsupported compare argument %s\n", debugstr_variant(args));
1647 return E_NOTIMPL;
1648 DEFAULT_UNREACHABLE;
1651 if(startv) {
1652 hres = to_int(startv, &start);
1653 if(FAILED(hres))
1654 return hres;
1655 if(--start < 0) {
1656 FIXME("start %d\n", start);
1657 return E_FAIL;
1659 }else {
1660 start = 0;
1663 if(V_VT(str1v) == VT_NULL || V_VT(str2v) == VT_NULL)
1664 return return_null(res);
1666 if(V_VT(str1v) != VT_BSTR) {
1667 FIXME("Unsupported str1 type %s\n", debugstr_variant(str1v));
1668 return E_NOTIMPL;
1670 str1 = V_BSTR(str1v);
1672 if(V_VT(str2v) != VT_BSTR) {
1673 FIXME("Unsupported str2 type %s\n", debugstr_variant(str2v));
1674 return E_NOTIMPL;
1676 str2 = V_BSTR(str2v);
1678 if(start < SysStringLen(str1)) {
1679 WCHAR *ptr;
1681 ptr = wcsstr(str1+start, str2);
1682 ret = ptr ? ptr-str1+1 : 0;
1683 }else {
1684 ret = 0;
1687 return return_int(res, ret);
1690 static HRESULT Global_InStrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1692 FIXME("\n");
1693 return E_NOTIMPL;
1696 static HRESULT Global_AscB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1698 FIXME("\n");
1699 return E_NOTIMPL;
1702 static HRESULT Global_ChrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1704 FIXME("\n");
1705 return E_NOTIMPL;
1708 static HRESULT Global_Asc(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1710 BSTR conv_str = NULL, str;
1711 HRESULT hres = S_OK;
1713 TRACE("(%s)\n", debugstr_variant(arg));
1715 switch(V_VT(arg)) {
1716 case VT_NULL:
1717 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1718 case VT_EMPTY:
1719 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1720 case VT_BSTR:
1721 str = V_BSTR(arg);
1722 break;
1723 default:
1724 hres = to_string(arg, &conv_str);
1725 if(FAILED(hres))
1726 return hres;
1727 str = conv_str;
1730 if(!SysStringLen(str) || *str >= 0x100)
1731 hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1732 else if(res)
1733 hres = return_short(res, *str);
1734 SysFreeString(conv_str);
1735 return hres;
1738 /* The function supports only single-byte and double-byte character sets. It
1739 * ignores language specified by IActiveScriptSite::GetLCID. The argument needs
1740 * to be in range of short or unsigned short. */
1741 static HRESULT Global_Chr(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1743 int cp, c, len = 0;
1744 CPINFO cpi;
1745 WCHAR ch;
1746 char buf[2];
1747 HRESULT hres;
1749 TRACE("%s\n", debugstr_variant(arg));
1751 hres = to_int(arg, &c);
1752 if(FAILED(hres))
1753 return hres;
1755 cp = GetACP();
1756 if(!GetCPInfo(cp, &cpi))
1757 cpi.MaxCharSize = 1;
1759 if((c!=(short)c && c!=(unsigned short)c) ||
1760 (unsigned short)c>=(cpi.MaxCharSize>1 ? 0x10000 : 0x100)) {
1761 WARN("invalid arg %d\n", c);
1762 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1765 if(c>>8)
1766 buf[len++] = c>>8;
1767 if(!len || IsDBCSLeadByteEx(cp, buf[0]))
1768 buf[len++] = c;
1769 if(!MultiByteToWideChar(CP_ACP, 0, buf, len, &ch, 1)) {
1770 WARN("invalid arg %d, cp %d\n", c, cp);
1771 return E_FAIL;
1774 if(res) {
1775 V_VT(res) = VT_BSTR;
1776 V_BSTR(res) = SysAllocStringLen(&ch, 1);
1777 if(!V_BSTR(res))
1778 return E_OUTOFMEMORY;
1780 return S_OK;
1783 static HRESULT Global_AscW(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1785 FIXME("\n");
1786 return E_NOTIMPL;
1789 static HRESULT Global_ChrW(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1791 FIXME("\n");
1792 return E_NOTIMPL;
1795 static HRESULT Global_Abs(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1797 HRESULT hres;
1798 VARIANT dst;
1800 TRACE("(%s)\n", debugstr_variant(arg));
1802 assert(args_cnt == 1);
1804 hres = VarAbs(arg, &dst);
1805 if(FAILED(hres))
1806 return hres;
1808 if (res)
1809 *res = dst;
1810 else
1811 VariantClear(&dst);
1813 return S_OK;
1816 static HRESULT Global_Fix(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1818 HRESULT hres;
1819 VARIANT dst;
1821 TRACE("(%s)\n", debugstr_variant(arg));
1823 assert(args_cnt == 1);
1825 hres = VarFix(arg, &dst);
1826 if(FAILED(hres))
1827 return hres;
1829 if (res)
1830 *res = dst;
1831 else
1832 VariantClear(&dst);
1834 return S_OK;
1837 static HRESULT Global_Int(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1839 HRESULT hres;
1840 VARIANT dst;
1842 TRACE("(%s)\n", debugstr_variant(arg));
1844 assert(args_cnt == 1);
1846 hres = VarInt(arg, &dst);
1847 if(FAILED(hres))
1848 return hres;
1850 if (res)
1851 *res = dst;
1852 else
1853 VariantClear(&dst);
1855 return S_OK;
1858 static HRESULT Global_Sgn(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1860 double v;
1861 short val;
1862 HRESULT hres;
1864 TRACE("(%s)\n", debugstr_variant(arg));
1866 assert(args_cnt == 1);
1868 if(V_VT(arg) == VT_NULL)
1869 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1871 hres = to_double(arg, &v);
1872 if (FAILED(hres))
1873 return hres;
1875 val = v == 0 ? 0 : (v > 0 ? 1 : -1);
1876 return return_short(res, val);
1879 static HRESULT Global_Now(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1881 SYSTEMTIME lt;
1882 double date;
1884 TRACE("\n");
1886 GetLocalTime(&lt);
1887 SystemTimeToVariantTime(&lt, &date);
1888 return return_date(res, date);
1891 static HRESULT Global_Date(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1893 SYSTEMTIME lt;
1894 UDATE ud;
1895 DATE date;
1896 HRESULT hres;
1898 TRACE("\n");
1900 GetLocalTime(&lt);
1901 ud.st = lt;
1902 ud.wDayOfYear = 0;
1903 hres = VarDateFromUdateEx(&ud, 0, VAR_DATEVALUEONLY, &date);
1904 if(FAILED(hres))
1905 return hres;
1906 return return_date(res, date);
1909 static HRESULT Global_Time(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1911 SYSTEMTIME lt;
1912 UDATE ud;
1913 DATE time;
1914 HRESULT hres;
1916 TRACE("\n");
1918 GetLocalTime(&lt);
1919 ud.st = lt;
1920 ud.wDayOfYear = 0;
1921 hres = VarDateFromUdateEx(&ud, 0, VAR_TIMEVALUEONLY, &time);
1922 if(FAILED(hres))
1923 return hres;
1924 return return_date(res, time);
1927 static HRESULT Global_Day(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1929 SYSTEMTIME st;
1930 HRESULT hres;
1932 TRACE("(%s)\n", debugstr_variant(arg));
1934 hres = to_system_time(arg, &st);
1935 return FAILED(hres) ? hres : return_short(res, st.wDay);
1938 static HRESULT Global_Month(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1940 SYSTEMTIME st;
1941 HRESULT hres;
1943 TRACE("(%s)\n", debugstr_variant(arg));
1945 hres = to_system_time(arg, &st);
1946 return FAILED(hres) ? hres : return_short(res, st.wMonth);
1949 static HRESULT Global_Weekday(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1951 FIXME("\n");
1952 return E_NOTIMPL;
1955 static HRESULT Global_Year(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1957 SYSTEMTIME st;
1958 HRESULT hres;
1960 TRACE("(%s)\n", debugstr_variant(arg));
1962 hres = to_system_time(arg, &st);
1963 return FAILED(hres) ? hres : return_short(res, st.wYear);
1966 static HRESULT Global_Hour(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1968 SYSTEMTIME st;
1969 HRESULT hres;
1971 TRACE("(%s)\n", debugstr_variant(arg));
1973 hres = to_system_time(arg, &st);
1974 return FAILED(hres) ? hres : return_short(res, st.wHour);
1977 static HRESULT Global_Minute(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1979 SYSTEMTIME st;
1980 HRESULT hres;
1982 TRACE("(%s)\n", debugstr_variant(arg));
1984 hres = to_system_time(arg, &st);
1985 return FAILED(hres) ? hres : return_short(res, st.wMinute);
1988 static HRESULT Global_Second(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1990 SYSTEMTIME st;
1991 HRESULT hres;
1993 TRACE("(%s)\n", debugstr_variant(arg));
1995 hres = to_system_time(arg, &st);
1996 return FAILED(hres) ? hres : return_short(res, st.wSecond);
1999 static HRESULT Global_DateValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2001 FIXME("\n");
2002 return E_NOTIMPL;
2005 static HRESULT Global_TimeValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2007 FIXME("\n");
2008 return E_NOTIMPL;
2011 static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2013 FIXME("\n");
2014 return E_NOTIMPL;
2017 static HRESULT Global_TimeSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2019 FIXME("\n");
2020 return E_NOTIMPL;
2023 static HRESULT Global_InputBox(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2025 FIXME("\n");
2026 return E_NOTIMPL;
2029 static HRESULT Global_MsgBox(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2031 BSTR prompt, title = NULL;
2032 int type = MB_OK;
2033 HRESULT hres;
2035 TRACE("\n");
2037 assert(1 <= args_cnt && args_cnt <= 5);
2039 hres = to_string(args, &prompt);
2040 if(FAILED(hres))
2041 return hres;
2043 if(args_cnt > 1)
2044 hres = to_int(args+1, &type);
2046 if(SUCCEEDED(hres) && args_cnt > 2)
2047 hres = to_string(args+2, &title);
2049 if(SUCCEEDED(hres) && args_cnt > 3) {
2050 FIXME("unsupported arg_cnt %d\n", args_cnt);
2051 hres = E_NOTIMPL;
2054 if(SUCCEEDED(hres))
2055 hres = show_msgbox(This->ctx, prompt, type, title, res);
2057 SysFreeString(prompt);
2058 SysFreeString(title);
2059 return hres;
2062 static HRESULT Global_CreateObject(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2064 IUnknown *obj;
2065 HRESULT hres;
2067 TRACE("(%s)\n", debugstr_variant(arg));
2069 if(V_VT(arg) != VT_BSTR) {
2070 FIXME("non-bstr arg\n");
2071 return E_INVALIDARG;
2074 obj = create_object(This->ctx, V_BSTR(arg));
2075 if(!obj)
2076 return VB_E_CANNOT_CREATE_OBJ;
2078 if(res) {
2079 hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&V_DISPATCH(res));
2080 if(FAILED(hres))
2081 return hres;
2083 V_VT(res) = VT_DISPATCH;
2086 IUnknown_Release(obj);
2087 return S_OK;
2090 static HRESULT Global_GetObject(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2092 IBindCtx *bind_ctx;
2093 IUnknown *obj_unk;
2094 IDispatch *disp;
2095 ULONG eaten = 0;
2096 IMoniker *mon;
2097 HRESULT hres;
2099 TRACE("%s %s\n", args_cnt ? debugstr_variant(args) : "", args_cnt > 1 ? debugstr_variant(args+1) : "");
2101 if(args_cnt != 1 || V_VT(args) != VT_BSTR) {
2102 FIXME("unsupported args\n");
2103 return E_NOTIMPL;
2106 if(This->ctx->safeopt & (INTERFACE_USES_SECURITY_MANAGER|INTERFACESAFE_FOR_UNTRUSTED_DATA)) {
2107 WARN("blocked in current safety mode\n");
2108 return VB_E_CANNOT_CREATE_OBJ;
2111 hres = CreateBindCtx(0, &bind_ctx);
2112 if(FAILED(hres))
2113 return hres;
2115 hres = MkParseDisplayName(bind_ctx, V_BSTR(args), &eaten, &mon);
2116 if(SUCCEEDED(hres)) {
2117 hres = IMoniker_BindToObject(mon, bind_ctx, NULL, &IID_IUnknown, (void**)&obj_unk);
2118 IMoniker_Release(mon);
2119 }else {
2120 hres = MK_E_SYNTAX;
2122 IBindCtx_Release(bind_ctx);
2123 if(FAILED(hres))
2124 return hres;
2126 hres = set_object_site(This->ctx, obj_unk);
2127 if(FAILED(hres)) {
2128 IUnknown_Release(obj_unk);
2129 return hres;
2132 hres = IUnknown_QueryInterface(obj_unk, &IID_IDispatch, (void**)&disp);
2133 if(SUCCEEDED(hres)) {
2134 if(res) {
2135 V_VT(res) = VT_DISPATCH;
2136 V_DISPATCH(res) = disp;
2137 }else {
2138 IDispatch_Release(disp);
2140 }else {
2141 FIXME("object does not support IDispatch\n");
2144 return hres;
2147 static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2149 FIXME("\n");
2150 return E_NOTIMPL;
2153 static HRESULT Global_DateDiff(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2155 FIXME("\n");
2156 return E_NOTIMPL;
2159 static HRESULT Global_DatePart(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2161 FIXME("\n");
2162 return E_NOTIMPL;
2165 static HRESULT Global_TypeName(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2167 static const WCHAR ByteW[] = {'B', 'y', 't', 'e', 0};
2168 static const WCHAR IntegerW[] = {'I', 'n', 't', 'e', 'g', 'e', 'r', 0};
2169 static const WCHAR LongW[] = {'L', 'o', 'n', 'g', 0};
2170 static const WCHAR SingleW[] = {'S', 'i', 'n', 'g', 'l', 'e', 0};
2171 static const WCHAR DoubleW[] = {'D', 'o', 'u', 'b', 'l', 'e', 0};
2172 static const WCHAR CurrencyW[] = {'C', 'u', 'r', 'r', 'e', 'n', 'c', 'y', 0};
2173 static const WCHAR DecimalW[] = {'D', 'e', 'c', 'i', 'm', 'a', 'l', 0};
2174 static const WCHAR DateW[] = {'D', 'a', 't', 'e', 0};
2175 static const WCHAR StringW[] = {'S', 't', 'r', 'i', 'n', 'g', 0};
2176 static const WCHAR BooleanW[] = {'B', 'o', 'o', 'l', 'e', 'a', 'n', 0};
2177 static const WCHAR EmptyW[] = {'E', 'm', 'p', 't', 'y', 0};
2178 static const WCHAR NullW[] = {'N', 'u', 'l', 'l', 0};
2180 TRACE("(%s)\n", debugstr_variant(arg));
2182 assert(args_cnt == 1);
2184 switch(V_VT(arg)) {
2185 case VT_UI1:
2186 return return_string(res, ByteW);
2187 case VT_I2:
2188 return return_string(res, IntegerW);
2189 case VT_I4:
2190 return return_string(res, LongW);
2191 case VT_R4:
2192 return return_string(res, SingleW);
2193 case VT_R8:
2194 return return_string(res, DoubleW);
2195 case VT_CY:
2196 return return_string(res, CurrencyW);
2197 case VT_DECIMAL:
2198 return return_string(res, DecimalW);
2199 case VT_DATE:
2200 return return_string(res, DateW);
2201 case VT_BSTR:
2202 return return_string(res, StringW);
2203 case VT_BOOL:
2204 return return_string(res, BooleanW);
2205 case VT_EMPTY:
2206 return return_string(res, EmptyW);
2207 case VT_NULL:
2208 return return_string(res, NullW);
2209 default:
2210 FIXME("arg %s not supported\n", debugstr_variant(arg));
2211 return E_NOTIMPL;
2215 static HRESULT Global_Array(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2217 SAFEARRAYBOUND bounds;
2218 SAFEARRAY *sa;
2219 VARIANT *data;
2220 HRESULT hres;
2221 unsigned i;
2223 TRACE("arg_cnt=%u\n", args_cnt);
2225 bounds.lLbound = 0;
2226 bounds.cElements = args_cnt;
2227 sa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
2228 if(!sa)
2229 return E_OUTOFMEMORY;
2231 hres = SafeArrayAccessData(sa, (void**)&data);
2232 if(FAILED(hres)) {
2233 SafeArrayDestroy(sa);
2234 return hres;
2237 for(i=0; i<args_cnt; i++) {
2238 hres = VariantCopyInd(data+i, arg+i);
2239 if(FAILED(hres)) {
2240 SafeArrayUnaccessData(sa);
2241 SafeArrayDestroy(sa);
2242 return hres;
2245 SafeArrayUnaccessData(sa);
2247 if(res) {
2248 V_VT(res) = VT_ARRAY|VT_VARIANT;
2249 V_ARRAY(res) = sa;
2250 }else {
2251 SafeArrayDestroy(sa);
2254 return S_OK;
2257 static HRESULT Global_Erase(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2259 FIXME("\n");
2260 return E_NOTIMPL;
2263 static HRESULT Global_Filter(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2265 FIXME("\n");
2266 return E_NOTIMPL;
2269 static HRESULT Global_Join(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2271 FIXME("\n");
2272 return E_NOTIMPL;
2275 static HRESULT Global_Split(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2277 FIXME("\n");
2278 return E_NOTIMPL;
2281 static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2283 BSTR string, find = NULL, replace = NULL, ret;
2284 int from = 1, cnt = -1;
2285 HRESULT hres = S_OK;
2287 TRACE("%s %s %s %u...\n", debugstr_variant(args), debugstr_variant(args+1), debugstr_variant(args+2), args_cnt);
2289 assert(3 <= args_cnt && args_cnt <= 6);
2290 if(V_VT(args) != VT_BSTR) {
2291 hres = to_string(args, &string);
2292 if(FAILED(hres))
2293 return hres;
2294 }else {
2295 string = V_BSTR(args);
2298 if(V_VT(args+1) != VT_BSTR) {
2299 hres = to_string(args+1, &find);
2300 if(FAILED(hres))
2301 goto error;
2302 }else {
2303 find = V_BSTR(args+1);
2306 if(V_VT(args+2) != VT_BSTR) {
2307 hres = to_string(args+2, &replace);
2308 if(FAILED(hres))
2309 goto error;
2310 }else {
2311 replace = V_BSTR(args+2);
2314 if(args_cnt >= 4) {
2315 hres = to_int(args+3, &from);
2316 if(FAILED(hres))
2317 goto error;
2318 if(from < 1) {
2319 hres = E_INVALIDARG;
2320 goto error;
2324 if(args_cnt >= 5) {
2325 hres = to_int(args+4, &cnt);
2326 if(FAILED(hres))
2327 goto error;
2328 if(cnt < -1) {
2329 hres = E_INVALIDARG;
2330 goto error;
2334 if(args_cnt == 6)
2335 FIXME("copare argument not supported\n");
2337 ret = string_replace(string, find, replace, from - 1, cnt);
2338 if(!ret) {
2339 hres = E_OUTOFMEMORY;
2340 }else if(res) {
2341 V_VT(res) = VT_BSTR;
2342 V_BSTR(res) = ret;
2343 }else {
2344 SysFreeString(ret);
2347 error:
2348 if(V_VT(args) != VT_BSTR)
2349 SysFreeString(string);
2350 if(V_VT(args+1) != VT_BSTR)
2351 SysFreeString(find);
2352 if(V_VT(args+2) != VT_BSTR)
2353 SysFreeString(replace);
2354 return hres;
2357 static HRESULT Global_StrReverse(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2359 WCHAR *ptr1, *ptr2, ch;
2360 BSTR ret;
2361 HRESULT hres;
2363 TRACE("%s\n", debugstr_variant(arg));
2365 hres = to_string(arg, &ret);
2366 if(FAILED(hres))
2367 return hres;
2369 ptr1 = ret;
2370 ptr2 = ret + SysStringLen(ret)-1;
2371 while(ptr1 < ptr2) {
2372 ch = *ptr1;
2373 *ptr1++ = *ptr2;
2374 *ptr2-- = ch;
2377 return return_bstr(res, ret);
2380 static HRESULT Global_InStrRev(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2382 int start, ret = 0;
2383 BSTR str1, str2;
2384 HRESULT hres;
2386 TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args), debugstr_variant(args+1), args_cnt);
2388 if(args_cnt > 3) {
2389 FIXME("Unsupported args\n");
2390 return E_NOTIMPL;
2393 assert(2 <= args_cnt && args_cnt <= 4);
2395 if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL))
2396 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
2398 hres = to_string(args, &str1);
2399 if(FAILED(hres))
2400 return hres;
2402 hres = to_string(args+1, &str2);
2403 if(SUCCEEDED(hres)) {
2404 if(args_cnt > 2) {
2405 hres = to_int(args+2, &start);
2406 if(SUCCEEDED(hres) && start <= 0) {
2407 FIXME("Unsupported start %d\n", start);
2408 hres = E_NOTIMPL;
2410 }else {
2411 start = SysStringLen(str1);
2413 } else {
2414 str2 = NULL;
2417 if(SUCCEEDED(hres)) {
2418 const WCHAR *ptr;
2419 size_t len;
2421 len = SysStringLen(str2);
2422 if(start >= len && start <= SysStringLen(str1)) {
2423 for(ptr = str1+start-SysStringLen(str2); ptr >= str1; ptr--) {
2424 if(!memcmp(ptr, str2, len*sizeof(WCHAR))) {
2425 ret = ptr-str1+1;
2426 break;
2432 SysFreeString(str1);
2433 SysFreeString(str2);
2434 if(FAILED(hres))
2435 return hres;
2437 return return_int(res, ret);
2440 static HRESULT Global_LoadPicture(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2442 FIXME("\n");
2443 return E_NOTIMPL;
2446 static HRESULT Global_ScriptEngine(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2448 TRACE("%s\n", debugstr_variant(arg));
2450 assert(args_cnt == 0);
2452 return return_string(res, vbscriptW);
2455 static HRESULT Global_ScriptEngineMajorVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2457 TRACE("%s\n", debugstr_variant(arg));
2459 assert(args_cnt == 0);
2461 return return_int(res, VBSCRIPT_MAJOR_VERSION);
2464 static HRESULT Global_ScriptEngineMinorVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2466 TRACE("%s\n", debugstr_variant(arg));
2468 assert(args_cnt == 0);
2470 return return_int(res, VBSCRIPT_MINOR_VERSION);
2473 static HRESULT Global_ScriptEngineBuildVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2475 TRACE("%s\n", debugstr_variant(arg));
2477 assert(args_cnt == 0);
2479 return return_int(res, VBSCRIPT_BUILD_VERSION);
2482 static HRESULT Global_FormatNumber(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2484 FIXME("\n");
2485 return E_NOTIMPL;
2488 static HRESULT Global_FormatCurrency(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2490 FIXME("\n");
2491 return E_NOTIMPL;
2494 static HRESULT Global_FormatPercent(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2496 FIXME("\n");
2497 return E_NOTIMPL;
2500 static HRESULT Global_FormatDateTime(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2502 FIXME("\n");
2503 return E_NOTIMPL;
2506 static HRESULT Global_WeekdayName(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2508 int weekday, first_day = 1, abbrev = 0;
2509 BSTR ret;
2510 HRESULT hres;
2512 TRACE("\n");
2514 assert(1 <= args_cnt && args_cnt <= 3);
2516 hres = to_int(args, &weekday);
2517 if(FAILED(hres))
2518 return hres;
2520 if(args_cnt > 1) {
2521 hres = to_int(args+1, &abbrev);
2522 if(FAILED(hres))
2523 return hres;
2525 if(args_cnt == 3) {
2526 hres = to_int(args+2, &first_day);
2527 if(FAILED(hres))
2528 return hres;
2532 hres = VarWeekdayName(weekday, abbrev, first_day, 0, &ret);
2533 if(FAILED(hres))
2534 return hres;
2536 return return_bstr(res, ret);
2539 static HRESULT Global_MonthName(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2541 int month, abbrev = 0;
2542 BSTR ret;
2543 HRESULT hres;
2545 TRACE("\n");
2547 assert(args_cnt == 1 || args_cnt == 2);
2549 hres = to_int(args, &month);
2550 if(FAILED(hres))
2551 return hres;
2553 if(args_cnt == 2) {
2554 hres = to_int(args+1, &abbrev);
2555 if(FAILED(hres))
2556 return hres;
2559 hres = VarMonthName(month, abbrev, 0, &ret);
2560 if(FAILED(hres))
2561 return hres;
2563 return return_bstr(res, ret);
2566 static HRESULT Global_Round(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2568 double n;
2569 HRESULT hres;
2571 TRACE("%s\n", debugstr_variant(arg));
2573 if(!res)
2574 return S_OK;
2576 switch(V_VT(arg)) {
2577 case VT_I2:
2578 case VT_I4:
2579 case VT_BOOL:
2580 *res = *arg;
2581 return S_OK;
2582 case VT_R8:
2583 n = V_R8(arg);
2584 break;
2585 default:
2586 hres = to_double(arg, &n);
2587 if(FAILED(hres))
2588 return hres;
2591 return return_double(res, round(n));
2594 static HRESULT Global_Escape(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2596 FIXME("\n");
2597 return E_NOTIMPL;
2600 static HRESULT Global_Unescape(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2602 FIXME("\n");
2603 return E_NOTIMPL;
2606 static HRESULT Global_Eval(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2608 FIXME("\n");
2609 return E_NOTIMPL;
2612 static HRESULT Global_Execute(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2614 FIXME("\n");
2615 return E_NOTIMPL;
2618 static HRESULT Global_ExecuteGlobal(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2620 FIXME("\n");
2621 return E_NOTIMPL;
2624 static HRESULT Global_GetRef(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2626 FIXME("\n");
2627 return E_NOTIMPL;
2630 static HRESULT Global_Err(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2632 TRACE("\n");
2634 if(args_cnt) {
2635 FIXME("Setter not supported\n");
2636 return E_NOTIMPL;
2639 V_VT(res) = VT_DISPATCH;
2640 V_DISPATCH(res) = &This->ctx->err_obj->IDispatch_iface;
2641 IDispatch_AddRef(V_DISPATCH(res));
2642 return S_OK;
2645 static const string_constant_t vbCr = {1, {'\r'}};
2646 static const string_constant_t vbCrLf = {2, {'\r','\n'}};
2647 static const string_constant_t vbNewLine = {2, {'\r','\n'}};
2648 static const string_constant_t vbFormFeed = {1, {0xc}};
2649 static const string_constant_t vbLf = {1, {'\n'}};
2650 static const string_constant_t vbNullChar = {1};
2651 static const string_constant_t vbNullString = {0};
2652 static const string_constant_t vbTab = {1, {'\t'}};
2653 static const string_constant_t vbVerticalTab = {1, {0xb}};
2655 static const builtin_prop_t global_props[] = {
2656 {NULL}, /* no default value */
2657 {L"Abs", Global_Abs, 0, 1},
2658 {L"Array", Global_Array, 0, 0, MAXDWORD},
2659 {L"Asc", Global_Asc, 0, 1},
2660 {L"AscB", Global_AscB, 0, 1},
2661 {L"AscW", Global_AscW, 0, 1},
2662 {L"Atn", Global_Atn, 0, 1},
2663 {L"CBool", Global_CBool, 0, 1},
2664 {L"CByte", Global_CByte, 0, 1},
2665 {L"CCur", Global_CCur, 0, 1},
2666 {L"CDate", Global_CDate, 0, 1},
2667 {L"CDbl", Global_CDbl, 0, 1},
2668 {L"Chr", Global_Chr, 0, 1},
2669 {L"ChrB", Global_ChrB, 0, 1},
2670 {L"ChrW", Global_ChrW, 0, 1},
2671 {L"CInt", Global_CInt, 0, 1},
2672 {L"CLng", Global_CLng, 0, 1},
2673 {L"Cos", Global_Cos, 0, 1},
2674 {L"CreateObject", Global_CreateObject, 0, 1},
2675 {L"CSng", Global_CSng, 0, 1},
2676 {L"CStr", Global_CStr, 0, 1},
2677 {L"Date", Global_Date, 0, 0},
2678 {L"DateAdd", Global_DateAdd, 0, 3},
2679 {L"DateDiff", Global_DateDiff, 0, 3, 5},
2680 {L"DatePart", Global_DatePart, 0, 2, 4},
2681 {L"DateSerial", Global_DateSerial, 0, 3},
2682 {L"DateValue", Global_DateValue, 0, 1},
2683 {L"Day", Global_Day, 0, 1},
2684 {L"Erase", Global_Erase, 0, 1},
2685 {L"Err", Global_Err, BP_GETPUT},
2686 {L"Escape", Global_Escape, 0, 1},
2687 {L"Eval", Global_Eval, 0, 1},
2688 {L"Execute", Global_Execute, 0, 1},
2689 {L"ExecuteGlobal", Global_ExecuteGlobal, 0, 1},
2690 {L"Exp", Global_Exp, 0, 1},
2691 {L"Filter", Global_Filter, 0, 2, 4},
2692 {L"Fix", Global_Fix, 0, 1},
2693 {L"FormatCurrency", Global_FormatCurrency, 0, 1, 5},
2694 {L"FormatDateTime", Global_FormatDateTime, 0, 1, 2},
2695 {L"FormatNumber", Global_FormatNumber, 0, 1, 5},
2696 {L"FormatPercent", Global_FormatPercent, 0, 1, 5},
2697 {L"GetObject", Global_GetObject, 0, 0, 2},
2698 {L"GetRef", Global_GetRef, 0, 1},
2699 {L"Hex", Global_Hex, 0, 1},
2700 {L"Hour", Global_Hour, 0, 1},
2701 {L"InputBox", Global_InputBox, 0, 1, 7},
2702 {L"InStr", Global_InStr, 0, 2, 4},
2703 {L"InStrB", Global_InStrB, 0, 3, 4},
2704 {L"InStrRev", Global_InStrRev, 0, 2, 4},
2705 {L"Int", Global_Int, 0, 1},
2706 {L"IsArray", Global_IsArray, 0, 1},
2707 {L"IsDate", Global_IsDate, 0, 1},
2708 {L"IsEmpty", Global_IsEmpty, 0, 1},
2709 {L"IsNull", Global_IsNull, 0, 1},
2710 {L"IsNumeric", Global_IsNumeric, 0, 1},
2711 {L"IsObject", Global_IsObject, 0, 1},
2712 {L"Join", Global_Join, 0, 1, 2},
2713 {L"LBound", Global_LBound, 0, 1, 2},
2714 {L"LCase", Global_LCase, 0, 1},
2715 {L"Left", Global_Left, 0, 2},
2716 {L"LeftB", Global_LeftB, 0, 2},
2717 {L"Len", Global_Len, 0, 1},
2718 {L"LenB", Global_LenB, 0, 1},
2719 {L"LoadPicture", Global_LoadPicture, 0, 1},
2720 {L"Log", Global_Log, 0, 1},
2721 {L"LTrim", Global_LTrim, 0, 1},
2722 {L"Mid", Global_Mid, 0, 2, 3},
2723 {L"MidB", Global_MidB, 0, 2, 3},
2724 {L"Minute", Global_Minute, 0, 1},
2725 {L"Month", Global_Month, 0, 1},
2726 {L"MonthName", Global_MonthName, 0, 1, 2},
2727 {L"MsgBox", Global_MsgBox, 0, 1, 5},
2728 {L"Now", Global_Now, 0, 0},
2729 {L"Oct", Global_Oct, 0, 1},
2730 {L"Randomize", Global_Randomize, 0, 1},
2731 {L"Replace", Global_Replace, 0, 3, 6},
2732 {L"RGB", Global_RGB, 0, 3},
2733 {L"Right", Global_Right, 0, 2},
2734 {L"RightB", Global_RightB, 0, 2},
2735 {L"Rnd", Global_Rnd, 0, 1},
2736 {L"Round", Global_Round, 0, 1, 2},
2737 {L"RTrim", Global_RTrim, 0, 1},
2738 {L"ScriptEngine", Global_ScriptEngine, 0, 0},
2739 {L"ScriptEngineBuildVersion", Global_ScriptEngineBuildVersion, 0, 0},
2740 {L"ScriptEngineMajorVersion", Global_ScriptEngineMajorVersion, 0, 0},
2741 {L"ScriptEngineMinorVersion", Global_ScriptEngineMinorVersion, 0, 0},
2742 {L"Second", Global_Second, 0, 1},
2743 {L"Sgn", Global_Sgn, 0, 1},
2744 {L"Sin", Global_Sin, 0, 1},
2745 {L"Space", Global_Space, 0, 1},
2746 {L"Split", Global_Split, 0, 1, 4},
2747 {L"Sqr", Global_Sqr, 0, 1},
2748 {L"StrComp", Global_StrComp, 0, 2, 3},
2749 {L"String", Global_String, 0, 0, 2},
2750 {L"StrReverse", Global_StrReverse, 0, 1},
2751 {L"Tan", Global_Tan, 0, 1},
2752 {L"Time", Global_Time, 0, 0},
2753 {L"Timer", Global_Timer, 0, 0},
2754 {L"TimeSerial", Global_TimeSerial, 0, 3},
2755 {L"TimeValue", Global_TimeValue, 0, 1},
2756 {L"Trim", Global_Trim, 0, 1},
2757 {L"TypeName", Global_TypeName, 0, 1},
2758 {L"UBound", Global_UBound, 0, 1, 2},
2759 {L"UCase", Global_UCase, 0, 1},
2760 {L"Unescape", Global_Unescape, 0, 1},
2761 {L"VarType", Global_VarType, 0, 1},
2762 {L"vbAbort", NULL, BP_GET, VT_I2, IDABORT},
2763 {L"vbAbortRetryIgnore", NULL, BP_GET, VT_I2, MB_ABORTRETRYIGNORE},
2764 {L"vbApplicationModal", NULL, BP_GET, VT_I2, MB_APPLMODAL},
2765 {L"vbArray", NULL, BP_GET, VT_I2, VT_ARRAY},
2766 {L"vbBinaryCompare", NULL, BP_GET, VT_I2, 0},
2767 {L"vbBlack", NULL, BP_GET, VT_I4, 0x000000},
2768 {L"vbBlue", NULL, BP_GET, VT_I4, 0xff0000},
2769 {L"vbBoolean", NULL, BP_GET, VT_I2, VT_BOOL},
2770 {L"vbByte", NULL, BP_GET, VT_I2, VT_UI1},
2771 {L"vbCancel", NULL, BP_GET, VT_I2, IDCANCEL},
2772 {L"vbCr", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCr},
2773 {L"vbCritical", NULL, BP_GET, VT_I2, MB_ICONHAND},
2774 {L"vbCrLf", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCrLf},
2775 {L"vbCurrency", NULL, BP_GET, VT_I2, VT_CY},
2776 {L"vbCyan", NULL, BP_GET, VT_I4, 0xffff00},
2777 {L"vbDatabaseCompare", NULL, BP_GET, VT_I2, 2},
2778 {L"vbDataObject", NULL, BP_GET, VT_I2, VT_UNKNOWN},
2779 {L"vbDate", NULL, BP_GET, VT_I2, VT_DATE},
2780 {L"vbDecimal", NULL, BP_GET, VT_I2, VT_DECIMAL},
2781 {L"vbDefaultButton1", NULL, BP_GET, VT_I2, MB_DEFBUTTON1},
2782 {L"vbDefaultButton2", NULL, BP_GET, VT_I2, MB_DEFBUTTON2},
2783 {L"vbDefaultButton3", NULL, BP_GET, VT_I2, MB_DEFBUTTON3},
2784 {L"vbDefaultButton4", NULL, BP_GET, VT_I2, MB_DEFBUTTON4},
2785 {L"vbDouble", NULL, BP_GET, VT_I2, VT_R8},
2786 {L"vbEmpty", NULL, BP_GET, VT_I2, VT_EMPTY},
2787 {L"vbError", NULL, BP_GET, VT_I2, VT_ERROR},
2788 {L"vbExclamation", NULL, BP_GET, VT_I2, MB_ICONEXCLAMATION},
2789 {L"vbFalse", NULL, BP_GET, VT_I2, VARIANT_FALSE},
2790 {L"vbFirstFourDays", NULL, BP_GET, VT_I2, 2},
2791 {L"vbFirstFullWeek", NULL, BP_GET, VT_I2, 3},
2792 {L"vbFirstJan1", NULL, BP_GET, VT_I2, 1},
2793 {L"vbFormFeed", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbFormFeed},
2794 {L"vbFriday", NULL, BP_GET, VT_I2, 6},
2795 {L"vbGeneralDate", NULL, BP_GET, VT_I2, 0},
2796 {L"vbGreen", NULL, BP_GET, VT_I4, 0x00ff00},
2797 {L"vbIgnore", NULL, BP_GET, VT_I2, IDIGNORE},
2798 {L"vbInformation", NULL, BP_GET, VT_I2, MB_ICONASTERISK},
2799 {L"vbInteger", NULL, BP_GET, VT_I2, VT_I2},
2800 {L"vbLf", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbLf},
2801 {L"vbLong", NULL, BP_GET, VT_I2, VT_I4},
2802 {L"vbLongDate", NULL, BP_GET, VT_I2, 1},
2803 {L"vbLongTime", NULL, BP_GET, VT_I2, 3},
2804 {L"vbMagenta", NULL, BP_GET, VT_I4, 0xff00ff},
2805 {L"vbMonday", NULL, BP_GET, VT_I2, 2},
2806 {L"vbMsgBoxHelpButton", NULL, BP_GET, VT_I4, MB_HELP},
2807 {L"vbMsgBoxRight", NULL, BP_GET, VT_I4, MB_RIGHT},
2808 {L"vbMsgBoxRtlReading", NULL, BP_GET, VT_I4, MB_RTLREADING},
2809 {L"vbMsgBoxSetForeground", NULL, BP_GET, VT_I4, MB_SETFOREGROUND},
2810 {L"vbNewLine", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNewLine},
2811 {L"vbNo", NULL, BP_GET, VT_I2, IDNO},
2812 {L"vbNull", NULL, BP_GET, VT_I2, VT_NULL},
2813 {L"vbNullChar", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullChar},
2814 {L"vbNullString", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullString},
2815 {L"vbObject", NULL, BP_GET, VT_I2, VT_DISPATCH},
2816 {L"vbObjectError", NULL, BP_GET, VT_I4, 0x80040000},
2817 {L"vbOK", NULL, BP_GET, VT_I2, IDOK},
2818 {L"vbOKCancel", NULL, BP_GET, VT_I2, MB_OKCANCEL},
2819 {L"vbOKOnly", NULL, BP_GET, VT_I2, MB_OK},
2820 {L"vbQuestion", NULL, BP_GET, VT_I2, MB_ICONQUESTION},
2821 {L"vbRed", NULL, BP_GET, VT_I4, 0x0000ff},
2822 {L"vbRetry", NULL, BP_GET, VT_I2, IDRETRY},
2823 {L"vbRetryCancel", NULL, BP_GET, VT_I2, MB_RETRYCANCEL},
2824 {L"vbSaturday", NULL, BP_GET, VT_I2, 7},
2825 {L"vbShortDate", NULL, BP_GET, VT_I2, 2},
2826 {L"vbShortTime", NULL, BP_GET, VT_I2, 4},
2827 {L"vbSingle", NULL, BP_GET, VT_I2, VT_R4},
2828 {L"vbString", NULL, BP_GET, VT_I2, VT_BSTR},
2829 {L"vbSunday", NULL, BP_GET, VT_I2, 1},
2830 {L"vbSystemModal", NULL, BP_GET, VT_I2, MB_SYSTEMMODAL},
2831 {L"vbTab", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbTab},
2832 {L"vbTextCompare", NULL, BP_GET, VT_I2, 1},
2833 {L"vbThursday", NULL, BP_GET, VT_I2, 5},
2834 {L"vbTrue", NULL, BP_GET, VT_I2, VARIANT_TRUE},
2835 {L"vbTuesday", NULL, BP_GET, VT_I2, 3},
2836 {L"vbUseDefault", NULL, BP_GET, VT_I2, -2},
2837 {L"vbUseSystem", NULL, BP_GET, VT_I2, 0},
2838 {L"vbUseSystemDayOfWeek", NULL, BP_GET, VT_I2, 0},
2839 {L"vbVariant", NULL, BP_GET, VT_I2, VT_VARIANT},
2840 {L"vbVerticalTab", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbVerticalTab},
2841 {L"vbWednesday", NULL, BP_GET, VT_I2, 4},
2842 {L"vbWhite", NULL, BP_GET, VT_I4, 0xffffff},
2843 {L"vbYellow", NULL, BP_GET, VT_I4, 0x00ffff},
2844 {L"vbYes", NULL, BP_GET, VT_I2, IDYES},
2845 {L"vbYesNo", NULL, BP_GET, VT_I2, MB_YESNO},
2846 {L"vbYesNoCancel", NULL, BP_GET, VT_I2, MB_YESNOCANCEL},
2847 {L"Weekday", Global_Weekday, 0, 1, 2},
2848 {L"WeekdayName", Global_WeekdayName, 0, 1, 3},
2849 {L"Year", Global_Year, 0, 1}
2852 static HRESULT err_string_prop(BSTR *prop, VARIANT *args, unsigned args_cnt, VARIANT *res)
2854 BSTR str;
2855 HRESULT hres;
2857 if(!args_cnt)
2858 return return_string(res, *prop ? *prop : L"");
2860 hres = to_string(args, &str);
2861 if(FAILED(hres))
2862 return hres;
2864 SysFreeString(*prop);
2865 *prop = str;
2866 return S_OK;
2869 static HRESULT Err_Description(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2871 TRACE("\n");
2872 return err_string_prop(&This->ctx->ei.bstrDescription, args, args_cnt, res);
2875 static HRESULT Err_HelpContext(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2877 TRACE("\n");
2879 if(args_cnt) {
2880 FIXME("setter not implemented\n");
2881 return E_NOTIMPL;
2884 return return_int(res, This->ctx->ei.dwHelpContext);
2887 static HRESULT Err_HelpFile(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2889 TRACE("\n");
2890 return err_string_prop(&This->ctx->ei.bstrHelpFile, args, args_cnt, res);
2893 static HRESULT Err_Number(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2895 HRESULT hres;
2897 TRACE("\n");
2899 if(args_cnt) {
2900 FIXME("setter not implemented\n");
2901 return E_NOTIMPL;
2904 hres = This->ctx->ei.scode;
2905 return return_int(res, HRESULT_FACILITY(hres) == FACILITY_VBS ? HRESULT_CODE(hres) : hres);
2908 static HRESULT Err_Source(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2910 TRACE("\n");
2911 return err_string_prop(&This->ctx->ei.bstrSource, args, args_cnt, res);
2914 static HRESULT Err_Clear(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2916 TRACE("\n");
2918 clear_ei(&This->ctx->ei);
2919 return S_OK;
2922 static HRESULT Err_Raise(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2924 BSTR source = NULL, description = NULL, helpfile = NULL;
2925 int code, helpcontext = 0;
2926 HRESULT hres, error;
2928 TRACE("%s %u...\n", debugstr_variant(args), args_cnt);
2930 hres = to_int(args, &code);
2931 if(FAILED(hres))
2932 return hres;
2933 if(code > 0 && code > 0xffff)
2934 return E_INVALIDARG;
2936 if(args_cnt >= 2)
2937 hres = to_string(args + 1, &source);
2938 if(args_cnt >= 3 && SUCCEEDED(hres))
2939 hres = to_string(args + 2, &description);
2940 if(args_cnt >= 4 && SUCCEEDED(hres))
2941 hres = to_string(args + 3, &helpfile);
2942 if(args_cnt >= 5 && SUCCEEDED(hres))
2943 hres = to_int(args + 4, &helpcontext);
2945 if(SUCCEEDED(hres)) {
2946 script_ctx_t *ctx = This->ctx;
2948 error = (code & ~0xffff) ? map_hres(code) : MAKE_VBSERROR(code);
2950 if(source) {
2951 SysFreeString(ctx->ei.bstrSource);
2952 ctx->ei.bstrSource = source;
2954 if(!ctx->ei.bstrSource)
2955 ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR);
2956 if(description) {
2957 SysFreeString(ctx->ei.bstrDescription);
2958 ctx->ei.bstrDescription = description;
2960 if(!ctx->ei.bstrDescription)
2961 ctx->ei.bstrDescription = get_vbscript_error_string(error);
2962 if(helpfile) {
2963 SysFreeString(ctx->ei.bstrHelpFile);
2964 ctx->ei.bstrHelpFile = helpfile;
2966 if(args_cnt >= 5)
2967 ctx->ei.dwHelpContext = helpcontext;
2969 ctx->ei.scode = error;
2970 hres = SCRIPT_E_RECORDED;
2971 }else {
2972 SysFreeString(source);
2973 SysFreeString(description);
2974 SysFreeString(helpfile);
2977 return hres;
2980 static const builtin_prop_t err_props[] = {
2981 {NULL, Err_Number, BP_GETPUT},
2982 {L"Clear", Err_Clear},
2983 {L"Description", Err_Description, BP_GETPUT},
2984 {L"HelpContext", Err_HelpContext, BP_GETPUT},
2985 {L"HelpFile", Err_HelpFile, BP_GETPUT},
2986 {L"Number", Err_Number, BP_GETPUT},
2987 {L"Raise", Err_Raise, 0, 1, 5},
2988 {L"Source", Err_Source, BP_GETPUT}
2991 void detach_global_objects(script_ctx_t *ctx)
2993 if(ctx->err_obj) {
2994 ctx->err_obj->ctx = NULL;
2995 IDispatch_Release(&ctx->err_obj->IDispatch_iface);
2996 ctx->err_obj = NULL;
2999 if(ctx->global_obj) {
3000 ctx->global_obj->ctx = NULL;
3001 IDispatch_Release(&ctx->global_obj->IDispatch_iface);
3002 ctx->global_obj = NULL;
3006 HRESULT init_global(script_ctx_t *ctx)
3008 HRESULT hres;
3010 hres = create_builtin_dispatch(ctx, global_props, ARRAY_SIZE(global_props), &ctx->global_obj);
3011 if(FAILED(hres))
3012 return hres;
3014 return create_builtin_dispatch(ctx, err_props, ARRAY_SIZE(err_props), &ctx->err_obj);