1 /*
2 * Copyright 2011 Jacek Caban for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include <assert.h>
20 #include <math.h>
21
22 #include "vbscript.h"
23 #include "vbscript_defs.h"
24
25 #include "mshtmhst.h"
26 #include "objsafe.h"
27
28 #include "wine/debug.h"
29
30 #ifdef __REACTOS__
31 #include <wingdi.h>
32 #include <winnls.h>
33 #endif
34
35 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
36
37 #define VB_E_CANNOT_CREATE_OBJ 0x800a01ad
38 #define VB_E_MK_PARSE_ERROR 0x800a01b0
39
40 /* Defined as extern in urlmon.idl, but not exported by uuid.lib */
41 const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY =
42 {0x10200490,0xfa38,0x11d0,{0xac,0x0e,0x00,0xa0,0xc9,0xf,0xff,0xc0}};
43
44 static const WCHAR emptyW[] = {0};
45 static const WCHAR vbscriptW[] = {'V','B','S','c','r','i','p','t',0};
46
47 #define BP_GET 1
48 #define BP_GETPUT 2
49
50 typedef struct {
51 UINT16 len;
52 WCHAR buf[7];
53 } string_constant_t;
54
55 struct _builtin_prop_t {
56 const WCHAR *name;
57 HRESULT (*proc)(BuiltinDisp*,VARIANT*,unsigned,VARIANT*);
58 DWORD flags;
59 unsigned min_args;
60 UINT_PTR max_args;
61 };
62
impl_from_IDispatch(IDispatch * iface)63 static inline BuiltinDisp *impl_from_IDispatch(IDispatch *iface)
64 {
65 return CONTAINING_RECORD(iface, BuiltinDisp, IDispatch_iface);
66 }
67
Builtin_QueryInterface(IDispatch * iface,REFIID riid,void ** ppv)68 static HRESULT WINAPI Builtin_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
69 {
70 BuiltinDisp *This = impl_from_IDispatch(iface);
71
72 if(IsEqualGUID(&IID_IUnknown, riid)) {
73 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
74 *ppv = &This->IDispatch_iface;
75 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
76 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
77 *ppv = &This->IDispatch_iface;
78 }else {
79 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
80 *ppv = NULL;
81 return E_NOINTERFACE;
82 }
83
84 IUnknown_AddRef((IUnknown*)*ppv);
85 return S_OK;
86 }
87
Builtin_AddRef(IDispatch * iface)88 static ULONG WINAPI Builtin_AddRef(IDispatch *iface)
89 {
90 BuiltinDisp *This = impl_from_IDispatch(iface);
91 LONG ref = InterlockedIncrement(&This->ref);
92
93 TRACE("(%p) ref=%d\n", This, ref);
94
95 return ref;
96 }
97
Builtin_Release(IDispatch * iface)98 static ULONG WINAPI Builtin_Release(IDispatch *iface)
99 {
100 BuiltinDisp *This = impl_from_IDispatch(iface);
101 LONG ref = InterlockedDecrement(&This->ref);
102
103 TRACE("(%p) ref=%d\n", This, ref);
104
105 if(!ref) {
106 assert(!This->ctx);
107 heap_free(This);
108 }
109
110 return ref;
111 }
112
Builtin_GetTypeInfoCount(IDispatch * iface,UINT * pctinfo)113 static HRESULT WINAPI Builtin_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
114 {
115 BuiltinDisp *This = impl_from_IDispatch(iface);
116 TRACE("(%p)->(%p)\n", This, pctinfo);
117 *pctinfo = 0;
118 return S_OK;
119 }
120
Builtin_GetTypeInfo(IDispatch * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)121 static HRESULT WINAPI Builtin_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
122 {
123 BuiltinDisp *This = impl_from_IDispatch(iface);
124 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
125 return DISP_E_BADINDEX;
126 }
127
get_builtin_id(BuiltinDisp * disp,const WCHAR * name,DISPID * id)128 HRESULT get_builtin_id(BuiltinDisp *disp, const WCHAR *name, DISPID *id)
129 {
130 size_t min = 1, max = disp->member_cnt - 1, i;
131 int r;
132
133 while(min <= max) {
134 i = (min + max) / 2;
135 r = wcsicmp(disp->members[i].name, name);
136 if(!r) {
137 *id = i;
138 return S_OK;
139 }
140 if(r < 0)
141 min = i+1;
142 else
143 max = i-1;
144 }
145
146 return DISP_E_MEMBERNOTFOUND;
147
148 }
149
Builtin_GetIDsOfNames(IDispatch * iface,REFIID riid,LPOLESTR * names,UINT name_cnt,LCID lcid,DISPID * ids)150 static HRESULT WINAPI Builtin_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *names, UINT name_cnt,
151 LCID lcid, DISPID *ids)
152 {
153 BuiltinDisp *This = impl_from_IDispatch(iface);
154 unsigned i;
155 HRESULT hres;
156
157 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), names, name_cnt, lcid, ids);
158
159 if(!This->ctx) {
160 FIXME("NULL context\n");
161 return E_UNEXPECTED;
162 }
163
164 for(i = 0; i < name_cnt; i++) {
165 hres = get_builtin_id(This, names[i], &ids[i]);
166 if(FAILED(hres))
167 return hres;
168 }
169
170 return S_OK;
171 }
172
Builtin_Invoke(IDispatch * iface,DISPID id,REFIID riid,LCID lcid,WORD flags,DISPPARAMS * dp,VARIANT * res,EXCEPINFO * ei,UINT * err)173 static HRESULT WINAPI Builtin_Invoke(IDispatch *iface, DISPID id, REFIID riid, LCID lcid, WORD flags,
174 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, UINT *err)
175 {
176 BuiltinDisp *This = impl_from_IDispatch(iface);
177 const builtin_prop_t *prop;
178 VARIANT args[8];
179 unsigned argn, i;
180
181 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, id, debugstr_guid(riid), lcid, flags, dp, res, ei, err);
182
183 if(!This->ctx) {
184 FIXME("NULL context\n");
185 return E_UNEXPECTED;
186 }
187
188 if(id >= This->member_cnt || (!This->members[id].proc && !This->members[id].flags))
189 return DISP_E_MEMBERNOTFOUND;
190 prop = This->members + id;
191
192 switch(flags) {
193 case DISPATCH_PROPERTYGET:
194 if(!(prop->flags & (BP_GET|BP_GETPUT))) {
195 FIXME("property does not support DISPATCH_PROPERTYGET\n");
196 return E_FAIL;
197 }
198 break;
199 case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
200 if(!prop->proc && prop->flags == BP_GET) {
201 const int vt = prop->min_args, val = prop->max_args;
202 switch(vt) {
203 case VT_I2:
204 V_VT(res) = VT_I2;
205 V_I2(res) = val;
206 break;
207 case VT_I4:
208 V_VT(res) = VT_I4;
209 V_I4(res) = val;
210 break;
211 case VT_BSTR: {
212 const string_constant_t *str = (const string_constant_t*)prop->max_args;
213 BSTR ret;
214
215 ret = SysAllocStringLen(str->buf, str->len);
216 if(!ret)
217 return E_OUTOFMEMORY;
218
219 V_VT(res) = VT_BSTR;
220 V_BSTR(res) = ret;
221 break;
222 }
223 DEFAULT_UNREACHABLE;
224 }
225 return S_OK;
226 }
227 break;
228 case DISPATCH_METHOD:
229 if(prop->flags & (BP_GET|BP_GETPUT)) {
230 FIXME("Call on property\n");
231 return E_FAIL;
232 }
233 break;
234 case DISPATCH_PROPERTYPUT:
235 if(!(prop->flags & BP_GETPUT)) {
236 FIXME("property does not support DISPATCH_PROPERTYPUT\n");
237 return E_FAIL;
238 }
239
240 FIXME("call put\n");
241 return E_NOTIMPL;
242 default:
243 FIXME("unsupported flags %x\n", flags);
244 return E_NOTIMPL;
245 }
246
247 argn = arg_cnt(dp);
248
249 if(argn < prop->min_args || argn > (prop->max_args ? prop->max_args : prop->min_args)) {
250 WARN("invalid number of arguments\n");
251 return MAKE_VBSERROR(VBSE_FUNC_ARITY_MISMATCH);
252 }
253
254 assert(argn < ARRAY_SIZE(args));
255
256 for(i=0; i < argn; i++) {
257 if(V_VT(dp->rgvarg+dp->cArgs-i-1) == (VT_BYREF|VT_VARIANT))
258 args[i] = *V_VARIANTREF(dp->rgvarg+dp->cArgs-i-1);
259 else
260 args[i] = dp->rgvarg[dp->cArgs-i-1];
261 }
262
263 return prop->proc(This, args, dp->cArgs, res);
264 }
265
266 static const IDispatchVtbl BuiltinDispVtbl = {
267 Builtin_QueryInterface,
268 Builtin_AddRef,
269 Builtin_Release,
270 Builtin_GetTypeInfoCount,
271 Builtin_GetTypeInfo,
272 Builtin_GetIDsOfNames,
273 Builtin_Invoke
274 };
275
create_builtin_dispatch(script_ctx_t * ctx,const builtin_prop_t * members,size_t member_cnt,BuiltinDisp ** ret)276 static HRESULT create_builtin_dispatch(script_ctx_t *ctx, const builtin_prop_t *members, size_t member_cnt, BuiltinDisp **ret)
277 {
278 BuiltinDisp *disp;
279
280 if(!(disp = heap_alloc(sizeof(*disp))))
281 return E_OUTOFMEMORY;
282
283 disp->IDispatch_iface.lpVtbl = &BuiltinDispVtbl;
284 disp->ref = 1;
285 disp->members = members;
286 disp->member_cnt = member_cnt;
287 disp->ctx = ctx;
288
289 *ret = disp;
290 return S_OK;
291 }
292
get_sec_mgr(script_ctx_t * ctx)293 static IInternetHostSecurityManager *get_sec_mgr(script_ctx_t *ctx)
294 {
295 IInternetHostSecurityManager *secmgr;
296 IServiceProvider *sp;
297 HRESULT hres;
298
299 if(!ctx->site)
300 return NULL;
301
302 if(ctx->secmgr)
303 return ctx->secmgr;
304
305 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp);
306 if(FAILED(hres))
307 return NULL;
308
309 hres = IServiceProvider_QueryService(sp, &SID_SInternetHostSecurityManager, &IID_IInternetHostSecurityManager,
310 (void**)&secmgr);
311 IServiceProvider_Release(sp);
312 if(FAILED(hres))
313 return NULL;
314
315 return ctx->secmgr = secmgr;
316 }
317
return_string(VARIANT * res,const WCHAR * str)318 static HRESULT return_string(VARIANT *res, const WCHAR *str)
319 {
320 BSTR ret;
321
322 if(!res)
323 return S_OK;
324
325 ret = SysAllocString(str);
326 if(!ret)
327 return E_OUTOFMEMORY;
328
329 V_VT(res) = VT_BSTR;
330 V_BSTR(res) = ret;
331 return S_OK;
332 }
333
return_bstr(VARIANT * res,BSTR str)334 static HRESULT return_bstr(VARIANT *res, BSTR str)
335 {
336 if(res) {
337 V_VT(res) = VT_BSTR;
338 V_BSTR(res) = str;
339 }else {
340 SysFreeString(str);
341 }
342 return S_OK;
343 }
344
return_bool(VARIANT * res,BOOL val)345 static HRESULT return_bool(VARIANT *res, BOOL val)
346 {
347 if(res) {
348 V_VT(res) = VT_BOOL;
349 V_BOOL(res) = val ? VARIANT_TRUE : VARIANT_FALSE;
350 }
351 return S_OK;
352 }
353
return_short(VARIANT * res,short val)354 static HRESULT return_short(VARIANT *res, short val)
355 {
356 if(res) {
357 V_VT(res) = VT_I2;
358 V_I2(res) = val;
359 }
360
361 return S_OK;
362 }
363
return_int(VARIANT * res,int val)364 static HRESULT return_int(VARIANT *res, int val)
365 {
366 if(res) {
367 V_VT(res) = VT_I4;
368 V_I4(res) = val;
369 }
370
371 return S_OK;
372 }
373
return_double(VARIANT * res,double val)374 static inline HRESULT return_double(VARIANT *res, double val)
375 {
376 if(res) {
377 V_VT(res) = VT_R8;
378 V_R8(res) = val;
379 }
380
381 return S_OK;
382 }
383
return_float(VARIANT * res,float val)384 static inline HRESULT return_float(VARIANT *res, float val)
385 {
386 if(res) {
387 V_VT(res) = VT_R4;
388 V_R4(res) = val;
389 }
390
391 return S_OK;
392 }
393
return_null(VARIANT * res)394 static inline HRESULT return_null(VARIANT *res)
395 {
396 if(res)
397 V_VT(res) = VT_NULL;
398 return S_OK;
399 }
400
return_date(VARIANT * res,double date)401 static inline HRESULT return_date(VARIANT *res, double date)
402 {
403 if(res) {
404 V_VT(res) = VT_DATE;
405 V_DATE(res) = date;
406 }
407 return S_OK;
408 }
409
to_int(VARIANT * v,int * ret)410 HRESULT to_int(VARIANT *v, int *ret)
411 {
412 VARIANT r;
413 HRESULT hres;
414
415 V_VT(&r) = VT_EMPTY;
416 hres = VariantChangeType(&r, v, 0, VT_I4);
417 if(FAILED(hres))
418 return hres;
419
420 *ret = V_I4(&r);
421 return S_OK;
422 }
423
to_double(VARIANT * v,double * ret)424 static HRESULT to_double(VARIANT *v, double *ret)
425 {
426 VARIANT dst;
427 HRESULT hres;
428
429 V_VT(&dst) = VT_EMPTY;
430 hres = VariantChangeType(&dst, v, 0, VT_R8);
431 if(FAILED(hres))
432 return hres;
433
434 *ret = V_R8(&dst);
435 return S_OK;
436 }
437
to_string(VARIANT * v,BSTR * ret)438 static HRESULT to_string(VARIANT *v, BSTR *ret)
439 {
440 VARIANT dst;
441 HRESULT hres;
442
443 V_VT(&dst) = VT_EMPTY;
444 hres = VariantChangeType(&dst, v, VARIANT_LOCALBOOL, VT_BSTR);
445 if(FAILED(hres))
446 return hres;
447
448 *ret = V_BSTR(&dst);
449 return S_OK;
450 }
451
to_system_time(VARIANT * v,SYSTEMTIME * st)452 static HRESULT to_system_time(VARIANT *v, SYSTEMTIME *st)
453 {
454 VARIANT date;
455 HRESULT hres;
456
457 V_VT(&date) = VT_EMPTY;
458 hres = VariantChangeType(&date, v, 0, VT_DATE);
459 if(FAILED(hres))
460 return hres;
461
462 return VariantTimeToSystemTime(V_DATE(&date), st);
463 }
464
set_object_site(script_ctx_t * ctx,IUnknown * obj)465 static HRESULT set_object_site(script_ctx_t *ctx, IUnknown *obj)
466 {
467 IObjectWithSite *obj_site;
468 IUnknown *ax_site;
469 HRESULT hres;
470
471 hres = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (void**)&obj_site);
472 if(FAILED(hres))
473 return S_OK;
474
475 ax_site = create_ax_site(ctx);
476 if(ax_site) {
477 hres = IObjectWithSite_SetSite(obj_site, ax_site);
478 IUnknown_Release(ax_site);
479 }
480 else
481 hres = E_OUTOFMEMORY;
482 IObjectWithSite_Release(obj_site);
483 return hres;
484 }
485
create_object(script_ctx_t * ctx,const WCHAR * progid)486 static IUnknown *create_object(script_ctx_t *ctx, const WCHAR *progid)
487 {
488 IInternetHostSecurityManager *secmgr = NULL;
489 struct CONFIRMSAFETY cs;
490 IClassFactoryEx *cfex;
491 IClassFactory *cf;
492 DWORD policy_size;
493 BYTE *bpolicy;
494 IUnknown *obj;
495 DWORD policy;
496 GUID guid;
497 HRESULT hres;
498
499 hres = CLSIDFromProgID(progid, &guid);
500 if(FAILED(hres))
501 return NULL;
502
503 TRACE("GUID %s\n", debugstr_guid(&guid));
504
505 if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
506 secmgr = get_sec_mgr(ctx);
507 if(!secmgr)
508 return NULL;
509
510 policy = 0;
511 hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN,
512 (BYTE*)&policy, sizeof(policy), (BYTE*)&guid, sizeof(GUID), 0, 0);
513 if(FAILED(hres) || policy != URLPOLICY_ALLOW)
514 return NULL;
515 }
516
517 hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
518 if(FAILED(hres))
519 return NULL;
520
521 hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
522 if(SUCCEEDED(hres)) {
523 FIXME("Use IClassFactoryEx\n");
524 IClassFactoryEx_Release(cfex);
525 }
526
527 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
528 if(FAILED(hres))
529 return NULL;
530
531 if(secmgr) {
532 cs.clsid = guid;
533 cs.pUnk = obj;
534 cs.dwFlags = 0;
535 hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
536 &bpolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
537 if(SUCCEEDED(hres)) {
538 policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW;
539 CoTaskMemFree(bpolicy);
540 }
541
542 if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
543 IUnknown_Release(obj);
544 return NULL;
545 }
546 }
547
548 hres = set_object_site(ctx, obj);
549 if(FAILED(hres)) {
550 IUnknown_Release(obj);
551 return NULL;
552 }
553
554 return obj;
555 }
556
show_msgbox(script_ctx_t * ctx,BSTR prompt,unsigned type,BSTR orig_title,VARIANT * res)557 static HRESULT show_msgbox(script_ctx_t *ctx, BSTR prompt, unsigned type, BSTR orig_title, VARIANT *res)
558 {
559 SCRIPTUICHANDLING uic_handling = SCRIPTUICHANDLING_ALLOW;
560 IActiveScriptSiteUIControl *ui_control;
561 IActiveScriptSiteWindow *acts_window;
562 WCHAR *title_buf = NULL;
563 const WCHAR *title;
564 HWND hwnd = NULL;
565 int ret = 0;
566 HRESULT hres;
567
568 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteUIControl, (void**)&ui_control);
569 if(SUCCEEDED(hres)) {
570 hres = IActiveScriptSiteUIControl_GetUIBehavior(ui_control, SCRIPTUICITEM_MSGBOX, &uic_handling);
571 IActiveScriptSiteUIControl_Release(ui_control);
572 if(FAILED(hres))
573 uic_handling = SCRIPTUICHANDLING_ALLOW;
574 }
575
576 switch(uic_handling) {
577 case SCRIPTUICHANDLING_ALLOW:
578 break;
579 case SCRIPTUICHANDLING_NOUIDEFAULT:
580 return return_short(res, 0);
581 default:
582 FIXME("blocked\n");
583 return E_FAIL;
584 }
585
586 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IActiveScriptSiteWindow, (void**)&acts_window);
587 if(FAILED(hres)) {
588 FIXME("No IActiveScriptSiteWindow\n");
589 return hres;
590 }
591
592 if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
593 if(orig_title && *orig_title) {
594 WCHAR *ptr;
595
596 title = title_buf = heap_alloc(sizeof(vbscriptW) + (lstrlenW(orig_title)+2)*sizeof(WCHAR));
597 if(!title)
598 return E_OUTOFMEMORY;
599
600 memcpy(title_buf, vbscriptW, sizeof(vbscriptW));
601 ptr = title_buf + ARRAY_SIZE(vbscriptW)-1;
602
603 *ptr++ = ':';
604 *ptr++ = ' ';
605 lstrcpyW(ptr, orig_title);
606 }else {
607 title = vbscriptW;
608 }
609 }else {
610 title = orig_title ? orig_title : emptyW;
611 }
612
613 hres = IActiveScriptSiteWindow_GetWindow(acts_window, &hwnd);
614 if(SUCCEEDED(hres)) {
615 hres = IActiveScriptSiteWindow_EnableModeless(acts_window, FALSE);
616 if(SUCCEEDED(hres)) {
617 ret = MessageBoxW(hwnd, prompt, title, type);
618 hres = IActiveScriptSiteWindow_EnableModeless(acts_window, TRUE);
619 }
620 }
621
622 heap_free(title_buf);
623 IActiveScriptSiteWindow_Release(acts_window);
624 if(FAILED(hres)) {
625 FIXME("failed: %08x\n", hres);
626 return hres;
627 }
628
629 return return_short(res, ret);
630 }
631
Global_CCur(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)632 static HRESULT Global_CCur(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
633 {
634 VARIANT v;
635 HRESULT hres;
636
637 TRACE("%s\n", debugstr_variant(arg));
638
639 assert(args_cnt == 1);
640
641 V_VT(&v) = VT_EMPTY;
642 hres = VariantChangeType(&v, arg, 0, VT_CY);
643 if(FAILED(hres))
644 return hres;
645
646 if(!res) {
647 VariantClear(&v);
648 return DISP_E_BADVARTYPE;
649 }
650
651 *res = v;
652 return S_OK;
653 }
654
Global_CInt(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)655 static HRESULT Global_CInt(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
656 {
657 VARIANT v;
658 HRESULT hres;
659
660 TRACE("%s\n", debugstr_variant(arg));
661
662 assert(args_cnt == 1);
663
664 V_VT(&v) = VT_EMPTY;
665 hres = VariantChangeType(&v, arg, 0, VT_I2);
666 if(FAILED(hres))
667 return hres;
668
669 if(!res)
670 return DISP_E_BADVARTYPE;
671 else {
672 *res = v;
673 return S_OK;
674 }
675 }
676
Global_CLng(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)677 static HRESULT Global_CLng(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
678 {
679 int i;
680 HRESULT hres;
681
682 TRACE("%s\n", debugstr_variant(arg));
683
684 assert(args_cnt == 1);
685
686 hres = to_int(arg, &i);
687 if(FAILED(hres))
688 return hres;
689 if(!res)
690 return DISP_E_BADVARTYPE;
691
692 return return_int(res, i);
693 }
694
Global_CBool(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)695 static HRESULT Global_CBool(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
696 {
697 VARIANT v;
698 HRESULT hres;
699
700 TRACE("%s\n", debugstr_variant(arg));
701
702 assert(args_cnt == 1);
703
704 V_VT(&v) = VT_EMPTY;
705 hres = VariantChangeType(&v, arg, VARIANT_LOCALBOOL, VT_BOOL);
706 if(FAILED(hres))
707 return hres;
708
709 if(res)
710 *res = v;
711 else
712 VariantClear(&v);
713 return S_OK;
714 }
715
Global_CByte(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)716 static HRESULT Global_CByte(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
717 {
718 VARIANT v;
719 HRESULT hres;
720
721 TRACE("%s\n", debugstr_variant(arg));
722
723 assert(args_cnt == 1);
724
725 V_VT(&v) = VT_EMPTY;
726 hres = VariantChangeType(&v, arg, VARIANT_LOCALBOOL, VT_UI1);
727 if(FAILED(hres))
728 return hres;
729
730 if(!res) {
731 VariantClear(&v);
732 return DISP_E_BADVARTYPE;
733 }
734
735 *res = v;
736 return S_OK;
737 }
738
Global_CDate(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)739 static HRESULT Global_CDate(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
740 {
741 FIXME("\n");
742 return E_NOTIMPL;
743 }
744
Global_CDbl(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)745 static HRESULT Global_CDbl(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
746 {
747 VARIANT v;
748 HRESULT hres;
749
750 TRACE("%s\n", debugstr_variant(arg));
751
752 assert(args_cnt == 1);
753
754 V_VT(&v) = VT_EMPTY;
755 hres = VariantChangeType(&v, arg, 0, VT_R8);
756 if(FAILED(hres))
757 return hres;
758
759 if(!res)
760 return DISP_E_BADVARTYPE;
761 else {
762 *res = v;
763 return S_OK;
764 }
765 }
766
Global_CSng(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)767 static HRESULT Global_CSng(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
768 {
769 VARIANT v;
770 HRESULT hres;
771
772 TRACE("%s\n", debugstr_variant(arg));
773
774 assert(args_cnt == 1);
775
776 V_VT(&v) = VT_EMPTY;
777 hres = VariantChangeType(&v, arg, 0, VT_R4);
778 if(FAILED(hres))
779 return hres;
780
781 if(!res)
782 return DISP_E_BADVARTYPE;
783
784 *res = v;
785 return S_OK;
786 }
787
Global_CStr(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)788 static HRESULT Global_CStr(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
789 {
790 BSTR str;
791 HRESULT hres;
792
793 TRACE("%s\n", debugstr_variant(arg));
794
795 if(V_VT(arg) == VT_NULL)
796 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
797
798 hres = to_string(arg, &str);
799 if(FAILED(hres))
800 return hres;
801
802 return return_bstr(res, str);
803 }
804
hex_char(unsigned n)805 static inline WCHAR hex_char(unsigned n)
806 {
807 return n < 10 ? '0'+n : 'A'+n-10;
808 }
809
Global_Hex(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)810 static HRESULT Global_Hex(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
811 {
812 WCHAR buf[17], *ptr;
813 DWORD n;
814 HRESULT hres;
815 int ret;
816
817 TRACE("%s\n", debugstr_variant(arg));
818
819 switch(V_VT(arg)) {
820 case VT_I2:
821 n = (WORD)V_I2(arg);
822 break;
823 case VT_NULL:
824 if(res)
825 V_VT(res) = VT_NULL;
826 return S_OK;
827 default:
828 hres = to_int(arg, &ret);
829 if(FAILED(hres))
830 return hres;
831 else
832 n = ret;
833 }
834
835 buf[16] = 0;
836 ptr = buf+15;
837
838 if(n) {
839 do {
840 *ptr-- = hex_char(n & 0xf);
841 n >>= 4;
842 }while(n);
843 ptr++;
844 }else {
845 *ptr = '0';
846 }
847
848 return return_string(res, ptr);
849 }
850
Global_Oct(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)851 static HRESULT Global_Oct(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
852 {
853 HRESULT hres;
854 WCHAR buf[23], *ptr;
855 DWORD n;
856 int ret;
857
858 TRACE("%s\n", debugstr_variant(arg));
859
860 switch(V_VT(arg)) {
861 case VT_I2:
862 n = (WORD)V_I2(arg);
863 break;
864 case VT_NULL:
865 if(res)
866 V_VT(res) = VT_NULL;
867 return S_OK;
868 default:
869 hres = to_int(arg, &ret);
870 if(FAILED(hres))
871 return hres;
872 else
873 n = ret;
874 }
875
876 buf[22] = 0;
877 ptr = buf + 21;
878
879 if(n) {
880 do {
881 *ptr-- = '0' + (n & 0x7);
882 n >>= 3;
883 }while(n);
884 ptr++;
885 }else {
886 *ptr = '0';
887 }
888
889 return return_string(res, ptr);
890 }
891
Global_VarType(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)892 static HRESULT Global_VarType(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
893 {
894 VARTYPE vt;
895
896 TRACE("(%s)\n", debugstr_variant(arg));
897
898 assert(args_cnt == 1);
899
900 vt = V_VT(arg) & ~VT_BYREF;
901 if(vt & ~(VT_TYPEMASK | VT_ARRAY)) {
902 FIXME("not supported %s\n", debugstr_variant(arg));
903 return E_NOTIMPL;
904 }
905
906 return return_short(res, vt);
907 }
908
Global_IsDate(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)909 static HRESULT Global_IsDate(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
910 {
911 FIXME("\n");
912 return E_NOTIMPL;
913 }
914
Global_IsEmpty(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)915 static HRESULT Global_IsEmpty(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
916 {
917 TRACE("(%s)\n", debugstr_variant(arg));
918
919 assert(args_cnt == 1);
920
921 if(res) {
922 V_VT(res) = VT_BOOL;
923 V_BOOL(res) = V_VT(arg) == VT_EMPTY ? VARIANT_TRUE : VARIANT_FALSE;
924 }
925 return S_OK;
926 }
927
Global_IsNull(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)928 static HRESULT Global_IsNull(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
929 {
930 TRACE("(%s)\n", debugstr_variant(arg));
931
932 assert(args_cnt == 1);
933
934 if(res) {
935 V_VT(res) = VT_BOOL;
936 V_BOOL(res) = V_VT(arg) == VT_NULL ? VARIANT_TRUE : VARIANT_FALSE;
937 }
938 return S_OK;
939 }
940
Global_IsNumeric(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)941 static HRESULT Global_IsNumeric(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
942 {
943 HRESULT hres;
944 double d;
945
946 TRACE("(%s)\n", debugstr_variant(arg));
947
948 assert(args_cnt == 1);
949
950 hres = to_double(arg, &d);
951
952 return return_bool(res, SUCCEEDED(hres));
953 }
954
Global_IsArray(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)955 static HRESULT Global_IsArray(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
956 {
957 FIXME("\n");
958 return E_NOTIMPL;
959 }
960
Global_IsObject(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)961 static HRESULT Global_IsObject(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
962 {
963 TRACE("(%s)\n", debugstr_variant(arg));
964
965 assert(args_cnt == 1);
966
967 if(res) {
968 V_VT(res) = VT_BOOL;
969 V_BOOL(res) = V_VT(arg) == VT_DISPATCH ? VARIANT_TRUE : VARIANT_FALSE;
970 }
971 return S_OK;
972 }
973
Global_Atn(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)974 static HRESULT Global_Atn(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
975 {
976 HRESULT hres;
977 double d;
978
979 hres = to_double(arg, &d);
980 if(FAILED(hres))
981 return hres;
982
983 return return_double(res, atan(d));
984 }
985
Global_Cos(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)986 static HRESULT Global_Cos(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
987 {
988 HRESULT hres;
989 double d;
990
991 hres = to_double(arg, &d);
992 if(FAILED(hres))
993 return hres;
994
995 return return_double(res, cos(d));
996 }
997
Global_Sin(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)998 static HRESULT Global_Sin(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
999 {
1000 HRESULT hres;
1001 double d;
1002
1003 hres = to_double(arg, &d);
1004 if(FAILED(hres))
1005 return hres;
1006
1007 return return_double(res, sin(d));
1008 }
1009
Global_Tan(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1010 static HRESULT Global_Tan(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1011 {
1012 HRESULT hres;
1013 double d;
1014
1015 hres = to_double(arg, &d);
1016 if(FAILED(hres))
1017 return hres;
1018
1019 return return_double(res, tan(d));
1020 }
1021
Global_Exp(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1022 static HRESULT Global_Exp(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1023 {
1024 HRESULT hres;
1025 double d;
1026
1027 hres = to_double(arg, &d);
1028 if(FAILED(hres))
1029 return hres;
1030
1031 return return_double(res, exp(d));
1032 }
1033
Global_Log(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1034 static HRESULT Global_Log(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1035 {
1036 HRESULT hres;
1037 double d;
1038
1039 hres = to_double(arg, &d);
1040 if(FAILED(hres))
1041 return hres;
1042
1043 if(d <= 0)
1044 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1045 else
1046 return return_double(res, log(d));
1047 }
1048
Global_Sqr(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1049 static HRESULT Global_Sqr(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1050 {
1051 HRESULT hres;
1052 double d;
1053
1054 hres = to_double(arg, &d);
1055 if(FAILED(hres))
1056 return hres;
1057
1058 if(d < 0)
1059 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1060 else
1061 return return_double(res, sqrt(d));
1062 }
1063
Global_Randomize(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1064 static HRESULT Global_Randomize(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1065 {
1066 FIXME("\n");
1067 return E_NOTIMPL;
1068 }
1069
Global_Rnd(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1070 static HRESULT Global_Rnd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1071 {
1072 FIXME("\n");
1073 return E_NOTIMPL;
1074 }
1075
Global_Timer(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1076 static HRESULT Global_Timer(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1077 {
1078 SYSTEMTIME lt;
1079 double sec;
1080
1081 GetLocalTime(<);
1082 sec = lt.wHour * 3600 + lt.wMinute * 60 + lt.wSecond + lt.wMilliseconds / 1000.0;
1083 return return_float(res, sec);
1084
1085 }
1086
Global_LBound(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1087 static HRESULT Global_LBound(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1088 {
1089 FIXME("\n");
1090 return E_NOTIMPL;
1091 }
1092
Global_UBound(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1093 static HRESULT Global_UBound(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1094 {
1095 SAFEARRAY *sa;
1096 HRESULT hres;
1097 LONG ubound;
1098 int dim;
1099
1100 assert(args_cnt == 1 || args_cnt == 2);
1101
1102 TRACE("%s %s\n", debugstr_variant(arg), args_cnt == 2 ? debugstr_variant(arg + 1) : "1");
1103
1104 switch(V_VT(arg)) {
1105 case VT_VARIANT|VT_ARRAY:
1106 sa = V_ARRAY(arg);
1107 break;
1108 case VT_VARIANT|VT_ARRAY|VT_BYREF:
1109 sa = *V_ARRAYREF(arg);
1110 break;
1111 default:
1112 FIXME("arg %s not supported\n", debugstr_variant(arg));
1113 return E_NOTIMPL;
1114 }
1115
1116 if(args_cnt == 2) {
1117 hres = to_int(arg + 1, &dim);
1118 if(FAILED(hres))
1119 return hres;
1120 }else {
1121 dim = 1;
1122 }
1123
1124 hres = SafeArrayGetUBound(sa, dim, &ubound);
1125 if(FAILED(hres))
1126 return hres;
1127
1128 return return_int(res, ubound);
1129 }
1130
Global_RGB(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1131 static HRESULT Global_RGB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1132 {
1133 HRESULT hres;
1134 int i, color[3];
1135
1136 TRACE("%s %s %s\n", debugstr_variant(arg), debugstr_variant(arg + 1), debugstr_variant(arg + 2));
1137
1138 assert(args_cnt == 3);
1139
1140 for(i = 0; i < 3; i++) {
1141 hres = to_int(arg + i, color + i);
1142 if(FAILED(hres))
1143 return hres;
1144 if(color[i] > 255)
1145 color[i] = 255;
1146 if(color[i] < 0)
1147 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1148 }
1149
1150 return return_int(res, RGB(color[0], color[1], color[2]));
1151 }
1152
Global_Len(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1153 static HRESULT Global_Len(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1154 {
1155 DWORD len;
1156 HRESULT hres;
1157
1158 TRACE("%s\n", debugstr_variant(arg));
1159
1160 if(V_VT(arg) == VT_NULL)
1161 return return_null(res);
1162
1163 if(V_VT(arg) != VT_BSTR) {
1164 BSTR str;
1165
1166 hres = to_string(arg, &str);
1167 if(FAILED(hres))
1168 return hres;
1169
1170 len = SysStringLen(str);
1171 SysFreeString(str);
1172 }else {
1173 len = SysStringLen(V_BSTR(arg));
1174 }
1175
1176 return return_int(res, len);
1177 }
1178
Global_LenB(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1179 static HRESULT Global_LenB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1180 {
1181 FIXME("\n");
1182 return E_NOTIMPL;
1183 }
1184
Global_Left(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)1185 static HRESULT Global_Left(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1186 {
1187 BSTR str, ret, conv_str = NULL;
1188 int len, str_len;
1189 HRESULT hres;
1190
1191 TRACE("(%s %s)\n", debugstr_variant(args+1), debugstr_variant(args));
1192
1193 if(V_VT(args) == VT_BSTR) {
1194 str = V_BSTR(args);
1195 }else {
1196 hres = to_string(args, &conv_str);
1197 if(FAILED(hres))
1198 return hres;
1199 str = conv_str;
1200 }
1201
1202 hres = to_int(args+1, &len);
1203 if(FAILED(hres))
1204 return hres;
1205
1206 if(len < 0) {
1207 FIXME("len = %d\n", len);
1208 return E_FAIL;
1209 }
1210
1211 str_len = SysStringLen(str);
1212 if(len > str_len)
1213 len = str_len;
1214
1215 ret = SysAllocStringLen(str, len);
1216 SysFreeString(conv_str);
1217 if(!ret)
1218 return E_OUTOFMEMORY;
1219
1220 return return_bstr(res, ret);
1221 }
1222
Global_LeftB(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1223 static HRESULT Global_LeftB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1224 {
1225 FIXME("\n");
1226 return E_NOTIMPL;
1227 }
1228
Global_Right(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)1229 static HRESULT Global_Right(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1230 {
1231 BSTR str, ret, conv_str = NULL;
1232 int len, str_len;
1233 HRESULT hres;
1234
1235 TRACE("(%s %s)\n", debugstr_variant(args), debugstr_variant(args+1));
1236
1237 if(V_VT(args+1) == VT_BSTR) {
1238 str = V_BSTR(args);
1239 }else {
1240 hres = to_string(args, &conv_str);
1241 if(FAILED(hres))
1242 return hres;
1243 str = conv_str;
1244 }
1245
1246 hres = to_int(args+1, &len);
1247 if(FAILED(hres))
1248 return hres;
1249
1250 if(len < 0) {
1251 FIXME("len = %d\n", len);
1252 return E_FAIL;
1253 }
1254
1255 str_len = SysStringLen(str);
1256 if(len > str_len)
1257 len = str_len;
1258
1259 ret = SysAllocStringLen(str+str_len-len, len);
1260 SysFreeString(conv_str);
1261 if(!ret)
1262 return E_OUTOFMEMORY;
1263
1264 return return_bstr(res, ret);
1265 }
1266
Global_RightB(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1267 static HRESULT Global_RightB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1268 {
1269 FIXME("\n");
1270 return E_NOTIMPL;
1271 }
1272
Global_Mid(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)1273 static HRESULT Global_Mid(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1274 {
1275 int len = -1, start, str_len;
1276 BSTR str;
1277 HRESULT hres;
1278
1279 TRACE("(%s %s ...)\n", debugstr_variant(args), debugstr_variant(args+1));
1280
1281 assert(args_cnt == 2 || args_cnt == 3);
1282
1283 if(V_VT(args) != VT_BSTR) {
1284 FIXME("args[0] = %s\n", debugstr_variant(args));
1285 return E_NOTIMPL;
1286 }
1287
1288 str = V_BSTR(args);
1289
1290 hres = to_int(args+1, &start);
1291 if(FAILED(hres))
1292 return hres;
1293
1294 if(args_cnt == 3) {
1295 hres = to_int(args+2, &len);
1296 if(FAILED(hres))
1297 return hres;
1298
1299 if(len < 0) {
1300 FIXME("len = %d\n", len);
1301 return E_FAIL;
1302 }
1303 }
1304
1305
1306 str_len = SysStringLen(str);
1307 start--;
1308 if(start > str_len)
1309 start = str_len;
1310
1311 if(len == -1)
1312 len = str_len-start;
1313 else if(len > str_len-start)
1314 len = str_len-start;
1315
1316 if(res) {
1317 V_VT(res) = VT_BSTR;
1318 V_BSTR(res) = SysAllocStringLen(str+start, len);
1319 if(!V_BSTR(res))
1320 return E_OUTOFMEMORY;
1321 }
1322
1323 return S_OK;
1324 }
1325
Global_MidB(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1326 static HRESULT Global_MidB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1327 {
1328 FIXME("\n");
1329 return E_NOTIMPL;
1330 }
1331
Global_StrComp(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)1332 static HRESULT Global_StrComp(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1333 {
1334 BSTR left, right;
1335 int mode, ret;
1336 HRESULT hres;
1337 short val;
1338
1339 TRACE("(%s %s ...)\n", debugstr_variant(args), debugstr_variant(args+1));
1340
1341 assert(args_cnt == 2 || args_cnt == 3);
1342
1343 if (args_cnt == 3) {
1344 hres = to_int(args+2, &mode);
1345 if(FAILED(hres))
1346 return hres;
1347
1348 if (mode != 0 && mode != 1) {
1349 FIXME("unknown compare mode = %d\n", mode);
1350 return E_FAIL;
1351 }
1352 }
1353 else
1354 mode = 0;
1355
1356 hres = to_string(args, &left);
1357 if(FAILED(hres))
1358 return hres;
1359
1360 hres = to_string(args+1, &right);
1361 if(FAILED(hres))
1362 {
1363 SysFreeString(left);
1364 return hres;
1365 }
1366
1367 ret = mode ? wcsicmp(left, right) : wcscmp(left, right);
1368 val = ret < 0 ? -1 : (ret > 0 ? 1 : 0);
1369
1370 SysFreeString(left);
1371 SysFreeString(right);
1372 return return_short(res, val);
1373 }
1374
Global_LCase(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1375 static HRESULT Global_LCase(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1376 {
1377 BSTR str;
1378 HRESULT hres;
1379
1380 TRACE("%s\n", debugstr_variant(arg));
1381
1382 if(V_VT(arg) == VT_NULL) {
1383 if(res)
1384 V_VT(res) = VT_NULL;
1385 return S_OK;
1386 }
1387
1388 hres = to_string(arg, &str);
1389 if(FAILED(hres))
1390 return hres;
1391
1392 if(res) {
1393 WCHAR *ptr;
1394
1395 for(ptr = str; *ptr; ptr++)
1396 *ptr = towlower(*ptr);
1397
1398 V_VT(res) = VT_BSTR;
1399 V_BSTR(res) = str;
1400 }else {
1401 SysFreeString(str);
1402 }
1403 return S_OK;
1404 }
1405
Global_UCase(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1406 static HRESULT Global_UCase(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1407 {
1408 BSTR str;
1409 HRESULT hres;
1410
1411 TRACE("%s\n", debugstr_variant(arg));
1412
1413 if(V_VT(arg) == VT_NULL) {
1414 if(res)
1415 V_VT(res) = VT_NULL;
1416 return S_OK;
1417 }
1418
1419 hres = to_string(arg, &str);
1420 if(FAILED(hres))
1421 return hres;
1422
1423 if(res) {
1424 WCHAR *ptr;
1425
1426 for(ptr = str; *ptr; ptr++)
1427 *ptr = towupper(*ptr);
1428
1429 V_VT(res) = VT_BSTR;
1430 V_BSTR(res) = str;
1431 }else {
1432 SysFreeString(str);
1433 }
1434 return S_OK;
1435 }
1436
Global_LTrim(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1437 static HRESULT Global_LTrim(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1438 {
1439 BSTR str, conv_str = NULL;
1440 WCHAR *ptr;
1441 HRESULT hres;
1442
1443 TRACE("%s\n", debugstr_variant(arg));
1444
1445 if(V_VT(arg) == VT_BSTR) {
1446 str = V_BSTR(arg);
1447 }else {
1448 hres = to_string(arg, &conv_str);
1449 if(FAILED(hres))
1450 return hres;
1451 str = conv_str;
1452 }
1453
1454 for(ptr = str; *ptr && iswspace(*ptr); ptr++);
1455
1456 str = SysAllocString(ptr);
1457 SysFreeString(conv_str);
1458 if(!str)
1459 return E_OUTOFMEMORY;
1460
1461 return return_bstr(res, str);
1462 }
1463
Global_RTrim(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1464 static HRESULT Global_RTrim(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1465 {
1466 BSTR str, conv_str = NULL;
1467 WCHAR *ptr;
1468 HRESULT hres;
1469
1470 TRACE("%s\n", debugstr_variant(arg));
1471
1472 if(V_VT(arg) == VT_BSTR) {
1473 str = V_BSTR(arg);
1474 }else {
1475 hres = to_string(arg, &conv_str);
1476 if(FAILED(hres))
1477 return hres;
1478 str = conv_str;
1479 }
1480
1481 for(ptr = str+SysStringLen(str); ptr-1 > str && iswspace(*(ptr-1)); ptr--);
1482
1483 str = SysAllocStringLen(str, ptr-str);
1484 SysFreeString(conv_str);
1485 if(!str)
1486 return E_OUTOFMEMORY;
1487
1488 return return_bstr(res, str);
1489 }
1490
Global_Trim(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1491 static HRESULT Global_Trim(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1492 {
1493 BSTR str, conv_str = NULL;
1494 WCHAR *begin_ptr, *end_ptr;
1495 HRESULT hres;
1496
1497 TRACE("%s\n", debugstr_variant(arg));
1498
1499 if(V_VT(arg) == VT_BSTR) {
1500 str = V_BSTR(arg);
1501 }else {
1502 hres = to_string(arg, &conv_str);
1503 if(FAILED(hres))
1504 return hres;
1505 str = conv_str;
1506 }
1507
1508 for(begin_ptr = str; *begin_ptr && iswspace(*begin_ptr); begin_ptr++);
1509 for(end_ptr = str+SysStringLen(str); end_ptr-1 > begin_ptr && iswspace(*(end_ptr-1)); end_ptr--);
1510
1511 str = SysAllocStringLen(begin_ptr, end_ptr-begin_ptr);
1512 SysFreeString(conv_str);
1513 if(!str)
1514 return E_OUTOFMEMORY;
1515
1516 return return_bstr(res, str);
1517 }
1518
Global_Space(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1519 static HRESULT Global_Space(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1520 {
1521 BSTR str;
1522 int n, i;
1523 HRESULT hres;
1524
1525 TRACE("%s\n", debugstr_variant(arg));
1526
1527 hres = to_int(arg, &n);
1528 if(FAILED(hres))
1529 return hres;
1530
1531 if(n < 0) {
1532 FIXME("n = %d\n", n);
1533 return E_NOTIMPL;
1534 }
1535
1536 if(!res)
1537 return S_OK;
1538
1539 str = SysAllocStringLen(NULL, n);
1540 if(!str)
1541 return E_OUTOFMEMORY;
1542
1543 for(i=0; i<n; i++)
1544 str[i] = ' ';
1545
1546 V_VT(res) = VT_BSTR;
1547 V_BSTR(res) = str;
1548 return S_OK;
1549 }
1550
Global_String(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1551 static HRESULT Global_String(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1552 {
1553 FIXME("\n");
1554 return E_NOTIMPL;
1555 }
1556
Global_InStr(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)1557 static HRESULT Global_InStr(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1558 {
1559 VARIANT *startv, *str1v, *str2v;
1560 BSTR str1, str2;
1561 int start, ret;
1562 HRESULT hres;
1563
1564 TRACE("\n");
1565
1566 assert(2 <= args_cnt && args_cnt <= 4);
1567
1568 switch(args_cnt) {
1569 case 2:
1570 startv = NULL;
1571 str1v = args;
1572 str2v = args+1;
1573 break;
1574 case 3:
1575 startv = args;
1576 str1v = args+1;
1577 str2v = args+2;
1578 break;
1579 case 4:
1580 FIXME("unsupported compare argument %s\n", debugstr_variant(args));
1581 return E_NOTIMPL;
1582 DEFAULT_UNREACHABLE;
1583 }
1584
1585 if(startv) {
1586 hres = to_int(startv, &start);
1587 if(FAILED(hres))
1588 return hres;
1589 if(--start < 0) {
1590 FIXME("start %d\n", start);
1591 return E_FAIL;
1592 }
1593 }else {
1594 start = 0;
1595 }
1596
1597 if(V_VT(str1v) == VT_NULL || V_VT(str2v) == VT_NULL)
1598 return return_null(res);
1599
1600 if(V_VT(str1v) != VT_BSTR) {
1601 FIXME("Unsupported str1 type %s\n", debugstr_variant(str1v));
1602 return E_NOTIMPL;
1603 }
1604 str1 = V_BSTR(str1v);
1605
1606 if(V_VT(str2v) != VT_BSTR) {
1607 FIXME("Unsupported str2 type %s\n", debugstr_variant(str2v));
1608 return E_NOTIMPL;
1609 }
1610 str2 = V_BSTR(str2v);
1611
1612 if(start < SysStringLen(str1)) {
1613 WCHAR *ptr;
1614
1615 ptr = wcsstr(str1+start, str2);
1616 ret = ptr ? ptr-str1+1 : 0;
1617 }else {
1618 ret = 0;
1619 }
1620
1621 return return_int(res, ret);
1622 }
1623
Global_InStrB(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1624 static HRESULT Global_InStrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1625 {
1626 FIXME("\n");
1627 return E_NOTIMPL;
1628 }
1629
Global_AscB(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1630 static HRESULT Global_AscB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1631 {
1632 FIXME("\n");
1633 return E_NOTIMPL;
1634 }
1635
Global_ChrB(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1636 static HRESULT Global_ChrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1637 {
1638 FIXME("\n");
1639 return E_NOTIMPL;
1640 }
1641
Global_Asc(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1642 static HRESULT Global_Asc(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1643 {
1644 BSTR conv_str = NULL, str;
1645 HRESULT hres = S_OK;
1646
1647 TRACE("(%s)\n", debugstr_variant(arg));
1648
1649 switch(V_VT(arg)) {
1650 case VT_NULL:
1651 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1652 case VT_EMPTY:
1653 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1654 case VT_BSTR:
1655 str = V_BSTR(arg);
1656 break;
1657 default:
1658 hres = to_string(arg, &conv_str);
1659 if(FAILED(hres))
1660 return hres;
1661 str = conv_str;
1662 }
1663
1664 if(!SysStringLen(str) || *str >= 0x100)
1665 hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1666 else if(res)
1667 hres = return_short(res, *str);
1668 SysFreeString(conv_str);
1669 return hres;
1670 }
1671
1672 /* The function supports only single-byte and double-byte character sets. It
1673 * ignores language specified by IActiveScriptSite::GetLCID. The argument needs
1674 * to be in range of short or unsigned short. */
Global_Chr(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1675 static HRESULT Global_Chr(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1676 {
1677 int cp, c, len = 0;
1678 CPINFO cpi;
1679 WCHAR ch;
1680 char buf[2];
1681 HRESULT hres;
1682
1683 TRACE("%s\n", debugstr_variant(arg));
1684
1685 hres = to_int(arg, &c);
1686 if(FAILED(hres))
1687 return hres;
1688
1689 cp = GetACP();
1690 if(!GetCPInfo(cp, &cpi))
1691 cpi.MaxCharSize = 1;
1692
1693 if((c!=(short)c && c!=(unsigned short)c) ||
1694 (unsigned short)c>=(cpi.MaxCharSize>1 ? 0x10000 : 0x100)) {
1695 WARN("invalid arg %d\n", c);
1696 return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
1697 }
1698
1699 if(c>>8)
1700 buf[len++] = c>>8;
1701 if(!len || IsDBCSLeadByteEx(cp, buf[0]))
1702 buf[len++] = c;
1703 if(!MultiByteToWideChar(CP_ACP, 0, buf, len, &ch, 1)) {
1704 WARN("invalid arg %d, cp %d\n", c, cp);
1705 return E_FAIL;
1706 }
1707
1708 if(res) {
1709 V_VT(res) = VT_BSTR;
1710 V_BSTR(res) = SysAllocStringLen(&ch, 1);
1711 if(!V_BSTR(res))
1712 return E_OUTOFMEMORY;
1713 }
1714 return S_OK;
1715 }
1716
Global_AscW(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1717 static HRESULT Global_AscW(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1718 {
1719 FIXME("\n");
1720 return E_NOTIMPL;
1721 }
1722
Global_ChrW(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1723 static HRESULT Global_ChrW(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1724 {
1725 FIXME("\n");
1726 return E_NOTIMPL;
1727 }
1728
Global_Abs(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1729 static HRESULT Global_Abs(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1730 {
1731 HRESULT hres;
1732 VARIANT dst;
1733
1734 TRACE("(%s)\n", debugstr_variant(arg));
1735
1736 assert(args_cnt == 1);
1737
1738 hres = VarAbs(arg, &dst);
1739 if(FAILED(hres))
1740 return hres;
1741
1742 if (res)
1743 *res = dst;
1744 else
1745 VariantClear(&dst);
1746
1747 return S_OK;
1748 }
1749
Global_Fix(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1750 static HRESULT Global_Fix(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1751 {
1752 HRESULT hres;
1753 VARIANT dst;
1754
1755 TRACE("(%s)\n", debugstr_variant(arg));
1756
1757 assert(args_cnt == 1);
1758
1759 hres = VarFix(arg, &dst);
1760 if(FAILED(hres))
1761 return hres;
1762
1763 if (res)
1764 *res = dst;
1765 else
1766 VariantClear(&dst);
1767
1768 return S_OK;
1769 }
1770
Global_Int(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1771 static HRESULT Global_Int(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1772 {
1773 HRESULT hres;
1774 VARIANT dst;
1775
1776 TRACE("(%s)\n", debugstr_variant(arg));
1777
1778 assert(args_cnt == 1);
1779
1780 hres = VarInt(arg, &dst);
1781 if(FAILED(hres))
1782 return hres;
1783
1784 if (res)
1785 *res = dst;
1786 else
1787 VariantClear(&dst);
1788
1789 return S_OK;
1790 }
1791
Global_Sgn(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1792 static HRESULT Global_Sgn(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1793 {
1794 double v;
1795 short val;
1796 HRESULT hres;
1797
1798 TRACE("(%s)\n", debugstr_variant(arg));
1799
1800 assert(args_cnt == 1);
1801
1802 if(V_VT(arg) == VT_NULL)
1803 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
1804
1805 hres = to_double(arg, &v);
1806 if (FAILED(hres))
1807 return hres;
1808
1809 val = v == 0 ? 0 : (v > 0 ? 1 : -1);
1810 return return_short(res, val);
1811 }
1812
Global_Now(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1813 static HRESULT Global_Now(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1814 {
1815 SYSTEMTIME lt;
1816 double date;
1817
1818 TRACE("\n");
1819
1820 GetLocalTime(<);
1821 SystemTimeToVariantTime(<, &date);
1822 return return_date(res, date);
1823 }
1824
Global_Date(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1825 static HRESULT Global_Date(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1826 {
1827 SYSTEMTIME lt;
1828 UDATE ud;
1829 DATE date;
1830 HRESULT hres;
1831
1832 TRACE("\n");
1833
1834 GetLocalTime(<);
1835 ud.st = lt;
1836 ud.wDayOfYear = 0;
1837 hres = VarDateFromUdateEx(&ud, 0, VAR_DATEVALUEONLY, &date);
1838 if(FAILED(hres))
1839 return hres;
1840 return return_date(res, date);
1841 }
1842
Global_Time(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1843 static HRESULT Global_Time(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1844 {
1845 SYSTEMTIME lt;
1846 UDATE ud;
1847 DATE time;
1848 HRESULT hres;
1849
1850 TRACE("\n");
1851
1852 GetLocalTime(<);
1853 ud.st = lt;
1854 ud.wDayOfYear = 0;
1855 hres = VarDateFromUdateEx(&ud, 0, VAR_TIMEVALUEONLY, &time);
1856 if(FAILED(hres))
1857 return hres;
1858 return return_date(res, time);
1859 }
1860
Global_Day(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1861 static HRESULT Global_Day(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1862 {
1863 SYSTEMTIME st;
1864 HRESULT hres;
1865
1866 TRACE("(%s)\n", debugstr_variant(arg));
1867
1868 hres = to_system_time(arg, &st);
1869 return FAILED(hres) ? hres : return_short(res, st.wDay);
1870 }
1871
Global_Month(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1872 static HRESULT Global_Month(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1873 {
1874 SYSTEMTIME st;
1875 HRESULT hres;
1876
1877 TRACE("(%s)\n", debugstr_variant(arg));
1878
1879 hres = to_system_time(arg, &st);
1880 return FAILED(hres) ? hres : return_short(res, st.wMonth);
1881 }
1882
Global_Weekday(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1883 static HRESULT Global_Weekday(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1884 {
1885 FIXME("\n");
1886 return E_NOTIMPL;
1887 }
1888
Global_Year(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1889 static HRESULT Global_Year(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1890 {
1891 SYSTEMTIME st;
1892 HRESULT hres;
1893
1894 TRACE("(%s)\n", debugstr_variant(arg));
1895
1896 hres = to_system_time(arg, &st);
1897 return FAILED(hres) ? hres : return_short(res, st.wYear);
1898 }
1899
Global_Hour(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1900 static HRESULT Global_Hour(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1901 {
1902 SYSTEMTIME st;
1903 HRESULT hres;
1904
1905 TRACE("(%s)\n", debugstr_variant(arg));
1906
1907 hres = to_system_time(arg, &st);
1908 return FAILED(hres) ? hres : return_short(res, st.wHour);
1909 }
1910
Global_Minute(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1911 static HRESULT Global_Minute(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1912 {
1913 SYSTEMTIME st;
1914 HRESULT hres;
1915
1916 TRACE("(%s)\n", debugstr_variant(arg));
1917
1918 hres = to_system_time(arg, &st);
1919 return FAILED(hres) ? hres : return_short(res, st.wMinute);
1920 }
1921
Global_Second(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1922 static HRESULT Global_Second(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1923 {
1924 SYSTEMTIME st;
1925 HRESULT hres;
1926
1927 TRACE("(%s)\n", debugstr_variant(arg));
1928
1929 hres = to_system_time(arg, &st);
1930 return FAILED(hres) ? hres : return_short(res, st.wSecond);
1931 }
1932
Global_DateValue(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1933 static HRESULT Global_DateValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1934 {
1935 FIXME("\n");
1936 return E_NOTIMPL;
1937 }
1938
Global_TimeValue(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1939 static HRESULT Global_TimeValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1940 {
1941 FIXME("\n");
1942 return E_NOTIMPL;
1943 }
1944
Global_DateSerial(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1945 static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1946 {
1947 FIXME("\n");
1948 return E_NOTIMPL;
1949 }
1950
Global_TimeSerial(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1951 static HRESULT Global_TimeSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1952 {
1953 FIXME("\n");
1954 return E_NOTIMPL;
1955 }
1956
Global_InputBox(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1957 static HRESULT Global_InputBox(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1958 {
1959 FIXME("\n");
1960 return E_NOTIMPL;
1961 }
1962
Global_MsgBox(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)1963 static HRESULT Global_MsgBox(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
1964 {
1965 BSTR prompt, title = NULL;
1966 int type = MB_OK;
1967 HRESULT hres;
1968
1969 TRACE("\n");
1970
1971 assert(1 <= args_cnt && args_cnt <= 5);
1972
1973 hres = to_string(args, &prompt);
1974 if(FAILED(hres))
1975 return hres;
1976
1977 if(args_cnt > 1)
1978 hres = to_int(args+1, &type);
1979
1980 if(SUCCEEDED(hres) && args_cnt > 2)
1981 hres = to_string(args+2, &title);
1982
1983 if(SUCCEEDED(hres) && args_cnt > 3) {
1984 FIXME("unsupported arg_cnt %d\n", args_cnt);
1985 hres = E_NOTIMPL;
1986 }
1987
1988 if(SUCCEEDED(hres))
1989 hres = show_msgbox(This->ctx, prompt, type, title, res);
1990
1991 SysFreeString(prompt);
1992 SysFreeString(title);
1993 return hres;
1994 }
1995
Global_CreateObject(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)1996 static HRESULT Global_CreateObject(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
1997 {
1998 IUnknown *obj;
1999 HRESULT hres;
2000
2001 TRACE("(%s)\n", debugstr_variant(arg));
2002
2003 if(V_VT(arg) != VT_BSTR) {
2004 FIXME("non-bstr arg\n");
2005 return E_INVALIDARG;
2006 }
2007
2008 obj = create_object(This->ctx, V_BSTR(arg));
2009 if(!obj)
2010 return VB_E_CANNOT_CREATE_OBJ;
2011
2012 if(res) {
2013 hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&V_DISPATCH(res));
2014 if(FAILED(hres))
2015 return hres;
2016
2017 V_VT(res) = VT_DISPATCH;
2018 }
2019
2020 IUnknown_Release(obj);
2021 return S_OK;
2022 }
2023
Global_GetObject(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2024 static HRESULT Global_GetObject(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2025 {
2026 IBindCtx *bind_ctx;
2027 IUnknown *obj_unk;
2028 IDispatch *disp;
2029 ULONG eaten = 0;
2030 IMoniker *mon;
2031 HRESULT hres;
2032
2033 TRACE("%s %s\n", args_cnt ? debugstr_variant(args) : "", args_cnt > 1 ? debugstr_variant(args+1) : "");
2034
2035 if(args_cnt != 1 || V_VT(args) != VT_BSTR) {
2036 FIXME("unsupported args\n");
2037 return E_NOTIMPL;
2038 }
2039
2040 if(This->ctx->safeopt & (INTERFACE_USES_SECURITY_MANAGER|INTERFACESAFE_FOR_UNTRUSTED_DATA)) {
2041 WARN("blocked in current safety mode\n");
2042 return VB_E_CANNOT_CREATE_OBJ;
2043 }
2044
2045 hres = CreateBindCtx(0, &bind_ctx);
2046 if(FAILED(hres))
2047 return hres;
2048
2049 hres = MkParseDisplayName(bind_ctx, V_BSTR(args), &eaten, &mon);
2050 if(SUCCEEDED(hres)) {
2051 hres = IMoniker_BindToObject(mon, bind_ctx, NULL, &IID_IUnknown, (void**)&obj_unk);
2052 IMoniker_Release(mon);
2053 }else {
2054 hres = MK_E_SYNTAX;
2055 }
2056 IBindCtx_Release(bind_ctx);
2057 if(FAILED(hres))
2058 return hres;
2059
2060 hres = set_object_site(This->ctx, obj_unk);
2061 if(FAILED(hres)) {
2062 IUnknown_Release(obj_unk);
2063 return hres;
2064 }
2065
2066 hres = IUnknown_QueryInterface(obj_unk, &IID_IDispatch, (void**)&disp);
2067 if(SUCCEEDED(hres)) {
2068 if(res) {
2069 V_VT(res) = VT_DISPATCH;
2070 V_DISPATCH(res) = disp;
2071 }else {
2072 IDispatch_Release(disp);
2073 }
2074 }else {
2075 FIXME("object does not support IDispatch\n");
2076 }
2077
2078 return hres;
2079 }
2080
Global_DateAdd(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2081 static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2082 {
2083 FIXME("\n");
2084 return E_NOTIMPL;
2085 }
2086
Global_DateDiff(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2087 static HRESULT Global_DateDiff(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2088 {
2089 FIXME("\n");
2090 return E_NOTIMPL;
2091 }
2092
Global_DatePart(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2093 static HRESULT Global_DatePart(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2094 {
2095 FIXME("\n");
2096 return E_NOTIMPL;
2097 }
2098
Global_TypeName(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2099 static HRESULT Global_TypeName(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2100 {
2101 static const WCHAR ByteW[] = {'B', 'y', 't', 'e', 0};
2102 static const WCHAR IntegerW[] = {'I', 'n', 't', 'e', 'g', 'e', 'r', 0};
2103 static const WCHAR LongW[] = {'L', 'o', 'n', 'g', 0};
2104 static const WCHAR SingleW[] = {'S', 'i', 'n', 'g', 'l', 'e', 0};
2105 static const WCHAR DoubleW[] = {'D', 'o', 'u', 'b', 'l', 'e', 0};
2106 static const WCHAR CurrencyW[] = {'C', 'u', 'r', 'r', 'e', 'n', 'c', 'y', 0};
2107 static const WCHAR DecimalW[] = {'D', 'e', 'c', 'i', 'm', 'a', 'l', 0};
2108 static const WCHAR DateW[] = {'D', 'a', 't', 'e', 0};
2109 static const WCHAR StringW[] = {'S', 't', 'r', 'i', 'n', 'g', 0};
2110 static const WCHAR BooleanW[] = {'B', 'o', 'o', 'l', 'e', 'a', 'n', 0};
2111 static const WCHAR EmptyW[] = {'E', 'm', 'p', 't', 'y', 0};
2112 static const WCHAR NullW[] = {'N', 'u', 'l', 'l', 0};
2113
2114 TRACE("(%s)\n", debugstr_variant(arg));
2115
2116 assert(args_cnt == 1);
2117
2118 switch(V_VT(arg)) {
2119 case VT_UI1:
2120 return return_string(res, ByteW);
2121 case VT_I2:
2122 return return_string(res, IntegerW);
2123 case VT_I4:
2124 return return_string(res, LongW);
2125 case VT_R4:
2126 return return_string(res, SingleW);
2127 case VT_R8:
2128 return return_string(res, DoubleW);
2129 case VT_CY:
2130 return return_string(res, CurrencyW);
2131 case VT_DECIMAL:
2132 return return_string(res, DecimalW);
2133 case VT_DATE:
2134 return return_string(res, DateW);
2135 case VT_BSTR:
2136 return return_string(res, StringW);
2137 case VT_BOOL:
2138 return return_string(res, BooleanW);
2139 case VT_EMPTY:
2140 return return_string(res, EmptyW);
2141 case VT_NULL:
2142 return return_string(res, NullW);
2143 default:
2144 FIXME("arg %s not supported\n", debugstr_variant(arg));
2145 return E_NOTIMPL;
2146 }
2147 }
2148
Global_Array(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2149 static HRESULT Global_Array(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2150 {
2151 SAFEARRAYBOUND bounds;
2152 SAFEARRAY *sa;
2153 VARIANT *data;
2154 HRESULT hres;
2155 unsigned i;
2156
2157 TRACE("arg_cnt=%u\n", args_cnt);
2158
2159 bounds.lLbound = 0;
2160 bounds.cElements = args_cnt;
2161 sa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
2162 if(!sa)
2163 return E_OUTOFMEMORY;
2164
2165 hres = SafeArrayAccessData(sa, (void**)&data);
2166 if(FAILED(hres)) {
2167 SafeArrayDestroy(sa);
2168 return hres;
2169 }
2170
2171 for(i=0; i<args_cnt; i++) {
2172 hres = VariantCopyInd(data+i, arg+i);
2173 if(FAILED(hres)) {
2174 SafeArrayUnaccessData(sa);
2175 SafeArrayDestroy(sa);
2176 return hres;
2177 }
2178 }
2179 SafeArrayUnaccessData(sa);
2180
2181 if(res) {
2182 V_VT(res) = VT_ARRAY|VT_VARIANT;
2183 V_ARRAY(res) = sa;
2184 }else {
2185 SafeArrayDestroy(sa);
2186 }
2187
2188 return S_OK;
2189 }
2190
Global_Erase(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2191 static HRESULT Global_Erase(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2192 {
2193 FIXME("\n");
2194 return E_NOTIMPL;
2195 }
2196
Global_Filter(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2197 static HRESULT Global_Filter(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2198 {
2199 FIXME("\n");
2200 return E_NOTIMPL;
2201 }
2202
Global_Join(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2203 static HRESULT Global_Join(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2204 {
2205 FIXME("\n");
2206 return E_NOTIMPL;
2207 }
2208
Global_Split(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2209 static HRESULT Global_Split(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2210 {
2211 FIXME("\n");
2212 return E_NOTIMPL;
2213 }
2214
Global_Replace(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2215 static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2216 {
2217 FIXME("\n");
2218 return E_NOTIMPL;
2219 }
2220
Global_StrReverse(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2221 static HRESULT Global_StrReverse(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2222 {
2223 WCHAR *ptr1, *ptr2, ch;
2224 BSTR ret;
2225 HRESULT hres;
2226
2227 TRACE("%s\n", debugstr_variant(arg));
2228
2229 hres = to_string(arg, &ret);
2230 if(FAILED(hres))
2231 return hres;
2232
2233 ptr1 = ret;
2234 ptr2 = ret + SysStringLen(ret)-1;
2235 while(ptr1 < ptr2) {
2236 ch = *ptr1;
2237 *ptr1++ = *ptr2;
2238 *ptr2-- = ch;
2239 }
2240
2241 return return_bstr(res, ret);
2242 }
2243
Global_InStrRev(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2244 static HRESULT Global_InStrRev(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2245 {
2246 int start, ret = 0;
2247 BSTR str1, str2;
2248 HRESULT hres;
2249
2250 TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args), debugstr_variant(args+1), args_cnt);
2251
2252 if(args_cnt > 3) {
2253 FIXME("Unsupported args\n");
2254 return E_NOTIMPL;
2255 }
2256
2257 assert(2 <= args_cnt && args_cnt <= 4);
2258
2259 if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL))
2260 return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
2261
2262 hres = to_string(args, &str1);
2263 if(FAILED(hres))
2264 return hres;
2265
2266 hres = to_string(args+1, &str2);
2267 if(SUCCEEDED(hres)) {
2268 if(args_cnt > 2) {
2269 hres = to_int(args+2, &start);
2270 if(SUCCEEDED(hres) && start <= 0) {
2271 FIXME("Unsupported start %d\n", start);
2272 hres = E_NOTIMPL;
2273 }
2274 }else {
2275 start = SysStringLen(str1);
2276 }
2277 } else {
2278 str2 = NULL;
2279 }
2280
2281 if(SUCCEEDED(hres)) {
2282 const WCHAR *ptr;
2283 size_t len;
2284
2285 len = SysStringLen(str2);
2286 if(start >= len && start <= SysStringLen(str1)) {
2287 for(ptr = str1+start-SysStringLen(str2); ptr >= str1; ptr--) {
2288 if(!memcmp(ptr, str2, len*sizeof(WCHAR))) {
2289 ret = ptr-str1+1;
2290 break;
2291 }
2292 }
2293 }
2294 }
2295
2296 SysFreeString(str1);
2297 SysFreeString(str2);
2298 if(FAILED(hres))
2299 return hres;
2300
2301 return return_int(res, ret);
2302 }
2303
Global_LoadPicture(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2304 static HRESULT Global_LoadPicture(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2305 {
2306 FIXME("\n");
2307 return E_NOTIMPL;
2308 }
2309
Global_ScriptEngine(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2310 static HRESULT Global_ScriptEngine(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2311 {
2312 TRACE("%s\n", debugstr_variant(arg));
2313
2314 assert(args_cnt == 0);
2315
2316 return return_string(res, vbscriptW);
2317 }
2318
Global_ScriptEngineMajorVersion(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2319 static HRESULT Global_ScriptEngineMajorVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2320 {
2321 TRACE("%s\n", debugstr_variant(arg));
2322
2323 assert(args_cnt == 0);
2324
2325 return return_int(res, VBSCRIPT_MAJOR_VERSION);
2326 }
2327
Global_ScriptEngineMinorVersion(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2328 static HRESULT Global_ScriptEngineMinorVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2329 {
2330 TRACE("%s\n", debugstr_variant(arg));
2331
2332 assert(args_cnt == 0);
2333
2334 return return_int(res, VBSCRIPT_MINOR_VERSION);
2335 }
2336
Global_ScriptEngineBuildVersion(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2337 static HRESULT Global_ScriptEngineBuildVersion(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2338 {
2339 TRACE("%s\n", debugstr_variant(arg));
2340
2341 assert(args_cnt == 0);
2342
2343 return return_int(res, VBSCRIPT_BUILD_VERSION);
2344 }
2345
Global_FormatNumber(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2346 static HRESULT Global_FormatNumber(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2347 {
2348 FIXME("\n");
2349 return E_NOTIMPL;
2350 }
2351
Global_FormatCurrency(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2352 static HRESULT Global_FormatCurrency(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2353 {
2354 FIXME("\n");
2355 return E_NOTIMPL;
2356 }
2357
Global_FormatPercent(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2358 static HRESULT Global_FormatPercent(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2359 {
2360 FIXME("\n");
2361 return E_NOTIMPL;
2362 }
2363
Global_FormatDateTime(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2364 static HRESULT Global_FormatDateTime(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2365 {
2366 FIXME("\n");
2367 return E_NOTIMPL;
2368 }
2369
Global_WeekdayName(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2370 static HRESULT Global_WeekdayName(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2371 {
2372 int weekday, first_day = 1, abbrev = 0;
2373 BSTR ret;
2374 HRESULT hres;
2375
2376 TRACE("\n");
2377
2378 assert(1 <= args_cnt && args_cnt <= 3);
2379
2380 hres = to_int(args, &weekday);
2381 if(FAILED(hres))
2382 return hres;
2383
2384 if(args_cnt > 1) {
2385 hres = to_int(args+1, &abbrev);
2386 if(FAILED(hres))
2387 return hres;
2388
2389 if(args_cnt == 3) {
2390 hres = to_int(args+2, &first_day);
2391 if(FAILED(hres))
2392 return hres;
2393 }
2394 }
2395
2396 hres = VarWeekdayName(weekday, abbrev, first_day, 0, &ret);
2397 if(FAILED(hres))
2398 return hres;
2399
2400 return return_bstr(res, ret);
2401 }
2402
Global_MonthName(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2403 static HRESULT Global_MonthName(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2404 {
2405 int month, abbrev = 0;
2406 BSTR ret;
2407 HRESULT hres;
2408
2409 TRACE("\n");
2410
2411 assert(args_cnt == 1 || args_cnt == 2);
2412
2413 hres = to_int(args, &month);
2414 if(FAILED(hres))
2415 return hres;
2416
2417 if(args_cnt == 2) {
2418 hres = to_int(args+1, &abbrev);
2419 if(FAILED(hres))
2420 return hres;
2421 }
2422
2423 hres = VarMonthName(month, abbrev, 0, &ret);
2424 if(FAILED(hres))
2425 return hres;
2426
2427 return return_bstr(res, ret);
2428 }
2429
Global_Round(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2430 static HRESULT Global_Round(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2431 {
2432 double n;
2433 HRESULT hres;
2434
2435 TRACE("%s\n", debugstr_variant(arg));
2436
2437 if(!res)
2438 return S_OK;
2439
2440 switch(V_VT(arg)) {
2441 case VT_I2:
2442 case VT_I4:
2443 case VT_BOOL:
2444 *res = *arg;
2445 return S_OK;
2446 case VT_R8:
2447 n = V_R8(arg);
2448 break;
2449 default:
2450 hres = to_double(arg, &n);
2451 if(FAILED(hres))
2452 return hres;
2453 }
2454
2455 return return_double(res, round(n));
2456 }
2457
Global_Escape(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2458 static HRESULT Global_Escape(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2459 {
2460 FIXME("\n");
2461 return E_NOTIMPL;
2462 }
2463
Global_Unescape(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2464 static HRESULT Global_Unescape(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2465 {
2466 FIXME("\n");
2467 return E_NOTIMPL;
2468 }
2469
Global_Eval(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2470 static HRESULT Global_Eval(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2471 {
2472 FIXME("\n");
2473 return E_NOTIMPL;
2474 }
2475
Global_Execute(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2476 static HRESULT Global_Execute(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2477 {
2478 FIXME("\n");
2479 return E_NOTIMPL;
2480 }
2481
Global_ExecuteGlobal(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2482 static HRESULT Global_ExecuteGlobal(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2483 {
2484 FIXME("\n");
2485 return E_NOTIMPL;
2486 }
2487
Global_GetRef(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2488 static HRESULT Global_GetRef(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2489 {
2490 FIXME("\n");
2491 return E_NOTIMPL;
2492 }
2493
Global_Err(BuiltinDisp * This,VARIANT * arg,unsigned args_cnt,VARIANT * res)2494 static HRESULT Global_Err(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
2495 {
2496 TRACE("\n");
2497
2498 if(args_cnt) {
2499 FIXME("Setter not supported\n");
2500 return E_NOTIMPL;
2501 }
2502
2503 V_VT(res) = VT_DISPATCH;
2504 V_DISPATCH(res) = &This->ctx->err_obj->IDispatch_iface;
2505 IDispatch_AddRef(V_DISPATCH(res));
2506 return S_OK;
2507 }
2508
2509 static const string_constant_t vbCr = {1, {'\r'}};
2510 static const string_constant_t vbCrLf = {2, {'\r','\n'}};
2511 static const string_constant_t vbNewLine = {2, {'\r','\n'}};
2512 static const string_constant_t vbFormFeed = {1, {0xc}};
2513 static const string_constant_t vbLf = {1, {'\n'}};
2514 static const string_constant_t vbNullChar = {1};
2515 static const string_constant_t vbNullString = {0};
2516 static const string_constant_t vbTab = {1, {'\t'}};
2517 static const string_constant_t vbVerticalTab = {1, {0xb}};
2518
2519 static const builtin_prop_t global_props[] = {
2520 {NULL}, /* no default value */
2521 {L"Abs", Global_Abs, 0, 1},
2522 {L"Array", Global_Array, 0, 0, MAXDWORD},
2523 {L"Asc", Global_Asc, 0, 1},
2524 {L"AscB", Global_AscB, 0, 1},
2525 {L"AscW", Global_AscW, 0, 1},
2526 {L"Atn", Global_Atn, 0, 1},
2527 {L"CBool", Global_CBool, 0, 1},
2528 {L"CByte", Global_CByte, 0, 1},
2529 {L"CCur", Global_CCur, 0, 1},
2530 {L"CDate", Global_CDate, 0, 1},
2531 {L"CDbl", Global_CDbl, 0, 1},
2532 {L"Chr", Global_Chr, 0, 1},
2533 {L"ChrB", Global_ChrB, 0, 1},
2534 {L"ChrW", Global_ChrW, 0, 1},
2535 {L"CInt", Global_CInt, 0, 1},
2536 {L"CLng", Global_CLng, 0, 1},
2537 {L"Cos", Global_Cos, 0, 1},
2538 {L"CreateObject", Global_CreateObject, 0, 1},
2539 {L"CSng", Global_CSng, 0, 1},
2540 {L"CStr", Global_CStr, 0, 1},
2541 {L"Date", Global_Date, 0, 0},
2542 {L"DateAdd", Global_DateAdd, 0, 3},
2543 {L"DateDiff", Global_DateDiff, 0, 3, 5},
2544 {L"DatePart", Global_DatePart, 0, 2, 4},
2545 {L"DateSerial", Global_DateSerial, 0, 3},
2546 {L"DateValue", Global_DateValue, 0, 1},
2547 {L"Day", Global_Day, 0, 1},
2548 {L"Erase", Global_Erase, 0, 1},
2549 {L"Err", Global_Err, BP_GETPUT},
2550 {L"Escape", Global_Escape, 0, 1},
2551 {L"Eval", Global_Eval, 0, 1},
2552 {L"Execute", Global_Execute, 0, 1},
2553 {L"ExecuteGlobal", Global_ExecuteGlobal, 0, 1},
2554 {L"Exp", Global_Exp, 0, 1},
2555 {L"Filter", Global_Filter, 0, 2, 4},
2556 {L"Fix", Global_Fix, 0, 1},
2557 {L"FormatCurrency", Global_FormatCurrency, 0, 1, 5},
2558 {L"FormatDateTime", Global_FormatDateTime, 0, 1, 2},
2559 {L"FormatNumber", Global_FormatNumber, 0, 1, 5},
2560 {L"FormatPercent", Global_FormatPercent, 0, 1, 5},
2561 {L"GetObject", Global_GetObject, 0, 0, 2},
2562 {L"GetRef", Global_GetRef, 0, 1},
2563 {L"Hex", Global_Hex, 0, 1},
2564 {L"Hour", Global_Hour, 0, 1},
2565 {L"InputBox", Global_InputBox, 0, 1, 7},
2566 {L"InStr", Global_InStr, 0, 2, 4},
2567 {L"InStrB", Global_InStrB, 0, 3, 4},
2568 {L"InStrRev", Global_InStrRev, 0, 2, 4},
2569 {L"Int", Global_Int, 0, 1},
2570 {L"IsArray", Global_IsArray, 0, 1},
2571 {L"IsDate", Global_IsDate, 0, 1},
2572 {L"IsEmpty", Global_IsEmpty, 0, 1},
2573 {L"IsNull", Global_IsNull, 0, 1},
2574 {L"IsNumeric", Global_IsNumeric, 0, 1},
2575 {L"IsObject", Global_IsObject, 0, 1},
2576 {L"Join", Global_Join, 0, 1, 2},
2577 {L"LBound", Global_LBound, 0, 1},
2578 {L"LCase", Global_LCase, 0, 1},
2579 {L"Left", Global_Left, 0, 2},
2580 {L"LeftB", Global_LeftB, 0, 2},
2581 {L"Len", Global_Len, 0, 1},
2582 {L"LenB", Global_LenB, 0, 1},
2583 {L"LoadPicture", Global_LoadPicture, 0, 1},
2584 {L"Log", Global_Log, 0, 1},
2585 {L"LTrim", Global_LTrim, 0, 1},
2586 {L"Mid", Global_Mid, 0, 2, 3},
2587 {L"MidB", Global_MidB, 0, 2, 3},
2588 {L"Minute", Global_Minute, 0, 1},
2589 {L"Month", Global_Month, 0, 1},
2590 {L"MonthName", Global_MonthName, 0, 1, 2},
2591 {L"MsgBox", Global_MsgBox, 0, 1, 5},
2592 {L"Now", Global_Now, 0, 0},
2593 {L"Oct", Global_Oct, 0, 1},
2594 {L"Randomize", Global_Randomize, 0, 1},
2595 {L"Replace", Global_Replace, 0, 3, 6},
2596 {L"RGB", Global_RGB, 0, 3},
2597 {L"Right", Global_Right, 0, 2},
2598 {L"RightB", Global_RightB, 0, 2},
2599 {L"Rnd", Global_Rnd, 0, 1},
2600 {L"Round", Global_Round, 0, 1, 2},
2601 {L"RTrim", Global_RTrim, 0, 1},
2602 {L"ScriptEngine", Global_ScriptEngine, 0, 0},
2603 {L"ScriptEngineBuildVersion", Global_ScriptEngineBuildVersion, 0, 0},
2604 {L"ScriptEngineMajorVersion", Global_ScriptEngineMajorVersion, 0, 0},
2605 {L"ScriptEngineMinorVersion", Global_ScriptEngineMinorVersion, 0, 0},
2606 {L"Second", Global_Second, 0, 1},
2607 {L"Sgn", Global_Sgn, 0, 1},
2608 {L"Sin", Global_Sin, 0, 1},
2609 {L"Space", Global_Space, 0, 1},
2610 {L"Split", Global_Split, 0, 1, 4},
2611 {L"Sqr", Global_Sqr, 0, 1},
2612 {L"StrComp", Global_StrComp, 0, 2, 3},
2613 {L"String", Global_String, 0, 0, 2},
2614 {L"StrReverse", Global_StrReverse, 0, 1},
2615 {L"Tan", Global_Tan, 0, 1},
2616 {L"Time", Global_Time, 0, 0},
2617 {L"Timer", Global_Timer, 0, 0},
2618 {L"TimeSerial", Global_TimeSerial, 0, 3},
2619 {L"TimeValue", Global_TimeValue, 0, 1},
2620 {L"Trim", Global_Trim, 0, 1},
2621 {L"TypeName", Global_TypeName, 0, 1},
2622 {L"UBound", Global_UBound, 0, 1, 2},
2623 {L"UCase", Global_UCase, 0, 1},
2624 {L"Unescape", Global_Unescape, 0, 1},
2625 {L"VarType", Global_VarType, 0, 1},
2626 {L"vbAbort", NULL, BP_GET, VT_I2, IDABORT},
2627 {L"vbAbortRetryIgnore", NULL, BP_GET, VT_I2, MB_ABORTRETRYIGNORE},
2628 {L"vbApplicationModal", NULL, BP_GET, VT_I2, MB_APPLMODAL},
2629 {L"vbArray", NULL, BP_GET, VT_I2, VT_ARRAY},
2630 {L"vbBinaryCompare", NULL, BP_GET, VT_I2, 0},
2631 {L"vbBlack", NULL, BP_GET, VT_I4, 0x000000},
2632 {L"vbBlue", NULL, BP_GET, VT_I4, 0xff0000},
2633 {L"vbBoolean", NULL, BP_GET, VT_I2, VT_BOOL},
2634 {L"vbByte", NULL, BP_GET, VT_I2, VT_UI1},
2635 {L"vbCancel", NULL, BP_GET, VT_I2, IDCANCEL},
2636 {L"vbCr", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCr},
2637 {L"vbCritical", NULL, BP_GET, VT_I2, MB_ICONHAND},
2638 {L"vbCrLf", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbCrLf},
2639 {L"vbCurrency", NULL, BP_GET, VT_I2, VT_CY},
2640 {L"vbCyan", NULL, BP_GET, VT_I4, 0xffff00},
2641 {L"vbDatabaseCompare", NULL, BP_GET, VT_I2, 2},
2642 {L"vbDataObject", NULL, BP_GET, VT_I2, VT_UNKNOWN},
2643 {L"vbDate", NULL, BP_GET, VT_I2, VT_DATE},
2644 {L"vbDecimal", NULL, BP_GET, VT_I2, VT_DECIMAL},
2645 {L"vbDefaultButton1", NULL, BP_GET, VT_I2, MB_DEFBUTTON1},
2646 {L"vbDefaultButton2", NULL, BP_GET, VT_I2, MB_DEFBUTTON2},
2647 {L"vbDefaultButton3", NULL, BP_GET, VT_I2, MB_DEFBUTTON3},
2648 {L"vbDefaultButton4", NULL, BP_GET, VT_I2, MB_DEFBUTTON4},
2649 {L"vbDouble", NULL, BP_GET, VT_I2, VT_R8},
2650 {L"vbEmpty", NULL, BP_GET, VT_I2, VT_EMPTY},
2651 {L"vbError", NULL, BP_GET, VT_I2, VT_ERROR},
2652 {L"vbExclamation", NULL, BP_GET, VT_I2, MB_ICONEXCLAMATION},
2653 {L"vbFalse", NULL, BP_GET, VT_I2, VARIANT_FALSE},
2654 {L"vbFirstFourDays", NULL, BP_GET, VT_I2, 2},
2655 {L"vbFirstFullWeek", NULL, BP_GET, VT_I2, 3},
2656 {L"vbFirstJan1", NULL, BP_GET, VT_I2, 1},
2657 {L"vbFormFeed", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbFormFeed},
2658 {L"vbFriday", NULL, BP_GET, VT_I2, 6},
2659 {L"vbGeneralDate", NULL, BP_GET, VT_I2, 0},
2660 {L"vbGreen", NULL, BP_GET, VT_I4, 0x00ff00},
2661 {L"vbIgnore", NULL, BP_GET, VT_I2, IDIGNORE},
2662 {L"vbInformation", NULL, BP_GET, VT_I2, MB_ICONASTERISK},
2663 {L"vbInteger", NULL, BP_GET, VT_I2, VT_I2},
2664 {L"vbLf", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbLf},
2665 {L"vbLong", NULL, BP_GET, VT_I2, VT_I4},
2666 {L"vbLongDate", NULL, BP_GET, VT_I2, 1},
2667 {L"vbLongTime", NULL, BP_GET, VT_I2, 3},
2668 {L"vbMagenta", NULL, BP_GET, VT_I4, 0xff00ff},
2669 {L"vbMonday", NULL, BP_GET, VT_I2, 2},
2670 {L"vbMsgBoxHelpButton", NULL, BP_GET, VT_I4, MB_HELP},
2671 {L"vbMsgBoxRight", NULL, BP_GET, VT_I4, MB_RIGHT},
2672 {L"vbMsgBoxRtlReading", NULL, BP_GET, VT_I4, MB_RTLREADING},
2673 {L"vbMsgBoxSetForeground", NULL, BP_GET, VT_I4, MB_SETFOREGROUND},
2674 {L"vbNewLine", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNewLine},
2675 {L"vbNo", NULL, BP_GET, VT_I2, IDNO},
2676 {L"vbNull", NULL, BP_GET, VT_I2, VT_NULL},
2677 {L"vbNullChar", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullChar},
2678 {L"vbNullString", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbNullString},
2679 {L"vbObject", NULL, BP_GET, VT_I2, VT_DISPATCH},
2680 {L"vbObjectError", NULL, BP_GET, VT_I4, 0x80040000},
2681 {L"vbOK", NULL, BP_GET, VT_I2, IDOK},
2682 {L"vbOKCancel", NULL, BP_GET, VT_I2, MB_OKCANCEL},
2683 {L"vbOKOnly", NULL, BP_GET, VT_I2, MB_OK},
2684 {L"vbQuestion", NULL, BP_GET, VT_I2, MB_ICONQUESTION},
2685 {L"vbRed", NULL, BP_GET, VT_I4, 0x0000ff},
2686 {L"vbRetry", NULL, BP_GET, VT_I2, IDRETRY},
2687 {L"vbRetryCancel", NULL, BP_GET, VT_I2, MB_RETRYCANCEL},
2688 {L"vbSaturday", NULL, BP_GET, VT_I2, 7},
2689 {L"vbShortDate", NULL, BP_GET, VT_I2, 2},
2690 {L"vbShortTime", NULL, BP_GET, VT_I2, 4},
2691 {L"vbSingle", NULL, BP_GET, VT_I2, VT_R4},
2692 {L"vbString", NULL, BP_GET, VT_I2, VT_BSTR},
2693 {L"vbSunday", NULL, BP_GET, VT_I2, 1},
2694 {L"vbSystemModal", NULL, BP_GET, VT_I2, MB_SYSTEMMODAL},
2695 {L"vbTab", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbTab},
2696 {L"vbTextCompare", NULL, BP_GET, VT_I2, 1},
2697 {L"vbThursday", NULL, BP_GET, VT_I2, 5},
2698 {L"vbTrue", NULL, BP_GET, VT_I2, VARIANT_TRUE},
2699 {L"vbTuesday", NULL, BP_GET, VT_I2, 3},
2700 {L"vbUseDefault", NULL, BP_GET, VT_I2, -2},
2701 {L"vbUseSystem", NULL, BP_GET, VT_I2, 0},
2702 {L"vbUseSystemDayOfWeek", NULL, BP_GET, VT_I2, 0},
2703 {L"vbVariant", NULL, BP_GET, VT_I2, VT_VARIANT},
2704 {L"vbVerticalTab", NULL, BP_GET, VT_BSTR, (UINT_PTR)&vbVerticalTab},
2705 {L"vbWednesday", NULL, BP_GET, VT_I2, 4},
2706 {L"vbWhite", NULL, BP_GET, VT_I4, 0xffffff},
2707 {L"vbYellow", NULL, BP_GET, VT_I4, 0x00ffff},
2708 {L"vbYes", NULL, BP_GET, VT_I2, IDYES},
2709 {L"vbYesNo", NULL, BP_GET, VT_I2, MB_YESNO},
2710 {L"vbYesNoCancel", NULL, BP_GET, VT_I2, MB_YESNOCANCEL},
2711 {L"Weekday", Global_Weekday, 0, 1, 2},
2712 {L"WeekdayName", Global_WeekdayName, 0, 1, 3},
2713 {L"Year", Global_Year, 0, 1}
2714 };
2715
err_string_prop(BSTR * prop,VARIANT * args,unsigned args_cnt,VARIANT * res)2716 static HRESULT err_string_prop(BSTR *prop, VARIANT *args, unsigned args_cnt, VARIANT *res)
2717 {
2718 BSTR str;
2719 HRESULT hres;
2720
2721 if(!args_cnt)
2722 return return_string(res, *prop ? *prop : L"");
2723
2724 hres = to_string(args, &str);
2725 if(FAILED(hres))
2726 return hres;
2727
2728 SysFreeString(*prop);
2729 *prop = str;
2730 return S_OK;
2731 }
2732
Err_Description(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2733 static HRESULT Err_Description(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2734 {
2735 TRACE("\n");
2736 return err_string_prop(&This->ctx->ei.bstrDescription, args, args_cnt, res);
2737 }
2738
Err_HelpContext(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2739 static HRESULT Err_HelpContext(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2740 {
2741 TRACE("\n");
2742
2743 if(args_cnt) {
2744 FIXME("setter not implemented\n");
2745 return E_NOTIMPL;
2746 }
2747
2748 return return_int(res, This->ctx->ei.dwHelpContext);
2749 }
2750
Err_HelpFile(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2751 static HRESULT Err_HelpFile(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2752 {
2753 TRACE("\n");
2754 return err_string_prop(&This->ctx->ei.bstrHelpFile, args, args_cnt, res);
2755 }
2756
Err_Number(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2757 static HRESULT Err_Number(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2758 {
2759 HRESULT hres;
2760
2761 TRACE("\n");
2762
2763 if(args_cnt) {
2764 FIXME("setter not implemented\n");
2765 return E_NOTIMPL;
2766 }
2767
2768 hres = This->ctx->ei.scode;
2769 return return_int(res, HRESULT_FACILITY(hres) == FACILITY_VBS ? HRESULT_CODE(hres) : hres);
2770 }
2771
Err_Source(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2772 static HRESULT Err_Source(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2773 {
2774 TRACE("\n");
2775 return err_string_prop(&This->ctx->ei.bstrSource, args, args_cnt, res);
2776 }
2777
Err_Clear(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2778 static HRESULT Err_Clear(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2779 {
2780 TRACE("\n");
2781
2782 clear_ei(&This->ctx->ei);
2783 return S_OK;
2784 }
2785
Err_Raise(BuiltinDisp * This,VARIANT * args,unsigned args_cnt,VARIANT * res)2786 static HRESULT Err_Raise(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
2787 {
2788 BSTR source = NULL, description = NULL, helpfile = NULL;
2789 int code, helpcontext = 0;
2790 HRESULT hres, error;
2791
2792 TRACE("%s %u...\n", debugstr_variant(args), args_cnt);
2793
2794 hres = to_int(args, &code);
2795 if(FAILED(hres))
2796 return hres;
2797 if(code > 0 && code > 0xffff)
2798 return E_INVALIDARG;
2799
2800 if(args_cnt >= 2)
2801 hres = to_string(args + 1, &source);
2802 if(args_cnt >= 3 && SUCCEEDED(hres))
2803 hres = to_string(args + 2, &description);
2804 if(args_cnt >= 4 && SUCCEEDED(hres))
2805 hres = to_string(args + 3, &helpfile);
2806 if(args_cnt >= 5 && SUCCEEDED(hres))
2807 hres = to_int(args + 4, &helpcontext);
2808
2809 if(SUCCEEDED(hres)) {
2810 script_ctx_t *ctx = This->ctx;
2811
2812 error = (code & ~0xffff) ? map_hres(code) : MAKE_VBSERROR(code);
2813
2814 if(source) {
2815 if(ctx->ei.bstrSource) SysFreeString(ctx->ei.bstrSource);
2816 ctx->ei.bstrSource = source;
2817 }
2818 if(!ctx->ei.bstrSource)
2819 ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR);
2820 if(description) {
2821 if(ctx->ei.bstrDescription) SysFreeString(ctx->ei.bstrDescription);
2822 ctx->ei.bstrDescription = description;
2823 }
2824 if(!ctx->ei.bstrDescription)
2825 ctx->ei.bstrDescription = get_vbscript_error_string(error);
2826 if(helpfile) {
2827 if(ctx->ei.bstrHelpFile) SysFreeString(ctx->ei.bstrHelpFile);
2828 ctx->ei.bstrHelpFile = helpfile;
2829 }
2830 if(args_cnt >= 5)
2831 ctx->ei.dwHelpContext = helpcontext;
2832
2833 ctx->ei.scode = error;
2834 hres = SCRIPT_E_RECORDED;
2835 }else {
2836 SysFreeString(source);
2837 SysFreeString(description);
2838 SysFreeString(helpfile);
2839 }
2840
2841 return hres;
2842 }
2843
2844 static const builtin_prop_t err_props[] = {
2845 {NULL, Err_Number, BP_GETPUT},
2846 {L"Clear", Err_Clear},
2847 {L"Description", Err_Description, BP_GETPUT},
2848 {L"HelpContext", Err_HelpContext, BP_GETPUT},
2849 {L"HelpFile", Err_HelpFile, BP_GETPUT},
2850 {L"Number", Err_Number, BP_GETPUT},
2851 {L"Raise", Err_Raise, 0, 1, 5},
2852 {L"Source", Err_Source, BP_GETPUT}
2853 };
2854
detach_global_objects(script_ctx_t * ctx)2855 void detach_global_objects(script_ctx_t *ctx)
2856 {
2857 if(ctx->err_obj) {
2858 ctx->err_obj->ctx = NULL;
2859 IDispatch_Release(&ctx->err_obj->IDispatch_iface);
2860 ctx->err_obj = NULL;
2861 }
2862
2863 if(ctx->global_obj) {
2864 ctx->global_obj->ctx = NULL;
2865 IDispatch_Release(&ctx->global_obj->IDispatch_iface);
2866 ctx->global_obj = NULL;
2867 }
2868 }
2869
init_global(script_ctx_t * ctx)2870 HRESULT init_global(script_ctx_t *ctx)
2871 {
2872 HRESULT hres;
2873
2874 hres = create_builtin_dispatch(ctx, global_props, ARRAY_SIZE(global_props), &ctx->global_obj);
2875 if(FAILED(hres))
2876 return hres;
2877
2878 return create_builtin_dispatch(ctx, err_props, ARRAY_SIZE(err_props), &ctx->err_obj);
2879 }
2880