4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
15 #include "wine/winbase16.h"
23 DEFAULT_DEBUG_CHANNEL(profile
)
25 typedef struct tagPROFILEKEY
29 struct tagPROFILEKEY
*next
;
32 typedef struct tagPROFILESECTION
35 struct tagPROFILEKEY
*key
;
36 struct tagPROFILESECTION
*next
;
43 PROFILESECTION
*section
;
51 #define N_CACHED_PROFILES 10
53 /* Cached profile files */
54 static PROFILE
*MRUProfile
[N_CACHED_PROFILES
]={NULL
};
56 #define CurProfile (MRUProfile[0])
58 /* wine.ini profile content */
59 static PROFILESECTION
*PROFILE_WineProfile
;
61 #define PROFILE_MAX_LINE_LEN 1024
63 /* Wine profile name in $HOME directory; must begin with slash */
64 static const char PROFILE_WineIniName
[] = "/.winerc";
66 /* Wine profile: the profile file being used */
67 static char PROFILE_WineIniUsed
[MAX_PATHNAME_LEN
] = "";
69 /* Check for comments in profile */
70 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
72 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
74 static LPCWSTR wininiW
= NULL
;
76 static CRITICAL_SECTION PROFILE_CritSect
;
78 /***********************************************************************
81 * Copy the content of an entry into a buffer, removing quotes, and possibly
82 * translating environment variables.
84 static void PROFILE_CopyEntry( char *buffer
, const char *value
, int len
,
90 if ((*value
== '\'') || (*value
== '\"'))
92 if (value
[1] && (value
[strlen(value
)-1] == *value
)) quote
= *value
++;
97 lstrcpynA( buffer
, value
, len
);
98 if (quote
&& (len
>= strlen(value
))) buffer
[strlen(buffer
)-1] = '\0';
102 for (p
= value
; (*p
&& (len
> 1)); *buffer
++ = *p
++, len
-- )
104 if ((*p
== '$') && (p
[1] == '{'))
108 const char *p2
= strchr( p
, '}' );
109 if (!p2
) continue; /* ignore it */
110 lstrcpynA(env_val
, p
+ 2, MIN( sizeof(env_val
), (int)(p2
-p
)-1 ));
111 if ((env_p
= getenv( env_val
)) != NULL
)
113 lstrcpynA( buffer
, env_p
, len
);
114 buffer
+= strlen( buffer
);
115 len
-= strlen( buffer
);
124 /***********************************************************************
127 * Save a profile tree to a file.
129 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
133 for ( ; section
; section
= section
->next
)
135 if (section
->name
) fprintf( file
, "\r\n[%s]\r\n", section
->name
);
136 for (key
= section
->key
; key
; key
= key
->next
)
138 fprintf( file
, "%s", key
->name
);
139 if (key
->value
) fprintf( file
, "=%s", key
->value
);
140 fprintf( file
, "\r\n" );
146 /***********************************************************************
149 * Free a profile tree.
151 static void PROFILE_Free( PROFILESECTION
*section
)
153 PROFILESECTION
*next_section
;
154 PROFILEKEY
*key
, *next_key
;
156 for ( ; section
; section
= next_section
)
158 if (section
->name
) HeapFree( SystemHeap
, 0, section
->name
);
159 for (key
= section
->key
; key
; key
= next_key
)
161 next_key
= key
->next
;
162 if (key
->name
) HeapFree( SystemHeap
, 0, key
->name
);
163 if (key
->value
) HeapFree( SystemHeap
, 0, key
->value
);
164 HeapFree( SystemHeap
, 0, key
);
166 next_section
= section
->next
;
167 HeapFree( SystemHeap
, 0, section
);
172 PROFILE_isspace(char c
) {
173 if (isspace(c
)) return 1;
174 if (c
=='\r' || c
==0x1a) return 1;
175 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
180 /***********************************************************************
183 * Load a profile tree from a file.
185 static PROFILESECTION
*PROFILE_Load( FILE *file
)
187 char buffer
[PROFILE_MAX_LINE_LEN
];
190 PROFILESECTION
*section
, *first_section
;
191 PROFILESECTION
**next_section
;
192 PROFILEKEY
*key
, *prev_key
, **next_key
;
194 first_section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
195 first_section
->name
= NULL
;
196 first_section
->key
= NULL
;
197 first_section
->next
= NULL
;
198 next_section
= &first_section
->next
;
199 next_key
= &first_section
->key
;
202 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
206 while (*p
&& PROFILE_isspace(*p
)) p
++;
207 if (*p
== '[') /* section start */
209 if (!(p2
= strrchr( p
, ']' )))
211 WARN(profile
, "Invalid section header at line %d: '%s'\n",
218 section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
219 section
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
221 section
->next
= NULL
;
222 *next_section
= section
;
223 next_section
= §ion
->next
;
224 next_key
= §ion
->key
;
227 TRACE(profile
, "New section: '%s'\n",section
->name
);
234 while ((p2
> p
) && ((*p2
== '\n') || PROFILE_isspace(*p2
))) *p2
--='\0';
236 if ((p2
= strchr( p
, '=' )) != NULL
)
239 while ((p3
> p
) && PROFILE_isspace(*p3
)) *p3
-- = '\0';
241 while (*p2
&& PROFILE_isspace(*p2
)) p2
++;
244 if(*p
|| !prev_key
|| *prev_key
->name
)
246 key
= HEAP_xalloc( SystemHeap
, 0, sizeof(*key
) );
247 key
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
248 key
->value
= p2
? HEAP_strdupA( SystemHeap
, 0, p2
) : NULL
;
251 next_key
= &key
->next
;
254 TRACE(profile
, "New key: name='%s', value='%s'\n",key
->name
,key
->value
?key
->value
:"(none)");
257 return first_section
;
261 /***********************************************************************
262 * PROFILE_DeleteSection
264 * Delete a section from a profile tree.
266 static BOOL
PROFILE_DeleteSection( PROFILESECTION
**section
, LPCSTR name
)
270 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, name
))
272 PROFILESECTION
*to_del
= *section
;
273 *section
= to_del
->next
;
275 PROFILE_Free( to_del
);
278 section
= &(*section
)->next
;
284 /***********************************************************************
287 * Delete a key from a profile tree.
289 static BOOL
PROFILE_DeleteKey( PROFILESECTION
**section
,
290 LPCSTR section_name
, LPCSTR key_name
)
294 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
296 PROFILEKEY
**key
= &(*section
)->key
;
299 if (!strcasecmp( (*key
)->name
, key_name
))
301 PROFILEKEY
*to_del
= *key
;
303 if (to_del
->name
) HeapFree( SystemHeap
, 0, to_del
->name
);
304 if (to_del
->value
) HeapFree( SystemHeap
, 0, to_del
->value
);
305 HeapFree( SystemHeap
, 0, to_del
);
311 section
= &(*section
)->next
;
317 /***********************************************************************
320 * Find a key in a profile tree, optionally creating it.
322 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
323 const char *section_name
,
324 const char *key_name
, int create
)
328 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
330 PROFILEKEY
**key
= &(*section
)->key
;
333 if (!strcasecmp( (*key
)->name
, key_name
)) return *key
;
336 if (!create
) return NULL
;
337 *key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
338 (*key
)->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
339 (*key
)->value
= NULL
;
343 section
= &(*section
)->next
;
345 if (!create
) return NULL
;
346 *section
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILESECTION
) );
347 (*section
)->name
= HEAP_strdupA( SystemHeap
, 0, section_name
);
348 (*section
)->next
= NULL
;
349 (*section
)->key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
350 (*section
)->key
->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
351 (*section
)->key
->value
= NULL
;
352 (*section
)->key
->next
= NULL
;
353 return (*section
)->key
;
357 /***********************************************************************
360 * Flush the current profile to disk if changed.
362 static BOOL
PROFILE_FlushFile(void)
364 char *p
, buffer
[MAX_PATHNAME_LEN
];
365 const char *unix_name
;
371 WARN(profile
, "No current profile!\n");
375 if (!CurProfile
->changed
|| !CurProfile
->dos_name
) return TRUE
;
376 if (!(unix_name
= CurProfile
->unix_name
) || !(file
= fopen(unix_name
, "w")))
378 /* Try to create it in $HOME/.wine */
379 /* FIXME: this will need a more general solution */
380 if ((p
= getenv( "HOME" )) != NULL
)
383 strcat( buffer
, "/.wine/" );
384 p
= buffer
+ strlen(buffer
);
385 strcpy( p
, strrchr( CurProfile
->dos_name
, '\\' ) + 1 );
387 file
= fopen( buffer
, "w" );
394 WARN(profile
, "could not save profile file %s\n", CurProfile
->dos_name
);
398 TRACE(profile
, "Saving '%s' into '%s'\n", CurProfile
->dos_name
, unix_name
);
399 PROFILE_Save( file
, CurProfile
->section
);
401 CurProfile
->changed
= FALSE
;
402 if(!stat(unix_name
,&buf
))
403 CurProfile
->mtime
=buf
.st_mtime
;
408 /***********************************************************************
411 * Open a profile file, checking the cached file first.
413 static BOOL
PROFILE_Open( LPCSTR filename
)
415 DOS_FULL_NAME full_name
;
416 char buffer
[MAX_PATHNAME_LEN
];
417 char *newdos_name
, *p
;
421 PROFILE
*tempProfile
;
423 /* First time around */
426 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
428 MRUProfile
[i
]=HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILE
) );
429 MRUProfile
[i
]->changed
=FALSE
;
430 MRUProfile
[i
]->section
=NULL
;
431 MRUProfile
[i
]->dos_name
=NULL
;
432 MRUProfile
[i
]->unix_name
=NULL
;
433 MRUProfile
[i
]->filename
=NULL
;
434 MRUProfile
[i
]->mtime
=0;
437 /* Check for a match */
439 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
440 strchr( filename
, ':' ))
442 if (!DOSFS_GetFullName( filename
, FALSE
, &full_name
)) return FALSE
;
446 GetWindowsDirectoryA( buffer
, sizeof(buffer
) );
447 strcat( buffer
, "\\" );
448 strcat( buffer
, filename
);
449 if (!DOSFS_GetFullName( buffer
, FALSE
, &full_name
)) return FALSE
;
452 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
454 if ((MRUProfile
[i
]->filename
&& !strcmp( filename
, MRUProfile
[i
]->filename
)) ||
455 (MRUProfile
[i
]->dos_name
&& !strcmp( full_name
.short_name
, MRUProfile
[i
]->dos_name
)))
460 tempProfile
=MRUProfile
[i
];
462 MRUProfile
[j
]=MRUProfile
[j
-1];
463 CurProfile
=tempProfile
;
465 if(!stat(CurProfile
->unix_name
,&buf
) && CurProfile
->mtime
==buf
.st_mtime
)
466 TRACE(profile
, "(%s): already opened (mru=%d)\n",
469 TRACE(profile
, "(%s): already opened, needs refreshing (mru=%d)\n",
475 /* Rotate the oldest to the top to be replaced */
477 if(i
==N_CACHED_PROFILES
)
479 tempProfile
=MRUProfile
[N_CACHED_PROFILES
-1];
480 for(i
=N_CACHED_PROFILES
-1;i
>0;i
--)
481 MRUProfile
[i
]=MRUProfile
[i
-1];
482 CurProfile
=tempProfile
;
485 /* Flush the profile */
487 if(CurProfile
->filename
)
490 PROFILE_Free( CurProfile
->section
);
491 if (CurProfile
->dos_name
) HeapFree( SystemHeap
, 0, CurProfile
->dos_name
);
492 if (CurProfile
->unix_name
) HeapFree( SystemHeap
, 0, CurProfile
->unix_name
);
493 if (CurProfile
->filename
) HeapFree( SystemHeap
, 0, CurProfile
->filename
);
494 CurProfile
->changed
=FALSE
;
495 CurProfile
->section
=NULL
;
496 CurProfile
->dos_name
=NULL
;
497 CurProfile
->unix_name
=NULL
;
498 CurProfile
->filename
=NULL
;
502 newdos_name
= HEAP_strdupA( SystemHeap
, 0, full_name
.short_name
);
503 CurProfile
->dos_name
= newdos_name
;
504 CurProfile
->filename
= HEAP_strdupA( SystemHeap
, 0, filename
);
506 /* Try to open the profile file, first in $HOME/.wine */
508 /* FIXME: this will need a more general solution */
509 if ((p
= getenv( "HOME" )) != NULL
)
512 strcat( buffer
, "/.wine/" );
513 p
= buffer
+ strlen(buffer
);
514 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
516 if ((file
= fopen( buffer
, "r" )))
518 TRACE(profile
, "(%s): found it in %s\n",
520 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0, buffer
);
526 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0,
527 full_name
.long_name
);
528 if ((file
= fopen( full_name
.long_name
, "r" )))
529 TRACE(profile
, "(%s): found it in %s\n",
530 filename
, full_name
.long_name
);
535 CurProfile
->section
= PROFILE_Load( file
);
537 if(!stat(CurProfile
->unix_name
,&buf
))
538 CurProfile
->mtime
=buf
.st_mtime
;
542 /* Does not exist yet, we will create it in PROFILE_FlushFile */
543 WARN(profile
, "profile file %s not found\n", newdos_name
);
549 /***********************************************************************
552 * Returns all keys of a section.
553 * If return_values is TRUE, also include the corresponding values.
555 static INT
PROFILE_GetSection( PROFILESECTION
*section
, LPCSTR section_name
,
556 LPSTR buffer
, UINT len
, BOOL handle_env
,
562 if (section
->name
&& !strcasecmp( section
->name
, section_name
))
565 for (key
= section
->key
; key
; key
= key
->next
)
568 if (!*key
->name
) continue; /* Skip empty lines */
569 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
570 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
571 len
-= strlen(buffer
) + 1;
572 buffer
+= strlen(buffer
) + 1;
573 if (return_values
&& key
->value
) {
575 PROFILE_CopyEntry ( buffer
,
576 key
->value
, len
- 1, handle_env
);
577 len
-= strlen(buffer
) + 1;
578 buffer
+= strlen(buffer
) + 1;
583 /*If either lpszSection or lpszKey is NULL and the supplied
584 destination buffer is too small to hold all the strings,
585 the last string is truncated and followed by two null characters.
586 In this case, the return value is equal to cchReturnBuffer
594 section
= section
->next
;
596 buffer
[0] = buffer
[1] = '\0';
601 static INT
PROFILE_GetSectionNames( LPSTR buffer
, UINT len
)
605 PROFILESECTION
*section
;
607 for (section
= CurProfile
->section
; section
; section
= section
->next
)
609 l
= strlen(section
->name
);
614 strcpy(buf
, section
->name
);
624 /***********************************************************************
627 * Get a profile string.
629 static INT
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
630 LPCSTR def_val
, LPSTR buffer
, UINT len
)
632 PROFILEKEY
*key
= NULL
;
634 if (!def_val
) def_val
= "";
635 if (key_name
&& key_name
[0])
637 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
638 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
640 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
641 section
, key_name
, def_val
, buffer
);
642 return strlen( buffer
);
644 if (section
&& section
[0])
645 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
647 /* undocumented; both section and key_name are NULL */
648 return PROFILE_GetSectionNames(buffer
, len
);
652 /***********************************************************************
655 * Set a profile string.
657 static BOOL
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
660 if (!key_name
) /* Delete a whole section */
662 TRACE(profile
, "('%s')\n", section_name
);
663 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
665 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
666 this is not an error on application's level.*/
668 else if (!value
) /* Delete a key */
670 TRACE(profile
, "('%s','%s')\n",
671 section_name
, key_name
);
672 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
673 section_name
, key_name
);
674 return TRUE
; /* same error handling as above */
676 else /* Set the key value */
678 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
680 TRACE(profile
, "('%s','%s','%s'): \n",
681 section_name
, key_name
, value
);
682 if (!key
) return FALSE
;
685 if (!strcmp( key
->value
, value
))
687 TRACE(profile
, " no change needed\n" );
688 return TRUE
; /* No change needed */
690 TRACE(profile
, " replacing '%s'\n", key
->value
);
691 HeapFree( SystemHeap
, 0, key
->value
);
693 else TRACE(profile
, " creating key\n" );
694 key
->value
= HEAP_strdupA( SystemHeap
, 0, value
);
695 CurProfile
->changed
= TRUE
;
701 /***********************************************************************
702 * PROFILE_GetWineIniString
704 * Get a config string from the wine.ini file.
706 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
707 const char *def
, char *buffer
, int len
)
711 EnterCriticalSection( &PROFILE_CritSect
);
715 PROFILEKEY
*key
= PROFILE_Find(&PROFILE_WineProfile
, section
, key_name
, FALSE
);
716 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
718 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
719 section
, key_name
, def
, buffer
);
720 ret
= strlen( buffer
);
724 ret
= PROFILE_GetSection( PROFILE_WineProfile
, section
, buffer
, len
, TRUE
, FALSE
);
726 LeaveCriticalSection( &PROFILE_CritSect
);
732 /***********************************************************************
733 * PROFILE_GetWineIniInt
735 * Get a config integer from the wine.ini file.
737 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
745 EnterCriticalSection( &PROFILE_CritSect
);
747 key
= PROFILE_Find( &PROFILE_WineProfile
, section
, key_name
, FALSE
);
748 if (!key
|| !key
->value
) {
751 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
752 result
= strtol( buffer
, &p
, 0 );
753 ret
= (p
== buffer
) ? 0 /* No digits at all */ : (int)result
;
756 LeaveCriticalSection( &PROFILE_CritSect
);
762 /******************************************************************************
764 * int PROFILE_EnumerateWineIniSection(
765 * char const *section, #Name of the section to enumerate
766 * void (*cbfn)(char const *key, char const *value, void *user),
767 * # Address of the callback function
768 * void *user ) # User-specified pointer.
770 * For each entry in a section in the wine.conf file, this function will
771 * call the specified callback function, informing it of each key and
772 * value. An optional user pointer may be passed to it (if this is not
773 * needed, pass NULL through it and ignore the value in the callback
776 * The callback function must accept three parameters:
777 * The name of the key (char const *)
778 * The value of the key (char const *)
779 * A user-specified parameter (void *)
780 * Note that the first two are char CONST *'s, not char *'s! The callback
781 * MUST not modify these strings!
783 * The return value indicates the number of times the callback function
786 int PROFILE_EnumerateWineIniSection(
788 void (*cbfn
)(char const *, char const *, void *),
791 PROFILESECTION
*scansect
;
795 EnterCriticalSection( &PROFILE_CritSect
);
797 /* Search for the correct section */
798 for(scansect
= PROFILE_WineProfile
; scansect
; scansect
= scansect
->next
) {
799 if(scansect
->name
&& !strcasecmp(scansect
->name
, section
)) {
801 /* Enumerate each key with the callback */
802 for(scankey
= scansect
->key
; scankey
; scankey
= scankey
->next
) {
804 /* Ignore blank entries -- these shouldn't exist, but let's
806 if(scankey
->name
[0]) {
807 cbfn(scankey
->name
, scankey
->value
, userptr
);
815 LeaveCriticalSection( &PROFILE_CritSect
);
821 /******************************************************************************
823 * int PROFILE_GetWineIniBool(
824 * char const *section,
825 * char const *key_name,
828 * Reads a boolean value from the wine.ini file. This function attempts to
829 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
830 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
831 * true. Anything else results in the return of the default value.
833 * This function uses 1 to indicate true, and 0 for false. You can check
834 * for existence by setting def to something other than 0 or 1 and
835 * examining the return value.
837 int PROFILE_GetWineIniBool(
839 char const *key_name
,
845 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
847 switch(key_value
[0]) {
868 TRACE(profile
, "(\"%s\", \"%s\", %s), "
869 "[%c], ret %s.\n", section
, key_name
,
870 def
? "TRUE" : "FALSE", key_value
[0],
871 retval
? "TRUE" : "FALSE");
877 /***********************************************************************
878 * PROFILE_LoadWineIni
880 * Load the wine.ini file.
882 int PROFILE_LoadWineIni(void)
884 char buffer
[MAX_PATHNAME_LEN
];
888 InitializeCriticalSection( &PROFILE_CritSect
);
889 MakeCriticalSectionGlobal( &PROFILE_CritSect
);
891 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
893 /* Open -config specified file */
894 PROFILE_WineProfile
= PROFILE_Load ( f
);
896 strncpy(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
-1);
900 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
902 PROFILE_WineProfile
= PROFILE_Load( f
);
904 strncpy(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
-1);
907 if ((p
= getenv( "HOME" )) != NULL
)
909 lstrcpynA(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
910 strcat( buffer
, PROFILE_WineIniName
);
911 if ((f
= fopen( buffer
, "r" )) != NULL
)
913 PROFILE_WineProfile
= PROFILE_Load( f
);
915 strncpy(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
-1);
919 else WARN(profile
, "could not get $HOME value for config file.\n" );
921 /* Try global file */
923 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
925 PROFILE_WineProfile
= PROFILE_Load( f
);
927 strncpy(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
-1);
930 MSG( "Can't open configuration file %s or $HOME%s\n",
931 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
936 /***********************************************************************
937 * PROFILE_UsageWineIni
939 * Explain the wine.ini file to those who don't read documentation.
940 * Keep below one screenful in length so that error messages above are
943 void PROFILE_UsageWineIni(void)
945 MSG("Perhaps you have not properly edited or created "
946 "your Wine configuration file.\n");
947 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
948 MSG(" or it is determined by the -config option or from\n"
949 " the WINE_INI environment variable.\n");
950 if (*PROFILE_WineIniUsed
)
951 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
952 /* RTFM, so to say */
955 /***********************************************************************
956 * PROFILE_GetStringItem
958 * Convenience function that turns a string 'xxx, yyy, zzz' into
959 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
961 char* PROFILE_GetStringItem( char* start
)
965 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
969 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
971 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
973 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
976 if( lpch
) *lpch
= '\0';
980 /********************* API functions **********************************/
982 /***********************************************************************
983 * GetProfileInt16 (KERNEL.57)
985 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
987 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
991 /***********************************************************************
992 * GetProfileInt32A (KERNEL32.264)
994 UINT WINAPI
GetProfileIntA( LPCSTR section
, LPCSTR entry
, INT def_val
)
996 return GetPrivateProfileIntA( section
, entry
, def_val
, "win.ini" );
999 /***********************************************************************
1000 * GetProfileInt32W (KERNEL32.264)
1002 UINT WINAPI
GetProfileIntW( LPCWSTR section
, LPCWSTR entry
, INT def_val
)
1004 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1005 return GetPrivateProfileIntW( section
, entry
, def_val
, wininiW
);
1008 /***********************************************************************
1009 * GetProfileString16 (KERNEL.58)
1011 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1012 LPSTR buffer
, UINT16 len
)
1014 return GetPrivateProfileString16( section
, entry
, def_val
,
1015 buffer
, len
, "win.ini" );
1018 /***********************************************************************
1019 * GetProfileString32A (KERNEL32.268)
1021 INT WINAPI
GetProfileStringA( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1022 LPSTR buffer
, UINT len
)
1024 return GetPrivateProfileStringA( section
, entry
, def_val
,
1025 buffer
, len
, "win.ini" );
1028 /***********************************************************************
1029 * GetProfileString32W (KERNEL32.269)
1031 INT WINAPI
GetProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1032 LPCWSTR def_val
, LPWSTR buffer
, UINT len
)
1034 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1035 return GetPrivateProfileStringW( section
, entry
, def_val
,
1036 buffer
, len
, wininiW
);
1039 /***********************************************************************
1040 * WriteProfileString16 (KERNEL.59)
1042 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1045 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1048 /***********************************************************************
1049 * WriteProfileString32A (KERNEL32.587)
1051 BOOL WINAPI
WriteProfileStringA( LPCSTR section
, LPCSTR entry
,
1054 return WritePrivateProfileStringA( section
, entry
, string
, "win.ini" );
1057 /***********************************************************************
1058 * WriteProfileString32W (KERNEL32.588)
1060 BOOL WINAPI
WriteProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1063 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1064 return WritePrivateProfileStringW( section
, entry
, string
, wininiW
);
1068 /***********************************************************************
1069 * GetPrivateProfileInt16 (KERNEL.127)
1071 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1072 INT16 def_val
, LPCSTR filename
)
1074 long result
=(long)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
1076 if (result
> 65535) return 65535;
1077 if (result
>= 0) return (UINT16
)result
;
1078 if (result
< -32768) return -32768;
1079 return (UINT16
)(INT16
)result
;
1082 /***********************************************************************
1083 * GetPrivateProfileInt32A (KERNEL32.251)
1085 UINT WINAPI
GetPrivateProfileIntA( LPCSTR section
, LPCSTR entry
,
1086 INT def_val
, LPCSTR filename
)
1092 GetPrivateProfileStringA( section
, entry
, "",
1093 buffer
, sizeof(buffer
), filename
);
1094 if (!buffer
[0]) return (UINT
)def_val
;
1095 result
= strtol( buffer
, &p
, 0 );
1096 if (p
== buffer
) return 0; /* No digits at all */
1097 return (UINT
)result
;
1100 /***********************************************************************
1101 * GetPrivateProfileInt32W (KERNEL32.252)
1103 UINT WINAPI
GetPrivateProfileIntW( LPCWSTR section
, LPCWSTR entry
,
1104 INT def_val
, LPCWSTR filename
)
1106 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1107 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1108 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1109 UINT res
= GetPrivateProfileIntA(sectionA
, entryA
, def_val
, filenameA
);
1110 HeapFree( GetProcessHeap(), 0, sectionA
);
1111 HeapFree( GetProcessHeap(), 0, filenameA
);
1112 HeapFree( GetProcessHeap(), 0, entryA
);
1116 /***********************************************************************
1117 * GetPrivateProfileString16 (KERNEL.128)
1119 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1120 LPCSTR def_val
, LPSTR buffer
,
1121 UINT16 len
, LPCSTR filename
)
1123 return GetPrivateProfileStringA(section
,entry
,def_val
,buffer
,len
,filename
);
1126 /***********************************************************************
1127 * GetPrivateProfileString32A (KERNEL32.255)
1129 INT WINAPI
GetPrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1130 LPCSTR def_val
, LPSTR buffer
,
1131 UINT len
, LPCSTR filename
)
1136 filename
= "win.ini";
1138 EnterCriticalSection( &PROFILE_CritSect
);
1140 if (PROFILE_Open( filename
)) {
1141 ret
= PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1143 lstrcpynA( buffer
, def_val
, len
);
1144 ret
= strlen( buffer
);
1147 LeaveCriticalSection( &PROFILE_CritSect
);
1152 /***********************************************************************
1153 * GetPrivateProfileString32W (KERNEL32.256)
1155 INT WINAPI
GetPrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1156 LPCWSTR def_val
, LPWSTR buffer
,
1157 UINT len
, LPCWSTR filename
)
1159 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1160 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1161 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1162 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1163 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1164 INT ret
= GetPrivateProfileStringA( sectionA
, entryA
, def_valA
,
1165 bufferA
, len
, filenameA
);
1166 lstrcpynAtoW( buffer
, bufferA
, len
);
1167 HeapFree( GetProcessHeap(), 0, sectionA
);
1168 HeapFree( GetProcessHeap(), 0, entryA
);
1169 HeapFree( GetProcessHeap(), 0, filenameA
);
1170 HeapFree( GetProcessHeap(), 0, def_valA
);
1171 HeapFree( GetProcessHeap(), 0, bufferA
);
1175 /***********************************************************************
1176 * GetPrivateProfileSection16 (KERNEL.418)
1178 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
1179 UINT16 len
, LPCSTR filename
)
1181 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
1184 /***********************************************************************
1185 * GetPrivateProfileSection32A (KERNEL32.255)
1187 INT WINAPI
GetPrivateProfileSectionA( LPCSTR section
, LPSTR buffer
,
1188 DWORD len
, LPCSTR filename
)
1192 EnterCriticalSection( &PROFILE_CritSect
);
1194 if (PROFILE_Open( filename
))
1195 ret
= PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1198 LeaveCriticalSection( &PROFILE_CritSect
);
1203 /***********************************************************************
1204 * GetPrivateProfileSection32W (KERNEL32.256)
1207 INT WINAPI
GetPrivateProfileSectionW (LPCWSTR section
, LPWSTR buffer
,
1208 DWORD len
, LPCWSTR filename
)
1211 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1212 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1213 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1214 INT ret
= GetPrivateProfileSectionA( sectionA
, bufferA
, len
,
1216 MultiByteToWideChar(CP_ACP
,0,bufferA
,ret
,buffer
,len
);
1217 HeapFree( GetProcessHeap(), 0, sectionA
);
1218 HeapFree( GetProcessHeap(), 0, filenameA
);
1219 HeapFree( GetProcessHeap(), 0, bufferA
);
1223 /***********************************************************************
1224 * GetProfileSection16 (KERNEL.419)
1226 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
1228 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
1231 /***********************************************************************
1232 * GetProfileSection32A (KERNEL32.268)
1234 INT WINAPI
GetProfileSectionA( LPCSTR section
, LPSTR buffer
, DWORD len
)
1236 return GetPrivateProfileSectionA( section
, buffer
, len
, "win.ini" );
1239 /***********************************************************************
1240 * GetProfileSection32W (KERNEL32)
1242 INT WINAPI
GetProfileSectionW( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
1244 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1245 return GetPrivateProfileSectionW( section
, buffer
, len
, wininiW
);
1249 /***********************************************************************
1250 * WritePrivateProfileString16 (KERNEL.129)
1252 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1253 LPCSTR string
, LPCSTR filename
)
1255 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
1258 /***********************************************************************
1259 * WritePrivateProfileString32A (KERNEL32.582)
1261 BOOL WINAPI
WritePrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1262 LPCSTR string
, LPCSTR filename
)
1266 EnterCriticalSection( &PROFILE_CritSect
);
1268 if (!PROFILE_Open( filename
)) {
1270 } else if (!section
) {
1271 ret
= PROFILE_FlushFile();
1273 ret
= PROFILE_SetString( section
, entry
, string
);
1276 LeaveCriticalSection( &PROFILE_CritSect
);
1281 /***********************************************************************
1282 * WritePrivateProfileString32W (KERNEL32.583)
1284 BOOL WINAPI
WritePrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1285 LPCWSTR string
, LPCWSTR filename
)
1287 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1288 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1289 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1290 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1291 BOOL res
= WritePrivateProfileStringA( sectionA
, entryA
,
1292 stringA
, filenameA
);
1293 HeapFree( GetProcessHeap(), 0, sectionA
);
1294 HeapFree( GetProcessHeap(), 0, entryA
);
1295 HeapFree( GetProcessHeap(), 0, stringA
);
1296 HeapFree( GetProcessHeap(), 0, filenameA
);
1300 /***********************************************************************
1301 * WritePrivateProfileSection16 (KERNEL.416)
1303 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
1304 LPCSTR string
, LPCSTR filename
)
1306 return WritePrivateProfileSectionA( section
, string
, filename
);
1309 /***********************************************************************
1310 * WritePrivateProfileSection32A (KERNEL32)
1312 BOOL WINAPI
WritePrivateProfileSectionA( LPCSTR section
,
1313 LPCSTR string
, LPCSTR filename
)
1315 char *p
=(char*)string
;
1317 FIXME(profile
, "WritePrivateProfileSection32A empty stub\n");
1318 if (TRACE_ON(profile
)) {
1319 TRACE(profile
, "(%s) => [%s]\n", filename
, section
);
1321 TRACE(profile
, "%s\n", p
);
1330 /***********************************************************************
1331 * WritePrivateProfileSection32W (KERNEL32)
1333 BOOL WINAPI
WritePrivateProfileSectionW( LPCWSTR section
,
1334 LPCWSTR string
, LPCWSTR filename
)
1337 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1338 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1339 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1340 BOOL res
= WritePrivateProfileSectionA( sectionA
, stringA
, filenameA
);
1341 HeapFree( GetProcessHeap(), 0, sectionA
);
1342 HeapFree( GetProcessHeap(), 0, stringA
);
1343 HeapFree( GetProcessHeap(), 0, filenameA
);
1347 /***********************************************************************
1348 * WriteProfileSection16 (KERNEL.417)
1350 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
1352 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
1355 /***********************************************************************
1356 * WriteProfileSection32A (KERNEL32.747)
1358 BOOL WINAPI
WriteProfileSectionA( LPCSTR section
, LPCSTR keys_n_values
)
1361 return WritePrivateProfileSectionA( section
, keys_n_values
, "win.ini");
1364 /***********************************************************************
1365 * WriteProfileSection32W (KERNEL32.748)
1367 BOOL WINAPI
WriteProfileSectionW( LPCWSTR section
, LPCWSTR keys_n_values
)
1369 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini");
1371 return (WritePrivateProfileSectionW (section
,keys_n_values
, wininiW
));
1374 /***********************************************************************
1375 * GetPrivateProfileSectionNames16 (KERNEL.143)
1377 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1382 EnterCriticalSection( &PROFILE_CritSect
);
1384 if (PROFILE_Open( filename
))
1385 ret
= PROFILE_GetSectionNames(buffer
, size
);
1387 LeaveCriticalSection( &PROFILE_CritSect
);
1393 /***********************************************************************
1394 * GetProfileSectionNames16 (KERNEL.142)
1396 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1399 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1403 /***********************************************************************
1404 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1406 DWORD WINAPI
GetPrivateProfileSectionNamesA( LPSTR buffer
, DWORD size
,
1410 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1414 /***********************************************************************
1415 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1417 DWORD WINAPI
GetPrivateProfileSectionNamesW( LPWSTR buffer
, DWORD size
,
1421 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1422 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1424 INT ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1425 lstrcpynAtoW( buffer
, bufferA
, size
);
1426 HeapFree( GetProcessHeap(), 0, bufferA
);
1427 HeapFree( GetProcessHeap(), 0, filenameA
);
1432 /***********************************************************************
1433 * GetPrivateProfileStruct16 (KERNEL.407)
1435 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
1436 LPVOID buf
, UINT16 len
, LPCSTR filename
)
1438 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
1441 /***********************************************************************
1442 * GetPrivateProfileStruct32A (KERNEL32.370)
1444 BOOL WINAPI
GetPrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1445 LPVOID buf
, UINT len
, LPCSTR filename
)
1449 EnterCriticalSection( &PROFILE_CritSect
);
1451 if (PROFILE_Open( filename
)) {
1452 PROFILEKEY
*k
= PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1454 lstrcpynA( buf
, k
->value
, strlen(k
->value
));
1458 LeaveCriticalSection( &PROFILE_CritSect
);
1463 /***********************************************************************
1464 * GetPrivateProfileStruct32W (KERNEL32.543)
1466 BOOL WINAPI
GetPrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1467 LPVOID buffer
, UINT len
, LPCWSTR filename
)
1469 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1470 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1471 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1472 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1474 INT ret
= GetPrivateProfileStructA( sectionA
, keyA
, bufferA
,
1476 lstrcpynAtoW( buffer
, bufferA
, len
);
1477 HeapFree( GetProcessHeap(), 0, bufferA
);
1478 HeapFree( GetProcessHeap(), 0, sectionA
);
1479 HeapFree( GetProcessHeap(), 0, keyA
);
1480 HeapFree( GetProcessHeap(), 0, filenameA
);
1487 /***********************************************************************
1488 * WritePrivateProfileStruct16 (KERNEL.406)
1490 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
1491 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
1493 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
1496 /***********************************************************************
1497 * WritePrivateProfileStruct32A (KERNEL32.744)
1499 BOOL WINAPI
WritePrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1500 LPVOID buf
, UINT bufsize
, LPCSTR filename
)
1504 EnterCriticalSection( &PROFILE_CritSect
);
1506 if ((!section
) && (!key
) && (!buf
)) { /* flush the cache */
1507 PROFILE_FlushFile();
1510 if (!PROFILE_Open( filename
))
1513 ret
= PROFILE_SetString( section
, key
, buf
);
1516 LeaveCriticalSection( &PROFILE_CritSect
);
1521 /***********************************************************************
1522 * WritePrivateProfileStruct32W (KERNEL32.544)
1524 BOOL WINAPI
WritePrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1525 LPVOID buf
, UINT bufsize
, LPCWSTR filename
)
1527 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1528 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1529 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1530 INT ret
= WritePrivateProfileStructA( sectionA
, keyA
, buf
, bufsize
,
1532 HeapFree( GetProcessHeap(), 0, sectionA
);
1533 HeapFree( GetProcessHeap(), 0, keyA
);
1534 HeapFree( GetProcessHeap(), 0, filenameA
);
1540 /***********************************************************************
1541 * WriteOutProfiles (KERNEL.315)
1543 void WINAPI
WriteOutProfiles16(void)
1545 EnterCriticalSection( &PROFILE_CritSect
);
1546 PROFILE_FlushFile();
1547 LeaveCriticalSection( &PROFILE_CritSect
);