mshtml: Added IOmHistory::get_length implementation.
[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_UNREACHABLE;
1014     }
1015
1016     if(startv) {
1017         hres = to_int(startv, &start);
1018         if(FAILED(hres))
1019             return hres;
1020         if(--start < 0) {
1021             FIXME("start %d\n", start);
1022             return E_FAIL;
1023         }
1024     }else {
1025         start = 0;
1026     }
1027
1028     if(V_VT(str1v) == VT_NULL || V_VT(str2v) == VT_NULL)
1029         return return_null(res);
1030
1031     if(V_VT(str1v) != VT_BSTR) {
1032         FIXME("Unsupported str1 type %s\n", debugstr_variant(str1v));
1033         return E_NOTIMPL;
1034     }
1035     str1 = V_BSTR(str1v);
1036
1037     if(V_VT(str2v) != VT_BSTR) {
1038         FIXME("Unsupported str2 type %s\n", debugstr_variant(str2v));
1039         return E_NOTIMPL;
1040     }
1041     str2 = V_BSTR(str2v);
1042
1043     if(start < SysStringLen(str1)) {
1044         WCHAR *ptr;
1045
1046         ptr = strstrW(str1+start, str2);
1047         ret = ptr ? ptr-str1+1 : 0;
1048     }else {
1049         ret = 0;
1050     }
1051
1052     return return_int(res, ret);
1053 }
1054
1055 static HRESULT Global_InStrB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1056 {
1057     FIXME("\n");
1058     return E_NOTIMPL;
1059 }
1060
1061 static HRESULT Global_AscB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1062 {
1063     FIXME("\n");
1064     return E_NOTIMPL;
1065 }
1066
1067 static HRESULT Global_ChrB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1068 {
1069     FIXME("\n");
1070     return E_NOTIMPL;
1071 }
1072
1073 static HRESULT Global_Asc(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1074 {
1075     FIXME("\n");
1076     return E_NOTIMPL;
1077 }
1078
1079 static HRESULT Global_Chr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1080 {
1081     int c;
1082     HRESULT hres;
1083
1084     TRACE("%s\n", debugstr_variant(arg));
1085
1086     hres = to_int(arg, &c);
1087     if(FAILED(hres))
1088         return hres;
1089
1090     if(c < 0 || c >= 0x100) {
1091         FIXME("invalid arg\n");
1092         return E_FAIL;
1093     }
1094
1095     if(res) {
1096         WCHAR ch = c;
1097
1098         V_VT(res) = VT_BSTR;
1099         V_BSTR(res) = SysAllocStringLen(&ch, 1);
1100         if(!V_BSTR(res))
1101             return E_OUTOFMEMORY;
1102     }
1103     return S_OK;
1104 }
1105
1106 static HRESULT Global_AscW(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1107 {
1108     FIXME("\n");
1109     return E_NOTIMPL;
1110 }
1111
1112 static HRESULT Global_ChrW(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1113 {
1114     FIXME("\n");
1115     return E_NOTIMPL;
1116 }
1117
1118 static HRESULT Global_Abs(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1119 {
1120     FIXME("\n");
1121     return E_NOTIMPL;
1122 }
1123
1124 static HRESULT Global_Fix(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1125 {
1126     FIXME("\n");
1127     return E_NOTIMPL;
1128 }
1129
1130 static HRESULT Global_Int(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1131 {
1132     FIXME("\n");
1133     return E_NOTIMPL;
1134 }
1135
1136 static HRESULT Global_Sgn(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1137 {
1138     FIXME("\n");
1139     return E_NOTIMPL;
1140 }
1141
1142 static HRESULT Global_Now(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1143 {
1144     SYSTEMTIME lt;
1145     double date;
1146
1147     TRACE("\n");
1148
1149     GetLocalTime(&lt);
1150     SystemTimeToVariantTime(&lt, &date);
1151     return return_date(res, date);
1152 }
1153
1154 static HRESULT Global_Date(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1155 {
1156     FIXME("\n");
1157     return E_NOTIMPL;
1158 }
1159
1160 static HRESULT Global_Time(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1161 {
1162     FIXME("\n");
1163     return E_NOTIMPL;
1164 }
1165
1166 static HRESULT Global_Day(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1167 {
1168     FIXME("\n");
1169     return E_NOTIMPL;
1170 }
1171
1172 static HRESULT Global_Month(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1173 {
1174     FIXME("\n");
1175     return E_NOTIMPL;
1176 }
1177
1178 static HRESULT Global_Weekday(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1179 {
1180     FIXME("\n");
1181     return E_NOTIMPL;
1182 }
1183
1184 static HRESULT Global_Year(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1185 {
1186     FIXME("\n");
1187     return E_NOTIMPL;
1188 }
1189
1190 static HRESULT Global_Hour(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1191 {
1192     FIXME("\n");
1193     return E_NOTIMPL;
1194 }
1195
1196 static HRESULT Global_Minute(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1197 {
1198     FIXME("\n");
1199     return E_NOTIMPL;
1200 }
1201
1202 static HRESULT Global_Second(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1203 {
1204     FIXME("\n");
1205     return E_NOTIMPL;
1206 }
1207
1208 static HRESULT Global_DateValue(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1209 {
1210     FIXME("\n");
1211     return E_NOTIMPL;
1212 }
1213
1214 static HRESULT Global_TimeValue(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1215 {
1216     FIXME("\n");
1217     return E_NOTIMPL;
1218 }
1219
1220 static HRESULT Global_DateSerial(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1221 {
1222     FIXME("\n");
1223     return E_NOTIMPL;
1224 }
1225
1226 static HRESULT Global_TimeSerial(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1227 {
1228     FIXME("\n");
1229     return E_NOTIMPL;
1230 }
1231
1232 static HRESULT Global_InputBox(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1233 {
1234     FIXME("\n");
1235     return E_NOTIMPL;
1236 }
1237
1238 static HRESULT Global_MsgBox(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1239 {
1240     BSTR prompt;
1241     HRESULT hres;
1242
1243     TRACE("\n");
1244
1245     if(args_cnt != 1) {
1246         FIXME("unsupported arg_cnt %d\n", args_cnt);
1247         return E_NOTIMPL;
1248     }
1249
1250     hres = to_string(args, &prompt);
1251     if(FAILED(hres))
1252         return hres;
1253
1254     hres = show_msgbox(This->desc->ctx, prompt, res);
1255     SysFreeString(prompt);
1256     return hres;
1257 }
1258
1259 static HRESULT Global_CreateObject(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1260 {
1261     IUnknown *obj;
1262     HRESULT hres;
1263
1264     TRACE("(%s)\n", debugstr_variant(arg));
1265
1266     if(V_VT(arg) != VT_BSTR) {
1267         FIXME("non-bstr arg\n");
1268         return E_INVALIDARG;
1269     }
1270
1271     obj = create_object(This->desc->ctx, V_BSTR(arg));
1272     if(!obj)
1273         return VB_E_CANNOT_CREATE_OBJ;
1274
1275     if(res) {
1276         hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&V_DISPATCH(res));
1277         if(FAILED(hres))
1278             return hres;
1279
1280         V_VT(res) = VT_DISPATCH;
1281     }
1282
1283     IUnknown_Release(obj);
1284     return S_OK;
1285 }
1286
1287 static HRESULT Global_GetObject(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1288 {
1289     IBindCtx *bind_ctx;
1290     IUnknown *obj_unk;
1291     IDispatch *disp;
1292     ULONG eaten = 0;
1293     IMoniker *mon;
1294     HRESULT hres;
1295
1296     TRACE("%s %s\n", args_cnt ? debugstr_variant(args) : "", args_cnt > 1 ? debugstr_variant(args+1) : "");
1297
1298     if(args_cnt != 1 || V_VT(args) != VT_BSTR) {
1299         FIXME("unsupported args\n");
1300         return E_NOTIMPL;
1301     }
1302
1303     if(This->desc->ctx->safeopt & (INTERFACE_USES_SECURITY_MANAGER|INTERFACESAFE_FOR_UNTRUSTED_DATA)) {
1304         WARN("blocked in current safety mode\n");
1305         return VB_E_CANNOT_CREATE_OBJ;
1306     }
1307
1308     hres = CreateBindCtx(0, &bind_ctx);
1309     if(FAILED(hres))
1310         return hres;
1311
1312     hres = MkParseDisplayName(bind_ctx, V_BSTR(args), &eaten, &mon);
1313     if(SUCCEEDED(hres)) {
1314         hres = IMoniker_BindToObject(mon, bind_ctx, NULL, &IID_IUnknown, (void**)&obj_unk);
1315         IMoniker_Release(mon);
1316     }else {
1317         hres = MK_E_SYNTAX;
1318     }
1319     IBindCtx_Release(bind_ctx);
1320     if(FAILED(hres))
1321         return hres;
1322
1323     hres = set_object_site(This->desc->ctx, obj_unk);
1324     if(FAILED(hres)) {
1325         IUnknown_Release(obj_unk);
1326         return hres;
1327     }
1328
1329     hres = IUnknown_QueryInterface(obj_unk, &IID_IDispatch, (void**)&disp);
1330     if(SUCCEEDED(hres)) {
1331         if(res) {
1332             V_VT(res) = VT_DISPATCH;
1333             V_DISPATCH(res) = disp;
1334         }else {
1335             IDispatch_Release(disp);
1336         }
1337     }else {
1338         FIXME("object does not support IDispatch\n");
1339     }
1340
1341     return hres;
1342 }
1343
1344 static HRESULT Global_DateAdd(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1345 {
1346     FIXME("\n");
1347     return E_NOTIMPL;
1348 }
1349
1350 static HRESULT Global_DateDiff(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1351 {
1352     FIXME("\n");
1353     return E_NOTIMPL;
1354 }
1355
1356 static HRESULT Global_DatePart(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1357 {
1358     FIXME("\n");
1359     return E_NOTIMPL;
1360 }
1361
1362 static HRESULT Global_TypeName(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1363 {
1364     FIXME("\n");
1365     return E_NOTIMPL;
1366 }
1367
1368 static HRESULT Global_Array(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1369 {
1370     FIXME("\n");
1371     return E_NOTIMPL;
1372 }
1373
1374 static HRESULT Global_Erase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1375 {
1376     FIXME("\n");
1377     return E_NOTIMPL;
1378 }
1379
1380 static HRESULT Global_Filter(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1381 {
1382     FIXME("\n");
1383     return E_NOTIMPL;
1384 }
1385
1386 static HRESULT Global_Join(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1387 {
1388     FIXME("\n");
1389     return E_NOTIMPL;
1390 }
1391
1392 static HRESULT Global_Split(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1393 {
1394     FIXME("\n");
1395     return E_NOTIMPL;
1396 }
1397
1398 static HRESULT Global_Replace(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1399 {
1400     FIXME("\n");
1401     return E_NOTIMPL;
1402 }
1403
1404 static HRESULT Global_StrReverse(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1405 {
1406     WCHAR *ptr1, *ptr2, ch;
1407     BSTR ret;
1408     HRESULT hres;
1409
1410     TRACE("%s\n", debugstr_variant(arg));
1411
1412     hres = to_string(arg, &ret);
1413     if(FAILED(hres))
1414         return hres;
1415
1416     ptr1 = ret;
1417     ptr2 = ret + SysStringLen(ret)-1;
1418     while(ptr1 < ptr2) {
1419         ch = *ptr1;
1420         *ptr1++ = *ptr2;
1421         *ptr2-- = ch;
1422     }
1423
1424     return return_bstr(res, ret);
1425 }
1426
1427 static HRESULT Global_InStrRev(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1428 {
1429     FIXME("\n");
1430     return E_NOTIMPL;
1431 }
1432
1433 static HRESULT Global_LoadPicture(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1434 {
1435     FIXME("\n");
1436     return E_NOTIMPL;
1437 }
1438
1439 static HRESULT Global_ScriptEngine(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1440 {
1441     FIXME("\n");
1442     return E_NOTIMPL;
1443 }
1444
1445 static HRESULT Global_ScriptEngineMajorVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1446 {
1447     FIXME("\n");
1448     return E_NOTIMPL;
1449 }
1450
1451 static HRESULT Global_ScriptEngineMinorVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1452 {
1453     FIXME("\n");
1454     return E_NOTIMPL;
1455 }
1456
1457 static HRESULT Global_ScriptEngineBuildVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1458 {
1459     FIXME("\n");
1460     return E_NOTIMPL;
1461 }
1462
1463 static HRESULT Global_FormatNumber(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1464 {
1465     FIXME("\n");
1466     return E_NOTIMPL;
1467 }
1468
1469 static HRESULT Global_FormatCurrency(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1470 {
1471     FIXME("\n");
1472     return E_NOTIMPL;
1473 }
1474
1475 static HRESULT Global_FormatPercent(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1476 {
1477     FIXME("\n");
1478     return E_NOTIMPL;
1479 }
1480
1481 static HRESULT Global_FormatDateTime(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1482 {
1483     FIXME("\n");
1484     return E_NOTIMPL;
1485 }
1486
1487 static HRESULT Global_WeekdayName(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1488 {
1489     int weekday, first_day = 1, abbrev = 0;
1490     BSTR ret;
1491     HRESULT hres;
1492
1493     TRACE("\n");
1494
1495     assert(1 <= args_cnt && args_cnt <= 3);
1496
1497     hres = to_int(args, &weekday);
1498     if(FAILED(hres))
1499         return hres;
1500
1501     if(args_cnt > 1) {
1502         hres = to_int(args+1, &abbrev);
1503         if(FAILED(hres))
1504             return hres;
1505
1506         if(args_cnt == 3) {
1507             hres = to_int(args+2, &first_day);
1508             if(FAILED(hres))
1509                 return hres;
1510         }
1511     }
1512
1513     hres = VarWeekdayName(weekday, abbrev, first_day, 0, &ret);
1514     if(FAILED(hres))
1515         return hres;
1516
1517     return return_bstr(res, ret);
1518 }
1519
1520 static HRESULT Global_MonthName(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1521 {
1522     int month, abbrev = 0;
1523     BSTR ret;
1524     HRESULT hres;
1525
1526     TRACE("\n");
1527
1528     assert(args_cnt == 1 || args_cnt == 2);
1529
1530     hres = to_int(args, &month);
1531     if(FAILED(hres))
1532         return hres;
1533
1534     if(args_cnt == 2) {
1535         hres = to_int(args+1, &abbrev);
1536         if(FAILED(hres))
1537             return hres;
1538     }
1539
1540     hres = VarMonthName(month, abbrev, 0, &ret);
1541     if(FAILED(hres))
1542         return hres;
1543
1544     return return_bstr(res, ret);
1545 }
1546
1547 static HRESULT Global_Round(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1548 {
1549     double n;
1550     HRESULT hres;
1551
1552     TRACE("%s\n", debugstr_variant(arg));
1553
1554     if(!res)
1555         return S_OK;
1556
1557     switch(V_VT(arg)) {
1558     case VT_I2:
1559     case VT_I4:
1560     case VT_BOOL:
1561         *res = *arg;
1562         return S_OK;
1563     case VT_R8:
1564         n = V_R8(arg);
1565         break;
1566     default:
1567         hres = to_double(arg, &n);
1568         if(FAILED(hres))
1569             return hres;
1570     }
1571
1572     return return_double(res, round(n));
1573 }
1574
1575 static HRESULT Global_Escape(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1576 {
1577     FIXME("\n");
1578     return E_NOTIMPL;
1579 }
1580
1581 static HRESULT Global_Unescape(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1582 {
1583     FIXME("\n");
1584     return E_NOTIMPL;
1585 }
1586
1587 static HRESULT Global_Eval(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1588 {
1589     FIXME("\n");
1590     return E_NOTIMPL;
1591 }
1592
1593 static HRESULT Global_Execute(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1594 {
1595     FIXME("\n");
1596     return E_NOTIMPL;
1597 }
1598
1599 static HRESULT Global_ExecuteGlobal(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1600 {
1601     FIXME("\n");
1602     return E_NOTIMPL;
1603 }
1604
1605 static HRESULT Global_GetRef(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1606 {
1607     FIXME("\n");
1608     return E_NOTIMPL;
1609 }
1610
1611 static const string_constant_t vbCr          = {1, {'\r'}};
1612 static const string_constant_t vbCrLf        = {2, {'\r','\n'}};
1613 static const string_constant_t vbNewLine     = {2, {'\r','\n'}};
1614 static const string_constant_t vbFormFeed    = {1, {0xc}};
1615 static const string_constant_t vbLf          = {1, {'\n'}};
1616 static const string_constant_t vbNullChar    = {1};
1617 static const string_constant_t vbNullString  = {0};
1618 static const string_constant_t vbTab         = {1, {'\t'}};
1619 static const string_constant_t vbVerticalTab = {1, {0xb}};
1620
1621 static const builtin_prop_t global_props[] = {
1622     {DISPID_GLOBAL_VBUSESYSTEM,        NULL, BP_GET, VT_I2, 0},
1623     {DISPID_GLOBAL_USESYSTEMDAYOFWEEK, NULL, BP_GET, VT_I2, 0},
1624     {DISPID_GLOBAL_VBSUNDAY,           NULL, BP_GET, VT_I2, 1},
1625     {DISPID_GLOBAL_VBMONDAY,           NULL, BP_GET, VT_I2, 2},
1626     {DISPID_GLOBAL_VBTUESDAY,          NULL, BP_GET, VT_I2, 3},
1627     {DISPID_GLOBAL_VBWEDNESDAY,        NULL, BP_GET, VT_I2, 4},
1628     {DISPID_GLOBAL_VBTHURSDAY,         NULL, BP_GET, VT_I2, 5},
1629     {DISPID_GLOBAL_VBFRIDAY,           NULL, BP_GET, VT_I2, 6},
1630     {DISPID_GLOBAL_VBSATURDAY,         NULL, BP_GET, VT_I2, 7},
1631     {DISPID_GLOBAL_VBFIRSTJAN1,        NULL, BP_GET, VT_I2, 1},
1632     {DISPID_GLOBAL_VBFIRSTFOURDAYS,    NULL, BP_GET, VT_I2, 2},
1633     {DISPID_GLOBAL_VBFIRSTFULLWEEK,    NULL, BP_GET, VT_I2, 3},
1634     {DISPID_GLOBAL_VBOKONLY,           NULL, BP_GET, VT_I2, MB_OK},
1635     {DISPID_GLOBAL_VBOKCANCEL,         NULL, BP_GET, VT_I2, MB_OKCANCEL},
1636     {DISPID_GLOBAL_VBABORTRETRYIGNORE, NULL, BP_GET, VT_I2, MB_ABORTRETRYIGNORE},
1637     {DISPID_GLOBAL_VBYESNOCANCEL,      NULL, BP_GET, VT_I2, MB_YESNOCANCEL},
1638     {DISPID_GLOBAL_VBYESNO,            NULL, BP_GET, VT_I2, MB_YESNO},
1639     {DISPID_GLOBAL_VBRETRYCANCEL,      NULL, BP_GET, VT_I2, MB_RETRYCANCEL},
1640     {DISPID_GLOBAL_VBCRITICAL,         NULL, BP_GET, VT_I2, MB_ICONHAND},
1641     {DISPID_GLOBAL_VBQUESTION,         NULL, BP_GET, VT_I2, MB_ICONQUESTION},
1642     {DISPID_GLOBAL_VBEXCLAMATION,      NULL, BP_GET, VT_I2, MB_ICONEXCLAMATION},
1643     {DISPID_GLOBAL_VBINFORMATION,      NULL, BP_GET, VT_I2, MB_ICONASTERISK},
1644     {DISPID_GLOBAL_VBDEFAULTBUTTON1,   NULL, BP_GET, VT_I2, MB_DEFBUTTON1},
1645     {DISPID_GLOBAL_VBDEFAULTBUTTON2,   NULL, BP_GET, VT_I2, MB_DEFBUTTON2},
1646     {DISPID_GLOBAL_VBDEFAULTBUTTON3,   NULL, BP_GET, VT_I2, MB_DEFBUTTON3},
1647     {DISPID_GLOBAL_VBDEFAULTBUTTON4,   NULL, BP_GET, VT_I2, MB_DEFBUTTON4},
1648     {DISPID_GLOBAL_VBAPPLICATIONMODAL, NULL, BP_GET, VT_I2, MB_APPLMODAL},
1649     {DISPID_GLOBAL_VBSYSTEMMODAL,      NULL, BP_GET, VT_I2, MB_SYSTEMMODAL},
1650     {DISPID_GLOBAL_VBOK,               NULL, BP_GET, VT_I2, IDOK},
1651     {DISPID_GLOBAL_VBCANCEL,           NULL, BP_GET, VT_I2, IDCANCEL},
1652     {DISPID_GLOBAL_VBABORT,            NULL, BP_GET, VT_I2, IDABORT},
1653     {DISPID_GLOBAL_VBRETRY,            NULL, BP_GET, VT_I2, IDRETRY},
1654     {DISPID_GLOBAL_VBIGNORE,           NULL, BP_GET, VT_I2, IDIGNORE},
1655     {DISPID_GLOBAL_VBYES,              NULL, BP_GET, VT_I2, IDYES},
1656     {DISPID_GLOBAL_VBNO,               NULL, BP_GET, VT_I2, IDNO},
1657     {DISPID_GLOBAL_VBEMPTY,            NULL, BP_GET, VT_I2, VT_EMPTY},
1658     {DISPID_GLOBAL_VBNULL,             NULL, BP_GET, VT_I2, VT_NULL},
1659     {DISPID_GLOBAL_VBINTEGER,          NULL, BP_GET, VT_I2, VT_I2},
1660     {DISPID_GLOBAL_VBLONG,             NULL, BP_GET, VT_I2, VT_I4},
1661     {DISPID_GLOBAL_VBSINGLE,           NULL, BP_GET, VT_I2, VT_R4},
1662     {DISPID_GLOBAL_VBDOUBLE,           NULL, BP_GET, VT_I2, VT_R8},
1663     {DISPID_GLOBAL_VBCURRENCY,         NULL, BP_GET, VT_I2, VT_CY},
1664     {DISPID_GLOBAL_VBDATE,             NULL, BP_GET, VT_I2, VT_DATE},
1665     {DISPID_GLOBAL_VBSTRING,           NULL, BP_GET, VT_I2, VT_BSTR},
1666     {DISPID_GLOBAL_VBOBJECT,           NULL, BP_GET, VT_I2, VT_DISPATCH},
1667     {DISPID_GLOBAL_VBERROR,            NULL, BP_GET, VT_I2, VT_ERROR},
1668     {DISPID_GLOBAL_VBBOOLEAN,          NULL, BP_GET, VT_I2, VT_BOOL},
1669     {DISPID_GLOBAL_VBVARIANT,          NULL, BP_GET, VT_I2, VT_VARIANT},
1670     {DISPID_GLOBAL_VBDATAOBJECT,       NULL, BP_GET, VT_I2, VT_UNKNOWN},
1671     {DISPID_GLOBAL_VBDECIMAL,          NULL, BP_GET, VT_I2, VT_DECIMAL},
1672     {DISPID_GLOBAL_VBBYTE,             NULL, BP_GET, VT_I2, VT_UI1},
1673     {DISPID_GLOBAL_VBARRAY,            NULL, BP_GET, VT_I2, VT_ARRAY},
1674     {DISPID_GLOBAL_VBTRUE,             NULL, BP_GET, VT_I2, VARIANT_TRUE},
1675     {DISPID_GLOBAL_VBFALSE,            NULL, BP_GET, VT_I2, VARIANT_FALSE},
1676     {DISPID_GLOBAL_VBUSEDEFAULT,       NULL, BP_GET, VT_I2, -2},
1677     {DISPID_GLOBAL_VBBINARYCOMPARE,    NULL, BP_GET, VT_I2, 0},
1678     {DISPID_GLOBAL_VBTEXTCOMPARE,      NULL, BP_GET, VT_I2, 1},
1679     {DISPID_GLOBAL_VBDATABASECOMPARE,  NULL, BP_GET, VT_I2, 2},
1680     {DISPID_GLOBAL_VBGENERALDATE,      NULL, BP_GET, VT_I2, 0},
1681     {DISPID_GLOBAL_VBLONGDATE,         NULL, BP_GET, VT_I2, 1},
1682     {DISPID_GLOBAL_VBSHORTDATE,        NULL, BP_GET, VT_I2, 2},
1683     {DISPID_GLOBAL_VBLONGTIME,         NULL, BP_GET, VT_I2, 3},
1684     {DISPID_GLOBAL_VBSHORTTIME,        NULL, BP_GET, VT_I2, 4},
1685     {DISPID_GLOBAL_VBOBJECTERROR,      NULL, BP_GET, VT_I4, 0x80040000},
1686     {DISPID_GLOBAL_VBBLACK,            NULL, BP_GET, VT_I4, 0x000000},
1687     {DISPID_GLOBAL_VBBLUE,             NULL, BP_GET, VT_I4, 0xff0000},
1688     {DISPID_GLOBAL_VBCYAN,             NULL, BP_GET, VT_I4, 0xffff00},
1689     {DISPID_GLOBAL_VBGREEN,            NULL, BP_GET, VT_I4, 0x00ff00},
1690     {DISPID_GLOBAL_VBMAGENTA,          NULL, BP_GET, VT_I4, 0xff00ff},
1691     {DISPID_GLOBAL_VBRED,              NULL, BP_GET, VT_I4, 0x0000ff},
1692     {DISPID_GLOBAL_VBWHITE,            NULL, BP_GET, VT_I4, 0xffffff},
1693     {DISPID_GLOBAL_VBYELLOW,           NULL, BP_GET, VT_I4, 0x00ffff},
1694     {DISPID_GLOBAL_VBCR,               NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCr},
1695     {DISPID_GLOBAL_VBCRLF,             NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCrLf},
1696     {DISPID_GLOBAL_VBNEWLINE,          NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNewLine},
1697     {DISPID_GLOBAL_VBFORMFEED,         NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbFormFeed},
1698     {DISPID_GLOBAL_VBLF,               NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbLf},
1699     {DISPID_GLOBAL_VBNULLCHAR,         NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullChar},
1700     {DISPID_GLOBAL_VBNULLSTRING,       NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullString},
1701     {DISPID_GLOBAL_VBTAB,              NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbTab},
1702     {DISPID_GLOBAL_VBVERTICALTAB,      NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbVerticalTab},
1703     {DISPID_GLOBAL_CCUR,                      Global_CCur, 0, 1},
1704     {DISPID_GLOBAL_CINT,                      Global_CInt, 0, 1},
1705     {DISPID_GLOBAL_CLNG,                      Global_CLng, 0, 1},
1706     {DISPID_GLOBAL_CBOOL,                     Global_CBool, 0, 1},
1707     {DISPID_GLOBAL_CBYTE,                     Global_CByte, 0, 1},
1708     {DISPID_GLOBAL_CDATE,                     Global_CDate, 0, 1},
1709     {DISPID_GLOBAL_CDBL,                      Global_CDbl, 0, 1},
1710     {DISPID_GLOBAL_CSNG,                      Global_CSng, 0, 1},
1711     {DISPID_GLOBAL_CSTR,                      Global_CStr, 0, 1},
1712     {DISPID_GLOBAL_HEX,                       Global_Hex, 0, 1},
1713     {DISPID_GLOBAL_OCT,                       Global_Oct, 0, 1},
1714     {DISPID_GLOBAL_VARTYPE,                   Global_VarType, 0, 1},
1715     {DISPID_GLOBAL_ISDATE,                    Global_IsDate, 0, 1},
1716     {DISPID_GLOBAL_ISEMPTY,                   Global_IsEmpty, 0, 1},
1717     {DISPID_GLOBAL_ISNULL,                    Global_IsNull, 0, 1},
1718     {DISPID_GLOBAL_ISNUMERIC,                 Global_IsNumeric, 0, 1},
1719     {DISPID_GLOBAL_ISARRAY,                   Global_IsArray, 0, 1},
1720     {DISPID_GLOBAL_ISOBJECT,                  Global_IsObject, 0, 1},
1721     {DISPID_GLOBAL_ATN,                       Global_Ant, 0, 1},
1722     {DISPID_GLOBAL_COS,                       Global_Cos, 0, 1},
1723     {DISPID_GLOBAL_SIN,                       Global_Sin, 0, 1},
1724     {DISPID_GLOBAL_TAN,                       Global_Tan, 0, 1},
1725     {DISPID_GLOBAL_EXP,                       Global_Exp, 0, 1},
1726     {DISPID_GLOBAL_LOG,                       Global_Log, 0, 1},
1727     {DISPID_GLOBAL_SQR,                       Global_Sqr, 0, 1},
1728     {DISPID_GLOBAL_RANDOMIZE,                 Global_Randomize, 0, 1},
1729     {DISPID_GLOBAL_RND,                       Global_Rnd, 0, 1},
1730     {DISPID_GLOBAL_TIMER,                     Global_Timer, 0, 0},
1731     {DISPID_GLOBAL_LBOUND,                    Global_LBound, 0, 1},
1732     {DISPID_GLOBAL_UBOUND,                    Global_UBound, 0, 1},
1733     {DISPID_GLOBAL_RGB,                       Global_RGB, 0, 3},
1734     {DISPID_GLOBAL_LEN,                       Global_Len, 0, 1},
1735     {DISPID_GLOBAL_LENB,                      Global_LenB, 0, 1},
1736     {DISPID_GLOBAL_LEFT,                      Global_Left, 0, 2},
1737     {DISPID_GLOBAL_LEFTB,                     Global_LeftB, 0, 2},
1738     {DISPID_GLOBAL_RIGHT,                     Global_Right, 0, 2},
1739     {DISPID_GLOBAL_RIGHTB,                    Global_RightB, 0, 2},
1740     {DISPID_GLOBAL_MID,                       Global_Mid, 0, 2, 3},
1741     {DISPID_GLOBAL_MIDB,                      Global_MidB, 0, 2, 3},
1742     {DISPID_GLOBAL_STRCOMP,                   Global_StrComp, 0, 2, 3},
1743     {DISPID_GLOBAL_LCASE,                     Global_LCase, 0, 1},
1744     {DISPID_GLOBAL_UCASE,                     Global_UCase, 0, 1},
1745     {DISPID_GLOBAL_LTRIM,                     Global_LTrim, 0, 1},
1746     {DISPID_GLOBAL_RTRIM,                     Global_RTrim, 0, 1},
1747     {DISPID_GLOBAL_TRIM,                      Global_Trim, 0, 1},
1748     {DISPID_GLOBAL_SPACE,                     Global_Space, 0, 1},
1749     {DISPID_GLOBAL_STRING,                    Global_String, 0, 0, 2},
1750     {DISPID_GLOBAL_INSTR,                     Global_InStr, 0, 2, 4},
1751     {DISPID_GLOBAL_INSTRB,                    Global_InStrB, 0, 3, 4},
1752     {DISPID_GLOBAL_ASCB,                      Global_AscB, 0, 1},
1753     {DISPID_GLOBAL_CHRB,                      Global_ChrB, 0, 1},
1754     {DISPID_GLOBAL_ASC,                       Global_Asc, 0, 1},
1755     {DISPID_GLOBAL_CHR,                       Global_Chr, 0, 1},
1756     {DISPID_GLOBAL_ASCW,                      Global_AscW, 0, 1},
1757     {DISPID_GLOBAL_CHRW,                      Global_ChrW, 0, 1},
1758     {DISPID_GLOBAL_ABS,                       Global_Abs, 0, 1},
1759     {DISPID_GLOBAL_FIX,                       Global_Fix, 0, 1},
1760     {DISPID_GLOBAL_INT,                       Global_Int, 0, 1},
1761     {DISPID_GLOBAL_SGN,                       Global_Sgn, 0, 1},
1762     {DISPID_GLOBAL_NOW,                       Global_Now, 0, 0},
1763     {DISPID_GLOBAL_DATE,                      Global_Date, 0, 0},
1764     {DISPID_GLOBAL_TIME,                      Global_Time, 0, 0},
1765     {DISPID_GLOBAL_DAY,                       Global_Day, 0, 1},
1766     {DISPID_GLOBAL_MONTH,                     Global_Month, 0, 1},
1767     {DISPID_GLOBAL_WEEKDAY,                   Global_Weekday, 0, 1, 2},
1768     {DISPID_GLOBAL_YEAR,                      Global_Year, 0, 1},
1769     {DISPID_GLOBAL_HOUR,                      Global_Hour, 0, 1},
1770     {DISPID_GLOBAL_MINUTE,                    Global_Minute, 0, 1},
1771     {DISPID_GLOBAL_SECOND,                    Global_Second, 0, 1},
1772     {DISPID_GLOBAL_DATEVALUE,                 Global_DateValue, 0, 1},
1773     {DISPID_GLOBAL_TIMEVALUE,                 Global_TimeValue, 0, 1},
1774     {DISPID_GLOBAL_DATESERIAL,                Global_DateSerial, 0, 3},
1775     {DISPID_GLOBAL_TIMESERIAL,                Global_TimeSerial, 0, 3},
1776     {DISPID_GLOBAL_INPUTBOX,                  Global_InputBox, 0, 1, 7},
1777     {DISPID_GLOBAL_MSGBOX,                    Global_MsgBox, 0, 1, 5},
1778     {DISPID_GLOBAL_CREATEOBJECT,              Global_CreateObject, 0, 1},
1779     {DISPID_GLOBAL_GETOBJECT,                 Global_GetObject, 0, 0, 2},
1780     {DISPID_GLOBAL_DATEADD,                   Global_DateAdd, 0, 3},
1781     {DISPID_GLOBAL_DATEDIFF,                  Global_DateDiff, 0, 3, 5},
1782     {DISPID_GLOBAL_DATEPART,                  Global_DatePart, 0, 2, 4},
1783     {DISPID_GLOBAL_TYPENAME,                  Global_TypeName, 0, 1},
1784     {DISPID_GLOBAL_ARRAY,                     Global_Array, 0, 1},
1785     {DISPID_GLOBAL_ERASE,                     Global_Erase, 0, 1},
1786     {DISPID_GLOBAL_FILTER,                    Global_Filter, 0, 2, 4},
1787     {DISPID_GLOBAL_JOIN,                      Global_Join, 0, 1, 2},
1788     {DISPID_GLOBAL_SPLIT,                     Global_Split, 0, 1, 4},
1789     {DISPID_GLOBAL_REPLACE,                   Global_Replace, 0, 3, 6},
1790     {DISPID_GLOBAL_STRREVERSE,                Global_StrReverse, 0, 1},
1791     {DISPID_GLOBAL_INSTRREV,                  Global_InStrRev, 0, 2, 4},
1792     {DISPID_GLOBAL_LOADPICTURE,               Global_LoadPicture, 0, 1},
1793     {DISPID_GLOBAL_SCRIPTENGINE,              Global_ScriptEngine, 0, 0},
1794     {DISPID_GLOBAL_SCRIPTENGINEMAJORVERSION,  Global_ScriptEngineMajorVersion, 0, 0},
1795     {DISPID_GLOBAL_SCRIPTENGINEMINORVERSION,  Global_ScriptEngineMinorVersion, 0, 0},
1796     {DISPID_GLOBAL_SCRIPTENGINEBUILDVERSION,  Global_ScriptEngineBuildVersion, 0, 0},
1797     {DISPID_GLOBAL_FORMATNUMBER,              Global_FormatNumber, 0, 1, 5},
1798     {DISPID_GLOBAL_FORMATCURRENCY,            Global_FormatCurrency, 0, 1, 5},
1799     {DISPID_GLOBAL_FORMATPERCENT,             Global_FormatPercent, 0, 1, 5},
1800     {DISPID_GLOBAL_FORMATDATETIME,            Global_FormatDateTime, 0, 1, 2},
1801     {DISPID_GLOBAL_WEEKDAYNAME,               Global_WeekdayName, 0, 1, 3},
1802     {DISPID_GLOBAL_MONTHNAME,                 Global_MonthName, 0, 1, 2},
1803     {DISPID_GLOBAL_ROUND,                     Global_Round, 0, 1, 2},
1804     {DISPID_GLOBAL_ESCAPE,                    Global_Escape, 0, 1},
1805     {DISPID_GLOBAL_UNESCAPE,                  Global_Unescape, 0, 1},
1806     {DISPID_GLOBAL_EVAL,                      Global_Eval, 0, 1},
1807     {DISPID_GLOBAL_EXECUTE,                   Global_Execute, 0, 1},
1808     {DISPID_GLOBAL_EXECUTEGLOBAL,             Global_ExecuteGlobal, 0, 1},
1809     {DISPID_GLOBAL_GETREF,                    Global_GetRef, 0, 1},
1810     {DISPID_GLOBAL_VBMSGBOXHELPBUTTON,     NULL, BP_GET, VT_I4, MB_HELP},
1811     {DISPID_GLOBAL_VBMSGBOXSETFOREGROUND,  NULL, BP_GET, VT_I4, MB_SETFOREGROUND},
1812     {DISPID_GLOBAL_VBMSGBOXRIGHT,          NULL, BP_GET, VT_I4, MB_RIGHT},
1813     {DISPID_GLOBAL_VBMSGBOXRTLREADING,     NULL, BP_GET, VT_I4, MB_RTLREADING}
1814 };
1815
1816 HRESULT init_global(script_ctx_t *ctx)
1817 {
1818     HRESULT hres;
1819
1820     ctx->global_desc.ctx = ctx;
1821     ctx->global_desc.builtin_prop_cnt = sizeof(global_props)/sizeof(*global_props);
1822     ctx->global_desc.builtin_props = global_props;
1823
1824     hres = get_typeinfo(GlobalObj_tid, &ctx->global_desc.typeinfo);
1825     if(FAILED(hres))
1826         return hres;
1827
1828     hres = create_vbdisp(&ctx->global_desc, &ctx->global_obj);
1829     if(FAILED(hres))
1830         return hres;
1831
1832     hres = create_script_disp(ctx, &ctx->script_obj);
1833     if(FAILED(hres))
1834         return hres;
1835
1836     return init_err(ctx);
1837 }