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