Some interrupt enhancements.
[wine/hacks.git] / files / profile.c
blob8f4943e9381f7b3b45b12b27b94ee271811f8d2b
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 = key->next)
560 if (len <= 2) break;
561 if (!*key->name) continue; /* Skip empty lines */
562 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
563 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
564 len -= strlen(buffer) + 1;
565 buffer += strlen(buffer) + 1;
566 if (return_values && key->value) {
567 buffer[-1] = '=';
568 PROFILE_CopyEntry ( buffer,
569 key->value, len - 1, handle_env );
570 len -= strlen(buffer) + 1;
571 buffer += strlen(buffer) + 1;
574 *buffer = '\0';
575 if (len < 1)
576 /*If either lpszSection or lpszKey is NULL and the supplied
577 destination buffer is too small to hold all the strings,
578 the last string is truncated and followed by two null characters.
579 In this case, the return value is equal to cchReturnBuffer
580 minus two. */
582 buffer[-1] = '\0';
583 return oldlen - 2;
585 return oldlen - len;
587 section = section->next;
589 buffer[0] = buffer[1] = '\0';
590 return 0;
594 /***********************************************************************
595 * PROFILE_GetString
597 * Get a profile string.
599 static INT32 PROFILE_GetString( LPCSTR section, LPCSTR key_name,
600 LPCSTR def_val, LPSTR buffer, UINT32 len )
602 PROFILEKEY *key = NULL;
604 if (!def_val) def_val = "";
605 if (key_name && key_name[0])
607 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
608 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
609 len, FALSE );
610 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
611 section, key_name, def_val, buffer );
612 return strlen( buffer );
614 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
615 FALSE, FALSE);
619 /***********************************************************************
620 * PROFILE_SetString
622 * Set a profile string.
624 static BOOL32 PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
625 LPCSTR value )
627 if (!key_name) /* Delete a whole section */
629 TRACE(profile, "('%s')\n", section_name);
630 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
631 section_name );
632 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
633 this is not an error on application's level.*/
635 else if (!value) /* Delete a key */
637 TRACE(profile, "('%s','%s')\n",
638 section_name, key_name );
639 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
640 section_name, key_name );
641 return TRUE; /* same error handling as above */
643 else /* Set the key value */
645 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
646 key_name, TRUE );
647 TRACE(profile, "('%s','%s','%s'): \n",
648 section_name, key_name, value );
649 if (!key) return FALSE;
650 if (key->value)
652 if (!strcmp( key->value, value ))
654 TRACE(profile, " no change needed\n" );
655 return TRUE; /* No change needed */
657 TRACE(profile, " replacing '%s'\n", key->value );
658 HeapFree( SystemHeap, 0, key->value );
660 else TRACE(profile, " creating key\n" );
661 key->value = HEAP_strdupA( SystemHeap, 0, value );
662 CurProfile->changed = TRUE;
664 return TRUE;
668 /***********************************************************************
669 * PROFILE_GetWineIniString
671 * Get a config string from the wine.ini file.
673 int PROFILE_GetWineIniString( const char *section, const char *key_name,
674 const char *def, char *buffer, int len )
676 if (key_name)
678 PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
679 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
680 len, TRUE );
681 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
682 section, key_name, def, buffer );
683 return strlen( buffer );
685 return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE, FALSE );
689 /***********************************************************************
690 * PROFILE_GetWineIniInt
692 * Get a config integer from the wine.ini file.
694 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
696 char buffer[20];
697 char *p;
698 long result;
700 PROFILEKEY *key = PROFILE_Find( &WineProfile, section, key_name, FALSE );
701 if (!key || !key->value) return def;
702 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
703 result = strtol( buffer, &p, 0 );
704 if (p == buffer) return 0; /* No digits at all */
705 return (int)result;
709 /******************************************************************************
711 * int PROFILE_EnumerateWineIniSection(
712 * char const *section, #Name of the section to enumerate
713 * void (*cbfn)(char const *key, char const *value, void *user),
714 * # Address of the callback function
715 * void *user ) # User-specified pointer.
717 * For each entry in a section in the wine.conf file, this function will
718 * call the specified callback function, informing it of each key and
719 * value. An optional user pointer may be passed to it (if this is not
720 * needed, pass NULL through it and ignore the value in the callback
721 * function).
723 * The callback function must accept three parameters:
724 * The name of the key (char const *)
725 * The value of the key (char const *)
726 * A user-specified parameter (void *)
727 * Note that the first two are char CONST *'s, not char *'s! The callback
728 * MUST not modify these strings!
730 * The return value indicates the number of times the callback function
731 * was called.
733 int PROFILE_EnumerateWineIniSection(
734 char const *section,
735 void (*cbfn)(char const *, char const *, void *),
736 void *userptr )
738 PROFILESECTION *scansect;
739 PROFILEKEY *scankey;
740 int calls = 0;
742 /* Search for the correct section */
743 for(scansect = WineProfile; scansect; scansect = scansect->next) {
744 if(scansect->name && !strcasecmp(scansect->name, section)) {
746 /* Enumerate each key with the callback */
747 for(scankey = scansect->key; scankey; scankey = scankey->next) {
749 /* Ignore blank entries -- these shouldn't exist, but let's
750 be extra careful */
751 if(scankey->name[0]) {
752 cbfn(scankey->name, scankey->value, userptr);
753 ++calls;
757 break;
761 return calls;
765 /******************************************************************************
767 * int PROFILE_GetWineIniBool(
768 * char const *section,
769 * char const *key_name,
770 * int def )
772 * Reads a boolean value from the wine.ini file. This function attempts to
773 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
774 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
775 * true. Anything else results in the return of the default value.
777 * This function uses 1 to indicate true, and 0 for false. You can check
778 * for existence by setting def to something other than 0 or 1 and
779 * examining the return value.
781 int PROFILE_GetWineIniBool(
782 char const *section,
783 char const *key_name,
784 int def )
786 char key_value[2];
787 int retval;
789 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
791 switch(key_value[0]) {
792 case 'n':
793 case 'N':
794 case 'f':
795 case 'F':
796 case '0':
797 retval = 0;
798 break;
800 case 'y':
801 case 'Y':
802 case 't':
803 case 'T':
804 case '1':
805 retval = 1;
806 break;
808 default:
809 retval = def;
812 TRACE(profile, "(\"%s\", \"%s\", %s), "
813 "[%c], ret %s.\n", section, key_name,
814 def ? "TRUE" : "FALSE", key_value[0],
815 retval ? "TRUE" : "FALSE");
817 return retval;
821 /***********************************************************************
822 * PROFILE_LoadWineIni
824 * Load the wine.ini file.
826 int PROFILE_LoadWineIni(void)
828 char buffer[MAX_PATHNAME_LEN];
829 const char *p;
830 FILE *f;
832 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
834 /* Open -config specified file */
835 WineProfile = PROFILE_Load ( f);
836 fclose ( f );
837 strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);
838 return 1;
841 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
843 WineProfile = PROFILE_Load( f );
844 fclose( f );
845 strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);
846 return 1;
848 if ((p = getenv( "HOME" )) != NULL)
850 lstrcpyn32A(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
851 strcat( buffer, PROFILE_WineIniName );
852 if ((f = fopen( buffer, "r" )) != NULL)
854 WineProfile = PROFILE_Load( f );
855 fclose( f );
856 strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);
857 return 1;
860 else WARN(profile, "could not get $HOME value for config file.\n" );
862 /* Try global file */
864 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
866 WineProfile = PROFILE_Load( f );
867 fclose( f );
868 strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);
869 return 1;
871 MSG( "Can't open configuration file %s or $HOME%s\n",
872 WINE_INI_GLOBAL, PROFILE_WineIniName );
873 return 0;
877 /***********************************************************************
878 * PROFILE_UsageWineIni
880 * Explain the wine.ini file to those who don't read documentation.
881 * Keep below one screenful in length so that error messages above are
882 * noticed.
884 void PROFILE_UsageWineIni(void)
886 MSG("Perhaps you have not properly edited or created "
887 "your Wine configuration file.\n");
888 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
889 MSG(" or it is determined by the -config option or from\n"
890 " the WINE_INI environment variable.\n");
891 if (*PROFILE_WineIniUsed)
892 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
893 /* RTFM, so to say */
897 /***********************************************************************
898 * PROFILE_GetStringItem
900 * Convenience function that turns a string 'xxx, yyy, zzz' into
901 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
903 char* PROFILE_GetStringItem( char* start )
905 char* lpchX, *lpch;
907 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
909 if( *lpchX == ',' )
911 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
912 while( *(++lpchX) )
913 if( !PROFILE_isspace(*lpchX) ) return lpchX;
915 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
916 else lpch = NULL;
918 if( lpch ) *lpch = '\0';
919 return NULL;
923 /********************* API functions **********************************/
925 /***********************************************************************
926 * GetProfileInt16 (KERNEL.57)
928 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
930 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
934 /***********************************************************************
935 * GetProfileInt32A (KERNEL32.264)
937 UINT32 WINAPI GetProfileInt32A( LPCSTR section, LPCSTR entry, INT32 def_val )
939 return GetPrivateProfileInt32A( section, entry, def_val, "win.ini" );
942 /***********************************************************************
943 * GetProfileInt32W (KERNEL32.264)
945 UINT32 WINAPI GetProfileInt32W( LPCWSTR section, LPCWSTR entry, INT32 def_val )
947 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
948 return GetPrivateProfileInt32W( section, entry, def_val, wininiW );
951 /***********************************************************************
952 * GetProfileString16 (KERNEL.58)
954 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
955 LPSTR buffer, UINT16 len )
957 return GetPrivateProfileString16( section, entry, def_val,
958 buffer, len, "win.ini" );
961 /***********************************************************************
962 * GetProfileString32A (KERNEL32.268)
964 INT32 WINAPI GetProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR def_val,
965 LPSTR buffer, UINT32 len )
967 return GetPrivateProfileString32A( section, entry, def_val,
968 buffer, len, "win.ini" );
971 /***********************************************************************
972 * GetProfileString32W (KERNEL32.269)
974 INT32 WINAPI GetProfileString32W( LPCWSTR section, LPCWSTR entry,
975 LPCWSTR def_val, LPWSTR buffer, UINT32 len )
977 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
978 return GetPrivateProfileString32W( section, entry, def_val,
979 buffer, len, wininiW );
982 /***********************************************************************
983 * GetProfileSection32A (KERNEL32.268)
985 INT32 WINAPI GetProfileSection32A( LPCSTR section, LPSTR buffer, DWORD len )
987 return GetPrivateProfileSection32A( section, buffer, len, "win.ini" );
991 /***********************************************************************
992 * GetProfileSection32W (KERNEL32)
994 INT32 WINAPI GetProfileSection32W( LPCWSTR section, LPWSTR buffer, DWORD len )
996 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
997 return GetPrivateProfileSection32W( section, buffer, len, wininiW );
1004 /***********************************************************************
1005 * WriteProfileString16 (KERNEL.59)
1007 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
1008 LPCSTR string )
1010 return WritePrivateProfileString16( section, entry, string, "win.ini" );
1013 /***********************************************************************
1014 * WriteProfileString32A (KERNEL32.587)
1016 BOOL32 WINAPI WriteProfileString32A( LPCSTR section, LPCSTR entry,
1017 LPCSTR string )
1019 return WritePrivateProfileString32A( section, entry, string, "win.ini" );
1022 /***********************************************************************
1023 * WriteProfileString32W (KERNEL32.588)
1025 BOOL32 WINAPI WriteProfileString32W( LPCWSTR section, LPCWSTR entry,
1026 LPCWSTR string )
1028 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1029 return WritePrivateProfileString32W( section, entry, string, wininiW );
1033 /***********************************************************************
1034 * GetPrivateProfileInt16 (KERNEL.127)
1036 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
1037 INT16 def_val, LPCSTR filename )
1039 long result=(long)GetPrivateProfileInt32A(section,entry,def_val,filename);
1041 if (result > 65535) return 65535;
1042 if (result >= 0) return (UINT16)result;
1043 if (result < -32768) return -32768;
1044 return (UINT16)(INT16)result;
1047 /***********************************************************************
1048 * GetPrivateProfileInt32A (KERNEL32.251)
1050 UINT32 WINAPI GetPrivateProfileInt32A( LPCSTR section, LPCSTR entry,
1051 INT32 def_val, LPCSTR filename )
1053 char buffer[20];
1054 char *p;
1055 long result;
1057 GetPrivateProfileString32A( section, entry, "",
1058 buffer, sizeof(buffer), filename );
1059 if (!buffer[0]) return (UINT32)def_val;
1060 result = strtol( buffer, &p, 0 );
1061 if (p == buffer) return 0; /* No digits at all */
1062 return (UINT32)result;
1065 /***********************************************************************
1066 * GetPrivateProfileInt32W (KERNEL32.252)
1068 UINT32 WINAPI GetPrivateProfileInt32W( LPCWSTR section, LPCWSTR entry,
1069 INT32 def_val, LPCWSTR filename )
1071 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1072 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1073 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1074 UINT32 res = GetPrivateProfileInt32A(sectionA, entryA, def_val, filenameA);
1075 HeapFree( GetProcessHeap(), 0, sectionA );
1076 HeapFree( GetProcessHeap(), 0, filenameA );
1077 HeapFree( GetProcessHeap(), 0, entryA );
1078 return res;
1081 /***********************************************************************
1082 * GetPrivateProfileString16 (KERNEL.128)
1084 INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
1085 LPCSTR def_val, LPSTR buffer,
1086 UINT16 len, LPCSTR filename )
1088 return GetPrivateProfileString32A(section,entry,def_val,buffer,len,filename);
1091 /***********************************************************************
1092 * GetPrivateProfileString32A (KERNEL32.255)
1094 INT32 WINAPI GetPrivateProfileString32A( LPCSTR section, LPCSTR entry,
1095 LPCSTR def_val, LPSTR buffer,
1096 UINT32 len, LPCSTR filename )
1098 if (!filename)
1099 filename = "win.ini";
1100 if (PROFILE_Open( filename ))
1101 return PROFILE_GetString( section, entry, def_val, buffer, len );
1102 lstrcpyn32A( buffer, def_val, len );
1103 return strlen( buffer );
1106 /***********************************************************************
1107 * GetPrivateProfileString32W (KERNEL32.256)
1109 INT32 WINAPI GetPrivateProfileString32W( LPCWSTR section, LPCWSTR entry,
1110 LPCWSTR def_val, LPWSTR buffer,
1111 UINT32 len, LPCWSTR filename )
1113 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1114 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1115 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1116 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1117 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1118 INT32 ret = GetPrivateProfileString32A( sectionA, entryA, def_valA,
1119 bufferA, len, filenameA );
1120 lstrcpynAtoW( buffer, bufferA, len );
1121 HeapFree( GetProcessHeap(), 0, sectionA );
1122 HeapFree( GetProcessHeap(), 0, entryA );
1123 HeapFree( GetProcessHeap(), 0, filenameA );
1124 HeapFree( GetProcessHeap(), 0, def_valA );
1125 HeapFree( GetProcessHeap(), 0, bufferA);
1126 return ret;
1129 /***********************************************************************
1130 * GetPrivateProfileSection32A (KERNEL32.255)
1132 INT32 WINAPI GetPrivateProfileSection32A( LPCSTR section, LPSTR buffer,
1133 DWORD len, LPCSTR filename )
1135 if (PROFILE_Open( filename ))
1136 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
1137 FALSE, TRUE);
1139 return 0;
1142 /***********************************************************************
1143 * GetPrivateProfileSection32W (KERNEL32.256)
1146 INT32 WINAPI GetPrivateProfileSection32W (LPCWSTR section, LPWSTR buffer,
1147 DWORD len, LPCWSTR filename )
1150 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1151 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1152 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1153 INT32 ret = GetPrivateProfileSection32A( sectionA, bufferA, len,
1154 filenameA );
1155 HeapFree( GetProcessHeap(), 0, sectionA );
1156 HeapFree( GetProcessHeap(), 0, filenameA );
1157 HeapFree( GetProcessHeap(), 0, bufferA);
1158 return ret;
1161 /***********************************************************************
1162 * WritePrivateProfileString16 (KERNEL.129)
1164 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
1165 LPCSTR string, LPCSTR filename )
1167 return WritePrivateProfileString32A(section,entry,string,filename);
1170 /***********************************************************************
1171 * WritePrivateProfileString32A (KERNEL32.582)
1173 BOOL32 WINAPI WritePrivateProfileString32A( LPCSTR section, LPCSTR entry,
1174 LPCSTR string, LPCSTR filename )
1176 if (!PROFILE_Open( filename )) return FALSE;
1177 if (!section) return PROFILE_FlushFile();
1178 return PROFILE_SetString( section, entry, string );
1181 /***********************************************************************
1182 * WritePrivateProfileString32W (KERNEL32.583)
1184 BOOL32 WINAPI WritePrivateProfileString32W( LPCWSTR section, LPCWSTR entry,
1185 LPCWSTR string, LPCWSTR filename )
1187 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1188 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1189 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1190 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1191 BOOL32 res = WritePrivateProfileString32A( sectionA, entryA,
1192 stringA, filenameA );
1193 HeapFree( GetProcessHeap(), 0, sectionA );
1194 HeapFree( GetProcessHeap(), 0, entryA );
1195 HeapFree( GetProcessHeap(), 0, stringA );
1196 HeapFree( GetProcessHeap(), 0, filenameA );
1197 return res;
1200 /***********************************************************************
1201 * WritePrivateProfileSection32A (KERNEL32)
1203 BOOL32 WINAPI WritePrivateProfileSection32A( LPCSTR section,
1204 LPCSTR string, LPCSTR filename )
1206 char *p =(char*)string;
1208 FIXME(profile, "WritePrivateProfileSection32A empty stub\n");
1209 if (TRACE_ON(profile)) {
1210 TRACE(profile, "(%s) => [%s]\n", filename, section);
1211 while (*(p+1)) {
1212 TRACE(profile, "%s\n", p);
1213 p += strlen(p);
1214 p += 1;
1218 return FALSE;
1221 /***********************************************************************
1222 * WritePrivateProfileSection32W (KERNEL32)
1224 BOOL32 WINAPI WritePrivateProfileSection32W( LPCWSTR section,
1225 LPCWSTR string, LPCWSTR filename)
1228 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1229 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1230 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1231 BOOL32 res = WritePrivateProfileSection32A( sectionA, stringA, filenameA );
1232 HeapFree( GetProcessHeap(), 0, sectionA );
1233 HeapFree( GetProcessHeap(), 0, stringA );
1234 HeapFree( GetProcessHeap(), 0, filenameA );
1235 return res;
1239 /***********************************************************************
1240 * WriteProfileSection32A (KERNEL32.747)
1242 BOOL32 WINAPI WriteProfileSection32A( LPCSTR section, LPCSTR keys_n_values)
1245 return WritePrivateProfileSection32A( section, keys_n_values, "win.ini");
1248 /***********************************************************************
1249 * WriteProfileSection32W (KERNEL32.748)
1251 BOOL32 WINAPI WriteProfileSection32W( LPCWSTR section, LPCWSTR keys_n_values)
1253 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini");
1255 return (WritePrivateProfileSection32W (section,keys_n_values, wininiW));
1258 /***********************************************************************
1259 * GetPrivateProfileSectionNames16 (KERNEL.143)
1261 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1262 LPCSTR filename )
1264 char *buf;
1265 int l,cursize;
1266 PROFILESECTION *section;
1268 if (PROFILE_Open( filename )) {
1269 buf=buffer;
1270 cursize=0;
1271 section=CurProfile->section;
1272 for ( ; section; section = section->next)
1273 if (section->name) {
1274 l=strlen (section->name);
1275 cursize+=l+1;
1276 if (cursize > size+1)
1277 return size-2;
1278 strcpy (buf,section->name);
1279 buf+=l;
1280 *buf=0;
1281 buf++;
1283 buf++;
1284 *buf=0;
1285 return (buf-buffer);
1287 return FALSE;
1291 /***********************************************************************
1292 * GetProfileSectionNames16 (KERNEL.142)
1294 WORD WINAPI GetProfileSectionNames16( LPSTR buffer, WORD size)
1297 return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
1301 /***********************************************************************
1302 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1304 DWORD WINAPI GetPrivateProfileSectionNames32A( LPSTR buffer, DWORD size,
1305 LPCSTR filename)
1308 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1312 /***********************************************************************
1313 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1315 DWORD WINAPI GetPrivateProfileSectionNames32W( LPWSTR buffer, DWORD size,
1316 LPCWSTR filename)
1319 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1320 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, size);
1322 INT32 ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1323 lstrcpynAtoW( buffer, bufferA, size);
1324 HeapFree( GetProcessHeap(), 0, bufferA);
1325 HeapFree( GetProcessHeap(), 0, filenameA );
1327 return ret;
1331 /***********************************************************************
1332 * GetPrivateProfileStruct32A (KERNEL32.370)
1334 BOOL32 WINAPI GetPrivateProfileStruct32A (LPCSTR section, LPCSTR key,
1335 LPVOID buf, UINT32 len, LPCSTR filename)
1337 PROFILEKEY *k;
1339 if (PROFILE_Open( filename )) {
1340 k=PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1341 if (!k) return FALSE;
1342 lstrcpyn32A( buf, k->value, strlen(k->value));
1343 return TRUE;
1345 return FALSE;
1348 /***********************************************************************
1349 * GetPrivateProfileStruct32W (KERNEL32.543)
1351 BOOL32 WINAPI GetPrivateProfileStruct32W (LPCWSTR section, LPCWSTR key,
1352 LPVOID buffer, UINT32 len, LPCWSTR filename)
1354 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1355 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1356 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1357 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1359 INT32 ret = GetPrivateProfileStruct32A( sectionA, keyA, bufferA,
1360 len, filenameA );
1361 lstrcpynAtoW( buffer, bufferA, len );
1362 HeapFree( GetProcessHeap(), 0, bufferA);
1363 HeapFree( GetProcessHeap(), 0, sectionA );
1364 HeapFree( GetProcessHeap(), 0, keyA );
1365 HeapFree( GetProcessHeap(), 0, filenameA );
1367 return ret;
1373 /***********************************************************************
1374 * WritePrivateProfileStruct32A (KERNEL32.744)
1376 BOOL32 WINAPI WritePrivateProfileStruct32A (LPCSTR section, LPCSTR key,
1377 LPVOID buf, UINT32 bufsize, LPCSTR filename)
1379 if ((!section) && (!key) && (!buf)) { /* flush the cache */
1380 PROFILE_FlushFile();
1381 return FALSE;
1384 if (!PROFILE_Open( filename )) return FALSE;
1385 return PROFILE_SetString( section, key, buf);
1388 /***********************************************************************
1389 * WritePrivateProfileStruct32W (KERNEL32.544)
1391 BOOL32 WINAPI WritePrivateProfileStruct32W (LPCWSTR section, LPCWSTR key,
1392 LPVOID buf, UINT32 bufsize, LPCWSTR filename)
1394 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1395 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1396 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1397 INT32 ret = WritePrivateProfileStruct32A( sectionA, keyA, buf, bufsize,
1398 filenameA );
1399 HeapFree( GetProcessHeap(), 0, sectionA );
1400 HeapFree( GetProcessHeap(), 0, keyA );
1401 HeapFree( GetProcessHeap(), 0, filenameA );
1403 return ret;
1407 /***********************************************************************
1408 * WriteOutProfiles (KERNEL.315)
1410 void WINAPI WriteOutProfiles(void)
1412 PROFILE_FlushFile();