Release 980726
[wine/multimedia.git] / files / profile.c
blobc1f0daf492ee35837bdbfafe04de0b536b5ddfc1
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"
19 typedef struct tagPROFILEKEY
21 char *name;
22 char *value;
23 struct tagPROFILEKEY *next;
24 } PROFILEKEY;
26 typedef struct tagPROFILESECTION
28 char *name;
29 struct tagPROFILEKEY *key;
30 struct tagPROFILESECTION *next;
31 } PROFILESECTION;
34 typedef struct
36 BOOL32 changed;
37 PROFILESECTION *section;
38 char *dos_name;
39 char *unix_name;
40 char *filename;
41 time_t mtime;
42 } PROFILE;
45 #define N_CACHED_PROFILES 10
47 /* Cached profile files */
48 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
50 #define CurProfile (MRUProfile[0])
52 /* wine.ini profile content */
53 static PROFILESECTION *WineProfile;
55 #define PROFILE_MAX_LINE_LEN 1024
57 /* Wine profile name in $HOME directory; must begin with slash */
58 static const char PROFILE_WineIniName[] = "/.winerc";
60 /* Check for comments in profile */
61 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
63 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
65 static LPCWSTR wininiW = NULL;
67 /***********************************************************************
68 * PROFILE_CopyEntry
70 * Copy the content of an entry into a buffer, removing quotes, and possibly
71 * translating environment variables.
73 static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
74 int handle_env )
76 char quote = '\0';
77 const char *p;
79 if ((*value == '\'') || (*value == '\"'))
81 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
84 if (!handle_env)
86 lstrcpyn32A( buffer, value, len );
87 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
88 return;
91 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
93 if ((*p == '$') && (p[1] == '{'))
95 char env_val[1024];
96 const char *env_p;
97 const char *p2 = strchr( p, '}' );
98 if (!p2) continue; /* ignore it */
99 lstrcpyn32A(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
100 if ((env_p = getenv( env_val )) != NULL)
102 lstrcpyn32A( buffer, env_p, len );
103 buffer += strlen( buffer );
104 len -= strlen( buffer );
106 p = p2 + 1;
109 *buffer = '\0';
113 /***********************************************************************
114 * PROFILE_Save
116 * Save a profile tree to a file.
118 static void PROFILE_Save( FILE *file, PROFILESECTION *section )
120 PROFILEKEY *key;
122 for ( ; section; section = section->next)
124 if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
125 for (key = section->key; key; key = key->next)
127 fprintf( file, "%s", key->name );
128 if (key->value) fprintf( file, "=%s", key->value );
129 fprintf( file, "\r\n" );
135 /***********************************************************************
136 * PROFILE_Free
138 * Free a profile tree.
140 static void PROFILE_Free( PROFILESECTION *section )
142 PROFILESECTION *next_section;
143 PROFILEKEY *key, *next_key;
145 for ( ; section; section = next_section)
147 if (section->name) HeapFree( SystemHeap, 0, section->name );
148 for (key = section->key; key; key = next_key)
150 next_key = key->next;
151 if (key->name) HeapFree( SystemHeap, 0, key->name );
152 if (key->value) HeapFree( SystemHeap, 0, key->value );
153 HeapFree( SystemHeap, 0, key );
155 next_section = section->next;
156 HeapFree( SystemHeap, 0, section );
160 static int
161 PROFILE_isspace(char c) {
162 if (isspace(c)) return 1;
163 if (c=='\r' || c==0x1a) return 1;
164 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
165 return 0;
169 /***********************************************************************
170 * PROFILE_Load
172 * Load a profile tree from a file.
174 static PROFILESECTION *PROFILE_Load( FILE *file )
176 char buffer[PROFILE_MAX_LINE_LEN];
177 char *p, *p2;
178 int line = 0;
179 PROFILESECTION *section, *first_section;
180 PROFILESECTION **next_section;
181 PROFILEKEY *key, *prev_key, **next_key;
183 first_section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
184 first_section->name = NULL;
185 first_section->key = NULL;
186 first_section->next = NULL;
187 next_section = &first_section->next;
188 next_key = &first_section->key;
189 prev_key = NULL;
191 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
193 line++;
194 p = buffer;
195 while (*p && PROFILE_isspace(*p)) p++;
196 if (*p == '[') /* section start */
198 if (!(p2 = strrchr( p, ']' )))
200 WARN(profile, "Invalid section header at line %d: '%s'\n",
201 line, p );
203 else
205 *p2 = '\0';
206 p++;
207 section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
208 section->name = HEAP_strdupA( SystemHeap, 0, p );
209 section->key = NULL;
210 section->next = NULL;
211 *next_section = section;
212 next_section = &section->next;
213 next_key = &section->key;
214 prev_key = NULL;
216 TRACE(profile, "New section: '%s'\n",section->name);
218 continue;
222 p2=p+strlen(p) - 1;
223 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
225 if ((p2 = strchr( p, '=' )) != NULL)
227 char *p3 = p2 - 1;
228 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
229 *p2++ = '\0';
230 while (*p2 && PROFILE_isspace(*p2)) p2++;
233 if(*p || !prev_key || *prev_key->name)
235 key = HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
236 key->name = HEAP_strdupA( SystemHeap, 0, p );
237 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
238 key->next = NULL;
239 *next_key = key;
240 next_key = &key->next;
241 prev_key = key;
243 TRACE(profile, "New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)");
246 return first_section;
250 /***********************************************************************
251 * PROFILE_DeleteSection
253 * Delete a section from a profile tree.
255 static BOOL32 PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
257 while (*section)
259 if ((*section)->name && !strcasecmp( (*section)->name, name ))
261 PROFILESECTION *to_del = *section;
262 *section = to_del->next;
263 to_del->next = NULL;
264 PROFILE_Free( to_del );
265 return TRUE;
267 section = &(*section)->next;
269 return FALSE;
273 /***********************************************************************
274 * PROFILE_DeleteKey
276 * Delete a key from a profile tree.
278 static BOOL32 PROFILE_DeleteKey( PROFILESECTION **section,
279 LPCSTR section_name, LPCSTR key_name )
281 while (*section)
283 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
285 PROFILEKEY **key = &(*section)->key;
286 while (*key)
288 if (!strcasecmp( (*key)->name, key_name ))
290 PROFILEKEY *to_del = *key;
291 *key = to_del->next;
292 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
293 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
294 HeapFree( SystemHeap, 0, to_del );
295 return TRUE;
297 key = &(*key)->next;
300 section = &(*section)->next;
302 return FALSE;
306 /***********************************************************************
307 * PROFILE_Find
309 * Find a key in a profile tree, optionally creating it.
311 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
312 const char *section_name,
313 const char *key_name, int create )
315 while (*section)
317 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
319 PROFILEKEY **key = &(*section)->key;
320 while (*key)
322 if (!strcasecmp( (*key)->name, key_name )) return *key;
323 key = &(*key)->next;
325 if (!create) return NULL;
326 *key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
327 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
328 (*key)->value = NULL;
329 (*key)->next = NULL;
330 return *key;
332 section = &(*section)->next;
334 if (!create) return NULL;
335 *section = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
336 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
337 (*section)->next = NULL;
338 (*section)->key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
339 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
340 (*section)->key->value = NULL;
341 (*section)->key->next = NULL;
342 return (*section)->key;
346 /***********************************************************************
347 * PROFILE_FlushFile
349 * Flush the current profile to disk if changed.
351 static BOOL32 PROFILE_FlushFile(void)
353 char *p, buffer[MAX_PATHNAME_LEN];
354 const char *unix_name;
355 FILE *file = NULL;
356 struct stat buf;
358 if(!CurProfile)
360 WARN(profile, "No current profile!\n");
361 return FALSE;
364 if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
365 if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
367 /* Try to create it in $HOME/.wine */
368 /* FIXME: this will need a more general solution */
369 if ((p = getenv( "HOME" )) != NULL)
371 strcpy( buffer, p );
372 strcat( buffer, "/.wine/" );
373 p = buffer + strlen(buffer);
374 strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
375 CharLower32A( p );
376 file = fopen( buffer, "w" );
377 unix_name = buffer;
381 if (!file)
383 WARN(profile, "could not save profile file %s\n", CurProfile->dos_name);
384 return FALSE;
387 TRACE(profile, "Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name );
388 PROFILE_Save( file, CurProfile->section );
389 fclose( file );
390 CurProfile->changed = FALSE;
391 if(!stat(unix_name,&buf))
392 CurProfile->mtime=buf.st_mtime;
393 return TRUE;
397 /***********************************************************************
398 * PROFILE_Open
400 * Open a profile file, checking the cached file first.
402 static BOOL32 PROFILE_Open( LPCSTR filename )
404 DOS_FULL_NAME full_name;
405 char buffer[MAX_PATHNAME_LEN];
406 char *newdos_name, *p;
407 FILE *file = NULL;
408 int i,j;
409 struct stat buf;
410 PROFILE *tempProfile;
412 /* First time around */
414 if(!CurProfile)
415 for(i=0;i<N_CACHED_PROFILES;i++)
417 MRUProfile[i]=HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );
418 MRUProfile[i]->changed=FALSE;
419 MRUProfile[i]->section=NULL;
420 MRUProfile[i]->dos_name=NULL;
421 MRUProfile[i]->unix_name=NULL;
422 MRUProfile[i]->filename=NULL;
423 MRUProfile[i]->mtime=0;
426 /* Check for a match */
428 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
429 strchr( filename, ':' ))
431 if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
433 else
435 GetWindowsDirectory32A( buffer, sizeof(buffer) );
436 strcat( buffer, "\\" );
437 strcat( buffer, filename );
438 if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
441 for(i=0;i<N_CACHED_PROFILES;i++)
443 if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )) ||
444 (MRUProfile[i]->dos_name && !strcmp( full_name.short_name, MRUProfile[i]->dos_name )))
446 if(i)
448 PROFILE_FlushFile();
449 tempProfile=MRUProfile[i];
450 for(j=i;j>0;j--)
451 MRUProfile[j]=MRUProfile[j-1];
452 CurProfile=tempProfile;
454 if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
456 TRACE(profile, "(%s): already opened (mru=%d)\n",
457 filename, i );
458 return TRUE;
460 TRACE(profile, "(%s): already opened, needs refreshing (mru=%d)\n",
461 filename, i );
465 /* Rotate the oldest to the top to be replaced */
467 if(i==N_CACHED_PROFILES)
469 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
470 for(i=N_CACHED_PROFILES-1;i>0;i--)
471 MRUProfile[i]=MRUProfile[i-1];
472 CurProfile=tempProfile;
475 /* Flush the profile */
477 if(CurProfile->filename)
479 PROFILE_FlushFile();
480 PROFILE_Free( CurProfile->section );
481 if (CurProfile->dos_name) HeapFree( SystemHeap, 0, CurProfile->dos_name );
482 if (CurProfile->unix_name) HeapFree( SystemHeap, 0, CurProfile->unix_name );
483 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
484 CurProfile->changed=FALSE;
485 CurProfile->section=NULL;
486 CurProfile->dos_name=NULL;
487 CurProfile->unix_name=NULL;
488 CurProfile->filename=NULL;
489 CurProfile->mtime=0;
492 newdos_name = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
493 CurProfile->dos_name = newdos_name;
494 CurProfile->filename = HEAP_strdupA( SystemHeap, 0, filename );
496 /* Try to open the profile file, first in $HOME/.wine */
498 /* FIXME: this will need a more general solution */
499 if ((p = getenv( "HOME" )) != NULL)
501 strcpy( buffer, p );
502 strcat( buffer, "/.wine/" );
503 p = buffer + strlen(buffer);
504 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
505 CharLower32A( p );
506 if ((file = fopen( buffer, "r" )))
508 TRACE(profile, "(%s): found it in %s\n",
509 filename, buffer );
510 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
514 if (!file)
516 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0,
517 full_name.long_name );
518 if ((file = fopen( full_name.long_name, "r" )))
519 TRACE(profile, "(%s): found it in %s\n",
520 filename, full_name.long_name );
523 if (file)
525 CurProfile->section = PROFILE_Load( file );
526 fclose( file );
527 if(!stat(CurProfile->unix_name,&buf))
528 CurProfile->mtime=buf.st_mtime;
530 else
532 /* Does not exist yet, we will create it in PROFILE_FlushFile */
533 WARN(profile, "profile file %s not found\n", newdos_name );
535 return TRUE;
539 /***********************************************************************
540 * PROFILE_GetSection
542 * Returns all keys of a section.
543 * If return_values is TRUE, also include the corresponding values.
545 static INT32 PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
546 LPSTR buffer, UINT32 len, BOOL32 handle_env,
547 BOOL32 return_values )
549 PROFILEKEY *key;
550 while (section)
552 if (section->name && !strcasecmp( section->name, section_name ))
554 UINT32 oldlen = len;
555 for (key = section->key; key && *(key->name); key = key->next)
557 if (len <= 2) break;
558 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
559 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
560 len -= strlen(buffer) + 1;
561 buffer += strlen(buffer) + 1;
562 if (return_values && key->value) {
563 buffer[-1] = '=';
564 PROFILE_CopyEntry ( buffer,
565 key->value, len - 1, handle_env );
566 len -= strlen(buffer) + 1;
567 buffer += strlen(buffer) + 1;
570 *buffer = '\0';
571 if (len < 1)
572 /*If either lpszSection or lpszKey is NULL and the supplied
573 destination buffer is too small to hold all the strings,
574 the last string is truncated and followed by two null characters.
575 In this case, the return value is equal to cchReturnBuffer
576 minus two. */
578 buffer[-1] = '\0';
579 return oldlen - 2;
581 return oldlen - len;
583 section = section->next;
585 buffer[0] = buffer[1] = '\0';
586 return 0;
590 /***********************************************************************
591 * PROFILE_GetString
593 * Get a profile string.
595 static INT32 PROFILE_GetString( LPCSTR section, LPCSTR key_name,
596 LPCSTR def_val, LPSTR buffer, UINT32 len )
598 PROFILEKEY *key = NULL;
600 if (!def_val) def_val = "";
601 if (key_name && key_name[0])
603 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
604 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
605 len, FALSE );
606 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
607 section, key_name, def_val, buffer );
608 return strlen( buffer );
610 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
611 FALSE, FALSE);
615 /***********************************************************************
616 * PROFILE_SetString
618 * Set a profile string.
620 static BOOL32 PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
621 LPCSTR value )
623 if (!key_name) /* Delete a whole section */
625 TRACE(profile, "('%s')\n", section_name);
626 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
627 section_name );
628 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
629 this is not an error on application's level.*/
631 else if (!value) /* Delete a key */
633 TRACE(profile, "('%s','%s')\n",
634 section_name, key_name );
635 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
636 section_name, key_name );
637 return TRUE; /* same error handling as above */
639 else /* Set the key value */
641 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
642 key_name, TRUE );
643 TRACE(profile, "('%s','%s','%s'): \n",
644 section_name, key_name, value );
645 if (!key) return FALSE;
646 if (key->value)
648 if (!strcmp( key->value, value ))
650 TRACE(profile, " no change needed\n" );
651 return TRUE; /* No change needed */
653 TRACE(profile, " replacing '%s'\n", key->value );
654 HeapFree( SystemHeap, 0, key->value );
656 else TRACE(profile, " creating key\n" );
657 key->value = HEAP_strdupA( SystemHeap, 0, value );
658 CurProfile->changed = TRUE;
660 return TRUE;
664 /***********************************************************************
665 * PROFILE_GetWineIniString
667 * Get a config string from the wine.ini file.
669 int PROFILE_GetWineIniString( const char *section, const char *key_name,
670 const char *def, char *buffer, int len )
672 if (key_name)
674 PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
675 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
676 len, TRUE );
677 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
678 section, key_name, def, buffer );
679 return strlen( buffer );
681 return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE, FALSE );
685 /***********************************************************************
686 * PROFILE_GetWineIniInt
688 * Get a config integer from the wine.ini file.
690 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
692 char buffer[20];
693 char *p;
694 long result;
696 PROFILEKEY *key = PROFILE_Find( &WineProfile, section, key_name, FALSE );
697 if (!key || !key->value) return def;
698 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
699 result = strtol( buffer, &p, 0 );
700 if (p == buffer) return 0; /* No digits at all */
701 return (int)result;
705 /******************************************************************************
707 * int PROFILE_EnumerateWineIniSection(
708 * char const *section, // Name of the section to enumerate
709 * void (*cbfn)(char const *key, char const *value, void *user),
710 // Address of the callback function
711 * void *user ) // User-specified pointer.
713 * For each entry in a section in the wine.conf file, this function will
714 * call the specified callback function, informing it of each key and
715 * value. An optional user pointer may be passed to it (if this is not
716 * needed, pass NULL through it and ignore the value in the callback
717 * function).
719 * The callback function must accept three parameters:
720 * The name of the key (char const *)
721 * The value of the key (char const *)
722 * A user-specified parameter (void *)
723 * Note that the first two are char CONST *'s, not char *'s! The callback
724 * MUST not modify these strings!
726 * The return value indicates the number of times the callback function
727 * was called.
729 int PROFILE_EnumerateWineIniSection(
730 char const *section,
731 void (*cbfn)(char const *, char const *, void *),
732 void *userptr )
734 PROFILESECTION *scansect;
735 PROFILEKEY *scankey;
736 int calls = 0;
738 /* Search for the correct section */
739 for(scansect = WineProfile; scansect; scansect = scansect->next) {
740 if(scansect->name && !strcasecmp(scansect->name, section)) {
742 /* Enumerate each key with the callback */
743 for(scankey = scansect->key; scankey; scankey = scankey->next) {
745 /* Ignore blank entries -- these shouldn't exist, but let's
746 be extra careful */
747 if(scankey->name[0]) {
748 cbfn(scankey->name, scankey->value, userptr);
749 ++calls;
753 break;
757 return calls;
761 /******************************************************************************
763 * int PROFILE_GetWineIniBool(
764 * char const *section,
765 * char const *key_name,
766 * int def )
768 * Reads a boolean value from the wine.ini file. This function attempts to
769 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
770 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
771 * true. Anything else results in the return of the default value.
773 * This function uses 1 to indicate true, and 0 for false. You can check
774 * for existence by setting def to something other than 0 or 1 and
775 * examining the return value.
777 int PROFILE_GetWineIniBool(
778 char const *section,
779 char const *key_name,
780 int def )
782 char key_value[2];
783 int retval;
785 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
787 switch(key_value[0]) {
788 case 'n':
789 case 'N':
790 case 'f':
791 case 'F':
792 case '0':
793 retval = 0;
794 break;
796 case 'y':
797 case 'Y':
798 case 't':
799 case 'T':
800 case '1':
801 retval = 1;
802 break;
804 default:
805 retval = def;
808 TRACE(profile, "(\"%s\", \"%s\", %s), "
809 "[%c], ret %s.\n", section, key_name,
810 def ? "TRUE" : "FALSE", key_value[0],
811 retval ? "TRUE" : "FALSE");
813 return retval;
817 /***********************************************************************
818 * PROFILE_LoadWineIni
820 * Load the wine.ini file.
822 int PROFILE_LoadWineIni(void)
824 char buffer[MAX_PATHNAME_LEN];
825 const char *p;
826 FILE *f;
828 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
830 WineProfile = PROFILE_Load( f );
831 fclose( f );
832 return 1;
834 if ((p = getenv( "HOME" )) != NULL)
836 lstrcpyn32A(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
837 strcat( buffer, PROFILE_WineIniName );
838 if ((f = fopen( buffer, "r" )) != NULL)
840 WineProfile = PROFILE_Load( f );
841 fclose( f );
842 return 1;
845 else WARN(profile, "could not get $HOME value for config file.\n" );
847 /* Try global file */
849 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
851 WineProfile = PROFILE_Load( f );
852 fclose( f );
853 return 1;
855 MSG( "Can't open configuration file %s or $HOME%s\n",
856 WINE_INI_GLOBAL, PROFILE_WineIniName );
857 return 0;
861 /***********************************************************************
862 * PROFILE_GetStringItem
864 * Convenience function that turns a string 'xxx, yyy, zzz' into
865 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
867 char* PROFILE_GetStringItem( char* start )
869 char* lpchX, *lpch;
871 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
873 if( *lpchX == ',' )
875 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
876 while( *(++lpchX) )
877 if( !PROFILE_isspace(*lpchX) ) return lpchX;
879 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
880 else lpch = NULL;
882 if( lpch ) *lpch = '\0';
883 return NULL;
887 /********************* API functions **********************************/
889 /***********************************************************************
890 * GetProfileInt16 (KERNEL.57)
892 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
894 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
898 /***********************************************************************
899 * GetProfileInt32A (KERNEL32.264)
901 UINT32 WINAPI GetProfileInt32A( LPCSTR section, LPCSTR entry, INT32 def_val )
903 return GetPrivateProfileInt32A( section, entry, def_val, "win.ini" );
906 /***********************************************************************
907 * GetProfileInt32W (KERNEL32.264)
909 UINT32 WINAPI GetProfileInt32W( LPCWSTR section, LPCWSTR entry, INT32 def_val )
911 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
912 return GetPrivateProfileInt32W( section, entry, def_val, wininiW );
915 /***********************************************************************
916 * GetProfileString16 (KERNEL.58)
918 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
919 LPSTR buffer, UINT16 len )
921 return GetPrivateProfileString16( section, entry, def_val,
922 buffer, len, "win.ini" );
925 /***********************************************************************
926 * GetProfileString32A (KERNEL32.268)
928 INT32 WINAPI GetProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR def_val,
929 LPSTR buffer, UINT32 len )
931 return GetPrivateProfileString32A( section, entry, def_val,
932 buffer, len, "win.ini" );
935 /***********************************************************************
936 * GetProfileString32W (KERNEL32.269)
938 INT32 WINAPI GetProfileString32W( LPCWSTR section, LPCWSTR entry,
939 LPCWSTR def_val, LPWSTR buffer, UINT32 len )
941 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
942 return GetPrivateProfileString32W( section, entry, def_val,
943 buffer, len, wininiW );
946 /***********************************************************************
947 * GetProfileSection32A (KERNEL32.268)
949 INT32 WINAPI GetProfileSection32A( LPCSTR section, LPSTR buffer, UINT32 len )
951 return GetPrivateProfileSection32A( section, buffer, len, "win.ini" );
955 /***********************************************************************
956 * WriteProfileString16 (KERNEL.59)
958 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
959 LPCSTR string )
961 return WritePrivateProfileString16( section, entry, string, "win.ini" );
964 /***********************************************************************
965 * WriteProfileString32A (KERNEL32.587)
967 BOOL32 WINAPI WriteProfileString32A( LPCSTR section, LPCSTR entry,
968 LPCSTR string )
970 return WritePrivateProfileString32A( section, entry, string, "win.ini" );
973 /***********************************************************************
974 * WriteProfileString32W (KERNEL32.588)
976 BOOL32 WINAPI WriteProfileString32W( LPCWSTR section, LPCWSTR entry,
977 LPCWSTR string )
979 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
980 return WritePrivateProfileString32W( section, entry, string, wininiW );
984 /***********************************************************************
985 * GetPrivateProfileInt16 (KERNEL.127)
987 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
988 INT16 def_val, LPCSTR filename )
990 long result=(long)GetPrivateProfileInt32A(section,entry,def_val,filename);
992 if (result > 65535) return 65535;
993 if (result >= 0) return (UINT16)result;
994 if (result < -32768) return -32768;
995 return (UINT16)(INT16)result;
998 /***********************************************************************
999 * GetPrivateProfileInt32A (KERNEL32.251)
1001 UINT32 WINAPI GetPrivateProfileInt32A( LPCSTR section, LPCSTR entry,
1002 INT32 def_val, LPCSTR filename )
1004 char buffer[20];
1005 char *p;
1006 long result;
1008 GetPrivateProfileString32A( section, entry, "",
1009 buffer, sizeof(buffer), filename );
1010 if (!buffer[0]) return (UINT32)def_val;
1011 result = strtol( buffer, &p, 0 );
1012 if (p == buffer) return 0; /* No digits at all */
1013 return (UINT32)result;
1016 /***********************************************************************
1017 * GetPrivateProfileInt32W (KERNEL32.252)
1019 UINT32 WINAPI GetPrivateProfileInt32W( LPCWSTR section, LPCWSTR entry,
1020 INT32 def_val, LPCWSTR filename )
1022 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1023 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1024 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1025 UINT32 res = GetPrivateProfileInt32A(sectionA, entryA, def_val, filenameA);
1026 HeapFree( GetProcessHeap(), 0, sectionA );
1027 HeapFree( GetProcessHeap(), 0, filenameA );
1028 HeapFree( GetProcessHeap(), 0, entryA );
1029 return res;
1032 /***********************************************************************
1033 * GetPrivateProfileString16 (KERNEL.128)
1035 INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
1036 LPCSTR def_val, LPSTR buffer,
1037 UINT16 len, LPCSTR filename )
1039 return GetPrivateProfileString32A(section,entry,def_val,buffer,len,filename);
1042 /***********************************************************************
1043 * GetPrivateProfileString32A (KERNEL32.255)
1045 INT32 WINAPI GetPrivateProfileString32A( LPCSTR section, LPCSTR entry,
1046 LPCSTR def_val, LPSTR buffer,
1047 UINT32 len, LPCSTR filename )
1049 if (!filename)
1050 filename = "win.ini";
1051 if (PROFILE_Open( filename ))
1052 return PROFILE_GetString( section, entry, def_val, buffer, len );
1053 lstrcpyn32A( buffer, def_val, len );
1054 return strlen( buffer );
1057 /***********************************************************************
1058 * GetPrivateProfileString32W (KERNEL32.256)
1060 INT32 WINAPI GetPrivateProfileString32W( LPCWSTR section, LPCWSTR entry,
1061 LPCWSTR def_val, LPWSTR buffer,
1062 UINT32 len, LPCWSTR filename )
1064 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1065 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1066 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1067 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1068 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1069 INT32 ret = GetPrivateProfileString32A( sectionA, entryA, def_valA,
1070 bufferA, len, filenameA );
1071 lstrcpynAtoW( buffer, bufferA, len );
1072 HeapFree( GetProcessHeap(), 0, sectionA );
1073 HeapFree( GetProcessHeap(), 0, entryA );
1074 HeapFree( GetProcessHeap(), 0, filenameA );
1075 HeapFree( GetProcessHeap(), 0, def_valA );
1076 HeapFree( GetProcessHeap(), 0, bufferA);
1077 return ret;
1080 /***********************************************************************
1081 * GetPrivateProfileSection32A (KERNEL32.255)
1083 INT32 WINAPI GetPrivateProfileSection32A( LPCSTR section, LPSTR buffer,
1084 UINT32 len, LPCSTR filename )
1086 if (PROFILE_Open( filename ))
1087 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
1088 FALSE, TRUE);
1090 return 0;
1093 /***********************************************************************
1094 * WritePrivateProfileString16 (KERNEL.129)
1096 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
1097 LPCSTR string, LPCSTR filename )
1099 return WritePrivateProfileString32A(section,entry,string,filename);
1102 /***********************************************************************
1103 * WritePrivateProfileString32A (KERNEL32.582)
1105 BOOL32 WINAPI WritePrivateProfileString32A( LPCSTR section, LPCSTR entry,
1106 LPCSTR string, LPCSTR filename )
1108 if (!PROFILE_Open( filename )) return FALSE;
1109 if (!section) return PROFILE_FlushFile();
1110 return PROFILE_SetString( section, entry, string );
1113 /***********************************************************************
1114 * WritePrivateProfileString32W (KERNEL32.583)
1116 BOOL32 WINAPI WritePrivateProfileString32W( LPCWSTR section, LPCWSTR entry,
1117 LPCWSTR string, LPCWSTR filename )
1119 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1120 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1121 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1122 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1123 BOOL32 res = WritePrivateProfileString32A( sectionA, entryA,
1124 stringA, filenameA );
1125 HeapFree( GetProcessHeap(), 0, sectionA );
1126 HeapFree( GetProcessHeap(), 0, entryA );
1127 HeapFree( GetProcessHeap(), 0, stringA );
1128 HeapFree( GetProcessHeap(), 0, filenameA );
1129 return res;
1132 /***********************************************************************
1133 * WritePrivateProfileSection32A (KERNEL32)
1135 BOOL32 WINAPI WritePrivateProfileSection32A( LPCSTR section,
1136 LPCSTR string, LPCSTR filename )
1138 char *p =(char*)string;
1140 FIXME(profile, "WritePrivateProfileSection32A empty stup\n");
1141 if (TRACE_ON(profile)) {
1142 TRACE(profile, "(%s) => [%s]\n", filename, section);
1143 while (*(p+1)) {
1144 TRACE(profile, "%s\n", p);
1145 p += strlen(p);
1146 p += 1;
1150 return FALSE;
1153 /***********************************************************************
1154 * GetPrivateProfileSectionNames16 (KERNEL.143)
1156 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1157 LPCSTR filename )
1159 char *buf;
1160 int l,cursize;
1161 PROFILESECTION *section;
1163 if (PROFILE_Open( filename )) {
1164 buf=buffer;
1165 cursize=0;
1166 section=CurProfile->section;
1167 for ( ; section; section = section->next)
1168 if (section->name) {
1169 l=strlen (section->name);
1170 cursize+=l+1;
1171 if (cursize > size+1)
1172 return size-2;
1173 strcpy (buf,section->name);
1174 buf+=l;
1175 *buf=0;
1176 buf++;
1178 buf++;
1179 *buf=0;
1180 return (buf-buffer);
1182 return FALSE;
1187 /***********************************************************************
1188 * GetPrivateProfileStruct32A (KERNEL32.370)
1190 WORD WINAPI GetPrivateProfileStruct32A (LPCSTR section, LPCSTR key,
1191 LPVOID buf, UINT32 len, LPCSTR filename)
1193 PROFILEKEY *k;
1195 if (PROFILE_Open( filename )) {
1196 k=PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1197 if (!k) return FALSE;
1198 lstrcpyn32A( buf, k->value, strlen(k->value));
1199 return TRUE;
1201 return FALSE;
1205 /***********************************************************************
1206 * WritePrivateProfileStruct32A (KERNEL32.744)
1208 WORD WINAPI WritePrivateProfileStruct32A (LPCSTR section, LPCSTR key,
1209 LPVOID buf, UINT32 bufsize, LPCSTR filename)
1211 if ((!section) && (!key) && (!buf)) { /* flush the cache */
1212 PROFILE_FlushFile();
1213 return FALSE;
1216 if (!PROFILE_Open( filename )) return FALSE;
1217 return PROFILE_SetString( section, key, buf);
1221 /***********************************************************************
1222 * WriteOutProfiles (KERNEL.315)
1224 void WINAPI WriteOutProfiles(void)
1226 PROFILE_FlushFile();