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] == ';')
57 /***********************************************************************
60 * Copy the content of an entry into a buffer, removing quotes, and possibly
61 * translating environment variables.
63 static void PROFILE_CopyEntry( char *buffer
, const char *value
, int len
,
69 if ((*value
== '\'') || (*value
== '\"'))
71 if (value
[1] && (value
[strlen(value
)-1] == *value
)) quote
= *value
++;
76 lstrcpyn( buffer
, value
, len
);
77 if (quote
&& (len
>= strlen(value
))) buffer
[strlen(buffer
)-1] = '\0';
81 for (p
= value
; (*p
&& (len
> 1)); *buffer
++ = *p
++, len
-- )
83 if ((*p
== '$') && (p
[1] == '{'))
87 const char *p2
= strchr( p
, '}' );
88 if (!p2
) continue; /* ignore it */
89 lstrcpyn( env_val
, p
+ 2, MIN( sizeof(env_val
), (int)(p2
-p
)-1 ) );
90 if ((env_p
= getenv( env_val
)) != NULL
)
92 lstrcpyn( buffer
, env_p
, len
);
93 buffer
+= strlen( buffer
);
94 len
-= strlen( buffer
);
103 /***********************************************************************
106 * Save a profile tree to a file.
108 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
112 for ( ; section
; section
= section
->next
)
114 if (section
->name
) fprintf( file
, "[%s]\r\n", section
->name
);
115 for (key
= section
->key
; key
; key
= key
->next
)
117 fprintf( file
, "%s", key
->name
);
118 if (key
->value
) fprintf( file
, "=%s", key
->value
);
119 fprintf( file
, "\r\n" );
125 /***********************************************************************
128 * Free a profile tree.
130 static void PROFILE_Free( PROFILESECTION
*section
)
132 PROFILESECTION
*next_section
;
133 PROFILEKEY
*key
, *next_key
;
135 for ( ; section
; section
= next_section
)
137 if (section
->name
) free( section
->name
);
138 for (key
= section
->key
; key
; key
= next_key
)
140 next_key
= key
->next
;
141 if (key
->name
) free( key
->name
);
142 if (key
->value
) free( key
->value
);
145 next_section
= section
->next
;
151 /***********************************************************************
154 * Load a profile tree from a file.
156 static PROFILESECTION
*PROFILE_Load( FILE *file
)
158 char buffer
[PROFILE_MAX_LINE_LEN
];
161 PROFILESECTION
*section
, *first_section
;
162 PROFILESECTION
**prev_section
;
163 PROFILEKEY
*key
, **prev_key
;
165 first_section
= (PROFILESECTION
*)xmalloc( sizeof(*section
) );
166 first_section
->name
= NULL
;
167 first_section
->key
= NULL
;
168 first_section
->next
= NULL
;
169 prev_section
= &first_section
->next
;
170 prev_key
= &first_section
->key
;
172 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
175 p
= buffer
+ strlen(buffer
) - 1;
176 while ((p
> buffer
) && ((*p
== '\n') || isspace(*p
))) *p
-- = '\0';
178 while (*p
&& isspace(*p
)) p
++;
179 if (*p
== '[') /* section start */
181 if (!(p2
= strrchr( p
, ']' )))
183 fprintf( stderr
, "PROFILE_Load: Invalid section header at line %d: '%s'\n",
190 section
= (PROFILESECTION
*)xmalloc( sizeof(*section
));
191 section
->name
= xstrdup( p
);
193 section
->next
= NULL
;
194 *prev_section
= section
;
195 prev_section
= §ion
->next
;
196 prev_key
= §ion
->key
;
200 if ((p2
= strchr( p
, '=' )) != NULL
)
203 while ((p3
> p
) && isspace(*p3
)) *p3
-- = '\0';
205 while (*p2
&& isspace(*p2
)) p2
++;
207 key
= (PROFILEKEY
*)xmalloc( sizeof(*key
) );
208 key
->name
= xstrdup( p
);
209 key
->value
= p2
? xstrdup( p2
) : NULL
;
212 prev_key
= &key
->next
;
214 if (debugging_profile
)
216 fprintf( stddeb
, "PROFILE_Load:\n" );
217 PROFILE_Save( stddeb
, first_section
);
218 fprintf( stddeb
, "PROFILE_Load finished.\n" );
220 return first_section
;
224 /***********************************************************************
225 * PROFILE_DeleteSection
227 * Delete a section from a profile tree.
229 static BOOL
PROFILE_DeleteSection( PROFILESECTION
**section
, const char *name
)
233 if ((*section
)->name
&& !lstrcmpi( (*section
)->name
, name
))
235 PROFILESECTION
*to_del
= *section
;
236 *section
= to_del
->next
;
238 PROFILE_Free( to_del
);
241 section
= &(*section
)->next
;
247 /***********************************************************************
250 * Delete a key from a profile tree.
252 static BOOL
PROFILE_DeleteKey( PROFILESECTION
**section
,
253 const char *section_name
, const char *key_name
)
257 if ((*section
)->name
&& !lstrcmpi( (*section
)->name
, section_name
))
259 PROFILEKEY
**key
= &(*section
)->key
;
262 if (!lstrcmpi( (*key
)->name
, key_name
))
264 PROFILEKEY
*to_del
= *key
;
266 if (to_del
->name
) free( to_del
->name
);
267 if (to_del
->value
) free( to_del
->value
);
274 section
= &(*section
)->next
;
280 /***********************************************************************
283 * Find a key in a profile tree, optionally creating it.
285 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
286 const char *section_name
,
287 const char *key_name
, int create
)
291 if ((*section
)->name
&& !lstrcmpi( (*section
)->name
, section_name
))
293 PROFILEKEY
**key
= &(*section
)->key
;
296 if (!lstrcmpi( (*key
)->name
, key_name
)) return *key
;
299 if (!create
) return NULL
;
300 *key
= (PROFILEKEY
*)xmalloc( sizeof(PROFILEKEY
) );
301 (*key
)->name
= xstrdup( key_name
);
302 (*key
)->value
= NULL
;
306 section
= &(*section
)->next
;
308 if (!create
) return NULL
;
309 *section
= (PROFILESECTION
*)xmalloc( sizeof(PROFILESECTION
) );
310 (*section
)->name
= xstrdup(section_name
);
311 (*section
)->next
= NULL
;
312 (*section
)->key
= (PROFILEKEY
*)xmalloc( sizeof(PROFILEKEY
) );
313 (*section
)->key
->name
= xstrdup( key_name
);
314 (*section
)->key
->value
= NULL
;
315 (*section
)->key
->next
= NULL
;
316 return (*section
)->key
;
320 /***********************************************************************
323 * Flush the current profile to disk if changed.
325 static BOOL
PROFILE_FlushFile(void)
327 char *p
, buffer
[MAX_PATHNAME_LEN
];
328 const char *unix_name
;
331 if (!CurProfile
.changed
|| !CurProfile
.dos_name
) return TRUE
;
332 if (!(unix_name
= DOSFS_GetUnixFileName( CurProfile
.dos_name
, FALSE
)) ||
333 !(file
= fopen( unix_name
, "w" )))
335 /* Try to create it in $HOME/.wine */
336 /* FIXME: this will need a more general solution */
337 if ((p
= getenv( "HOME" )) != NULL
)
340 strcat( buffer
, "/.wine/" );
341 p
= buffer
+ strlen(buffer
);
342 strcpy( p
, strrchr( CurProfile
.dos_name
, '\\' ) + 1 );
344 file
= fopen( buffer
, "w" );
351 fprintf( stderr
, "Warning: could not save profile file %s\n",
352 CurProfile
.dos_name
);
356 dprintf_profile( stddeb
, "Saving '%s' into '%s'\n",
357 CurProfile
.dos_name
, unix_name
);
358 PROFILE_Save( file
, CurProfile
.section
);
360 CurProfile
.changed
= FALSE
;
365 /***********************************************************************
368 * Open a profile file, checking the cached file first.
370 static BOOL
PROFILE_Open( const char *filename
)
372 char buffer
[MAX_PATHNAME_LEN
];
373 const char *dos_name
, *unix_name
;
374 char *newdos_name
, *p
;
377 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
378 strchr( filename
, ':' ))
380 if (!(dos_name
= DOSFS_GetDosTrueName( filename
, FALSE
))) return FALSE
;
384 GetWindowsDirectory( buffer
, sizeof(buffer
) );
385 strcat( buffer
, "\\" );
386 strcat( buffer
, filename
);
387 if (!(dos_name
= DOSFS_GetDosTrueName( buffer
, FALSE
))) return FALSE
;
389 if (CurProfile
.dos_name
&& !strcmp( dos_name
, CurProfile
.dos_name
))
391 dprintf_profile( stddeb
, "PROFILE_Open(%s): already opened\n",
396 /* Flush the previous profile */
398 newdos_name
= xstrdup( dos_name
);
400 PROFILE_Free( CurProfile
.section
);
401 if (CurProfile
.dos_name
) free( CurProfile
.dos_name
);
402 CurProfile
.section
= NULL
;
403 CurProfile
.dos_name
= newdos_name
;
405 /* Try to open the profile file, first in $HOME/.wine */
407 /* FIXME: this will need a more general solution */
408 if ((p
= getenv( "HOME" )) != NULL
)
411 strcat( buffer
, "/.wine/" );
412 p
= buffer
+ strlen(buffer
);
413 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
415 if ((file
= fopen( buffer
, "r" )))
416 dprintf_profile( stddeb
, "Found it in %s\n", buffer
);
419 if (!file
&& ((unix_name
= DOSFS_GetUnixFileName( dos_name
, TRUE
))))
421 if ((file
= fopen( unix_name
, "r" )))
422 dprintf_profile( stddeb
, "Found it in %s\n", unix_name
);
427 CurProfile
.section
= PROFILE_Load( file
);
431 fprintf( stderr
, "Warning: profile file %s not found\n", newdos_name
);
432 dprintf_profile( stddeb
, "PROFILE_Open(%s): successful\n", filename
);
437 /***********************************************************************
440 * Enumerate all the keys of a section.
442 static INT
PROFILE_GetSection( PROFILESECTION
*section
,
443 const char *section_name
,
444 char *buffer
, INT len
, int handle_env
)
449 if (section
->name
&& !lstrcmpi( section
->name
, section_name
))
452 for (key
= section
->key
; key
; key
= key
->next
)
455 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
456 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
457 len
-= strlen(buffer
) + 1;
458 buffer
+= strlen(buffer
) + 1;
461 return oldlen
- len
+ 1;
463 section
= section
->next
;
465 buffer
[0] = buffer
[1] = '\0';
470 /***********************************************************************
473 * Get a profile string.
475 static INT
PROFILE_GetString( const char *section
, const char *key_name
,
476 const char *def_val
, char *buffer
, INT len
)
478 PROFILEKEY
*key
= NULL
;
480 if (!def_val
) def_val
= "";
483 key
= PROFILE_Find( &CurProfile
.section
, section
, key_name
, FALSE
);
484 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
486 dprintf_profile( stddeb
, "PROFILE_GetString('%s','%s','%s'): returning '%s'\n",
487 section
, key_name
, def_val
, buffer
);
488 return strlen( buffer
);
490 return PROFILE_GetSection(CurProfile
.section
, section
, buffer
, len
, FALSE
);
494 /***********************************************************************
497 * Set a profile string.
499 static BOOL
PROFILE_SetString( const char *section_name
, const char *key_name
,
504 if (!key_name
) /* Delete a whole section */
506 dprintf_profile(stddeb
, "PROFILE_DeleteSection('%s')\n", section_name
);
507 ret
= PROFILE_DeleteSection( &CurProfile
.section
, section_name
);
508 CurProfile
.changed
|= ret
;
511 else if (!value
) /* Delete a key */
513 dprintf_profile( stddeb
, "PROFILE_DeleteKey('%s','%s')\n",
514 section_name
, key_name
);
515 ret
= PROFILE_DeleteKey( &CurProfile
.section
, section_name
, key_name
);
516 CurProfile
.changed
|= ret
;
519 else /* Set the key value */
521 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
.section
, section_name
,
523 dprintf_profile( stddeb
, "PROFILE_SetString('%s','%s','%s'): ",
524 section_name
, key_name
, value
);
527 if (!strcmp( key
->value
, value
))
529 dprintf_profile( stddeb
, "no change needed\n" );
530 return TRUE
; /* No change needed */
532 dprintf_profile( stddeb
, "replacing '%s'\n", key
->value
);
535 else dprintf_profile( stddeb
, "creating key\n" );
536 key
->value
= xstrdup( value
);
537 CurProfile
.changed
= TRUE
;
543 /***********************************************************************
544 * PROFILE_GetWineIniString
546 * Get a config string from the wine.ini file.
548 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
549 const char *def
, char *buffer
, int len
)
553 PROFILEKEY
*key
= PROFILE_Find(&WineProfile
, section
, key_name
, FALSE
);
554 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
556 dprintf_profile( stddeb
, "PROFILE_GetWineIniString('%s','%s','%s'): returning '%s'\n",
557 section
, key_name
, def
, buffer
);
558 return strlen( buffer
);
560 return PROFILE_GetSection( WineProfile
, section
, buffer
, len
, TRUE
);
564 /***********************************************************************
565 * PROFILE_LoadWineIni
567 * Load the wine.ini file.
569 int PROFILE_LoadWineIni(void)
571 char buffer
[MAX_PATHNAME_LEN
];
575 if ((p
= getenv( "HOME" )) != NULL
)
577 lstrcpyn( buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
) );
578 strcat( buffer
, PROFILE_WineIniName
);
579 if ((f
= fopen( buffer
, "r" )) != NULL
)
581 WineProfile
= PROFILE_Load( f
);
586 else fprintf( stderr
, "Warning: could not get $HOME value for config file.\n" );
588 /* Try global file */
590 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
592 WineProfile
= PROFILE_Load( f
);
596 fprintf( stderr
, "Can't open configuration file %s or $HOME%s\n",
597 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
602 /***********************************************************************
603 * GetProfileInt (KERNEL.57)
605 UINT
GetProfileInt( LPCSTR section
, LPCSTR entry
, INT def_val
)
607 return GetPrivateProfileInt( section
, entry
, def_val
, "win.ini" );
611 /***********************************************************************
612 * GetProfileString (KERNEL.58)
614 INT
GetProfileString( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
615 LPSTR buffer
, INT len
)
617 return GetPrivateProfileString( section
, entry
, def_val
,
618 buffer
, len
, "win.ini" );
622 /***********************************************************************
623 * WriteProfileString (KERNEL.59)
625 BOOL
WriteProfileString( LPCSTR section
, LPCSTR entry
, LPCSTR string
)
627 return WritePrivateProfileString( section
, entry
, string
, "win.ini" );
631 /***********************************************************************
632 * GetPrivateProfileInt (KERNEL.127)
634 UINT
GetPrivateProfileInt( LPCSTR section
, LPCSTR entry
, INT def_val
,
641 GetPrivateProfileString( section
, entry
, "",
642 buffer
, sizeof(buffer
), filename
);
643 if (!buffer
[0]) return (UINT
)def_val
;
644 result
= strtol( buffer
, &p
, 0 );
645 if (p
== buffer
) return 0; /* No digits at all */
649 if (result
> 65535) return 65535;
650 if (result
>= 0) return (UINT
)result
;
651 if (result
< -32768) return -32768;
652 return (UINT
)(INT
)result
;
657 /***********************************************************************
658 * GetPrivateProfileString (KERNEL.128)
660 INT
GetPrivateProfileString( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
661 LPSTR buffer
, INT len
, LPCSTR filename
)
663 if (PROFILE_Open( filename
))
664 return PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
665 lstrcpyn( buffer
, def_val
, len
);
666 return strlen( buffer
);
670 /***********************************************************************
671 * WritePrivateProfileString (KERNEL.129)
673 BOOL
WritePrivateProfileString( LPCSTR section
, LPCSTR entry
, LPCSTR string
,
676 if (!PROFILE_Open( filename
)) return FALSE
;
677 if (!section
) return PROFILE_FlushFile();
678 return PROFILE_SetString( section
, entry
, string
);
682 /***********************************************************************
683 * WriteOutProfiles (KERNEL.315)
685 void WriteOutProfiles(void)