Implemented Win95-style shared cursor/icon cache.
[wine/wine-kai.git] / files / profile.c
blobfb67b711f3c2ffcf33407ac2875aa0db8dda127f
1 /*
2 * Profile functions
4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
6 */
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <string.h>
12 #include <sys/stat.h>
14 #include "winbase.h"
15 #include "wine/winbase16.h"
16 #include "winuser.h"
17 #include "file.h"
18 #include "heap.h"
19 #include "debug.h"
20 #include "options.h"
22 typedef struct tagPROFILEKEY
24 char *name;
25 char *value;
26 struct tagPROFILEKEY *next;
27 } PROFILEKEY;
29 typedef struct tagPROFILESECTION
31 char *name;
32 struct tagPROFILEKEY *key;
33 struct tagPROFILESECTION *next;
34 } PROFILESECTION;
37 typedef struct
39 BOOL changed;
40 PROFILESECTION *section;
41 char *dos_name;
42 char *unix_name;
43 char *filename;
44 time_t mtime;
45 } PROFILE;
48 #define N_CACHED_PROFILES 10
50 /* Cached profile files */
51 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
53 #define CurProfile (MRUProfile[0])
55 /* wine.ini profile content */
56 static PROFILESECTION *WineProfile;
58 #define PROFILE_MAX_LINE_LEN 1024
60 /* Wine profile name in $HOME directory; must begin with slash */
61 static const char PROFILE_WineIniName[] = "/.winerc";
63 /* Wine profile: the profile file being used */
64 static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
66 /* Check for comments in profile */
67 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
69 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
71 static LPCWSTR wininiW = NULL;
73 /***********************************************************************
74 * PROFILE_CopyEntry
76 * Copy the content of an entry into a buffer, removing quotes, and possibly
77 * translating environment variables.
79 static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
80 int handle_env )
82 char quote = '\0';
83 const char *p;
85 if ((*value == '\'') || (*value == '\"'))
87 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
90 if (!handle_env)
92 lstrcpynA( buffer, value, len );
93 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
94 return;
97 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
99 if ((*p == '$') && (p[1] == '{'))
101 char env_val[1024];
102 const char *env_p;
103 const char *p2 = strchr( p, '}' );
104 if (!p2) continue; /* ignore it */
105 lstrcpynA(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
106 if ((env_p = getenv( env_val )) != NULL)
108 lstrcpynA( buffer, env_p, len );
109 buffer += strlen( buffer );
110 len -= strlen( buffer );
112 p = p2 + 1;
115 *buffer = '\0';
119 /***********************************************************************
120 * PROFILE_Save
122 * Save a profile tree to a file.
124 static void PROFILE_Save( FILE *file, PROFILESECTION *section )
126 PROFILEKEY *key;
128 for ( ; section; section = section->next)
130 if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
131 for (key = section->key; key; key = key->next)
133 fprintf( file, "%s", key->name );
134 if (key->value) fprintf( file, "=%s", key->value );
135 fprintf( file, "\r\n" );
141 /***********************************************************************
142 * PROFILE_Free
144 * Free a profile tree.
146 static void PROFILE_Free( PROFILESECTION *section )
148 PROFILESECTION *next_section;
149 PROFILEKEY *key, *next_key;
151 for ( ; section; section = next_section)
153 if (section->name) HeapFree( SystemHeap, 0, section->name );
154 for (key = section->key; key; key = next_key)
156 next_key = key->next;
157 if (key->name) HeapFree( SystemHeap, 0, key->name );
158 if (key->value) HeapFree( SystemHeap, 0, key->value );
159 HeapFree( SystemHeap, 0, key );
161 next_section = section->next;
162 HeapFree( SystemHeap, 0, section );
166 static int
167 PROFILE_isspace(char c) {
168 if (isspace(c)) return 1;
169 if (c=='\r' || c==0x1a) return 1;
170 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
171 return 0;
175 /***********************************************************************
176 * PROFILE_Load
178 * Load a profile tree from a file.
180 static PROFILESECTION *PROFILE_Load( FILE *file )
182 char buffer[PROFILE_MAX_LINE_LEN];
183 char *p, *p2;
184 int line = 0;
185 PROFILESECTION *section, *first_section;
186 PROFILESECTION **next_section;
187 PROFILEKEY *key, *prev_key, **next_key;
189 first_section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
190 first_section->name = NULL;
191 first_section->key = NULL;
192 first_section->next = NULL;
193 next_section = &first_section->next;
194 next_key = &first_section->key;
195 prev_key = NULL;
197 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
199 line++;
200 p = buffer;
201 while (*p && PROFILE_isspace(*p)) p++;
202 if (*p == '[') /* section start */
204 if (!(p2 = strrchr( p, ']' )))
206 WARN(profile, "Invalid section header at line %d: '%s'\n",
207 line, p );
209 else
211 *p2 = '\0';
212 p++;
213 section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
214 section->name = HEAP_strdupA( SystemHeap, 0, p );
215 section->key = NULL;
216 section->next = NULL;
217 *next_section = section;
218 next_section = &section->next;
219 next_key = &section->key;
220 prev_key = NULL;
222 TRACE(profile, "New section: '%s'\n",section->name);
224 continue;
228 p2=p+strlen(p) - 1;
229 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
231 if ((p2 = strchr( p, '=' )) != NULL)
233 char *p3 = p2 - 1;
234 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
235 *p2++ = '\0';
236 while (*p2 && PROFILE_isspace(*p2)) p2++;
239 if(*p || !prev_key || *prev_key->name)
241 key = HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
242 key->name = HEAP_strdupA( SystemHeap, 0, p );
243 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
244 key->next = NULL;
245 *next_key = key;
246 next_key = &key->next;
247 prev_key = key;
249 TRACE(profile, "New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)");
252 return first_section;
256 /***********************************************************************
257 * PROFILE_DeleteSection
259 * Delete a section from a profile tree.
261 static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
263 while (*section)
265 if ((*section)->name && !strcasecmp( (*section)->name, name ))
267 PROFILESECTION *to_del = *section;
268 *section = to_del->next;
269 to_del->next = NULL;
270 PROFILE_Free( to_del );
271 return TRUE;
273 section = &(*section)->next;
275 return FALSE;
279 /***********************************************************************
280 * PROFILE_DeleteKey
282 * Delete a key from a profile tree.
284 static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
285 LPCSTR section_name, LPCSTR key_name )
287 while (*section)
289 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
291 PROFILEKEY **key = &(*section)->key;
292 while (*key)
294 if (!strcasecmp( (*key)->name, key_name ))
296 PROFILEKEY *to_del = *key;
297 *key = to_del->next;
298 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
299 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
300 HeapFree( SystemHeap, 0, to_del );
301 return TRUE;
303 key = &(*key)->next;
306 section = &(*section)->next;
308 return FALSE;
312 /***********************************************************************
313 * PROFILE_Find
315 * Find a key in a profile tree, optionally creating it.
317 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
318 const char *section_name,
319 const char *key_name, int create )
321 while (*section)
323 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
325 PROFILEKEY **key = &(*section)->key;
326 while (*key)
328 if (!strcasecmp( (*key)->name, key_name )) return *key;
329 key = &(*key)->next;
331 if (!create) return NULL;
332 *key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
333 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
334 (*key)->value = NULL;
335 (*key)->next = NULL;
336 return *key;
338 section = &(*section)->next;
340 if (!create) return NULL;
341 *section = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
342 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
343 (*section)->next = NULL;
344 (*section)->key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
345 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
346 (*section)->key->value = NULL;
347 (*section)->key->next = NULL;
348 return (*section)->key;
352 /***********************************************************************
353 * PROFILE_FlushFile
355 * Flush the current profile to disk if changed.
357 static BOOL PROFILE_FlushFile(void)
359 char *p, buffer[MAX_PATHNAME_LEN];
360 const char *unix_name;
361 FILE *file = NULL;
362 struct stat buf;
364 if(!CurProfile)
366 WARN(profile, "No current profile!\n");
367 return FALSE;
370 if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
371 if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
373 /* Try to create it in $HOME/.wine */
374 /* FIXME: this will need a more general solution */
375 if ((p = getenv( "HOME" )) != NULL)
377 strcpy( buffer, p );
378 strcat( buffer, "/.wine/" );
379 p = buffer + strlen(buffer);
380 strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
381 CharLowerA( p );
382 file = fopen( buffer, "w" );
383 unix_name = buffer;
387 if (!file)
389 WARN(profile, "could not save profile file %s\n", CurProfile->dos_name);
390 return FALSE;
393 TRACE(profile, "Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name );
394 PROFILE_Save( file, CurProfile->section );
395 fclose( file );
396 CurProfile->changed = FALSE;
397 if(!stat(unix_name,&buf))
398 CurProfile->mtime=buf.st_mtime;
399 return TRUE;
403 /***********************************************************************
404 * PROFILE_Open
406 * Open a profile file, checking the cached file first.
408 static BOOL PROFILE_Open( LPCSTR filename )
410 DOS_FULL_NAME full_name;
411 char buffer[MAX_PATHNAME_LEN];
412 char *newdos_name, *p;
413 FILE *file = NULL;
414 int i,j;
415 struct stat buf;
416 PROFILE *tempProfile;
418 /* First time around */
420 if(!CurProfile)
421 for(i=0;i<N_CACHED_PROFILES;i++)
423 MRUProfile[i]=HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );
424 MRUProfile[i]->changed=FALSE;
425 MRUProfile[i]->section=NULL;
426 MRUProfile[i]->dos_name=NULL;
427 MRUProfile[i]->unix_name=NULL;
428 MRUProfile[i]->filename=NULL;
429 MRUProfile[i]->mtime=0;
432 /* Check for a match */
434 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
435 strchr( filename, ':' ))
437 if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
439 else
441 GetWindowsDirectoryA( buffer, sizeof(buffer) );
442 strcat( buffer, "\\" );
443 strcat( buffer, filename );
444 if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
447 for(i=0;i<N_CACHED_PROFILES;i++)
449 if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )) ||
450 (MRUProfile[i]->dos_name && !strcmp( full_name.short_name, MRUProfile[i]->dos_name )))
452 if(i)
454 PROFILE_FlushFile();
455 tempProfile=MRUProfile[i];
456 for(j=i;j>0;j--)
457 MRUProfile[j]=MRUProfile[j-1];
458 CurProfile=tempProfile;
460 if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
461 TRACE(profile, "(%s): already opened (mru=%d)\n",
462 filename, i );
463 else
464 TRACE(profile, "(%s): already opened, needs refreshing (mru=%d)\n",
465 filename, i );
466 return TRUE;
470 /* Rotate the oldest to the top to be replaced */
472 if(i==N_CACHED_PROFILES)
474 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
475 for(i=N_CACHED_PROFILES-1;i>0;i--)
476 MRUProfile[i]=MRUProfile[i-1];
477 CurProfile=tempProfile;
480 /* Flush the profile */
482 if(CurProfile->filename)
484 PROFILE_FlushFile();
485 PROFILE_Free( CurProfile->section );
486 if (CurProfile->dos_name) HeapFree( SystemHeap, 0, CurProfile->dos_name );
487 if (CurProfile->unix_name) HeapFree( SystemHeap, 0, CurProfile->unix_name );
488 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
489 CurProfile->changed=FALSE;
490 CurProfile->section=NULL;
491 CurProfile->dos_name=NULL;
492 CurProfile->unix_name=NULL;
493 CurProfile->filename=NULL;
494 CurProfile->mtime=0;
497 newdos_name = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
498 CurProfile->dos_name = newdos_name;
499 CurProfile->filename = HEAP_strdupA( SystemHeap, 0, filename );
501 /* Try to open the profile file, first in $HOME/.wine */
503 /* FIXME: this will need a more general solution */
504 if ((p = getenv( "HOME" )) != NULL)
506 strcpy( buffer, p );
507 strcat( buffer, "/.wine/" );
508 p = buffer + strlen(buffer);
509 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
510 CharLowerA( p );
511 if ((file = fopen( buffer, "r" )))
513 TRACE(profile, "(%s): found it in %s\n",
514 filename, buffer );
515 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
519 if (!file)
521 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0,
522 full_name.long_name );
523 if ((file = fopen( full_name.long_name, "r" )))
524 TRACE(profile, "(%s): found it in %s\n",
525 filename, full_name.long_name );
528 if (file)
530 CurProfile->section = PROFILE_Load( file );
531 fclose( file );
532 if(!stat(CurProfile->unix_name,&buf))
533 CurProfile->mtime=buf.st_mtime;
535 else
537 /* Does not exist yet, we will create it in PROFILE_FlushFile */
538 WARN(profile, "profile file %s not found\n", newdos_name );
540 return TRUE;
544 /***********************************************************************
545 * PROFILE_GetSection
547 * Returns all keys of a section.
548 * If return_values is TRUE, also include the corresponding values.
550 static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
551 LPSTR buffer, UINT len, BOOL handle_env,
552 BOOL return_values )
554 PROFILEKEY *key;
555 while (section)
557 if (section->name && !strcasecmp( section->name, section_name ))
559 UINT oldlen = len;
560 for (key = section->key; key; key = key->next)
562 if (len <= 2) break;
563 if (!*key->name) continue; /* Skip empty lines */
564 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
565 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
566 len -= strlen(buffer) + 1;
567 buffer += strlen(buffer) + 1;
568 if (return_values && key->value) {
569 buffer[-1] = '=';
570 PROFILE_CopyEntry ( buffer,
571 key->value, len - 1, handle_env );
572 len -= strlen(buffer) + 1;
573 buffer += strlen(buffer) + 1;
576 *buffer = '\0';
577 if (len < 1)
578 /*If either lpszSection or lpszKey is NULL and the supplied
579 destination buffer is too small to hold all the strings,
580 the last string is truncated and followed by two null characters.
581 In this case, the return value is equal to cchReturnBuffer
582 minus two. */
584 buffer[-1] = '\0';
585 return oldlen - 2;
587 return oldlen - len;
589 section = section->next;
591 buffer[0] = buffer[1] = '\0';
592 return 0;
596 /***********************************************************************
597 * PROFILE_GetString
599 * Get a profile string.
601 static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
602 LPCSTR def_val, LPSTR buffer, UINT len )
604 PROFILEKEY *key = NULL;
606 if (!def_val) def_val = "";
607 if (key_name && key_name[0])
609 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
610 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
611 len, FALSE );
612 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
613 section, key_name, def_val, buffer );
614 return strlen( buffer );
616 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
617 FALSE, FALSE);
621 /***********************************************************************
622 * PROFILE_SetString
624 * Set a profile string.
626 static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
627 LPCSTR value )
629 if (!key_name) /* Delete a whole section */
631 TRACE(profile, "('%s')\n", section_name);
632 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
633 section_name );
634 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
635 this is not an error on application's level.*/
637 else if (!value) /* Delete a key */
639 TRACE(profile, "('%s','%s')\n",
640 section_name, key_name );
641 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
642 section_name, key_name );
643 return TRUE; /* same error handling as above */
645 else /* Set the key value */
647 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
648 key_name, TRUE );
649 TRACE(profile, "('%s','%s','%s'): \n",
650 section_name, key_name, value );
651 if (!key) return FALSE;
652 if (key->value)
654 if (!strcmp( key->value, value ))
656 TRACE(profile, " no change needed\n" );
657 return TRUE; /* No change needed */
659 TRACE(profile, " replacing '%s'\n", key->value );
660 HeapFree( SystemHeap, 0, key->value );
662 else TRACE(profile, " creating key\n" );
663 key->value = HEAP_strdupA( SystemHeap, 0, value );
664 CurProfile->changed = TRUE;
666 return TRUE;
670 /***********************************************************************
671 * PROFILE_GetWineIniString
673 * Get a config string from the wine.ini file.
675 int PROFILE_GetWineIniString( const char *section, const char *key_name,
676 const char *def, char *buffer, int len )
678 if (key_name)
680 PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
681 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
682 len, TRUE );
683 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
684 section, key_name, def, buffer );
685 return strlen( buffer );
687 return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE, FALSE );
691 /***********************************************************************
692 * PROFILE_GetWineIniInt
694 * Get a config integer from the wine.ini file.
696 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
698 char buffer[20];
699 char *p;
700 long result;
702 PROFILEKEY *key = PROFILE_Find( &WineProfile, section, key_name, FALSE );
703 if (!key || !key->value) return def;
704 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
705 result = strtol( buffer, &p, 0 );
706 if (p == buffer) return 0; /* No digits at all */
707 return (int)result;
711 /******************************************************************************
713 * int PROFILE_EnumerateWineIniSection(
714 * char const *section, #Name of the section to enumerate
715 * void (*cbfn)(char const *key, char const *value, void *user),
716 * # Address of the callback function
717 * void *user ) # User-specified pointer.
719 * For each entry in a section in the wine.conf file, this function will
720 * call the specified callback function, informing it of each key and
721 * value. An optional user pointer may be passed to it (if this is not
722 * needed, pass NULL through it and ignore the value in the callback
723 * function).
725 * The callback function must accept three parameters:
726 * The name of the key (char const *)
727 * The value of the key (char const *)
728 * A user-specified parameter (void *)
729 * Note that the first two are char CONST *'s, not char *'s! The callback
730 * MUST not modify these strings!
732 * The return value indicates the number of times the callback function
733 * was called.
735 int PROFILE_EnumerateWineIniSection(
736 char const *section,
737 void (*cbfn)(char const *, char const *, void *),
738 void *userptr )
740 PROFILESECTION *scansect;
741 PROFILEKEY *scankey;
742 int calls = 0;
744 /* Search for the correct section */
745 for(scansect = WineProfile; scansect; scansect = scansect->next) {
746 if(scansect->name && !strcasecmp(scansect->name, section)) {
748 /* Enumerate each key with the callback */
749 for(scankey = scansect->key; scankey; scankey = scankey->next) {
751 /* Ignore blank entries -- these shouldn't exist, but let's
752 be extra careful */
753 if(scankey->name[0]) {
754 cbfn(scankey->name, scankey->value, userptr);
755 ++calls;
759 break;
763 return calls;
767 /******************************************************************************
769 * int PROFILE_GetWineIniBool(
770 * char const *section,
771 * char const *key_name,
772 * int def )
774 * Reads a boolean value from the wine.ini file. This function attempts to
775 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
776 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
777 * true. Anything else results in the return of the default value.
779 * This function uses 1 to indicate true, and 0 for false. You can check
780 * for existence by setting def to something other than 0 or 1 and
781 * examining the return value.
783 int PROFILE_GetWineIniBool(
784 char const *section,
785 char const *key_name,
786 int def )
788 char key_value[2];
789 int retval;
791 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
793 switch(key_value[0]) {
794 case 'n':
795 case 'N':
796 case 'f':
797 case 'F':
798 case '0':
799 retval = 0;
800 break;
802 case 'y':
803 case 'Y':
804 case 't':
805 case 'T':
806 case '1':
807 retval = 1;
808 break;
810 default:
811 retval = def;
814 TRACE(profile, "(\"%s\", \"%s\", %s), "
815 "[%c], ret %s.\n", section, key_name,
816 def ? "TRUE" : "FALSE", key_value[0],
817 retval ? "TRUE" : "FALSE");
819 return retval;
823 /***********************************************************************
824 * PROFILE_LoadWineIni
826 * Load the wine.ini file.
828 int PROFILE_LoadWineIni(void)
830 char buffer[MAX_PATHNAME_LEN];
831 const char *p;
832 FILE *f;
834 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
836 /* Open -config specified file */
837 WineProfile = PROFILE_Load ( f);
838 fclose ( f );
839 strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);
840 return 1;
843 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
845 WineProfile = PROFILE_Load( f );
846 fclose( f );
847 strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);
848 return 1;
850 if ((p = getenv( "HOME" )) != NULL)
852 lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
853 strcat( buffer, PROFILE_WineIniName );
854 if ((f = fopen( buffer, "r" )) != NULL)
856 WineProfile = PROFILE_Load( f );
857 fclose( f );
858 strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);
859 return 1;
862 else WARN(profile, "could not get $HOME value for config file.\n" );
864 /* Try global file */
866 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
868 WineProfile = PROFILE_Load( f );
869 fclose( f );
870 strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);
871 return 1;
873 MSG( "Can't open configuration file %s or $HOME%s\n",
874 WINE_INI_GLOBAL, PROFILE_WineIniName );
875 return 0;
879 /***********************************************************************
880 * PROFILE_UsageWineIni
882 * Explain the wine.ini file to those who don't read documentation.
883 * Keep below one screenful in length so that error messages above are
884 * noticed.
886 void PROFILE_UsageWineIni(void)
888 MSG("Perhaps you have not properly edited or created "
889 "your Wine configuration file.\n");
890 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
891 MSG(" or it is determined by the -config option or from\n"
892 " the WINE_INI environment variable.\n");
893 if (*PROFILE_WineIniUsed)
894 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
895 /* RTFM, so to say */
899 /***********************************************************************
900 * PROFILE_GetStringItem
902 * Convenience function that turns a string 'xxx, yyy, zzz' into
903 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
905 char* PROFILE_GetStringItem( char* start )
907 char* lpchX, *lpch;
909 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
911 if( *lpchX == ',' )
913 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
914 while( *(++lpchX) )
915 if( !PROFILE_isspace(*lpchX) ) return lpchX;
917 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
918 else lpch = NULL;
920 if( lpch ) *lpch = '\0';
921 return NULL;
925 /********************* API functions **********************************/
927 /***********************************************************************
928 * GetProfileInt16 (KERNEL.57)
930 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
932 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
936 /***********************************************************************
937 * GetProfileInt32A (KERNEL32.264)
939 UINT WINAPI GetProfileIntA( LPCSTR section, LPCSTR entry, INT def_val )
941 return GetPrivateProfileIntA( section, entry, def_val, "win.ini" );
944 /***********************************************************************
945 * GetProfileInt32W (KERNEL32.264)
947 UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )
949 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
950 return GetPrivateProfileIntW( section, entry, def_val, wininiW );
953 /***********************************************************************
954 * GetProfileString16 (KERNEL.58)
956 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
957 LPSTR buffer, UINT16 len )
959 return GetPrivateProfileString16( section, entry, def_val,
960 buffer, len, "win.ini" );
963 /***********************************************************************
964 * GetProfileString32A (KERNEL32.268)
966 INT WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,
967 LPSTR buffer, UINT len )
969 return GetPrivateProfileStringA( section, entry, def_val,
970 buffer, len, "win.ini" );
973 /***********************************************************************
974 * GetProfileString32W (KERNEL32.269)
976 INT WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry,
977 LPCWSTR def_val, LPWSTR buffer, UINT len )
979 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
980 return GetPrivateProfileStringW( section, entry, def_val,
981 buffer, len, wininiW );
984 /***********************************************************************
985 * GetProfileSection32A (KERNEL32.268)
987 INT WINAPI GetProfileSectionA( LPCSTR section, LPSTR buffer, DWORD len )
989 return GetPrivateProfileSectionA( section, buffer, len, "win.ini" );
993 /***********************************************************************
994 * GetProfileSection32W (KERNEL32)
996 INT WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len )
998 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
999 return GetPrivateProfileSectionW( section, buffer, len, wininiW );
1006 /***********************************************************************
1007 * WriteProfileString16 (KERNEL.59)
1009 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
1010 LPCSTR string )
1012 return WritePrivateProfileString16( section, entry, string, "win.ini" );
1015 /***********************************************************************
1016 * WriteProfileString32A (KERNEL32.587)
1018 BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry,
1019 LPCSTR string )
1021 return WritePrivateProfileStringA( section, entry, string, "win.ini" );
1024 /***********************************************************************
1025 * WriteProfileString32W (KERNEL32.588)
1027 BOOL WINAPI WriteProfileStringW( LPCWSTR section, LPCWSTR entry,
1028 LPCWSTR string )
1030 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1031 return WritePrivateProfileStringW( section, entry, string, wininiW );
1035 /***********************************************************************
1036 * GetPrivateProfileInt16 (KERNEL.127)
1038 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
1039 INT16 def_val, LPCSTR filename )
1041 long result=(long)GetPrivateProfileIntA(section,entry,def_val,filename);
1043 if (result > 65535) return 65535;
1044 if (result >= 0) return (UINT16)result;
1045 if (result < -32768) return -32768;
1046 return (UINT16)(INT16)result;
1049 /***********************************************************************
1050 * GetPrivateProfileInt32A (KERNEL32.251)
1052 UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
1053 INT def_val, LPCSTR filename )
1055 char buffer[20];
1056 char *p;
1057 long result;
1059 GetPrivateProfileStringA( section, entry, "",
1060 buffer, sizeof(buffer), filename );
1061 if (!buffer[0]) return (UINT)def_val;
1062 result = strtol( buffer, &p, 0 );
1063 if (p == buffer) return 0; /* No digits at all */
1064 return (UINT)result;
1067 /***********************************************************************
1068 * GetPrivateProfileInt32W (KERNEL32.252)
1070 UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,
1071 INT def_val, LPCWSTR filename )
1073 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1074 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1075 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1076 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
1077 HeapFree( GetProcessHeap(), 0, sectionA );
1078 HeapFree( GetProcessHeap(), 0, filenameA );
1079 HeapFree( GetProcessHeap(), 0, entryA );
1080 return res;
1083 /***********************************************************************
1084 * GetPrivateProfileString16 (KERNEL.128)
1086 INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
1087 LPCSTR def_val, LPSTR buffer,
1088 UINT16 len, LPCSTR filename )
1090 return GetPrivateProfileStringA(section,entry,def_val,buffer,len,filename);
1093 /***********************************************************************
1094 * GetPrivateProfileString32A (KERNEL32.255)
1096 INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
1097 LPCSTR def_val, LPSTR buffer,
1098 UINT len, LPCSTR filename )
1100 if (!filename)
1101 filename = "win.ini";
1102 if (PROFILE_Open( filename ))
1103 return PROFILE_GetString( section, entry, def_val, buffer, len );
1104 lstrcpynA( buffer, def_val, len );
1105 return strlen( buffer );
1108 /***********************************************************************
1109 * GetPrivateProfileString32W (KERNEL32.256)
1111 INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
1112 LPCWSTR def_val, LPWSTR buffer,
1113 UINT len, LPCWSTR filename )
1115 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1116 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1117 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1118 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1119 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1120 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
1121 bufferA, len, filenameA );
1122 lstrcpynAtoW( buffer, bufferA, len );
1123 HeapFree( GetProcessHeap(), 0, sectionA );
1124 HeapFree( GetProcessHeap(), 0, entryA );
1125 HeapFree( GetProcessHeap(), 0, filenameA );
1126 HeapFree( GetProcessHeap(), 0, def_valA );
1127 HeapFree( GetProcessHeap(), 0, bufferA);
1128 return ret;
1131 /***********************************************************************
1132 * GetPrivateProfileSection32A (KERNEL32.255)
1134 INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,
1135 DWORD len, LPCSTR filename )
1137 if (PROFILE_Open( filename ))
1138 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
1139 FALSE, TRUE);
1141 return 0;
1144 /***********************************************************************
1145 * GetPrivateProfileSection32W (KERNEL32.256)
1148 INT WINAPI GetPrivateProfileSectionW (LPCWSTR section, LPWSTR buffer,
1149 DWORD len, LPCWSTR filename )
1152 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1153 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1154 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1155 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
1156 filenameA );
1157 HeapFree( GetProcessHeap(), 0, sectionA );
1158 HeapFree( GetProcessHeap(), 0, filenameA );
1159 HeapFree( GetProcessHeap(), 0, bufferA);
1160 return ret;
1163 /***********************************************************************
1164 * WritePrivateProfileString16 (KERNEL.129)
1166 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
1167 LPCSTR string, LPCSTR filename )
1169 return WritePrivateProfileStringA(section,entry,string,filename);
1172 /***********************************************************************
1173 * WritePrivateProfileString32A (KERNEL32.582)
1175 BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
1176 LPCSTR string, LPCSTR filename )
1178 if (!PROFILE_Open( filename )) return FALSE;
1179 if (!section) return PROFILE_FlushFile();
1180 return PROFILE_SetString( section, entry, string );
1183 /***********************************************************************
1184 * WritePrivateProfileString32W (KERNEL32.583)
1186 BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
1187 LPCWSTR string, LPCWSTR filename )
1189 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1190 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1191 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1192 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1193 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
1194 stringA, filenameA );
1195 HeapFree( GetProcessHeap(), 0, sectionA );
1196 HeapFree( GetProcessHeap(), 0, entryA );
1197 HeapFree( GetProcessHeap(), 0, stringA );
1198 HeapFree( GetProcessHeap(), 0, filenameA );
1199 return res;
1202 /***********************************************************************
1203 * WritePrivateProfileSection32A (KERNEL32)
1205 BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section,
1206 LPCSTR string, LPCSTR filename )
1208 char *p =(char*)string;
1210 FIXME(profile, "WritePrivateProfileSection32A empty stub\n");
1211 if (TRACE_ON(profile)) {
1212 TRACE(profile, "(%s) => [%s]\n", filename, section);
1213 while (*(p+1)) {
1214 TRACE(profile, "%s\n", p);
1215 p += strlen(p);
1216 p += 1;
1220 return FALSE;
1223 /***********************************************************************
1224 * WritePrivateProfileSection32W (KERNEL32)
1226 BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
1227 LPCWSTR string, LPCWSTR filename)
1230 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1231 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1232 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1233 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
1234 HeapFree( GetProcessHeap(), 0, sectionA );
1235 HeapFree( GetProcessHeap(), 0, stringA );
1236 HeapFree( GetProcessHeap(), 0, filenameA );
1237 return res;
1241 /***********************************************************************
1242 * WriteProfileSection32A (KERNEL32.747)
1244 BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values)
1247 return WritePrivateProfileSectionA( section, keys_n_values, "win.ini");
1250 /***********************************************************************
1251 * WriteProfileSection32W (KERNEL32.748)
1253 BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values)
1255 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini");
1257 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW));
1260 /***********************************************************************
1261 * GetPrivateProfileSectionNames16 (KERNEL.143)
1263 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1264 LPCSTR filename )
1266 char *buf;
1267 int l,cursize;
1268 PROFILESECTION *section;
1270 if (PROFILE_Open( filename )) {
1271 buf=buffer;
1272 cursize=0;
1273 section=CurProfile->section;
1274 for ( ; section; section = section->next)
1275 if (section->name) {
1276 l=strlen (section->name);
1277 cursize+=l+1;
1278 if (cursize > size+1)
1279 return size-2;
1280 strcpy (buf,section->name);
1281 buf+=l;
1282 *buf=0;
1283 buf++;
1285 buf++;
1286 *buf=0;
1287 return (buf-buffer);
1289 return FALSE;
1293 /***********************************************************************
1294 * GetProfileSectionNames16 (KERNEL.142)
1296 WORD WINAPI GetProfileSectionNames16( LPSTR buffer, WORD size)
1299 return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
1303 /***********************************************************************
1304 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1306 DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,
1307 LPCSTR filename)
1310 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1314 /***********************************************************************
1315 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1317 DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
1318 LPCWSTR filename)
1321 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1322 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, size);
1324 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1325 lstrcpynAtoW( buffer, bufferA, size);
1326 HeapFree( GetProcessHeap(), 0, bufferA);
1327 HeapFree( GetProcessHeap(), 0, filenameA );
1329 return ret;
1333 /***********************************************************************
1334 * GetPrivateProfileStruct32A (KERNEL32.370)
1336 BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
1337 LPVOID buf, UINT len, LPCSTR filename)
1339 PROFILEKEY *k;
1341 if (PROFILE_Open( filename )) {
1342 k=PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1343 if (!k) return FALSE;
1344 lstrcpynA( buf, k->value, strlen(k->value));
1345 return TRUE;
1347 return FALSE;
1350 /***********************************************************************
1351 * GetPrivateProfileStruct32W (KERNEL32.543)
1353 BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
1354 LPVOID buffer, UINT len, LPCWSTR filename)
1356 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1357 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1358 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1359 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1361 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
1362 len, filenameA );
1363 lstrcpynAtoW( buffer, bufferA, len );
1364 HeapFree( GetProcessHeap(), 0, bufferA);
1365 HeapFree( GetProcessHeap(), 0, sectionA );
1366 HeapFree( GetProcessHeap(), 0, keyA );
1367 HeapFree( GetProcessHeap(), 0, filenameA );
1369 return ret;
1375 /***********************************************************************
1376 * WritePrivateProfileStruct32A (KERNEL32.744)
1378 BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
1379 LPVOID buf, UINT bufsize, LPCSTR filename)
1381 if ((!section) && (!key) && (!buf)) { /* flush the cache */
1382 PROFILE_FlushFile();
1383 return FALSE;
1386 if (!PROFILE_Open( filename )) return FALSE;
1387 return PROFILE_SetString( section, key, buf);
1390 /***********************************************************************
1391 * WritePrivateProfileStruct32W (KERNEL32.544)
1393 BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
1394 LPVOID buf, UINT bufsize, LPCWSTR filename)
1396 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1397 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1398 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1399 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
1400 filenameA );
1401 HeapFree( GetProcessHeap(), 0, sectionA );
1402 HeapFree( GetProcessHeap(), 0, keyA );
1403 HeapFree( GetProcessHeap(), 0, filenameA );
1405 return ret;
1409 /***********************************************************************
1410 * WriteOutProfiles (KERNEL.315)
1412 void WINAPI WriteOutProfiles16(void)
1414 PROFILE_FlushFile();