Changeset 1370 for trunk/src/kernel32/profile.cpp
- Timestamp:
- Oct 20, 1999, 10:09:05 AM (26 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/profile.cpp
r573 r1370 1 /* $Id: profile.cpp,v 1.1 8 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> 1 /* $Id: profile.cpp,v 1.19 1999-10-20 08:09:05 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 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 22 #include "heap.h" 23 #include "heapstring.h" 24 25 #include <sys/stat.h> 26 27 #include "winbase.h" 28 #include "winuser.h" 29 #include "winnls.h" 30 31 33 32 ODINDEBUGCHANNEL(PROFILE) 34 33 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, 34 // ------------------------- 35 // WINE compatibility macros 36 // ------------------------- 37 38 #ifndef MAX_PATHNAME_LEN 39 #define MAX_PATHNAME_LEN 260 40 #endif 41 42 #define SystemHeap GetProcessHeap() 43 #define strcasecmp stricmp 44 #define DOSFS_GetFullName(a,b,c) strcpy(c,a) 45 #define CharLowerA(a) (a) 46 47 48 typedef struct tagPROFILEKEY 49 { 50 char *name; 51 char *value; 52 struct tagPROFILEKEY *next; 53 } PROFILEKEY; 54 55 typedef struct tagPROFILESECTION 56 { 57 char *name; 58 struct tagPROFILEKEY *key; 59 struct tagPROFILESECTION *next; 60 } PROFILESECTION; 61 62 63 typedef struct 64 { 65 BOOL changed; 66 PROFILESECTION *section; 67 char *filename; //first open name 68 char *fullname; //name with path 69 time_t mtime; 70 } PROFILE; 71 72 73 #define N_CACHED_PROFILES 10 74 75 /* Cached profile files */ 76 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL}; 77 78 #define CurProfile (MRUProfile[0]) 79 80 /* ODIN.INI profile content */ 81 BOOL OdinProfileChanged = FALSE; 82 static PROFILESECTION *PROFILE_OdinProfile; 83 84 #define PROFILE_MAX_LINE_LEN 1024 85 #define WINININAME "WIN.INI" 86 87 /* Odin profile name in KERNEL32.DLL directory */ 88 #define ODINININAME "ODIN.INI" 89 90 /* Odin profile: the profile file being used */ 91 static char PROFILE_OdinIniUsed[MAX_PATHNAME_LEN] = ""; 92 93 /* Check for comments in profile */ 94 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';') 95 96 static LPCWSTR wininiW = NULL; 97 98 static CRITICAL_SECTION PROFILE_CritSect; 99 100 101 /*********************************************************************** 102 * PROFILE_CopyEntry 103 * 104 * Copy the content of an entry into a buffer, removing quotes, and possibly 105 * 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_Save 151 * 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_Free 173 * 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 int 197 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_Load 207 * 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 else 240 { 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_DeleteSection 288 * 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_DeleteKey 311 * 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_Find 344 * 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_FlushFile 384 * 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 immediately 399 if (!CurProfile->changed) 400 return TRUE; 401 402 // try to open file 403 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_ReleaseFile 422 * 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_Open 441 * 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 && (!stricmp(filename,MRUProfile[i]->filename) || !stricmp(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 else 484 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 else 532 { 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_GetSection 542 * 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 supplied 575 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 cchReturnBuffer 578 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_GetString 617 * 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_SetString 645 * 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_GetOdinIniString 694 * 695 * Get a config string from the odin.ini file. 696 */ 697 ODINFUNCTION5(int,PROFILE_GetOdinIniString, 698 LPCSTR,section, 699 LPCSTR,key_name, 700 LPCSTR,def, 701 LPCSTR,buffer, 702 int,len) 703 { 704 int ret; 705 706 EnterCriticalSection( &PROFILE_CritSect ); 707 708 if (key_name) 709 { 710 PROFILEKEY *key = PROFILE_Find(&PROFILE_OdinProfile, section, key_name, FALSE); 711 PROFILE_CopyEntry( (char*)buffer, (key && key->value) ? key->value : def, 712 len, TRUE ); 713 dprintf(("Kernel32:Odin profile:('%s','%s','%s'): returning '%s'\n", 714 section, key_name, def, buffer )); 715 ret = strlen( buffer ); 716 } 717 else 718 { 719 ret = PROFILE_GetSection( PROFILE_OdinProfile, section, (char*)buffer, len, TRUE, FALSE ); 720 } 721 LeaveCriticalSection( &PROFILE_CritSect ); 722 723 return ret; 724 } 725 726 ODINFUNCTION3(int,PROFILE_SetOdinIniString, 727 LPCSTR,section_name, 728 LPCSTR,key_name, 729 LPCSTR,value) 730 { 731 int ret; 732 733 EnterCriticalSection( &PROFILE_CritSect ); 734 735 if (!key_name) /* Delete a whole section */ 736 { 737 dprintf(("Kernel32:Odin profile:('%s')\n", section_name)); 738 OdinProfileChanged |= PROFILE_DeleteSection( &PROFILE_OdinProfile, 739 section_name ); 740 ret = TRUE; /* Even if PROFILE_DeleteSection() has failed, 741 this is not an error on application's level.*/ 742 } 743 else if (!value) /* Delete a key */ 744 { 745 dprintf(("Kernel32:Odin profile:('%s','%s')\n", section_name, key_name )); 746 OdinProfileChanged |= PROFILE_DeleteKey( &PROFILE_OdinProfile, 747 section_name, key_name ); 748 ret = TRUE; /* same error handling as above */ 749 } 750 else /* Set the key value */ 751 { 752 PROFILEKEY *key = PROFILE_Find( &PROFILE_OdinProfile, section_name, 753 key_name, TRUE ); 754 dprintf(("Kernel32:Odin profile:('%s','%s','%s'): \n", 755 section_name, key_name, value )); 756 if (!key) ret = FALSE; else 757 { 758 if (key->value && !strcmp(key->value,value)) 759 { 760 dprintf(("Kernel32:Odin profile: no change needed\n" )); 761 /* No change needed */ 762 } else 763 { 764 if (key->value) 765 { 766 dprintf(("Kernel32:Odin profile: replacing '%s'\n", key->value )); 767 HeapFree( SystemHeap, 0, key->value ); 768 } 769 else dprintf(("Kernel32:Odin profile: creating key\n" )); 770 key->value = HEAP_strdupA( SystemHeap, 0, value ); 771 OdinProfileChanged = TRUE; 772 } 773 ret = TRUE; 774 } 775 } 776 777 LeaveCriticalSection( &PROFILE_CritSect ); 778 779 return ret; 780 } 781 782 783 /*********************************************************************** 784 * PROFILE_GetOdinIniInt 785 * 786 * Get a config integer from the odin.ini file. 787 */ 788 ODINFUNCTION3(int,PROFILE_GetOdinIniInt, 789 LPCSTR,section, 790 LPCSTR,key_name, 791 int,def ) 792 { 793 char buffer[20]; 794 char *p; 795 long result; 796 PROFILEKEY *key; 797 int ret; 798 799 EnterCriticalSection( &PROFILE_CritSect ); 800 801 key = PROFILE_Find( &PROFILE_OdinProfile, section, key_name, FALSE ); 802 if (!key || !key->value) { 803 ret = def; 804 } else { 805 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE ); 806 result = strtol( buffer, &p, 0 ); 807 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result; 808 } 809 810 LeaveCriticalSection( &PROFILE_CritSect ); 811 812 return ret; 813 } 814 815 816 ODINFUNCTION3(int,PROFILE_SetOdinIniInt, 817 LPCSTR,section, 818 LPCSTR,key_name, 819 int,value ) 820 { 821 char buffer[20]; 822 823 sprintf(buffer,"%d",value); 824 return PROFILE_SetOdinIniString(section,key_name,buffer); 825 } 826 827 /****************************************************************************** 828 * 829 * int PROFILE_EnumerateOdinIniSection( 830 * char const *section, #Name of the section to enumerate 831 * void (*cbfn)(char const *key, char const *value, void *user), 832 * # Address of the callback function 833 * void *user ) # User-specified pointer. 834 * 835 * For each entry in a section in the wine.conf file, this function will 836 * call the specified callback function, informing it of each key and 837 * value. An optional user pointer may be passed to it (if this is not 838 * needed, pass NULL through it and ignore the value in the callback 839 * function). 840 * 841 * The callback function must accept three parameters: 842 * The name of the key (char const *) 843 * The value of the key (char const *) 844 * A user-specified parameter (void *) 845 * Note that the first two are char CONST *'s, not char *'s! The callback 846 * MUST not modify these strings! 847 * 848 * The return value indicates the number of times the callback function 849 * was called. 850 */ 851 int PROFILE_EnumerateOdinIniSection(LPCSTR section,PVOID (*cbfn)(LPCSTR,LPCSTR,PVOID),PVOID userptr) 852 { 853 PROFILESECTION *scansect; 854 PROFILEKEY *scankey; 855 int calls = 0; 856 857 EnterCriticalSection( &PROFILE_CritSect ); 858 859 /* Search for the correct section */ 860 for(scansect = PROFILE_OdinProfile; scansect; scansect = scansect->next) { 861 if(scansect->name && !strcasecmp(scansect->name, section)) { 862 863 /* Enumerate each key with the callback */ 864 for(scankey = scansect->key; scankey; scankey = scankey->next) { 865 866 /* Ignore blank entries -- these shouldn't exist, but let's 867 be extra careful */ 868 if(scankey->name[0]) { 869 cbfn(scankey->name, scankey->value, userptr); 870 ++calls; 871 } 872 } 873 874 break; 875 } 876 } 877 LeaveCriticalSection( &PROFILE_CritSect ); 878 879 return calls; 880 } 881 882 883 /****************************************************************************** 884 * 885 * int PROFILE_GetOdinIniBool( 886 * char const *section, 887 * char const *key_name, 888 * int def ) 889 * 890 * Reads a boolean value from the odin.ini file. This function attempts to 891 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0' 892 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for 893 * true. Anything else results in the return of the default value. 894 * 895 * This function uses 1 to indicate true, and 0 for false. You can check 896 * for existence by setting def to something other than 0 or 1 and 897 * examining the return value. 898 */ 899 ODINFUNCTION3(int,PROFILE_GetOdinIniBool, 900 LPCSTR,section, 901 LPCSTR,key_name, 902 int,def) 903 { 904 char key_value[2]; 905 int retval; 906 907 PROFILE_GetOdinIniString(section, key_name, "~", key_value, 2); 908 909 switch(key_value[0]) { 910 case 'n': 911 case 'N': 912 case 'f': 913 case 'F': 914 case '0': 915 retval = 0; 916 break; 917 918 case 'y': 919 case 'Y': 920 case 't': 921 case 'T': 922 case '1': 923 retval = 1; 924 break; 925 926 default: 927 retval = def; 928 } 929 930 dprintf(("Kernel32:Odin profile:(\"%s\", \"%s\", %s), " 931 "[%c], ret %s.\n", section, key_name, 932 def ? "TRUE" : "FALSE", key_value[0], 933 retval ? "TRUE" : "FALSE")); 934 935 return retval; 936 } 937 938 939 ODINFUNCTION3(int,PROFILE_SetOdinIniBool, 940 LPCSTR,section, 941 LPCSTR,key_name, 942 int,value ) 943 { 944 return PROFILE_SetOdinIniString(section,key_name,value ? "1":"0"); 945 } 946 947 948 /*********************************************************************** 949 * LoadOdinIni 950 * 951 * Load the odin.ini file. 952 */ 953 ODINFUNCTION0(int,PROFILE_LoadOdinIni) 954 { 955 char buffer[MAX_PATHNAME_LEN]; 956 const char *p; 957 FILE *f; 958 959 InitializeCriticalSection( &PROFILE_CritSect ); 960 MakeCriticalSectionGlobal( &PROFILE_CritSect ); 961 962 if ( (p = getenv( "ODIN_INI" )) && (f = fopen( p, "r" )) ) 963 { 964 PROFILE_OdinProfile = PROFILE_Load( f ); 965 fclose( f ); 966 strncpy(PROFILE_OdinIniUsed,p,MAX_PATHNAME_LEN-1); 967 } else 968 { 969 HINSTANCE hInstance = LoadLibraryA("KERNEL32.DLL"); 970 GetModuleFileNameA(hInstance,PROFILE_OdinIniUsed,sizeof(PROFILE_OdinIniUsed)); 971 FreeLibrary(hInstance); 972 strcpy(strrchr(PROFILE_OdinIniUsed,'\\')+1,ODINININAME); 973 f = fopen(PROFILE_OdinIniUsed,"r"); 974 PROFILE_OdinProfile = PROFILE_Load(f); 975 fclose(f); 976 } 977 978 dprintf(("Kernel32: Odin ini loaded: %s",PROFILE_OdinIniUsed)); 979 980 return 1; 981 } 982 983 ODINFUNCTION0(int,PROFILE_SaveOdinIni) 984 { 985 int ret; 986 FILE *file; 987 988 EnterCriticalSection( &PROFILE_CritSect ); 989 990 if (OdinProfileChanged) 991 { 992 file = fopen(PROFILE_OdinIniUsed,"w"); 993 if (!file) 994 { 995 dprintf(("Kernel32:Odin profile:could not save profile file %s\n", PROFILE_OdinIniUsed)); 996 ret = FALSE; 997 } else 998 { 999 dprintf(("Kernel32:Odin profile:Saving %s\n", PROFILE_OdinIniUsed )); 1000 PROFILE_Save( file, PROFILE_OdinProfile ); 1001 fclose( file ); 1002 OdinProfileChanged = FALSE; 1003 ret = TRUE; 1004 } 1005 } 1006 1007 LeaveCriticalSection( &PROFILE_CritSect ); 1008 1009 return ret; 1010 } 1011 1012 #if 0 1013 /*********************************************************************** 1014 * PROFILE_UsageOdinIni 1015 * 1016 * Explain the wine.ini file to those who don't read documentation. 1017 * Keep below one screenful in length so that error messages above are 1018 * noticed. 1019 */ 1020 void PROFILE_UsageOdinIni(void) 1021 { 1022 MESSAGE("Perhaps you have not properly edited or created " 1023 "your Odin configuration file.\n"); 1024 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName); 1025 MESSAGE(" or it is determined by the -config option or from\n" 1026 " the WINE_INI environment variable.\n"); 1027 if (*PROFILE_WineIniUsed) 1028 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed); 1029 /* RTFM, so to say */ 1030 } 1031 #endif 1032 1033 /*********************************************************************** 1034 * PROFILE_GetStringItem 1035 * 1036 * Convenience function that turns a string 'xxx, yyy, zzz' into 1037 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'. 1038 */ 1039 char* PROFILE_GetStringItem( char* start ) 1040 { 1041 char* lpchX, *lpch; 1042 1043 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ ) 1044 { 1045 if( *lpchX == ',' ) 1046 { 1047 if( lpch ) *lpch = '\0'; else *lpchX = '\0'; 1048 while( *(++lpchX) ) 1049 if( !PROFILE_isspace(*lpchX) ) return lpchX; 1050 } 1051 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX; 1052 else lpch = NULL; 1053 } 1054 if( lpch ) *lpch = '\0'; 1055 return NULL; 1056 } 1057 1058 /********************* API functions **********************************/ 1059 1060 /*********************************************************************** 1061 * GetProfileInt32A (KERNEL32.264) 1062 */ 1063 ODINFUNCTION3(UINT, GetProfileIntA, 1064 LPCSTR, section, 1065 LPCSTR, entry, 1066 INT, def_val) 1067 { 1068 return GetPrivateProfileIntA( section, entry, def_val, WINININAME ); 1069 } 1070 1071 /*********************************************************************** 1072 * GetProfileInt32W (KERNEL32.264) 1073 */ 1074 ODINFUNCTION3(UINT, GetProfileIntW, 1075 LPCWSTR, section, 1076 LPCWSTR, entry, 1077 INT, def_val) 1078 { 1079 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME ); 1080 return GetPrivateProfileIntW( section, entry, def_val, wininiW ); 1081 } 1082 1083 /*********************************************************************** 1084 * GetProfileString32A (KERNEL32.268) 1085 */ 1086 ODINFUNCTION5(INT, GetProfileStringA, 1087 LPCSTR, section, 1088 LPCSTR, entry, 1089 LPCSTR, def_val, 1090 LPSTR, buffer, 1091 UINT, len) 1092 { 1093 return GetPrivateProfileStringA( section, entry, def_val, 1094 buffer, len, WINININAME ); 1095 } 1096 1097 /*********************************************************************** 1098 * GetProfileString32W (KERNEL32.269) 1099 */ 1100 ODINFUNCTION5(INT, GetProfileStringW, 1101 LPCWSTR, section, 1102 LPCWSTR, entry, 1103 LPCWSTR, def_val, 1104 LPWSTR, buffer, 1105 UINT, len) 1106 { 1107 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME ); 1108 return GetPrivateProfileStringW( section, entry, def_val, 1109 buffer, len, wininiW ); 1110 } 1111 1112 /*********************************************************************** 1113 * WriteProfileString32A (KERNEL32.587) 1114 */ 1115 ODINFUNCTION3(BOOL, WriteProfileStringA, 1116 LPCSTR, section, 1117 LPCSTR, entry, 1118 LPCSTR, string) 1119 { 1120 return WritePrivateProfileStringA( section, entry, string, WINININAME ); 1121 } 1122 1123 /*********************************************************************** 1124 * WriteProfileString32W (KERNEL32.588) 1125 */ 1126 ODINFUNCTION3(BOOL, WriteProfileStringW, 1127 LPCWSTR, section, 1128 LPCWSTR, entry, 1129 LPCWSTR, string) 1130 { 1131 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME ); 1132 return WritePrivateProfileStringW( section, entry, string, wininiW ); 1133 } 1134 1135 /*********************************************************************** 1136 * GetPrivateProfileInt32A (KERNEL32.251) 1137 */ 1138 ODINFUNCTION4(UINT, GetPrivateProfileIntA, 1139 LPCSTR, section, 1140 LPCSTR, entry, 1141 INT, def_val, 1142 LPCSTR, filename) 1143 { 1144 char buffer[20]; 1145 char *p; 1146 long result; 1147 1148 GetPrivateProfileStringA( section, entry, "", 1149 buffer, sizeof(buffer), filename ); 1150 if (!buffer[0]) return (UINT)def_val; 1151 result = strtol( buffer, &p, 0 ); 1152 if (p == buffer) return 0; /* No digits at all */ 1153 return (UINT)result; 1154 } 1155 1156 /*********************************************************************** 1157 * GetPrivateProfileInt32W (KERNEL32.252) 1158 */ 1159 ODINFUNCTION4(UINT, GetPrivateProfileIntW, 1160 LPCWSTR, section, 1161 LPCWSTR, entry, 1162 INT, def_val, 1285 1163 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, 1164 { 1165 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1166 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry ); 1167 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1168 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA); 1169 HeapFree( GetProcessHeap(), 0, sectionA ); 1170 HeapFree( GetProcessHeap(), 0, filenameA ); 1171 HeapFree( GetProcessHeap(), 0, entryA ); 1172 return res; 1173 } 1174 1175 /*********************************************************************** 1176 * GetPrivateProfileString32A (KERNEL32.255) 1177 */ 1178 ODINFUNCTION6(INT, GetPrivateProfileStringA, 1179 LPCSTR, section, 1180 LPCSTR, entry, 1181 LPCSTR, def_val, 1182 LPSTR, buffer, 1183 UINT, len, 1184 LPCSTR, filename) 1185 { 1186 int ret; 1187 1188 if (!filename) 1189 filename = WINININAME; 1190 1191 EnterCriticalSection( &PROFILE_CritSect ); 1192 1193 if (PROFILE_Open( filename )) { 1194 ret = PROFILE_GetString( section, entry, def_val, buffer, len ); 1195 } else { 1196 lstrcpynA( buffer, def_val, len ); 1197 ret = strlen( buffer ); 1198 } 1199 1200 LeaveCriticalSection( &PROFILE_CritSect ); 1201 1202 return ret; 1203 } 1204 1205 /*********************************************************************** 1206 * GetPrivateProfileString32W (KERNEL32.256) 1207 */ 1208 ODINFUNCTION6(INT, GetPrivateProfileStringW, 1209 LPCWSTR, section, 1210 LPCWSTR, entry, 1211 LPCWSTR, def_val, 1212 LPWSTR, buffer, 1213 UINT, len, 1214 LPCWSTR, filename) 1215 { 1216 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1217 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry ); 1218 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1219 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val ); 1220 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len ); 1221 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA, 1222 bufferA, len, filenameA ); 1223 lstrcpynAtoW( buffer, bufferA, len ); 1224 HeapFree( GetProcessHeap(), 0, sectionA ); 1225 HeapFree( GetProcessHeap(), 0, entryA ); 1226 HeapFree( GetProcessHeap(), 0, filenameA ); 1227 HeapFree( GetProcessHeap(), 0, def_valA ); 1228 HeapFree( GetProcessHeap(), 0, bufferA); 1229 return ret; 1230 } 1231 1232 /*********************************************************************** 1233 * GetPrivateProfileSection32A (KERNEL32.255) 1234 */ 1235 ODINFUNCTION4(INT, GetPrivateProfileSectionA, 1236 LPCSTR, section, 1237 LPSTR, buffer, 1238 DWORD, len, 1239 LPCSTR, filename) 1240 { 1241 int ret = 0; 1242 1243 EnterCriticalSection( &PROFILE_CritSect ); 1244 1245 if (PROFILE_Open( filename )) 1246 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, 1247 FALSE, TRUE); 1248 1249 LeaveCriticalSection( &PROFILE_CritSect ); 1250 1251 return ret; 1252 } 1253 1254 /*********************************************************************** 1255 * GetPrivateProfileSection32W (KERNEL32.256) 1256 */ 1257 1258 ODINFUNCTION4(INT, GetPrivateProfileSectionW, 1259 LPCWSTR, section, 1260 LPWSTR, buffer, 1261 DWORD, len, 1262 LPCWSTR, filename) 1263 1264 { 1265 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1266 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1267 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len ); 1268 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len, 1269 filenameA ); 1270 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len); 1271 HeapFree( GetProcessHeap(), 0, sectionA ); 1272 HeapFree( GetProcessHeap(), 0, filenameA ); 1273 HeapFree( GetProcessHeap(), 0, bufferA); 1274 return ret; 1275 } 1276 1277 /*********************************************************************** 1278 * GetProfileSection32A (KERNEL32.268) 1279 */ 1280 ODINFUNCTION3(INT, GetProfileSectionA, 1281 LPCSTR, section, 1282 LPSTR, buffer, 1283 DWORD, len) 1284 { 1285 return GetPrivateProfileSectionA( section, buffer, len, WINININAME ); 1286 } 1287 1288 /*********************************************************************** 1289 * GetProfileSection32W (KERNEL32) 1290 */ 1291 ODINFUNCTION3(INT, GetProfileSectionW, 1292 LPCWSTR, section, 1293 LPWSTR, buffer, 1294 DWORD, len) 1295 { 1296 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME ); 1297 return GetPrivateProfileSectionW( section, buffer, len, wininiW ); 1298 } 1299 1300 /*********************************************************************** 1301 * WritePrivateProfileString32A (KERNEL32.582) 1302 */ 1303 ODINFUNCTION4(BOOL, WritePrivateProfileStringA, 1304 LPCSTR, section, 1305 LPCSTR, entry, 1306 LPCSTR, string, 1307 LPCSTR, filename) 1308 { 1309 BOOL ret = FALSE; 1310 1311 EnterCriticalSection( &PROFILE_CritSect ); 1312 1313 if (PROFILE_Open( filename )) 1314 { 1315 if (!section && !entry && !string) 1316 PROFILE_ReleaseFile(); /* always return FALSE in this case */ 1317 else 1318 ret = PROFILE_SetString( section, entry, string ); 1319 } 1320 1321 LeaveCriticalSection( &PROFILE_CritSect ); 1322 return ret; 1323 } 1324 1325 /*********************************************************************** 1326 * WritePrivateProfileString32W (KERNEL32.583) 1327 */ 1328 ODINFUNCTION4(BOOL, WritePrivateProfileStringW, 1329 LPCWSTR, section, 1330 LPCWSTR, entry, 1331 LPCWSTR, string, 1332 LPCWSTR, filename) 1333 { 1334 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1335 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry ); 1336 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string ); 1337 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1338 BOOL res = WritePrivateProfileStringA( sectionA, entryA, 1339 stringA, filenameA ); 1340 HeapFree( GetProcessHeap(), 0, sectionA ); 1341 HeapFree( GetProcessHeap(), 0, entryA ); 1342 HeapFree( GetProcessHeap(), 0, stringA ); 1343 HeapFree( GetProcessHeap(), 0, filenameA ); 1344 return res; 1345 } 1346 1347 /*********************************************************************** 1348 * WritePrivateProfileSection32A (KERNEL32) 1349 */ 1350 ODINFUNCTION3(BOOL, WritePrivateProfileSectionA, 1351 LPCSTR, section, 1352 LPCSTR, string, 1353 LPCSTR, filename) 1354 { 1355 char *p =(char*)string; 1356 1357 dprintf(("Kernel32:Profile:fixme WritePrivateProfileSection32A empty stub\n")); 1358 return FALSE; 1359 } 1360 1361 /*********************************************************************** 1362 * WritePrivateProfileSection32W (KERNEL32) 1363 */ 1364 ODINFUNCTION3(BOOL, WritePrivateProfileSectionW, 1365 LPCWSTR, section, 1366 LPCWSTR, string, 1367 LPCWSTR, filename) 1368 { 1369 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1370 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string ); 1371 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1372 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA ); 1373 HeapFree( GetProcessHeap(), 0, sectionA ); 1374 HeapFree( GetProcessHeap(), 0, stringA ); 1375 HeapFree( GetProcessHeap(), 0, filenameA ); 1376 return res; 1377 } 1378 1379 /*********************************************************************** 1380 * WriteProfileSection32A (KERNEL32.747) 1381 */ 1382 ODINFUNCTION2(BOOL, WriteProfileSectionA, 1383 LPCSTR, section, 1302 1384 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, 1385 { 1386 return WritePrivateProfileSectionA( section, keys_n_values, WINININAME); 1387 } 1388 1389 /*********************************************************************** 1390 * WriteProfileSection32W (KERNEL32.748) 1391 */ 1392 ODINFUNCTION2(BOOL, WriteProfileSectionW, 1393 LPCWSTR, section, 1312 1394 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, 1395 { 1396 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME); 1397 1398 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW)); 1399 } 1400 1401 /*********************************************************************** 1402 * GetPrivateProfileSectionNames16 (KERNEL.143) 1403 */ 1404 ODINFUNCTION3(WORD, GetPrivateProfileSectionNames16, 1405 LPSTR, buffer, 1406 WORD, size, 1345 1407 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, 1408 { 1409 WORD ret = 0; 1410 1411 EnterCriticalSection( &PROFILE_CritSect ); 1412 1413 if (PROFILE_Open( filename )) 1414 ret = PROFILE_GetSectionNames(buffer, size); 1415 1416 LeaveCriticalSection( &PROFILE_CritSect ); 1417 1418 return ret; 1419 } 1420 1421 /*********************************************************************** 1422 * GetPrivateProfileSectionNames32A (KERNEL32.365) 1423 */ 1424 ODINFUNCTION3(DWORD, GetPrivateProfileSectionNamesA, 1425 LPSTR, buffer, 1426 DWORD, size, 1427 LPCSTR, filename) 1428 { 1429 return (GetPrivateProfileSectionNames16 (buffer,size,filename)); 1430 } 1431 1432 /*********************************************************************** 1433 * GetPrivateProfileSectionNames32W (KERNEL32.366) 1434 */ 1435 ODINFUNCTION3(DWORD, GetPrivateProfileSectionNamesW, 1436 LPWSTR, buffer, 1437 DWORD, size, 1356 1438 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, 1439 { 1440 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1441 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size); 1442 1443 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA); 1444 lstrcpynAtoW( buffer, bufferA, size); 1445 HeapFree( GetProcessHeap(), 0, bufferA); 1446 HeapFree( GetProcessHeap(), 0, filenameA ); 1447 1448 return ret; 1449 } 1450 1451 /*********************************************************************** 1452 * GetPrivateProfileStruct32A (KERNEL32.370) 1453 */ 1454 ODINFUNCTION5(BOOL, GetPrivateProfileStructA, 1455 LPCSTR, section, 1456 LPCSTR, key, 1457 LPVOID, buf, 1458 UINT, len, 1377 1459 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, 1460 { 1461 BOOL ret = FALSE; 1462 1463 EnterCriticalSection( &PROFILE_CritSect ); 1464 1465 if (PROFILE_Open( filename )) { 1466 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE); 1467 if (k) { 1468 lstrcpynA( (LPSTR)buf, k->value, strlen(k->value)); 1469 ret = TRUE; 1470 } 1471 } 1472 LeaveCriticalSection( &PROFILE_CritSect ); 1473 1474 return FALSE; 1475 } 1476 1477 /*********************************************************************** 1478 * GetPrivateProfileStruct32W (KERNEL32.543) 1479 */ 1480 ODINFUNCTION5(BOOL, GetPrivateProfileStructW, 1481 LPCWSTR, section, 1482 LPCWSTR, key, 1483 LPVOID, buffer, 1484 UINT, len, 1403 1485 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, 1486 { 1487 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1488 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key); 1489 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1490 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len ); 1491 1492 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA, 1493 len, filenameA ); 1494 lstrcpynAtoW( (LPWSTR)buffer, bufferA, len ); 1495 HeapFree( GetProcessHeap(), 0, bufferA); 1496 HeapFree( GetProcessHeap(), 0, sectionA ); 1497 HeapFree( GetProcessHeap(), 0, keyA ); 1498 HeapFree( GetProcessHeap(), 0, filenameA ); 1499 1500 return ret; 1501 } 1502 1503 1504 /*********************************************************************** 1505 * WritePrivateProfileStruct32A (KERNEL32.744) 1506 */ 1507 ODINFUNCTION5(BOOL, WritePrivateProfileStructA, 1508 LPCSTR, section, 1509 LPCSTR, key, 1510 LPVOID, buf, 1511 UINT, bufsize, 1430 1512 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, 1513 { 1514 BOOL ret = FALSE; 1515 1516 if (!section && !key && !buf) /* flush the cache */ 1517 return WritePrivateProfileStringA( NULL, NULL, NULL, filename ); 1518 1519 EnterCriticalSection( &PROFILE_CritSect ); 1520 1521 if (PROFILE_Open( filename )) 1522 ret = PROFILE_SetString( section, key, (LPCSTR)buf ); 1523 1524 LeaveCriticalSection( &PROFILE_CritSect ); 1525 1526 return ret; 1527 } 1528 1529 /*********************************************************************** 1530 * WritePrivateProfileStruct32W (KERNEL32.544) 1531 */ 1532 ODINFUNCTION5(BOOL, WritePrivateProfileStructW, 1533 LPCWSTR, section, 1534 LPCWSTR, key, 1535 LPVOID, buf, 1536 UINT, bufsize, 1455 1537 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 */ 1538 { 1539 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section ); 1540 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key); 1541 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename ); 1542 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize, 1543 filenameA ); 1544 HeapFree( GetProcessHeap(), 0, sectionA ); 1545 HeapFree( GetProcessHeap(), 0, keyA ); 1546 HeapFree( GetProcessHeap(), 0, filenameA ); 1547 1548 return ret; 1549 } 1550 1551 /*********************************************************************** 1552 * WriteOutProfiles (KERNEL.315) 1553 * CB: original: 16 bit function 1554 * here: necessary to save open ini files 1555 */ 1474 1556 ODINPROCEDURE0(WriteOutProfiles) 1475 1557 { 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 1501 1558 PROFILE *lastCurProfile; 1559 INT x; 1560 1561 PROFILE_SaveOdinIni(); 1562 1563 EnterCriticalSection(&PROFILE_CritSect); 1564 1565 if (CurProfile && CurProfile->filename) 1566 PROFILE_FlushFile(); //flash current 1567 1568 if (MRUProfile) 1569 { 1570 lastCurProfile = CurProfile; 1571 for(x = 1;x < N_CACHED_PROFILES;x++) 1572 { 1573 if (MRUProfile[x] && MRUProfile[x]->filename) 1574 { 1575 CurProfile = MRUProfile[x]; 1576 PROFILE_FlushFile(); 1577 } 1578 } 1579 CurProfile = lastCurProfile; 1580 } 1581 LeaveCriticalSection(&PROFILE_CritSect); 1582 } 1583 1584 1585
Note:
See TracChangeset
for help on using the changeset viewer.