PROFILE.CPP (29170B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/PROFILE.CPP 1 3/03/97 10:25a Joe_bostic $ */ 17 /*********************************************************************************************** 18 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : PROFILE.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : September 10, 1993 * 28 * * 29 * Last Update : September 10, 1993 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * WWGetPrivateProfileInt -- Fetches integer value from INI. * 34 * WWGetPrivateProfileString -- Fetch string from INI. * 35 * WWWritePrivateProfileInt -- Write a profile int to the profile data block. * 36 * WWWritePrivateProfileString -- Write a string to the profile data block. * 37 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 38 39 #include "function.h" 40 41 42 static char * WriteBinBuffer = NULL; 43 static int WriteBinBufferLen = 0; 44 static int WriteBinBufferPos = 0; 45 static int WriteBinBufferMax = 0; 46 static char * ReadBinBuffer = NULL; 47 static int ReadBinBufferLen = 0; 48 static int ReadBinBufferPos = 0; 49 static int ReadBinBufferMax = 0; 50 51 52 /*************************************************************************** 53 * Read_Private_Config_Struct -- Fetches override integer value. * 54 * * 55 * INPUT: * 56 * OUTPUT: * 57 * WARNINGS: * 58 * HISTORY: * 59 * 08/05/1992 JLB : Created. * 60 *=========================================================================*/ 61 bool Read_Private_Config_Struct(FileClass & file, NewConfigType * config) 62 { 63 INIClass ini; 64 ini.Load(file); 65 66 config->DigitCard = ini.Get_Hex("Sound", "Card", 0); 67 config->IRQ = ini.Get_Int("Sound", "IRQ", 0); 68 config->DMA = ini.Get_Int("Sound", "DMA", 0); 69 config->Port = ini.Get_Hex("Sound", "Port", 0); 70 config->BitsPerSample= ini.Get_Int("Sound", "BitsPerSample", 0); 71 config->Channels = ini.Get_Int("Sound", "Channels", 0); 72 config->Reverse = ini.Get_Int("Sound", "Reverse", 0); 73 config->Speed = ini.Get_Int("Sound", "Speed", 0); 74 ini.Get_String("Language", "Language", NULL, config->Language, sizeof(config->Language)); 75 76 77 // config->DigitCard = WWGetPrivateProfileHex("Sound", "Card", profile); 78 // config->IRQ = WWGetPrivateProfileInt("Sound", "IRQ", 0,profile); 79 // config->DMA = WWGetPrivateProfileInt("Sound", "DMA", 0,profile); 80 // config->Port = WWGetPrivateProfileHex("Sound", "Port", profile); 81 // config->BitsPerSample= WWGetPrivateProfileInt("Sound", "BitsPerSample",0,profile); 82 // config->Channels = WWGetPrivateProfileInt("Sound", "Channels", 0,profile); 83 // config->Reverse = WWGetPrivateProfileInt("Sound", "Reverse", 0,profile); 84 // config->Speed = WWGetPrivateProfileInt("Sound", "Speed", 0,profile); 85 // WWGetPrivateProfileString("Language", "Language", NULL, config->Language, 3, profile); 86 87 return((config->DigitCard == 0) && (config->IRQ == 0) && (config->DMA == 0)); 88 } 89 90 91 /*************************************************************************** 92 * Get_Private_Profile_Hex -- Fetches override integer value. * 93 * * 94 * INPUT: * 95 * OUTPUT: * 96 * WARNINGS: * 97 * HISTORY: * 98 * 08/05/1992 MML : Created. * 99 *=========================================================================*/ 100 unsigned WWGetPrivateProfileHex (char const * section, char const * entry, char * profile) 101 { 102 char buffer[16]; // Integer staging buffer. 103 unsigned card; 104 105 memset (buffer, '0', sizeof(buffer)); // MAX_ENTRY_SIZE = 15 106 buffer[sizeof(buffer)-1] = '\0'; 107 108 WWGetPrivateProfileString(section, entry, "0", buffer, sizeof(buffer), profile); 109 110 if (strlen (buffer) > 0) { 111 sscanf (buffer, "%x", &card); 112 } else { 113 card = 0; 114 } 115 116 return(card); 117 } 118 119 120 /*********************************************************************************************** 121 * WWGetPrivateProfileInt -- Fetches integer value. * 122 * * 123 * INPUT: * 124 * section section to read from * 125 * * 126 * entry name of entry to read * 127 * * 128 * def default value, if entry isn't found * 129 * * 130 * profile buffer containing INI data * 131 * * 132 * OUTPUT: * 133 * integer requested * 134 * * 135 * WARNINGS: * 136 * none. * 137 * * 138 * HISTORY: * 139 * 08/05/1992 JLB : Created. * 140 *=============================================================================================*/ 141 int WWGetPrivateProfileInt(char const * section, char const * entry, int def, char * profile) 142 { 143 char buffer[16]; // Integer staging buffer. 144 145 /* 146 ** Store the default in the buffer. 147 */ 148 sprintf(buffer, "%d", def); 149 150 /* 151 ** Get the buffer; use itself as the default. 152 */ 153 WWGetPrivateProfileString(section, entry, buffer, buffer, sizeof(buffer)-1, profile); 154 155 /* 156 ** Convert to int & return. 157 */ 158 return(atoi(buffer)); 159 } 160 161 162 /*********************************************************************************************** 163 * WWWritePrivateProfileInt -- Write a profile int to the profile data block. * 164 * * 165 * INPUT: * 166 * section section name to write to * 167 * * 168 * entry name of entry to write; if NULL, the entire section is deleted * 169 * * 170 * value value to write * 171 * * 172 * profile INI buffer * 173 * * 174 * OUTPUT: * 175 * true = success, false = failure * 176 * * 177 * WARNINGS: * 178 * none. * 179 * * 180 * HISTORY: * 181 * 10/07/1992 JLB : Created. * 182 *=============================================================================================*/ 183 bool WWWritePrivateProfileInt(char const * section, char const * entry, int value, char * profile) 184 { 185 char buffer[250]; // Working section buffer. 186 187 /* 188 ** Just return if nothing to do. 189 */ 190 if (!profile || !section) { 191 return(true); 192 } 193 194 /* 195 ** Generate string to save. 196 */ 197 sprintf(buffer, "%d", value); 198 199 /* 200 ** Save the string. 201 */ 202 return(WWWritePrivateProfileString(section, entry, buffer, profile)); 203 } 204 205 206 /*********************************************************************************************** 207 * WWGetPrivateProfileString -- Fetch game override string. * 208 * * 209 * INPUT: * 210 * section section name to read from * 211 * * 212 * entry name of entry to read; if NULL, all entry names are returned * 213 * * 214 * def default string to use if not found; can be NULL * 215 * * 216 * retbuffer buffer to store result in * 217 * * 218 * retlen max length of return buffer * 219 * * 220 * profile INI buffer * 221 * * 222 * OUTPUT: * 223 * ptr to entry found in INI buf; NULL if not found * 224 * * 225 * WARNINGS: * 226 * On the PC, the "\n" (10) is translated to "\r\n" (13,10) when it's written * 227 * to disk. This routine must take this into consideration, by searching * 228 * for \n when scanning backward, and for \r when scanning forward. * 229 * * 230 * HISTORY: * 231 * 08/05/1992 JLB : Created. * 232 *=============================================================================================*/ 233 char * WWGetPrivateProfileString(char const * section, char const * entry, char const * def, char * retbuffer, int retlen, char const * profile) 234 { 235 char const * workptr; // Working pointer into profile block. 236 char * altworkptr; // Alternate work pointer. 237 char sec[50]; // Working section buffer. 238 char const * retval; // Start of section or entry pointer. 239 char * next; // Pointer to start of next section (or EOF). 240 char c,c2; // Working character values. 241 int len; // Working substring length value. 242 int entrylen; // Byte length of specified entry. 243 char * orig_retbuf; // original retbuffer ptr 244 245 // if (!retlen) return(NULL); 246 247 /* 248 ** Fill in the default value just in case the entry could not be found. 249 */ 250 if (retbuffer) { 251 retbuffer[0] = '\0'; 252 if (retlen > 1 || retlen == 0) retbuffer[1] = '\0'; 253 if (def) { 254 strncpy(retbuffer, def, retlen); 255 } 256 retbuffer[retlen-1] = '\0'; 257 orig_retbuf = retbuffer; 258 } 259 260 /* 261 ** Make sure a profile string was passed in 262 */ 263 if (!profile || !section) { 264 return(retbuffer); 265 } 266 267 /* 268 ** Build section string to match file image. 269 */ 270 sprintf(sec, "[%s]", section); // sec = section name including []'s 271 strupr(sec); 272 len = strlen(sec); // len = section name length, incl []'s 273 274 /* 275 ** Scan for a matching section 276 */ 277 retval = profile; 278 workptr = profile; 279 for (;;) { 280 281 /* 282 ** 'workptr' = start of next section 283 */ 284 workptr = strchr(workptr, '['); 285 286 /* 287 ** If the end has been reached without finding the desired section 288 ** then abort with a failure flag. 289 */ 290 if (!workptr) { 291 return(NULL); 292 } 293 294 /* 295 ** 'c' = character just before the '[' 296 */ 297 if (workptr==profile) { 298 c = '\n'; 299 } else { 300 c = *(workptr-1); 301 } 302 303 /* 304 ** If this is the section name & the character before is a newline, 305 ** process this section 306 */ 307 if (memicmp(workptr, sec, len) == 0 && (c == '\n')) { 308 309 /* 310 ** Skip work pointer to start of first valid entry. 311 */ 312 workptr += len; 313 while (isspace(*workptr)) { 314 workptr++; 315 } 316 317 /* 318 ** If the section name is empty, we will have stepped onto the start 319 ** of the next section name; inserting new entries here will leave 320 ** a blank line between this section's name & 1st entry. So, check 321 ** for 2 newlines in a row & step backward. 322 */ 323 if (workptr - profile > 4) { 324 if ( *(workptr-1)=='\n' && *(workptr-3)=='\n') 325 workptr -= 2; 326 } 327 328 /* 329 ** 'next = end of section or end of file. 330 */ 331 next = (char*)strchr(workptr, '['); 332 for (;;) { 333 if (next) { 334 335 c = *(next-1); 336 337 /* 338 ** If character before '[' is newline, this is the start of the 339 ** next section 340 */ 341 if (c == '\n') { 342 if (*(next-1)=='\n' && *(next-3)=='\n') { 343 next -= 2; 344 } 345 break; 346 } 347 348 /* 349 ** This bracket was in the section; keep looking 350 */ 351 next = strchr(next+1, '['); 352 } else { 353 354 /* 355 ** No bracket found; set 'next' to the end of the file 356 */ 357 next = (char*)workptr + strlen(workptr)-1; 358 break; 359 } 360 } 361 362 /* 363 ** If a specific entry was specified then return with the associated 364 ** string. 365 */ 366 if (entry) { 367 retval = workptr; 368 entrylen = strlen(entry); 369 370 for (;;) { 371 /* 372 ** Search for the 1st character of the entry 373 */ 374 workptr = strchr(workptr, *entry); 375 376 /* 377 ** If the end of the file has been reached or we have spilled 378 ** into the next section, then abort 379 */ 380 if (!workptr || workptr >= next) { 381 return(NULL); 382 } 383 384 /* 385 ** 'c' = character before possible entry; must be a newline 386 ** 'c2' = character after possible entry; must be '=' or space 387 */ 388 c = *(workptr-1); 389 c2 = *(workptr+entrylen); 390 391 /* 392 ** Entry found; extract it 393 */ 394 if (memicmp(workptr, entry, entrylen) == 0 && (c == '\n') && 395 (c2 == '=' || isspace(c2))) { 396 retval = workptr; 397 workptr += entrylen; // skip entry name 398 workptr = strchr(workptr, '='); // find '=' 399 400 /* 401 ** 'altworkptr' = next newline; \r is used here since we're 402 ** scanning forward! 403 */ 404 if (workptr) { 405 altworkptr = (char*)strchr(workptr, '\r'); // find next newline 406 } 407 408 /* 409 ** Return if there was no '=', or if the newline is before 410 ** the next '=' 411 */ 412 if (workptr == NULL || altworkptr < workptr) { 413 return((char *)retval); 414 } 415 416 /* 417 ** Skip any white space after the '=' and before the first 418 ** valid character of the parameter. 419 */ 420 workptr++; // Skip the '='. 421 while (isspace(*workptr)) { 422 423 /* 424 ** Just return if there's no entry past the '='. 425 */ 426 if (workptr >= altworkptr) 427 return((char*)retval); 428 429 workptr++; // Skip the whitespace 430 } 431 432 /* 433 ** Copy the entry into the return buffer. 434 */ 435 len = (int)(altworkptr - workptr); 436 if (len > retlen-1) { 437 len = retlen-1; 438 } 439 440 if (retbuffer) { 441 memcpy(retbuffer, workptr, len); 442 *(retbuffer + len) = '\0'; // Insert trailing null. 443 strtrim(retbuffer); 444 } 445 return((char*)retval); 446 } 447 448 /* 449 ** Entry was not found; go to the next one 450 */ 451 workptr++; 452 } 453 } else { 454 455 /* 456 ** No entry was specified, so build a list of all entries. 457 ** 'workptr' is at 1st entry after section name 458 ** 'next' is next bracket, or end of file 459 */ 460 retval = workptr; 461 462 if (retbuffer) { 463 464 /* 465 ** Keep accumulating the identifier strings in the retbuffer. 466 */ 467 while (workptr && workptr < next) { 468 altworkptr = (char*)strchr(workptr, '='); // find '=' 469 470 if (altworkptr && altworkptr < next) { 471 int length; // Length of ID string. 472 473 length = (int)(altworkptr - workptr); 474 475 /* 476 ** Make sure we don't write past the end of the retbuffer; 477 ** add '3' for the 3 NULL's at the end 478 */ 479 if (retbuffer - orig_retbuf + length + 3 < retlen) { 480 memcpy(retbuffer, workptr, length); // copy entry name 481 *(retbuffer+length) = '\0'; // NULL-terminate it 482 strtrim(retbuffer); // trim spaces 483 retbuffer += strlen(retbuffer)+1; // next pos in dest buf 484 } else { 485 break; 486 } 487 488 /* 489 ** Advance the work pointer to the start of the next line 490 ** by skipping the end of line character. 491 */ 492 workptr = strchr(altworkptr, '\n'); 493 if (!workptr) { 494 break; 495 } 496 workptr++; 497 } else { 498 499 /* 500 ** If no '=', break out of loop 501 */ 502 break; 503 } 504 } 505 506 /* 507 ** Final trailing terminator. Make double sure the double 508 ** trailing null is added. 509 */ 510 *retbuffer++ = '\0'; 511 *retbuffer++ = '\0'; 512 } 513 break; 514 } 515 } else { 516 517 /* 518 ** Section name not found; go to the next bracket & try again 519 ** Advance past '[' and keep scanning. 520 */ 521 workptr++; 522 } 523 } 524 525 return((char*)retval); 526 } 527 528 529 /*********************************************************************************************** 530 * WritePrivateProfileString -- Write a string to the profile data block. * 531 * * 532 * INPUT: * 533 * section section name to write to * 534 * entry name of entry to write; if NULL, the section is deleted * 535 * string string to write; if NULL, the entry is deleted * 536 * profile INI buffer * 537 * * 538 * OUTPUT: * 539 * true = success, false = failure * 540 * * 541 * WARNINGS: * 542 * This function has to translate newlines into \r\n sequences. * 543 * * 544 * HISTORY: * 545 * 10/07/1992 JLB : Created. * 546 *=============================================================================================*/ 547 bool WWWritePrivateProfileString(char const * section, char const * entry, char const * string, char * profile) 548 { 549 char buffer[250]; // Working section buffer 550 char const * offset; 551 char const * next; // ptr to next section 552 char c; // Working character value 553 554 /* 555 ** Just return if nothing to do. 556 */ 557 if (!profile || !section) { 558 return(true); 559 } 560 561 /* 562 ** Try to find the section. WWGetPrivateProfileString with NULL entry name 563 ** will return all entry names in the given buffer, truncated to the given 564 ** buffer length. 'offset' will point to 1st entry in the section, NULL if 565 ** section not found. 566 */ 567 offset = WWGetPrivateProfileString(section, NULL, NULL, NULL, 0, profile); 568 569 /* 570 ** If the section could not be found, then add it to the end. Don't add 571 ** anything if a removal of an entry is requested (it is obviously already 572 ** non-existent). Make sure two newlines precede the section name. 573 */ 574 if (!offset && entry) { 575 sprintf(buffer, "\r\n[%s]\r\n", section); 576 strcat(profile, buffer); 577 } 578 579 /* 580 ** If the section is there and 'entry' is NULL, remove the entire section 581 */ 582 if (offset && !entry) { 583 584 /* 585 ** 'next = end of section or end of file. 586 */ 587 next = strchr(offset, '['); 588 for (;;) { 589 if (next) { 590 c = *(next-1); 591 592 /* 593 ** If character before '[' is newline, this is the start of the 594 ** next section 595 */ 596 if (c == '\n') { 597 if ( *(next-1)=='\n' && *(next-3)=='\n') { 598 next -= 2; 599 } 600 break; 601 } 602 603 /* 604 ** This bracket was in the section; keep looking 605 */ 606 next = strchr(next+1, '['); 607 } else { 608 609 /* 610 ** No bracket found; set 'next' to the end of the file 611 */ 612 next = offset + strlen(offset); 613 break; 614 } 615 } 616 617 /* 618 ** Remove the section 619 */ 620 strcpy((char*)offset, (char*)next); 621 622 return(true); 623 } 624 625 /* 626 ** Find the matching entry within the desired section. A NULL return buffer 627 ** with 0 length will just return the offset of the found entry, NULL if 628 ** entry not found. 629 */ 630 offset = WWGetPrivateProfileString(section, entry, NULL, NULL, 0, profile); 631 632 /* 633 ** Remove any existing entry 634 */ 635 if (offset) { 636 int eol; // Working EOL offset. 637 638 /* 639 ** Get # characters up to newline; \n is used since we're after the end 640 ** of this line 641 */ 642 eol = strcspn(offset, "\n"); 643 644 /* 645 ** Erase the entry by strcpy'ing the entire INI file over this entry 646 */ 647 if (eol) { 648 strcpy((char*)offset, offset + eol + 1); 649 } 650 } else { 651 652 /* 653 ** Entry doesn't exist, so point 'offset' to the 1st entry position in 654 ** the section. 655 */ 656 offset = WWGetPrivateProfileString(section, NULL, NULL, NULL, 0, profile); 657 } 658 659 /* 660 ** Add the desired entry. 661 */ 662 if (entry && string) { 663 664 /* 665 ** Generate entry string. 666 */ 667 sprintf(buffer, "%s=%s\r\n", entry, string); 668 669 /* 670 ** Make room for new entry. 671 */ 672 memmove((char*)offset+strlen(buffer), offset, strlen(offset)+1); 673 674 /* 675 ** Copy the entry into the INI buffer. 676 */ 677 memcpy((char*)offset, buffer, strlen(buffer)); 678 } 679 680 return(true); 681 } 682 683 684 char * Read_Bin_Buffer( void ) 685 { 686 return( ReadBinBuffer ); 687 } 688 689 690 bool Read_Bin_Init( char * buffer, int length ) 691 { 692 ReadBinBuffer = buffer; 693 ReadBinBufferLen = length; 694 ReadBinBufferPos = 0; 695 ReadBinBufferMax = 0; 696 return( true ); 697 } 698 699 700 int Read_Bin_Length( char * buffer ) 701 { 702 if (buffer != ReadBinBuffer) { 703 return( -1 ); 704 } else { 705 return( ReadBinBufferMax ); 706 } 707 } 708 709 710 bool Read_Bin_Num( void * num, int length, char * buffer ) 711 { 712 char * ptr; 713 714 if (buffer != ReadBinBuffer || length <= 0 || length > 4 || 715 (ReadBinBufferPos + length) >= ReadBinBufferLen) { 716 return( false ); 717 } else { 718 ptr = ReadBinBuffer + ReadBinBufferPos; 719 memcpy( num, ptr, length ); 720 ReadBinBufferPos += length; 721 722 if (ReadBinBufferPos > ReadBinBufferMax) { 723 ReadBinBufferMax = ReadBinBufferPos; 724 } 725 726 return( true ); 727 } 728 } 729 730 731 int Read_Bin_Pos( char * buffer ) 732 { 733 if (buffer != ReadBinBuffer) { 734 return( -1 ); 735 } else { 736 return( ReadBinBufferPos ); 737 } 738 } 739 740 741 int Read_Bin_PosSet( unsigned int pos, char * buffer ) 742 { 743 if (buffer != ReadBinBuffer) { 744 return( -1 ); 745 } else { 746 ReadBinBufferPos = pos; 747 return( ReadBinBufferPos ); 748 } 749 } 750 751 752 bool Read_Bin_String( char * string, char * buffer ) 753 { 754 char * ptr; 755 unsigned char length; 756 757 if (buffer != ReadBinBuffer || 758 ReadBinBufferPos >= ReadBinBufferLen) { 759 return( false ); 760 } else { 761 ptr = ReadBinBuffer + ReadBinBufferPos; 762 length = (unsigned char)*ptr++; 763 if ( (ReadBinBufferPos + length + 2) <= ReadBinBufferLen) { 764 memcpy( string, ptr, (unsigned int)(length + 1) ); 765 ReadBinBufferPos += (length + 2); 766 767 if (ReadBinBufferPos > ReadBinBufferMax) { 768 ReadBinBufferMax = ReadBinBufferPos; 769 } 770 771 return( true ); 772 } else { 773 return( false ); 774 } 775 } 776 } 777 778 779 char * Write_Bin_Buffer( void ) 780 { 781 return( WriteBinBuffer ); 782 } 783 784 785 bool Write_Bin_Init( char * buffer, int length ) 786 { 787 WriteBinBuffer = buffer; 788 WriteBinBufferLen = length; 789 WriteBinBufferPos = 0; 790 WriteBinBufferMax = 0; 791 return( true ); 792 } 793 794 795 int Write_Bin_Length( char * buffer ) 796 { 797 if (buffer != WriteBinBuffer) { 798 return( -1 ); 799 } else { 800 return( WriteBinBufferMax ); 801 } 802 } 803 804 805 bool Write_Bin_Num( void * num, int length, char * buffer ) 806 { 807 char * ptr; 808 809 if (buffer != WriteBinBuffer || length <= 0 || length > 4 || 810 (WriteBinBufferPos + length) > WriteBinBufferLen) { 811 return( false ); 812 } else { 813 ptr = WriteBinBuffer + WriteBinBufferPos; 814 memcpy( ptr, num, length ); 815 WriteBinBufferPos += length; 816 817 if (WriteBinBufferPos > WriteBinBufferMax) { 818 WriteBinBufferMax = WriteBinBufferPos; 819 } 820 821 return( true ); 822 } 823 } 824 825 826 int Write_Bin_Pos( char * buffer ) 827 { 828 if (buffer != WriteBinBuffer) { 829 return( -1 ); 830 } else { 831 return( WriteBinBufferPos ); 832 } 833 } 834 835 836 int Write_Bin_PosSet( unsigned int pos, char * buffer ) 837 { 838 if (buffer != WriteBinBuffer) { 839 return( -1 ); 840 } else { 841 WriteBinBufferPos = pos; 842 return( WriteBinBufferPos ); 843 } 844 } 845 846 847 bool Write_Bin_String( char * string, int length, char * buffer ) 848 { 849 char * ptr; 850 851 if (buffer != WriteBinBuffer || length < 0 || length > 255 || 852 (WriteBinBufferPos + length + 2) > WriteBinBufferLen) { 853 return( false ); 854 } else { 855 ptr = WriteBinBuffer + WriteBinBufferPos; 856 *ptr++ = (char)length; 857 memcpy( ptr, string, (length + 1) ); 858 WriteBinBufferPos += (length + 2); 859 860 if (WriteBinBufferPos > WriteBinBufferMax) { 861 WriteBinBufferMax = WriteBinBufferPos; 862 } 863 864 return( true ); 865 } 866 } 867