Changeset 573 for trunk/src/kernel32/profile.cpp
- Timestamp:
- Aug 19, 1999, 12:48:49 PM (26 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/profile.cpp
r565 r573 1 /* $Id: profile.cpp,v 1.17 1999-08-18 23:44:48 phaller Exp $ */ 1 /* $Id: profile.cpp,v 1.18 1999-08-19 10:48:49 sandervl Exp $ */ 2 3 /* 4 * Project Odin Software License can be found in LICENSE.TXT 5 * 6 * Win32 profile API functions 7 * 8 * Copyright 1993 Miguel de Icaza 9 * Copyright 1996 Alexandre Julliard 10 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl) 11 * Copyright 1998 Patrick Haller 12 * Copyright 1999 Christoph Bratschi 13 */ 14 15 #include <os2win.h> 16 #include <ctype.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <stdio.h> 20 #include <unicode.h> 21 #include <odinwrap.h> 22 #include "heap.h" 23 #include "heapstring.h" 24 25 #include <sys/stat.h> 26 27 #include "winbase.h" 28 //#include "wine/winbase16.h" 29 #include "winuser.h" 30 #include "winnls.h" 31 32 33 ODINDEBUGCHANNEL(PROFILE) 2 34 3 /* 4 * Project Odin Software License can be found in LICENSE.TXT 5 * 6 * Win32 profile API functions 7 * 8 * Copyright 1993 Miguel de Icaza 9 * Copyright 1996 Alexandre Julliard 10 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl) 11 * Copyright 1998 Patrick Haller 12 * Copyright 1999 Christoph Bratschi 13 */ 35 // ------------------------- 36 // WINE compatibility macros 37 // ------------------------- 38 39 #ifndef MAX_PATHNAME_LEN 40 #define MAX_PATHNAME_LEN 260 41 #endif 42 43 #define SystemHeap GetProcessHeap() 44 #define strcasecmp strcmp 45 #define DOSFS_GetFullName(a,b,c) strcpy(c,a) 46 //#define lstrcpynA(a,b,c) strncpy((char*)a,(char*)b,(int)c) 47 #define CharLowerA(a) (a) 48 49 50 typedef struct tagPROFILEKEY 51 { 52 char *name; 53 char *value; 54 struct tagPROFILEKEY *next; 55 } PROFILEKEY; 56 57 typedef struct tagPROFILESECTION 58 { 59 char *name; 60 struct tagPROFILEKEY *key; 61 struct tagPROFILESECTION *next; 62 } PROFILESECTION; 63 64 65 typedef struct 66 { 67 BOOL changed; 68 PROFILESECTION *section; 69 char *filename; //first open name 70 char *fullname; //name with path 71 time_t mtime; 72 } PROFILE; 73 74 75 #define N_CACHED_PROFILES 10 76 77 /* Cached profile files */ 78 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL}; 79 80 #define CurProfile (MRUProfile[0]) 81 82 /* wine.ini profile content */ 83 static PROFILESECTION *PROFILE_WineProfile; 84 85 #define PROFILE_MAX_LINE_LEN 1024 86 #define WINININAME "WIN.INI" 87 88 /* Wine profile name in $HOME directory; must begin with slash */ 89 static const char PROFILE_WineIniName[] = "/.winerc"; 90 91 /* Wine profile: the profile file being used */ 92 static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = ""; 93 94 /* Check for comments in profile */ 95 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';') 96 97 #define WINE_INI_GLOBAL ETCDIR "/wine.conf" 98 99 static LPCWSTR wininiW = NULL; //CB: never freed 100 101 static CRITICAL_SECTION PROFILE_CritSect; 102 103 104 /*********************************************************************** 105 * PROFILE_CopyEntry 106 * 107 * Copy the content of an entry into a buffer, removing quotes, and possibly 108 * translating environment variables. 109 */ 110 static void PROFILE_CopyEntry( char *buffer, 111 const char *value, 112 int len, 113 int handle_env ) 114 { 115 char quote = '\0'; 116 const char *p; 117 118 if ((*value == '\'') || (*value == '\"')) 119 { 120 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++; 121 } 122 123 if (!handle_env) 124 { 125 lstrcpynA( buffer, value, len ); 126 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0'; 127 return; 128 } 129 130 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- ) 131 { 132 if ((*p == '$') && (p[1] == '{')) 133 { 134 char env_val[1024]; 135 const char *env_p; 136 const char *p2 = strchr( p, '}' ); 137 if (!p2) continue; /* ignore it */ 138 lstrcpynA(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 )); 139 if ((env_p = getenv( env_val )) != NULL) 140 { 141 lstrcpynA( buffer, env_p, len ); 142 buffer += strlen( buffer ); 143 len -= strlen( buffer ); 144 } 145 p = p2 + 1; 146 } 147 } 148 *buffer = '\0'; 149 } 150 151 152 /*********************************************************************** 153 * PROFILE_Save 154 * 155 * Save a profile tree to a file. 156 */ 157 static void PROFILE_Save( FILE *file, PROFILESECTION *section ) 158 { 159 PROFILEKEY *key; 160 161 for ( ; section; section = section->next) 162 { 163 if (section->name) fprintf( file, "\n[%s]\n", section->name ); 164 for (key = section->key; key; key = key->next) 165 { 166 fprintf( file, "%s", key->name ); 167 if (key->value) fprintf( file, "=%s", key->value ); 168 fprintf( file, "\n" ); 169 } 170 } 171 } 172 173 174 /*********************************************************************** 175 * PROFILE_Free 176 * 177 * Free a profile tree. 178 */ 179 static void PROFILE_Free( PROFILESECTION *section ) 180 { 181 PROFILESECTION *next_section; 182 PROFILEKEY *key, *next_key; 183 184 for ( ; section; section = next_section) 185 { 186 if (section->name) HeapFree( SystemHeap, 0, section->name ); 187 for (key = section->key; key; key = next_key) 188 { 189 next_key = key->next; 190 if (key->name) HeapFree( SystemHeap, 0, key->name ); 191 if (key->value) HeapFree( SystemHeap, 0, key->value ); 192 HeapFree( SystemHeap, 0, key ); 193 } 194 next_section = section->next; 195 HeapFree( SystemHeap, 0, section ); 196 } 197 } 198 199 static int 200 PROFILE_isspace(char c) { 201 if (isspace(c)) return 1; 202 if (c=='\r' || c==0x1a) return 1; 203 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */ 204 return 0; 205 } 206 207 208 /*********************************************************************** 209 * PROFILE_Load 210 * 211 * Load a profile tree from a file. 212 */ 213 static PROFILESECTION *PROFILE_Load( FILE *file ) 214 { 215 char buffer[PROFILE_MAX_LINE_LEN]; 216 char *p, *p2; 217 int line = 0; 218 PROFILESECTION *section, *first_section; 219 PROFILESECTION **next_section; 220 PROFILEKEY *key, *prev_key, **next_key; 221 222 first_section = (PROFILESECTION *)HEAP_xalloc( SystemHeap, 0, sizeof(*section) ); 223 first_section->name = NULL; 224 first_section->key = NULL; 225 first_section->next = NULL; 226 next_section = &first_section->next; 227 next_key = &first_section->key; 228 prev_key = NULL; 229 230 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file )) 231 { 232 line++; 233 p = buffer; 234 while (*p && PROFILE_isspace(*p)) p++; 235 if (*p == '[') /* section start */ 236 { 237 if (!(p2 = strrchr( p, ']' ))) 238 { 239 dprintf(("Kernel32:Profile:Invalid section header at line %d: '%s'\n", 240 line, p )); 241 } 242 else 243 { 244 *p2 = '\0'; 245 p++; 246 section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(*section) ); 247 section->name = HEAP_strdupA( SystemHeap, 0, p ); 248 section->key = NULL; 249 section->next = NULL; 250 *next_section = section; 251 next_section = §ion->next; 252 next_key = §ion->key; 253 prev_key = NULL; 254 255 dprintf(("Kernel32:Profile:New section: '%s'\n",section->name)); 256 257 continue; 258 } 259 } 260 261 p2=p+strlen(p) - 1; 262 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0'; 263 264 if ((p2 = strchr( p, '=' )) != NULL) 265 { 266 char *p3 = p2 - 1; 267 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0'; 268 *p2++ = '\0'; 269 while (*p2 && PROFILE_isspace(*p2)) p2++; 270 } 271 272 if(*p || !prev_key || *prev_key->name) 273 { 274 key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(*key) ); 275 key->name = HEAP_strdupA( SystemHeap, 0, p ); 276 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL; 277 key->next = NULL; 278 *next_key = key; 279 next_key = &key->next; 280 prev_key = key; 281 282 dprintf(("Kernel32:Profile:New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)")); 283 } 284 } 285 return first_section; 286 } 287 288 289 /*********************************************************************** 290 * PROFILE_DeleteSection 291 * 292 * Delete a section from a profile tree. 293 */ 294 static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name ) 295 { 296 while (*section) 297 { 298 if ((*section)->name && !strcasecmp( (*section)->name, name )) 299 { 300 PROFILESECTION *to_del = *section; 301 *section = to_del->next; 302 to_del->next = NULL; 303 PROFILE_Free( to_del ); 304 return TRUE; 305 } 306 section = &(*section)->next; 307 } 308 return FALSE; 309 } 310 311 312 /*********************************************************************** 313 * PROFILE_DeleteKey 314 * 315 * Delete a key from a profile tree. 316 */ 317 static BOOL PROFILE_DeleteKey( PROFILESECTION **section, 318 LPCSTR section_name, LPCSTR key_name ) 319 { 320 while (*section) 321 { 322 if ((*section)->name && !strcasecmp( (*section)->name, section_name )) 323 { 324 PROFILEKEY **key = &(*section)->key; 325 while (*key) 326 { 327 if (!strcasecmp( (*key)->name, key_name )) 328 { 329 PROFILEKEY *to_del = *key; 330 *key = to_del->next; 331 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name ); 332 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value); 333 HeapFree( SystemHeap, 0, to_del ); 334 return TRUE; 335 } 336 key = &(*key)->next; 337 } 338 } 339 section = &(*section)->next; 340 } 341 return FALSE; 342 } 343 344 345 /*********************************************************************** 346 * PROFILE_Find 347 * 348 * Find a key in a profile tree, optionally creating it. 349 */ 350 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section, 351 const char *section_name, 352 const char *key_name, int create ) 353 { 354 while (*section) 355 { 356 if ((*section)->name && !strcasecmp( (*section)->name, section_name )) 357 { 358 PROFILEKEY **key = &(*section)->key; 359 while (*key) 360 { 361 if (!strcasecmp( (*key)->name, key_name )) return *key; 362 key = &(*key)->next; 363 } 364 if (!create) return NULL; 365 *key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) ); 366 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name ); 367 (*key)->value = NULL; 368 (*key)->next = NULL; 369 return *key; 370 } 371 section = &(*section)->next; 372 } 373 if (!create) return NULL; 374 *section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) ); 375 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name ); 376 (*section)->next = NULL; 377 (*section)->key = (tagPROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) ); 378 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name ); 379 (*section)->key->value = NULL; 380 (*section)->key->next = NULL; 381 return (*section)->key; 382 } 383 384 385 /*********************************************************************** 386 * PROFILE_FlushFile 387 * 388 * Flush the current profile to disk if changed. 389 */ 390 static BOOL PROFILE_FlushFile(void) 391 { 392 FILE *file = NULL; 393 struct stat buf; 394 395 if(!CurProfile) 396 { 397 dprintf(("Kernel32:Profile:No current profile!\n")); 398 return FALSE; 399 } 400 401 // not changed, return immediately 402 if (!CurProfile->changed) 403 return TRUE; 404 405 // try to open file 406 file = fopen(CurProfile->fullname, "w"); 407 if (!file) 408 { 409 dprintf(("Kernel32:Profile:could not save profile file %s\n", CurProfile->fullname)); 410 return FALSE; 411 } 412 413 dprintf(("Kernel32:Profile:Saving %s\n", CurProfile->fullname )); 414 PROFILE_Save( file, CurProfile->section ); 415 fclose( file ); 416 CurProfile->changed = FALSE; 417 if(!stat(CurProfile->fullname,&buf)) 418 CurProfile->mtime=buf.st_mtime; 419 return TRUE; 420 } 421 422 423 /*********************************************************************** 424 * PROFILE_ReleaseFile 425 * 426 * Flush the current profile to disk and remove it from the cache. 427 */ 428 static void PROFILE_ReleaseFile(void) 429 { 430 PROFILE_FlushFile(); 431 PROFILE_Free( CurProfile->section ); 432 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename ); 433 if (CurProfile->fullname) HeapFree(SystemHeap,0,CurProfile->fullname); 434 CurProfile->changed = FALSE; 435 CurProfile->section = NULL; 436 CurProfile->filename = NULL; 437 CurProfile->fullname = NULL; 438 CurProfile->mtime = 0; 439 } 440 441 442 /*********************************************************************** 443 * PROFILE_Open 444 * 445 * Open a profile file, checking the cached file first. 446 */ 447 static BOOL PROFILE_Open( LPCSTR filename ) 448 { 449 FILE *file = NULL; 450 int i,j; 451 struct stat buf; 452 PROFILE *tempProfile; 453 454 if (!filename || filename[0] == 0) return FALSE; 455 456 /* First time around */ 457 458 if(!CurProfile) 459 for(i=0;i<N_CACHED_PROFILES;i++) 460 { 461 MRUProfile[i]= (PROFILE*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) ); 462 MRUProfile[i]->changed=FALSE; 463 MRUProfile[i]->section=NULL; 464 MRUProfile[i]->filename=NULL; 465 MRUProfile[i]->fullname=NULL; 466 MRUProfile[i]->mtime=0; 467 } 468 469 /* Check for a match */ 470 471 for(i=0;i<N_CACHED_PROFILES;i++) 472 { 473 if (MRUProfile[i]->filename && (!strcmp(filename,MRUProfile[i]->filename) || !strcmp(filename,MRUProfile[i]->fullname))) 474 { 475 if(i) 476 { 477 PROFILE_FlushFile(); 478 tempProfile=MRUProfile[i]; 479 for(j=i;j>0;j--) 480 MRUProfile[j]=MRUProfile[j-1]; 481 CurProfile=tempProfile; 482 } 483 if(!stat(CurProfile->fullname,&buf) && CurProfile->mtime==buf.st_mtime) 484 dprintf(("Kernel32:Profile:(%s): already opened (mru=%d)\n", 485 filename, i )); 486 else 487 dprintf(("Kernel32:Profile:(%s): already opened, needs refreshing (mru=%d)\n", 488 filename, i )); 489 return TRUE; 490 } 491 } 492 493 /* Rotate the oldest to the top to be replaced */ 494 495 if(i==N_CACHED_PROFILES) 496 { 497 tempProfile=MRUProfile[N_CACHED_PROFILES-1]; 498 for(i=N_CACHED_PROFILES-1;i>0;i--) 499 MRUProfile[i]=MRUProfile[i-1]; 500 CurProfile=tempProfile; 501 } 502 503 /* Flush the profile */ 504 505 if(CurProfile->filename) PROFILE_ReleaseFile(); 506 507 CurProfile->filename = HEAP_strdupA(SystemHeap,0,filename); 508 509 /* check for path */ 510 511 if ((!strchr( filename,'/') && 512 !strchr( filename,'\\')) || 513 !strchr( filename,':')) 514 { 515 char fullname[MAX_PATHNAME_LEN]; 516 517 GetWindowsDirectoryA(fullname,sizeof(fullname)); 518 strcat(fullname,"\\"); 519 strcat(fullname,filename); 520 CurProfile->fullname = HEAP_strdupA(SystemHeap,0,fullname); 521 } else CurProfile->fullname = HEAP_strdupA(SystemHeap,0,filename); 522 523 file = fopen(CurProfile->fullname,"r"); 524 if (file) 525 { 526 dprintf(("Kernel32:Profile:(%s): found it in %s\n", 527 filename, CurProfile->fullname )); 528 529 CurProfile->section = PROFILE_Load( file ); 530 fclose( file ); 531 if(!stat(CurProfile->fullname,&buf)) 532 CurProfile->mtime=buf.st_mtime; 533 } 534 else 535 { 536 /* Does not exist yet, we will create it in PROFILE_FlushFile */ 537 dprintf(("Kernel32:Profile:profile file %s not found\n", CurProfile->fullname )); 538 } 539 return TRUE; 540 } 541 542 543 /*********************************************************************** 544 * PROFILE_GetSection 545 * 546 * Returns all keys of a section. 547 * If return_values is TRUE, also include the corresponding values. 548 */ 549 static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name, 550 LPSTR buffer, UINT len, BOOL handle_env, 551 BOOL return_values ) 552 { 553 PROFILEKEY *key; 554 while (section) 555 { 556 if (section->name && !strcasecmp( section->name, section_name )) 557 { 558 UINT oldlen = len; 559 for (key = section->key; key; key = key->next) 560 { 561 if (len <= 2) break; 562 if (!*key->name) continue; /* Skip empty lines */ 563 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */ 564 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env ); 565 len -= strlen(buffer) + 1; 566 buffer += strlen(buffer) + 1; 567 if (return_values && key->value) { 568 buffer[-1] = '='; 569 PROFILE_CopyEntry ( buffer, 570 key->value, len - 1, handle_env ); 571 len -= strlen(buffer) + 1; 572 buffer += strlen(buffer) + 1; 573 } 574 } 575 *buffer = '\0'; 576 if (len <= 1) 577 /*If either lpszSection or lpszKey is NULL and the supplied 578 destination buffer is too small to hold all the strings, 579 the last string is truncated and followed by two null characters. 580 In this case, the return value is equal to cchReturnBuffer 581 minus two. */ 582 { 583 buffer[-1] = '\0'; 584 return oldlen - 2; 585 } 586 return oldlen - len; 587 } 588 section = section->next; 589 } 590 buffer[0] = buffer[1] = '\0'; 591 return 0; 592 } 593 594 595 static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len ) 596 { 597 LPSTR buf = buffer; 598 WORD l, cursize = 0; 599 PROFILESECTION *section; 600 601 for (section = CurProfile->section; section; section = section->next) 602 if (section->name) { 603 l = strlen(section->name); 604 cursize += l+1; 605 if (cursize > len+1) 606 return len-2; 607 608 strcpy(buf, section->name); 609 buf += l+1; 610 } 611 612 *buf=0; 613 buf++; 614 return buf-buffer; 615 } 616 617 618 /*********************************************************************** 619 * PROFILE_GetString 620 * 621 * Get a profile string. 622 */ 623 static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name, 624 LPCSTR def_val, LPSTR buffer, UINT len ) 625 { 626 PROFILEKEY *key = NULL; 627 628 if (!def_val) def_val = ""; 629 if (key_name && key_name[0]) 630 { 631 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE ); 632 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val, 633 len, FALSE ); 634 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n", 635 section, key_name, def_val, buffer )); 636 return strlen( buffer ); 637 } 638 if (section && section[0]) 639 return PROFILE_GetSection(CurProfile->section, section, buffer, len, 640 FALSE, FALSE); 641 /* undocumented; both section and key_name are NULL */ 642 return PROFILE_GetSectionNames(buffer, len); 643 } 644 645 646 /*********************************************************************** 647 * PROFILE_SetString 648 * 649 * Set a profile string. 650 */ 651 static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name, 652 LPCSTR value ) 653 { 654 if (!key_name) /* Delete a whole section */ 655 { 656 dprintf(("Kernel32:Profile:('%s')\n", section_name)); 657 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section, 658 section_name ); 659 return TRUE; /* Even if PROFILE_DeleteSection() has failed, 660 this is not an error on application's level.*/ 661 } 662 else if (!value) /* Delete a key */ 663 { 664 dprintf(("Kernel32:Profile:('%s','%s')\n", 665 section_name, key_name )); 666 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section, 667 section_name, key_name ); 668 return TRUE; /* same error handling as above */ 669 } 670 else /* Set the key value */ 671 { 672 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name, 673 key_name, TRUE ); 674 dprintf(("Kernel32:Profile:('%s','%s','%s'): \n", 675 section_name, key_name, value )); 676 if (!key) return FALSE; 677 if (key->value) 678 { 679 if (!strcmp( key->value, value )) 680 { 681 dprintf(("Kernel32:Profile: no change needed\n" )); 682 return TRUE; /* No change needed */ 683 } 684 dprintf(("Kernel32:Profile: replacing '%s'\n", key->value )); 685 HeapFree( SystemHeap, 0, key->value ); 686 } 687 else dprintf(("Kernel32:Profile: creating key\n" )); 688 key->value = HEAP_strdupA( SystemHeap, 0, value ); 689 CurProfile->changed = TRUE; 690 } 691 return TRUE; 692 } 693 694 695 /*********************************************************************** 696 * PROFILE_GetWineIniString 697 * 698 * Get a config string from the wine.ini file. 699 */ 700 int PROFILE_GetWineIniString( const char *section, const char *key_name, 701 const char *def, char *buffer, int len ) 702 { 703 int ret; 704 705 EnterCriticalSection( &PROFILE_CritSect ); 706 707 if (key_name) 708 { 709 PROFILEKEY *key = PROFILE_Find(&PROFILE_WineProfile, section, key_name, FALSE); 710 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def, 711 len, TRUE ); 712 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n", 713 section, key_name, def, buffer )); 714 ret = strlen( buffer ); 715 } 716 else 717 { 718 ret = PROFILE_GetSection( PROFILE_WineProfile, section, buffer, len, TRUE, FALSE ); 719 } 720 LeaveCriticalSection( &PROFILE_CritSect ); 721 722 return ret; 723 } 724 725 726 /*********************************************************************** 727 * PROFILE_GetWineIniInt 728 * 729 * Get a config integer from the wine.ini file. 730 */ 731 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def ) 732 { 733 char buffer[20]; 734 char *p; 735 long result; 736 PROFILEKEY *key; 737 int ret; 738 739 EnterCriticalSection( &PROFILE_CritSect ); 740 741 key = PROFILE_Find( &PROFILE_WineProfile, section, key_name, FALSE ); 742 if (!key || !key->value) { 743 ret = def; 744 } else { 745 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE ); 746 result = strtol( buffer, &p, 0 ); 747 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result; 748 } 749 750 LeaveCriticalSection( &PROFILE_CritSect ); 751 752 return ret; 753 } 754 755 756 /****************************************************************************** 757 * 758 * int PROFILE_EnumerateWineIniSection( 759 * char const *section, #Name of the section to enumerate 760 * void (*cbfn)(char const *key, char const *value, void *user), 761 * # Address of the callback function 762 * void *user ) # User-specified pointer. 763 * 764 * For each entry in a section in the wine.conf file, this function will 765 * call the specified callback function, informing it of each key and 766 * value. An optional user pointer may be passed to it (if this is not 767 * needed, pass NULL through it and ignore the value in the callback 768 * function). 769 * 770 * The callback function must accept three parameters: 771 * The name of the key (char const *) 772 * The value of the key (char const *) 773 * A user-specified parameter (void *) 774 * Note that the first two are char CONST *'s, not char *'s! The callback 775 * MUST not modify these strings! 776 * 777 * The return value indicates the number of times the callback function 778 * was called. 779 */ 780 int PROFILE_EnumerateWineIniSection( 781 char const *section, 782 void (*cbfn)(char const *, char const *, void *), 783 void *userptr ) 784 { 785 PROFILESECTION *scansect; 786 PROFILEKEY *scankey; 787 int calls = 0; 788 789 EnterCriticalSection( &PROFILE_CritSect ); 790 791 /* Search for the correct section */ 792 for(scansect = PROFILE_WineProfile; scansect; scansect = scansect->next) { 793 if(scansect->name && !strcasecmp(scansect->name, section)) { 794 795 /* Enumerate each key with the callback */ 796 for(scankey = scansect->key; scankey; scankey = scankey->next) { 797 798 /* Ignore blank entries -- these shouldn't exist, but let's 799 be extra careful */ 800 if(scankey->name[0]) { 801 cbfn(scankey->name, scankey->value, userptr); 802 ++calls; 803 } 804 } 805 806 break; 807 } 808 } 809 LeaveCriticalSection( &PROFILE_CritSect ); 810 811 return calls; 812 } 813 814 815 /****************************************************************************** 816 * 817 * int PROFILE_GetWineIniBool( 818 * char const *section, 819 * char const *key_name, 820 * int def ) 821 * 822 * Reads a boolean value from the wine.ini file. This function attempts to 823 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0' 824 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for 825 * true. Anything else results in the return of the default value. 826 * 827 * This function uses 1 to indicate true, and 0 for false. You can check 828 * for existence by setting def to something other than 0 or 1 and 829 * examining the return value. 830 */ 831 int PROFILE_GetWineIniBool( 832 char const *section, 833 char const *key_name, 834 int def ) 835 { 836 char key_value[2]; 837 int retval; 838 839 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2); 840 841 switch(key_value[0]) { 842 case 'n': 843 case 'N': 844 case 'f': 845 case 'F': 846 case '0': 847 retval = 0; 848 break; 849 850 case 'y': 851 case 'Y': 852 case 't': 853 case 'T': 854 case '1': 855 retval = 1; 856 break; 857 858 default: 859 retval = def; 860 } 861 862 dprintf(("Kernel32:Profile:(\"%s\", \"%s\", %s), " 863 "[%c], ret %s.\n", section, key_name, 864 def ? "TRUE" : "FALSE", key_value[0], 865 retval ? "TRUE" : "FALSE")); 866 867 return retval; 868 } 869 870 871 #if 0 872 /*********************************************************************** 873 * PROFILE_LoadWineIni 874 * 875 * Load the wine.ini file. 876 */ 877 int PROFILE_LoadWineIni(void) 878 { 879 char buffer[MAX_PATHNAME_LEN]; 880 const char *p; 881 FILE *f; 882 883 InitializeCriticalSection( &PROFILE_CritSect ); 884 MakeCriticalSectionGlobal( &PROFILE_CritSect ); 885 886 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) ) 887 { 888 /* Open -config specified file */ 889 PROFILE_WineProfile = PROFILE_Load ( f); 890 fclose ( f ); 891 strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1); 892 return 1; 893 } 894 895 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) ) 896 { 897 PROFILE_WineProfile = PROFILE_Load( f ); 898 fclose( f ); 899 strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1); 900 return 1; 901 } 902 if ((p = getenv( "HOME" )) != NULL) 903 { 904 lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName)); 905 strcat( buffer, PROFILE_WineIniName ); 906 if ((f = fopen( buffer, "r" )) != NULL) 907 { 908 PROFILE_WineProfile = PROFILE_Load( f ); 909 fclose( f ); 910 strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1); 911 return 1; 912 } 913 } 914 else dprintf(("Kernel32:Profile:could not get $HOME value for config file.\n" )); 915 916 /* Try global file */ 917 918 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL) 919 { 920 PROFILE_WineProfile = PROFILE_Load( f ); 921 fclose( f ); 922 strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1); 923 return 1; 924 } 925 MESSAGE( "Can't open configuration file %s or $HOME%s\n", 926 WINE_INI_GLOBAL, PROFILE_WineIniName ); 927 return 0; 928 } 929 930 931 /*********************************************************************** 932 * PROFILE_UsageWineIni 933 * 934 * Explain the wine.ini file to those who don't read documentation. 935 * Keep below one screenful in length so that error messages above are 936 * noticed. 937 */ 938 void PROFILE_UsageWineIni(void) 939 { 940 MESSAGE("Perhaps you have not properly edited or created " 941 "your Wine configuration file.\n"); 942 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName); 943 MESSAGE(" or it is determined by the -config option or from\n" 944 " the WINE_INI environment variable.\n"); 945 if (*PROFILE_WineIniUsed) 946 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed); 947 /* RTFM, so to say */ 948 } 949 #endif 950 951 /*********************************************************************** 952 * PROFILE_GetStringItem 953 * 954 * Convenience function that turns a string 'xxx, yyy, zzz' into 955 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'. 956 */ 957 char* PROFILE_GetStringItem( char* start ) 958 { 959 char* lpchX, *lpch; 960 961 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ ) 962 { 963 if( *lpchX == ',' ) 964 { 965 if( lpch ) *lpch = '\0'; else *lpchX = '\0'; 966 while( *(++lpchX) ) 967 if( !PROFILE_isspace(*lpchX) ) return lpchX; 968 } 969 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX; 970 else lpch = NULL; 971 } 972 if( lpch ) *lpch = '\0'; 973 return NULL; 974 } 975 976 /********************* API functions **********************************/ 977 978 /*********************************************************************** 979 * GetProfileInt32A (KERNEL32.264) 980 */ 981 ODINFUNCTION3(UINT, GetProfileIntA, 982 LPCSTR, section, 983 LPCSTR, entry, 984 INT, def_val) 985 { 986 return GetPrivateProfileIntA( section, entry, def_val, WINININAME ); 987 } 988 989 /*********************************************************************** 990 * GetProfileInt32W (KERNEL32.264) 991 */ 992 ODINFUNCTION3(UINT, GetProfileIntW, 993 LPCWSTR, section, 994 LPCWSTR, entry, 995 INT, def_val) 996 { 997 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME ); 998 return GetPrivateProfileIntW( section, entry, def_val, wininiW ); 999 } 1000 1001 /*********************************************************************** 1002 * GetProfileString32A (KERNEL32.268) 1003 */ 1004 ODINFUNCTION5(INT, GetProfileStringA, 1005 LPCSTR, section, 1006 LPCSTR, entry, 1007 LPCSTR, def_val, 1008 LPSTR, buffer, 1009 UINT, len) 1010 { 1011 return GetPrivateProfileStringA( section, entry, def_val, 1012 buffer, len, WINININAME ); 1013 } 1014 1015 /*********************************************************************** 1016 * GetProfileString32W (KERNEL32.269) 1017 */ 1018 ODINFUNCTION5(INT, GetProfileStringW, 1019 LPCWSTR, section, 1020 LPCWSTR, entry, 1021 LPCWSTR, def_val, 1022 LPWSTR, buffer, 1023 UINT, len) 1024 { 1025 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME ); 1026 return GetPrivateProfileStringW( section, entry, def_val, 1027 buffer, len, wininiW ); 1028 } 1029 1030 /*********************************************************************** 1031 * WriteProfileString32A (KERNEL32.587) 1032 */ 1033 ODINFUNCTION3(BOOL, WriteProfileStringA, 1034 LPCSTR, section, 1035 LPCSTR, entry, 1036 LPCSTR, string) 1037 { 1038 return WritePrivateProfileStringA( section, entry, string, WINININAME ); 1039 } 1040 1041 /*********************************************************************** 1042 * WriteProfileString32W (KERNEL32.588) 1043 */ 1044 ODINFUNCTION3(BOOL, WriteProfileStringW, 1045 LPCWSTR, section, 1046 LPCWSTR, entry, 1047 LPCWSTR, string) 1048 { 1049 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME ); 1050 return WritePrivateProfileStringW( section, entry, string, wininiW ); 1051 } 1052 1053 /*********************************************************************** 1054 * GetPrivateProfileInt32A (KERNEL32.251) 1055 */ 1056 ODINFUNCTION4(UINT, GetPrivateProfileIntA, 1057 LPCSTR, section, 1058 LPCSTR, entry, 1059 INT, def_val, 1060 LPCSTR, filename) 1061 { 1062 char buffer[20]; 1063 char *p; 1064 long result; 1065 1066 GetPrivateProfileStringA( section, entry, "", 1067 buffer, sizeof(buffer), filename ); 1068 if (!buffer[0]) return (UINT)def_val; 1069 result = strtol( buffer, &p, 0 ); 1070 if (p == buffer) return 0; /* No digits at all */ 1071 return (UINT)result; 1072 } 1073 1074 /*********************************************************************** 1075 * GetPrivateProfileInt32W (KERNEL32.252) 1076 */ 1077 ODINFUNCTION4(UINT, GetPrivateProfileIntW, 1078 LPCWSTR, section, 1079 LPCWSTR, entry, 1080 INT, def_val, 1081 LPCWSTR, filename) 1082 { 1083 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1084 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry ); 1085 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1086 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA); 1087 HeapFree( GetProcessHeap(), 0, sectionA ); 1088 HeapFree( GetProcessHeap(), 0, filenameA ); 1089 HeapFree( GetProcessHeap(), 0, entryA ); 1090 return res; 1091 } 1092 1093 /*********************************************************************** 1094 * GetPrivateProfileString32A (KERNEL32.255) 1095 */ 1096 ODINFUNCTION6(INT, GetPrivateProfileStringA, 1097 LPCSTR, section, 1098 LPCSTR, entry, 1099 LPCSTR, def_val, 1100 LPSTR, buffer, 1101 UINT, len, 1102 LPCSTR, filename) 1103 { 1104 int ret; 1105 1106 if (!filename) 1107 filename = WINININAME; 1108 1109 EnterCriticalSection( &PROFILE_CritSect ); 1110 1111 if (PROFILE_Open( filename )) { 1112 ret = PROFILE_GetString( section, entry, def_val, buffer, len ); 1113 } else { 1114 lstrcpynA( buffer, def_val, len ); 1115 ret = strlen( buffer ); 1116 } 1117 1118 LeaveCriticalSection( &PROFILE_CritSect ); 1119 1120 return ret; 1121 } 1122 1123 /*********************************************************************** 1124 * GetPrivateProfileString32W (KERNEL32.256) 1125 */ 1126 ODINFUNCTION6(INT, GetPrivateProfileStringW, 1127 LPCWSTR, section, 1128 LPCWSTR, entry, 1129 LPCWSTR, def_val, 1130 LPWSTR, buffer, 1131 UINT, len, 1132 LPCWSTR, filename) 1133 { 1134 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1135 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry ); 1136 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1137 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val ); 1138 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len ); 1139 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA, 1140 bufferA, len, filenameA ); 1141 lstrcpynAtoW( buffer, bufferA, len ); 1142 HeapFree( GetProcessHeap(), 0, sectionA ); 1143 HeapFree( GetProcessHeap(), 0, entryA ); 1144 HeapFree( GetProcessHeap(), 0, filenameA ); 1145 HeapFree( GetProcessHeap(), 0, def_valA ); 1146 HeapFree( GetProcessHeap(), 0, bufferA); 1147 return ret; 1148 } 1149 1150 /*********************************************************************** 1151 * GetPrivateProfileSection32A (KERNEL32.255) 1152 */ 1153 ODINFUNCTION4(INT, GetPrivateProfileSectionA, 1154 LPCSTR, section, 1155 LPSTR, buffer, 1156 DWORD, len, 1157 LPCSTR, filename) 1158 { 1159 int ret = 0; 1160 1161 EnterCriticalSection( &PROFILE_CritSect ); 1162 1163 if (PROFILE_Open( filename )) 1164 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, 1165 FALSE, TRUE); 1166 1167 LeaveCriticalSection( &PROFILE_CritSect ); 1168 1169 return ret; 1170 } 1171 1172 /*********************************************************************** 1173 * GetPrivateProfileSection32W (KERNEL32.256) 1174 */ 1175 1176 ODINFUNCTION4(INT, GetPrivateProfileSectionW, 1177 LPCWSTR, section, 1178 LPWSTR, buffer, 1179 DWORD, len, 1180 LPCWSTR, filename) 1181 1182 { 1183 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1184 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1185 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len ); 1186 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len, 1187 filenameA ); 1188 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len); 1189 HeapFree( GetProcessHeap(), 0, sectionA ); 1190 HeapFree( GetProcessHeap(), 0, filenameA ); 1191 HeapFree( GetProcessHeap(), 0, bufferA); 1192 return ret; 1193 } 1194 1195 /*********************************************************************** 1196 * GetProfileSection32A (KERNEL32.268) 1197 */ 1198 ODINFUNCTION3(INT, GetProfileSectionA, 1199 LPCSTR, section, 1200 LPSTR, buffer, 1201 DWORD, len) 1202 { 1203 return GetPrivateProfileSectionA( section, buffer, len, WINININAME ); 1204 } 1205 1206 /*********************************************************************** 1207 * GetProfileSection32W (KERNEL32) 1208 */ 1209 ODINFUNCTION3(INT, GetProfileSectionW, 1210 LPCWSTR, section, 1211 LPWSTR, buffer, 1212 DWORD, len) 1213 { 1214 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME ); 1215 return GetPrivateProfileSectionW( section, buffer, len, wininiW ); 1216 } 1217 1218 /*********************************************************************** 1219 * WritePrivateProfileString32A (KERNEL32.582) 1220 */ 1221 ODINFUNCTION4(BOOL, WritePrivateProfileStringA, 1222 LPCSTR, section, 1223 LPCSTR, entry, 1224 LPCSTR, string, 1225 LPCSTR, filename) 1226 { 1227 BOOL ret = FALSE; 1228 1229 EnterCriticalSection( &PROFILE_CritSect ); 1230 1231 if (PROFILE_Open( filename )) 1232 { 1233 if (!section && !entry && !string) 1234 PROFILE_ReleaseFile(); /* always return FALSE in this case */ 1235 else 1236 ret = PROFILE_SetString( section, entry, string ); 1237 } 1238 1239 LeaveCriticalSection( &PROFILE_CritSect ); 1240 return ret; 1241 } 1242 1243 /*********************************************************************** 1244 * WritePrivateProfileString32W (KERNEL32.583) 1245 */ 1246 ODINFUNCTION4(BOOL, WritePrivateProfileStringW, 1247 LPCWSTR, section, 1248 LPCWSTR, entry, 1249 LPCWSTR, string, 1250 LPCWSTR, filename) 1251 { 1252 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1253 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry ); 1254 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string ); 1255 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1256 BOOL res = WritePrivateProfileStringA( sectionA, entryA, 1257 stringA, filenameA ); 1258 HeapFree( GetProcessHeap(), 0, sectionA ); 1259 HeapFree( GetProcessHeap(), 0, entryA ); 1260 HeapFree( GetProcessHeap(), 0, stringA ); 1261 HeapFree( GetProcessHeap(), 0, filenameA ); 1262 return res; 1263 } 1264 1265 /*********************************************************************** 1266 * WritePrivateProfileSection32A (KERNEL32) 1267 */ 1268 ODINFUNCTION3(BOOL, WritePrivateProfileSectionA, 1269 LPCSTR, section, 1270 LPCSTR, string, 1271 LPCSTR, filename) 1272 { 1273 char *p =(char*)string; 1274 1275 dprintf(("Kernel32:Profile:fixme WritePrivateProfileSection32A empty stub\n")); 1276 return FALSE; 1277 } 1278 1279 /*********************************************************************** 1280 * WritePrivateProfileSection32W (KERNEL32) 1281 */ 1282 ODINFUNCTION3(BOOL, WritePrivateProfileSectionW, 1283 LPCWSTR, section, 1284 LPCWSTR, string, 1285 LPCWSTR, filename) 1286 { 1287 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1288 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string ); 1289 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1290 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA ); 1291 HeapFree( GetProcessHeap(), 0, sectionA ); 1292 HeapFree( GetProcessHeap(), 0, stringA ); 1293 HeapFree( GetProcessHeap(), 0, filenameA ); 1294 return res; 1295 } 1296 1297 /*********************************************************************** 1298 * WriteProfileSection32A (KERNEL32.747) 1299 */ 1300 ODINFUNCTION2(BOOL, WriteProfileSectionA, 1301 LPCSTR, section, 1302 LPCSTR, keys_n_values) 1303 { 1304 return WritePrivateProfileSectionA( section, keys_n_values, WINININAME); 1305 } 1306 1307 /*********************************************************************** 1308 * WriteProfileSection32W (KERNEL32.748) 1309 */ 1310 ODINFUNCTION2(BOOL, WriteProfileSectionW, 1311 LPCWSTR, section, 1312 LPCWSTR, keys_n_values) 1313 { 1314 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME); 1315 1316 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW)); 1317 } 1318 1319 /*********************************************************************** 1320 * GetPrivateProfileSectionNames16 (KERNEL.143) 1321 */ 1322 ODINFUNCTION3(WORD, GetPrivateProfileSectionNames16, 1323 LPSTR, buffer, 1324 WORD, size, 1325 LPCSTR, filename) 1326 { 1327 WORD ret = 0; 1328 1329 EnterCriticalSection( &PROFILE_CritSect ); 1330 1331 if (PROFILE_Open( filename )) 1332 ret = PROFILE_GetSectionNames(buffer, size); 1333 1334 LeaveCriticalSection( &PROFILE_CritSect ); 1335 1336 return ret; 1337 } 1338 1339 /*********************************************************************** 1340 * GetPrivateProfileSectionNames32A (KERNEL32.365) 1341 */ 1342 ODINFUNCTION3(DWORD, GetPrivateProfileSectionNamesA, 1343 LPSTR, buffer, 1344 DWORD, size, 1345 LPCSTR, filename) 1346 { 1347 return (GetPrivateProfileSectionNames16 (buffer,size,filename)); 1348 } 1349 1350 /*********************************************************************** 1351 * GetPrivateProfileSectionNames32W (KERNEL32.366) 1352 */ 1353 ODINFUNCTION3(DWORD, GetPrivateProfileSectionNamesW, 1354 LPWSTR, buffer, 1355 DWORD, size, 1356 LPCWSTR, filename) 1357 { 1358 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1359 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size); 1360 1361 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA); 1362 lstrcpynAtoW( buffer, bufferA, size); 1363 HeapFree( GetProcessHeap(), 0, bufferA); 1364 HeapFree( GetProcessHeap(), 0, filenameA ); 1365 1366 return ret; 1367 } 1368 1369 /*********************************************************************** 1370 * GetPrivateProfileStruct32A (KERNEL32.370) 1371 */ 1372 ODINFUNCTION5(BOOL, GetPrivateProfileStructA, 1373 LPCSTR, section, 1374 LPCSTR, key, 1375 LPVOID, buf, 1376 UINT, len, 1377 LPCSTR, filename) 1378 { 1379 BOOL ret = FALSE; 1380 1381 EnterCriticalSection( &PROFILE_CritSect ); 1382 1383 if (PROFILE_Open( filename )) { 1384 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE); 1385 if (k) { 1386 lstrcpynA( (LPSTR)buf, k->value, strlen(k->value)); 1387 ret = TRUE; 1388 } 1389 } 1390 LeaveCriticalSection( &PROFILE_CritSect ); 1391 1392 return FALSE; 1393 } 1394 1395 /*********************************************************************** 1396 * GetPrivateProfileStruct32W (KERNEL32.543) 1397 */ 1398 ODINFUNCTION5(BOOL, GetPrivateProfileStructW, 1399 LPCWSTR, section, 1400 LPCWSTR, key, 1401 LPVOID, buffer, 1402 UINT, len, 1403 LPCWSTR, filename) 1404 { 1405 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1406 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key); 1407 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1408 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len ); 1409 1410 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA, 1411 len, filenameA ); 1412 lstrcpynAtoW( (LPWSTR)buffer, bufferA, len ); 1413 HeapFree( GetProcessHeap(), 0, bufferA); 1414 HeapFree( GetProcessHeap(), 0, sectionA ); 1415 HeapFree( GetProcessHeap(), 0, keyA ); 1416 HeapFree( GetProcessHeap(), 0, filenameA ); 1417 1418 return ret; 1419 } 1420 1421 1422 /*********************************************************************** 1423 * WritePrivateProfileStruct32A (KERNEL32.744) 1424 */ 1425 ODINFUNCTION5(BOOL, WritePrivateProfileStructA, 1426 LPCSTR, section, 1427 LPCSTR, key, 1428 LPVOID, buf, 1429 UINT, bufsize, 1430 LPCSTR, filename) 1431 { 1432 BOOL ret = FALSE; 1433 1434 if (!section && !key && !buf) /* flush the cache */ 1435 return WritePrivateProfileStringA( NULL, NULL, NULL, filename ); 1436 1437 EnterCriticalSection( &PROFILE_CritSect ); 1438 1439 if (PROFILE_Open( filename )) 1440 ret = PROFILE_SetString( section, key, (LPCSTR)buf ); 1441 1442 LeaveCriticalSection( &PROFILE_CritSect ); 1443 1444 return ret; 1445 } 1446 1447 /*********************************************************************** 1448 * WritePrivateProfileStruct32W (KERNEL32.544) 1449 */ 1450 ODINFUNCTION5(BOOL, WritePrivateProfileStructW, 1451 LPCWSTR, section, 1452 LPCWSTR, key, 1453 LPVOID, buf, 1454 UINT, bufsize, 1455 LPCWSTR, filename) 1456 { 1457 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1458 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key); 1459 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1460 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize, 1461 filenameA ); 1462 HeapFree( GetProcessHeap(), 0, sectionA ); 1463 HeapFree( GetProcessHeap(), 0, keyA ); 1464 HeapFree( GetProcessHeap(), 0, filenameA ); 1465 1466 return ret; 1467 } 1468 1469 /*********************************************************************** 1470 * WriteOutProfiles (KERNEL.315) 1471 * CB: original: 16 bit function 1472 * here: necessary to save open ini files 1473 */ 1474 ODINPROCEDURE0(WriteOutProfiles) 1475 { 1476 PROFILE *lastCurProfile; 1477 INT x; 1478 1479 EnterCriticalSection(&PROFILE_CritSect); 1480 1481 if (CurProfile && CurProfile->filename) 1482 PROFILE_FlushFile(); //flash current 1483 1484 if (MRUProfile) 1485 { 1486 lastCurProfile = CurProfile; 1487 for(x = 1;x < N_CACHED_PROFILES;x++) 1488 { 1489 if (MRUProfile[x] && MRUProfile[x]->filename) 1490 { 1491 CurProfile = MRUProfile[x]; 1492 PROFILE_FlushFile(); 1493 } 1494 } 1495 CurProfile = lastCurProfile; 1496 } 1497 LeaveCriticalSection(&PROFILE_CritSect); 1498 } 1499 1500 14 1501 15 #include <os2win.h>16 #include <ctype.h>17 #include <stdlib.h>18 #include <string.h>19 #include <stdio.h>20 #include <unicode.h>21 #include "heap.h"22 #include "heapstring.h"23 24 #include <sys/stat.h>25 26 #include "winbase.h"27 //#include "wine/winbase16.h"28 #include "winuser.h"29 #include "winnls.h"30 31 32 // -------------------------33 // WINE compatibility macros34 // -------------------------35 36 #ifndef MAX_PATHNAME_LEN37 #define MAX_PATHNAME_LEN 26038 #endif39 40 #define SystemHeap GetProcessHeap()41 #define strcasecmp strcmp42 #define DOSFS_GetFullName(a,b,c) strcpy(c,a)43 //#define lstrcpynA(a,b,c) strncpy((char*)a,(char*)b,(int)c)44 #define CharLowerA(a) (a)45 46 47 typedef struct tagPROFILEKEY48 {49 char *name;50 char *value;51 struct tagPROFILEKEY *next;52 } PROFILEKEY;53 54 typedef struct tagPROFILESECTION55 {56 char *name;57 struct tagPROFILEKEY *key;58 struct tagPROFILESECTION *next;59 } PROFILESECTION;60 61 62 typedef struct63 {64 BOOL changed;65 PROFILESECTION *section;66 char *filename; //first open name67 char *fullname; //name with path68 time_t mtime;69 } PROFILE;70 71 72 #define N_CACHED_PROFILES 1073 74 /* Cached profile files */75 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};76 77 #define CurProfile (MRUProfile[0])78 79 /* wine.ini profile content */80 static PROFILESECTION *PROFILE_WineProfile;81 82 #define PROFILE_MAX_LINE_LEN 102483 #define WINININAME "WIN.INI"84 85 /* Wine profile name in $HOME directory; must begin with slash */86 static const char PROFILE_WineIniName[] = "/.winerc";87 88 /* Wine profile: the profile file being used */89 static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";90 91 /* Check for comments in profile */92 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')93 94 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"95 96 static LPCWSTR wininiW = NULL; //CB: never freed97 98 static CRITICAL_SECTION PROFILE_CritSect;99 100 101 /***********************************************************************102 * PROFILE_CopyEntry103 *104 * Copy the content of an entry into a buffer, removing quotes, and possibly105 * translating environment variables.106 */107 static void PROFILE_CopyEntry( char *buffer,108 const char *value,109 int len,110 int handle_env )111 {112 char quote = '\0';113 const char *p;114 115 if ((*value == '\'') || (*value == '\"'))116 {117 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;118 }119 120 if (!handle_env)121 {122 lstrcpynA( buffer, value, len );123 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';124 return;125 }126 127 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )128 {129 if ((*p == '$') && (p[1] == '{'))130 {131 char env_val[1024];132 const char *env_p;133 const char *p2 = strchr( p, '}' );134 if (!p2) continue; /* ignore it */135 lstrcpynA(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));136 if ((env_p = getenv( env_val )) != NULL)137 {138 lstrcpynA( buffer, env_p, len );139 buffer += strlen( buffer );140 len -= strlen( buffer );141 }142 p = p2 + 1;143 }144 }145 *buffer = '\0';146 }147 148 149 /***********************************************************************150 * PROFILE_Save151 *152 * Save a profile tree to a file.153 */154 static void PROFILE_Save( FILE *file, PROFILESECTION *section )155 {156 PROFILEKEY *key;157 158 for ( ; section; section = section->next)159 {160 if (section->name) fprintf( file, "\n[%s]\n", section->name );161 for (key = section->key; key; key = key->next)162 {163 fprintf( file, "%s", key->name );164 if (key->value) fprintf( file, "=%s", key->value );165 fprintf( file, "\n" );166 }167 }168 }169 170 171 /***********************************************************************172 * PROFILE_Free173 *174 * Free a profile tree.175 */176 static void PROFILE_Free( PROFILESECTION *section )177 {178 PROFILESECTION *next_section;179 PROFILEKEY *key, *next_key;180 181 for ( ; section; section = next_section)182 {183 if (section->name) HeapFree( SystemHeap, 0, section->name );184 for (key = section->key; key; key = next_key)185 {186 next_key = key->next;187 if (key->name) HeapFree( SystemHeap, 0, key->name );188 if (key->value) HeapFree( SystemHeap, 0, key->value );189 HeapFree( SystemHeap, 0, key );190 }191 next_section = section->next;192 HeapFree( SystemHeap, 0, section );193 }194 }195 196 static int197 PROFILE_isspace(char c) {198 if (isspace(c)) return 1;199 if (c=='\r' || c==0x1a) return 1;200 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */201 return 0;202 }203 204 205 /***********************************************************************206 * PROFILE_Load207 *208 * Load a profile tree from a file.209 */210 static PROFILESECTION *PROFILE_Load( FILE *file )211 {212 char buffer[PROFILE_MAX_LINE_LEN];213 char *p, *p2;214 int line = 0;215 PROFILESECTION *section, *first_section;216 PROFILESECTION **next_section;217 PROFILEKEY *key, *prev_key, **next_key;218 219 first_section = (PROFILESECTION *)HEAP_xalloc( SystemHeap, 0, sizeof(*section) );220 first_section->name = NULL;221 first_section->key = NULL;222 first_section->next = NULL;223 next_section = &first_section->next;224 next_key = &first_section->key;225 prev_key = NULL;226 227 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))228 {229 line++;230 p = buffer;231 while (*p && PROFILE_isspace(*p)) p++;232 if (*p == '[') /* section start */233 {234 if (!(p2 = strrchr( p, ']' )))235 {236 dprintf(("Kernel32:Profile:Invalid section header at line %d: '%s'\n",237 line, p ));238 }239 else240 {241 *p2 = '\0';242 p++;243 section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(*section) );244 section->name = HEAP_strdupA( SystemHeap, 0, p );245 section->key = NULL;246 section->next = NULL;247 *next_section = section;248 next_section = §ion->next;249 next_key = §ion->key;250 prev_key = NULL;251 252 dprintf(("Kernel32:Profile:New section: '%s'\n",section->name));253 254 continue;255 }256 }257 258 p2=p+strlen(p) - 1;259 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';260 261 if ((p2 = strchr( p, '=' )) != NULL)262 {263 char *p3 = p2 - 1;264 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';265 *p2++ = '\0';266 while (*p2 && PROFILE_isspace(*p2)) p2++;267 }268 269 if(*p || !prev_key || *prev_key->name)270 {271 key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(*key) );272 key->name = HEAP_strdupA( SystemHeap, 0, p );273 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;274 key->next = NULL;275 *next_key = key;276 next_key = &key->next;277 prev_key = key;278 279 dprintf(("Kernel32:Profile:New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)"));280 }281 }282 return first_section;283 }284 285 286 /***********************************************************************287 * PROFILE_DeleteSection288 *289 * Delete a section from a profile tree.290 */291 static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )292 {293 while (*section)294 {295 if ((*section)->name && !strcasecmp( (*section)->name, name ))296 {297 PROFILESECTION *to_del = *section;298 *section = to_del->next;299 to_del->next = NULL;300 PROFILE_Free( to_del );301 return TRUE;302 }303 section = &(*section)->next;304 }305 return FALSE;306 }307 308 309 /***********************************************************************310 * PROFILE_DeleteKey311 *312 * Delete a key from a profile tree.313 */314 static BOOL PROFILE_DeleteKey( PROFILESECTION **section,315 LPCSTR section_name, LPCSTR key_name )316 {317 while (*section)318 {319 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))320 {321 PROFILEKEY **key = &(*section)->key;322 while (*key)323 {324 if (!strcasecmp( (*key)->name, key_name ))325 {326 PROFILEKEY *to_del = *key;327 *key = to_del->next;328 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );329 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);330 HeapFree( SystemHeap, 0, to_del );331 return TRUE;332 }333 key = &(*key)->next;334 }335 }336 section = &(*section)->next;337 }338 return FALSE;339 }340 341 342 /***********************************************************************343 * PROFILE_Find344 *345 * Find a key in a profile tree, optionally creating it.346 */347 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,348 const char *section_name,349 const char *key_name, int create )350 {351 while (*section)352 {353 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))354 {355 PROFILEKEY **key = &(*section)->key;356 while (*key)357 {358 if (!strcasecmp( (*key)->name, key_name )) return *key;359 key = &(*key)->next;360 }361 if (!create) return NULL;362 *key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );363 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );364 (*key)->value = NULL;365 (*key)->next = NULL;366 return *key;367 }368 section = &(*section)->next;369 }370 if (!create) return NULL;371 *section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );372 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );373 (*section)->next = NULL;374 (*section)->key = (tagPROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );375 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );376 (*section)->key->value = NULL;377 (*section)->key->next = NULL;378 return (*section)->key;379 }380 381 382 /***********************************************************************383 * PROFILE_FlushFile384 *385 * Flush the current profile to disk if changed.386 */387 static BOOL PROFILE_FlushFile(void)388 {389 FILE *file = NULL;390 struct stat buf;391 392 if(!CurProfile)393 {394 dprintf(("Kernel32:Profile:No current profile!\n"));395 return FALSE;396 }397 398 // not changed, return immediately399 if (!CurProfile->changed)400 return TRUE;401 402 // try to open file403 file = fopen(CurProfile->fullname, "w");404 if (!file)405 {406 dprintf(("Kernel32:Profile:could not save profile file %s\n", CurProfile->fullname));407 return FALSE;408 }409 410 dprintf(("Kernel32:Profile:Saving %s\n", CurProfile->fullname ));411 PROFILE_Save( file, CurProfile->section );412 fclose( file );413 CurProfile->changed = FALSE;414 if(!stat(CurProfile->fullname,&buf))415 CurProfile->mtime=buf.st_mtime;416 return TRUE;417 }418 419 420 /***********************************************************************421 * PROFILE_ReleaseFile422 *423 * Flush the current profile to disk and remove it from the cache.424 */425 static void PROFILE_ReleaseFile(void)426 {427 PROFILE_FlushFile();428 PROFILE_Free( CurProfile->section );429 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );430 if (CurProfile->fullname) HeapFree(SystemHeap,0,CurProfile->fullname);431 CurProfile->changed = FALSE;432 CurProfile->section = NULL;433 CurProfile->filename = NULL;434 CurProfile->fullname = NULL;435 CurProfile->mtime = 0;436 }437 438 439 /***********************************************************************440 * PROFILE_Open441 *442 * Open a profile file, checking the cached file first.443 */444 static BOOL PROFILE_Open( LPCSTR filename )445 {446 FILE *file = NULL;447 int i,j;448 struct stat buf;449 PROFILE *tempProfile;450 451 if (!filename || filename[0] == 0) return FALSE;452 453 /* First time around */454 455 if(!CurProfile)456 for(i=0;i<N_CACHED_PROFILES;i++)457 {458 MRUProfile[i]= (PROFILE*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );459 MRUProfile[i]->changed=FALSE;460 MRUProfile[i]->section=NULL;461 MRUProfile[i]->filename=NULL;462 MRUProfile[i]->fullname=NULL;463 MRUProfile[i]->mtime=0;464 }465 466 /* Check for a match */467 468 for(i=0;i<N_CACHED_PROFILES;i++)469 {470 if (MRUProfile[i]->filename && (!strcmp(filename,MRUProfile[i]->filename) || !strcmp(filename,MRUProfile[i]->fullname)))471 {472 if(i)473 {474 PROFILE_FlushFile();475 tempProfile=MRUProfile[i];476 for(j=i;j>0;j--)477 MRUProfile[j]=MRUProfile[j-1];478 CurProfile=tempProfile;479 }480 if(!stat(CurProfile->fullname,&buf) && CurProfile->mtime==buf.st_mtime)481 dprintf(("Kernel32:Profile:(%s): already opened (mru=%d)\n",482 filename, i ));483 else484 dprintf(("Kernel32:Profile:(%s): already opened, needs refreshing (mru=%d)\n",485 filename, i ));486 return TRUE;487 }488 }489 490 /* Rotate the oldest to the top to be replaced */491 492 if(i==N_CACHED_PROFILES)493 {494 tempProfile=MRUProfile[N_CACHED_PROFILES-1];495 for(i=N_CACHED_PROFILES-1;i>0;i--)496 MRUProfile[i]=MRUProfile[i-1];497 CurProfile=tempProfile;498 }499 500 /* Flush the profile */501 502 if(CurProfile->filename) PROFILE_ReleaseFile();503 504 CurProfile->filename = HEAP_strdupA(SystemHeap,0,filename);505 506 /* check for path */507 508 if ((!strchr( filename,'/') &&509 !strchr( filename,'\\')) ||510 !strchr( filename,':'))511 {512 char fullname[MAX_PATHNAME_LEN];513 514 GetWindowsDirectoryA(fullname,sizeof(fullname));515 strcat(fullname,"\\");516 strcat(fullname,filename);517 CurProfile->fullname = HEAP_strdupA(SystemHeap,0,fullname);518 } else CurProfile->fullname = HEAP_strdupA(SystemHeap,0,filename);519 520 file = fopen(CurProfile->fullname,"r");521 if (file)522 {523 dprintf(("Kernel32:Profile:(%s): found it in %s\n",524 filename, CurProfile->fullname ));525 526 CurProfile->section = PROFILE_Load( file );527 fclose( file );528 if(!stat(CurProfile->fullname,&buf))529 CurProfile->mtime=buf.st_mtime;530 }531 else532 {533 /* Does not exist yet, we will create it in PROFILE_FlushFile */534 dprintf(("Kernel32:Profile:profile file %s not found\n", CurProfile->fullname ));535 }536 return TRUE;537 }538 539 540 /***********************************************************************541 * PROFILE_GetSection542 *543 * Returns all keys of a section.544 * If return_values is TRUE, also include the corresponding values.545 */546 static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,547 LPSTR buffer, UINT len, BOOL handle_env,548 BOOL return_values )549 {550 PROFILEKEY *key;551 while (section)552 {553 if (section->name && !strcasecmp( section->name, section_name ))554 {555 UINT oldlen = len;556 for (key = section->key; key; key = key->next)557 {558 if (len <= 2) break;559 if (!*key->name) continue; /* Skip empty lines */560 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */561 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );562 len -= strlen(buffer) + 1;563 buffer += strlen(buffer) + 1;564 if (return_values && key->value) {565 buffer[-1] = '=';566 PROFILE_CopyEntry ( buffer,567 key->value, len - 1, handle_env );568 len -= strlen(buffer) + 1;569 buffer += strlen(buffer) + 1;570 }571 }572 *buffer = '\0';573 if (len <= 1)574 /*If either lpszSection or lpszKey is NULL and the supplied575 destination buffer is too small to hold all the strings,576 the last string is truncated and followed by two null characters.577 In this case, the return value is equal to cchReturnBuffer578 minus two. */579 {580 buffer[-1] = '\0';581 return oldlen - 2;582 }583 return oldlen - len;584 }585 section = section->next;586 }587 buffer[0] = buffer[1] = '\0';588 return 0;589 }590 591 592 static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )593 {594 LPSTR buf = buffer;595 WORD l, cursize = 0;596 PROFILESECTION *section;597 598 for (section = CurProfile->section; section; section = section->next)599 if (section->name) {600 l = strlen(section->name);601 cursize += l+1;602 if (cursize > len+1)603 return len-2;604 605 strcpy(buf, section->name);606 buf += l+1;607 }608 609 *buf=0;610 buf++;611 return buf-buffer;612 }613 614 615 /***********************************************************************616 * PROFILE_GetString617 *618 * Get a profile string.619 */620 static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,621 LPCSTR def_val, LPSTR buffer, UINT len )622 {623 PROFILEKEY *key = NULL;624 625 if (!def_val) def_val = "";626 if (key_name && key_name[0])627 {628 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );629 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,630 len, FALSE );631 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",632 section, key_name, def_val, buffer ));633 return strlen( buffer );634 }635 if (section && section[0])636 return PROFILE_GetSection(CurProfile->section, section, buffer, len,637 FALSE, FALSE);638 /* undocumented; both section and key_name are NULL */639 return PROFILE_GetSectionNames(buffer, len);640 }641 642 643 /***********************************************************************644 * PROFILE_SetString645 *646 * Set a profile string.647 */648 static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,649 LPCSTR value )650 {651 if (!key_name) /* Delete a whole section */652 {653 dprintf(("Kernel32:Profile:('%s')\n", section_name));654 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,655 section_name );656 return TRUE; /* Even if PROFILE_DeleteSection() has failed,657 this is not an error on application's level.*/658 }659 else if (!value) /* Delete a key */660 {661 dprintf(("Kernel32:Profile:('%s','%s')\n",662 section_name, key_name ));663 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,664 section_name, key_name );665 return TRUE; /* same error handling as above */666 }667 else /* Set the key value */668 {669 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,670 key_name, TRUE );671 dprintf(("Kernel32:Profile:('%s','%s','%s'): \n",672 section_name, key_name, value ));673 if (!key) return FALSE;674 if (key->value)675 {676 if (!strcmp( key->value, value ))677 {678 dprintf(("Kernel32:Profile: no change needed\n" ));679 return TRUE; /* No change needed */680 }681 dprintf(("Kernel32:Profile: replacing '%s'\n", key->value ));682 HeapFree( SystemHeap, 0, key->value );683 }684 else dprintf(("Kernel32:Profile: creating key\n" ));685 key->value = HEAP_strdupA( SystemHeap, 0, value );686 CurProfile->changed = TRUE;687 }688 return TRUE;689 }690 691 692 /***********************************************************************693 * PROFILE_GetWineIniString694 *695 * Get a config string from the wine.ini file.696 */697 int PROFILE_GetWineIniString( const char *section, const char *key_name,698 const char *def, char *buffer, int len )699 {700 int ret;701 702 EnterCriticalSection( &PROFILE_CritSect );703 704 if (key_name)705 {706 PROFILEKEY *key = PROFILE_Find(&PROFILE_WineProfile, section, key_name, FALSE);707 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,708 len, TRUE );709 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",710 section, key_name, def, buffer ));711 ret = strlen( buffer );712 }713 else714 {715 ret = PROFILE_GetSection( PROFILE_WineProfile, section, buffer, len, TRUE, FALSE );716 }717 LeaveCriticalSection( &PROFILE_CritSect );718 719 return ret;720 }721 722 723 /***********************************************************************724 * PROFILE_GetWineIniInt725 *726 * Get a config integer from the wine.ini file.727 */728 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )729 {730 char buffer[20];731 char *p;732 long result;733 PROFILEKEY *key;734 int ret;735 736 EnterCriticalSection( &PROFILE_CritSect );737 738 key = PROFILE_Find( &PROFILE_WineProfile, section, key_name, FALSE );739 if (!key || !key->value) {740 ret = def;741 } else {742 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );743 result = strtol( buffer, &p, 0 );744 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result;745 }746 747 LeaveCriticalSection( &PROFILE_CritSect );748 749 return ret;750 }751 752 753 /******************************************************************************754 *755 * int PROFILE_EnumerateWineIniSection(756 * char const *section, #Name of the section to enumerate757 * void (*cbfn)(char const *key, char const *value, void *user),758 * # Address of the callback function759 * void *user ) # User-specified pointer.760 *761 * For each entry in a section in the wine.conf file, this function will762 * call the specified callback function, informing it of each key and763 * value. An optional user pointer may be passed to it (if this is not764 * needed, pass NULL through it and ignore the value in the callback765 * function).766 *767 * The callback function must accept three parameters:768 * The name of the key (char const *)769 * The value of the key (char const *)770 * A user-specified parameter (void *)771 * Note that the first two are char CONST *'s, not char *'s! The callback772 * MUST not modify these strings!773 *774 * The return value indicates the number of times the callback function775 * was called.776 */777 int PROFILE_EnumerateWineIniSection(778 char const *section,779 void (*cbfn)(char const *, char const *, void *),780 void *userptr )781 {782 PROFILESECTION *scansect;783 PROFILEKEY *scankey;784 int calls = 0;785 786 EnterCriticalSection( &PROFILE_CritSect );787 788 /* Search for the correct section */789 for(scansect = PROFILE_WineProfile; scansect; scansect = scansect->next) {790 if(scansect->name && !strcasecmp(scansect->name, section)) {791 792 /* Enumerate each key with the callback */793 for(scankey = scansect->key; scankey; scankey = scankey->next) {794 795 /* Ignore blank entries -- these shouldn't exist, but let's796 be extra careful */797 if(scankey->name[0]) {798 cbfn(scankey->name, scankey->value, userptr);799 ++calls;800 }801 }802 803 break;804 }805 }806 LeaveCriticalSection( &PROFILE_CritSect );807 808 return calls;809 }810 811 812 /******************************************************************************813 *814 * int PROFILE_GetWineIniBool(815 * char const *section,816 * char const *key_name,817 * int def )818 *819 * Reads a boolean value from the wine.ini file. This function attempts to820 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'821 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for822 * true. Anything else results in the return of the default value.823 *824 * This function uses 1 to indicate true, and 0 for false. You can check825 * for existence by setting def to something other than 0 or 1 and826 * examining the return value.827 */828 int PROFILE_GetWineIniBool(829 char const *section,830 char const *key_name,831 int def )832 {833 char key_value[2];834 int retval;835 836 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);837 838 switch(key_value[0]) {839 case 'n':840 case 'N':841 case 'f':842 case 'F':843 case '0':844 retval = 0;845 break;846 847 case 'y':848 case 'Y':849 case 't':850 case 'T':851 case '1':852 retval = 1;853 break;854 855 default:856 retval = def;857 }858 859 dprintf(("Kernel32:Profile:(\"%s\", \"%s\", %s), "860 "[%c], ret %s.\n", section, key_name,861 def ? "TRUE" : "FALSE", key_value[0],862 retval ? "TRUE" : "FALSE"));863 864 return retval;865 }866 867 868 #if 0869 /***********************************************************************870 * PROFILE_LoadWineIni871 *872 * Load the wine.ini file.873 */874 int PROFILE_LoadWineIni(void)875 {876 char buffer[MAX_PATHNAME_LEN];877 const char *p;878 FILE *f;879 880 InitializeCriticalSection( &PROFILE_CritSect );881 MakeCriticalSectionGlobal( &PROFILE_CritSect );882 883 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )884 {885 /* Open -config specified file */886 PROFILE_WineProfile = PROFILE_Load ( f);887 fclose ( f );888 strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);889 return 1;890 }891 892 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )893 {894 PROFILE_WineProfile = PROFILE_Load( f );895 fclose( f );896 strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);897 return 1;898 }899 if ((p = getenv( "HOME" )) != NULL)900 {901 lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));902 strcat( buffer, PROFILE_WineIniName );903 if ((f = fopen( buffer, "r" )) != NULL)904 {905 PROFILE_WineProfile = PROFILE_Load( f );906 fclose( f );907 strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);908 return 1;909 }910 }911 else dprintf(("Kernel32:Profile:could not get $HOME value for config file.\n" ));912 913 /* Try global file */914 915 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)916 {917 PROFILE_WineProfile = PROFILE_Load( f );918 fclose( f );919 strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);920 return 1;921 }922 MESSAGE( "Can't open configuration file %s or $HOME%s\n",923 WINE_INI_GLOBAL, PROFILE_WineIniName );924 return 0;925 }926 927 928 /***********************************************************************929 * PROFILE_UsageWineIni930 *931 * Explain the wine.ini file to those who don't read documentation.932 * Keep below one screenful in length so that error messages above are933 * noticed.934 */935 void PROFILE_UsageWineIni(void)936 {937 MESSAGE("Perhaps you have not properly edited or created "938 "your Wine configuration file.\n");939 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);940 MESSAGE(" or it is determined by the -config option or from\n"941 " the WINE_INI environment variable.\n");942 if (*PROFILE_WineIniUsed)943 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);944 /* RTFM, so to say */945 }946 #endif947 948 /***********************************************************************949 * PROFILE_GetStringItem950 *951 * Convenience function that turns a string 'xxx, yyy, zzz' into952 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.953 */954 char* PROFILE_GetStringItem( char* start )955 {956 char* lpchX, *lpch;957 958 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )959 {960 if( *lpchX == ',' )961 {962 if( lpch ) *lpch = '\0'; else *lpchX = '\0';963 while( *(++lpchX) )964 if( !PROFILE_isspace(*lpchX) ) return lpchX;965 }966 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;967 else lpch = NULL;968 }969 if( lpch ) *lpch = '\0';970 return NULL;971 }972 973 /********************* API functions **********************************/974 975 /***********************************************************************976 * GetProfileInt32A (KERNEL32.264)977 */978 UINT WINAPI GetProfileIntA( LPCSTR section, LPCSTR entry, INT def_val )979 {980 return GetPrivateProfileIntA( section, entry, def_val, WINININAME );981 }982 983 /***********************************************************************984 * GetProfileInt32W (KERNEL32.264)985 */986 UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )987 {988 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );989 return GetPrivateProfileIntW( section, entry, def_val, wininiW );990 }991 992 /***********************************************************************993 * GetProfileString32A (KERNEL32.268)994 */995 INT WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,996 LPSTR buffer, UINT len )997 {998 return GetPrivateProfileStringA( section, entry, def_val,999 buffer, len, WINININAME );1000 }1001 1002 /***********************************************************************1003 * GetProfileString32W (KERNEL32.269)1004 */1005 INT WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry,1006 LPCWSTR def_val, LPWSTR buffer, UINT len )1007 {1008 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );1009 return GetPrivateProfileStringW( section, entry, def_val,1010 buffer, len, wininiW );1011 }1012 1013 /***********************************************************************1014 * WriteProfileString32A (KERNEL32.587)1015 */1016 BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry,1017 LPCSTR string )1018 {1019 return WritePrivateProfileStringA( section, entry, string, WINININAME );1020 }1021 1022 /***********************************************************************1023 * WriteProfileString32W (KERNEL32.588)1024 */1025 BOOL WINAPI WriteProfileStringW( LPCWSTR section, LPCWSTR entry,1026 LPCWSTR string )1027 {1028 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );1029 return WritePrivateProfileStringW( section, entry, string, wininiW );1030 }1031 1032 /***********************************************************************1033 * GetPrivateProfileInt32A (KERNEL32.251)1034 */1035 UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,1036 INT def_val, LPCSTR filename )1037 {1038 char buffer[20];1039 char *p;1040 long result;1041 1042 GetPrivateProfileStringA( section, entry, "",1043 buffer, sizeof(buffer), filename );1044 if (!buffer[0]) return (UINT)def_val;1045 result = strtol( buffer, &p, 0 );1046 if (p == buffer) return 0; /* No digits at all */1047 return (UINT)result;1048 }1049 1050 /***********************************************************************1051 * GetPrivateProfileInt32W (KERNEL32.252)1052 */1053 UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,1054 INT def_val, LPCWSTR filename )1055 {1056 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );1057 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );1058 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );1059 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);1060 HeapFree( GetProcessHeap(), 0, sectionA );1061 HeapFree( GetProcessHeap(), 0, filenameA );1062 HeapFree( GetProcessHeap(), 0, entryA );1063 return res;1064 }1065 1066 /***********************************************************************1067 * GetPrivateProfileString32A (KERNEL32.255)1068 */1069 INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,1070 LPCSTR def_val, LPSTR buffer,1071 UINT len, LPCSTR filename )1072 {1073 int ret;1074 1075 if (!filename)1076 filename = WINININAME;1077 1078 EnterCriticalSection( &PROFILE_CritSect );1079 1080 if (PROFILE_Open( filename )) {1081 ret = PROFILE_GetString( section, entry, def_val, buffer, len );1082 } else {1083 lstrcpynA( buffer, def_val, len );1084 ret = strlen( buffer );1085 }1086 1087 LeaveCriticalSection( &PROFILE_CritSect );1088 1089 return ret;1090 }1091 1092 /***********************************************************************1093 * GetPrivateProfileString32W (KERNEL32.256)1094 */1095 INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,1096 LPCWSTR def_val, LPWSTR buffer,1097 UINT len, LPCWSTR filename )1098 {1099 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );1100 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );1101 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );1102 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );1103 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );1104 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,1105 bufferA, len, filenameA );1106 lstrcpynAtoW( buffer, bufferA, len );1107 HeapFree( GetProcessHeap(), 0, sectionA );1108 HeapFree( GetProcessHeap(), 0, entryA );1109 HeapFree( GetProcessHeap(), 0, filenameA );1110 HeapFree( GetProcessHeap(), 0, def_valA );1111 HeapFree( GetProcessHeap(), 0, bufferA);1112 return ret;1113 }1114 1115 /***********************************************************************1116 * GetPrivateProfileSection32A (KERNEL32.255)1117 */1118 INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,1119 DWORD len, LPCSTR filename )1120 {1121 int ret = 0;1122 1123 EnterCriticalSection( &PROFILE_CritSect );1124 1125 if (PROFILE_Open( filename ))1126 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,1127 FALSE, TRUE);1128 1129 LeaveCriticalSection( &PROFILE_CritSect );1130 1131 return ret;1132 }1133 1134 /***********************************************************************1135 * GetPrivateProfileSection32W (KERNEL32.256)1136 */1137 1138 INT WINAPI GetPrivateProfileSectionW (LPCWSTR section, LPWSTR buffer,1139 DWORD len, LPCWSTR filename )1140 1141 {1142 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );1143 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );1144 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );1145 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,1146 filenameA );1147 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);1148 HeapFree( GetProcessHeap(), 0, sectionA );1149 HeapFree( GetProcessHeap(), 0, filenameA );1150 HeapFree( GetProcessHeap(), 0, bufferA);1151 return ret;1152 }1153 1154 /***********************************************************************1155 * GetProfileSection32A (KERNEL32.268)1156 */1157 INT WINAPI GetProfileSectionA( LPCSTR section, LPSTR buffer, DWORD len )1158 {1159 return GetPrivateProfileSectionA( section, buffer, len, WINININAME );1160 }1161 1162 /***********************************************************************1163 * GetProfileSection32W (KERNEL32)1164 */1165 INT WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len )1166 {1167 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );1168 return GetPrivateProfileSectionW( section, buffer, len, wininiW );1169 }1170 1171 /***********************************************************************1172 * WritePrivateProfileString32A (KERNEL32.582)1173 */1174 BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,1175 LPCSTR string, LPCSTR filename )1176 {1177 BOOL ret = FALSE;1178 1179 EnterCriticalSection( &PROFILE_CritSect );1180 1181 if (PROFILE_Open( filename ))1182 {1183 if (!section && !entry && !string)1184 PROFILE_ReleaseFile(); /* always return FALSE in this case */1185 else1186 ret = PROFILE_SetString( section, entry, string );1187 }1188 1189 LeaveCriticalSection( &PROFILE_CritSect );1190 return ret;1191 }1192 1193 /***********************************************************************1194 * WritePrivateProfileString32W (KERNEL32.583)1195 */1196 BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,1197 LPCWSTR string, LPCWSTR filename )1198 {1199 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );1200 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );1201 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );1202 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );1203 BOOL res = WritePrivateProfileStringA( sectionA, entryA,1204 stringA, filenameA );1205 HeapFree( GetProcessHeap(), 0, sectionA );1206 HeapFree( GetProcessHeap(), 0, entryA );1207 HeapFree( GetProcessHeap(), 0, stringA );1208 HeapFree( GetProcessHeap(), 0, filenameA );1209 return res;1210 }1211 1212 /***********************************************************************1213 * WritePrivateProfileSection32A (KERNEL32)1214 */1215 BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section,1216 LPCSTR string, LPCSTR filename )1217 {1218 char *p =(char*)string;1219 1220 dprintf(("Kernel32:Profile:fixme WritePrivateProfileSection32A empty stub\n"));1221 return FALSE;1222 }1223 1224 /***********************************************************************1225 * WritePrivateProfileSection32W (KERNEL32)1226 */1227 BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,1228 LPCWSTR string, LPCWSTR filename)1229 1230 {1231 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );1232 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );1233 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );1234 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );1235 HeapFree( GetProcessHeap(), 0, sectionA );1236 HeapFree( GetProcessHeap(), 0, stringA );1237 HeapFree( GetProcessHeap(), 0, filenameA );1238 return res;1239 }1240 1241 /***********************************************************************1242 * WriteProfileSection32A (KERNEL32.747)1243 */1244 BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values)1245 1246 {1247 return WritePrivateProfileSectionA( section, keys_n_values, WINININAME);1248 }1249 1250 /***********************************************************************1251 * WriteProfileSection32W (KERNEL32.748)1252 */1253 BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values)1254 {1255 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME);1256 1257 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW));1258 }1259 1260 /***********************************************************************1261 * GetPrivateProfileSectionNames16 (KERNEL.143)1262 */1263 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,1264 LPCSTR filename )1265 {1266 WORD ret = 0;1267 1268 EnterCriticalSection( &PROFILE_CritSect );1269 1270 if (PROFILE_Open( filename ))1271 ret = PROFILE_GetSectionNames(buffer, size);1272 1273 LeaveCriticalSection( &PROFILE_CritSect );1274 1275 return ret;1276 }1277 1278 /***********************************************************************1279 * GetPrivateProfileSectionNames32A (KERNEL32.365)1280 */1281 DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,1282 LPCSTR filename)1283 1284 {1285 return (GetPrivateProfileSectionNames16 (buffer,size,filename));1286 }1287 1288 /***********************************************************************1289 * GetPrivateProfileSectionNames32W (KERNEL32.366)1290 */1291 DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,1292 LPCWSTR filename)1293 1294 {1295 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );1296 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size);1297 1298 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);1299 lstrcpynAtoW( buffer, bufferA, size);1300 HeapFree( GetProcessHeap(), 0, bufferA);1301 HeapFree( GetProcessHeap(), 0, filenameA );1302 1303 return ret;1304 }1305 1306 /***********************************************************************1307 * GetPrivateProfileStruct32A (KERNEL32.370)1308 */1309 BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,1310 LPVOID buf, UINT len, LPCSTR filename)1311 {1312 BOOL ret = FALSE;1313 1314 EnterCriticalSection( &PROFILE_CritSect );1315 1316 if (PROFILE_Open( filename )) {1317 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);1318 if (k) {1319 lstrcpynA( (LPSTR)buf, k->value, strlen(k->value));1320 ret = TRUE;1321 }1322 }1323 LeaveCriticalSection( &PROFILE_CritSect );1324 1325 return FALSE;1326 }1327 1328 /***********************************************************************1329 * GetPrivateProfileStruct32W (KERNEL32.543)1330 */1331 BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,1332 LPVOID buffer, UINT len, LPCWSTR filename)1333 {1334 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );1335 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);1336 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );1337 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );1338 1339 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,1340 len, filenameA );1341 lstrcpynAtoW( (LPWSTR)buffer, bufferA, len );1342 HeapFree( GetProcessHeap(), 0, bufferA);1343 HeapFree( GetProcessHeap(), 0, sectionA );1344 HeapFree( GetProcessHeap(), 0, keyA );1345 HeapFree( GetProcessHeap(), 0, filenameA );1346 1347 return ret;1348 }1349 1350 1351 /***********************************************************************1352 * WritePrivateProfileStruct32A (KERNEL32.744)1353 */1354 BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,1355 LPVOID buf, UINT bufsize, LPCSTR filename)1356 {1357 BOOL ret = FALSE;1358 1359 if (!section && !key && !buf) /* flush the cache */1360 return WritePrivateProfileStringA( NULL, NULL, NULL, filename );1361 1362 EnterCriticalSection( &PROFILE_CritSect );1363 1364 if (PROFILE_Open( filename ))1365 ret = PROFILE_SetString( section, key, (LPCSTR)buf );1366 1367 LeaveCriticalSection( &PROFILE_CritSect );1368 1369 return ret;1370 }1371 1372 /***********************************************************************1373 * WritePrivateProfileStruct32W (KERNEL32.544)1374 */1375 BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,1376 LPVOID buf, UINT bufsize, LPCWSTR filename)1377 {1378 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );1379 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);1380 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );1381 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,1382 filenameA );1383 HeapFree( GetProcessHeap(), 0, sectionA );1384 HeapFree( GetProcessHeap(), 0, keyA );1385 HeapFree( GetProcessHeap(), 0, filenameA );1386 1387 return ret;1388 }1389 1390 /***********************************************************************1391 * WriteOutProfiles (KERNEL.315)1392 * CB: original: 16 bit function1393 * here: necessary to save open ini files1394 */1395 void WINAPI WriteOutProfiles(void)1396 {1397 PROFILE *lastCurProfile;1398 INT x;1399 1400 EnterCriticalSection(&PROFILE_CritSect);1401 1402 if (CurProfile && CurProfile->filename)1403 PROFILE_FlushFile(); //flash current1404 1405 if (MRUProfile)1406 {1407 lastCurProfile = CurProfile;1408 for(x = 1;x < N_CACHED_PROFILES;x++)1409 {1410 if (MRUProfile[x] && MRUProfile[x]->filename)1411 {1412 CurProfile = MRUProfile[x];1413 PROFILE_FlushFile();1414 }1415 }1416 CurProfile = lastCurProfile;1417 }1418 LeaveCriticalSection(&PROFILE_CritSect);1419 }1420 1421
Note:
See TracChangeset
for help on using the changeset viewer.