xref: /reactos/dll/win32/vbscript/global.c (revision 31019e8c)
1 /*
2  * Copyright 2011 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <assert.h>
20 #include <math.h>
21 
22 #include "vbscript.h"
23 #include "vbscript_defs.h"
24 
25 #include "mshtmhst.h"
26 #include "objsafe.h"
27 
28 #include "wine/debug.h"
29 
30 #ifdef __REACTOS__
31 #include <wingdi.h>
32 #endif
33 
34 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
35 
36 #define VB_E_CANNOT_CREATE_OBJ 0x800a01ad
37 #define VB_E_MK_PARSE_ERROR    0x800a01b0
38 
39 /* Defined as extern in urlmon.idl, but not exported by uuid.lib */
40 const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY =
41     {0x10200490,0xfa38,0x11d0,{0xac,0x0e,0x00,0xa0,0xc9,0xf,0xff,0xc0}};
42 
43 static const WCHAR emptyW[] = {0};
44 static const WCHAR vbscriptW[] = {'V','B','S','c','r','i','p','t',0};
45 
46 static IInternetHostSecurityManager *get_sec_mgr(script_ctx_t *ctx)
47 {
48     IInternetHostSecurityManager *secmgr;
49     IServiceProvider *sp;
50     HRESULT hres;
51 
52     if(!ctx->site)
53         return NULL;
54 
55     if(ctx->secmgr)
56         return ctx->secmgr;
57 
58     hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp);
59     if(FAILED(hres))
60         return NULL;
61 
62     hres = IServiceProvider_QueryService(sp, &SID_SInternetHostSecurityManager, &IID_IInternetHostSecurityManager,
63             (void**)&secmgr);
64     IServiceProvider_Release(sp);
65     if(FAILED(hres))
66         return NULL;
67 
68     return ctx->secmgr = secmgr;
69 }
70 
71 static HRESULT return_string(VARIANT *res, const WCHAR *str)
72 {
73     BSTR ret;
74 
75     if(!res)
76         return S_OK;
77 
78     ret = SysAllocString(str);
79     if(!ret)
80         return E_OUTOFMEMORY;
81 
82     V_VT(res) = VT_BSTR;
83     V_BSTR(res) = ret;
84     return S_OK;
85 }
86 
87 static HRESULT return_bstr(VARIANT *res, BSTR str)
88 {
89     if(res) {
90         V_VT(res) = VT_BSTR;
91         V_BSTR(res) = str;
92     }else {
93         SysFreeString(str);
94     }
95     return S_OK;
96 }
97 
98 static HRESULT return_bool(VARIANT *res, BOOL val)
99 {
100     if(res) {
101         V_VT(res) = VT_BOOL;
102         V_BOOL(res) = val ? VARIANT_TRUE : VARIANT_FALSE;
103     }
104     return S_OK;
105 }
106 
107 static HRESULT return_short(VARIANT *res, short val)
108 {
109     if(res) {
110         V_VT(res) = VT_I2;
111         V_I2(res) = val;
112     }
113 
114     return S_OK;
115 }
116 
117 static HRESULT return_int(VARIANT *res, int val)
118 {
119     if(res) {
120         V_VT(res) = VT_I4;
121         V_I4(res) = val;
122     }
123 
124     return S_OK;
125 }
126 
127 static inline HRESULT return_double(VARIANT *res, double val)
128 {
129     if(res) {
130         V_VT(res) = VT_R8;
131         V_R8(res) = val;
132     }
133 
134     return S_OK;
135 }
136 
137 static inline HRESULT return_float(VARIANT *res, float val)
138 {
139     if(res) {
140         V_VT(res) = VT_R4;
141         V_R4(res) = val;
142     }
143 
144     return S_OK;
145 }
146 
147 static inline HRESULT return_null(VARIANT *res)
148 {
149     if(res)
150         V_VT(res) = VT_NULL;
151     return S_OK;
152 }
153 
154 static inline HRESULT return_date(VARIANT *res, double date)
155 {
156     if(res) {
157         V_VT(res) = VT_DATE;
158         V_DATE(res) = date;
159     }
160     return S_OK;
161 }
162 
163 HRESULT to_int(VARIANT *v, int *ret)
164 {
165     VARIANT r;
166     HRESULT hres;
167 
168     V_VT(&r) = VT_EMPTY;
169     hres = VariantChangeType(&r, v, 0, VT_I4);
170     if(FAILED(hres))
171         return hres;
172 
173     *ret = V_I4(&r);
174     return S_OK;
175 }
176 
177 static HRESULT to_double(VARIANT *v, double *ret)
178 {
179     VARIANT dst;
180     HRESULT hres;
181 
182     V_VT(&dst) = VT_EMPTY;
183     hres = VariantChangeType(&dst, v, 0, VT_R8);
184     if(FAILED(hres))
185         return hres;
186 
187     *ret = V_R8(&dst);
188     return S_OK;
189 }
190 
191 static HRESULT to_string(VARIANT *v, BSTR *ret)
192 {
193     VARIANT dst;
194     HRESULT hres;
195 
196     V_VT(&dst) = VT_EMPTY;
197     hres = VariantChangeType(&dst, v, VARIANT_LOCALBOOL, VT_BSTR);
198     if(FAILED(hres))
199         return hres;
200 
201     *ret = V_BSTR(&dst);
202     return S_OK;
203 }
204 
205 static HRESULT set_object_site(script_ctx_t *ctx, IUnknown *obj)
206 {
207     IObjectWithSite *obj_site;
208     IUnknown *ax_site;
209     HRESULT hres;
210 
211     hres = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (void**)&obj_site);
212     if(FAILED(hres))
213         return S_OK;
214 
215     ax_site = create_ax_site(ctx);
216     if(ax_site) {
217         hres = IObjectWithSite_SetSite(obj_site, ax_site);
218         IUnknown_Release(ax_site);
219     }
220     else
221         hres = E_OUTOFMEMORY;
222     IObjectWithSite_Release(obj_site);
223     return hres;
224 }
225 
226 static IUnknown *create_object(script_ctx_t *ctx, const WCHAR *progid)
227 {
228     IInternetHostSecurityManager *secmgr = NULL;
229     struct CONFIRMSAFETY cs;
230     IClassFactoryEx *cfex;
231     IClassFactory *cf;
232     DWORD policy_size;
233     BYTE *bpolicy;
234     IUnknown *obj;
235     DWORD policy;
236     GUID guid;
237     HRESULT hres;
238 
239     hres = CLSIDFromProgID(progid, &guid);
240     if(FAILED(hres))
241         return NULL;
242 
243     TRACE("GUID %s\n", debugstr_guid(&guid));
244 
245     if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
246         secmgr = get_sec_mgr(ctx);
247         if(!secmgr)
248             return NULL;
249 
250         policy = 0;
251         hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN,
252                 (BYTE*)&policy, sizeof(policy), (BYTE*)&guid, sizeof(GUID), 0, 0);
253         if(FAILED(hres) || policy != URLPOLICY_ALLOW)
254             return NULL;
255     }
256 
257     hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
258     if(FAILED(hres))
259         return NULL;
260 
261     hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
262     if(SUCCEEDED(hres)) {
263         FIXME("Use IClassFactoryEx\n");
264         IClassFactoryEx_Release(cfex);
265     }
266 
267     hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
268     if(FAILED(hres))
269         return NULL;
270 
271     if(secmgr) {
272         cs.clsid = guid;
273         cs.pUnk = obj;
274         cs.dwFlags = 0;
275         hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
276                 &bpolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
277         if(SUCCEEDED(hres)) {
278             policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW;
279             CoTaskMemFree(bpolicy);
280         }
281 
282         if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
283             IUnknown_Release(obj);
284             return NULL;
285         }
286     }
287 
288     hres = set_object_site(ctx, obj);
289     if(FAILED(hres)) {
290         IUnknown_Release(obj);
291         return NULL;
292     }
293 
294     return obj;
295 }
296 
297 static HRESULT show_msgbox(script_ctx_t *ctx, BSTR prompt, unsigned type, BSTR orig_title, VARIANT *res)
298 {
299     SCRIPTUICHANDLING uic_handling = SCRIPTUICHANDLING_ALLOW;
300     IActiveScriptSiteUIControl *ui_control;
301     IActiveScriptSiteWindow *acts_window;
302     WCHAR *title_buf = NULL;
303     const WCHAR *title;
304     HWND hwnd = NULL;
305     int ret = 0;
306     HRESULT hres;
307 
308     hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteUIControl, (void**)&ui_control);
309     if(SUCCEEDED(hres)) {
310         hres = IActiveScriptSiteUIControl_GetUIBehavior(ui_control, SCRIPTUICITEM_MSGBOX, &uic_handling);
311         IActiveScriptSiteUIControl_Release(ui_control);
312         if(FAILED(hres))
313             uic_handling = SCRIPTUICHANDLING_ALLOW;
314     }
315 
316     switch(uic_handling) {
317     case SCRIPTUICHANDLING_ALLOW:
318         break;
319     case SCRIPTUICHANDLING_NOUIDEFAULT:
320         return return_short(res, 0);
321     default:
322         FIXME("blocked\n");
323         return E_FAIL;
324     }
325 
326     hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteWindow, (void**)&acts_window);
327     if(FAILED(hres)) {
328         FIXME("No IActiveScriptSiteWindow\n");
329         return hres;
330     }
331 
332     if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
333         if(orig_title && *orig_title) {
334             WCHAR *ptr;
335 
336             title = title_buf = heap_alloc(sizeof(vbscriptW) + (strlenW(orig_title)+2)*sizeof(WCHAR));
337             if(!title)
338                 return E_OUTOFMEMORY;
339 
340             memcpy(title_buf, vbscriptW, sizeof(vbscriptW));
341             ptr = title_buf + sizeof(vbscriptW)/sizeof(WCHAR)-1;
342 
343             *ptr++ = ':';
344             *ptr++ = ' ';
345             strcpyW(ptr, orig_title);
346         }else {
347             title = vbscriptW;
348         }
349     }else {
350         title = orig_title ? orig_title : emptyW;
351     }
352 
353     hres = IActiveScriptSiteWindow_GetWindow(acts_window, &hwnd);
354     if(SUCCEEDED(hres)) {
355         hres = IActiveScriptSiteWindow_EnableModeless(acts_window, FALSE);
356         if(SUCCEEDED(hres)) {
357             ret = MessageBoxW(hwnd, prompt, title, type);
358             hres = IActiveScriptSiteWindow_EnableModeless(acts_window, TRUE);
359         }
360     }
361 
362     heap_free(title_buf);
363     IActiveScriptSiteWindow_Release(acts_window);
364     if(FAILED(hres)) {
365         FIXME("failed: %08x\n", hres);
366         return hres;
367     }
368 
369     return return_short(res, ret);
370 }
371 
372 static HRESULT Global_CCur(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
373 {
374     VARIANT v;
375     HRESULT hres;
376 
377     TRACE("%s\n", debugstr_variant(arg));
378 
379     assert(args_cnt == 1);
380 
381     V_VT(&v) = VT_EMPTY;
382     hres = VariantChangeType(&v, arg, 0, VT_CY);
383     if(FAILED(hres))
384         return hres;
385 
386     if(!res) {
387         VariantClear(&v);
388         return DISP_E_BADVARTYPE;
389     }
390 
391     *res = v;
392     return S_OK;
393 }
394 
395 static HRESULT Global_CInt(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
396 {
397     VARIANT v;
398     HRESULT hres;
399 
400     TRACE("%s\n", debugstr_variant(arg));
401 
402     assert(args_cnt == 1);
403 
404     V_VT(&v) = VT_EMPTY;
405     hres = VariantChangeType(&v, arg, 0, VT_I2);
406     if(FAILED(hres))
407         return hres;
408 
409     if(!res)
410         return DISP_E_BADVARTYPE;
411     else {
412         *res = v;
413         return S_OK;
414     }
415 }
416 
417 static HRESULT Global_CLng(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
418 {
419     int i;
420     HRESULT hres;
421 
422     TRACE("%s\n", debugstr_variant(arg));
423 
424     assert(args_cnt == 1);
425 
426     hres = to_int(arg, &i);
427     if(FAILED(hres))
428         return hres;
429     if(!res)
430         return DISP_E_BADVARTYPE;
431 
432     return return_int(res, i);
433 }
434 
435 static HRESULT Global_CBool(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
436 {
437     VARIANT v;
438     HRESULT hres;
439 
440     TRACE("%s\n", debugstr_variant(arg));
441 
442     assert(args_cnt == 1);
443 
444     V_VT(&v) = VT_EMPTY;
445     hres = VariantChangeType(&v, arg, VARIANT_LOCALBOOL, VT_BOOL);
446     if(FAILED(hres))
447         return hres;
448 
449     if(res)
450         *res = v;
451     else
452         VariantClear(&v);
453     return S_OK;
454 }
455 
456 static HRESULT Global_CByte(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
457 {
458     VARIANT v;
459     HRESULT hres;
460 
461     TRACE("%s\n", debugstr_variant(arg));
462 
463     assert(args_cnt == 1);
464 
465     V_VT(&v) = VT_EMPTY;
466     hres = VariantChangeType(&v, arg, VARIANT_LOCALBOOL, VT_UI1);
467     if(FAILED(hres))
468         return hres;
469 
470     if(!res) {
471         VariantClear(&v);
472         return DISP_E_BADVARTYPE;
473     }
474 
475     *res = v;
476     return S_OK;
477 }
478 
479 static HRESULT Global_CDate(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
480 {
481     FIXME("\n");
482     return E_NOTIMPL;
483 }
484 
485 static HRESULT Global_CDbl(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
486 {
487     VARIANT v;
488     HRESULT hres;
489 
490     TRACE("%s\n", debugstr_variant(arg));
491 
492     assert(args_cnt == 1);
493 
494     V_VT(&v) = VT_EMPTY;
495     hres = VariantChangeType(&v, arg, 0, VT_R8);
496     if(FAILED(hres))
497         return hres;
498 
499     if(!res)
500         return DISP_E_BADVARTYPE;
501     else {
502         *res = v;
503         return S_OK;
504     }
505 }
506 
507 static HRESULT Global_CSng(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
508 {
509     VARIANT v;
510     HRESULT hres;
511 
512     TRACE("%s\n", debugstr_variant(arg));
513 
514     assert(args_cnt == 1);
515 
516     V_VT(&v) = VT_EMPTY;
517     hres = VariantChangeType(&v, arg, 0, VT_R4);
518     if(FAILED(hres))
519         return hres;
520 
521     if(!res)
522         return DISP_E_BADVARTYPE;
523 
524    *res = v;
525    return S_OK;
526 }
527 
528 static HRESULT Global_CStr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
529 {
530     BSTR str;
531     HRESULT hres;
532 
533     TRACE("%s\n", debugstr_variant(arg));
534 
535     hres = to_string(arg, &str);
536     if(FAILED(hres))
537         return hres;
538 
539     return return_bstr(res, str);
540 }
541 
542 static inline WCHAR hex_char(unsigned n)
543 {
544     return n < 10 ? '0'+n : 'A'+n-10;
545 }
546 
547 static HRESULT Global_Hex(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
548 {
549     WCHAR buf[17], *ptr;
550     DWORD n;
551     HRESULT hres;
552     int ret;
553 
554     TRACE("%s\n", debugstr_variant(arg));
555 
556     switch(V_VT(arg)) {
557     case VT_I2:
558         n = (WORD)V_I2(arg);
559         break;
560     case VT_NULL:
561         if(res)
562             V_VT(res) = VT_NULL;
563         return S_OK;
564     default:
565         hres = to_int(arg, &ret);
566         if(FAILED(hres))
567             return hres;
568         else
569             n = ret;
570     }
571 
572     buf[16] = 0;
573     ptr = buf+15;
574 
575     if(n) {
576         do {
577             *ptr-- = hex_char(n & 0xf);
578             n >>= 4;
579         }while(n);
580         ptr++;
581     }else {
582         *ptr = '0';
583     }
584 
585     return return_string(res, ptr);
586 }
587 
588 static HRESULT Global_Oct(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
589 {
590     HRESULT hres;
591     WCHAR buf[23], *ptr;
592     DWORD n;
593     int ret;
594 
595     TRACE("%s\n", debugstr_variant(arg));
596 
597     switch(V_VT(arg)) {
598     case VT_I2:
599         n = (WORD)V_I2(arg);
600         break;
601     case VT_NULL:
602         if(res)
603             V_VT(res) = VT_NULL;
604         return S_OK;
605     default:
606         hres = to_int(arg, &ret);
607         if(FAILED(hres))
608             return hres;
609         else
610             n = ret;
611     }
612 
613     buf[22] = 0;
614     ptr = buf + 21;
615 
616     if(n) {
617         do {
618             *ptr-- = '0' + (n & 0x7);
619             n >>= 3;
620         }while(n);
621         ptr++;
622     }else {
623         *ptr = '0';
624     }
625 
626     return return_string(res, ptr);
627 }
628 
629 static HRESULT Global_VarType(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
630 {
631     TRACE("(%s)\n", debugstr_variant(arg));
632 
633     assert(args_cnt == 1);
634 
635     if(V_VT(arg) & ~VT_TYPEMASK) {
636         FIXME("not supported %s\n", debugstr_variant(arg));
637         return E_NOTIMPL;
638     }
639 
640     return return_short(res, V_VT(arg));
641 }
642 
643 static HRESULT Global_IsDate(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
644 {
645     FIXME("\n");
646     return E_NOTIMPL;
647 }
648 
649 static HRESULT Global_IsEmpty(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
650 {
651     TRACE("(%s)\n", debugstr_variant(arg));
652 
653     assert(args_cnt == 1);
654 
655     if(res) {
656         V_VT(res) = VT_BOOL;
657         V_BOOL(res) = V_VT(arg) == VT_EMPTY ? VARIANT_TRUE : VARIANT_FALSE;
658     }
659     return S_OK;
660 }
661 
662 static HRESULT Global_IsNull(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
663 {
664     TRACE("(%s)\n", debugstr_variant(arg));
665 
666     assert(args_cnt == 1);
667 
668     if(res) {
669         V_VT(res) = VT_BOOL;
670         V_BOOL(res) = V_VT(arg) == VT_NULL ? VARIANT_TRUE : VARIANT_FALSE;
671     }
672     return S_OK;
673 }
674 
675 static HRESULT Global_IsNumeric(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
676 {
677     HRESULT hres;
678     double d;
679 
680     TRACE("(%s)\n", debugstr_variant(arg));
681 
682     assert(args_cnt == 1);
683 
684     hres = to_double(arg, &d);
685 
686     return return_bool(res, SUCCEEDED(hres));
687 }
688 
689 static HRESULT Global_IsArray(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
690 {
691     FIXME("\n");
692     return E_NOTIMPL;
693 }
694 
695 static HRESULT Global_IsObject(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
696 {
697     TRACE("(%s)\n", debugstr_variant(arg));
698 
699     assert(args_cnt == 1);
700 
701     if(res) {
702         V_VT(res) = VT_BOOL;
703         V_BOOL(res) = V_VT(arg) == VT_DISPATCH ? VARIANT_TRUE : VARIANT_FALSE;
704     }
705     return S_OK;
706 }
707 
708 static HRESULT Global_Atn(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
709 {
710     HRESULT hres;
711     double d;
712 
713     hres = to_double(arg, &d);
714     if(FAILED(hres))
715         return hres;
716 
717     return return_double(res, atan(d));
718 }
719 
720 static HRESULT Global_Cos(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
721 {
722     HRESULT hres;
723     double d;
724 
725     hres = to_double(arg, &d);
726     if(FAILED(hres))
727         return hres;
728 
729     return return_double(res, cos(d));
730 }
731 
732 static HRESULT Global_Sin(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
733 {
734     HRESULT hres;
735     double d;
736 
737     hres = to_double(arg, &d);
738     if(FAILED(hres))
739         return hres;
740 
741     return return_double(res, sin(d));
742 }
743 
744 static HRESULT Global_Tan(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
745 {
746     HRESULT hres;
747     double d;
748 
749     hres = to_double(arg, &d);
750     if(FAILED(hres))
751         return hres;
752 
753     return return_double(res, tan(d));
754 }
755 
756 static HRESULT Global_Exp(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
757 {
758     HRESULT hres;
759     double d;
760 
761     hres = to_double(arg, &d);
762     if(FAILED(hres))
763         return hres;
764 
765     return return_double(res, exp(d));
766 }
767 
768 static HRESULT Global_Log(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
769 {
770     HRESULT hres;
771     double d;
772 
773     hres = to_double(arg, &d);
774     if(FAILED(hres))
775         return hres;
776 
777     if(d <= 0)
778         return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
779     else
780         return return_double(res, log(d));
781 }
782 
783 static HRESULT Global_Sqr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
784 {
785     HRESULT hres;
786     double d;
787 
788     hres = to_double(arg, &d);
789     if(FAILED(hres))
790         return hres;
791 
792     if(d < 0)
793         return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
794     else
795         return return_double(res, sqrt(d));
796 }
797 
798 static HRESULT Global_Randomize(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
799 {
800     FIXME("\n");
801     return E_NOTIMPL;
802 }
803 
804 static HRESULT Global_Rnd(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
805 {
806     FIXME("\n");
807     return E_NOTIMPL;
808 }
809 
810 static HRESULT Global_Timer(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
811 {
812     SYSTEMTIME lt;
813     double sec;
814 
815     GetLocalTime(&lt);
816     sec = lt.wHour * 3600 + lt.wMinute * 60 + lt.wSecond + lt.wMilliseconds / 1000.0;
817     return return_float(res, sec);
818 
819 }
820 
821 static HRESULT Global_LBound(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
822 {
823     FIXME("\n");
824     return E_NOTIMPL;
825 }
826 
827 static HRESULT Global_UBound(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
828 {
829     SAFEARRAY *sa;
830     HRESULT hres;
831     LONG ubound;
832     int dim;
833 
834     assert(args_cnt == 1 || args_cnt == 2);
835 
836     TRACE("%s %s\n", debugstr_variant(arg), args_cnt == 2 ? debugstr_variant(arg + 1) : "1");
837 
838     switch(V_VT(arg)) {
839     case VT_VARIANT|VT_ARRAY:
840         sa = V_ARRAY(arg);
841         break;
842     case VT_VARIANT|VT_ARRAY|VT_BYREF:
843         sa = *V_ARRAYREF(arg);
844         break;
845     default:
846         FIXME("arg %s not supported\n", debugstr_variant(arg));
847         return E_NOTIMPL;
848     }
849 
850     if(args_cnt == 2) {
851         hres = to_int(arg + 1, &dim);
852         if(FAILED(hres))
853             return hres;
854     }else {
855         dim = 1;
856     }
857 
858     hres = SafeArrayGetUBound(sa, dim, &ubound);
859     if(FAILED(hres))
860         return hres;
861 
862     return return_int(res, ubound);
863 }
864 
865 static HRESULT Global_RGB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
866 {
867     HRESULT hres;
868     int i, color[3];
869 
870     TRACE("%s %s %s\n", debugstr_variant(arg), debugstr_variant(arg + 1), debugstr_variant(arg + 2));
871 
872     assert(args_cnt == 3);
873 
874     for(i = 0; i < 3; i++) {
875         hres = to_int(arg + i, color + i);
876         if(FAILED(hres))
877             return hres;
878         if(color[i] > 255)
879             color[i] = 255;
880         if(color[i] < 0)
881             return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
882     }
883 
884     return return_int(res, RGB(color[0], color[1], color[2]));
885 }
886 
887 static HRESULT Global_Len(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
888 {
889     DWORD len;
890     HRESULT hres;
891 
892     TRACE("%s\n", debugstr_variant(arg));
893 
894     if(V_VT(arg) == VT_NULL)
895         return return_null(res);
896 
897     if(V_VT(arg) != VT_BSTR) {
898         BSTR str;
899 
900         hres = to_string(arg, &str);
901         if(FAILED(hres))
902             return hres;
903 
904         len = SysStringLen(str);
905         SysFreeString(str);
906     }else {
907         len = SysStringLen(V_BSTR(arg));
908     }
909 
910     return return_int(res, len);
911 }
912 
913 static HRESULT Global_LenB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
914 {
915     FIXME("\n");
916     return E_NOTIMPL;
917 }
918 
919 static HRESULT Global_Left(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
920 {
921     BSTR str, ret, conv_str = NULL;
922     int len, str_len;
923     HRESULT hres;
924 
925     TRACE("(%s %s)\n", debugstr_variant(args+1), debugstr_variant(args));
926 
927     if(V_VT(args) == VT_BSTR) {
928         str = V_BSTR(args);
929     }else {
930         hres = to_string(args, &conv_str);
931         if(FAILED(hres))
932             return hres;
933         str = conv_str;
934     }
935 
936     hres = to_int(args+1, &len);
937     if(FAILED(hres))
938         return hres;
939 
940     if(len < 0) {
941         FIXME("len = %d\n", len);
942         return E_FAIL;
943     }
944 
945     str_len = SysStringLen(str);
946     if(len > str_len)
947         len = str_len;
948 
949     ret = SysAllocStringLen(str, len);
950     SysFreeString(conv_str);
951     if(!ret)
952         return E_OUTOFMEMORY;
953 
954     return return_bstr(res, ret);
955 }
956 
957 static HRESULT Global_LeftB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
958 {
959     FIXME("\n");
960     return E_NOTIMPL;
961 }
962 
963 static HRESULT Global_Right(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
964 {
965     BSTR str, ret, conv_str = NULL;
966     int len, str_len;
967     HRESULT hres;
968 
969     TRACE("(%s %s)\n", debugstr_variant(args), debugstr_variant(args+1));
970 
971     if(V_VT(args+1) == VT_BSTR) {
972         str = V_BSTR(args);
973     }else {
974         hres = to_string(args, &conv_str);
975         if(FAILED(hres))
976             return hres;
977         str = conv_str;
978     }
979 
980     hres = to_int(args+1, &len);
981     if(FAILED(hres))
982         return hres;
983 
984     if(len < 0) {
985         FIXME("len = %d\n", len);
986         return E_FAIL;
987     }
988 
989     str_len = SysStringLen(str);
990     if(len > str_len)
991         len = str_len;
992 
993     ret = SysAllocStringLen(str+str_len-len, len);
994     SysFreeString(conv_str);
995     if(!ret)
996         return E_OUTOFMEMORY;
997 
998     return return_bstr(res, ret);
999 }
1000 
1001 static HRESULT Global_RightB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1002 {
1003     FIXME("\n");
1004     return E_NOTIMPL;
1005 }
1006 
1007 static HRESULT Global_Mid(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1008 {
1009     int len = -1, start, str_len;
1010     BSTR str;
1011     HRESULT hres;
1012 
1013     TRACE("(%s %s ...)\n", debugstr_variant(args), debugstr_variant(args+1));
1014 
1015     assert(args_cnt == 2 || args_cnt == 3);
1016 
1017     if(V_VT(args) != VT_BSTR) {
1018         FIXME("args[0] = %s\n", debugstr_variant(args));
1019         return E_NOTIMPL;
1020     }
1021 
1022     str = V_BSTR(args);
1023 
1024     hres = to_int(args+1, &start);
1025     if(FAILED(hres))
1026         return hres;
1027 
1028     if(args_cnt == 3) {
1029         hres = to_int(args+2, &len);
1030         if(FAILED(hres))
1031             return hres;
1032 
1033         if(len < 0) {
1034             FIXME("len = %d\n", len);
1035             return E_FAIL;
1036         }
1037     }
1038 
1039 
1040     str_len = SysStringLen(str);
1041     start--;
1042     if(start > str_len)
1043         start = str_len;
1044 
1045     if(len == -1)
1046         len = str_len-start;
1047     else if(len > str_len-start)
1048         len = str_len-start;
1049 
1050     if(res) {
1051         V_VT(res) = VT_BSTR;
1052         V_BSTR(res) = SysAllocStringLen(str+start, len);
1053         if(!V_BSTR(res))
1054             return E_OUTOFMEMORY;
1055     }
1056 
1057     return S_OK;
1058 }
1059 
1060 static HRESULT Global_MidB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1061 {
1062     FIXME("\n");
1063     return E_NOTIMPL;
1064 }
1065 
1066 static HRESULT Global_StrComp(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1067 {
1068     BSTR left, right;
1069     int mode, ret;
1070     HRESULT hres;
1071     short val;
1072 
1073     TRACE("(%s %s ...)\n", debugstr_variant(args), debugstr_variant(args+1));
1074 
1075     assert(args_cnt == 2 || args_cnt == 3);
1076 
1077     if (args_cnt == 3) {
1078         hres = to_int(args+2, &mode);
1079         if(FAILED(hres))
1080             return hres;
1081 
1082         if (mode != 0 && mode != 1) {
1083             FIXME("unknown compare mode = %d\n", mode);
1084             return E_FAIL;
1085         }
1086     }
1087     else
1088         mode = 0;
1089 
1090     hres = to_string(args, &left);
1091     if(FAILED(hres))
1092         return hres;
1093 
1094     hres = to_string(args+1, &right);
1095     if(FAILED(hres))
1096     {
1097         SysFreeString(left);
1098         return hres;
1099     }
1100 
1101     ret = mode ? strcmpiW(left, right) : strcmpW(left, right);
1102     val = ret < 0 ? -1 : (ret > 0 ? 1 : 0);
1103 
1104     SysFreeString(left);
1105     SysFreeString(right);
1106     return return_short(res, val);
1107 }
1108 
1109 static HRESULT Global_LCase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1110 {
1111     BSTR str;
1112     HRESULT hres;
1113 
1114     TRACE("%s\n", debugstr_variant(arg));
1115 
1116     if(V_VT(arg) == VT_NULL) {
1117         if(res)
1118             V_VT(res) = VT_NULL;
1119         return S_OK;
1120     }
1121 
1122     hres = to_string(arg, &str);
1123     if(FAILED(hres))
1124         return hres;
1125 
1126     if(res) {
1127         WCHAR *ptr;
1128 
1129         for(ptr = str; *ptr; ptr++)
1130             *ptr = tolowerW(*ptr);
1131 
1132         V_VT(res) = VT_BSTR;
1133         V_BSTR(res) = str;
1134     }else {
1135         SysFreeString(str);
1136     }
1137     return S_OK;
1138 }
1139 
1140 static HRESULT Global_UCase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1141 {
1142     BSTR str;
1143     HRESULT hres;
1144 
1145     TRACE("%s\n", debugstr_variant(arg));
1146 
1147     if(V_VT(arg) == VT_NULL) {
1148         if(res)
1149             V_VT(res) = VT_NULL;
1150         return S_OK;
1151     }
1152 
1153     hres = to_string(arg, &str);
1154     if(FAILED(hres))
1155         return hres;
1156 
1157     if(res) {
1158         WCHAR *ptr;
1159 
1160         for(ptr = str; *ptr; ptr++)
1161             *ptr = toupperW(*ptr);
1162 
1163         V_VT(res) = VT_BSTR;
1164         V_BSTR(res) = str;
1165     }else {
1166         SysFreeString(str);
1167     }
1168     return S_OK;
1169 }
1170 
1171 static HRESULT Global_LTrim(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1172 {
1173     BSTR str, conv_str = NULL;
1174     WCHAR *ptr;
1175     HRESULT hres;
1176 
1177     TRACE("%s\n", debugstr_variant(arg));
1178 
1179     if(V_VT(arg) == VT_BSTR) {
1180         str = V_BSTR(arg);
1181     }else {
1182         hres = to_string(arg, &conv_str);
1183         if(FAILED(hres))
1184             return hres;
1185         str = conv_str;
1186     }
1187 
1188     for(ptr = str; *ptr && isspaceW(*ptr); ptr++);
1189 
1190     str = SysAllocString(ptr);
1191     SysFreeString(conv_str);
1192     if(!str)
1193         return E_OUTOFMEMORY;
1194 
1195     return return_bstr(res, str);
1196 }
1197 
1198 static HRESULT Global_RTrim(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1199 {
1200     BSTR str, conv_str = NULL;
1201     WCHAR *ptr;
1202     HRESULT hres;
1203 
1204     TRACE("%s\n", debugstr_variant(arg));
1205 
1206     if(V_VT(arg) == VT_BSTR) {
1207         str = V_BSTR(arg);
1208     }else {
1209         hres = to_string(arg, &conv_str);
1210         if(FAILED(hres))
1211             return hres;
1212         str = conv_str;
1213     }
1214 
1215     for(ptr = str+SysStringLen(str); ptr-1 > str && isspaceW(*(ptr-1)); ptr--);
1216 
1217     str = SysAllocStringLen(str, ptr-str);
1218     SysFreeString(conv_str);
1219     if(!str)
1220         return E_OUTOFMEMORY;
1221 
1222     return return_bstr(res, str);
1223 }
1224 
1225 static HRESULT Global_Trim(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1226 {
1227     BSTR str, conv_str = NULL;
1228     WCHAR *begin_ptr, *end_ptr;
1229     HRESULT hres;
1230 
1231     TRACE("%s\n", debugstr_variant(arg));
1232 
1233     if(V_VT(arg) == VT_BSTR) {
1234         str = V_BSTR(arg);
1235     }else {
1236         hres = to_string(arg, &conv_str);
1237         if(FAILED(hres))
1238             return hres;
1239         str = conv_str;
1240     }
1241 
1242     for(begin_ptr = str; *begin_ptr && isspaceW(*begin_ptr); begin_ptr++);
1243     for(end_ptr = str+SysStringLen(str); end_ptr-1 > begin_ptr && isspaceW(*(end_ptr-1)); end_ptr--);
1244 
1245     str = SysAllocStringLen(begin_ptr, end_ptr-begin_ptr);
1246     SysFreeString(conv_str);
1247     if(!str)
1248         return E_OUTOFMEMORY;
1249 
1250     return return_bstr(res, str);
1251 }
1252 
1253 static HRESULT Global_Space(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1254 {
1255     BSTR str;
1256     int n, i;
1257     HRESULT hres;
1258 
1259     TRACE("%s\n", debugstr_variant(arg));
1260 
1261     hres = to_int(arg, &n);
1262     if(FAILED(hres))
1263         return hres;
1264 
1265     if(n < 0) {
1266         FIXME("n = %d\n", n);
1267         return E_NOTIMPL;
1268     }
1269 
1270     if(!res)
1271         return S_OK;
1272 
1273     str = SysAllocStringLen(NULL, n);
1274     if(!str)
1275         return E_OUTOFMEMORY;
1276 
1277     for(i=0; i<n; i++)
1278         str[i] = ' ';
1279 
1280     V_VT(res) = VT_BSTR;
1281     V_BSTR(res) = str;
1282     return S_OK;
1283 }
1284 
1285 static HRESULT Global_String(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1286 {
1287     FIXME("\n");
1288     return E_NOTIMPL;
1289 }
1290 
1291 static HRESULT Global_InStr(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1292 {
1293     VARIANT *startv, *str1v, *str2v;
1294     BSTR str1, str2;
1295     int start, ret;
1296     HRESULT hres;
1297 
1298     TRACE("\n");
1299 
1300     assert(2 <= args_cnt && args_cnt <= 4);
1301 
1302     switch(args_cnt) {
1303     case 2:
1304         startv = NULL;
1305         str1v = args;
1306         str2v = args+1;
1307         break;
1308     case 3:
1309         startv = args;
1310         str1v = args+1;
1311         str2v = args+2;
1312         break;
1313     case 4:
1314         FIXME("unsupported compare argument %s\n", debugstr_variant(args));
1315         return E_NOTIMPL;
1316     DEFAULT_UNREACHABLE;
1317     }
1318 
1319     if(startv) {
1320         hres = to_int(startv, &start);
1321         if(FAILED(hres))
1322             return hres;
1323         if(--start < 0) {
1324             FIXME("start %d\n", start);
1325             return E_FAIL;
1326         }
1327     }else {
1328         start = 0;
1329     }
1330 
1331     if(V_VT(str1v) == VT_NULL || V_VT(str2v) == VT_NULL)
1332         return return_null(res);
1333 
1334     if(V_VT(str1v) != VT_BSTR) {
1335         FIXME("Unsupported str1 type %s\n", debugstr_variant(str1v));
1336         return E_NOTIMPL;
1337     }
1338     str1 = V_BSTR(str1v);
1339 
1340     if(V_VT(str2v) != VT_BSTR) {
1341         FIXME("Unsupported str2 type %s\n", debugstr_variant(str2v));
1342         return E_NOTIMPL;
1343     }
1344     str2 = V_BSTR(str2v);
1345 
1346     if(start < SysStringLen(str1)) {
1347         WCHAR *ptr;
1348 
1349         ptr = strstrW(str1+start, str2);
1350         ret = ptr ? ptr-str1+1 : 0;
1351     }else {
1352         ret = 0;
1353     }
1354 
1355     return return_int(res, ret);
1356 }
1357 
1358 static HRESULT Global_InStrB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1359 {
1360     FIXME("\n");
1361     return E_NOTIMPL;
1362 }
1363 
1364 static HRESULT Global_AscB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1365 {
1366     FIXME("\n");
1367     return E_NOTIMPL;
1368 }
1369 
1370 static HRESULT Global_ChrB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1371 {
1372     FIXME("\n");
1373     return E_NOTIMPL;
1374 }
1375 
1376 static HRESULT Global_Asc(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1377 {
1378     FIXME("\n");
1379     return E_NOTIMPL;
1380 }
1381 
1382 /* The function supports only single-byte and double-byte character sets. It
1383  * ignores language specified by IActiveScriptSite::GetLCID. The argument needs
1384  * to be in range of short or unsigned short. */
1385 static HRESULT Global_Chr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1386 {
1387     int cp, c, len = 0;
1388     CPINFO cpi;
1389     WCHAR ch;
1390     char buf[2];
1391     HRESULT hres;
1392 
1393     TRACE("%s\n", debugstr_variant(arg));
1394 
1395     hres = to_int(arg, &c);
1396     if(FAILED(hres))
1397         return hres;
1398 
1399     cp = GetACP();
1400     if(!GetCPInfo(cp, &cpi))
1401         cpi.MaxCharSize = 1;
1402 
1403     if((c!=(short)c && c!=(unsigned short)c) ||
1404             (unsigned short)c>=(cpi.MaxCharSize>1 ? 0x10000 : 0x100)) {
1405         WARN("invalid arg %d\n", c);
1406         return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1407     }
1408 
1409     if(c>>8)
1410         buf[len++] = c>>8;
1411     if(!len || IsDBCSLeadByteEx(cp, buf[0]))
1412         buf[len++] = c;
1413     if(!MultiByteToWideChar(CP_ACP, 0, buf, len, &ch, 1)) {
1414         WARN("invalid arg %d, cp %d\n", c, cp);
1415         return E_FAIL;
1416     }
1417 
1418     if(res) {
1419         V_VT(res) = VT_BSTR;
1420         V_BSTR(res) = SysAllocStringLen(&ch, 1);
1421         if(!V_BSTR(res))
1422             return E_OUTOFMEMORY;
1423     }
1424     return S_OK;
1425 }
1426 
1427 static HRESULT Global_AscW(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1428 {
1429     FIXME("\n");
1430     return E_NOTIMPL;
1431 }
1432 
1433 static HRESULT Global_ChrW(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1434 {
1435     FIXME("\n");
1436     return E_NOTIMPL;
1437 }
1438 
1439 static HRESULT Global_Abs(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1440 {
1441     HRESULT hres;
1442     VARIANT dst;
1443 
1444     TRACE("(%s)\n", debugstr_variant(arg));
1445 
1446     assert(args_cnt == 1);
1447 
1448     hres = VarAbs(arg, &dst);
1449     if(FAILED(hres))
1450         return hres;
1451 
1452     if (res)
1453         *res = dst;
1454     else
1455         VariantClear(&dst);
1456 
1457     return S_OK;
1458 }
1459 
1460 static HRESULT Global_Fix(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1461 {
1462     HRESULT hres;
1463     VARIANT dst;
1464 
1465     TRACE("(%s)\n", debugstr_variant(arg));
1466 
1467     assert(args_cnt == 1);
1468 
1469     hres = VarFix(arg, &dst);
1470     if(FAILED(hres))
1471         return hres;
1472 
1473     if (res)
1474         *res = dst;
1475     else
1476         VariantClear(&dst);
1477 
1478     return S_OK;
1479 }
1480 
1481 static HRESULT Global_Int(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1482 {
1483     HRESULT hres;
1484     VARIANT dst;
1485 
1486     TRACE("(%s)\n", debugstr_variant(arg));
1487 
1488     assert(args_cnt == 1);
1489 
1490     hres = VarInt(arg, &dst);
1491     if(FAILED(hres))
1492         return hres;
1493 
1494     if (res)
1495         *res = dst;
1496     else
1497         VariantClear(&dst);
1498 
1499     return S_OK;
1500 }
1501 
1502 static HRESULT Global_Sgn(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1503 {
1504     double v;
1505     short val;
1506     HRESULT hres;
1507 
1508     TRACE("(%s)\n", debugstr_variant(arg));
1509 
1510     assert(args_cnt == 1);
1511 
1512     if(V_VT(arg) == VT_NULL)
1513         return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1514 
1515     hres = to_double(arg, &v);
1516     if (FAILED(hres))
1517         return hres;
1518 
1519     val = v == 0 ? 0 : (v > 0 ? 1 : -1);
1520     return return_short(res, val);
1521 }
1522 
1523 static HRESULT Global_Now(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1524 {
1525     SYSTEMTIME lt;
1526     double date;
1527 
1528     TRACE("\n");
1529 
1530     GetLocalTime(&lt);
1531     SystemTimeToVariantTime(&lt, &date);
1532     return return_date(res, date);
1533 }
1534 
1535 static HRESULT Global_Date(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1536 {
1537     SYSTEMTIME lt;
1538     UDATE ud;
1539     DATE date;
1540     HRESULT hres;
1541 
1542     TRACE("\n");
1543 
1544     GetLocalTime(&lt);
1545     ud.st = lt;
1546     ud.wDayOfYear = 0;
1547     hres = VarDateFromUdateEx(&ud, 0, VAR_DATEVALUEONLY, &date);
1548     if(FAILED(hres))
1549         return hres;
1550     return return_date(res, date);
1551 }
1552 
1553 static HRESULT Global_Time(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1554 {
1555     SYSTEMTIME lt;
1556     UDATE ud;
1557     DATE time;
1558     HRESULT hres;
1559 
1560     TRACE("\n");
1561 
1562     GetLocalTime(&lt);
1563     ud.st = lt;
1564     ud.wDayOfYear = 0;
1565     hres = VarDateFromUdateEx(&ud, 0, VAR_TIMEVALUEONLY, &time);
1566     if(FAILED(hres))
1567         return hres;
1568     return return_date(res, time);
1569 }
1570 
1571 static HRESULT Global_Day(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1572 {
1573     FIXME("\n");
1574     return E_NOTIMPL;
1575 }
1576 
1577 static HRESULT Global_Month(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1578 {
1579     FIXME("\n");
1580     return E_NOTIMPL;
1581 }
1582 
1583 static HRESULT Global_Weekday(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1584 {
1585     FIXME("\n");
1586     return E_NOTIMPL;
1587 }
1588 
1589 static HRESULT Global_Year(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1590 {
1591     FIXME("\n");
1592     return E_NOTIMPL;
1593 }
1594 
1595 static HRESULT Global_Hour(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1596 {
1597     FIXME("\n");
1598     return E_NOTIMPL;
1599 }
1600 
1601 static HRESULT Global_Minute(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1602 {
1603     FIXME("\n");
1604     return E_NOTIMPL;
1605 }
1606 
1607 static HRESULT Global_Second(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1608 {
1609     FIXME("\n");
1610     return E_NOTIMPL;
1611 }
1612 
1613 static HRESULT Global_DateValue(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1614 {
1615     FIXME("\n");
1616     return E_NOTIMPL;
1617 }
1618 
1619 static HRESULT Global_TimeValue(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1620 {
1621     FIXME("\n");
1622     return E_NOTIMPL;
1623 }
1624 
1625 static HRESULT Global_DateSerial(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1626 {
1627     FIXME("\n");
1628     return E_NOTIMPL;
1629 }
1630 
1631 static HRESULT Global_TimeSerial(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1632 {
1633     FIXME("\n");
1634     return E_NOTIMPL;
1635 }
1636 
1637 static HRESULT Global_InputBox(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1638 {
1639     FIXME("\n");
1640     return E_NOTIMPL;
1641 }
1642 
1643 static HRESULT Global_MsgBox(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1644 {
1645     BSTR prompt, title = NULL;
1646     int type = MB_OK;
1647     HRESULT hres;
1648 
1649     TRACE("\n");
1650 
1651     assert(1 <= args_cnt && args_cnt <= 5);
1652 
1653     hres = to_string(args, &prompt);
1654     if(FAILED(hres))
1655         return hres;
1656 
1657     if(args_cnt > 1)
1658         hres = to_int(args+1, &type);
1659 
1660     if(SUCCEEDED(hres) && args_cnt > 2)
1661         hres = to_string(args+2, &title);
1662 
1663     if(SUCCEEDED(hres) && args_cnt > 3) {
1664         FIXME("unsupported arg_cnt %d\n", args_cnt);
1665         hres = E_NOTIMPL;
1666     }
1667 
1668     if(SUCCEEDED(hres))
1669         hres = show_msgbox(This->desc->ctx, prompt, type, title, res);
1670 
1671     SysFreeString(prompt);
1672     SysFreeString(title);
1673     return hres;
1674 }
1675 
1676 static HRESULT Global_CreateObject(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1677 {
1678     IUnknown *obj;
1679     HRESULT hres;
1680 
1681     TRACE("(%s)\n", debugstr_variant(arg));
1682 
1683     if(V_VT(arg) != VT_BSTR) {
1684         FIXME("non-bstr arg\n");
1685         return E_INVALIDARG;
1686     }
1687 
1688     obj = create_object(This->desc->ctx, V_BSTR(arg));
1689     if(!obj)
1690         return VB_E_CANNOT_CREATE_OBJ;
1691 
1692     if(res) {
1693         hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&V_DISPATCH(res));
1694         if(FAILED(hres))
1695             return hres;
1696 
1697         V_VT(res) = VT_DISPATCH;
1698     }
1699 
1700     IUnknown_Release(obj);
1701     return S_OK;
1702 }
1703 
1704 static HRESULT Global_GetObject(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1705 {
1706     IBindCtx *bind_ctx;
1707     IUnknown *obj_unk;
1708     IDispatch *disp;
1709     ULONG eaten = 0;
1710     IMoniker *mon;
1711     HRESULT hres;
1712 
1713     TRACE("%s %s\n", args_cnt ? debugstr_variant(args) : "", args_cnt > 1 ? debugstr_variant(args+1) : "");
1714 
1715     if(args_cnt != 1 || V_VT(args) != VT_BSTR) {
1716         FIXME("unsupported args\n");
1717         return E_NOTIMPL;
1718     }
1719 
1720     if(This->desc->ctx->safeopt & (INTERFACE_USES_SECURITY_MANAGER|INTERFACESAFE_FOR_UNTRUSTED_DATA)) {
1721         WARN("blocked in current safety mode\n");
1722         return VB_E_CANNOT_CREATE_OBJ;
1723     }
1724 
1725     hres = CreateBindCtx(0, &bind_ctx);
1726     if(FAILED(hres))
1727         return hres;
1728 
1729     hres = MkParseDisplayName(bind_ctx, V_BSTR(args), &eaten, &mon);
1730     if(SUCCEEDED(hres)) {
1731         hres = IMoniker_BindToObject(mon, bind_ctx, NULL, &IID_IUnknown, (void**)&obj_unk);
1732         IMoniker_Release(mon);
1733     }else {
1734         hres = MK_E_SYNTAX;
1735     }
1736     IBindCtx_Release(bind_ctx);
1737     if(FAILED(hres))
1738         return hres;
1739 
1740     hres = set_object_site(This->desc->ctx, obj_unk);
1741     if(FAILED(hres)) {
1742         IUnknown_Release(obj_unk);
1743         return hres;
1744     }
1745 
1746     hres = IUnknown_QueryInterface(obj_unk, &IID_IDispatch, (void**)&disp);
1747     if(SUCCEEDED(hres)) {
1748         if(res) {
1749             V_VT(res) = VT_DISPATCH;
1750             V_DISPATCH(res) = disp;
1751         }else {
1752             IDispatch_Release(disp);
1753         }
1754     }else {
1755         FIXME("object does not support IDispatch\n");
1756     }
1757 
1758     return hres;
1759 }
1760 
1761 static HRESULT Global_DateAdd(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1762 {
1763     FIXME("\n");
1764     return E_NOTIMPL;
1765 }
1766 
1767 static HRESULT Global_DateDiff(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1768 {
1769     FIXME("\n");
1770     return E_NOTIMPL;
1771 }
1772 
1773 static HRESULT Global_DatePart(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1774 {
1775     FIXME("\n");
1776     return E_NOTIMPL;
1777 }
1778 
1779 static HRESULT Global_TypeName(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1780 {
1781     static const WCHAR ByteW[]     = {'B', 'y', 't', 'e', 0};
1782     static const WCHAR IntegerW[]  = {'I', 'n', 't', 'e', 'g', 'e', 'r', 0};
1783     static const WCHAR LongW[]     = {'L', 'o', 'n', 'g', 0};
1784     static const WCHAR SingleW[]   = {'S', 'i', 'n', 'g', 'l', 'e', 0};
1785     static const WCHAR DoubleW[]   = {'D', 'o', 'u', 'b', 'l', 'e', 0};
1786     static const WCHAR CurrencyW[] = {'C', 'u', 'r', 'r', 'e', 'n', 'c', 'y', 0};
1787     static const WCHAR DecimalW[]  = {'D', 'e', 'c', 'i', 'm', 'a', 'l', 0};
1788     static const WCHAR DateW[]     = {'D', 'a', 't', 'e', 0};
1789     static const WCHAR StringW[]   = {'S', 't', 'r', 'i', 'n', 'g', 0};
1790     static const WCHAR BooleanW[]  = {'B', 'o', 'o', 'l', 'e', 'a', 'n', 0};
1791     static const WCHAR EmptyW[]    = {'E', 'm', 'p', 't', 'y', 0};
1792     static const WCHAR NullW[]     = {'N', 'u', 'l', 'l', 0};
1793 
1794     TRACE("(%s)\n", debugstr_variant(arg));
1795 
1796     assert(args_cnt == 1);
1797 
1798     switch(V_VT(arg)) {
1799         case VT_UI1:
1800             return return_string(res, ByteW);
1801         case VT_I2:
1802             return return_string(res, IntegerW);
1803         case VT_I4:
1804             return return_string(res, LongW);
1805         case VT_R4:
1806             return return_string(res, SingleW);
1807         case VT_R8:
1808             return return_string(res, DoubleW);
1809         case VT_CY:
1810             return return_string(res, CurrencyW);
1811         case VT_DECIMAL:
1812             return return_string(res, DecimalW);
1813         case VT_DATE:
1814             return return_string(res, DateW);
1815         case VT_BSTR:
1816             return return_string(res, StringW);
1817         case VT_BOOL:
1818             return return_string(res, BooleanW);
1819         case VT_EMPTY:
1820             return return_string(res, EmptyW);
1821         case VT_NULL:
1822             return return_string(res, NullW);
1823         default:
1824             FIXME("arg %s not supported\n", debugstr_variant(arg));
1825             return E_NOTIMPL;
1826         }
1827 }
1828 
1829 static HRESULT Global_Array(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1830 {
1831     SAFEARRAYBOUND bounds;
1832     SAFEARRAY *sa;
1833     VARIANT *data;
1834     HRESULT hres;
1835     unsigned i;
1836 
1837     TRACE("arg_cnt=%u\n", args_cnt);
1838 
1839     bounds.lLbound = 0;
1840     bounds.cElements = args_cnt;
1841     sa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
1842     if(!sa)
1843         return E_OUTOFMEMORY;
1844 
1845     hres = SafeArrayAccessData(sa, (void**)&data);
1846     if(FAILED(hres)) {
1847         SafeArrayDestroy(sa);
1848         return hres;
1849     }
1850 
1851     for(i=0; i<args_cnt; i++) {
1852         hres = VariantCopyInd(data+i, arg+i);
1853         if(FAILED(hres)) {
1854             SafeArrayUnaccessData(sa);
1855             SafeArrayDestroy(sa);
1856             return hres;
1857         }
1858     }
1859     SafeArrayUnaccessData(sa);
1860 
1861     if(res) {
1862         V_VT(res) = VT_ARRAY|VT_VARIANT;
1863         V_ARRAY(res) = sa;
1864     }else {
1865         SafeArrayDestroy(sa);
1866     }
1867 
1868     return S_OK;
1869 }
1870 
1871 static HRESULT Global_Erase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1872 {
1873     FIXME("\n");
1874     return E_NOTIMPL;
1875 }
1876 
1877 static HRESULT Global_Filter(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1878 {
1879     FIXME("\n");
1880     return E_NOTIMPL;
1881 }
1882 
1883 static HRESULT Global_Join(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1884 {
1885     FIXME("\n");
1886     return E_NOTIMPL;
1887 }
1888 
1889 static HRESULT Global_Split(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1890 {
1891     FIXME("\n");
1892     return E_NOTIMPL;
1893 }
1894 
1895 static HRESULT Global_Replace(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1896 {
1897     FIXME("\n");
1898     return E_NOTIMPL;
1899 }
1900 
1901 static HRESULT Global_StrReverse(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1902 {
1903     WCHAR *ptr1, *ptr2, ch;
1904     BSTR ret;
1905     HRESULT hres;
1906 
1907     TRACE("%s\n", debugstr_variant(arg));
1908 
1909     hres = to_string(arg, &ret);
1910     if(FAILED(hres))
1911         return hres;
1912 
1913     ptr1 = ret;
1914     ptr2 = ret + SysStringLen(ret)-1;
1915     while(ptr1 < ptr2) {
1916         ch = *ptr1;
1917         *ptr1++ = *ptr2;
1918         *ptr2-- = ch;
1919     }
1920 
1921     return return_bstr(res, ret);
1922 }
1923 
1924 static HRESULT Global_InStrRev(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1925 {
1926     int start, ret = 0;
1927     BSTR str1, str2;
1928     HRESULT hres;
1929 
1930     TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args), debugstr_variant(args+1), args_cnt);
1931 
1932     if(args_cnt > 3) {
1933         FIXME("Unsupported args\n");
1934         return E_NOTIMPL;
1935     }
1936 
1937     assert(2 <= args_cnt && args_cnt <= 4);
1938 
1939     if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL))
1940         return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1941 
1942     hres = to_string(args, &str1);
1943     if(FAILED(hres))
1944         return hres;
1945 
1946     hres = to_string(args+1, &str2);
1947     if(SUCCEEDED(hres)) {
1948         if(args_cnt > 2) {
1949             hres = to_int(args+2, &start);
1950             if(SUCCEEDED(hres) && start <= 0) {
1951                 FIXME("Unsupported start %d\n", start);
1952                 hres = E_NOTIMPL;
1953             }
1954         }else {
1955             start = SysStringLen(str1);
1956         }
1957     } else {
1958         str2 = NULL;
1959     }
1960 
1961     if(SUCCEEDED(hres)) {
1962         const WCHAR *ptr;
1963         size_t len;
1964 
1965         len = SysStringLen(str2);
1966         if(start >= len && start <= SysStringLen(str1)) {
1967             for(ptr = str1+start-SysStringLen(str2); ptr >= str1; ptr--) {
1968                 if(!memcmp(ptr, str2, len*sizeof(WCHAR))) {
1969                     ret = ptr-str1+1;
1970                     break;
1971                 }
1972             }
1973         }
1974     }
1975 
1976     SysFreeString(str1);
1977     SysFreeString(str2);
1978     if(FAILED(hres))
1979         return hres;
1980 
1981     return return_int(res, ret);
1982 }
1983 
1984 static HRESULT Global_LoadPicture(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1985 {
1986     FIXME("\n");
1987     return E_NOTIMPL;
1988 }
1989 
1990 static HRESULT Global_ScriptEngine(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1991 {
1992     TRACE("%s\n", debugstr_variant(arg));
1993 
1994     assert(args_cnt == 0);
1995 
1996     return return_string(res, vbscriptW);
1997 }
1998 
1999 static HRESULT Global_ScriptEngineMajorVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2000 {
2001     TRACE("%s\n", debugstr_variant(arg));
2002 
2003     assert(args_cnt == 0);
2004 
2005     return return_int(res, VBSCRIPT_MAJOR_VERSION);
2006 }
2007 
2008 static HRESULT Global_ScriptEngineMinorVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2009 {
2010     TRACE("%s\n", debugstr_variant(arg));
2011 
2012     assert(args_cnt == 0);
2013 
2014     return return_int(res, VBSCRIPT_MINOR_VERSION);
2015 }
2016 
2017 static HRESULT Global_ScriptEngineBuildVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2018 {
2019     TRACE("%s\n", debugstr_variant(arg));
2020 
2021     assert(args_cnt == 0);
2022 
2023     return return_int(res, VBSCRIPT_BUILD_VERSION);
2024 }
2025 
2026 static HRESULT Global_FormatNumber(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2027 {
2028     FIXME("\n");
2029     return E_NOTIMPL;
2030 }
2031 
2032 static HRESULT Global_FormatCurrency(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2033 {
2034     FIXME("\n");
2035     return E_NOTIMPL;
2036 }
2037 
2038 static HRESULT Global_FormatPercent(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2039 {
2040     FIXME("\n");
2041     return E_NOTIMPL;
2042 }
2043 
2044 static HRESULT Global_FormatDateTime(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2045 {
2046     FIXME("\n");
2047     return E_NOTIMPL;
2048 }
2049 
2050 static HRESULT Global_WeekdayName(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2051 {
2052     int weekday, first_day = 1, abbrev = 0;
2053     BSTR ret;
2054     HRESULT hres;
2055 
2056     TRACE("\n");
2057 
2058     assert(1 <= args_cnt && args_cnt <= 3);
2059 
2060     hres = to_int(args, &weekday);
2061     if(FAILED(hres))
2062         return hres;
2063 
2064     if(args_cnt > 1) {
2065         hres = to_int(args+1, &abbrev);
2066         if(FAILED(hres))
2067             return hres;
2068 
2069         if(args_cnt == 3) {
2070             hres = to_int(args+2, &first_day);
2071             if(FAILED(hres))
2072                 return hres;
2073         }
2074     }
2075 
2076     hres = VarWeekdayName(weekday, abbrev, first_day, 0, &ret);
2077     if(FAILED(hres))
2078         return hres;
2079 
2080     return return_bstr(res, ret);
2081 }
2082 
2083 static HRESULT Global_MonthName(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2084 {
2085     int month, abbrev = 0;
2086     BSTR ret;
2087     HRESULT hres;
2088 
2089     TRACE("\n");
2090 
2091     assert(args_cnt == 1 || args_cnt == 2);
2092 
2093     hres = to_int(args, &month);
2094     if(FAILED(hres))
2095         return hres;
2096 
2097     if(args_cnt == 2) {
2098         hres = to_int(args+1, &abbrev);
2099         if(FAILED(hres))
2100             return hres;
2101     }
2102 
2103     hres = VarMonthName(month, abbrev, 0, &ret);
2104     if(FAILED(hres))
2105         return hres;
2106 
2107     return return_bstr(res, ret);
2108 }
2109 
2110 static HRESULT Global_Round(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2111 {
2112     double n;
2113     HRESULT hres;
2114 
2115     TRACE("%s\n", debugstr_variant(arg));
2116 
2117     if(!res)
2118         return S_OK;
2119 
2120     switch(V_VT(arg)) {
2121     case VT_I2:
2122     case VT_I4:
2123     case VT_BOOL:
2124         *res = *arg;
2125         return S_OK;
2126     case VT_R8:
2127         n = V_R8(arg);
2128         break;
2129     default:
2130         hres = to_double(arg, &n);
2131         if(FAILED(hres))
2132             return hres;
2133     }
2134 
2135     return return_double(res, round(n));
2136 }
2137 
2138 static HRESULT Global_Escape(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2139 {
2140     FIXME("\n");
2141     return E_NOTIMPL;
2142 }
2143 
2144 static HRESULT Global_Unescape(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2145 {
2146     FIXME("\n");
2147     return E_NOTIMPL;
2148 }
2149 
2150 static HRESULT Global_Eval(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2151 {
2152     FIXME("\n");
2153     return E_NOTIMPL;
2154 }
2155 
2156 static HRESULT Global_Execute(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2157 {
2158     FIXME("\n");
2159     return E_NOTIMPL;
2160 }
2161 
2162 static HRESULT Global_ExecuteGlobal(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2163 {
2164     FIXME("\n");
2165     return E_NOTIMPL;
2166 }
2167 
2168 static HRESULT Global_GetRef(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2169 {
2170     FIXME("\n");
2171     return E_NOTIMPL;
2172 }
2173 
2174 static const string_constant_t vbCr          = {1, {'\r'}};
2175 static const string_constant_t vbCrLf        = {2, {'\r','\n'}};
2176 static const string_constant_t vbNewLine     = {2, {'\r','\n'}};
2177 static const string_constant_t vbFormFeed    = {1, {0xc}};
2178 static const string_constant_t vbLf          = {1, {'\n'}};
2179 static const string_constant_t vbNullChar    = {1};
2180 static const string_constant_t vbNullString  = {0};
2181 static const string_constant_t vbTab         = {1, {'\t'}};
2182 static const string_constant_t vbVerticalTab = {1, {0xb}};
2183 
2184 static const builtin_prop_t global_props[] = {
2185     {DISPID_GLOBAL_VBUSESYSTEM,        NULL, BP_GET, VT_I2, 0},
2186     {DISPID_GLOBAL_USESYSTEMDAYOFWEEK, NULL, BP_GET, VT_I2, 0},
2187     {DISPID_GLOBAL_VBSUNDAY,           NULL, BP_GET, VT_I2, 1},
2188     {DISPID_GLOBAL_VBMONDAY,           NULL, BP_GET, VT_I2, 2},
2189     {DISPID_GLOBAL_VBTUESDAY,          NULL, BP_GET, VT_I2, 3},
2190     {DISPID_GLOBAL_VBWEDNESDAY,        NULL, BP_GET, VT_I2, 4},
2191     {DISPID_GLOBAL_VBTHURSDAY,         NULL, BP_GET, VT_I2, 5},
2192     {DISPID_GLOBAL_VBFRIDAY,           NULL, BP_GET, VT_I2, 6},
2193     {DISPID_GLOBAL_VBSATURDAY,         NULL, BP_GET, VT_I2, 7},
2194     {DISPID_GLOBAL_VBFIRSTJAN1,        NULL, BP_GET, VT_I2, 1},
2195     {DISPID_GLOBAL_VBFIRSTFOURDAYS,    NULL, BP_GET, VT_I2, 2},
2196     {DISPID_GLOBAL_VBFIRSTFULLWEEK,    NULL, BP_GET, VT_I2, 3},
2197     {DISPID_GLOBAL_VBOKONLY,           NULL, BP_GET, VT_I2, MB_OK},
2198     {DISPID_GLOBAL_VBOKCANCEL,         NULL, BP_GET, VT_I2, MB_OKCANCEL},
2199     {DISPID_GLOBAL_VBABORTRETRYIGNORE, NULL, BP_GET, VT_I2, MB_ABORTRETRYIGNORE},
2200     {DISPID_GLOBAL_VBYESNOCANCEL,      NULL, BP_GET, VT_I2, MB_YESNOCANCEL},
2201     {DISPID_GLOBAL_VBYESNO,            NULL, BP_GET, VT_I2, MB_YESNO},
2202     {DISPID_GLOBAL_VBRETRYCANCEL,      NULL, BP_GET, VT_I2, MB_RETRYCANCEL},
2203     {DISPID_GLOBAL_VBCRITICAL,         NULL, BP_GET, VT_I2, MB_ICONHAND},
2204     {DISPID_GLOBAL_VBQUESTION,         NULL, BP_GET, VT_I2, MB_ICONQUESTION},
2205     {DISPID_GLOBAL_VBEXCLAMATION,      NULL, BP_GET, VT_I2, MB_ICONEXCLAMATION},
2206     {DISPID_GLOBAL_VBINFORMATION,      NULL, BP_GET, VT_I2, MB_ICONASTERISK},
2207     {DISPID_GLOBAL_VBDEFAULTBUTTON1,   NULL, BP_GET, VT_I2, MB_DEFBUTTON1},
2208     {DISPID_GLOBAL_VBDEFAULTBUTTON2,   NULL, BP_GET, VT_I2, MB_DEFBUTTON2},
2209     {DISPID_GLOBAL_VBDEFAULTBUTTON3,   NULL, BP_GET, VT_I2, MB_DEFBUTTON3},
2210     {DISPID_GLOBAL_VBDEFAULTBUTTON4,   NULL, BP_GET, VT_I2, MB_DEFBUTTON4},
2211     {DISPID_GLOBAL_VBAPPLICATIONMODAL, NULL, BP_GET, VT_I2, MB_APPLMODAL},
2212     {DISPID_GLOBAL_VBSYSTEMMODAL,      NULL, BP_GET, VT_I2, MB_SYSTEMMODAL},
2213     {DISPID_GLOBAL_VBOK,               NULL, BP_GET, VT_I2, IDOK},
2214     {DISPID_GLOBAL_VBCANCEL,           NULL, BP_GET, VT_I2, IDCANCEL},
2215     {DISPID_GLOBAL_VBABORT,            NULL, BP_GET, VT_I2, IDABORT},
2216     {DISPID_GLOBAL_VBRETRY,            NULL, BP_GET, VT_I2, IDRETRY},
2217     {DISPID_GLOBAL_VBIGNORE,           NULL, BP_GET, VT_I2, IDIGNORE},
2218     {DISPID_GLOBAL_VBYES,              NULL, BP_GET, VT_I2, IDYES},
2219     {DISPID_GLOBAL_VBNO,               NULL, BP_GET, VT_I2, IDNO},
2220     {DISPID_GLOBAL_VBEMPTY,            NULL, BP_GET, VT_I2, VT_EMPTY},
2221     {DISPID_GLOBAL_VBNULL,             NULL, BP_GET, VT_I2, VT_NULL},
2222     {DISPID_GLOBAL_VBINTEGER,          NULL, BP_GET, VT_I2, VT_I2},
2223     {DISPID_GLOBAL_VBLONG,             NULL, BP_GET, VT_I2, VT_I4},
2224     {DISPID_GLOBAL_VBSINGLE,           NULL, BP_GET, VT_I2, VT_R4},
2225     {DISPID_GLOBAL_VBDOUBLE,           NULL, BP_GET, VT_I2, VT_R8},
2226     {DISPID_GLOBAL_VBCURRENCY,         NULL, BP_GET, VT_I2, VT_CY},
2227     {DISPID_GLOBAL_VBDATE,             NULL, BP_GET, VT_I2, VT_DATE},
2228     {DISPID_GLOBAL_VBSTRING,           NULL, BP_GET, VT_I2, VT_BSTR},
2229     {DISPID_GLOBAL_VBOBJECT,           NULL, BP_GET, VT_I2, VT_DISPATCH},
2230     {DISPID_GLOBAL_VBERROR,            NULL, BP_GET, VT_I2, VT_ERROR},
2231     {DISPID_GLOBAL_VBBOOLEAN,          NULL, BP_GET, VT_I2, VT_BOOL},
2232     {DISPID_GLOBAL_VBVARIANT,          NULL, BP_GET, VT_I2, VT_VARIANT},
2233     {DISPID_GLOBAL_VBDATAOBJECT,       NULL, BP_GET, VT_I2, VT_UNKNOWN},
2234     {DISPID_GLOBAL_VBDECIMAL,          NULL, BP_GET, VT_I2, VT_DECIMAL},
2235     {DISPID_GLOBAL_VBBYTE,             NULL, BP_GET, VT_I2, VT_UI1},
2236     {DISPID_GLOBAL_VBARRAY,            NULL, BP_GET, VT_I2, VT_ARRAY},
2237     {DISPID_GLOBAL_VBTRUE,             NULL, BP_GET, VT_I2, VARIANT_TRUE},
2238     {DISPID_GLOBAL_VBFALSE,            NULL, BP_GET, VT_I2, VARIANT_FALSE},
2239     {DISPID_GLOBAL_VBUSEDEFAULT,       NULL, BP_GET, VT_I2, -2},
2240     {DISPID_GLOBAL_VBBINARYCOMPARE,    NULL, BP_GET, VT_I2, 0},
2241     {DISPID_GLOBAL_VBTEXTCOMPARE,      NULL, BP_GET, VT_I2, 1},
2242     {DISPID_GLOBAL_VBDATABASECOMPARE,  NULL, BP_GET, VT_I2, 2},
2243     {DISPID_GLOBAL_VBGENERALDATE,      NULL, BP_GET, VT_I2, 0},
2244     {DISPID_GLOBAL_VBLONGDATE,         NULL, BP_GET, VT_I2, 1},
2245     {DISPID_GLOBAL_VBSHORTDATE,        NULL, BP_GET, VT_I2, 2},
2246     {DISPID_GLOBAL_VBLONGTIME,         NULL, BP_GET, VT_I2, 3},
2247     {DISPID_GLOBAL_VBSHORTTIME,        NULL, BP_GET, VT_I2, 4},
2248     {DISPID_GLOBAL_VBOBJECTERROR,      NULL, BP_GET, VT_I4, 0x80040000},
2249     {DISPID_GLOBAL_VBBLACK,            NULL, BP_GET, VT_I4, 0x000000},
2250     {DISPID_GLOBAL_VBBLUE,             NULL, BP_GET, VT_I4, 0xff0000},
2251     {DISPID_GLOBAL_VBCYAN,             NULL, BP_GET, VT_I4, 0xffff00},
2252     {DISPID_GLOBAL_VBGREEN,            NULL, BP_GET, VT_I4, 0x00ff00},
2253     {DISPID_GLOBAL_VBMAGENTA,          NULL, BP_GET, VT_I4, 0xff00ff},
2254     {DISPID_GLOBAL_VBRED,              NULL, BP_GET, VT_I4, 0x0000ff},
2255     {DISPID_GLOBAL_VBWHITE,            NULL, BP_GET, VT_I4, 0xffffff},
2256     {DISPID_GLOBAL_VBYELLOW,           NULL, BP_GET, VT_I4, 0x00ffff},
2257     {DISPID_GLOBAL_VBCR,               NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCr},
2258     {DISPID_GLOBAL_VBCRLF,             NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCrLf},
2259     {DISPID_GLOBAL_VBNEWLINE,          NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNewLine},
2260     {DISPID_GLOBAL_VBFORMFEED,         NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbFormFeed},
2261     {DISPID_GLOBAL_VBLF,               NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbLf},
2262     {DISPID_GLOBAL_VBNULLCHAR,         NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullChar},
2263     {DISPID_GLOBAL_VBNULLSTRING,       NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullString},
2264     {DISPID_GLOBAL_VBTAB,              NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbTab},
2265     {DISPID_GLOBAL_VBVERTICALTAB,      NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbVerticalTab},
2266     {DISPID_GLOBAL_CCUR,                      Global_CCur, 0, 1},
2267     {DISPID_GLOBAL_CINT,                      Global_CInt, 0, 1},
2268     {DISPID_GLOBAL_CLNG,                      Global_CLng, 0, 1},
2269     {DISPID_GLOBAL_CBOOL,                     Global_CBool, 0, 1},
2270     {DISPID_GLOBAL_CBYTE,                     Global_CByte, 0, 1},
2271     {DISPID_GLOBAL_CDATE,                     Global_CDate, 0, 1},
2272     {DISPID_GLOBAL_CDBL,                      Global_CDbl, 0, 1},
2273     {DISPID_GLOBAL_CSNG,                      Global_CSng, 0, 1},
2274     {DISPID_GLOBAL_CSTR,                      Global_CStr, 0, 1},
2275     {DISPID_GLOBAL_HEX,                       Global_Hex, 0, 1},
2276     {DISPID_GLOBAL_OCT,                       Global_Oct, 0, 1},
2277     {DISPID_GLOBAL_VARTYPE,                   Global_VarType, 0, 1},
2278     {DISPID_GLOBAL_ISDATE,                    Global_IsDate, 0, 1},
2279     {DISPID_GLOBAL_ISEMPTY,                   Global_IsEmpty, 0, 1},
2280     {DISPID_GLOBAL_ISNULL,                    Global_IsNull, 0, 1},
2281     {DISPID_GLOBAL_ISNUMERIC,                 Global_IsNumeric, 0, 1},
2282     {DISPID_GLOBAL_ISARRAY,                   Global_IsArray, 0, 1},
2283     {DISPID_GLOBAL_ISOBJECT,                  Global_IsObject, 0, 1},
2284     {DISPID_GLOBAL_ATN,                       Global_Atn, 0, 1},
2285     {DISPID_GLOBAL_COS,                       Global_Cos, 0, 1},
2286     {DISPID_GLOBAL_SIN,                       Global_Sin, 0, 1},
2287     {DISPID_GLOBAL_TAN,                       Global_Tan, 0, 1},
2288     {DISPID_GLOBAL_EXP,                       Global_Exp, 0, 1},
2289     {DISPID_GLOBAL_LOG,                       Global_Log, 0, 1},
2290     {DISPID_GLOBAL_SQR,                       Global_Sqr, 0, 1},
2291     {DISPID_GLOBAL_RANDOMIZE,                 Global_Randomize, 0, 1},
2292     {DISPID_GLOBAL_RND,                       Global_Rnd, 0, 1},
2293     {DISPID_GLOBAL_TIMER,                     Global_Timer, 0, 0},
2294     {DISPID_GLOBAL_LBOUND,                    Global_LBound, 0, 1},
2295     {DISPID_GLOBAL_UBOUND,                    Global_UBound, 0, 1, 2},
2296     {DISPID_GLOBAL_RGB,                       Global_RGB, 0, 3},
2297     {DISPID_GLOBAL_LEN,                       Global_Len, 0, 1},
2298     {DISPID_GLOBAL_LENB,                      Global_LenB, 0, 1},
2299     {DISPID_GLOBAL_LEFT,                      Global_Left, 0, 2},
2300     {DISPID_GLOBAL_LEFTB,                     Global_LeftB, 0, 2},
2301     {DISPID_GLOBAL_RIGHT,                     Global_Right, 0, 2},
2302     {DISPID_GLOBAL_RIGHTB,                    Global_RightB, 0, 2},
2303     {DISPID_GLOBAL_MID,                       Global_Mid, 0, 2, 3},
2304     {DISPID_GLOBAL_MIDB,                      Global_MidB, 0, 2, 3},
2305     {DISPID_GLOBAL_STRCOMP,                   Global_StrComp, 0, 2, 3},
2306     {DISPID_GLOBAL_LCASE,                     Global_LCase, 0, 1},
2307     {DISPID_GLOBAL_UCASE,                     Global_UCase, 0, 1},
2308     {DISPID_GLOBAL_LTRIM,                     Global_LTrim, 0, 1},
2309     {DISPID_GLOBAL_RTRIM,                     Global_RTrim, 0, 1},
2310     {DISPID_GLOBAL_TRIM,                      Global_Trim, 0, 1},
2311     {DISPID_GLOBAL_SPACE,                     Global_Space, 0, 1},
2312     {DISPID_GLOBAL_STRING,                    Global_String, 0, 0, 2},
2313     {DISPID_GLOBAL_INSTR,                     Global_InStr, 0, 2, 4},
2314     {DISPID_GLOBAL_INSTRB,                    Global_InStrB, 0, 3, 4},
2315     {DISPID_GLOBAL_ASCB,                      Global_AscB, 0, 1},
2316     {DISPID_GLOBAL_CHRB,                      Global_ChrB, 0, 1},
2317     {DISPID_GLOBAL_ASC,                       Global_Asc, 0, 1},
2318     {DISPID_GLOBAL_CHR,                       Global_Chr, 0, 1},
2319     {DISPID_GLOBAL_ASCW,                      Global_AscW, 0, 1},
2320     {DISPID_GLOBAL_CHRW,                      Global_ChrW, 0, 1},
2321     {DISPID_GLOBAL_ABS,                       Global_Abs, 0, 1},
2322     {DISPID_GLOBAL_FIX,                       Global_Fix, 0, 1},
2323     {DISPID_GLOBAL_INT,                       Global_Int, 0, 1},
2324     {DISPID_GLOBAL_SGN,                       Global_Sgn, 0, 1},
2325     {DISPID_GLOBAL_NOW,                       Global_Now, 0, 0},
2326     {DISPID_GLOBAL_DATE,                      Global_Date, 0, 0},
2327     {DISPID_GLOBAL_TIME,                      Global_Time, 0, 0},
2328     {DISPID_GLOBAL_DAY,                       Global_Day, 0, 1},
2329     {DISPID_GLOBAL_MONTH,                     Global_Month, 0, 1},
2330     {DISPID_GLOBAL_WEEKDAY,                   Global_Weekday, 0, 1, 2},
2331     {DISPID_GLOBAL_YEAR,                      Global_Year, 0, 1},
2332     {DISPID_GLOBAL_HOUR,                      Global_Hour, 0, 1},
2333     {DISPID_GLOBAL_MINUTE,                    Global_Minute, 0, 1},
2334     {DISPID_GLOBAL_SECOND,                    Global_Second, 0, 1},
2335     {DISPID_GLOBAL_DATEVALUE,                 Global_DateValue, 0, 1},
2336     {DISPID_GLOBAL_TIMEVALUE,                 Global_TimeValue, 0, 1},
2337     {DISPID_GLOBAL_DATESERIAL,                Global_DateSerial, 0, 3},
2338     {DISPID_GLOBAL_TIMESERIAL,                Global_TimeSerial, 0, 3},
2339     {DISPID_GLOBAL_INPUTBOX,                  Global_InputBox, 0, 1, 7},
2340     {DISPID_GLOBAL_MSGBOX,                    Global_MsgBox, 0, 1, 5},
2341     {DISPID_GLOBAL_CREATEOBJECT,              Global_CreateObject, 0, 1},
2342     {DISPID_GLOBAL_GETOBJECT,                 Global_GetObject, 0, 0, 2},
2343     {DISPID_GLOBAL_DATEADD,                   Global_DateAdd, 0, 3},
2344     {DISPID_GLOBAL_DATEDIFF,                  Global_DateDiff, 0, 3, 5},
2345     {DISPID_GLOBAL_DATEPART,                  Global_DatePart, 0, 2, 4},
2346     {DISPID_GLOBAL_TYPENAME,                  Global_TypeName, 0, 1},
2347     {DISPID_GLOBAL_ARRAY,                     Global_Array, 0, 0, MAXDWORD},
2348     {DISPID_GLOBAL_ERASE,                     Global_Erase, 0, 1},
2349     {DISPID_GLOBAL_FILTER,                    Global_Filter, 0, 2, 4},
2350     {DISPID_GLOBAL_JOIN,                      Global_Join, 0, 1, 2},
2351     {DISPID_GLOBAL_SPLIT,                     Global_Split, 0, 1, 4},
2352     {DISPID_GLOBAL_REPLACE,                   Global_Replace, 0, 3, 6},
2353     {DISPID_GLOBAL_STRREVERSE,                Global_StrReverse, 0, 1},
2354     {DISPID_GLOBAL_INSTRREV,                  Global_InStrRev, 0, 2, 4},
2355     {DISPID_GLOBAL_LOADPICTURE,               Global_LoadPicture, 0, 1},
2356     {DISPID_GLOBAL_SCRIPTENGINE,              Global_ScriptEngine, 0, 0},
2357     {DISPID_GLOBAL_SCRIPTENGINEMAJORVERSION,  Global_ScriptEngineMajorVersion, 0, 0},
2358     {DISPID_GLOBAL_SCRIPTENGINEMINORVERSION,  Global_ScriptEngineMinorVersion, 0, 0},
2359     {DISPID_GLOBAL_SCRIPTENGINEBUILDVERSION,  Global_ScriptEngineBuildVersion, 0, 0},
2360     {DISPID_GLOBAL_FORMATNUMBER,              Global_FormatNumber, 0, 1, 5},
2361     {DISPID_GLOBAL_FORMATCURRENCY,            Global_FormatCurrency, 0, 1, 5},
2362     {DISPID_GLOBAL_FORMATPERCENT,             Global_FormatPercent, 0, 1, 5},
2363     {DISPID_GLOBAL_FORMATDATETIME,            Global_FormatDateTime, 0, 1, 2},
2364     {DISPID_GLOBAL_WEEKDAYNAME,               Global_WeekdayName, 0, 1, 3},
2365     {DISPID_GLOBAL_MONTHNAME,                 Global_MonthName, 0, 1, 2},
2366     {DISPID_GLOBAL_ROUND,                     Global_Round, 0, 1, 2},
2367     {DISPID_GLOBAL_ESCAPE,                    Global_Escape, 0, 1},
2368     {DISPID_GLOBAL_UNESCAPE,                  Global_Unescape, 0, 1},
2369     {DISPID_GLOBAL_EVAL,                      Global_Eval, 0, 1},
2370     {DISPID_GLOBAL_EXECUTE,                   Global_Execute, 0, 1},
2371     {DISPID_GLOBAL_EXECUTEGLOBAL,             Global_ExecuteGlobal, 0, 1},
2372     {DISPID_GLOBAL_GETREF,                    Global_GetRef, 0, 1},
2373     {DISPID_GLOBAL_VBMSGBOXHELPBUTTON,     NULL, BP_GET, VT_I4, MB_HELP},
2374     {DISPID_GLOBAL_VBMSGBOXSETFOREGROUND,  NULL, BP_GET, VT_I4, MB_SETFOREGROUND},
2375     {DISPID_GLOBAL_VBMSGBOXRIGHT,          NULL, BP_GET, VT_I4, MB_RIGHT},
2376     {DISPID_GLOBAL_VBMSGBOXRTLREADING,     NULL, BP_GET, VT_I4, MB_RTLREADING}
2377 };
2378 
2379 static HRESULT Err_Description(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2380 {
2381     FIXME("\n");
2382     return E_NOTIMPL;
2383 }
2384 
2385 static HRESULT Err_HelpContext(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2386 {
2387     FIXME("\n");
2388     return E_NOTIMPL;
2389 }
2390 
2391 static HRESULT Err_HelpFile(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2392 {
2393     FIXME("\n");
2394     return E_NOTIMPL;
2395 }
2396 
2397 static HRESULT Err_Number(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2398 {
2399     HRESULT hres;
2400 
2401     TRACE("\n");
2402 
2403     if(!This->desc)
2404         return E_UNEXPECTED;
2405 
2406     if(args_cnt) {
2407         FIXME("setter not implemented\n");
2408         return E_NOTIMPL;
2409     }
2410 
2411     hres = This->desc->ctx->err_number;
2412     return return_int(res, HRESULT_FACILITY(hres) == FACILITY_VBS ? HRESULT_CODE(hres) : hres);
2413 }
2414 
2415 static HRESULT Err_Source(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2416 {
2417     FIXME("\n");
2418     return E_NOTIMPL;
2419 }
2420 
2421 static HRESULT Err_Clear(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2422 {
2423     TRACE("\n");
2424 
2425     if(!This->desc)
2426         return E_UNEXPECTED;
2427 
2428     This->desc->ctx->err_number = S_OK;
2429     return S_OK;
2430 }
2431 
2432 static HRESULT Err_Raise(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2433 {
2434     FIXME("\n");
2435     return E_NOTIMPL;
2436 }
2437 
2438 static const builtin_prop_t err_props[] = {
2439     {DISPID_ERR_DESCRIPTION,  Err_Description, BP_GETPUT},
2440     {DISPID_ERR_HELPCONTEXT,  Err_HelpContext, BP_GETPUT},
2441     {DISPID_ERR_HELPFILE,     Err_HelpFile, BP_GETPUT},
2442     {DISPID_ERR_NUMBER,       Err_Number, BP_GETPUT},
2443     {DISPID_ERR_SOURCE,       Err_Source, BP_GETPUT},
2444     {DISPID_ERR_CLEAR,        Err_Clear},
2445     {DISPID_ERR_RAISE,        Err_Raise, 0, 5},
2446 };
2447 
2448 HRESULT init_global(script_ctx_t *ctx)
2449 {
2450     HRESULT hres;
2451 
2452     ctx->global_desc.ctx = ctx;
2453     ctx->global_desc.builtin_prop_cnt = sizeof(global_props)/sizeof(*global_props);
2454     ctx->global_desc.builtin_props = global_props;
2455 
2456     hres = get_typeinfo(GlobalObj_tid, &ctx->global_desc.typeinfo);
2457     if(FAILED(hres))
2458         return hres;
2459 
2460     hres = create_vbdisp(&ctx->global_desc, &ctx->global_obj);
2461     if(FAILED(hres))
2462         return hres;
2463 
2464     hres = create_script_disp(ctx, &ctx->script_obj);
2465     if(FAILED(hres))
2466         return hres;
2467 
2468     ctx->err_desc.ctx = ctx;
2469     ctx->err_desc.builtin_prop_cnt = sizeof(err_props)/sizeof(*err_props);
2470     ctx->err_desc.builtin_props = err_props;
2471 
2472     hres = get_typeinfo(ErrObj_tid, &ctx->err_desc.typeinfo);
2473     if(FAILED(hres))
2474         return hres;
2475 
2476     return create_vbdisp(&ctx->err_desc, &ctx->err_obj);
2477 }
2478