Initial revision
[wine/multimedia.git] / files / profile.c
blob66f1d31b51520f8446edc5919a338ff4b0c9b6f1
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 "windows.h"
15 #include "file.h"
16 #include "heap.h"
17 #include "debug.h"
18 #include "options.h"
20 typedef struct tagPROFILEKEY
22 char *name;
23 char *value;
24 struct tagPROFILEKEY *next;
25 } PROFILEKEY;
27 typedef struct tagPROFILESECTION
29 char *name;
30 struct tagPROFILEKEY *key;
31 struct tagPROFILESECTION *next;
32 } PROFILESECTION;
35 typedef struct
37 BOOL32 changed;
38 PROFILESECTION *section;
39 char *dos_name;
40 char *unix_name;
41 char *filename;
42 time_t mtime;
43 } PROFILE;
46 #define N_CACHED_PROFILES 10
48 /* Cached profile files */
49 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
51 #define CurProfile (MRUProfile[0])
53 /* wine.ini profile content */
54 static PROFILESECTION *WineProfile;
56 #define PROFILE_MAX_LINE_LEN 1024
58 /* Wine profile name in $HOME directory; must begin with slash */
59 static const char PROFILE_WineIniName[] = "/.winerc";
61 /* Wine profile: the profile file being used */
62 static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
64 /* Check for comments in profile */
65 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
67 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
69 static LPCWSTR wininiW = NULL;
71 /***********************************************************************
72 * PROFILE_CopyEntry
74 * Copy the content of an entry into a buffer, removing quotes, and possibly
75 * translating environment variables.
77 static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
78 int handle_env )
80 char quote = '\0';
81 const char *p;
83 if ((*value == '\'') || (*value == '\"'))
85 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
88 if (!handle_env)
90 lstrcpyn32A( buffer, value, len );
91 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
92 return;
95 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
97 if ((*p == '$') && (p[1] == '{'))
99 char env_val[1024];
100 const char *env_p;
101 const char *p2 = strchr( p, '}' );
102 if (!p2) continue; /* ignore it */
103 lstrcpyn32A(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
104 if ((env_p = getenv( env_val )) != NULL)
106 lstrcpyn32A( buffer, env_p, len );
107 buffer += strlen( buffer );
108 len -= strlen( buffer );
110 p = p2 + 1;
113 *buffer = '\0';
117 /***********************************************************************
118 * PROFILE_Save
120 * Save a profile tree to a file.
122 static void PROFILE_Save( FILE *file, PROFILESECTION *section )
124 PROFILEKEY *key;
126 for ( ; section; section = section->next)
128 if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
129 for (key = section->key; key; key = key->next)
131 fprintf( file, "%s", key->name );
132 if (key->value) fprintf( file, "=%s", key->value );
133 fprintf( file, "\r\n" );
139 /***********************************************************************
140 * PROFILE_Free
142 * Free a profile tree.
144 static void PROFILE_Free( PROFILESECTION *section )
146 PROFILESECTION *next_section;
147 PROFILEKEY *key, *next_key;
149 for ( ; section; section = next_section)
151 if (section->name) HeapFree( SystemHeap, 0, section->name );
152 for (key = section->key; key; key = next_key)
154 next_key = key->next;
155 if (key->name) HeapFree( SystemHeap, 0, key->name );
156 if (key->value) HeapFree( SystemHeap, 0, key->value );
157 HeapFree( SystemHeap, 0, key );
159 next_section = section->next;
160 HeapFree( SystemHeap, 0, section );
164 static int
165 PROFILE_isspace(char c) {
166 if (isspace(c)) return 1;
167 if (c=='\r' || c==0x1a) return 1;
168 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
169 return 0;
173 /***********************************************************************
174 * PROFILE_Load
176 * Load a profile tree from a file.
178 static PROFILESECTION *PROFILE_Load( FILE *file )
180 char buffer[PROFILE_MAX_LINE_LEN];
181 char *p, *p2;
182 int line = 0;
183 PROFILESECTION *section, *first_section;
184 PROFILESECTION **next_section;
185 PROFILEKEY *key, *prev_key, **next_key;
187 first_section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
188 first_section->name = NULL;
189 first_section->key = NULL;
190 first_section->next = NULL;
191 next_section = &first_section->next;
192 next_key = &first_section->key;
193 prev_key = NULL;
195 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
197 line++;
198 p = buffer;
199 while (*p && PROFILE_isspace(*p)) p++;
200 if (*p == '[') /* section start */
202 if (!(p2 = strrchr( p, ']' )))
204 WARN(profile, "Invalid section header at line %d: '%s'\n",
205 line, p );
207 else
209 *p2 = '\0';
210 p++;
211 section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
212 section->name = HEAP_strdupA( SystemHeap, 0, p );
213 section->key = NULL;
214 section->next = NULL;
215 *next_section = section;
216 next_section = &section->next;
217 next_key = &section->key;
218 prev_key = NULL;
220 TRACE(profile, "New section: '%s'\n",section->name);
222 continue;
226 p2=p+strlen(p) - 1;
227 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
229 if ((p2 = strchr( p, '=' )) != NULL)
231 char *p3 = p2 - 1;
232 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
233 *p2++ = '\0';
234 while (*p2 && PROFILE_isspace(*p2)) p2++;
237 if(*p || !prev_key || *prev_key->name)
239 key = HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
240 key->name = HEAP_strdupA( SystemHeap, 0, p );
241 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
242 key->next = NULL;
243 *next_key = key;
244 next_key = &key->next;
245 prev_key = key;
247 TRACE(profile, "New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)");
250 return first_section;
254 /***********************************************************************
255 * PROFILE_DeleteSection
257 * Delete a section from a profile tree.
259 static BOOL32 PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
261 while (*section)
263 if ((*section)->name && !strcasecmp( (*section)->name, name ))
265 PROFILESECTION *to_del = *section;
266 *section = to_del->next;
267 to_del->next = NULL;
268 PROFILE_Free( to_del );
269 return TRUE;
271 section = &(*section)->next;
273 return FALSE;
277 /***********************************************************************
278 * PROFILE_DeleteKey
280 * Delete a key from a profile tree.
282 static BOOL32 PROFILE_DeleteKey( PROFILESECTION **section,
283 LPCSTR section_name, LPCSTR key_name )
285 while (*section)
287 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
289 PROFILEKEY **key = &(*section)->key;
290 while (*key)
292 if (!strcasecmp( (*key)->name, key_name ))
294 PROFILEKEY *to_del = *key;
295 *key = to_del->next;
296 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
297 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
298 HeapFree( SystemHeap, 0, to_del );
299 return TRUE;
301 key = &(*key)->next;
304 section = &(*section)->next;
306 return FALSE;
310 /***********************************************************************
311 * PROFILE_Find
313 * Find a key in a profile tree, optionally creating it.
315 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
316 const char *section_name,
317 const char *key_name, int create )
319 while (*section)
321 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
323 PROFILEKEY **key = &(*section)->key;
324 while (*key)
326 if (!strcasecmp( (*key)->name, key_name )) return *key;
327 key = &(*key)->next;
329 if (!create) return NULL;
330 *key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
331 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
332 (*key)->value = NULL;
333 (*key)->next = NULL;
334 return *key;
336 section = &(*section)->next;
338 if (!create) return NULL;
339 *section = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
340 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
341 (*section)->next = NULL;
342 (*section)->key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
343 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
344 (*section)->key->value = NULL;
345 (*section)->key->next = NULL;
346 return (*section)->key;
350 /***********************************************************************
351 * PROFILE_FlushFile
353 * Flush the current profile to disk if changed.
355 static BOOL32 PROFILE_FlushFile(void)
357 char *p, buffer[MAX_PATHNAME_LEN];
358 const char *unix_name;
359 FILE *file = NULL;
360 struct stat buf;
362 if(!CurProfile)
364 WARN(profile, "No current profile!\n");
365 return FALSE;
368 if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
369 if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
371 /* Try to create it in $HOME/.wine */
372 /* FIXME: this will need a more general solution */
373 if ((p = getenv( "HOME" )) != NULL)
375 strcpy( buffer, p );
376 strcat( buffer, "/.wine/" );
377 p = buffer + strlen(buffer);
378 strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
379 CharLower32A( p );
380 file = fopen( buffer, "w" );
381 unix_name = buffer;
385 if (!file)
387 WARN(profile, "could not save profile file %s\n", CurProfile->dos_name);
388 return FALSE;
391 TRACE(profile, "Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name );
392 PROFILE_Save( file, CurProfile->section );
393 fclose( file );
394 CurProfile->changed = FALSE;
395 if(!stat(unix_name,&buf))
396 CurProfile->mtime=buf.st_mtime;
397 return TRUE;
401 /***********************************************************************
402 * PROFILE_Open
404 * Open a profile file, checking the cached file first.
406 static BOOL32 PROFILE_Open( LPCSTR filename )
408 DOS_FULL_NAME full_name;
409 char buffer[MAX_PATHNAME_LEN];
410 char *newdos_name, *p;
411 FILE *file = NULL;
412 int i,j;
413 struct stat buf;
414 PROFILE *tempProfile;
416 /* First time around */
418 if(!CurProfile)
419 for(i=0;i<N_CACHED_PROFILES;i++)
421 MRUProfile[i]=HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );
422 MRUProfile[i]->changed=FALSE;
423 MRUProfile[i]->section=NULL;
424 MRUProfile[i]->dos_name=NULL;
425 MRUProfile[i]->unix_name=NULL;
426 MRUProfile[i]->filename=NULL;
427 MRUProfile[i]->mtime=0;
430 /* Check for a match */
432 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
433 strchr( filename, ':' ))
435 if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
437 else
439 GetWindowsDirectory32A( buffer, sizeof(buffer) );
440 strcat( buffer, "\\" );
441 strcat( buffer, filename );
442 if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
445 for(i=0;i<N_CACHED_PROFILES;i++)
447 if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )) ||
448 (MRUProfile[i]->dos_name && !strcmp( full_name.short_name, MRUProfile[i]->dos_name )))
450 if(i)
452 PROFILE_FlushFile();
453 tempProfile=MRUProfile[i];
454 for(j=i;j>0;j--)
455 MRUProfile[j]=MRUProfile[j-1];
456 CurProfile=tempProfile;
458 if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
459 TRACE(profile, "(%s): already opened (mru=%d)\n",
460 filename, i );
461 else
462 TRACE(profile, "(%s): already opened, needs refreshing (mru=%d)\n",
463 filename, i );
464 return TRUE;
468 /* Rotate the oldest to the top to be replaced */
470 if(i==N_CACHED_PROFILES)
472 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
473 for(i=N_CACHED_PROFILES-1;i>0;i--)
474 MRUProfile[i]=MRUProfile[i-1];
475 CurProfile=tempProfile;
478 /* Flush the profile */
480 if(CurProfile->filename)
482 PROFILE_FlushFile();
483 PROFILE_Free( CurProfile->section );
484 if (CurProfile->dos_name) HeapFree( SystemHeap, 0, CurProfile->dos_name );
485 if (CurProfile->unix_name) HeapFree( SystemHeap, 0, CurProfile->unix_name );
486 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
487 CurProfile->changed=FALSE;
488 CurProfile->section=NULL;
489 CurProfile->dos_name=NULL;
490 CurProfile->unix_name=NULL;
491 CurProfile->filename=NULL;
492 CurProfile->mtime=0;
495 newdos_name = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
496 CurProfile->dos_name = newdos_name;
497 CurProfile->filename = HEAP_strdupA( SystemHeap, 0, filename );
499 /* Try to open the profile file, first in $HOME/.wine */
501 /* FIXME: this will need a more general solution */
502 if ((p = getenv( "HOME" )) != NULL)
504 strcpy( buffer, p );
505 strcat( buffer, "/.wine/" );
506 p = buffer + strlen(buffer);
507 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
508 CharLower32A( p );
509 if ((file = fopen( buffer, "r" )))
511 TRACE(profile, "(%s): found it in %s\n",
512 filename, buffer );
513 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
517 if (!file)
519 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0,
520 full_name.long_name );
521 if ((file = fopen( full_name.long_name, "r" )))
522 TRACE(profile, "(%s): found it in %s\n",
523 filename, full_name.long_name );
526 if (file)
528 CurProfile->section = PROFILE_Load( file );
529 fclose( file );
530 if(!stat(CurProfile->unix_name,&buf))
531 CurProfile->mtime=buf.st_mtime;
533 else
535 /* Does not exist yet, we will create it in PROFILE_FlushFile */
536 WARN(profile, "profile file %s not found\n", newdos_name );
538 return TRUE;
542 /***********************************************************************
543 * PROFILE_GetSection
545 * Returns all keys of a section.
546 * If return_values is TRUE, also include the corresponding values.
548 static INT32 PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
549 LPSTR buffer, UINT32 len, BOOL32 handle_env,
550 BOOL32 return_values )
552 PROFILEKEY *key;
553 while (section)
555 if (section->name && !strcasecmp( section->name, section_name ))
557 UINT32 oldlen = len;
558 for (key = section->key; key && *(key->name); key = key->next)
560 if (len <= 2) break;
561 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
562 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
563 len -= strlen(buffer) + 1;
564 buffer += strlen(buffer) + 1;
565 if (return_values && key->value) {
566 buffer[-1] = '=';
567 PROFILE_CopyEntry ( buffer,
568 key->value, len - 1, handle_env );
569 len -= strlen(buffer) + 1;
570 buffer += strlen(buffer) + 1;
573 *buffer = '\0';
574 if (len < 1)
575 /*If either lpszSection or lpszKey is NULL and the supplied
576 destination buffer is too small to hold all the strings,
577 the last string is truncated and followed by two null characters.
578 In this case, the return value is equal to cchReturnBuffer
579 minus two. */
581 buffer[-1] = '\0';
582 return oldlen - 2;
584 return oldlen - len;
586 section = section->next;
588 buffer[0] = buffer[1] = '\0';
589 return 0;
593 /***********************************************************************
594 * PROFILE_GetString
596 * Get a profile string.
598 static INT32 PROFILE_GetString( LPCSTR section, LPCSTR key_name,
599 LPCSTR def_val, LPSTR buffer, UINT32 len )
601 PROFILEKEY *key = NULL;
603 if (!def_val) def_val = "";
604 if (key_name && key_name[0])
606 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
607 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
608 len, FALSE );
609 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
610 section, key_name, def_val, buffer );
611 return strlen( buffer );
613 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
614 FALSE, FALSE);
618 /***********************************************************************
619 * PROFILE_SetString
621 * Set a profile string.
623 static BOOL32 PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
624 LPCSTR value )
626 if (!key_name) /* Delete a whole section */
628 TRACE(profile, "('%s')\n", section_name);
629 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
630 section_name );
631 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
632 this is not an error on application's level.*/
634 else if (!value) /* Delete a key */
636 TRACE(profile, "('%s','%s')\n",
637 section_name, key_name );
638 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
639 section_name, key_name );
640 return TRUE; /* same error handling as above */
642 else /* Set the key value */
644 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
645 key_name, TRUE );
646 TRACE(profile, "('%s','%s','%s'): \n",
647 section_name, key_name, value );
648 if (!key) return FALSE;
649 if (key->value)
651 if (!strcmp( key->value, value ))
653 TRACE(profile, " no change needed\n" );
654 return TRUE; /* No change needed */
656 TRACE(profile, " replacing '%s'\n", key->value );
657 HeapFree( SystemHeap, 0, key->value );
659 else TRACE(profile, " creating key\n" );
660 key->value = HEAP_strdupA( SystemHeap, 0, value );
661 CurProfile->changed = TRUE;
663 return TRUE;
667 /***********************************************************************
668 * PROFILE_GetWineIniString
670 * Get a config string from the wine.ini file.
672 int PROFILE_GetWineIniString( const char *section, const char *key_name,
673 const char *def, char *buffer, int len )
675 if (key_name)
677 PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
678 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
679 len, TRUE );
680 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
681 section, key_name, def, buffer );
682 return strlen( buffer );
684 return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE, FALSE );
688 /***********************************************************************
689 * PROFILE_GetWineIniInt
691 * Get a config integer from the wine.ini file.
693 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
695 char buffer[20];
696 char *p;
697 long result;
699 PROFILEKEY *key = PROFILE_Find( &WineProfile, section, key_name, FALSE );
700 if (!key || !key->value) return def;
701 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
702 result = strtol( buffer, &p, 0 );
703 if (p == buffer) return 0; /* No digits at all */
704 return (int)result;
708 /******************************************************************************
710 * int PROFILE_EnumerateWineIniSection(
711 * char const *section, // Name of the section to enumerate
712 * void (*cbfn)(char const *key, char const *value, void *user),
713 // Address of the callback function
714 * void *user ) // User-specified pointer.
716 * For each entry in a section in the wine.conf file, this function will
717 * call the specified callback function, informing it of each key and
718 * value. An optional user pointer may be passed to it (if this is not
719 * needed, pass NULL through it and ignore the value in the callback
720 * function).
722 * The callback function must accept three parameters:
723 * The name of the key (char const *)
724 * The value of the key (char const *)
725 * A user-specified parameter (void *)
726 * Note that the first two are char CONST *'s, not char *'s! The callback
727 * MUST not modify these strings!
729 * The return value indicates the number of times the callback function
730 * was called.
732 int PROFILE_EnumerateWineIniSection(
733 char const *section,
734 void (*cbfn)(char const *, char const *, void *),
735 void *userptr )
737 PROFILESECTION *scansect;
738 PROFILEKEY *scankey;
739 int calls = 0;
741 /* Search for the correct section */
742 for(scansect = WineProfile; scansect; scansect = scansect->next) {
743 if(scansect->name && !strcasecmp(scansect->name, section)) {
745 /* Enumerate each key with the callback */
746 for(scankey = scansect->key; scankey; scankey = scankey->next) {
748 /* Ignore blank entries -- these shouldn't exist, but let's
749 be extra careful */
750 if(scankey->name[0]) {
751 cbfn(scankey->name, scankey->value, userptr);
752 ++calls;
756 break;
760 return calls;
764 /******************************************************************************
766 * int PROFILE_GetWineIniBool(
767 * char const *section,
768 * char const *key_name,
769 * int def )
771 * Reads a boolean value from the wine.ini file. This function attempts to
772 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
773 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
774 * true. Anything else results in the return of the default value.
776 * This function uses 1 to indicate true, and 0 for false. You can check
777 * for existence by setting def to something other than 0 or 1 and
778 * examining the return value.
780 int PROFILE_GetWineIniBool(
781 char const *section,
782 char const *key_name,
783 int def )
785 char key_value[2];
786 int retval;
788 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
790 switch(key_value[0]) {
791 case 'n':
792 case 'N':
793 case 'f':
794 case 'F':
795 case '0':
796 retval = 0;
797 break;
799 case 'y':
800 case 'Y':
801 case 't':
802 case 'T':
803 case '1':
804 retval = 1;
805 break;
807 default:
808 retval = def;
811 TRACE(profile, "(\"%s\", \"%s\", %s), "
812 "[%c], ret %s.\n", section, key_name,
813 def ? "TRUE" : "FALSE", key_value[0],
814 retval ? "TRUE" : "FALSE");
816 return retval;
820 /***********************************************************************
821 * PROFILE_LoadWineIni
823 * Load the wine.ini file.
825 int PROFILE_LoadWineIni(void)
827 char buffer[MAX_PATHNAME_LEN];
828 const char *p;
829 FILE *f;
831 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
833 /* Open -config specified file */
834 WineProfile = PROFILE_Load ( f);
835 fclose ( f );
836 strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);
837 return 1;
840 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
842 WineProfile = PROFILE_Load( f );
843 fclose( f );
844 strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);
845 return 1;
847 if ((p = getenv( "HOME" )) != NULL)
849 lstrcpyn32A(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
850 strcat( buffer, PROFILE_WineIniName );
851 if ((f = fopen( buffer, "r" )) != NULL)
853 WineProfile = PROFILE_Load( f );
854 fclose( f );
855 strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);
856 return 1;
859 else WARN(profile, "could not get $HOME value for config file.\n" );
861 /* Try global file */
863 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
865 WineProfile = PROFILE_Load( f );
866 fclose( f );
867 strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);
868 return 1;
870 MSG( "Can't open configuration file %s or $HOME%s\n",
871 WINE_INI_GLOBAL, PROFILE_WineIniName );
872 return 0;
876 /***********************************************************************
877 * PROFILE_UsageWineIni
879 * Explain the wine.ini file to those who don't read documentation.
880 * Keep below one screenful in length so that error messages above are
881 * noticed.
883 void PROFILE_UsageWineIni(void)
885 MSG("Perhaps you have not properly edited or created "
886 "your Wine configuration file.\n");
887 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
888 MSG(" or it is determined by the -config option or from\n"
889 " the WINE_INI environment variable.\n");
890 if (*PROFILE_WineIniUsed)
891 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
892 /* RTFM, so to say */
896 /***********************************************************************
897 * PROFILE_GetStringItem
899 * Convenience function that turns a string 'xxx, yyy, zzz' into
900 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
902 char* PROFILE_GetStringItem( char* start )
904 char* lpchX, *lpch;
906 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
908 if( *lpchX == ',' )
910 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
911 while( *(++lpchX) )
912 if( !PROFILE_isspace(*lpchX) ) return lpchX;
914 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
915 else lpch = NULL;
917 if( lpch ) *lpch = '\0';
918 return NULL;
922 /********************* API functions **********************************/
924 /***********************************************************************
925 * GetProfileInt16 (KERNEL.57)
927 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
929 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
933 /***********************************************************************
934 * GetProfileInt32A (KERNEL32.264)
936 UINT32 WINAPI GetProfileInt32A( LPCSTR section, LPCSTR entry, INT32 def_val )
938 return GetPrivateProfileInt32A( section, entry, def_val, "win.ini" );
941 /***********************************************************************
942 * GetProfileInt32W (KERNEL32.264)
944 UINT32 WINAPI GetProfileInt32W( LPCWSTR section, LPCWSTR entry, INT32 def_val )
946 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
947 return GetPrivateProfileInt32W( section, entry, def_val, wininiW );
950 /***********************************************************************
951 * GetProfileString16 (KERNEL.58)
953 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
954 LPSTR buffer, UINT16 len )
956 return GetPrivateProfileString16( section, entry, def_val,
957 buffer, len, "win.ini" );
960 /***********************************************************************
961 * GetProfileString32A (KERNEL32.268)
963 INT32 WINAPI GetProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR def_val,
964 LPSTR buffer, UINT32 len )
966 return GetPrivateProfileString32A( section, entry, def_val,
967 buffer, len, "win.ini" );
970 /***********************************************************************
971 * GetProfileString32W (KERNEL32.269)
973 INT32 WINAPI GetProfileString32W( LPCWSTR section, LPCWSTR entry,
974 LPCWSTR def_val, LPWSTR buffer, UINT32 len )
976 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
977 return GetPrivateProfileString32W( section, entry, def_val,
978 buffer, len, wininiW );
981 /***********************************************************************
982 * GetProfileSection32A (KERNEL32.268)
984 INT32 WINAPI GetProfileSection32A( LPCSTR section, LPSTR buffer, DWORD len )
986 return GetPrivateProfileSection32A( section, buffer, len, "win.ini" );
990 /***********************************************************************
991 * GetProfileSection32W (KERNEL32)
993 INT32 WINAPI GetProfileSection32W( LPCWSTR section, LPWSTR buffer, DWORD len )
995 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
996 return GetPrivateProfileSection32W( section, buffer, len, wininiW );
1003 /***********************************************************************
1004 * WriteProfileString16 (KERNEL.59)
1006 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
1007 LPCSTR string )
1009 return WritePrivateProfileString16( section, entry, string, "win.ini" );
1012 /***********************************************************************
1013 * WriteProfileString32A (KERNEL32.587)
1015 BOOL32 WINAPI WriteProfileString32A( LPCSTR section, LPCSTR entry,
1016 LPCSTR string )
1018 return WritePrivateProfileString32A( section, entry, string, "win.ini" );
1021 /***********************************************************************
1022 * WriteProfileString32W (KERNEL32.588)
1024 BOOL32 WINAPI WriteProfileString32W( LPCWSTR section, LPCWSTR entry,
1025 LPCWSTR string )
1027 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1028 return WritePrivateProfileString32W( section, entry, string, wininiW );
1032 /***********************************************************************
1033 * GetPrivateProfileInt16 (KERNEL.127)
1035 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
1036 INT16 def_val, LPCSTR filename )
1038 long result=(long)GetPrivateProfileInt32A(section,entry,def_val,filename);
1040 if (result > 65535) return 65535;
1041 if (result >= 0) return (UINT16)result;
1042 if (result < -32768) return -32768;
1043 return (UINT16)(INT16)result;
1046 /***********************************************************************
1047 * GetPrivateProfileInt32A (KERNEL32.251)
1049 UINT32 WINAPI GetPrivateProfileInt32A( LPCSTR section, LPCSTR entry,
1050 INT32 def_val, LPCSTR filename )
1052 char buffer[20];
1053 char *p;
1054 long result;
1056 GetPrivateProfileString32A( section, entry, "",
1057 buffer, sizeof(buffer), filename );
1058 if (!buffer[0]) return (UINT32)def_val;
1059 result = strtol( buffer, &p, 0 );
1060 if (p == buffer) return 0; /* No digits at all */
1061 return (UINT32)result;
1064 /***********************************************************************
1065 * GetPrivateProfileInt32W (KERNEL32.252)
1067 UINT32 WINAPI GetPrivateProfileInt32W( LPCWSTR section, LPCWSTR entry,
1068 INT32 def_val, LPCWSTR filename )
1070 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1071 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1072 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1073 UINT32 res = GetPrivateProfileInt32A(sectionA, entryA, def_val, filenameA);
1074 HeapFree( GetProcessHeap(), 0, sectionA );
1075 HeapFree( GetProcessHeap(), 0, filenameA );
1076 HeapFree( GetProcessHeap(), 0, entryA );
1077 return res;
1080 /***********************************************************************
1081 * GetPrivateProfileString16 (KERNEL.128)
1083 INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
1084 LPCSTR def_val, LPSTR buffer,
1085 UINT16 len, LPCSTR filename )
1087 return GetPrivateProfileString32A(section,entry,def_val,buffer,len,filename);
1090 /***********************************************************************
1091 * GetPrivateProfileString32A (KERNEL32.255)
1093 INT32 WINAPI GetPrivateProfileString32A( LPCSTR section, LPCSTR entry,
1094 LPCSTR def_val, LPSTR buffer,
1095 UINT32 len, LPCSTR filename )
1097 if (!filename)
1098 filename = "win.ini";
1099 if (PROFILE_Open( filename ))
1100 return PROFILE_GetString( section, entry, def_val, buffer, len );
1101 lstrcpyn32A( buffer, def_val, len );
1102 return strlen( buffer );
1105 /***********************************************************************
1106 * GetPrivateProfileString32W (KERNEL32.256)
1108 INT32 WINAPI GetPrivateProfileString32W( LPCWSTR section, LPCWSTR entry,
1109 LPCWSTR def_val, LPWSTR buffer,
1110 UINT32 len, LPCWSTR filename )
1112 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1113 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1114 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1115 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1116 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1117 INT32 ret = GetPrivateProfileString32A( sectionA, entryA, def_valA,
1118 bufferA, len, filenameA );
1119 lstrcpynAtoW( buffer, bufferA, len );
1120 HeapFree( GetProcessHeap(), 0, sectionA );
1121 HeapFree( GetProcessHeap(), 0, entryA );
1122 HeapFree( GetProcessHeap(), 0, filenameA );
1123 HeapFree( GetProcessHeap(), 0, def_valA );
1124 HeapFree( GetProcessHeap(), 0, bufferA);
1125 return ret;
1128 /***********************************************************************
1129 * GetPrivateProfileSection32A (KERNEL32.255)
1131 INT32 WINAPI GetPrivateProfileSection32A( LPCSTR section, LPSTR buffer,
1132 DWORD len, LPCSTR filename )
1134 if (PROFILE_Open( filename ))
1135 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
1136 FALSE, TRUE);
1138 return 0;
1141 /***********************************************************************
1142 * GetPrivateProfileSection32W (KERNEL32.256)
1145 INT32 WINAPI GetPrivateProfileSection32W (LPCWSTR section, LPWSTR buffer,
1146 DWORD len, LPCWSTR filename )
1149 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1150 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1151 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1152 INT32 ret = GetPrivateProfileSection32A( sectionA, bufferA, len,
1153 filenameA );
1154 HeapFree( GetProcessHeap(), 0, sectionA );
1155 HeapFree( GetProcessHeap(), 0, filenameA );
1156 HeapFree( GetProcessHeap(), 0, bufferA);
1157 return ret;
1160 /***********************************************************************
1161 * WritePrivateProfileString16 (KERNEL.129)
1163 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
1164 LPCSTR string, LPCSTR filename )
1166 return WritePrivateProfileString32A(section,entry,string,filename);
1169 /***********************************************************************
1170 * WritePrivateProfileString32A (KERNEL32.582)
1172 BOOL32 WINAPI WritePrivateProfileString32A( LPCSTR section, LPCSTR entry,
1173 LPCSTR string, LPCSTR filename )
1175 if (!PROFILE_Open( filename )) return FALSE;
1176 if (!section) return PROFILE_FlushFile();
1177 return PROFILE_SetString( section, entry, string );
1180 /***********************************************************************
1181 * WritePrivateProfileString32W (KERNEL32.583)
1183 BOOL32 WINAPI WritePrivateProfileString32W( LPCWSTR section, LPCWSTR entry,
1184 LPCWSTR string, LPCWSTR filename )
1186 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1187 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1188 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1189 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1190 BOOL32 res = WritePrivateProfileString32A( sectionA, entryA,
1191 stringA, filenameA );
1192 HeapFree( GetProcessHeap(), 0, sectionA );
1193 HeapFree( GetProcessHeap(), 0, entryA );
1194 HeapFree( GetProcessHeap(), 0, stringA );
1195 HeapFree( GetProcessHeap(), 0, filenameA );
1196 return res;
1199 /***********************************************************************
1200 * WritePrivateProfileSection32A (KERNEL32)
1202 BOOL32 WINAPI WritePrivateProfileSection32A( LPCSTR section,
1203 LPCSTR string, LPCSTR filename )
1205 char *p =(char*)string;
1207 FIXME(profile, "WritePrivateProfileSection32A empty stub\n");
1208 if (TRACE_ON(profile)) {
1209 TRACE(profile, "(%s) => [%s]\n", filename, section);
1210 while (*(p+1)) {
1211 TRACE(profile, "%s\n", p);
1212 p += strlen(p);
1213 p += 1;
1217 return FALSE;
1220 /***********************************************************************
1221 * WritePrivateProfileSection32W (KERNEL32)
1223 BOOL32 WINAPI WritePrivateProfileSection32W( LPCWSTR section,
1224 LPCWSTR string, LPCWSTR filename)
1227 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1228 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1229 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1230 BOOL32 res = WritePrivateProfileSection32A( sectionA, stringA, filenameA );
1231 HeapFree( GetProcessHeap(), 0, sectionA );
1232 HeapFree( GetProcessHeap(), 0, stringA );
1233 HeapFree( GetProcessHeap(), 0, filenameA );
1234 return res;
1238 /***********************************************************************
1239 * WriteProfileSection32A (KERNEL32.747)
1241 BOOL32 WINAPI WriteProfileSection32A( LPCSTR section, LPCSTR keys_n_values)
1244 return WritePrivateProfileSection32A( section, keys_n_values, "win.ini");
1247 /***********************************************************************
1248 * WriteProfileSection32W (KERNEL32.748)
1250 BOOL32 WINAPI WriteProfileSection32W( LPCWSTR section, LPCWSTR keys_n_values)
1252 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini");
1254 return (WritePrivateProfileSection32W (section,keys_n_values, wininiW));
1257 /***********************************************************************
1258 * GetPrivateProfileSectionNames16 (KERNEL.143)
1260 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1261 LPCSTR filename )
1263 char *buf;
1264 int l,cursize;
1265 PROFILESECTION *section;
1267 if (PROFILE_Open( filename )) {
1268 buf=buffer;
1269 cursize=0;
1270 section=CurProfile->section;
1271 for ( ; section; section = section->next)
1272 if (section->name) {
1273 l=strlen (section->name);
1274 cursize+=l+1;
1275 if (cursize > size+1)
1276 return size-2;
1277 strcpy (buf,section->name);
1278 buf+=l;
1279 *buf=0;
1280 buf++;
1282 buf++;
1283 *buf=0;
1284 return (buf-buffer);
1286 return FALSE;
1290 /***********************************************************************
1291 * GetProfileSectionNames16 (KERNEL.142)
1293 WORD WINAPI GetProfileSectionNames16( LPSTR buffer, WORD size)
1296 return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
1300 /***********************************************************************
1301 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1303 DWORD WINAPI GetPrivateProfileSectionNames32A( LPSTR buffer, DWORD size,
1304 LPCSTR filename)
1307 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1311 /***********************************************************************
1312 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1314 DWORD WINAPI GetPrivateProfileSectionNames32W( LPWSTR buffer, DWORD size,
1315 LPCWSTR filename)
1318 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1319 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, size);
1321 INT32 ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1322 lstrcpynAtoW( buffer, bufferA, size);
1323 HeapFree( GetProcessHeap(), 0, bufferA);
1324 HeapFree( GetProcessHeap(), 0, filenameA );
1326 return ret;
1330 /***********************************************************************
1331 * GetPrivateProfileStruct32A (KERNEL32.370)
1333 BOOL32 WINAPI GetPrivateProfileStruct32A (LPCSTR section, LPCSTR key,
1334 LPVOID buf, UINT32 len, LPCSTR filename)
1336 PROFILEKEY *k;
1338 if (PROFILE_Open( filename )) {
1339 k=PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1340 if (!k) return FALSE;
1341 lstrcpyn32A( buf, k->value, strlen(k->value));
1342 return TRUE;
1344 return FALSE;
1347 /***********************************************************************
1348 * GetPrivateProfileStruct32W (KERNEL32.543)
1350 BOOL32 WINAPI GetPrivateProfileStruct32W (LPCWSTR section, LPCWSTR key,
1351 LPVOID buffer, UINT32 len, LPCWSTR filename)
1353 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1354 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1355 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1356 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1358 INT32 ret = GetPrivateProfileStruct32A( sectionA, keyA, bufferA,
1359 len, filenameA );
1360 lstrcpynAtoW( buffer, bufferA, len );
1361 HeapFree( GetProcessHeap(), 0, bufferA);
1362 HeapFree( GetProcessHeap(), 0, sectionA );
1363 HeapFree( GetProcessHeap(), 0, keyA );
1364 HeapFree( GetProcessHeap(), 0, filenameA );
1366 return ret;
1372 /***********************************************************************
1373 * WritePrivateProfileStruct32A (KERNEL32.744)
1375 BOOL32 WINAPI WritePrivateProfileStruct32A (LPCSTR section, LPCSTR key,
1376 LPVOID buf, UINT32 bufsize, LPCSTR filename)
1378 if ((!section) && (!key) && (!buf)) { /* flush the cache */
1379 PROFILE_FlushFile();
1380 return FALSE;
1383 if (!PROFILE_Open( filename )) return FALSE;
1384 return PROFILE_SetString( section, key, buf);
1387 /***********************************************************************
1388 * WritePrivateProfileStruct32W (KERNEL32.544)
1390 BOOL32 WINAPI WritePrivateProfileStruct32W (LPCWSTR section, LPCWSTR key,
1391 LPVOID buf, UINT32 bufsize, LPCWSTR filename)
1393 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1394 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1395 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1396 INT32 ret = WritePrivateProfileStruct32A( sectionA, keyA, buf, bufsize,
1397 filenameA );
1398 HeapFree( GetProcessHeap(), 0, sectionA );
1399 HeapFree( GetProcessHeap(), 0, keyA );
1400 HeapFree( GetProcessHeap(), 0, filenameA );
1402 return ret;
1406 /***********************************************************************
1407 * WriteOutProfiles (KERNEL.315)
1409 void WINAPI WriteOutProfiles(void)
1411 PROFILE_FlushFile();