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 63 static inline BuiltinDisp *impl_from_IDispatch(IDispatch *iface) 64 { 65 return CONTAINING_RECORD(iface, BuiltinDisp, IDispatch_iface); 66 } 67 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 394 static inline HRESULT return_null(VARIANT *res) 395 { 396 if(res) 397 V_VT(res) = VT_NULL; 398 return S_OK; 399 } 400 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 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 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 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 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 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 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 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 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 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 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 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 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 739 static HRESULT Global_CDate(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 740 { 741 FIXME("\n"); 742 return E_NOTIMPL; 743 } 744 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 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 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 805 static inline WCHAR hex_char(unsigned n) 806 { 807 return n < 10 ? '0'+n : 'A'+n-10; 808 } 809 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 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 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 909 static HRESULT Global_IsDate(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 910 { 911 FIXME("\n"); 912 return E_NOTIMPL; 913 } 914 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 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 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 955 static HRESULT Global_IsArray(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 956 { 957 FIXME("\n"); 958 return E_NOTIMPL; 959 } 960 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 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 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 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 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 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 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 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 1064 static HRESULT Global_Randomize(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1065 { 1066 FIXME("\n"); 1067 return E_NOTIMPL; 1068 } 1069 1070 static HRESULT Global_Rnd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1071 { 1072 FIXME("\n"); 1073 return E_NOTIMPL; 1074 } 1075 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 1087 static HRESULT Global_LBound(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1088 { 1089 FIXME("\n"); 1090 return E_NOTIMPL; 1091 } 1092 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 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 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 1179 static HRESULT Global_LenB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1180 { 1181 FIXME("\n"); 1182 return E_NOTIMPL; 1183 } 1184 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 1223 static HRESULT Global_LeftB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1224 { 1225 FIXME("\n"); 1226 return E_NOTIMPL; 1227 } 1228 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 1267 static HRESULT Global_RightB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1268 { 1269 FIXME("\n"); 1270 return E_NOTIMPL; 1271 } 1272 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 1326 static HRESULT Global_MidB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1327 { 1328 FIXME("\n"); 1329 return E_NOTIMPL; 1330 } 1331 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 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 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 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 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 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 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 1551 static HRESULT Global_String(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1552 { 1553 FIXME("\n"); 1554 return E_NOTIMPL; 1555 } 1556 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 1624 static HRESULT Global_InStrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1625 { 1626 FIXME("\n"); 1627 return E_NOTIMPL; 1628 } 1629 1630 static HRESULT Global_AscB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1631 { 1632 FIXME("\n"); 1633 return E_NOTIMPL; 1634 } 1635 1636 static HRESULT Global_ChrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1637 { 1638 FIXME("\n"); 1639 return E_NOTIMPL; 1640 } 1641 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. */ 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 1717 static HRESULT Global_AscW(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1718 { 1719 FIXME("\n"); 1720 return E_NOTIMPL; 1721 } 1722 1723 static HRESULT Global_ChrW(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1724 { 1725 FIXME("\n"); 1726 return E_NOTIMPL; 1727 } 1728 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 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 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 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 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 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 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 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 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 1883 static HRESULT Global_Weekday(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1884 { 1885 FIXME("\n"); 1886 return E_NOTIMPL; 1887 } 1888 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 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 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 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 1933 static HRESULT Global_DateValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1934 { 1935 FIXME("\n"); 1936 return E_NOTIMPL; 1937 } 1938 1939 static HRESULT Global_TimeValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1940 { 1941 FIXME("\n"); 1942 return E_NOTIMPL; 1943 } 1944 1945 static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1946 { 1947 FIXME("\n"); 1948 return E_NOTIMPL; 1949 } 1950 1951 static HRESULT Global_TimeSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1952 { 1953 FIXME("\n"); 1954 return E_NOTIMPL; 1955 } 1956 1957 static HRESULT Global_InputBox(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 1958 { 1959 FIXME("\n"); 1960 return E_NOTIMPL; 1961 } 1962 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 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 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 2081 static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2082 { 2083 FIXME("\n"); 2084 return E_NOTIMPL; 2085 } 2086 2087 static HRESULT Global_DateDiff(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2088 { 2089 FIXME("\n"); 2090 return E_NOTIMPL; 2091 } 2092 2093 static HRESULT Global_DatePart(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2094 { 2095 FIXME("\n"); 2096 return E_NOTIMPL; 2097 } 2098 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 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 2191 static HRESULT Global_Erase(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2192 { 2193 FIXME("\n"); 2194 return E_NOTIMPL; 2195 } 2196 2197 static HRESULT Global_Filter(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2198 { 2199 FIXME("\n"); 2200 return E_NOTIMPL; 2201 } 2202 2203 static HRESULT Global_Join(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2204 { 2205 FIXME("\n"); 2206 return E_NOTIMPL; 2207 } 2208 2209 static HRESULT Global_Split(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2210 { 2211 FIXME("\n"); 2212 return E_NOTIMPL; 2213 } 2214 2215 static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2216 { 2217 FIXME("\n"); 2218 return E_NOTIMPL; 2219 } 2220 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 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 2304 static HRESULT Global_LoadPicture(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2305 { 2306 FIXME("\n"); 2307 return E_NOTIMPL; 2308 } 2309 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 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 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 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 2346 static HRESULT Global_FormatNumber(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2347 { 2348 FIXME("\n"); 2349 return E_NOTIMPL; 2350 } 2351 2352 static HRESULT Global_FormatCurrency(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2353 { 2354 FIXME("\n"); 2355 return E_NOTIMPL; 2356 } 2357 2358 static HRESULT Global_FormatPercent(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2359 { 2360 FIXME("\n"); 2361 return E_NOTIMPL; 2362 } 2363 2364 static HRESULT Global_FormatDateTime(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2365 { 2366 FIXME("\n"); 2367 return E_NOTIMPL; 2368 } 2369 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 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 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 2458 static HRESULT Global_Escape(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2459 { 2460 FIXME("\n"); 2461 return E_NOTIMPL; 2462 } 2463 2464 static HRESULT Global_Unescape(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2465 { 2466 FIXME("\n"); 2467 return E_NOTIMPL; 2468 } 2469 2470 static HRESULT Global_Eval(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2471 { 2472 FIXME("\n"); 2473 return E_NOTIMPL; 2474 } 2475 2476 static HRESULT Global_Execute(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2477 { 2478 FIXME("\n"); 2479 return E_NOTIMPL; 2480 } 2481 2482 static HRESULT Global_ExecuteGlobal(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2483 { 2484 FIXME("\n"); 2485 return E_NOTIMPL; 2486 } 2487 2488 static HRESULT Global_GetRef(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) 2489 { 2490 FIXME("\n"); 2491 return E_NOTIMPL; 2492 } 2493 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 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 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 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 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 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 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 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 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 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 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