4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
15 #include "wine/winbase16.h"
20 #include "debugtools.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
);
120 if (quote
&& (len
> 1)) buffer
--;
125 /***********************************************************************
128 * Save a profile tree to a file.
130 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
134 for ( ; section
; section
= section
->next
)
136 if (section
->name
) fprintf( file
, "\r\n[%s]\r\n", section
->name
);
137 for (key
= section
->key
; key
; key
= key
->next
)
139 fprintf( file
, "%s", key
->name
);
140 if (key
->value
) fprintf( file
, "=%s", key
->value
);
141 fprintf( file
, "\r\n" );
147 /***********************************************************************
150 * Free a profile tree.
152 static void PROFILE_Free( PROFILESECTION
*section
)
154 PROFILESECTION
*next_section
;
155 PROFILEKEY
*key
, *next_key
;
157 for ( ; section
; section
= next_section
)
159 if (section
->name
) HeapFree( SystemHeap
, 0, section
->name
);
160 for (key
= section
->key
; key
; key
= next_key
)
162 next_key
= key
->next
;
163 if (key
->name
) HeapFree( SystemHeap
, 0, key
->name
);
164 if (key
->value
) HeapFree( SystemHeap
, 0, key
->value
);
165 HeapFree( SystemHeap
, 0, key
);
167 next_section
= section
->next
;
168 HeapFree( SystemHeap
, 0, section
);
173 PROFILE_isspace(char c
) {
174 if (isspace(c
)) return 1;
175 if (c
=='\r' || c
==0x1a) return 1;
176 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
181 /***********************************************************************
184 * Load a profile tree from a file.
186 static PROFILESECTION
*PROFILE_Load( FILE *file
)
188 char buffer
[PROFILE_MAX_LINE_LEN
];
191 PROFILESECTION
*section
, *first_section
;
192 PROFILESECTION
**next_section
;
193 PROFILEKEY
*key
, *prev_key
, **next_key
;
195 first_section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
196 first_section
->name
= NULL
;
197 first_section
->key
= NULL
;
198 first_section
->next
= NULL
;
199 next_section
= &first_section
->next
;
200 next_key
= &first_section
->key
;
203 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
207 while (*p
&& PROFILE_isspace(*p
)) p
++;
208 if (*p
== '[') /* section start */
210 if (!(p2
= strrchr( p
, ']' )))
212 WARN("Invalid section header at line %d: '%s'\n",
219 section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
220 section
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
222 section
->next
= NULL
;
223 *next_section
= section
;
224 next_section
= §ion
->next
;
225 next_key
= §ion
->key
;
228 TRACE("New section: '%s'\n",section
->name
);
235 while ((p2
> p
) && ((*p2
== '\n') || PROFILE_isspace(*p2
))) *p2
--='\0';
237 if ((p2
= strchr( p
, '=' )) != NULL
)
240 while ((p3
> p
) && PROFILE_isspace(*p3
)) *p3
-- = '\0';
242 while (*p2
&& PROFILE_isspace(*p2
)) p2
++;
245 if(*p
|| !prev_key
|| *prev_key
->name
)
247 key
= HEAP_xalloc( SystemHeap
, 0, sizeof(*key
) );
248 key
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
249 key
->value
= p2
? HEAP_strdupA( SystemHeap
, 0, p2
) : NULL
;
252 next_key
= &key
->next
;
255 TRACE("New key: name='%s', value='%s'\n",key
->name
,key
->value
?key
->value
:"(none)");
258 return first_section
;
262 /***********************************************************************
263 * PROFILE_DeleteSection
265 * Delete a section from a profile tree.
267 static BOOL
PROFILE_DeleteSection( PROFILESECTION
**section
, LPCSTR name
)
271 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, name
))
273 PROFILESECTION
*to_del
= *section
;
274 *section
= to_del
->next
;
276 PROFILE_Free( to_del
);
279 section
= &(*section
)->next
;
285 /***********************************************************************
288 * Delete a key from a profile tree.
290 static BOOL
PROFILE_DeleteKey( PROFILESECTION
**section
,
291 LPCSTR section_name
, LPCSTR key_name
)
295 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
297 PROFILEKEY
**key
= &(*section
)->key
;
300 if (!strcasecmp( (*key
)->name
, key_name
))
302 PROFILEKEY
*to_del
= *key
;
304 if (to_del
->name
) HeapFree( SystemHeap
, 0, to_del
->name
);
305 if (to_del
->value
) HeapFree( SystemHeap
, 0, to_del
->value
);
306 HeapFree( SystemHeap
, 0, to_del
);
312 section
= &(*section
)->next
;
318 /***********************************************************************
321 * Find a key in a profile tree, optionally creating it.
323 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
324 const char *section_name
,
325 const char *key_name
, int create
)
329 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
331 PROFILEKEY
**key
= &(*section
)->key
;
334 if (!strcasecmp( (*key
)->name
, key_name
)) return *key
;
337 if (!create
) return NULL
;
338 *key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
339 (*key
)->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
340 (*key
)->value
= NULL
;
344 section
= &(*section
)->next
;
346 if (!create
) return NULL
;
347 *section
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILESECTION
) );
348 (*section
)->name
= HEAP_strdupA( SystemHeap
, 0, section_name
);
349 (*section
)->next
= NULL
;
350 (*section
)->key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
351 (*section
)->key
->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
352 (*section
)->key
->value
= NULL
;
353 (*section
)->key
->next
= NULL
;
354 return (*section
)->key
;
358 /***********************************************************************
361 * Flush the current profile to disk if changed.
363 static BOOL
PROFILE_FlushFile(void)
365 char *p
, buffer
[MAX_PATHNAME_LEN
];
366 const char *unix_name
;
372 WARN("No current profile!\n");
376 if (!CurProfile
->changed
|| !CurProfile
->dos_name
) return TRUE
;
377 if (!(unix_name
= CurProfile
->unix_name
) || !(file
= fopen(unix_name
, "w")))
379 /* Try to create it in $HOME/.wine */
380 /* FIXME: this will need a more general solution */
381 if ((p
= getenv( "HOME" )) != NULL
)
384 strcat( buffer
, "/.wine/" );
385 p
= buffer
+ strlen(buffer
);
386 strcpy( p
, strrchr( CurProfile
->dos_name
, '\\' ) + 1 );
388 file
= fopen( buffer
, "w" );
395 WARN("could not save profile file %s\n", CurProfile
->dos_name
);
399 TRACE("Saving '%s' into '%s'\n", CurProfile
->dos_name
, unix_name
);
400 PROFILE_Save( file
, CurProfile
->section
);
402 CurProfile
->changed
= FALSE
;
403 if(!stat(unix_name
,&buf
))
404 CurProfile
->mtime
=buf
.st_mtime
;
409 /***********************************************************************
410 * PROFILE_ReleaseFile
412 * Flush the current profile to disk and remove it from the cache.
414 static void PROFILE_ReleaseFile(void)
417 PROFILE_Free( CurProfile
->section
);
418 if (CurProfile
->dos_name
) HeapFree( SystemHeap
, 0, CurProfile
->dos_name
);
419 if (CurProfile
->unix_name
) HeapFree( SystemHeap
, 0, CurProfile
->unix_name
);
420 if (CurProfile
->filename
) HeapFree( SystemHeap
, 0, CurProfile
->filename
);
421 CurProfile
->changed
= FALSE
;
422 CurProfile
->section
= NULL
;
423 CurProfile
->dos_name
= NULL
;
424 CurProfile
->unix_name
= NULL
;
425 CurProfile
->filename
= NULL
;
426 CurProfile
->mtime
= 0;
430 /***********************************************************************
433 * Open a profile file, checking the cached file first.
435 static BOOL
PROFILE_Open( LPCSTR filename
)
437 DOS_FULL_NAME full_name
;
438 char buffer
[MAX_PATHNAME_LEN
];
439 char *newdos_name
, *p
;
443 PROFILE
*tempProfile
;
445 /* First time around */
448 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
450 MRUProfile
[i
]=HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILE
) );
451 MRUProfile
[i
]->changed
=FALSE
;
452 MRUProfile
[i
]->section
=NULL
;
453 MRUProfile
[i
]->dos_name
=NULL
;
454 MRUProfile
[i
]->unix_name
=NULL
;
455 MRUProfile
[i
]->filename
=NULL
;
456 MRUProfile
[i
]->mtime
=0;
459 /* Check for a match */
461 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
462 strchr( filename
, ':' ))
464 if (!DOSFS_GetFullName( filename
, FALSE
, &full_name
)) return FALSE
;
468 GetWindowsDirectoryA( buffer
, sizeof(buffer
) );
469 strcat( buffer
, "\\" );
470 strcat( buffer
, filename
);
471 if (!DOSFS_GetFullName( buffer
, FALSE
, &full_name
)) return FALSE
;
474 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
476 if ((MRUProfile
[i
]->filename
&& !strcmp( filename
, MRUProfile
[i
]->filename
)) ||
477 (MRUProfile
[i
]->dos_name
&& !strcmp( full_name
.short_name
, MRUProfile
[i
]->dos_name
)))
482 tempProfile
=MRUProfile
[i
];
484 MRUProfile
[j
]=MRUProfile
[j
-1];
485 CurProfile
=tempProfile
;
487 if(!stat(CurProfile
->unix_name
,&buf
) && CurProfile
->mtime
==buf
.st_mtime
)
488 TRACE("(%s): already opened (mru=%d)\n",
491 TRACE("(%s): already opened, needs refreshing (mru=%d)\n",
497 /* Rotate the oldest to the top to be replaced */
499 if(i
==N_CACHED_PROFILES
)
501 tempProfile
=MRUProfile
[N_CACHED_PROFILES
-1];
502 for(i
=N_CACHED_PROFILES
-1;i
>0;i
--)
503 MRUProfile
[i
]=MRUProfile
[i
-1];
504 CurProfile
=tempProfile
;
507 /* Flush the profile */
509 if(CurProfile
->filename
) PROFILE_ReleaseFile();
511 newdos_name
= HEAP_strdupA( SystemHeap
, 0, full_name
.short_name
);
512 CurProfile
->dos_name
= newdos_name
;
513 CurProfile
->filename
= HEAP_strdupA( SystemHeap
, 0, filename
);
515 /* Try to open the profile file, first in $HOME/.wine */
517 /* FIXME: this will need a more general solution */
518 if ((p
= getenv( "HOME" )) != NULL
)
521 strcat( buffer
, "/.wine/" );
522 p
= buffer
+ strlen(buffer
);
523 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
525 if ((file
= fopen( buffer
, "r" )))
527 TRACE("(%s): found it in %s\n",
529 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0, buffer
);
535 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0,
536 full_name
.long_name
);
537 if ((file
= fopen( full_name
.long_name
, "r" )))
538 TRACE("(%s): found it in %s\n",
539 filename
, full_name
.long_name
);
544 CurProfile
->section
= PROFILE_Load( file
);
546 if(!stat(CurProfile
->unix_name
,&buf
))
547 CurProfile
->mtime
=buf
.st_mtime
;
551 /* Does not exist yet, we will create it in PROFILE_FlushFile */
552 WARN("profile file %s not found\n", newdos_name
);
558 /***********************************************************************
561 * Returns all keys of a section.
562 * If return_values is TRUE, also include the corresponding values.
564 static INT
PROFILE_GetSection( PROFILESECTION
*section
, LPCSTR section_name
,
565 LPSTR buffer
, UINT len
, BOOL handle_env
,
571 if (section
->name
&& !strcasecmp( section
->name
, section_name
))
574 for (key
= section
->key
; key
; key
= key
->next
)
577 if (!*key
->name
) continue; /* Skip empty lines */
578 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
579 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
580 len
-= strlen(buffer
) + 1;
581 buffer
+= strlen(buffer
) + 1;
582 if (return_values
&& key
->value
) {
584 PROFILE_CopyEntry ( buffer
,
585 key
->value
, len
- 1, handle_env
);
586 len
-= strlen(buffer
) + 1;
587 buffer
+= strlen(buffer
) + 1;
592 /*If either lpszSection or lpszKey is NULL and the supplied
593 destination buffer is too small to hold all the strings,
594 the last string is truncated and followed by two null characters.
595 In this case, the return value is equal to cchReturnBuffer
603 section
= section
->next
;
605 buffer
[0] = buffer
[1] = '\0';
610 static INT
PROFILE_GetSectionNames( LPSTR buffer
, UINT len
)
614 PROFILESECTION
*section
;
616 for (section
= CurProfile
->section
; section
; section
= section
->next
)
618 l
= strlen(section
->name
);
623 strcpy(buf
, section
->name
);
633 /***********************************************************************
636 * Get a profile string.
638 static INT
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
639 LPCSTR def_val
, LPSTR buffer
, UINT len
)
641 PROFILEKEY
*key
= NULL
;
643 if (!def_val
) def_val
= "";
644 if (key_name
&& key_name
[0])
646 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
647 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
649 TRACE("('%s','%s','%s'): returning '%s'\n",
650 section
, key_name
, def_val
, buffer
);
651 return strlen( buffer
);
653 if (section
&& section
[0])
654 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
656 /* undocumented; both section and key_name are NULL */
657 return PROFILE_GetSectionNames(buffer
, len
);
661 /***********************************************************************
664 * Set a profile string.
666 static BOOL
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
669 if (!key_name
) /* Delete a whole section */
671 TRACE("('%s')\n", section_name
);
672 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
674 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
675 this is not an error on application's level.*/
677 else if (!value
) /* Delete a key */
679 TRACE("('%s','%s')\n",
680 section_name
, key_name
);
681 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
682 section_name
, key_name
);
683 return TRUE
; /* same error handling as above */
685 else /* Set the key value */
687 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
689 TRACE("('%s','%s','%s'): \n",
690 section_name
, key_name
, value
);
691 if (!key
) return FALSE
;
694 if (!strcmp( key
->value
, value
))
696 TRACE(" no change needed\n" );
697 return TRUE
; /* No change needed */
699 TRACE(" replacing '%s'\n", key
->value
);
700 HeapFree( SystemHeap
, 0, key
->value
);
702 else TRACE(" creating key\n" );
703 key
->value
= HEAP_strdupA( SystemHeap
, 0, value
);
704 CurProfile
->changed
= TRUE
;
710 /***********************************************************************
711 * PROFILE_GetWineIniString
713 * Get a config string from the wine.ini file.
715 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
716 const char *def
, char *buffer
, int len
)
720 EnterCriticalSection( &PROFILE_CritSect
);
724 PROFILEKEY
*key
= PROFILE_Find(&PROFILE_WineProfile
, section
, key_name
, FALSE
);
725 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
727 TRACE("('%s','%s','%s'): returning '%s'\n",
728 section
, key_name
, def
, buffer
);
729 ret
= strlen( buffer
);
733 ret
= PROFILE_GetSection( PROFILE_WineProfile
, section
, buffer
, len
, TRUE
, FALSE
);
735 LeaveCriticalSection( &PROFILE_CritSect
);
741 /***********************************************************************
742 * PROFILE_GetWineIniInt
744 * Get a config integer from the wine.ini file.
746 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
754 EnterCriticalSection( &PROFILE_CritSect
);
756 key
= PROFILE_Find( &PROFILE_WineProfile
, section
, key_name
, FALSE
);
757 if (!key
|| !key
->value
) {
760 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
761 result
= strtol( buffer
, &p
, 0 );
762 ret
= (p
== buffer
) ? 0 /* No digits at all */ : (int)result
;
765 LeaveCriticalSection( &PROFILE_CritSect
);
771 /******************************************************************************
773 * int PROFILE_EnumerateWineIniSection(
774 * char const *section, #Name of the section to enumerate
775 * void (*cbfn)(char const *key, char const *value, void *user),
776 * # Address of the callback function
777 * void *user ) # User-specified pointer.
779 * For each entry in a section in the wine.conf file, this function will
780 * call the specified callback function, informing it of each key and
781 * value. An optional user pointer may be passed to it (if this is not
782 * needed, pass NULL through it and ignore the value in the callback
785 * The callback function must accept three parameters:
786 * The name of the key (char const *)
787 * The value of the key (char const *)
788 * A user-specified parameter (void *)
789 * Note that the first two are char CONST *'s, not char *'s! The callback
790 * MUST not modify these strings!
792 * The return value indicates the number of times the callback function
795 int PROFILE_EnumerateWineIniSection(
797 void (*cbfn
)(char const *, char const *, void *),
800 PROFILESECTION
*scansect
;
804 EnterCriticalSection( &PROFILE_CritSect
);
806 /* Search for the correct section */
807 for(scansect
= PROFILE_WineProfile
; scansect
; scansect
= scansect
->next
) {
808 if(scansect
->name
&& !strcasecmp(scansect
->name
, section
)) {
810 /* Enumerate each key with the callback */
811 for(scankey
= scansect
->key
; scankey
; scankey
= scankey
->next
) {
813 /* Ignore blank entries -- these shouldn't exist, but let's
815 if (!scankey
->name
[0]) continue;
816 if (!scankey
->value
) cbfn(scankey
->name
, NULL
, userptr
);
820 PROFILE_CopyEntry(value
, scankey
->value
, sizeof(value
), TRUE
);
821 cbfn(scankey
->name
, value
, userptr
);
829 LeaveCriticalSection( &PROFILE_CritSect
);
835 /******************************************************************************
837 * int PROFILE_GetWineIniBool(
838 * char const *section,
839 * char const *key_name,
842 * Reads a boolean value from the wine.ini file. This function attempts to
843 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
844 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
845 * true. Anything else results in the return of the default value.
847 * This function uses 1 to indicate true, and 0 for false. You can check
848 * for existence by setting def to something other than 0 or 1 and
849 * examining the return value.
851 int PROFILE_GetWineIniBool(
853 char const *key_name
,
859 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
861 switch(key_value
[0]) {
882 TRACE("(\"%s\", \"%s\", %s), "
883 "[%c], ret %s.\n", section
, key_name
,
884 def
? "TRUE" : "FALSE", key_value
[0],
885 retval
? "TRUE" : "FALSE");
891 /***********************************************************************
892 * PROFILE_LoadWineIni
894 * Load the wine.ini file.
896 int PROFILE_LoadWineIni(void)
898 char buffer
[MAX_PATHNAME_LEN
];
902 InitializeCriticalSection( &PROFILE_CritSect
);
903 MakeCriticalSectionGlobal( &PROFILE_CritSect
);
905 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
907 /* Open -config specified file */
908 PROFILE_WineProfile
= PROFILE_Load ( f
);
910 strncpy(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
-1);
914 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
916 PROFILE_WineProfile
= PROFILE_Load( f
);
918 strncpy(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
-1);
921 if ((p
= getenv( "HOME" )) != NULL
)
923 lstrcpynA(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
924 strcat( buffer
, PROFILE_WineIniName
);
925 if ((f
= fopen( buffer
, "r" )) != NULL
)
927 PROFILE_WineProfile
= PROFILE_Load( f
);
929 strncpy(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
-1);
933 else WARN("could not get $HOME value for config file.\n" );
935 /* Try global file */
937 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
939 PROFILE_WineProfile
= PROFILE_Load( f
);
941 strncpy(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
-1);
944 MESSAGE( "Can't open configuration file %s or $HOME%s\n",
945 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
950 /***********************************************************************
951 * PROFILE_UsageWineIni
953 * Explain the wine.ini file to those who don't read documentation.
954 * Keep below one screenful in length so that error messages above are
957 void PROFILE_UsageWineIni(void)
959 MESSAGE("Perhaps you have not properly edited or created "
960 "your Wine configuration file.\n");
961 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
962 MESSAGE(" or it is determined by the -config option or from\n"
963 " the WINE_INI environment variable.\n");
964 if (*PROFILE_WineIniUsed
)
965 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
966 /* RTFM, so to say */
969 /***********************************************************************
970 * PROFILE_GetStringItem
972 * Convenience function that turns a string 'xxx, yyy, zzz' into
973 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
975 char* PROFILE_GetStringItem( char* start
)
979 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
983 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
985 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
987 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
990 if( lpch
) *lpch
= '\0';
994 /********************* API functions **********************************/
996 /***********************************************************************
997 * GetProfileInt16 (KERNEL.57)
999 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
1001 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
1005 /***********************************************************************
1006 * GetProfileInt32A (KERNEL32.264)
1008 UINT WINAPI
GetProfileIntA( LPCSTR section
, LPCSTR entry
, INT def_val
)
1010 return GetPrivateProfileIntA( section
, entry
, def_val
, "win.ini" );
1013 /***********************************************************************
1014 * GetProfileInt32W (KERNEL32.264)
1016 UINT WINAPI
GetProfileIntW( LPCWSTR section
, LPCWSTR entry
, INT def_val
)
1018 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1019 return GetPrivateProfileIntW( section
, entry
, def_val
, wininiW
);
1022 /***********************************************************************
1023 * GetProfileString16 (KERNEL.58)
1025 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1026 LPSTR buffer
, UINT16 len
)
1028 return GetPrivateProfileString16( section
, entry
, def_val
,
1029 buffer
, len
, "win.ini" );
1032 /***********************************************************************
1033 * GetProfileString32A (KERNEL32.268)
1035 INT WINAPI
GetProfileStringA( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1036 LPSTR buffer
, UINT len
)
1038 return GetPrivateProfileStringA( section
, entry
, def_val
,
1039 buffer
, len
, "win.ini" );
1042 /***********************************************************************
1043 * GetProfileString32W (KERNEL32.269)
1045 INT WINAPI
GetProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1046 LPCWSTR def_val
, LPWSTR buffer
, UINT len
)
1048 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1049 return GetPrivateProfileStringW( section
, entry
, def_val
,
1050 buffer
, len
, wininiW
);
1053 /***********************************************************************
1054 * WriteProfileString16 (KERNEL.59)
1056 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1059 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1062 /***********************************************************************
1063 * WriteProfileString32A (KERNEL32.587)
1065 BOOL WINAPI
WriteProfileStringA( LPCSTR section
, LPCSTR entry
,
1068 return WritePrivateProfileStringA( section
, entry
, string
, "win.ini" );
1071 /***********************************************************************
1072 * WriteProfileString32W (KERNEL32.588)
1074 BOOL WINAPI
WriteProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1077 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1078 return WritePrivateProfileStringW( section
, entry
, string
, wininiW
);
1082 /***********************************************************************
1083 * GetPrivateProfileInt16 (KERNEL.127)
1085 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1086 INT16 def_val
, LPCSTR filename
)
1088 long result
=(long)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
1090 if (result
> 65535) return 65535;
1091 if (result
>= 0) return (UINT16
)result
;
1092 if (result
< -32768) return -32768;
1093 return (UINT16
)(INT16
)result
;
1096 /***********************************************************************
1097 * GetPrivateProfileInt32A (KERNEL32.251)
1099 UINT WINAPI
GetPrivateProfileIntA( LPCSTR section
, LPCSTR entry
,
1100 INT def_val
, LPCSTR filename
)
1106 GetPrivateProfileStringA( section
, entry
, "",
1107 buffer
, sizeof(buffer
), filename
);
1108 if (!buffer
[0]) return (UINT
)def_val
;
1109 result
= strtol( buffer
, &p
, 0 );
1110 if (p
== buffer
) return 0; /* No digits at all */
1111 return (UINT
)result
;
1114 /***********************************************************************
1115 * GetPrivateProfileInt32W (KERNEL32.252)
1117 UINT WINAPI
GetPrivateProfileIntW( LPCWSTR section
, LPCWSTR entry
,
1118 INT def_val
, LPCWSTR filename
)
1120 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1121 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1122 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1123 UINT res
= GetPrivateProfileIntA(sectionA
, entryA
, def_val
, filenameA
);
1124 HeapFree( GetProcessHeap(), 0, sectionA
);
1125 HeapFree( GetProcessHeap(), 0, filenameA
);
1126 HeapFree( GetProcessHeap(), 0, entryA
);
1130 /***********************************************************************
1131 * GetPrivateProfileString16 (KERNEL.128)
1133 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1134 LPCSTR def_val
, LPSTR buffer
,
1135 UINT16 len
, LPCSTR filename
)
1137 return GetPrivateProfileStringA(section
,entry
,def_val
,buffer
,len
,filename
);
1140 /***********************************************************************
1141 * GetPrivateProfileString32A (KERNEL32.255)
1143 INT WINAPI
GetPrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1144 LPCSTR def_val
, LPSTR buffer
,
1145 UINT len
, LPCSTR filename
)
1150 filename
= "win.ini";
1152 EnterCriticalSection( &PROFILE_CritSect
);
1154 if (PROFILE_Open( filename
)) {
1155 ret
= PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1157 lstrcpynA( buffer
, def_val
, len
);
1158 ret
= strlen( buffer
);
1161 LeaveCriticalSection( &PROFILE_CritSect
);
1166 /***********************************************************************
1167 * GetPrivateProfileString32W (KERNEL32.256)
1169 INT WINAPI
GetPrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1170 LPCWSTR def_val
, LPWSTR buffer
,
1171 UINT len
, LPCWSTR filename
)
1173 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1174 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1175 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1176 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1177 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1178 INT ret
= GetPrivateProfileStringA( sectionA
, entryA
, def_valA
,
1179 bufferA
, len
, filenameA
);
1180 lstrcpynAtoW( buffer
, bufferA
, len
);
1181 HeapFree( GetProcessHeap(), 0, sectionA
);
1182 HeapFree( GetProcessHeap(), 0, entryA
);
1183 HeapFree( GetProcessHeap(), 0, filenameA
);
1184 HeapFree( GetProcessHeap(), 0, def_valA
);
1185 HeapFree( GetProcessHeap(), 0, bufferA
);
1189 /***********************************************************************
1190 * GetPrivateProfileSection16 (KERNEL.418)
1192 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
1193 UINT16 len
, LPCSTR filename
)
1195 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
1198 /***********************************************************************
1199 * GetPrivateProfileSection32A (KERNEL32.255)
1201 INT WINAPI
GetPrivateProfileSectionA( LPCSTR section
, LPSTR buffer
,
1202 DWORD len
, LPCSTR filename
)
1206 EnterCriticalSection( &PROFILE_CritSect
);
1208 if (PROFILE_Open( filename
))
1209 ret
= PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1212 LeaveCriticalSection( &PROFILE_CritSect
);
1217 /***********************************************************************
1218 * GetPrivateProfileSection32W (KERNEL32.256)
1221 INT WINAPI
GetPrivateProfileSectionW (LPCWSTR section
, LPWSTR buffer
,
1222 DWORD len
, LPCWSTR filename
)
1225 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1226 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1227 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1228 INT ret
= GetPrivateProfileSectionA( sectionA
, bufferA
, len
,
1230 MultiByteToWideChar(CP_ACP
,0,bufferA
,ret
,buffer
,len
);
1231 HeapFree( GetProcessHeap(), 0, sectionA
);
1232 HeapFree( GetProcessHeap(), 0, filenameA
);
1233 HeapFree( GetProcessHeap(), 0, bufferA
);
1237 /***********************************************************************
1238 * GetProfileSection16 (KERNEL.419)
1240 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
1242 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
1245 /***********************************************************************
1246 * GetProfileSection32A (KERNEL32.268)
1248 INT WINAPI
GetProfileSectionA( LPCSTR section
, LPSTR buffer
, DWORD len
)
1250 return GetPrivateProfileSectionA( section
, buffer
, len
, "win.ini" );
1253 /***********************************************************************
1254 * GetProfileSection32W (KERNEL32)
1256 INT WINAPI
GetProfileSectionW( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
1258 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1259 return GetPrivateProfileSectionW( section
, buffer
, len
, wininiW
);
1263 /***********************************************************************
1264 * WritePrivateProfileString16 (KERNEL.129)
1266 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1267 LPCSTR string
, LPCSTR filename
)
1269 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
1272 /***********************************************************************
1273 * WritePrivateProfileString32A (KERNEL32.582)
1275 BOOL WINAPI
WritePrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1276 LPCSTR string
, LPCSTR filename
)
1280 EnterCriticalSection( &PROFILE_CritSect
);
1282 if (PROFILE_Open( filename
))
1284 if (!section
&& !entry
&& !string
)
1285 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1287 ret
= PROFILE_SetString( section
, entry
, string
);
1290 LeaveCriticalSection( &PROFILE_CritSect
);
1294 /***********************************************************************
1295 * WritePrivateProfileString32W (KERNEL32.583)
1297 BOOL WINAPI
WritePrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1298 LPCWSTR string
, LPCWSTR filename
)
1300 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1301 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1302 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1303 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1304 BOOL res
= WritePrivateProfileStringA( sectionA
, entryA
,
1305 stringA
, filenameA
);
1306 HeapFree( GetProcessHeap(), 0, sectionA
);
1307 HeapFree( GetProcessHeap(), 0, entryA
);
1308 HeapFree( GetProcessHeap(), 0, stringA
);
1309 HeapFree( GetProcessHeap(), 0, filenameA
);
1313 /***********************************************************************
1314 * WritePrivateProfileSection16 (KERNEL.416)
1316 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
1317 LPCSTR string
, LPCSTR filename
)
1319 return WritePrivateProfileSectionA( section
, string
, filename
);
1322 /***********************************************************************
1323 * WritePrivateProfileSection32A (KERNEL32)
1325 BOOL WINAPI
WritePrivateProfileSectionA( LPCSTR section
,
1326 LPCSTR string
, LPCSTR filename
)
1328 char *p
=(char*)string
;
1330 FIXME("WritePrivateProfileSection32A empty stub\n");
1331 if (TRACE_ON(profile
)) {
1332 TRACE("(%s) => [%s]\n", filename
, section
);
1343 /***********************************************************************
1344 * WritePrivateProfileSection32W (KERNEL32)
1346 BOOL WINAPI
WritePrivateProfileSectionW( LPCWSTR section
,
1347 LPCWSTR string
, LPCWSTR filename
)
1350 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1351 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1352 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1353 BOOL res
= WritePrivateProfileSectionA( sectionA
, stringA
, filenameA
);
1354 HeapFree( GetProcessHeap(), 0, sectionA
);
1355 HeapFree( GetProcessHeap(), 0, stringA
);
1356 HeapFree( GetProcessHeap(), 0, filenameA
);
1360 /***********************************************************************
1361 * WriteProfileSection16 (KERNEL.417)
1363 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
1365 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
1368 /***********************************************************************
1369 * WriteProfileSection32A (KERNEL32.747)
1371 BOOL WINAPI
WriteProfileSectionA( LPCSTR section
, LPCSTR keys_n_values
)
1374 return WritePrivateProfileSectionA( section
, keys_n_values
, "win.ini");
1377 /***********************************************************************
1378 * WriteProfileSection32W (KERNEL32.748)
1380 BOOL WINAPI
WriteProfileSectionW( LPCWSTR section
, LPCWSTR keys_n_values
)
1382 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini");
1384 return (WritePrivateProfileSectionW (section
,keys_n_values
, wininiW
));
1387 /***********************************************************************
1388 * GetPrivateProfileSectionNames16 (KERNEL.143)
1390 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1395 EnterCriticalSection( &PROFILE_CritSect
);
1397 if (PROFILE_Open( filename
))
1398 ret
= PROFILE_GetSectionNames(buffer
, size
);
1400 LeaveCriticalSection( &PROFILE_CritSect
);
1406 /***********************************************************************
1407 * GetProfileSectionNames16 (KERNEL.142)
1409 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1412 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1416 /***********************************************************************
1417 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1419 DWORD WINAPI
GetPrivateProfileSectionNamesA( LPSTR buffer
, DWORD size
,
1423 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1427 /***********************************************************************
1428 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1430 DWORD WINAPI
GetPrivateProfileSectionNamesW( LPWSTR buffer
, DWORD size
,
1434 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1435 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1437 INT ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1438 lstrcpynAtoW( buffer
, bufferA
, size
);
1439 HeapFree( GetProcessHeap(), 0, bufferA
);
1440 HeapFree( GetProcessHeap(), 0, filenameA
);
1445 /***********************************************************************
1446 * GetPrivateProfileStruct16 (KERNEL.407)
1448 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
1449 LPVOID buf
, UINT16 len
, LPCSTR filename
)
1451 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
1454 /***********************************************************************
1455 * GetPrivateProfileStruct32A (KERNEL32.370)
1457 BOOL WINAPI
GetPrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1458 LPVOID buf
, UINT len
, LPCSTR filename
)
1462 EnterCriticalSection( &PROFILE_CritSect
);
1464 if (PROFILE_Open( filename
)) {
1465 PROFILEKEY
*k
= PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1467 lstrcpynA( buf
, k
->value
, strlen(k
->value
));
1471 LeaveCriticalSection( &PROFILE_CritSect
);
1476 /***********************************************************************
1477 * GetPrivateProfileStruct32W (KERNEL32.543)
1479 BOOL WINAPI
GetPrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1480 LPVOID buffer
, UINT len
, LPCWSTR filename
)
1482 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1483 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1484 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1485 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1487 INT ret
= GetPrivateProfileStructA( sectionA
, keyA
, bufferA
,
1489 lstrcpynAtoW( buffer
, bufferA
, len
);
1490 HeapFree( GetProcessHeap(), 0, bufferA
);
1491 HeapFree( GetProcessHeap(), 0, sectionA
);
1492 HeapFree( GetProcessHeap(), 0, keyA
);
1493 HeapFree( GetProcessHeap(), 0, filenameA
);
1500 /***********************************************************************
1501 * WritePrivateProfileStruct16 (KERNEL.406)
1503 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
1504 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
1506 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
1509 /***********************************************************************
1510 * WritePrivateProfileStruct32A (KERNEL32.744)
1512 BOOL WINAPI
WritePrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1513 LPVOID buf
, UINT bufsize
, LPCSTR filename
)
1517 if (!section
&& !key
&& !buf
) /* flush the cache */
1518 return WritePrivateProfileStringA( NULL
, NULL
, NULL
, filename
);
1520 EnterCriticalSection( &PROFILE_CritSect
);
1522 if (PROFILE_Open( filename
))
1523 ret
= PROFILE_SetString( section
, key
, buf
);
1525 LeaveCriticalSection( &PROFILE_CritSect
);
1530 /***********************************************************************
1531 * WritePrivateProfileStruct32W (KERNEL32.544)
1533 BOOL WINAPI
WritePrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1534 LPVOID buf
, UINT bufsize
, LPCWSTR filename
)
1536 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1537 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1538 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1539 INT ret
= WritePrivateProfileStructA( sectionA
, keyA
, buf
, bufsize
,
1541 HeapFree( GetProcessHeap(), 0, sectionA
);
1542 HeapFree( GetProcessHeap(), 0, keyA
);
1543 HeapFree( GetProcessHeap(), 0, filenameA
);
1549 /***********************************************************************
1550 * WriteOutProfiles (KERNEL.315)
1552 void WINAPI
WriteOutProfiles16(void)
1554 EnterCriticalSection( &PROFILE_CritSect
);
1555 PROFILE_FlushFile();
1556 LeaveCriticalSection( &PROFILE_CritSect
);