1 /** 2 framework.d 3 Translated from framework.c by Laeeth Isharc 4 5 Purpose: Framework library for Microsoft Excel. 6 7 This library provides some basic functions 8 that help in writing Excel DLLs. It includes 9 simple functions for managing memory with XLOPER12s, 10 creating temporary XLOPER12s, robustly calling 11 Excel12(), and outputting debugging strings 12 to the debugger for the current application. 13 14 The main purpose of this library is to help 15 you to write cleaner C code for calling Excel. 16 For example, using the framework library you 17 can write 18 19 Excel12f(xlcDisplay, 0, 2, TempMissing12(), TempBool12(0)); 20 21 instead of the more verbose 22 23 XLOPER12 xMissing, bool_; 24 xMissing.xltype = xltypeMissing; 25 bool_.xltype = xltypeBool; 26 bool_.val.bool_ = 0; 27 Excel12(xlcDisplay, 0, 2, (LPXLOPER12) &xMissing, (LPXLOPER12) &bool_); 28 29 30 The library is non-reentrant. 31 32 Define _DEBUG to use the debugging functions. 33 34 Source code is provided so that you may 35 enhance this library or optimize it for your 36 own application. 37 38 Platform: Microsoft Windows 39 40 Functions: 41 debugPrintf 42 GetTempMemory 43 FreeAllTempMemory 44 Excel 45 Excel12f 46 TempNum 47 TempNum12 48 TempStr 49 TempStrConst 50 TempStr12 51 TempBool 52 TempBool12 53 TempInt 54 TempInt12 55 TempErr 56 TempErr12 57 TempActiveRef 58 TempActiveRef12 59 TempActiveCell 60 TempActiveCell12 61 TempActiveRow 62 TempActiveRow12 63 TempActiveColumn 64 TempActiveColumn12 65 TempMissing 66 TempMissing12 67 InitFramework 68 QuitFramework 69 70 */ 71 module xlld.framework; 72 73 /** 74 FreeXLOper() 75 76 Purpose: 77 Will free any malloc'd memory associated with the given 78 LPXLOPER, assuming it has any memory associated with it 79 80 Parameters: 81 82 LPXLOPER pxloper Pointer to the XLOPER whose associated 83 memory we want to free 84 85 Returns: 86 87 Comments: 88 89 */ 90 91 import xlld.xlcall; 92 93 94 void FreeXLOper(T)(T pxloper) if(is(T == LPXLOPER) || is(T == LPXLOPER12)) { 95 import xlld.memorymanager: allocator; 96 FreeXLOper(pxloper, allocator); 97 } 98 99 void FreeXLOper(T, A)(T pxloper, ref A allocator) 100 if(is(T == LPXLOPER) || is(T == LPXLOPER12)) 101 { 102 import std.experimental.allocator: dispose; 103 104 switch (pxloper.xltype & ~XlType.xlbitDLLFree) with(XlType) 105 { 106 case xltypeStr: 107 if (pxloper.val.str !is null) { 108 void* bytesPtr = pxloper.val.str; 109 const numBytes = (pxloper.val.str[0] + 1) * wchar.sizeof; 110 allocator.dispose(bytesPtr[0 .. numBytes]); 111 } 112 break; 113 case xltypeRef: 114 if (pxloper.val.mref.lpmref !is null) 115 allocator.dispose(pxloper.val.mref.lpmref); 116 break; 117 case xltypeMulti: 118 auto cxloper = pxloper.val.array.rows * pxloper.val.array.columns; 119 const numOpers = cxloper; 120 if (pxloper.val.array.lparray !is null) 121 { 122 auto pxloperFree = pxloper.val.array.lparray; 123 while (cxloper > 0) 124 { 125 FreeXLOper(pxloperFree, allocator); 126 pxloperFree++; 127 cxloper--; 128 } 129 allocator.dispose(pxloper.val.array.lparray[0 .. numOpers]); 130 } 131 break; 132 case xltypeBigData: 133 if (pxloper.val.bigdata.h.lpbData !is null) 134 allocator.dispose(pxloper.val.bigdata.h.lpbData); 135 break; 136 default: // todo: add error handling 137 break; 138 } 139 } 140 141 @("Free regular XLOPER") 142 unittest { 143 XLOPER oper; 144 FreeXLOper(&oper); 145 } 146 147 @("Free XLOPER12") 148 unittest { 149 XLOPER12 oper; 150 FreeXLOper(&oper); 151 } 152 153 /** 154 Excel12f() 155 156 Purpose: 157 A fancy wrapper for the Excel12() function. It also 158 does the following: 159 160 (1) Checks that none of the LPXLOPER12 arguments are 0, 161 which would indicate that creating a temporary XLOPER12 162 has failed. In this case, it doesn't call Excel12 163 but it does print a debug message. 164 (2) If an error occurs while calling Excel12, 165 print a useful debug message. 166 (3) When done, free all temporary memory. 167 168 #1 and #2 require _DEBUG to be defined. 169 170 Parameters: 171 172 int xlfn Function number (xl...) to call 173 LPXLOPER12 pxResult Pointer to a place to stuff the result, 174 or 0 if you don't care about the result. 175 int count Number of arguments 176 ... (all LPXLOPER12s) - the arguments. 177 178 Returns: 179 180 A return code (Some of the xlret... values, as defined 181 in XLCALL.H, OR'ed together). 182 183 Comments: 184 */ 185 186 int Excel12f(int xlfn, LPXLOPER12 pxResult, LPXLOPER12[] args) nothrow @nogc 187 { 188 import xlld.memorymanager: FreeAllTempMemory; 189 import xlld.xlcallcpp: Excel12v; 190 191 int xlret; 192 193 xlret = Excel12v(xlfn,pxResult,cast(int)args.length, cast(LPXLOPER12 *)args.ptr); 194 195 static if(false) //debug 196 { 197 if (xlret != xlretSuccess) 198 { 199 debugPrintf("Error! Excel12("); 200 201 if (xlfn & xlCommand) 202 debugPrintf("xlCommand | "); 203 if (xlfn & xlSpecial) 204 debugPrintf("xlSpecial | "); 205 if (xlfn & xlIntl) 206 debugPrintf("xlIntl | "); 207 if (xlfn & xlPrompt) 208 debugPrintf("xlPrompt | "); 209 210 debugPrintf("%u) callback failed:",xlfn & 0x0FFF); 211 212 /* More than one error bit may be on */ 213 214 if (xlret & xlretAbort) 215 { 216 debugPrintf(" Macro Halted\r"); 217 } 218 219 if (xlret & xlretInvXlfn) 220 { 221 debugPrintf(" Invalid Function Number\r"); 222 } 223 224 if (xlret & xlretInvCount) 225 { 226 debugPrintf(" Invalid Number of Arguments\r"); 227 } 228 229 if (xlret & xlretInvXloper) 230 { 231 debugPrintf(" Invalid XLOPER12\r"); 232 } 233 234 if (xlret & xlretStackOvfl) 235 { 236 debugPrintf(" Stack Overflow\r"); 237 } 238 239 if (xlret & xlretFailed) 240 { 241 debugPrintf(" Command failed\r"); 242 } 243 244 if (xlret & xlretUncalced) 245 { 246 debugPrintf(" Uncalced cell\r"); 247 } 248 249 } 250 } // debug 251 252 FreeAllTempMemory(); 253 254 return xlret; 255 } 256 257 258 version(Windows): 259 260 debug=0; 261 262 import xlld.xlcallcpp; 263 import std.typecons: Flag, Yes; 264 import core.sys.windows.windows; 265 266 enum rwMaxO8=65536; 267 enum colMaxO8=256; 268 enum cchMaxStz=255; 269 enum MAXSHORTINT =0x7fff; 270 enum CP_ACP = 0; 271 enum MAXWORD = 0xFFFF; 272 273 static if(false) // debug 274 { 275 276 /** 277 debugPrintf() 278 279 Purpose: 280 sends a string to the debugger for the current application. 281 282 Parameters: 283 284 LPSTR lpFormat The format definition string 285 ... The values to print 286 287 Returns: 288 289 Comments: 290 291 */ 292 293 void debugPrintf(LPSTR lpFormat, ...) // cdecl 294 { 295 char[256] rgch; 296 va_list argList; 297 298 va_start(argList,lpFormat); 299 wvsprintfA(rgch,lpFormat,argList); 300 va_end(argList); 301 OutputDebugStringA(rgch); 302 } 303 } 304 305 /** 306 Excel() 307 308 Purpose: 309 A fancy wrapper for the Excel4() function. It also 310 does the following: 311 312 (1) Checks that none of the LPXLOPER arguments are 0, 313 which would indicate that creating a temporary XLOPER 314 has failed. In this case, it doesn't call Excel 315 but it does print a debug message. 316 (2) If an error occurs while calling Excel, 317 print a useful debug message. 318 (3) When done, free all temporary memory. 319 320 #1 and #2 require _DEBUG to be defined. 321 322 Parameters: 323 324 int xlfn Function number (xl...) to call 325 LPXLOPER pxResult Pointer to a place to stuff the result, 326 or 0 if you don't care about the result. 327 int count Number of arguments 328 ... (all LPXLOPERs) - the arguments. 329 330 Returns: 331 332 A return code (Some of the xlret... values, as defined 333 in XLCALL.H, OR'ed together). 334 335 Comments: 336 */ 337 338 int Excel(int xlfn, LPXLOPER pxResult, LPXLOPER[] args ...) // cdecl 339 { 340 import xlld.memorymanager: FreeAllTempMemory; 341 int xlret; 342 343 xlret = Excel4v(xlfn,pxResult,cast(int)args.length,cast(LPXLOPER *)args.ptr); 344 345 static if(false) //debug 346 { 347 348 if (xlret != xlretSuccess) 349 { 350 debugPrintf("Error! Excel4("); 351 352 if (xlfn & xlCommand) 353 debugPrintf("xlCommand | "); 354 if (xlfn & xlSpecial) 355 debugPrintf("xlSpecial | "); 356 if (xlfn & xlIntl) 357 debugPrintf("xlIntl | "); 358 if (xlfn & xlPrompt) 359 debugPrintf("xlPrompt | "); 360 361 debugPrintf("%u) callback failed:",xlfn & 0x0FFF); 362 363 /* More than one error bit may be on */ 364 365 if (xlret & xlretAbort) 366 { 367 debugPrintf(" Macro Halted\r"); 368 } 369 370 if (xlret & xlretInvXlfn) 371 { 372 debugPrintf(" Invalid Function Number\r"); 373 } 374 375 if (xlret & xlretInvCount) 376 { 377 debugPrintf(" Invalid Number of Arguments\r"); 378 } 379 380 if (xlret & xlretInvXloper) 381 { 382 debugPrintf(" Invalid XLOPER\r"); 383 } 384 385 if (xlret & xlretStackOvfl) 386 { 387 debugPrintf(" Stack Overflow\r"); 388 } 389 390 if (xlret & xlretFailed) 391 { 392 debugPrintf(" Command failed\r"); 393 } 394 395 if (xlret & xlretUncalced) 396 { 397 debugPrintf(" Uncalced cell\r"); 398 } 399 400 } 401 } // debug 402 403 FreeAllTempMemory(); 404 405 return xlret; 406 } 407 408 409 410 411 /** 412 TempNum() 413 414 Purpose: 415 Creates a temporary numeric (IEEE floating point) XLOPER. 416 417 Parameters: 418 419 double d The value 420 421 Returns: 422 423 LPXLOPER The temporary XLOPER, or 0 424 if GetTempMemory() failed. 425 426 Comments: 427 */ 428 429 LPXLOPER TempNum(Flag!"autoFree" autoFree = Yes.autoFree)(double d) 430 { 431 LPXLOPER lpx; 432 433 lpx = cast(LPXLOPER) GetTempMemory!autoFree(XLOPER.sizeof); 434 435 if (!lpx) 436 { 437 return null; 438 } 439 440 lpx.xltype = xltypeNum; 441 lpx.val.num = d; 442 443 return lpx; 444 } 445 446 /** 447 TempNum12() 448 449 Purpose: 450 Creates a temporary numeric (IEEE floating point) XLOPER12. 451 452 Parameters: 453 454 double d The value 455 456 Returns: 457 458 LPXLOPER12 The temporary XLOPER12, or 0 459 if GetTempMemory() failed. 460 461 Comments: 462 463 464 */ 465 466 LPXLOPER12 TempNum12(Flag!"autoFree" autoFree = Yes.autoFree)(double d) 467 { 468 LPXLOPER12 lpx; 469 470 lpx = cast(LPXLOPER12) GetTempMemory!autoFree(XLOPER12.sizeof); 471 472 if (!lpx) 473 { 474 return null; 475 } 476 477 lpx.xltype = xltypeNum; 478 lpx.val.num = d; 479 480 return lpx; 481 } 482 483 /** 484 TempStr() 485 486 Purpose: 487 Creates a temporary string XLOPER 488 489 Parameters: 490 491 LPSTR lpstr The string, as a null-terminated 492 C string, with the first byte 493 undefined. This function will 494 count the bytes of the string 495 and insert that count in the 496 first byte of lpstr. Excel cannot 497 handle strings longer than 255 498 characters. 499 500 Returns: 501 502 LPXLOPER The temporary XLOPER, or 0 503 if GetTempMemory() failed. 504 505 Comments: 506 507 (1) This function has the side effect of inserting 508 the byte count as the first character of 509 the created string. 510 511 (2) For highest speed, with constant strings, 512 you may want to manually count the length of 513 the string before compiling, and then avoid 514 using this function. 515 516 (3) Behavior is undefined for non-null terminated 517 input or strings longer than 255 characters. 518 519 Note: If lpstr passed into TempStr is readonly, TempStr 520 will crash your XLL as it will try to modify a read only 521 string in place. strings declared on the stack as described below 522 are read only by default in VC++ 523 524 char *str = " I am a string" 525 526 Use extreme caution while calling TempStr on such strings. Refer to 527 VC++ documentation for complier options to ensure that these strings 528 are compiled as read write or use TempStrConst instead. 529 530 TempStr is provided mainly for backwards compatability and use of 531 TempStrConst is encouraged going forward. 532 */ 533 534 LPXLOPER TempStr(Flag!"autoFree" autoFree = Yes.autoFree)(LPSTR lpstr) 535 { 536 LPXLOPER lpx; 537 538 lpx = cast(LPXLOPER) GetTempMemory!autoFree(XLOPER.sizeof); 539 540 if (!lpx) 541 { 542 return null; 543 } 544 545 lpstr[0] = cast(BYTE) strlen (lpstr+1); 546 lpx.xltype = xltypeStr; 547 lpx.val.str = lpstr; 548 549 return lpx; 550 } 551 552 553 /** 554 TempStrConst() 555 556 Purpose: 557 Creates a temporary string XLOPER from a 558 const string with a local copy in temp memory 559 560 Parameters: 561 562 LPSTR lpstr The string, as a null-terminated 563 C string. This function will 564 count the bytes of the string 565 and insert that count in the 566 first byte of the temp string. 567 Excel cannot handle strings 568 longer than 255 characters. 569 570 Returns: 571 572 LPXLOPER The temporary XLOPER, or 0 573 if GetTempMemory() failed. 574 575 Comments: 576 577 Will take a string of the form "abc\0" and make a 578 temp XLOPER of the form "\003abc" 579 580 */ 581 582 LPXLOPER TempStrConst(Flag!"autoFree" autoFree = Yes.autoFree)(const LPSTR lpstr) 583 { 584 LPXLOPER lpx; 585 LPSTR lps; 586 size_t len; 587 588 len = strlen(lpstr); 589 590 lpx = cast(LPXLOPER) (GetTempMemory!autoFree(XLOPER.sizeof + len + 1)); 591 592 if (!lpx) 593 { 594 return null; 595 } 596 597 lps = cast(LPSTR)lpx + XLOPER.sizeof; 598 599 lps[0] = cast(BYTE)len; 600 //can't strcpy_s because of removal of null-termination 601 memcpy_s( cast(ubyte*)lps+1, cast(uint)len+1, cast(ubyte*)lpstr, cast(uint)len); 602 lpx.xltype = xltypeStr; 603 lpx.val.str = lps; 604 605 return lpx; 606 } 607 608 /** 609 TempStr12() 610 611 Purpose: 612 Creates a temporary string XLOPER12 from a 613 unicode const string with a local copy in 614 temp memory 615 616 Parameters: 617 618 wchar lpstr The string, as a null-terminated 619 unicode string. This function will 620 count the bytes of the string 621 and insert that count in the 622 first byte of the temp string. 623 624 Returns: 625 626 LPXLOPER12 The temporary XLOPER12, or 0 627 if GetTempMemory() failed. 628 629 Comments: 630 631 (1) Fix for const string pointers being passed in to TempStr. 632 Note it assumes NO leading space 633 634 (2) Also note that XLOPER12 now uses unicode for the string 635 operators 636 637 (3) Will remove the null-termination on the string 638 639 640 641 Note: TempStr12 is different from TempStr and is more like TempStrConst 642 in its behavior. We have consciously made this choice and deprecated the 643 behavior of TempStr going forward. Refer to the note in comment section 644 for TempStr to better understand this design decision. 645 */ 646 647 LPXLOPER12[] TempStr12(in wstring[] strings) 648 { 649 LPXLOPER12[] ret; 650 ret.length=strings.length; 651 foreach(i,str;strings) 652 ret[i]=strings[i].TempStr12; 653 return ret; 654 } 655 656 wchar* makePascalString(Flag!"autoFree" autoFree = Yes.autoFree)(wchar* str) 657 { 658 auto len=lstrlenW(str); 659 auto lpx=GetTempMemory!autoFree((len+1)*2); 660 if (lpx is null) 661 return null; 662 auto lps=cast(wchar*)(cast(CHAR*)lpx); 663 lps[0]=cast(BYTE)len; 664 wmemcpy_s( lps+1, len+1, str, len); 665 return lps; 666 } 667 668 wchar* makePascalString(Flag!"autoFree" autoFree = Yes.autoFree)(wstring str) 669 { 670 wchar* buf; 671 auto len=lstrlenW(str); 672 wchar* buf = GetTempMemory!autoFree((len + 1) * 2); 673 if (buf is null) 674 return null; 675 buf[0]=cast(wchar)len; 676 buf[1..len]=str[1..len]; 677 return buf; 678 } 679 680 LPXLOPER12 TempStr12(Flag!"autoFree" autoFree = Yes.autoFree)(wstring lpstr) 681 { 682 import xlld.memorymanager: GetTempMemory; 683 LPXLOPER12 lpx; 684 wchar* lps; 685 int len=cast(int)lpstr.length; 686 687 lpx = cast(LPXLOPER12) (GetTempMemory!autoFree(XLOPER12.sizeof + (len+1)*2)); 688 689 if (lpx is null) 690 { 691 return null; 692 } 693 694 lps = cast(wchar*)((cast(ubyte*)lpx + XLOPER12.sizeof)); 695 696 lps[0] = cast(wchar)len; 697 //can't wcscpy_s because of removal of null-termination 698 wmemcpy_s( lps+1, len+1, lpstr.ptr, len); 699 lpx.xltype = XlType.xltypeStr; 700 lpx.val.str = lps; 701 702 return lpx; 703 } 704 705 LPXLOPER12 TempStr12(Flag!"autoFree" autoFree = Yes.autoFree)(const(wchar*) lpstr) 706 { 707 LPXLOPER12 lpx; 708 wchar* lps; 709 int len; 710 711 len = lstrlenW(lpstr); 712 713 lpx = cast(LPXLOPER12) GetTempMemory!autoFree(XLOPER12.sizeof + (len+1)*2); 714 715 if (!lpx) 716 { 717 return null; 718 } 719 720 lps = cast(wchar*)((cast(CHAR*)lpx + XLOPER12.sizeof)); 721 722 lps[0] = cast(BYTE)len; 723 //can't wcscpy_s because of removal of null-termination 724 wmemcpy_s( lps+1, len+1, lpstr, len); 725 lpx.xltype = xltypeStr; 726 lpx.val.str = lps; 727 728 return lpx; 729 } 730 731 /** 732 TempBool() 733 734 Purpose: 735 Creates a temporary logical (true/false) XLOPER. 736 737 Parameters: 738 739 int b 0 - for a false XLOPER 740 Anything else - for a true XLOPER 741 742 Returns: 743 744 LPXLOPER The temporary XLOPER, or 0 745 if GetTempMemory() failed. 746 747 Comments: 748 */ 749 750 LPXLOPER TempBool(Flag!"autoFree" autoFree = Yes.autoFree)(int b) 751 { 752 LPXLOPER lpx; 753 754 lpx = cast(LPXLOPER) GetTempMemory!autoFree(XLOPER.sizeof); 755 756 if (!lpx) 757 { 758 return null; 759 } 760 761 lpx.xltype = xltypeBool; 762 lpx.val.bool_ = b?1:0; 763 return lpx; 764 } 765 766 /** 767 TempBool12() 768 769 Purpose: 770 Creates a temporary logical (true/false) XLOPER12. 771 772 Parameters: 773 774 BOOL b 0 - for a false XLOPER12 775 Anything else - for a true XLOPER12 776 777 Returns: 778 779 LPXLOPER12 The temporary XLOPER12, or 0 780 if GetTempMemory() failed. 781 782 Comments: 783 */ 784 785 LPXLOPER12 TempBool12(Flag!"autoFree" autoFree = Yes.autoFree)(BOOL b) 786 { 787 LPXLOPER12 lpx; 788 789 lpx = cast(LPXLOPER12) GetTempMemory!autoFree(XLOPER12.sizeof); 790 791 if (!lpx) 792 { 793 return cast(LPXLOPER12)0; 794 } 795 796 lpx.xltype = xltypeBool; 797 lpx.val.bool_ = b?1:0; 798 799 return lpx; 800 } 801 802 /** 803 TempInt() 804 805 Purpose: 806 Creates a temporary integer XLOPER. 807 808 Parameters: 809 810 short int i The integer 811 812 Returns: 813 814 LPXLOPER The temporary XLOPER, or 0 815 if GetTempMemory() failed. 816 817 Comments: 818 */ 819 820 LPXLOPER TempInt(Flag!"autoFree" autoFree = Yes.autoFree)(short i) 821 { 822 LPXLOPER lpx; 823 824 lpx = cast(LPXLOPER) GetTempMemory!autoFree(XLOPER.sizeof); 825 826 if (!lpx) 827 { 828 return cast(LPXLOPER)0; 829 } 830 831 lpx.xltype = xltypeInt; 832 lpx.val.w = i; 833 834 return lpx; 835 } 836 837 /** 838 TempInt12() 839 840 Purpose: 841 Creates a temporary integer XLOPER12. 842 843 Parameters: 844 845 int i The integer 846 847 Returns: 848 849 LPXLOPER12 The temporary XLOPER12, or 0 850 if GetTempMemory() failed. 851 852 Comments: 853 854 Note that the int oper has increased in size from 855 short int up to int in the 12 opers 856 */ 857 858 LPXLOPER12 TempInt12(Flag!"autoFree" autoFree = Yes.autoFree)(int i) 859 { 860 import xlld.memorymanager: GetTempMemory; 861 LPXLOPER12 lpx; 862 863 lpx = cast(LPXLOPER12) GetTempMemory!autoFree(XLOPER12.sizeof); 864 865 if (!lpx) 866 { 867 return cast(LPXLOPER12)0; 868 } 869 870 lpx.xltype = XlType.xltypeInt; 871 lpx.val.w = i; 872 873 return lpx; 874 } 875 876 /** 877 TempErr() 878 879 Purpose: 880 Creates a temporary error XLOPER. 881 882 Parameters: 883 884 WORD err The error code. One of the xlerr... 885 constants, as defined in XLCALL.H. 886 See the Excel user manual for 887 descriptions about the interpretation 888 of various error codes. 889 890 Returns: 891 892 LPXLOPER The temporary XLOPER, or 0 893 if GetTempMemory() failed. 894 895 Comments: 896 */ 897 898 LPXLOPER TempErr(Flag!"autoFree" autoFree = Yes.autoFree)(WORD err) 899 { 900 LPXLOPER lpx; 901 902 lpx = cast(LPXLOPER) GetTempMemory!autoFree(XLOPER.sizeof); 903 904 if (!lpx) 905 { 906 return null; 907 } 908 909 lpx.xltype = xltypeErr; 910 lpx.val.err = err; 911 912 return lpx; 913 } 914 915 /** 916 TempErr12() 917 918 Purpose: 919 Creates a temporary error XLOPER12. 920 921 Parameters: 922 923 int err The error code. One of the xlerr... 924 constants, as defined in XLCALL.H. 925 See the Excel user manual for 926 descriptions about the interpretation 927 of various error codes. 928 929 Returns: 930 931 LPXLOPER12 The temporary XLOPER12, or 0 932 if GetTempMemory() failed. 933 934 Comments: 935 936 Note the paramater has changed from a WORD to an int 937 in the new 12 operators 938 */ 939 940 LPXLOPER12 TempErr12(Flag!"autoFree" autoFree = Yes.autoFree)(int err) 941 { 942 LPXLOPER12 lpx; 943 944 lpx = cast(LPXLOPER12) GetTempMemory!autoFree(XLOPER12.sizeof); 945 946 if (!lpx) 947 { 948 return null; 949 } 950 951 lpx.xltype = xltypeErr; 952 lpx.val.err = err; 953 954 return lpx; 955 } 956 957 /** 958 TempActiveRef() 959 960 Purpose: 961 Creates a temporary rectangular reference to the active 962 sheet. Remember that the active sheet is the sheet that 963 the user sees in front, not the sheet that is currently 964 being calculated. 965 966 Parameters: 967 968 WORD rwFirst (0 based) The first row in the rectangle. 969 WORD rwLast (0 based) The last row in the rectangle. 970 BYTE colFirst (0 based) The first column in the rectangle. 971 BYTE colLast (0 based) The last column in the rectangle. 972 973 Returns: 974 975 LPXLOPER The temporary XLOPER, or 0 976 if GetTempMemory() failed. 977 978 Comments: 979 */ 980 LPXLOPER TempActiveRef(Flag!"autoFree" autoFree = Yes.autoFree)(WORD rwFirst, WORD rwLast, BYTE colFirst, BYTE colLast) 981 { 982 import xlld.memorymanager: allocator; 983 LPXLOPER lpx; 984 LPXLMREF lpmref; 985 int wRet; 986 987 lpx = cast(LPXLOPER) GetTempMemory!autoFree(XLOPER.sizeof); 988 lpmref = cast(LPXLMREF) GetTempMemory!autoFree(XLMREF.sizeof); 989 990 if(!lpmref) { 991 freePointer(lpx); 992 return null; 993 } 994 995 /* calling Excel() instead of Excel4() would free all temp memory! */ 996 wRet = Excel4(xlSheetId, lpx, 0); 997 998 if (wRet != xlretSuccess) 999 { 1000 freePointer(lmref); 1001 freePointer(lpx); 1002 return null; 1003 } 1004 else 1005 { 1006 lpx.xltype = xltypeRef; 1007 lpx.val.mref.lpmref = lpmref; 1008 lpmref.count = 1; 1009 lpmref.reftbl[0].rwFirst = rwFirst; 1010 lpmref.reftbl[0].rwLast = rwLast; 1011 lpmref.reftbl[0].colFirst = colFirst; 1012 lpmref.reftbl[0].colLast = colLast; 1013 1014 return lpx; 1015 } 1016 } 1017 1018 private void freePointer(Flag!"autoFree" autoFree = Yes.autoFree)(void* ptr) { 1019 import xlld.memorymanager: allocator; 1020 static if(autoFree) 1021 FreeAllTempMemory; 1022 else 1023 allocator.dispose(ptr); 1024 } 1025 1026 1027 /** 1028 TempActiveRef12() 1029 1030 Purpose: 1031 Creates a temporary rectangular reference to the active 1032 sheet. Remember that the active sheet is the sheet that 1033 the user sees in front, not the sheet that is currently 1034 being calculated. 1035 1036 Parameters: 1037 1038 RW rwFirst (0 based) The first row in the rectangle. 1039 RW rwLast (0 based) The last row in the rectangle. 1040 COL colFirst (0 based) The first column in the rectangle. 1041 COL colLast (0 based) The last column in the rectangle. 1042 1043 Returns: 1044 1045 LPXLOPER12 The temporary XLOPER12, or 0 1046 if GetTempMemory() failed. 1047 1048 Comments: 1049 1050 Note that the formal parameters have changed for Excel 2007 1051 The valid size has increased to accomodate the increase 1052 in Excel 2007 workbook sizes 1053 */ 1054 1055 LPXLOPER12 TempActiveRef12(Flag!"autoFree" autoFree = Yes.autoFree)(RW rwFirst,RW rwLast,COL colFirst,COL colLast) 1056 { 1057 LPXLOPER12 lpx; 1058 LPXLMREF12 lpmref; 1059 int wRet; 1060 1061 lpx = cast(LPXLOPER12) GetTempMemory!autoFree(XLOPER12.sizeof); 1062 lpmref = cast(LPXLMREF12) GetTempMemory!autoFree(XLMREF12.sizeof); 1063 1064 if (!lpmref) { 1065 freePointer(lpx); 1066 return null; 1067 } 1068 1069 /* calling Excel12f() instead of Excel12() would free all temp memory! */ 1070 wRet = Excel12(xlSheetId, lpx, []); 1071 1072 if (wRet != xlretSuccess) 1073 { 1074 freePointer(lpmref); 1075 freePointer(lpx); 1076 return null; 1077 } 1078 else 1079 { 1080 lpx.xltype = xltypeRef; 1081 lpx.val.mref.lpmref = cast(LPXLMREF12)lpmref; 1082 lpmref.count = 1; 1083 lpmref.reftbl[0].rwFirst = rwFirst; 1084 lpmref.reftbl[0].rwLast = rwLast; 1085 lpmref.reftbl[0].colFirst = colFirst; 1086 lpmref.reftbl[0].colLast = colLast; 1087 1088 return lpx; 1089 } 1090 } 1091 1092 /** 1093 TempActiveCell() 1094 1095 Purpose: 1096 Creates a temporary reference to a single cell on the active 1097 sheet. Remember that the active sheet is the sheet that 1098 the user sees in front, not the sheet that is currently 1099 being calculated. 1100 1101 Parameters: 1102 1103 WORD rw (0 based) The row of the cell. 1104 BYTE col (0 based) The column of the cell. 1105 1106 Returns: 1107 1108 LPXLOPER The temporary XLOPER, or 0 1109 if GetTempMemory() failed. 1110 1111 Comments: 1112 */ 1113 1114 1115 LPXLOPER TempActiveCell(Flag!"autoFree" autoFree = Yes.autoFree)(WORD rw, BYTE col) 1116 { 1117 return TempActiveRef!autoFree(rw, rw, col, col); 1118 } 1119 1120 /** 1121 TempActiveCell12() 1122 1123 Purpose: 1124 Creates a temporary reference to a single cell on the active 1125 sheet. Remember that the active sheet is the sheet that 1126 the user sees in front, not the sheet that is currently 1127 being calculated. 1128 1129 Parameters: 1130 1131 RW rw (0 based) The row of the cell. 1132 COL col (0 based) The column of the cell. 1133 1134 Returns: 1135 1136 LPXLOPER12 The temporary XLOPER12, or 0 1137 if GetTempMemory() failed. 1138 1139 Comments: 1140 1141 Paramter types changed to RW and COL to accomodate the increase 1142 in sheet sizes introduced in Excel 2007 1143 */ 1144 1145 LPXLOPER12 TempActiveCell12(Flag!"autoFree" autoFree = Yes.autoFree)(RW rw, COL col) 1146 { 1147 return TempActiveRef12!autoFree(rw, rw, col, col); 1148 } 1149 1150 /** 1151 TempActiveRow() 1152 1153 Purpose: 1154 Creates a temporary reference to an entire row on the active 1155 sheet. Remember that the active sheet is the sheet that 1156 the user sees in front, not the sheet that is currently 1157 being calculated. 1158 1159 Parameters: 1160 1161 RW rw (0 based) The row. 1162 1163 Returns: 1164 1165 LPXLOPER The temporary XLOPER, or 0 1166 if GetTempMemory() failed. 1167 1168 Comments: 1169 */ 1170 1171 LPXLOPER TempActiveRow(Flag!"autoFree" autoFree = Yes.autoFree)(WORD rw) 1172 { 1173 return TempActiveRef!autoFree(rw, rw, 0, 0xFF); 1174 } 1175 1176 /** 1177 TempActiveRow12() 1178 1179 Purpose: 1180 Creates a temporary reference to an entire row on the active 1181 sheet. Remember that the active sheet is the sheet that 1182 the user sees in front, not the sheet that is currently 1183 being calculated. 1184 1185 Parameters: 1186 1187 RW rw (0 based) The row. 1188 1189 Returns: 1190 1191 LPXLOPER12 The temporary XLOPER12, or 0 1192 if GetTempMemory() failed. 1193 1194 Comments: 1195 1196 Paramter type change to RW to accomodate the increase in sheet 1197 sizes introduced in Excel 2007 1198 */ 1199 1200 LPXLOPER12 TempActiveRow12(Flag!"autoFree" autoFree = Yes.autoFree)(RW rw) 1201 { 1202 return TempActiveRef12!autoFree(rw, rw, 0, 0x00003FFF); 1203 } 1204 1205 /** 1206 TempActiveColumn() 1207 1208 Purpose: 1209 Creates a temporary reference to an entire column on the active 1210 sheet. Remember that the active sheet is the sheet that 1211 the user sees in front, not the sheet that is currently 1212 being calculated. 1213 1214 Parameters: 1215 1216 LPSTR s First string 1217 LPSTR t Second string 1218 1219 Returns: 1220 1221 LPXLOPER The temporary XLOPER, or 0 1222 if GetTempMemory() failed. 1223 1224 Comments: 1225 1226 */ 1227 1228 LPXLOPER TempActiveColumn(Flag!"autoFree" autoFree = Yes.autoFree)(BYTE col) 1229 { 1230 return TempActiveRef!autoFree(0, 0xFFFF, col, col); 1231 } 1232 1233 /** 1234 TempActiveColumn12() 1235 1236 Purpose: 1237 Creates a temporary reference to an entire column on the active 1238 sheet. Remember that the active sheet is the sheet that 1239 the user sees in front, not the sheet that is currently 1240 being calculated. 1241 1242 Parameters: 1243 1244 COL col (0 based) The column. 1245 1246 Returns: 1247 1248 LPXLOPER12 The temporary XLOPER12, or 0 1249 if GetTempMemory() failed. 1250 1251 Comments: 1252 1253 Paramter type change to COL to accomodate the increase in sheet 1254 sizes introduced in Excel 2007 1255 1256 */ 1257 1258 LPXLOPER12 TempActiveColumn12(Flag!"autoFree" autoFree = Yes.autoFree)(COL col) 1259 { 1260 return TempActiveRef12!autoFree(0, 0x000FFFFF, col, col); 1261 } 1262 1263 1264 /** 1265 TempMissing() 1266 1267 Purpose: 1268 This is used to simulate a missing argument when 1269 calling Excel(). It creates a temporary 1270 "missing" XLOPER. 1271 1272 Parameters: 1273 1274 Returns: 1275 1276 LPXLOPER The temporary XLOPER, or 0 1277 if GetTempMemory() failed. 1278 1279 Comments: 1280 1281 */ 1282 1283 LPXLOPER TempMissing(Flag!"autoFree" autoFree = Yes.autoFree)() 1284 { 1285 LPXLOPER lpx; 1286 1287 lpx = cast(LPXLOPER) GetTempMemory!autoFree(XLOPER.sizeof); 1288 1289 if (!lpx) 1290 { 1291 return null; 1292 } 1293 1294 lpx.xltype = xltypeMissing; 1295 1296 return lpx; 1297 } 1298 1299 /** 1300 TempMissing12() 1301 1302 Purpose: 1303 This is used to simulate a missing argument when 1304 calling Excel12f(). It creates a temporary 1305 "missing" XLOPER12. 1306 1307 Parameters: 1308 1309 Returns: 1310 1311 LPXLOPER12 The temporary XLOPER12, or 0 1312 if GetTempMemory() failed. 1313 1314 Comments: 1315 1316 */ 1317 1318 LPXLOPER12 TempMissing12(Flag!"autoFree" autoFree = Yes.autoFree)() 1319 { 1320 LPXLOPER12 lpx; 1321 1322 lpx = cast(LPXLOPER12) GetTempMemory!autoFree(XLOPER12.sizeof); 1323 1324 if (!lpx) 1325 { 1326 return null; 1327 } 1328 1329 lpx.xltype = xltypeMissing; 1330 1331 return lpx; 1332 } 1333 1334 1335 1336 /** 1337 ConvertXLRefToXLRef12() 1338 1339 Purpose: 1340 Will attempt to convert an XLREF into the given XREF12 1341 1342 Parameters: 1343 1344 LPXLREF pxref Pointer to the XLREF to copy 1345 LPXLREF12 pxref12 Pointer to the XLREF12 to copy into 1346 1347 Returns: 1348 1349 BOOL true if the conversion succeeded, false otherwise 1350 1351 Comments: 1352 1353 */ 1354 1355 1356 BOOL ConvertXLRefToXLRef12(LPXLREF pxref, LPXLREF12 pxref12) 1357 { 1358 if (pxref.rwLast >= pxref.rwFirst && pxref.colLast >= pxref.colFirst) 1359 { 1360 if (pxref.rwFirst >= 0 && pxref.colFirst >= 0) 1361 { 1362 pxref12.rwFirst = pxref.rwFirst; 1363 pxref12.rwLast = pxref.rwLast; 1364 pxref12.colFirst = pxref.colFirst; 1365 pxref12.colLast = pxref.colLast; 1366 return true; 1367 } 1368 } 1369 return false; 1370 } 1371 1372 /** 1373 ConvertXLRef12ToXLRef() 1374 1375 Purpose: 1376 Will attempt to convert an XLREF12 into the given XLREF 1377 1378 Parameters: 1379 1380 LPXLREF12 pxref12 Pointer to the XLREF12 to copy 1381 LPXLREF pxref Pointer to the XLREF to copy into 1382 1383 Returns: 1384 1385 BOOL true if the conversion succeeded, false otherwise 1386 1387 Comments: 1388 1389 */ 1390 1391 BOOL ConvertXLRef12ToXLRef(LPXLREF12 pxref12, LPXLREF pxref) 1392 { 1393 if (pxref12.rwLast >= pxref12.rwFirst && pxref12.colLast >= pxref12.colFirst) 1394 { 1395 if (pxref12.rwFirst >=0 && pxref12.colFirst >= 0) 1396 { 1397 if (pxref12.rwLast < rwMaxO8 && pxref12.colLast < colMaxO8) 1398 { 1399 pxref.rwFirst = cast(WORD)pxref12.rwFirst; 1400 pxref.rwLast = cast(WORD)pxref12.rwLast; 1401 pxref.colFirst = cast(BYTE)pxref12.colFirst; 1402 pxref.colLast = cast(BYTE)pxref12.colLast; 1403 return true; 1404 } 1405 } 1406 } 1407 return false; 1408 } 1409 1410 /** 1411 XLOper12ToXLOper() 1412 1413 Purpose: 1414 Conversion routine used to convert from the new XLOPER12 1415 to the old XLOPER. 1416 1417 Parameters: 1418 1419 LPXLOPER12 pxloper12 Pointer to the XLOPER12 to copy 1420 LPXLOPER pxloper Pointer to the XLOPER to copy into 1421 1422 Returns: 1423 1424 BOOL true if the conversion succeeded, false otherwise 1425 1426 Comments: 1427 1428 - The caller is responsible for freeing any memory associated with 1429 the copy if the conversion is a success; FreeXOperT can be 1430 used, or it may be done by hand. 1431 1432 - If the conversion fails, any memory the method needed to malloc 1433 up until the point of failure in the conversion will be freed 1434 by the method itself during cleanup. 1435 */ 1436 1437 BOOL XLOper12ToXLOper(LPXLOPER12 pxloper12, LPXLOPER pxloper) 1438 { 1439 import core.stdc.stdlib: malloc,free; 1440 1441 BOOL fRet; 1442 BOOL fClean; 1443 //DWORD xltype; 1444 WORD cref; 1445 int cxloper12; 1446 RW crw; 1447 COL ccol; 1448 long cbyte; 1449 wchar *st; 1450 char *ast; 1451 int cch; 1452 char cach; 1453 BYTE *pbyte; 1454 LPXLMREF pmref; 1455 LPXLREF12 pref12; 1456 LPXLREF rgref; 1457 LPXLREF pref; 1458 LPXLOPER rgxloperConv; 1459 LPXLOPER pxloperConv; 1460 LPXLOPER12 pxloper12Conv; 1461 1462 fClean = false; 1463 fRet = true; 1464 auto xltype = pxloper12.xltype; 1465 1466 switch (xltype) with(XlType) 1467 { 1468 case xltypeNum: 1469 pxloper.val.num = pxloper12.val.num; 1470 break; 1471 case xltypeBool: 1472 pxloper.val.bool_ = cast(typeof(pxloper.val.bool_))pxloper12.val.bool_; 1473 break; 1474 case xltypeErr: 1475 if (pxloper12.val.err > MAXWORD) 1476 { 1477 fRet = false; 1478 // problem... overflow 1479 } 1480 else 1481 { 1482 pxloper.val.err = cast(WORD)pxloper12.val.err; 1483 } 1484 break; 1485 case xltypeMissing: 1486 case xltypeNil: 1487 break; 1488 case xltypeInt: 1489 if ((pxloper12.val.w + MAXSHORTINT + 1) >> 16) 1490 { 1491 pxloper.val.num = cast(float)pxloper12.val.w; 1492 xltype = xltypeNum; 1493 } 1494 else 1495 { 1496 pxloper.val.w = cast(short)pxloper12.val.w; 1497 } 1498 break; 1499 case xltypeStr: 1500 st = pxloper12.val.str; 1501 cch = st[0]; 1502 cach = cast(BYTE)cch; 1503 1504 if (cch > cchMaxStz || cch < 0) 1505 { 1506 fRet = false; 1507 } 1508 else 1509 { 1510 ast = cast(char*)malloc((cach + 2) * char.sizeof); 1511 if (ast is null) 1512 { 1513 fRet = false; 1514 } 1515 else 1516 { 1517 WideCharToMultiByte(CP_ACP, 0, st + 1, cch, ast + 1, cach, null, null); 1518 ast[0] = cach; 1519 ast[cach + 1] = '\0'; 1520 pxloper.val.str = ast; 1521 } 1522 } 1523 break; 1524 case xltypeFlow: 1525 if (pxloper12.val.flow.rw > rwMaxO8 || pxloper12.val.flow.col > colMaxO8) 1526 { 1527 fRet = false; 1528 } 1529 else 1530 { 1531 pxloper.val.flow.rw = cast(WORD)pxloper12.val.flow.rw; 1532 pxloper.val.flow.col = cast(BYTE)pxloper12.val.flow.col; 1533 pxloper.val.flow.xlflow = pxloper12.val.flow.xlflow; 1534 pxloper.val.flow.valflow.idSheet = pxloper12.val.flow.valflow.idSheet; 1535 } 1536 break; 1537 case xltypeRef: 1538 if (pxloper12.val.mref.lpmref && pxloper12.val.mref.lpmref.count > 0) 1539 { 1540 pref12 = pxloper12.val.mref.lpmref.reftbl; 1541 cref = pxloper12.val.mref.lpmref.count; 1542 1543 pmref = cast(LPXLMREF) (malloc(XLMREF.sizeof) + XLREF.sizeof*(cref-1)); 1544 if (pmref is null) 1545 { 1546 fRet = false; 1547 } 1548 else 1549 { 1550 pmref.count = cref; 1551 rgref = pmref.reftbl; 1552 pref = rgref; 1553 while (cref > 0 && !fClean) 1554 { 1555 if (!ConvertXLRef12ToXLRef(pref12, pref)) 1556 { 1557 fClean = true; 1558 cref = 0; 1559 } 1560 else 1561 { 1562 pref++; 1563 pref12++; 1564 cref--; 1565 } 1566 } 1567 if (fClean) 1568 { 1569 free(pmref); 1570 fRet = false; 1571 } 1572 else 1573 { 1574 pxloper.val.mref.lpmref = pmref; 1575 pxloper.val.mref.idSheet = pxloper12.val.mref.idSheet; 1576 } 1577 } 1578 } 1579 else 1580 { 1581 xltype = xltypeMissing; 1582 } 1583 break; 1584 case xltypeSRef: 1585 if (pxloper12.val.sref.count != 1) 1586 { 1587 fRet = false; 1588 } 1589 else if (ConvertXLRef12ToXLRef(&pxloper12.val.sref.ref_, &pxloper.val.sref.ref_)) 1590 { 1591 pxloper.val.sref.count = 1; 1592 } 1593 else 1594 { 1595 fRet = false; 1596 } 1597 break; 1598 case xltypeMulti: 1599 crw = pxloper12.val.array.rows; 1600 ccol = pxloper12.val.array.columns; 1601 if (crw > rwMaxO8 || ccol > colMaxO8) 1602 { 1603 fRet = false; 1604 } 1605 else 1606 { 1607 cxloper12 = crw * ccol; 1608 if (cxloper12 == 0) 1609 { 1610 xltype = xltypeMissing; 1611 } 1612 else 1613 { 1614 rgxloperConv = cast(typeof(rgxloperConv))malloc(cxloper12 * XLOPER.sizeof); 1615 if (rgxloperConv is null) 1616 { 1617 fRet = false; 1618 } 1619 else 1620 { 1621 pxloperConv = rgxloperConv; 1622 pxloper12Conv = pxloper12.val.array.lparray; 1623 while (cxloper12 > 0 && !fClean) 1624 { 1625 if (!XLOper12ToXLOper(pxloper12Conv, pxloperConv)) 1626 { 1627 fClean = true; 1628 cxloper12 = 0; 1629 } 1630 else 1631 { 1632 pxloperConv++; 1633 pxloper12Conv++; 1634 cxloper12--; 1635 } 1636 } 1637 if (fClean) 1638 { 1639 fRet = false; 1640 while (pxloperConv > rgxloperConv) 1641 { 1642 FreeXLOper(pxloperConv); 1643 pxloperConv--; 1644 } 1645 free(rgxloperConv); 1646 } 1647 else 1648 { 1649 pxloper.val.array.lparray = rgxloperConv; 1650 pxloper.val.array.rows = cast(typeof(pxloper.val.array.rows))crw; 1651 pxloper.val.array.columns = cast(typeof(pxloper.val.array.columns))ccol; 1652 } 1653 } 1654 } 1655 } 1656 break; 1657 case xltypeBigData: 1658 cbyte = pxloper12.val.bigdata.cbData; 1659 if (pxloper12.val.bigdata.h.lpbData !is null && cbyte > 0) 1660 { 1661 pbyte = cast(BYTE *)malloc(cast(uint)cbyte); 1662 if (pbyte !is null) 1663 { 1664 memcpy_s(pbyte, cast(uint)cbyte, pxloper12.val.bigdata.h.lpbData, cast(uint)cbyte); 1665 pxloper.val.bigdata.h.lpbData = pbyte; 1666 pxloper.val.bigdata.cbData = cbyte; 1667 } 1668 else 1669 { 1670 fRet = false; 1671 } 1672 } 1673 else 1674 { 1675 fRet = false; 1676 } 1677 break; 1678 default: 1679 break; 1680 } 1681 if (fRet) 1682 { 1683 pxloper.xltype = cast(WORD)xltype; 1684 } 1685 return fRet; 1686 } 1687 1688 /** 1689 XLOperToXLOper12() 1690 1691 Purpose: 1692 Conversion routine used to convert from the old XLOPER 1693 to the new XLOPER12. 1694 1695 Parameters: 1696 1697 LPXLOPER pxloper Pointer to the XLOPER to copy 1698 LPXLOPER12 pxloper12 Pointer to the XLOPER12 to copy into 1699 1700 Returns: 1701 1702 BOOL true if the conversion succeeded, false otherwise 1703 1704 Comments: 1705 1706 - The caller is responsible for freeing any memory associated with 1707 the copy if the conversion is a success; FreeXLOper12T can be 1708 used, or it may be done by hand. 1709 1710 - If the conversion fails, any memory the method needed to malloc 1711 up until the point of failure in the conversion will be freed 1712 by the method itself during cleanup. 1713 1714 */ 1715 1716 1717 BOOL XLOperToXLOper12(LPXLOPER pxloper, LPXLOPER12 pxloper12) 1718 { 1719 import core.stdc.stdlib: malloc,free; 1720 1721 BOOL fRet; 1722 BOOL fClean; 1723 WORD crw; 1724 WORD ccol; 1725 WORD cxloper; 1726 WORD cref12; 1727 BYTE *pbyte; 1728 char *ast; 1729 wchar *st; 1730 int cach; 1731 int cch; 1732 long cbyte; 1733 LPXLREF pref; 1734 LPXLREF12 pref12; 1735 LPXLREF12 rgref12; 1736 LPXLMREF12 pmref12; 1737 LPXLOPER pxloperConv; 1738 LPXLOPER12 rgxloper12Conv; 1739 LPXLOPER12 pxloper12Conv; 1740 1741 fClean = false; 1742 fRet = true; 1743 auto xltype = pxloper.xltype; 1744 1745 switch (xltype) with(XlType) 1746 { 1747 case xltypeNum: 1748 pxloper12.val.num = pxloper.val.num; 1749 break; 1750 case xltypeBool: 1751 pxloper12.val.bool_ = pxloper.val.bool_; 1752 break; 1753 case xltypeErr: 1754 pxloper12.val.err = cast(int)pxloper.val.err; 1755 break; 1756 case xltypeMissing: 1757 case xltypeNil: 1758 break; 1759 case xltypeInt: 1760 pxloper12.val.w = pxloper.val.w; 1761 break; 1762 case xltypeStr: 1763 ast = pxloper.val.str; 1764 if (ast is null) 1765 { 1766 fRet = false; 1767 } 1768 else 1769 { 1770 cach = ast[0]; 1771 cch = cach; 1772 if (cach > cchMaxStz || cach < 0) 1773 { 1774 fRet = false; 1775 } 1776 else 1777 { 1778 st = cast(wchar*) malloc((cch + 2) * wchar.sizeof); 1779 if (st is null) 1780 { 1781 fRet = false; 1782 } 1783 else 1784 { 1785 MultiByteToWideChar(CP_ACP, 0, ast + 1, cach, st + 1, cch); 1786 st[0] = cast(wchar) cch; 1787 st[cch + 1] = '\0'; 1788 pxloper12.val.str = st; 1789 } 1790 } 1791 } 1792 break; 1793 case xltypeFlow: 1794 pxloper12.val.flow.rw = pxloper.val.flow.rw; 1795 pxloper12.val.flow.col = pxloper.val.flow.col; 1796 pxloper12.val.flow.xlflow = pxloper.val.flow.xlflow; 1797 break; 1798 case xltypeRef: 1799 if (pxloper.val.mref.lpmref && pxloper.val.mref.lpmref.count > 0) 1800 { 1801 pref = pxloper.val.mref.lpmref.reftbl; 1802 cref12 = pxloper.val.mref.lpmref.count; 1803 1804 auto tmp = XLMREF12.sizeof + XLREF12.sizeof*(cref12-1); 1805 pmref12 = cast(LPXLMREF12) malloc(tmp)[0..tmp]; 1806 if (pmref12 is cast(typeof(pmref12))0) 1807 { 1808 fRet = false; 1809 } 1810 else 1811 { 1812 pmref12.count = cref12; 1813 rgref12 = pmref12.reftbl; 1814 pref12 = rgref12; 1815 while (cref12 > 0 && !fClean) 1816 { 1817 if (!ConvertXLRefToXLRef12(pref, pref12)) 1818 { 1819 fClean = true; 1820 cref12 = 0; 1821 } 1822 else 1823 { 1824 pref++; 1825 pref12++; 1826 cref12--; 1827 } 1828 } 1829 if (fClean) 1830 { 1831 free(cast(void*)pmref12); 1832 fRet = false; 1833 } 1834 else 1835 { 1836 pxloper12.val.mref.lpmref = cast(typeof(pxloper12.val.mref.lpmref ))pmref12; 1837 pxloper12.val.mref.idSheet = pxloper.val.mref.idSheet; 1838 } 1839 } 1840 } 1841 else 1842 { 1843 xltype = xltypeMissing; 1844 } 1845 break; 1846 case xltypeSRef: 1847 if (pxloper.val.sref.count != 1) 1848 { 1849 fRet = false; 1850 } 1851 else if (ConvertXLRefToXLRef12(&pxloper.val.sref.ref_, &pxloper12.val.sref.ref_)) 1852 { 1853 pxloper12.val.sref.count = 1; 1854 } 1855 else 1856 { 1857 fRet = false; 1858 } 1859 break; 1860 case xltypeMulti: 1861 crw = pxloper.val.array.rows; 1862 ccol = pxloper.val.array.columns; 1863 if (crw > rwMaxO8 || ccol > colMaxO8) 1864 { 1865 fRet = false; 1866 } 1867 else 1868 { 1869 cxloper = cast(typeof(cxloper))(crw * ccol); 1870 if (cxloper == 0) 1871 { 1872 xltype = xltypeMissing; 1873 } 1874 else 1875 { 1876 rgxloper12Conv = cast(typeof(rgxloper12Conv))malloc(cast(uint)(cxloper * XLOPER12.sizeof))[0..cxloper*XLOPER12.sizeof]; 1877 if (rgxloper12Conv is null) 1878 { 1879 fRet = false; 1880 } 1881 else 1882 { 1883 pxloper12Conv = rgxloper12Conv; 1884 pxloperConv = pxloper.val.array.lparray; 1885 while (cxloper > 0 && !fClean) 1886 { 1887 if (!XLOperToXLOper12(pxloperConv, pxloper12Conv)) 1888 { 1889 fClean = true; 1890 cxloper = 0; 1891 } 1892 else 1893 { 1894 pxloperConv++; 1895 pxloper12Conv++; 1896 cxloper--; 1897 } 1898 } 1899 if (fClean) 1900 { 1901 fRet = false; 1902 while (pxloper12Conv > rgxloper12Conv) 1903 { 1904 FreeXLOper(pxloperConv); 1905 pxloperConv--; 1906 } 1907 free(rgxloper12Conv); 1908 } 1909 else 1910 { 1911 pxloper12.val.array.lparray = rgxloper12Conv; 1912 pxloper12.val.array.rows = crw; 1913 pxloper12.val.array.columns = ccol; 1914 } 1915 } 1916 } 1917 } 1918 break; 1919 case xltypeBigData: 1920 cbyte = pxloper.val.bigdata.cbData; 1921 if (pxloper.val.bigdata.h.lpbData !is null && cbyte > 0) 1922 { 1923 pbyte = cast(BYTE *)malloc(cast(uint)cbyte); 1924 if (pbyte !is null) 1925 { 1926 memcpy_s(cast(ubyte*)pbyte, cast(uint)cbyte, cast(ubyte*)pxloper.val.bigdata.h.lpbData, cast(uint)cbyte); 1927 pxloper12.val.bigdata.h.lpbData = pbyte; 1928 pxloper12.val.bigdata.cbData = cbyte; 1929 } 1930 else 1931 { 1932 fRet = false; 1933 } 1934 } 1935 else 1936 { 1937 fRet = false; 1938 } 1939 break; 1940 default: 1941 break; 1942 } 1943 1944 if (fRet) 1945 { 1946 pxloper12.xltype = cast(XlType)xltype; 1947 } 1948 return fRet; 1949 } 1950 1951 1952 1953 /** 1954 memcpy_s.c - contains memcpy_s routine 1955 1956 1957 Purpose: 1958 memcpy_s() copies a source memory buffer to a destination buffer. 1959 Overlapping buffers are not treated specially, so propagation may occur. 1960 *******************************************************************************/ 1961 1962 1963 /*** 1964 *memcpy_s - Copy source buffer to destination buffer 1965 * 1966 *Purpose: 1967 * memcpy_s() copies a source memory buffer to a destination memory buffer. 1968 * This routine does NOT recognize overlapping buffers, and thus can lead 1969 * to propagation. 1970 * 1971 * For cases where propagation must be avoided, memmove_s() must be used. 1972 * 1973 *Entry: 1974 * void *dst = pointer to destination buffer 1975 * size_t sizeInBytes = size in bytes of the destination buffer 1976 * const void *src = pointer to source buffer 1977 * size_t count = number of bytes to copy 1978 * 1979 *Exit: 1980 * Returns 0 if everything is ok, else return the error code. 1981 * 1982 *Exceptions: 1983 * Input parameters are validated. Refer to the validation section of the function. 1984 * On error, the error code is returned and the destination buffer is zeroed. 1985 * 1986 *******************************************************************************/ 1987 1988 int memcpy_s(ubyte * dst, size_t sizeInBytes, const ubyte * src, size_t count) 1989 { 1990 import core.stdc.string: memset, memcpy; 1991 1992 if (count == 0) 1993 return 0; 1994 1995 /* validation section */ 1996 if(dst !is null) 1997 return -1; 1998 if (src is null || sizeInBytes < count) 1999 { 2000 memset(dst, 0, sizeInBytes); 2001 if(src is null) 2002 return -1; 2003 if(sizeInBytes>=count) 2004 return -1; 2005 return -1; 2006 } 2007 2008 memcpy(dst, src, count); 2009 return 0; 2010 } 2011 2012 2013 int wmemcpy_s(wchar* dst, size_t numElements, const wchar* src, size_t count) 2014 { 2015 import core.stdc.string: memset, memcpy; 2016 2017 auto sizeInBytes=numElements*wchar.sizeof; 2018 count=count*2; 2019 if (count == 0) 2020 return 0; 2021 2022 /* validation section */ 2023 if(dst is null) 2024 return -1; 2025 if (src is null || sizeInBytes < count) 2026 { 2027 memset(dst, 0, sizeInBytes); 2028 if(src is null) 2029 return -1; 2030 if(sizeInBytes>=count) 2031 return -1; 2032 return -1; 2033 } 2034 2035 memcpy(dst, src, count); 2036 return 0; 2037 } 2038 2039 2040 extern(Windows) short CallerExample() 2041 { 2042 XLOPER12 xRes; 2043 2044 Excel12(xlfCaller, &xRes, []); 2045 Excel12(xlcSelect, cast(LPXLOPER12)0, [cast(LPXLOPER12)&xRes]); 2046 Excel12(xlFree, cast(LPXLOPER12)0, [cast(LPXLOPER12)&xRes]); 2047 return 1; 2048 }