4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
19 typedef struct tagPROFILEKEY
23 struct tagPROFILEKEY
*next
;
26 typedef struct tagPROFILESECTION
29 struct tagPROFILEKEY
*key
;
30 struct tagPROFILESECTION
*next
;
37 PROFILESECTION
*section
;
42 /* Cached profile file */
43 static PROFILE CurProfile
= { FALSE
, NULL
, NULL
};
45 /* wine.ini profile content */
46 static PROFILESECTION
*WineProfile
;
48 #define PROFILE_MAX_LINE_LEN 1024
50 /* Wine profile name in $HOME directory; must begin with slash */
51 static const char PROFILE_WineIniName
[] = "/.winerc";
53 /* Check for comments in profile */
54 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
56 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
58 /***********************************************************************
61 * Copy the content of an entry into a buffer, removing quotes, and possibly
62 * translating environment variables.
64 static void PROFILE_CopyEntry( char *buffer
, const char *value
, int len
,
70 if ((*value
== '\'') || (*value
== '\"'))
72 if (value
[1] && (value
[strlen(value
)-1] == *value
)) quote
= *value
++;
77 lstrcpyn32A( buffer
, value
, len
);
78 if (quote
&& (len
>= strlen(value
))) buffer
[strlen(buffer
)-1] = '\0';
82 for (p
= value
; (*p
&& (len
> 1)); *buffer
++ = *p
++, len
-- )
84 if ((*p
== '$') && (p
[1] == '{'))
88 const char *p2
= strchr( p
, '}' );
89 if (!p2
) continue; /* ignore it */
90 lstrcpyn32A(env_val
, p
+ 2, MIN( sizeof(env_val
), (int)(p2
-p
)-1 ));
91 if ((env_p
= getenv( env_val
)) != NULL
)
93 lstrcpyn32A( buffer
, env_p
, len
);
94 buffer
+= strlen( buffer
);
95 len
-= strlen( buffer
);
104 /***********************************************************************
107 * Save a profile tree to a file.
109 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
113 for ( ; section
; section
= section
->next
)
115 if (section
->name
) fprintf( file
, "[%s]\r\n", section
->name
);
116 for (key
= section
->key
; key
; key
= key
->next
)
118 fprintf( file
, "%s", key
->name
);
119 if (key
->value
) fprintf( file
, "=%s", key
->value
);
120 fprintf( file
, "\r\n" );
126 /***********************************************************************
129 * Free a profile tree.
131 static void PROFILE_Free( PROFILESECTION
*section
)
133 PROFILESECTION
*next_section
;
134 PROFILEKEY
*key
, *next_key
;
136 for ( ; section
; section
= next_section
)
138 if (section
->name
) free( section
->name
);
139 for (key
= section
->key
; key
; key
= next_key
)
141 next_key
= key
->next
;
142 if (key
->name
) free( key
->name
);
143 if (key
->value
) free( key
->value
);
146 next_section
= section
->next
;
152 /***********************************************************************
155 * Load a profile tree from a file.
157 static PROFILESECTION
*PROFILE_Load( FILE *file
)
159 char buffer
[PROFILE_MAX_LINE_LEN
];
162 PROFILESECTION
*section
, *first_section
;
163 PROFILESECTION
**prev_section
;
164 PROFILEKEY
*key
, **prev_key
;
166 first_section
= (PROFILESECTION
*)xmalloc( sizeof(*section
) );
167 first_section
->name
= NULL
;
168 first_section
->key
= NULL
;
169 first_section
->next
= NULL
;
170 prev_section
= &first_section
->next
;
171 prev_key
= &first_section
->key
;
173 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
176 p
= buffer
+ strlen(buffer
) - 1;
177 while ((p
> buffer
) && ((*p
== '\n') || isspace(*p
))) *p
-- = '\0';
179 while (*p
&& isspace(*p
)) p
++;
180 if (*p
== '[') /* section start */
182 if (!(p2
= strrchr( p
, ']' )))
184 fprintf( stderr
, "PROFILE_Load: Invalid section header at line %d: '%s'\n",
191 section
= (PROFILESECTION
*)xmalloc( sizeof(*section
));
192 section
->name
= xstrdup( p
);
194 section
->next
= NULL
;
195 *prev_section
= section
;
196 prev_section
= §ion
->next
;
197 prev_key
= §ion
->key
;
201 if ((p2
= strchr( p
, '=' )) != NULL
)
204 while ((p3
> p
) && isspace(*p3
)) *p3
-- = '\0';
206 while (*p2
&& isspace(*p2
)) p2
++;
208 key
= (PROFILEKEY
*)xmalloc( sizeof(*key
) );
209 key
->name
= xstrdup( p
);
210 key
->value
= p2
? xstrdup( p2
) : NULL
;
213 prev_key
= &key
->next
;
215 if (debugging_profile
)
217 fprintf( stddeb
, "PROFILE_Load:\n" );
218 PROFILE_Save( stddeb
, first_section
);
219 fprintf( stddeb
, "PROFILE_Load finished.\n" );
221 return first_section
;
225 /***********************************************************************
226 * PROFILE_DeleteSection
228 * Delete a section from a profile tree.
230 static BOOL
PROFILE_DeleteSection( PROFILESECTION
**section
, const char *name
)
234 if ((*section
)->name
&& !lstrcmpi32A( (*section
)->name
, name
))
236 PROFILESECTION
*to_del
= *section
;
237 *section
= to_del
->next
;
239 PROFILE_Free( to_del
);
242 section
= &(*section
)->next
;
248 /***********************************************************************
251 * Delete a key from a profile tree.
253 static BOOL
PROFILE_DeleteKey( PROFILESECTION
**section
,
254 const char *section_name
, const char *key_name
)
258 if ((*section
)->name
&& !lstrcmpi32A( (*section
)->name
, section_name
))
260 PROFILEKEY
**key
= &(*section
)->key
;
263 if (!lstrcmpi32A( (*key
)->name
, key_name
))
265 PROFILEKEY
*to_del
= *key
;
267 if (to_del
->name
) free( to_del
->name
);
268 if (to_del
->value
) free( to_del
->value
);
275 section
= &(*section
)->next
;
281 /***********************************************************************
284 * Find a key in a profile tree, optionally creating it.
286 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
287 const char *section_name
,
288 const char *key_name
, int create
)
292 if ((*section
)->name
&& !lstrcmpi32A( (*section
)->name
, section_name
))
294 PROFILEKEY
**key
= &(*section
)->key
;
297 if (!lstrcmpi32A( (*key
)->name
, key_name
)) return *key
;
300 if (!create
) return NULL
;
301 *key
= (PROFILEKEY
*)xmalloc( sizeof(PROFILEKEY
) );
302 (*key
)->name
= xstrdup( key_name
);
303 (*key
)->value
= NULL
;
307 section
= &(*section
)->next
;
309 if (!create
) return NULL
;
310 *section
= (PROFILESECTION
*)xmalloc( sizeof(PROFILESECTION
) );
311 (*section
)->name
= xstrdup(section_name
);
312 (*section
)->next
= NULL
;
313 (*section
)->key
= (PROFILEKEY
*)xmalloc( sizeof(PROFILEKEY
) );
314 (*section
)->key
->name
= xstrdup( key_name
);
315 (*section
)->key
->value
= NULL
;
316 (*section
)->key
->next
= NULL
;
317 return (*section
)->key
;
321 /***********************************************************************
324 * Flush the current profile to disk if changed.
326 static BOOL
PROFILE_FlushFile(void)
328 char *p
, buffer
[MAX_PATHNAME_LEN
];
329 const char *unix_name
;
332 if (!CurProfile
.changed
|| !CurProfile
.dos_name
) return TRUE
;
333 if (!(unix_name
= DOSFS_GetUnixFileName( CurProfile
.dos_name
, FALSE
)) ||
334 !(file
= fopen( unix_name
, "w" )))
336 /* Try to create it in $HOME/.wine */
337 /* FIXME: this will need a more general solution */
338 if ((p
= getenv( "HOME" )) != NULL
)
341 strcat( buffer
, "/.wine/" );
342 p
= buffer
+ strlen(buffer
);
343 strcpy( p
, strrchr( CurProfile
.dos_name
, '\\' ) + 1 );
345 file
= fopen( buffer
, "w" );
352 fprintf( stderr
, "Warning: could not save profile file %s\n",
353 CurProfile
.dos_name
);
357 dprintf_profile( stddeb
, "Saving '%s' into '%s'\n",
358 CurProfile
.dos_name
, unix_name
);
359 PROFILE_Save( file
, CurProfile
.section
);
361 CurProfile
.changed
= FALSE
;
366 /***********************************************************************
369 * Open a profile file, checking the cached file first.
371 static BOOL
PROFILE_Open( const char *filename
)
373 char buffer
[MAX_PATHNAME_LEN
];
374 const char *dos_name
, *unix_name
;
375 char *newdos_name
, *p
;
378 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
379 strchr( filename
, ':' ))
381 if (!(dos_name
= DOSFS_GetDosTrueName( filename
, FALSE
))) return FALSE
;
385 GetWindowsDirectory32A( buffer
, sizeof(buffer
) );
386 strcat( buffer
, "\\" );
387 strcat( buffer
, filename
);
388 if (!(dos_name
= DOSFS_GetDosTrueName( buffer
, FALSE
))) return FALSE
;
390 if (CurProfile
.dos_name
&& !strcmp( dos_name
, CurProfile
.dos_name
))
392 dprintf_profile( stddeb
, "PROFILE_Open(%s): already opened\n",
397 /* Flush the previous profile */
399 newdos_name
= xstrdup( dos_name
);
401 PROFILE_Free( CurProfile
.section
);
402 if (CurProfile
.dos_name
) free( CurProfile
.dos_name
);
403 CurProfile
.section
= NULL
;
404 CurProfile
.dos_name
= newdos_name
;
406 /* Try to open the profile file, first in $HOME/.wine */
408 /* FIXME: this will need a more general solution */
409 if ((p
= getenv( "HOME" )) != NULL
)
412 strcat( buffer
, "/.wine/" );
413 p
= buffer
+ strlen(buffer
);
414 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
416 if ((file
= fopen( buffer
, "r" )))
417 dprintf_profile( stddeb
, "Found it in %s\n", buffer
);
420 if (!file
&& ((unix_name
= DOSFS_GetUnixFileName( dos_name
, TRUE
))))
422 if ((file
= fopen( unix_name
, "r" )))
423 dprintf_profile( stddeb
, "Found it in %s\n", unix_name
);
428 CurProfile
.section
= PROFILE_Load( file
);
433 /* Does not exist yet, we will create it in PROFILE_FlushFile */
434 fprintf( stderr
, "Warning: profile file %s not found\n", newdos_name
);
436 dprintf_profile( stddeb
, "PROFILE_Open(%s): successful\n", filename
);
441 /***********************************************************************
444 * Enumerate all the keys of a section.
446 static INT
PROFILE_GetSection( PROFILESECTION
*section
,
447 const char *section_name
,
448 char *buffer
, INT len
, int handle_env
)
453 if (section
->name
&& !lstrcmpi32A( section
->name
, section_name
))
456 for (key
= section
->key
; key
; key
= key
->next
)
459 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
460 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
461 len
-= strlen(buffer
) + 1;
462 buffer
+= strlen(buffer
) + 1;
465 return oldlen
- len
+ 1;
467 section
= section
->next
;
469 buffer
[0] = buffer
[1] = '\0';
474 /***********************************************************************
477 * Get a profile string.
479 static INT
PROFILE_GetString( const char *section
, const char *key_name
,
480 const char *def_val
, char *buffer
, INT len
)
482 PROFILEKEY
*key
= NULL
;
484 if (!def_val
) def_val
= "";
487 key
= PROFILE_Find( &CurProfile
.section
, section
, key_name
, FALSE
);
488 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
490 dprintf_profile( stddeb
, "PROFILE_GetString('%s','%s','%s'): returning '%s'\n",
491 section
, key_name
, def_val
, buffer
);
492 return strlen( buffer
);
494 return PROFILE_GetSection(CurProfile
.section
, section
, buffer
, len
, FALSE
);
498 /***********************************************************************
501 * Set a profile string.
503 static BOOL
PROFILE_SetString( const char *section_name
, const char *key_name
,
508 if (!key_name
) /* Delete a whole section */
510 dprintf_profile(stddeb
, "PROFILE_DeleteSection('%s')\n", section_name
);
511 ret
= PROFILE_DeleteSection( &CurProfile
.section
, section_name
);
512 CurProfile
.changed
|= ret
;
515 else if (!value
) /* Delete a key */
517 dprintf_profile( stddeb
, "PROFILE_DeleteKey('%s','%s')\n",
518 section_name
, key_name
);
519 ret
= PROFILE_DeleteKey( &CurProfile
.section
, section_name
, key_name
);
520 CurProfile
.changed
|= ret
;
523 else /* Set the key value */
525 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
.section
, section_name
,
527 dprintf_profile( stddeb
, "PROFILE_SetString('%s','%s','%s'): ",
528 section_name
, key_name
, value
);
531 if (!strcmp( key
->value
, value
))
533 dprintf_profile( stddeb
, "no change needed\n" );
534 return TRUE
; /* No change needed */
536 dprintf_profile( stddeb
, "replacing '%s'\n", key
->value
);
539 else dprintf_profile( stddeb
, "creating key\n" );
540 key
->value
= xstrdup( value
);
541 CurProfile
.changed
= TRUE
;
547 /***********************************************************************
548 * PROFILE_GetWineIniString
550 * Get a config string from the wine.ini file.
552 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
553 const char *def
, char *buffer
, int len
)
557 PROFILEKEY
*key
= PROFILE_Find(&WineProfile
, section
, key_name
, FALSE
);
558 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
560 dprintf_profile( stddeb
, "PROFILE_GetWineIniString('%s','%s','%s'): returning '%s'\n",
561 section
, key_name
, def
, buffer
);
562 return strlen( buffer
);
564 return PROFILE_GetSection( WineProfile
, section
, buffer
, len
, TRUE
);
568 /***********************************************************************
569 * PROFILE_GetWineIniInt
571 * Get a config integer from the wine.ini file.
573 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
579 PROFILEKEY
*key
= PROFILE_Find( &WineProfile
, section
, key_name
, FALSE
);
580 if (!key
|| !key
->value
) return def
;
581 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
582 result
= strtol( buffer
, &p
, 0 );
583 if (p
== buffer
) return 0; /* No digits at all */
588 /***********************************************************************
589 * PROFILE_LoadWineIni
591 * Load the wine.ini file.
593 int PROFILE_LoadWineIni(void)
595 char buffer
[MAX_PATHNAME_LEN
];
599 if ((p
= getenv( "HOME" )) != NULL
)
601 lstrcpyn32A(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
602 strcat( buffer
, PROFILE_WineIniName
);
603 if ((f
= fopen( buffer
, "r" )) != NULL
)
605 WineProfile
= PROFILE_Load( f
);
610 else fprintf( stderr
, "Warning: could not get $HOME value for config file.\n" );
612 /* Try global file */
614 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
616 WineProfile
= PROFILE_Load( f
);
620 fprintf( stderr
, "Can't open configuration file %s or $HOME%s\n",
621 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
626 /***********************************************************************
627 * GetProfileInt (KERNEL.57)
629 UINT
GetProfileInt( LPCSTR section
, LPCSTR entry
, INT def_val
)
631 return GetPrivateProfileInt( section
, entry
, def_val
, "win.ini" );
635 /***********************************************************************
636 * GetProfileString (KERNEL.58)
638 INT
GetProfileString( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
639 LPSTR buffer
, INT len
)
641 return GetPrivateProfileString( section
, entry
, def_val
,
642 buffer
, len
, "win.ini" );
646 /***********************************************************************
647 * WriteProfileString (KERNEL.59)
649 BOOL
WriteProfileString( LPCSTR section
, LPCSTR entry
, LPCSTR string
)
651 return WritePrivateProfileString( section
, entry
, string
, "win.ini" );
655 /***********************************************************************
656 * GetPrivateProfileInt (KERNEL.127)
658 UINT
GetPrivateProfileInt( LPCSTR section
, LPCSTR entry
, INT def_val
,
665 GetPrivateProfileString( section
, entry
, "",
666 buffer
, sizeof(buffer
), filename
);
667 if (!buffer
[0]) return (UINT
)def_val
;
668 result
= strtol( buffer
, &p
, 0 );
669 if (p
== buffer
) return 0; /* No digits at all */
673 if (result
> 65535) return 65535;
674 if (result
>= 0) return (UINT
)result
;
675 if (result
< -32768) return -32768;
676 return (UINT
)(INT
)result
;
681 /***********************************************************************
682 * GetPrivateProfileString (KERNEL.128)
684 INT
GetPrivateProfileString( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
685 LPSTR buffer
, INT len
, LPCSTR filename
)
687 if (PROFILE_Open( filename
))
688 return PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
689 lstrcpyn32A( buffer
, def_val
, len
);
690 return strlen( buffer
);
694 /***********************************************************************
695 * WritePrivateProfileString (KERNEL.129)
697 BOOL
WritePrivateProfileString( LPCSTR section
, LPCSTR entry
, LPCSTR string
,
700 if (!PROFILE_Open( filename
)) return FALSE
;
701 if (!section
) return PROFILE_FlushFile();
702 return PROFILE_SetString( section
, entry
, string
);
706 /***********************************************************************
707 * WriteOutProfiles (KERNEL.315)
709 void WriteOutProfiles(void)