vbscript: Make constant type explicit.
[wine] / dlls / vbscript / global.c
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 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
31
32 #define VB_E_CANNOT_CREATE_OBJ 0x800a01ad
33 #define VB_E_MK_PARSE_ERROR    0x800a01b0
34
35 /* Defined as extern in urlmon.idl, but not exported by uuid.lib */
36 const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY =
37     {0x10200490,0xfa38,0x11d0,{0xac,0x0e,0x00,0xa0,0xc9,0xf,0xff,0xc0}};
38
39 static const WCHAR emptyW[] = {0};
40 static const WCHAR vbscriptW[] = {'V','B','S','c','r','i','p','t',0};
41
42 static IInternetHostSecurityManager *get_sec_mgr(script_ctx_t *ctx)
43 {
44     IInternetHostSecurityManager *secmgr;
45     IServiceProvider *sp;
46     HRESULT hres;
47
48     if(!ctx->site)
49         return NULL;
50
51     if(ctx->secmgr)
52         return ctx->secmgr;
53
54     hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp);
55     if(FAILED(hres))
56         return NULL;
57
58     hres = IServiceProvider_QueryService(sp, &SID_SInternetHostSecurityManager, &IID_IInternetHostSecurityManager,
59             (void**)&secmgr);
60     IServiceProvider_Release(sp);
61     if(FAILED(hres))
62         return NULL;
63
64     return ctx->secmgr = secmgr;
65 }
66
67 static HRESULT return_string(VARIANT *res, const WCHAR *str)
68 {
69     BSTR ret;
70
71     if(!res)
72         return S_OK;
73
74     ret = SysAllocString(str);
75     if(!ret)
76         return E_OUTOFMEMORY;
77
78     V_VT(res) = VT_BSTR;
79     V_BSTR(res) = ret;
80     return S_OK;
81 }
82
83 static HRESULT return_bstr(VARIANT *res, BSTR str)
84 {
85     if(res) {
86         V_VT(res) = VT_BSTR;
87         V_BSTR(res) = str;
88     }else {
89         SysFreeString(str);
90     }
91     return S_OK;
92 }
93
94 static HRESULT return_short(VARIANT *res, short val)
95 {
96     if(res) {
97         V_VT(res) = VT_I2;
98         V_I2(res) = val;
99     }
100
101     return S_OK;
102 }
103
104 static HRESULT return_int(VARIANT *res, int val)
105 {
106     if((short)val == val)
107         return return_short(res, val);
108
109     if(res) {
110         V_VT(res) = VT_I4;
111         V_I4(res) = val;
112     }
113
114     return S_OK;
115 }
116
117 static inline HRESULT return_double(VARIANT *res, double val)
118 {
119     if(res) {
120         V_VT(res) = VT_R8;
121         V_R8(res) = val;
122     }
123
124     return S_OK;
125 }
126
127 static inline HRESULT return_null(VARIANT *res)
128 {
129     if(res)
130         V_VT(res) = VT_NULL;
131     return S_OK;
132 }
133
134 static inline HRESULT return_date(VARIANT *res, double date)
135 {
136     if(res) {
137         V_VT(res) = VT_DATE;
138         V_DATE(res) = date;
139     }
140     return S_OK;
141 }
142
143 static HRESULT to_int(VARIANT *v, int *ret)
144 {
145     switch(V_VT(v)) {
146     case VT_I2:
147         *ret = V_I2(v);
148         break;
149     case VT_I4:
150         *ret = V_I4(v);
151         break;
152     case VT_R8: {
153         double n = round(V_R8(v));
154         if(!is_int32(n)) {
155             FIXME("%lf is out of int range\n", n);
156             return E_FAIL;
157         }
158         *ret = n;
159         break;
160     }
161     case VT_BOOL:
162         *ret = V_BOOL(v) ? -1 : 0;
163         break;
164     default:
165         FIXME("not supported %s\n", debugstr_variant(v));
166         return E_NOTIMPL;
167     }
168
169     return S_OK;
170 }
171
172 static HRESULT to_double(VARIANT *v, double *ret)
173 {
174     switch(V_VT(v)) {
175     case VT_I2:
176         *ret = V_I2(v);
177         break;
178     case VT_I4:
179         *ret = V_I4(v);
180         break;
181     case VT_R4:
182         *ret = V_R4(v);
183         break;
184     case VT_R8:
185         *ret = V_R8(v);
186         break;
187     case VT_BSTR: {
188         VARIANT dst;
189         HRESULT hres;
190
191         V_VT(&dst) = VT_EMPTY;
192         hres = VariantChangeType(&dst, v, VARIANT_LOCALBOOL, VT_R8);
193         if(FAILED(hres))
194             return hres;
195         *ret = V_R8(&dst);
196         break;
197     }
198     default:
199         FIXME("arg %s not supported\n", debugstr_variant(v));
200         return E_NOTIMPL;
201     }
202
203     return S_OK;
204 }
205
206 static HRESULT to_string(VARIANT *v, BSTR *ret)
207 {
208     VARIANT dst;
209     HRESULT hres;
210
211     V_VT(&dst) = VT_EMPTY;
212     hres = VariantChangeType(&dst, v, VARIANT_LOCALBOOL, VT_BSTR);
213     if(FAILED(hres))
214         return hres;
215
216     *ret = V_BSTR(&dst);
217     return S_OK;
218 }
219
220 static HRESULT set_object_site(script_ctx_t *ctx, IUnknown *obj)
221 {
222     IObjectWithSite *obj_site;
223     IUnknown *ax_site;
224     HRESULT hres;
225
226     hres = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (void**)&obj_site);
227     if(FAILED(hres))
228         return S_OK;
229
230     ax_site = create_ax_site(ctx);
231     if(ax_site)
232         hres = IObjectWithSite_SetSite(obj_site, ax_site);
233     else
234         hres = E_OUTOFMEMORY;
235     IUnknown_Release(ax_site);
236     IObjectWithSite_Release(obj_site);
237     return hres;
238 }
239
240 static IUnknown *create_object(script_ctx_t *ctx, const WCHAR *progid)
241 {
242     IInternetHostSecurityManager *secmgr = NULL;
243     struct CONFIRMSAFETY cs;
244     IClassFactoryEx *cfex;
245     IClassFactory *cf;
246     DWORD policy_size;
247     BYTE *bpolicy;
248     IUnknown *obj;
249     DWORD policy;
250     GUID guid;
251     HRESULT hres;
252
253     hres = CLSIDFromProgID(progid, &guid);
254     if(FAILED(hres))
255         return NULL;
256
257     TRACE("GUID %s\n", debugstr_guid(&guid));
258
259     if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
260         secmgr = get_sec_mgr(ctx);
261         if(!secmgr)
262             return NULL;
263
264         policy = 0;
265         hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN,
266                 (BYTE*)&policy, sizeof(policy), (BYTE*)&guid, sizeof(GUID), 0, 0);
267         if(FAILED(hres) || policy != URLPOLICY_ALLOW)
268             return NULL;
269     }
270
271     hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
272     if(FAILED(hres))
273         return NULL;
274
275     hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
276     if(SUCCEEDED(hres)) {
277         FIXME("Use IClassFactoryEx\n");
278         IClassFactoryEx_Release(cfex);
279     }
280
281     hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
282     if(FAILED(hres))
283         return NULL;
284
285     if(secmgr) {
286         cs.clsid = guid;
287         cs.pUnk = obj;
288         cs.dwFlags = 0;
289         hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
290                 &bpolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
291         if(SUCCEEDED(hres)) {
292             policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW;
293             CoTaskMemFree(bpolicy);
294         }
295
296         if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
297             IUnknown_Release(obj);
298             return NULL;
299         }
300     }
301
302     hres = set_object_site(ctx, obj);
303     if(FAILED(hres)) {
304         IUnknown_Release(obj);
305         return NULL;
306     }
307
308     return obj;
309 }
310
311 static HRESULT show_msgbox(script_ctx_t *ctx, BSTR prompt, VARIANT *res)
312 {
313     SCRIPTUICHANDLING uic_handling = SCRIPTUICHANDLING_ALLOW;
314     IActiveScriptSiteUIControl *ui_control;
315     IActiveScriptSiteWindow *acts_window;
316     const WCHAR *title;
317     HWND hwnd = NULL;
318     int ret;
319     HRESULT hres;
320
321     hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteUIControl, (void**)&ui_control);
322     if(SUCCEEDED(hres)) {
323         hres = IActiveScriptSiteUIControl_GetUIBehavior(ui_control, SCRIPTUICITEM_MSGBOX, &uic_handling);
324         IActiveScriptSiteUIControl_Release(ui_control);
325         if(FAILED(hres))
326             uic_handling = SCRIPTUICHANDLING_ALLOW;
327     }
328
329     switch(uic_handling) {
330     case SCRIPTUICHANDLING_ALLOW:
331         break;
332     case SCRIPTUICHANDLING_NOUIDEFAULT:
333         return return_short(res, 0);
334     default:
335         FIXME("blocked\n");
336         return E_FAIL;
337     }
338
339     title = (ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) ? vbscriptW : emptyW;
340
341     hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteWindow, (void**)&acts_window);
342     if(FAILED(hres)) {
343         FIXME("No IActiveScriptSiteWindow\n");
344         return hres;
345     }
346
347     hres = IActiveScriptSiteWindow_GetWindow(acts_window, &hwnd);
348     if(SUCCEEDED(hres)) {
349         hres = IActiveScriptSiteWindow_EnableModeless(acts_window, FALSE);
350         if(SUCCEEDED(hres)) {
351             ret = MessageBoxW(hwnd, prompt, title, MB_OK);
352             hres = IActiveScriptSiteWindow_EnableModeless(acts_window, TRUE);
353         }
354     }
355
356     IActiveScriptSiteWindow_Release(acts_window);
357     if(FAILED(hres)) {
358         FIXME("failed: %08x\n", hres);
359         return hres;
360     }
361
362     return return_short(res, ret);
363 }
364
365 static HRESULT Global_CCur(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
366 {
367     FIXME("\n");
368     return E_NOTIMPL;
369 }
370
371 static HRESULT Global_CInt(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
372 {
373     FIXME("\n");
374     return E_NOTIMPL;
375 }
376
377 static HRESULT Global_CLng(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
378 {
379     FIXME("\n");
380     return E_NOTIMPL;
381 }
382
383 static HRESULT Global_CBool(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
384 {
385     FIXME("\n");
386     return E_NOTIMPL;
387 }
388
389 static HRESULT Global_CByte(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
390 {
391     FIXME("\n");
392     return E_NOTIMPL;
393 }
394
395 static HRESULT Global_CDate(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
396 {
397     FIXME("\n");
398     return E_NOTIMPL;
399 }
400
401 static HRESULT Global_CDbl(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
402 {
403     FIXME("\n");
404     return E_NOTIMPL;
405 }
406
407 static HRESULT Global_CSng(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
408 {
409     FIXME("\n");
410     return E_NOTIMPL;
411 }
412
413 static HRESULT Global_CStr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
414 {
415     BSTR str;
416     HRESULT hres;
417
418     TRACE("%s\n", debugstr_variant(arg));
419
420     hres = to_string(arg, &str);
421     if(FAILED(hres))
422         return hres;
423
424     return return_bstr(res, str);
425 }
426
427 static inline WCHAR hex_char(unsigned n)
428 {
429     return n < 10 ? '0'+n : 'A'+n-10;
430 }
431
432 static HRESULT Global_Hex(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
433 {
434     WCHAR buf[17], *ptr;
435     DWORD n;
436
437     TRACE("%s\n", debugstr_variant(arg));
438
439     switch(V_VT(arg)) {
440     case VT_I2:
441         n = (WORD)V_I2(arg);
442         break;
443     case VT_I4:
444         n = V_I4(arg);
445         break;
446     case VT_EMPTY:
447         n = 0;
448         break;
449     case VT_NULL:
450         if(res)
451             V_VT(res) = VT_NULL;
452         return S_OK;
453     default:
454         FIXME("unsupported type %s\n", debugstr_variant(arg));
455         return E_NOTIMPL;
456     }
457
458     buf[16] = 0;
459     ptr = buf+15;
460
461     if(n) {
462         do {
463             *ptr-- = hex_char(n & 0xf);
464             n >>= 4;
465         }while(n);
466         ptr++;
467     }else {
468         *ptr = '0';
469     }
470
471     return return_string(res, ptr);
472 }
473
474 static HRESULT Global_Oct(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
475 {
476     FIXME("\n");
477     return E_NOTIMPL;
478 }
479
480 static HRESULT Global_VarType(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
481 {
482     FIXME("\n");
483     return E_NOTIMPL;
484 }
485
486 static HRESULT Global_IsDate(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
487 {
488     FIXME("\n");
489     return E_NOTIMPL;
490 }
491
492 static HRESULT Global_IsEmpty(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
493 {
494     TRACE("(%s)\n", debugstr_variant(arg));
495
496     assert(args_cnt == 1);
497
498     if(res) {
499         V_VT(res) = VT_BOOL;
500         V_BOOL(res) = V_VT(arg) == VT_EMPTY ? VARIANT_TRUE : VARIANT_FALSE;
501     }
502     return S_OK;
503 }
504
505 static HRESULT Global_IsNull(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
506 {
507     TRACE("(%s)\n", debugstr_variant(arg));
508
509     assert(args_cnt == 1);
510
511     if(res) {
512         V_VT(res) = VT_BOOL;
513         V_BOOL(res) = V_VT(arg) == VT_NULL ? VARIANT_TRUE : VARIANT_FALSE;
514     }
515     return S_OK;
516 }
517
518 static HRESULT Global_IsNumeric(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
519 {
520     FIXME("\n");
521     return E_NOTIMPL;
522 }
523
524 static HRESULT Global_IsArray(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
525 {
526     FIXME("\n");
527     return E_NOTIMPL;
528 }
529
530 static HRESULT Global_IsObject(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
531 {
532     TRACE("(%s)\n", debugstr_variant(arg));
533
534     assert(args_cnt == 1);
535
536     if(res) {
537         V_VT(res) = VT_BOOL;
538         V_BOOL(res) = V_VT(arg) == VT_DISPATCH ? VARIANT_TRUE : VARIANT_FALSE;
539     }
540     return S_OK;
541 }
542
543 static HRESULT Global_Ant(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
544 {
545     FIXME("\n");
546     return E_NOTIMPL;
547 }
548
549 static HRESULT Global_Cos(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
550 {
551     FIXME("\n");
552     return E_NOTIMPL;
553 }
554
555 static HRESULT Global_Sin(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
556 {
557     FIXME("\n");
558     return E_NOTIMPL;
559 }
560
561 static HRESULT Global_Tan(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
562 {
563     FIXME("\n");
564     return E_NOTIMPL;
565 }
566
567 static HRESULT Global_Exp(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
568 {
569     FIXME("\n");
570     return E_NOTIMPL;
571 }
572
573 static HRESULT Global_Log(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
574 {
575     FIXME("\n");
576     return E_NOTIMPL;
577 }
578
579 static HRESULT Global_Sqr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
580 {
581     FIXME("\n");
582     return E_NOTIMPL;
583 }
584
585 static HRESULT Global_Randomize(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
586 {
587     FIXME("\n");
588     return E_NOTIMPL;
589 }
590
591 static HRESULT Global_Rnd(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
592 {
593     FIXME("\n");
594     return E_NOTIMPL;
595 }
596
597 static HRESULT Global_Timer(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
598 {
599     FIXME("\n");
600     return E_NOTIMPL;
601 }
602
603 static HRESULT Global_LBound(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
604 {
605     FIXME("\n");
606     return E_NOTIMPL;
607 }
608
609 static HRESULT Global_UBound(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
610 {
611     FIXME("\n");
612     return E_NOTIMPL;
613 }
614
615 static HRESULT Global_RGB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
616 {
617     FIXME("\n");
618     return E_NOTIMPL;
619 }
620
621 static HRESULT Global_Len(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
622 {
623     DWORD len;
624     HRESULT hres;
625
626     TRACE("%s\n", debugstr_variant(arg));
627
628     if(V_VT(arg) == VT_NULL)
629         return return_null(res);
630
631     if(V_VT(arg) != VT_BSTR) {
632         BSTR str;
633
634         hres = to_string(arg, &str);
635         if(FAILED(hres))
636             return hres;
637
638         len = SysStringLen(str);
639         SysFreeString(str);
640     }else {
641         len = SysStringLen(V_BSTR(arg));
642     }
643
644     return return_int(res, len);
645 }
646
647 static HRESULT Global_LenB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
648 {
649     FIXME("\n");
650     return E_NOTIMPL;
651 }
652
653 static HRESULT Global_Left(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
654 {
655     BSTR str, ret, conv_str = NULL;
656     int len, str_len;
657     HRESULT hres;
658
659     TRACE("(%s %s)\n", debugstr_variant(args+1), debugstr_variant(args));
660
661     if(V_VT(args) == VT_BSTR) {
662         str = V_BSTR(args);
663     }else {
664         hres = to_string(args, &conv_str);
665         if(FAILED(hres))
666             return hres;
667         str = conv_str;
668     }
669
670     hres = to_int(args+1, &len);
671     if(FAILED(hres))
672         return hres;
673
674     if(len < 0) {
675         FIXME("len = %d\n", len);
676         return E_FAIL;
677     }
678
679     str_len = SysStringLen(str);
680     if(len > str_len)
681         len = str_len;
682
683     ret = SysAllocStringLen(str, len);
684     SysFreeString(conv_str);
685     if(!ret)
686         return E_OUTOFMEMORY;
687
688     return return_bstr(res, ret);
689 }
690
691 static HRESULT Global_LeftB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
692 {
693     FIXME("\n");
694     return E_NOTIMPL;
695 }
696
697 static HRESULT Global_Right(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
698 {
699     BSTR str, ret, conv_str = NULL;
700     int len, str_len;
701     HRESULT hres;
702
703     TRACE("(%s %s)\n", debugstr_variant(args), debugstr_variant(args+1));
704
705     if(V_VT(args+1) == VT_BSTR) {
706         str = V_BSTR(args);
707     }else {
708         hres = to_string(args, &conv_str);
709         if(FAILED(hres))
710             return hres;
711         str = conv_str;
712     }
713
714     hres = to_int(args+1, &len);
715     if(FAILED(hres))
716         return hres;
717
718     if(len < 0) {
719         FIXME("len = %d\n", len);
720         return E_FAIL;
721     }
722
723     str_len = SysStringLen(str);
724     if(len > str_len)
725         len = str_len;
726
727     ret = SysAllocStringLen(str+str_len-len, len);
728     SysFreeString(conv_str);
729     if(!ret)
730         return E_OUTOFMEMORY;
731
732     return return_bstr(res, ret);
733 }
734
735 static HRESULT Global_RightB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
736 {
737     FIXME("\n");
738     return E_NOTIMPL;
739 }
740
741 static HRESULT Global_Mid(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
742 {
743     int len = -1, start, str_len;
744     BSTR str;
745     HRESULT hres;
746
747     TRACE("(%s %s ...)\n", debugstr_variant(args), debugstr_variant(args+1));
748
749     assert(args_cnt == 2 || args_cnt == 3);
750
751     if(V_VT(args) != VT_BSTR) {
752         FIXME("args[0] = %s\n", debugstr_variant(args));
753         return E_NOTIMPL;
754     }
755
756     str = V_BSTR(args);
757
758     hres = to_int(args+1, &start);
759     if(FAILED(hres))
760         return hres;
761
762     if(args_cnt == 3) {
763         hres = to_int(args+2, &len);
764         if(FAILED(hres))
765             return hres;
766
767         if(len < 0) {
768             FIXME("len = %d\n", len);
769             return E_FAIL;
770         }
771     }
772
773
774     str_len = SysStringLen(str);
775     start--;
776     if(start > str_len)
777         start = str_len;
778
779     if(len == -1)
780         len = str_len-start;
781     else if(len > str_len-start)
782         len = str_len-start;
783
784     if(res) {
785         V_VT(res) = VT_BSTR;
786         V_BSTR(res) = SysAllocStringLen(str+start, len);
787         if(!V_BSTR(res))
788             return E_OUTOFMEMORY;
789     }
790
791     return S_OK;
792 }
793
794 static HRESULT Global_MidB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
795 {
796     FIXME("\n");
797     return E_NOTIMPL;
798 }
799
800 static HRESULT Global_StrComp(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
801 {
802     FIXME("\n");
803     return E_NOTIMPL;
804 }
805
806 static HRESULT Global_LCase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
807 {
808     BSTR str;
809     HRESULT hres;
810
811     TRACE("%s\n", debugstr_variant(arg));
812
813     if(V_VT(arg) == VT_NULL) {
814         if(res)
815             V_VT(res) = VT_NULL;
816         return S_OK;
817     }
818
819     hres = to_string(arg, &str);
820     if(FAILED(hres))
821         return hres;
822
823     if(res) {
824         WCHAR *ptr;
825
826         for(ptr = str; *ptr; ptr++)
827             *ptr = tolowerW(*ptr);
828
829         V_VT(res) = VT_BSTR;
830         V_BSTR(res) = str;
831     }else {
832         SysFreeString(str);
833     }
834     return S_OK;
835 }
836
837 static HRESULT Global_UCase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
838 {
839     BSTR str;
840     HRESULT hres;
841
842     TRACE("%s\n", debugstr_variant(arg));
843
844     if(V_VT(arg) == VT_NULL) {
845         if(res)
846             V_VT(res) = VT_NULL;
847         return S_OK;
848     }
849
850     hres = to_string(arg, &str);
851     if(FAILED(hres))
852         return hres;
853
854     if(res) {
855         WCHAR *ptr;
856
857         for(ptr = str; *ptr; ptr++)
858             *ptr = toupperW(*ptr);
859
860         V_VT(res) = VT_BSTR;
861         V_BSTR(res) = str;
862     }else {
863         SysFreeString(str);
864     }
865     return S_OK;
866 }
867
868 static HRESULT Global_LTrim(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
869 {
870     BSTR str, conv_str = NULL;
871     WCHAR *ptr;
872     HRESULT hres;
873
874     TRACE("%s\n", debugstr_variant(arg));
875
876     if(V_VT(arg) == VT_BSTR) {
877         str = V_BSTR(arg);
878     }else {
879         hres = to_string(arg, &conv_str);
880         if(FAILED(hres))
881             return hres;
882         str = conv_str;
883     }
884
885     for(ptr = str; *ptr && isspaceW(*ptr); ptr++);
886
887     str = SysAllocString(ptr);
888     SysFreeString(conv_str);
889     if(!str)
890         return E_OUTOFMEMORY;
891
892     return return_bstr(res, str);
893 }
894
895 static HRESULT Global_RTrim(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
896 {
897     BSTR str, conv_str = NULL;
898     WCHAR *ptr;
899     HRESULT hres;
900
901     TRACE("%s\n", debugstr_variant(arg));
902
903     if(V_VT(arg) == VT_BSTR) {
904         str = V_BSTR(arg);
905     }else {
906         hres = to_string(arg, &conv_str);
907         if(FAILED(hres))
908             return hres;
909         str = conv_str;
910     }
911
912     for(ptr = str+SysStringLen(str); ptr-1 > str && isspaceW(*(ptr-1)); ptr--);
913
914     str = SysAllocStringLen(str, ptr-str);
915     SysFreeString(conv_str);
916     if(!str)
917         return E_OUTOFMEMORY;
918
919     return return_bstr(res, str);
920 }
921
922 static HRESULT Global_Trim(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
923 {
924     BSTR str, conv_str = NULL;
925     WCHAR *begin_ptr, *end_ptr;
926     HRESULT hres;
927
928     TRACE("%s\n", debugstr_variant(arg));
929
930     if(V_VT(arg) == VT_BSTR) {
931         str = V_BSTR(arg);
932     }else {
933         hres = to_string(arg, &conv_str);
934         if(FAILED(hres))
935             return hres;
936         str = conv_str;
937     }
938
939     for(begin_ptr = str; *begin_ptr && isspaceW(*begin_ptr); begin_ptr++);
940     for(end_ptr = str+SysStringLen(str); end_ptr-1 > begin_ptr && isspaceW(*(end_ptr-1)); end_ptr--);
941
942     str = SysAllocStringLen(begin_ptr, end_ptr-begin_ptr);
943     SysFreeString(conv_str);
944     if(!str)
945         return E_OUTOFMEMORY;
946
947     return return_bstr(res, str);
948 }
949
950 static HRESULT Global_Space(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
951 {
952     BSTR str;
953     int n, i;
954     HRESULT hres;
955
956     TRACE("%s\n", debugstr_variant(arg));
957
958     hres = to_int(arg, &n);
959     if(FAILED(hres))
960         return hres;
961
962     if(n < 0) {
963         FIXME("n = %d\n", n);
964         return E_NOTIMPL;
965     }
966
967     if(!res)
968         return S_OK;
969
970     str = SysAllocStringLen(NULL, n);
971     if(!str)
972         return E_OUTOFMEMORY;
973
974     for(i=0; i<n; i++)
975         str[i] = ' ';
976
977     V_VT(res) = VT_BSTR;
978     V_BSTR(res) = str;
979     return S_OK;
980 }
981
982 static HRESULT Global_String(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
983 {
984     FIXME("\n");
985     return E_NOTIMPL;
986 }
987
988 static HRESULT Global_InStr(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
989 {
990     VARIANT *startv, *str1v, *str2v;
991     BSTR str1, str2;
992     int start, ret;
993     HRESULT hres;
994
995     TRACE("\n");
996
997     assert(2 <= args_cnt && args_cnt <= 4);
998
999     switch(args_cnt) {
1000     case 2:
1001         startv = NULL;
1002         str1v = args;
1003         str2v = args+1;
1004         break;
1005     case 3:
1006         startv = args;
1007         str1v = args+1;
1008         str2v = args+2;
1009         break;
1010     case 4:
1011         FIXME("unsupported compare argument %s\n", debugstr_variant(args));
1012         return E_NOTIMPL;
1013     default:
1014         assert(0);
1015     }
1016
1017     if(startv) {
1018         hres = to_int(startv, &start);
1019         if(FAILED(hres))
1020             return hres;
1021         if(--start < 0) {
1022             FIXME("start %d\n", start);
1023             return E_FAIL;
1024         }
1025     }else {
1026         start = 0;
1027     }
1028
1029     if(V_VT(str1v) == VT_NULL || V_VT(str2v) == VT_NULL)
1030         return return_null(res);
1031
1032     if(V_VT(str1v) != VT_BSTR) {
1033         FIXME("Unsupported str1 type %s\n", debugstr_variant(str1v));
1034         return E_NOTIMPL;
1035     }
1036     str1 = V_BSTR(str1v);
1037
1038     if(V_VT(str2v) != VT_BSTR) {
1039         FIXME("Unsupported str2 type %s\n", debugstr_variant(str2v));
1040         return E_NOTIMPL;
1041     }
1042     str2 = V_BSTR(str2v);
1043
1044     if(start < SysStringLen(str1)) {
1045         WCHAR *ptr;
1046
1047         ptr = strstrW(str1+start, str2);
1048         ret = ptr ? ptr-str1+1 : 0;
1049     }else {
1050         ret = 0;
1051     }
1052
1053     return return_int(res, ret);
1054 }
1055
1056 static HRESULT Global_InStrB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1057 {
1058     FIXME("\n");
1059     return E_NOTIMPL;
1060 }
1061
1062 static HRESULT Global_AscB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1063 {
1064     FIXME("\n");
1065     return E_NOTIMPL;
1066 }
1067
1068 static HRESULT Global_ChrB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1069 {
1070     FIXME("\n");
1071     return E_NOTIMPL;
1072 }
1073
1074 static HRESULT Global_Asc(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1075 {
1076     FIXME("\n");
1077     return E_NOTIMPL;
1078 }
1079
1080 static HRESULT Global_Chr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1081 {
1082     int c;
1083     HRESULT hres;
1084
1085     TRACE("%s\n", debugstr_variant(arg));
1086
1087     hres = to_int(arg, &c);
1088     if(FAILED(hres))
1089         return hres;
1090
1091     if(c <= 0 || c >= 0x100) {
1092         FIXME("invalid arg\n");
1093         return E_FAIL;
1094     }
1095
1096     if(res) {
1097         WCHAR ch = c;
1098
1099         V_VT(res) = VT_BSTR;
1100         V_BSTR(res) = SysAllocStringLen(&ch, 1);
1101         if(!V_BSTR(res))
1102             return E_OUTOFMEMORY;
1103     }
1104     return S_OK;
1105 }
1106
1107 static HRESULT Global_AscW(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1108 {
1109     FIXME("\n");
1110     return E_NOTIMPL;
1111 }
1112
1113 static HRESULT Global_ChrW(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1114 {
1115     FIXME("\n");
1116     return E_NOTIMPL;
1117 }
1118
1119 static HRESULT Global_Abs(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1120 {
1121     FIXME("\n");
1122     return E_NOTIMPL;
1123 }
1124
1125 static HRESULT Global_Fix(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1126 {
1127     FIXME("\n");
1128     return E_NOTIMPL;
1129 }
1130
1131 static HRESULT Global_Int(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1132 {
1133     FIXME("\n");
1134     return E_NOTIMPL;
1135 }
1136
1137 static HRESULT Global_Sgn(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1138 {
1139     FIXME("\n");
1140     return E_NOTIMPL;
1141 }
1142
1143 static HRESULT Global_Now(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1144 {
1145     SYSTEMTIME lt;
1146     double date;
1147
1148     TRACE("\n");
1149
1150     GetLocalTime(&lt);
1151     SystemTimeToVariantTime(&lt, &date);
1152     return return_date(res, date);
1153 }
1154
1155 static HRESULT Global_Date(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1156 {
1157     FIXME("\n");
1158     return E_NOTIMPL;
1159 }
1160
1161 static HRESULT Global_Time(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1162 {
1163     FIXME("\n");
1164     return E_NOTIMPL;
1165 }
1166
1167 static HRESULT Global_Day(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1168 {
1169     FIXME("\n");
1170     return E_NOTIMPL;
1171 }
1172
1173 static HRESULT Global_Month(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1174 {
1175     FIXME("\n");
1176     return E_NOTIMPL;
1177 }
1178
1179 static HRESULT Global_Weekday(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1180 {
1181     FIXME("\n");
1182     return E_NOTIMPL;
1183 }
1184
1185 static HRESULT Global_Year(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1186 {
1187     FIXME("\n");
1188     return E_NOTIMPL;
1189 }
1190
1191 static HRESULT Global_Hour(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1192 {
1193     FIXME("\n");
1194     return E_NOTIMPL;
1195 }
1196
1197 static HRESULT Global_Minute(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1198 {
1199     FIXME("\n");
1200     return E_NOTIMPL;
1201 }
1202
1203 static HRESULT Global_Second(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1204 {
1205     FIXME("\n");
1206     return E_NOTIMPL;
1207 }
1208
1209 static HRESULT Global_DateValue(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1210 {
1211     FIXME("\n");
1212     return E_NOTIMPL;
1213 }
1214
1215 static HRESULT Global_TimeValue(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1216 {
1217     FIXME("\n");
1218     return E_NOTIMPL;
1219 }
1220
1221 static HRESULT Global_DateSerial(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1222 {
1223     FIXME("\n");
1224     return E_NOTIMPL;
1225 }
1226
1227 static HRESULT Global_TimeSerial(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1228 {
1229     FIXME("\n");
1230     return E_NOTIMPL;
1231 }
1232
1233 static HRESULT Global_InputBox(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1234 {
1235     FIXME("\n");
1236     return E_NOTIMPL;
1237 }
1238
1239 static HRESULT Global_MsgBox(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1240 {
1241     BSTR prompt;
1242     HRESULT hres;
1243
1244     TRACE("\n");
1245
1246     if(args_cnt != 1) {
1247         FIXME("unsupported arg_cnt %d\n", args_cnt);
1248         return E_NOTIMPL;
1249     }
1250
1251     hres = to_string(args, &prompt);
1252     if(FAILED(hres))
1253         return hres;
1254
1255     hres = show_msgbox(This->desc->ctx, prompt, res);
1256     SysFreeString(prompt);
1257     return hres;
1258 }
1259
1260 static HRESULT Global_CreateObject(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1261 {
1262     IUnknown *obj;
1263     HRESULT hres;
1264
1265     TRACE("(%s)\n", debugstr_variant(arg));
1266
1267     if(V_VT(arg) != VT_BSTR) {
1268         FIXME("non-bstr arg\n");
1269         return E_INVALIDARG;
1270     }
1271
1272     obj = create_object(This->desc->ctx, V_BSTR(arg));
1273     if(!obj)
1274         return VB_E_CANNOT_CREATE_OBJ;
1275
1276     if(res) {
1277         hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&V_DISPATCH(res));
1278         if(FAILED(hres))
1279             return hres;
1280
1281         V_VT(res) = VT_DISPATCH;
1282     }
1283
1284     IUnknown_Release(obj);
1285     return S_OK;
1286 }
1287
1288 static HRESULT Global_GetObject(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1289 {
1290     IBindCtx *bind_ctx;
1291     IUnknown *obj_unk;
1292     IDispatch *disp;
1293     ULONG eaten = 0;
1294     IMoniker *mon;
1295     HRESULT hres;
1296
1297     TRACE("%s %s\n", args_cnt ? debugstr_variant(args) : "", args_cnt > 1 ? debugstr_variant(args+1) : "");
1298
1299     if(args_cnt != 1 || V_VT(args) != VT_BSTR) {
1300         FIXME("unsupported args\n");
1301         return E_NOTIMPL;
1302     }
1303
1304     if(This->desc->ctx->safeopt & (INTERFACE_USES_SECURITY_MANAGER|INTERFACESAFE_FOR_UNTRUSTED_DATA)) {
1305         WARN("blocked in current safety mode\n");
1306         return VB_E_CANNOT_CREATE_OBJ;
1307     }
1308
1309     hres = CreateBindCtx(0, &bind_ctx);
1310     if(FAILED(hres))
1311         return hres;
1312
1313     hres = MkParseDisplayName(bind_ctx, V_BSTR(args), &eaten, &mon);
1314     if(SUCCEEDED(hres)) {
1315         hres = IMoniker_BindToObject(mon, bind_ctx, NULL, &IID_IUnknown, (void**)&obj_unk);
1316         IMoniker_Release(mon);
1317     }else {
1318         hres = MK_E_SYNTAX;
1319     }
1320     IBindCtx_Release(bind_ctx);
1321     if(FAILED(hres))
1322         return hres;
1323
1324     hres = set_object_site(This->desc->ctx, obj_unk);
1325     if(FAILED(hres)) {
1326         IUnknown_Release(obj_unk);
1327         return hres;
1328     }
1329
1330     hres = IUnknown_QueryInterface(obj_unk, &IID_IDispatch, (void**)&disp);
1331     if(SUCCEEDED(hres)) {
1332         if(res) {
1333             V_VT(res) = VT_DISPATCH;
1334             V_DISPATCH(res) = disp;
1335         }else {
1336             IDispatch_Release(disp);
1337         }
1338     }else {
1339         FIXME("object does not support IDispatch\n");
1340     }
1341
1342     return hres;
1343 }
1344
1345 static HRESULT Global_DateAdd(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1346 {
1347     FIXME("\n");
1348     return E_NOTIMPL;
1349 }
1350
1351 static HRESULT Global_DateDiff(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1352 {
1353     FIXME("\n");
1354     return E_NOTIMPL;
1355 }
1356
1357 static HRESULT Global_DatePart(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1358 {
1359     FIXME("\n");
1360     return E_NOTIMPL;
1361 }
1362
1363 static HRESULT Global_TypeName(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1364 {
1365     FIXME("\n");
1366     return E_NOTIMPL;
1367 }
1368
1369 static HRESULT Global_Array(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1370 {
1371     FIXME("\n");
1372     return E_NOTIMPL;
1373 }
1374
1375 static HRESULT Global_Erase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1376 {
1377     FIXME("\n");
1378     return E_NOTIMPL;
1379 }
1380
1381 static HRESULT Global_Filter(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1382 {
1383     FIXME("\n");
1384     return E_NOTIMPL;
1385 }
1386
1387 static HRESULT Global_Join(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1388 {
1389     FIXME("\n");
1390     return E_NOTIMPL;
1391 }
1392
1393 static HRESULT Global_Split(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1394 {
1395     FIXME("\n");
1396     return E_NOTIMPL;
1397 }
1398
1399 static HRESULT Global_Replace(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1400 {
1401     FIXME("\n");
1402     return E_NOTIMPL;
1403 }
1404
1405 static HRESULT Global_StrReverse(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1406 {
1407     WCHAR *ptr1, *ptr2, ch;
1408     BSTR ret;
1409     HRESULT hres;
1410
1411     TRACE("%s\n", debugstr_variant(arg));
1412
1413     hres = to_string(arg, &ret);
1414     if(FAILED(hres))
1415         return hres;
1416
1417     ptr1 = ret;
1418     ptr2 = ret + SysStringLen(ret)-1;
1419     while(ptr1 < ptr2) {
1420         ch = *ptr1;
1421         *ptr1++ = *ptr2;
1422         *ptr2-- = ch;
1423     }
1424
1425     return return_bstr(res, ret);
1426 }
1427
1428 static HRESULT Global_InStrRev(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1429 {
1430     FIXME("\n");
1431     return E_NOTIMPL;
1432 }
1433
1434 static HRESULT Global_LoadPicture(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1435 {
1436     FIXME("\n");
1437     return E_NOTIMPL;
1438 }
1439
1440 static HRESULT Global_ScriptEngine(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1441 {
1442     FIXME("\n");
1443     return E_NOTIMPL;
1444 }
1445
1446 static HRESULT Global_ScriptEngineMajorVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1447 {
1448     FIXME("\n");
1449     return E_NOTIMPL;
1450 }
1451
1452 static HRESULT Global_ScriptEngineMinorVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1453 {
1454     FIXME("\n");
1455     return E_NOTIMPL;
1456 }
1457
1458 static HRESULT Global_ScriptEngineBuildVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1459 {
1460     FIXME("\n");
1461     return E_NOTIMPL;
1462 }
1463
1464 static HRESULT Global_FormatNumber(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1465 {
1466     FIXME("\n");
1467     return E_NOTIMPL;
1468 }
1469
1470 static HRESULT Global_FormatCurrency(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1471 {
1472     FIXME("\n");
1473     return E_NOTIMPL;
1474 }
1475
1476 static HRESULT Global_FormatPercent(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1477 {
1478     FIXME("\n");
1479     return E_NOTIMPL;
1480 }
1481
1482 static HRESULT Global_FormatDateTime(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1483 {
1484     FIXME("\n");
1485     return E_NOTIMPL;
1486 }
1487
1488 static HRESULT Global_WeekdayName(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1489 {
1490     int weekday, first_day = 1, abbrev = 0;
1491     BSTR ret;
1492     HRESULT hres;
1493
1494     TRACE("\n");
1495
1496     assert(1 <= args_cnt && args_cnt <= 3);
1497
1498     hres = to_int(args, &weekday);
1499     if(FAILED(hres))
1500         return hres;
1501
1502     if(args_cnt > 1) {
1503         hres = to_int(args+1, &abbrev);
1504         if(FAILED(hres))
1505             return hres;
1506
1507         if(args_cnt == 3) {
1508             hres = to_int(args+2, &first_day);
1509             if(FAILED(hres))
1510                 return hres;
1511         }
1512     }
1513
1514     hres = VarWeekdayName(weekday, abbrev, first_day, 0, &ret);
1515     if(FAILED(hres))
1516         return hres;
1517
1518     return return_bstr(res, ret);
1519 }
1520
1521 static HRESULT Global_MonthName(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1522 {
1523     int month, abbrev = 0;
1524     BSTR ret;
1525     HRESULT hres;
1526
1527     TRACE("\n");
1528
1529     assert(args_cnt == 1 || args_cnt == 2);
1530
1531     hres = to_int(args, &month);
1532     if(FAILED(hres))
1533         return hres;
1534
1535     if(args_cnt == 2) {
1536         hres = to_int(args+1, &abbrev);
1537         if(FAILED(hres))
1538             return hres;
1539     }
1540
1541     hres = VarMonthName(month, abbrev, 0, &ret);
1542     if(FAILED(hres))
1543         return hres;
1544
1545     return return_bstr(res, ret);
1546 }
1547
1548 static HRESULT Global_Round(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1549 {
1550     double n;
1551     HRESULT hres;
1552
1553     TRACE("%s\n", debugstr_variant(arg));
1554
1555     if(!res)
1556         return S_OK;
1557
1558     switch(V_VT(arg)) {
1559     case VT_I2:
1560     case VT_I4:
1561     case VT_BOOL:
1562         *res = *arg;
1563         return S_OK;
1564     case VT_R8:
1565         n = V_R8(arg);
1566         break;
1567     default:
1568         hres = to_double(arg, &n);
1569         if(FAILED(hres))
1570             return hres;
1571     }
1572
1573     return return_double(res, round(n));
1574 }
1575
1576 static HRESULT Global_Escape(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1577 {
1578     FIXME("\n");
1579     return E_NOTIMPL;
1580 }
1581
1582 static HRESULT Global_Unescape(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1583 {
1584     FIXME("\n");
1585     return E_NOTIMPL;
1586 }
1587
1588 static HRESULT Global_Eval(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1589 {
1590     FIXME("\n");
1591     return E_NOTIMPL;
1592 }
1593
1594 static HRESULT Global_Execute(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1595 {
1596     FIXME("\n");
1597     return E_NOTIMPL;
1598 }
1599
1600 static HRESULT Global_ExecuteGlobal(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1601 {
1602     FIXME("\n");
1603     return E_NOTIMPL;
1604 }
1605
1606 static HRESULT Global_GetRef(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1607 {
1608     FIXME("\n");
1609     return E_NOTIMPL;
1610 }
1611
1612 static HRESULT Global_vbBlack(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1613 {
1614     FIXME("\n");
1615     return E_NOTIMPL;
1616 }
1617
1618 static HRESULT Global_vbBlue(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1619 {
1620     FIXME("\n");
1621     return E_NOTIMPL;
1622 }
1623
1624 static HRESULT Global_vbCyan(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1625 {
1626     FIXME("\n");
1627     return E_NOTIMPL;
1628 }
1629
1630 static HRESULT Global_vbGreen(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1631 {
1632     FIXME("\n");
1633     return E_NOTIMPL;
1634 }
1635
1636 static HRESULT Global_vbMagenta(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1637 {
1638     FIXME("\n");
1639     return E_NOTIMPL;
1640 }
1641
1642 static HRESULT Global_vbRed(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1643 {
1644     FIXME("\n");
1645     return E_NOTIMPL;
1646 }
1647
1648 static HRESULT Global_vbWhite(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1649 {
1650     FIXME("\n");
1651     return E_NOTIMPL;
1652 }
1653
1654 static HRESULT Global_vbYellow(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1655 {
1656     FIXME("\n");
1657     return E_NOTIMPL;
1658 }
1659
1660 static HRESULT Global_vbCr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1661 {
1662     FIXME("\n");
1663     return E_NOTIMPL;
1664 }
1665
1666 static HRESULT Global_vbCrLf(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1667 {
1668     FIXME("\n");
1669     return E_NOTIMPL;
1670 }
1671
1672 static HRESULT Global_vbNewLine(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1673 {
1674     FIXME("\n");
1675     return E_NOTIMPL;
1676 }
1677
1678 static HRESULT Global_vbFormFeed(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1679 {
1680     FIXME("\n");
1681     return E_NOTIMPL;
1682 }
1683
1684 static HRESULT Global_vbLf(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1685 {
1686     FIXME("\n");
1687     return E_NOTIMPL;
1688 }
1689
1690 static HRESULT Global_vbNullChar(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1691 {
1692     FIXME("\n");
1693     return E_NOTIMPL;
1694 }
1695
1696 static HRESULT Global_vbNullString(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1697 {
1698     FIXME("\n");
1699     return E_NOTIMPL;
1700 }
1701
1702 static HRESULT Global_vbTab(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1703 {
1704     FIXME("\n");
1705     return E_NOTIMPL;
1706 }
1707
1708 static HRESULT Global_vbVerticalTab(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1709 {
1710     FIXME("\n");
1711     return E_NOTIMPL;
1712 }
1713
1714 static const builtin_prop_t global_props[] = {
1715     {DISPID_GLOBAL_VBUSESYSTEM,        NULL, BP_GET, VT_I2, 0},
1716     {DISPID_GLOBAL_USESYSTEMDAYOFWEEK, NULL, BP_GET, VT_I2, 0},
1717     {DISPID_GLOBAL_VBSUNDAY,           NULL, BP_GET, VT_I2, 1},
1718     {DISPID_GLOBAL_VBMONDAY,           NULL, BP_GET, VT_I2, 2},
1719     {DISPID_GLOBAL_VBTUESDAY,          NULL, BP_GET, VT_I2, 3},
1720     {DISPID_GLOBAL_VBWEDNESDAY,        NULL, BP_GET, VT_I2, 4},
1721     {DISPID_GLOBAL_VBTHURSDAY,         NULL, BP_GET, VT_I2, 5},
1722     {DISPID_GLOBAL_VBFRIDAY,           NULL, BP_GET, VT_I2, 6},
1723     {DISPID_GLOBAL_VBSATURDAY,         NULL, BP_GET, VT_I2, 7},
1724     {DISPID_GLOBAL_VBFIRSTJAN1,        NULL, BP_GET, VT_I2, 1},
1725     {DISPID_GLOBAL_VBFIRSTFOURDAYS,    NULL, BP_GET, VT_I2, 2},
1726     {DISPID_GLOBAL_VBFIRSTFULLWEEK,    NULL, BP_GET, VT_I2, 3},
1727     {DISPID_GLOBAL_VBOKONLY,           NULL, BP_GET, VT_I2, MB_OK},
1728     {DISPID_GLOBAL_VBOKCANCEL,         NULL, BP_GET, VT_I2, MB_OKCANCEL},
1729     {DISPID_GLOBAL_VBABORTRETRYIGNORE, NULL, BP_GET, VT_I2, MB_ABORTRETRYIGNORE},
1730     {DISPID_GLOBAL_VBYESNOCANCEL,      NULL, BP_GET, VT_I2, MB_YESNOCANCEL},
1731     {DISPID_GLOBAL_VBYESNO,            NULL, BP_GET, VT_I2, MB_YESNO},
1732     {DISPID_GLOBAL_VBRETRYCANCEL,      NULL, BP_GET, VT_I2, MB_RETRYCANCEL},
1733     {DISPID_GLOBAL_VBCRITICAL,         NULL, BP_GET, VT_I2, MB_ICONHAND},
1734     {DISPID_GLOBAL_VBQUESTION,         NULL, BP_GET, VT_I2, MB_ICONQUESTION},
1735     {DISPID_GLOBAL_VBEXCLAMATION,      NULL, BP_GET, VT_I2, MB_ICONEXCLAMATION},
1736     {DISPID_GLOBAL_VBINFORMATION,      NULL, BP_GET, VT_I2, MB_ICONASTERISK},
1737     {DISPID_GLOBAL_VBDEFAULTBUTTON1,   NULL, BP_GET, VT_I2, MB_DEFBUTTON1},
1738     {DISPID_GLOBAL_VBDEFAULTBUTTON2,   NULL, BP_GET, VT_I2, MB_DEFBUTTON2},
1739     {DISPID_GLOBAL_VBDEFAULTBUTTON3,   NULL, BP_GET, VT_I2, MB_DEFBUTTON3},
1740     {DISPID_GLOBAL_VBDEFAULTBUTTON4,   NULL, BP_GET, VT_I2, MB_DEFBUTTON4},
1741     {DISPID_GLOBAL_VBAPPLICATIONMODAL, NULL, BP_GET, VT_I2, MB_APPLMODAL},
1742     {DISPID_GLOBAL_VBSYSTEMMODAL,      NULL, BP_GET, VT_I2, MB_SYSTEMMODAL},
1743     {DISPID_GLOBAL_VBOK,               NULL, BP_GET, VT_I2, IDOK},
1744     {DISPID_GLOBAL_VBCANCEL,           NULL, BP_GET, VT_I2, IDCANCEL},
1745     {DISPID_GLOBAL_VBABORT,            NULL, BP_GET, VT_I2, IDABORT},
1746     {DISPID_GLOBAL_VBRETRY,            NULL, BP_GET, VT_I2, IDRETRY},
1747     {DISPID_GLOBAL_VBIGNORE,           NULL, BP_GET, VT_I2, IDIGNORE},
1748     {DISPID_GLOBAL_VBYES,              NULL, BP_GET, VT_I2, IDYES},
1749     {DISPID_GLOBAL_VBNO,               NULL, BP_GET, VT_I2, IDNO},
1750     {DISPID_GLOBAL_VBEMPTY,            NULL, BP_GET, VT_I2, VT_EMPTY},
1751     {DISPID_GLOBAL_VBNULL,             NULL, BP_GET, VT_I2, VT_NULL},
1752     {DISPID_GLOBAL_VBINTEGER,          NULL, BP_GET, VT_I2, VT_I2},
1753     {DISPID_GLOBAL_VBLONG,             NULL, BP_GET, VT_I2, VT_I4},
1754     {DISPID_GLOBAL_VBSINGLE,           NULL, BP_GET, VT_I2, VT_R4},
1755     {DISPID_GLOBAL_VBDOUBLE,           NULL, BP_GET, VT_I2, VT_R8},
1756     {DISPID_GLOBAL_VBCURRENCY,         NULL, BP_GET, VT_I2, VT_CY},
1757     {DISPID_GLOBAL_VBDATE,             NULL, BP_GET, VT_I2, VT_DATE},
1758     {DISPID_GLOBAL_VBSTRING,           NULL, BP_GET, VT_I2, VT_BSTR},
1759     {DISPID_GLOBAL_VBOBJECT,           NULL, BP_GET, VT_I2, VT_DISPATCH},
1760     {DISPID_GLOBAL_VBERROR,            NULL, BP_GET, VT_I2, VT_ERROR},
1761     {DISPID_GLOBAL_VBBOOLEAN,          NULL, BP_GET, VT_I2, VT_BOOL},
1762     {DISPID_GLOBAL_VBVARIANT,          NULL, BP_GET, VT_I2, VT_VARIANT},
1763     {DISPID_GLOBAL_VBDATAOBJECT,       NULL, BP_GET, VT_I2, VT_UNKNOWN},
1764     {DISPID_GLOBAL_VBDECIMAL,          NULL, BP_GET, VT_I2, VT_DECIMAL},
1765     {DISPID_GLOBAL_VBBYTE,             NULL, BP_GET, VT_I2, VT_UI1},
1766     {DISPID_GLOBAL_VBARRAY,            NULL, BP_GET, VT_I2, VT_ARRAY},
1767     {DISPID_GLOBAL_VBTRUE,             NULL, BP_GET, VT_I2, VARIANT_TRUE},
1768     {DISPID_GLOBAL_VBFALSE,            NULL, BP_GET, VT_I2, VARIANT_FALSE},
1769     {DISPID_GLOBAL_VBUSEDEFAULT,       NULL, BP_GET, VT_I2, -2},
1770     {DISPID_GLOBAL_VBBINARYCOMPARE,    NULL, BP_GET, VT_I2, 0},
1771     {DISPID_GLOBAL_VBTEXTCOMPARE,      NULL, BP_GET, VT_I2, 1},
1772     {DISPID_GLOBAL_VBDATABASECOMPARE,  NULL, BP_GET, VT_I2, 2},
1773     {DISPID_GLOBAL_VBGENERALDATE,      NULL, BP_GET, VT_I2, 0},
1774     {DISPID_GLOBAL_VBLONGDATE,         NULL, BP_GET, VT_I2, 1},
1775     {DISPID_GLOBAL_VBSHORTDATE,        NULL, BP_GET, VT_I2, 2},
1776     {DISPID_GLOBAL_VBLONGTIME,         NULL, BP_GET, VT_I2, 3},
1777     {DISPID_GLOBAL_VBSHORTTIME,        NULL, BP_GET, VT_I2, 4},
1778     {DISPID_GLOBAL_VBOBJECTERROR,      NULL, BP_GET, VT_I4, 0x80040000},
1779     {DISPID_GLOBAL_VBBLACK,            Global_vbBlack, BP_GET},
1780     {DISPID_GLOBAL_VBBLUE,             Global_vbBlue, BP_GET},
1781     {DISPID_GLOBAL_VBCYAN,             Global_vbCyan, BP_GET},
1782     {DISPID_GLOBAL_VBGREEN,            Global_vbGreen, BP_GET},
1783     {DISPID_GLOBAL_VBMAGENTA,          Global_vbMagenta, BP_GET},
1784     {DISPID_GLOBAL_VBRED,              Global_vbRed, BP_GET},
1785     {DISPID_GLOBAL_VBWHITE,            Global_vbWhite, BP_GET},
1786     {DISPID_GLOBAL_VBYELLOW,           Global_vbYellow, BP_GET},
1787     {DISPID_GLOBAL_VBCR,               Global_vbCr, BP_GET},
1788     {DISPID_GLOBAL_VBCRLF,             Global_vbCrLf, BP_GET},
1789     {DISPID_GLOBAL_VBNEWLINE,          Global_vbNewLine, BP_GET},
1790     {DISPID_GLOBAL_VBFORMFEED,         Global_vbFormFeed, BP_GET},
1791     {DISPID_GLOBAL_VBLF,               Global_vbLf, BP_GET},
1792     {DISPID_GLOBAL_VBNULLCHAR,         Global_vbNullChar, BP_GET},
1793     {DISPID_GLOBAL_VBNULLSTRING,       Global_vbNullString, BP_GET},
1794     {DISPID_GLOBAL_VBTAB,              Global_vbTab, BP_GET},
1795     {DISPID_GLOBAL_VBVERTICALTAB,      Global_vbVerticalTab, BP_GET},
1796     {DISPID_GLOBAL_CCUR,                      Global_CCur, 0, 1},
1797     {DISPID_GLOBAL_CINT,                      Global_CInt, 0, 1},
1798     {DISPID_GLOBAL_CLNG,                      Global_CLng, 0, 1},
1799     {DISPID_GLOBAL_CBOOL,                     Global_CBool, 0, 1},
1800     {DISPID_GLOBAL_CBYTE,                     Global_CByte, 0, 1},
1801     {DISPID_GLOBAL_CDATE,                     Global_CDate, 0, 1},
1802     {DISPID_GLOBAL_CDBL,                      Global_CDbl, 0, 1},
1803     {DISPID_GLOBAL_CSNG,                      Global_CSng, 0, 1},
1804     {DISPID_GLOBAL_CSTR,                      Global_CStr, 0, 1},
1805     {DISPID_GLOBAL_HEX,                       Global_Hex, 0, 1},
1806     {DISPID_GLOBAL_OCT,                       Global_Oct, 0, 1},
1807     {DISPID_GLOBAL_VARTYPE,                   Global_VarType, 0, 1},
1808     {DISPID_GLOBAL_ISDATE,                    Global_IsDate, 0, 1},
1809     {DISPID_GLOBAL_ISEMPTY,                   Global_IsEmpty, 0, 1},
1810     {DISPID_GLOBAL_ISNULL,                    Global_IsNull, 0, 1},
1811     {DISPID_GLOBAL_ISNUMERIC,                 Global_IsNumeric, 0, 1},
1812     {DISPID_GLOBAL_ISARRAY,                   Global_IsArray, 0, 1},
1813     {DISPID_GLOBAL_ISOBJECT,                  Global_IsObject, 0, 1},
1814     {DISPID_GLOBAL_ATN,                       Global_Ant, 0, 1},
1815     {DISPID_GLOBAL_COS,                       Global_Cos, 0, 1},
1816     {DISPID_GLOBAL_SIN,                       Global_Sin, 0, 1},
1817     {DISPID_GLOBAL_TAN,                       Global_Tan, 0, 1},
1818     {DISPID_GLOBAL_EXP,                       Global_Exp, 0, 1},
1819     {DISPID_GLOBAL_LOG,                       Global_Log, 0, 1},
1820     {DISPID_GLOBAL_SQR,                       Global_Sqr, 0, 1},
1821     {DISPID_GLOBAL_RANDOMIZE,                 Global_Randomize, 0, 1},
1822     {DISPID_GLOBAL_RND,                       Global_Rnd, 0, 1},
1823     {DISPID_GLOBAL_TIMER,                     Global_Timer, 0, 0},
1824     {DISPID_GLOBAL_LBOUND,                    Global_LBound, 0, 1},
1825     {DISPID_GLOBAL_UBOUND,                    Global_UBound, 0, 1},
1826     {DISPID_GLOBAL_RGB,                       Global_RGB, 0, 3},
1827     {DISPID_GLOBAL_LEN,                       Global_Len, 0, 1},
1828     {DISPID_GLOBAL_LENB,                      Global_LenB, 0, 1},
1829     {DISPID_GLOBAL_LEFT,                      Global_Left, 0, 2},
1830     {DISPID_GLOBAL_LEFTB,                     Global_LeftB, 0, 2},
1831     {DISPID_GLOBAL_RIGHT,                     Global_Right, 0, 2},
1832     {DISPID_GLOBAL_RIGHTB,                    Global_RightB, 0, 2},
1833     {DISPID_GLOBAL_MID,                       Global_Mid, 0, 2, 3},
1834     {DISPID_GLOBAL_MIDB,                      Global_MidB, 0, 2, 3},
1835     {DISPID_GLOBAL_STRCOMP,                   Global_StrComp, 0, 2, 3},
1836     {DISPID_GLOBAL_LCASE,                     Global_LCase, 0, 1},
1837     {DISPID_GLOBAL_UCASE,                     Global_UCase, 0, 1},
1838     {DISPID_GLOBAL_LTRIM,                     Global_LTrim, 0, 1},
1839     {DISPID_GLOBAL_RTRIM,                     Global_RTrim, 0, 1},
1840     {DISPID_GLOBAL_TRIM,                      Global_Trim, 0, 1},
1841     {DISPID_GLOBAL_SPACE,                     Global_Space, 0, 1},
1842     {DISPID_GLOBAL_STRING,                    Global_String, 0, 0, 2},
1843     {DISPID_GLOBAL_INSTR,                     Global_InStr, 0, 2, 4},
1844     {DISPID_GLOBAL_INSTRB,                    Global_InStrB, 0, 3, 4},
1845     {DISPID_GLOBAL_ASCB,                      Global_AscB, 0, 1},
1846     {DISPID_GLOBAL_CHRB,                      Global_ChrB, 0, 1},
1847     {DISPID_GLOBAL_ASC,                       Global_Asc, 0, 1},
1848     {DISPID_GLOBAL_CHR,                       Global_Chr, 0, 1},
1849     {DISPID_GLOBAL_ASCW,                      Global_AscW, 0, 1},
1850     {DISPID_GLOBAL_CHRW,                      Global_ChrW, 0, 1},
1851     {DISPID_GLOBAL_ABS,                       Global_Abs, 0, 1},
1852     {DISPID_GLOBAL_FIX,                       Global_Fix, 0, 1},
1853     {DISPID_GLOBAL_INT,                       Global_Int, 0, 1},
1854     {DISPID_GLOBAL_SGN,                       Global_Sgn, 0, 1},
1855     {DISPID_GLOBAL_NOW,                       Global_Now, 0, 0},
1856     {DISPID_GLOBAL_DATE,                      Global_Date, 0, 0},
1857     {DISPID_GLOBAL_TIME,                      Global_Time, 0, 0},
1858     {DISPID_GLOBAL_DAY,                       Global_Day, 0, 1},
1859     {DISPID_GLOBAL_MONTH,                     Global_Month, 0, 1},
1860     {DISPID_GLOBAL_WEEKDAY,                   Global_Weekday, 0, 1, 2},
1861     {DISPID_GLOBAL_YEAR,                      Global_Year, 0, 1},
1862     {DISPID_GLOBAL_HOUR,                      Global_Hour, 0, 1},
1863     {DISPID_GLOBAL_MINUTE,                    Global_Minute, 0, 1},
1864     {DISPID_GLOBAL_SECOND,                    Global_Second, 0, 1},
1865     {DISPID_GLOBAL_DATEVALUE,                 Global_DateValue, 0, 1},
1866     {DISPID_GLOBAL_TIMEVALUE,                 Global_TimeValue, 0, 1},
1867     {DISPID_GLOBAL_DATESERIAL,                Global_DateSerial, 0, 3},
1868     {DISPID_GLOBAL_TIMESERIAL,                Global_TimeSerial, 0, 3},
1869     {DISPID_GLOBAL_INPUTBOX,                  Global_InputBox, 0, 1, 7},
1870     {DISPID_GLOBAL_MSGBOX,                    Global_MsgBox, 0, 1, 5},
1871     {DISPID_GLOBAL_CREATEOBJECT,              Global_CreateObject, 0, 1},
1872     {DISPID_GLOBAL_GETOBJECT,                 Global_GetObject, 0, 0, 2},
1873     {DISPID_GLOBAL_DATEADD,                   Global_DateAdd, 0, 3},
1874     {DISPID_GLOBAL_DATEDIFF,                  Global_DateDiff, 0, 3, 5},
1875     {DISPID_GLOBAL_DATEPART,                  Global_DatePart, 0, 2, 4},
1876     {DISPID_GLOBAL_TYPENAME,                  Global_TypeName, 0, 1},
1877     {DISPID_GLOBAL_ARRAY,                     Global_Array, 0, 1},
1878     {DISPID_GLOBAL_ERASE,                     Global_Erase, 0, 1},
1879     {DISPID_GLOBAL_FILTER,                    Global_Filter, 0, 2, 4},
1880     {DISPID_GLOBAL_JOIN,                      Global_Join, 0, 1, 2},
1881     {DISPID_GLOBAL_SPLIT,                     Global_Split, 0, 1, 4},
1882     {DISPID_GLOBAL_REPLACE,                   Global_Replace, 0, 3, 6},
1883     {DISPID_GLOBAL_STRREVERSE,                Global_StrReverse, 0, 1},
1884     {DISPID_GLOBAL_INSTRREV,                  Global_InStrRev, 0, 2, 4},
1885     {DISPID_GLOBAL_LOADPICTURE,               Global_LoadPicture, 0, 1},
1886     {DISPID_GLOBAL_SCRIPTENGINE,              Global_ScriptEngine, 0, 0},
1887     {DISPID_GLOBAL_SCRIPTENGINEMAJORVERSION,  Global_ScriptEngineMajorVersion, 0, 0},
1888     {DISPID_GLOBAL_SCRIPTENGINEMINORVERSION,  Global_ScriptEngineMinorVersion, 0, 0},
1889     {DISPID_GLOBAL_SCRIPTENGINEBUILDVERSION,  Global_ScriptEngineBuildVersion, 0, 0},
1890     {DISPID_GLOBAL_FORMATNUMBER,              Global_FormatNumber, 0, 1, 5},
1891     {DISPID_GLOBAL_FORMATCURRENCY,            Global_FormatCurrency, 0, 1, 5},
1892     {DISPID_GLOBAL_FORMATPERCENT,             Global_FormatPercent, 0, 1, 5},
1893     {DISPID_GLOBAL_FORMATDATETIME,            Global_FormatDateTime, 0, 1, 2},
1894     {DISPID_GLOBAL_WEEKDAYNAME,               Global_WeekdayName, 0, 1, 3},
1895     {DISPID_GLOBAL_MONTHNAME,                 Global_MonthName, 0, 1, 2},
1896     {DISPID_GLOBAL_ROUND,                     Global_Round, 0, 1, 2},
1897     {DISPID_GLOBAL_ESCAPE,                    Global_Escape, 0, 1},
1898     {DISPID_GLOBAL_UNESCAPE,                  Global_Unescape, 0, 1},
1899     {DISPID_GLOBAL_EVAL,                      Global_Eval, 0, 1},
1900     {DISPID_GLOBAL_EXECUTE,                   Global_Execute, 0, 1},
1901     {DISPID_GLOBAL_EXECUTEGLOBAL,             Global_ExecuteGlobal, 0, 1},
1902     {DISPID_GLOBAL_GETREF,                    Global_GetRef, 0, 1},
1903     {DISPID_GLOBAL_VBMSGBOXHELPBUTTON,     NULL, BP_GET, VT_I4, MB_HELP},
1904     {DISPID_GLOBAL_VBMSGBOXSETFOREGROUND,  NULL, BP_GET, VT_I4, MB_SETFOREGROUND},
1905     {DISPID_GLOBAL_VBMSGBOXRIGHT,          NULL, BP_GET, VT_I4, MB_RIGHT},
1906     {DISPID_GLOBAL_VBMSGBOXRTLREADING,     NULL, BP_GET, VT_I4, MB_RTLREADING}
1907 };
1908
1909 HRESULT init_global(script_ctx_t *ctx)
1910 {
1911     HRESULT hres;
1912
1913     ctx->global_desc.ctx = ctx;
1914     ctx->global_desc.builtin_prop_cnt = sizeof(global_props)/sizeof(*global_props);
1915     ctx->global_desc.builtin_props = global_props;
1916
1917     hres = get_typeinfo(GlobalObj_tid, &ctx->global_desc.typeinfo);
1918     if(FAILED(hres))
1919         return hres;
1920
1921     hres = create_vbdisp(&ctx->global_desc, &ctx->global_obj);
1922     if(FAILED(hres))
1923         return hres;
1924
1925     hres = create_script_disp(ctx, &ctx->script_obj);
1926     if(FAILED(hres))
1927         return hres;
1928
1929     return init_err(ctx);
1930 }