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
);
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("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("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("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("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("could not save profile file %s\n", CurProfile
->dos_name
);
398 TRACE("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 /***********************************************************************
409 * PROFILE_ReleaseFile
411 * Flush the current profile to disk and remove it from the cache.
413 static void PROFILE_ReleaseFile(void)
416 PROFILE_Free( CurProfile
->section
);
417 if (CurProfile
->dos_name
) HeapFree( SystemHeap
, 0, CurProfile
->dos_name
);
418 if (CurProfile
->unix_name
) HeapFree( SystemHeap
, 0, CurProfile
->unix_name
);
419 if (CurProfile
->filename
) HeapFree( SystemHeap
, 0, CurProfile
->filename
);
420 CurProfile
->changed
= FALSE
;
421 CurProfile
->section
= NULL
;
422 CurProfile
->dos_name
= NULL
;
423 CurProfile
->unix_name
= NULL
;
424 CurProfile
->filename
= NULL
;
425 CurProfile
->mtime
= 0;
429 /***********************************************************************
432 * Open a profile file, checking the cached file first.
434 static BOOL
PROFILE_Open( LPCSTR filename
)
436 DOS_FULL_NAME full_name
;
437 char buffer
[MAX_PATHNAME_LEN
];
438 char *newdos_name
, *p
;
442 PROFILE
*tempProfile
;
444 /* First time around */
447 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
449 MRUProfile
[i
]=HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILE
) );
450 MRUProfile
[i
]->changed
=FALSE
;
451 MRUProfile
[i
]->section
=NULL
;
452 MRUProfile
[i
]->dos_name
=NULL
;
453 MRUProfile
[i
]->unix_name
=NULL
;
454 MRUProfile
[i
]->filename
=NULL
;
455 MRUProfile
[i
]->mtime
=0;
458 /* Check for a match */
460 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
461 strchr( filename
, ':' ))
463 if (!DOSFS_GetFullName( filename
, FALSE
, &full_name
)) return FALSE
;
467 GetWindowsDirectoryA( buffer
, sizeof(buffer
) );
468 strcat( buffer
, "\\" );
469 strcat( buffer
, filename
);
470 if (!DOSFS_GetFullName( buffer
, FALSE
, &full_name
)) return FALSE
;
473 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
475 if ((MRUProfile
[i
]->filename
&& !strcmp( filename
, MRUProfile
[i
]->filename
)) ||
476 (MRUProfile
[i
]->dos_name
&& !strcmp( full_name
.short_name
, MRUProfile
[i
]->dos_name
)))
481 tempProfile
=MRUProfile
[i
];
483 MRUProfile
[j
]=MRUProfile
[j
-1];
484 CurProfile
=tempProfile
;
486 if(!stat(CurProfile
->unix_name
,&buf
) && CurProfile
->mtime
==buf
.st_mtime
)
487 TRACE("(%s): already opened (mru=%d)\n",
490 TRACE("(%s): already opened, needs refreshing (mru=%d)\n",
496 /* Rotate the oldest to the top to be replaced */
498 if(i
==N_CACHED_PROFILES
)
500 tempProfile
=MRUProfile
[N_CACHED_PROFILES
-1];
501 for(i
=N_CACHED_PROFILES
-1;i
>0;i
--)
502 MRUProfile
[i
]=MRUProfile
[i
-1];
503 CurProfile
=tempProfile
;
506 /* Flush the profile */
508 if(CurProfile
->filename
) PROFILE_ReleaseFile();
510 newdos_name
= HEAP_strdupA( SystemHeap
, 0, full_name
.short_name
);
511 CurProfile
->dos_name
= newdos_name
;
512 CurProfile
->filename
= HEAP_strdupA( SystemHeap
, 0, filename
);
514 /* Try to open the profile file, first in $HOME/.wine */
516 /* FIXME: this will need a more general solution */
517 if ((p
= getenv( "HOME" )) != NULL
)
520 strcat( buffer
, "/.wine/" );
521 p
= buffer
+ strlen(buffer
);
522 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
524 if ((file
= fopen( buffer
, "r" )))
526 TRACE("(%s): found it in %s\n",
528 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0, buffer
);
534 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0,
535 full_name
.long_name
);
536 if ((file
= fopen( full_name
.long_name
, "r" )))
537 TRACE("(%s): found it in %s\n",
538 filename
, full_name
.long_name
);
543 CurProfile
->section
= PROFILE_Load( file
);
545 if(!stat(CurProfile
->unix_name
,&buf
))
546 CurProfile
->mtime
=buf
.st_mtime
;
550 /* Does not exist yet, we will create it in PROFILE_FlushFile */
551 WARN("profile file %s not found\n", newdos_name
);
557 /***********************************************************************
560 * Returns all keys of a section.
561 * If return_values is TRUE, also include the corresponding values.
563 static INT
PROFILE_GetSection( PROFILESECTION
*section
, LPCSTR section_name
,
564 LPSTR buffer
, UINT len
, BOOL handle_env
,
570 if (section
->name
&& !strcasecmp( section
->name
, section_name
))
573 for (key
= section
->key
; key
; key
= key
->next
)
576 if (!*key
->name
) continue; /* Skip empty lines */
577 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
578 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
579 len
-= strlen(buffer
) + 1;
580 buffer
+= strlen(buffer
) + 1;
581 if (return_values
&& key
->value
) {
583 PROFILE_CopyEntry ( buffer
,
584 key
->value
, len
- 1, handle_env
);
585 len
-= strlen(buffer
) + 1;
586 buffer
+= strlen(buffer
) + 1;
591 /*If either lpszSection or lpszKey is NULL and the supplied
592 destination buffer is too small to hold all the strings,
593 the last string is truncated and followed by two null characters.
594 In this case, the return value is equal to cchReturnBuffer
602 section
= section
->next
;
604 buffer
[0] = buffer
[1] = '\0';
609 static INT
PROFILE_GetSectionNames( LPSTR buffer
, UINT len
)
613 PROFILESECTION
*section
;
615 for (section
= CurProfile
->section
; section
; section
= section
->next
)
617 l
= strlen(section
->name
);
622 strcpy(buf
, section
->name
);
632 /***********************************************************************
635 * Get a profile string.
637 static INT
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
638 LPCSTR def_val
, LPSTR buffer
, UINT len
)
640 PROFILEKEY
*key
= NULL
;
642 if (!def_val
) def_val
= "";
643 if (key_name
&& key_name
[0])
645 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
646 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
648 TRACE("('%s','%s','%s'): returning '%s'\n",
649 section
, key_name
, def_val
, buffer
);
650 return strlen( buffer
);
652 if (section
&& section
[0])
653 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
655 /* undocumented; both section and key_name are NULL */
656 return PROFILE_GetSectionNames(buffer
, len
);
660 /***********************************************************************
663 * Set a profile string.
665 static BOOL
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
668 if (!key_name
) /* Delete a whole section */
670 TRACE("('%s')\n", section_name
);
671 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
673 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
674 this is not an error on application's level.*/
676 else if (!value
) /* Delete a key */
678 TRACE("('%s','%s')\n",
679 section_name
, key_name
);
680 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
681 section_name
, key_name
);
682 return TRUE
; /* same error handling as above */
684 else /* Set the key value */
686 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
688 TRACE("('%s','%s','%s'): \n",
689 section_name
, key_name
, value
);
690 if (!key
) return FALSE
;
693 if (!strcmp( key
->value
, value
))
695 TRACE(" no change needed\n" );
696 return TRUE
; /* No change needed */
698 TRACE(" replacing '%s'\n", key
->value
);
699 HeapFree( SystemHeap
, 0, key
->value
);
701 else TRACE(" creating key\n" );
702 key
->value
= HEAP_strdupA( SystemHeap
, 0, value
);
703 CurProfile
->changed
= TRUE
;
709 /***********************************************************************
710 * PROFILE_GetWineIniString
712 * Get a config string from the wine.ini file.
714 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
715 const char *def
, char *buffer
, int len
)
719 EnterCriticalSection( &PROFILE_CritSect
);
723 PROFILEKEY
*key
= PROFILE_Find(&PROFILE_WineProfile
, section
, key_name
, FALSE
);
724 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
726 TRACE("('%s','%s','%s'): returning '%s'\n",
727 section
, key_name
, def
, buffer
);
728 ret
= strlen( buffer
);
732 ret
= PROFILE_GetSection( PROFILE_WineProfile
, section
, buffer
, len
, TRUE
, FALSE
);
734 LeaveCriticalSection( &PROFILE_CritSect
);
740 /***********************************************************************
741 * PROFILE_GetWineIniInt
743 * Get a config integer from the wine.ini file.
745 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
753 EnterCriticalSection( &PROFILE_CritSect
);
755 key
= PROFILE_Find( &PROFILE_WineProfile
, section
, key_name
, FALSE
);
756 if (!key
|| !key
->value
) {
759 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
760 result
= strtol( buffer
, &p
, 0 );
761 ret
= (p
== buffer
) ? 0 /* No digits at all */ : (int)result
;
764 LeaveCriticalSection( &PROFILE_CritSect
);
770 /******************************************************************************
772 * int PROFILE_EnumerateWineIniSection(
773 * char const *section, #Name of the section to enumerate
774 * void (*cbfn)(char const *key, char const *value, void *user),
775 * # Address of the callback function
776 * void *user ) # User-specified pointer.
778 * For each entry in a section in the wine.conf file, this function will
779 * call the specified callback function, informing it of each key and
780 * value. An optional user pointer may be passed to it (if this is not
781 * needed, pass NULL through it and ignore the value in the callback
784 * The callback function must accept three parameters:
785 * The name of the key (char const *)
786 * The value of the key (char const *)
787 * A user-specified parameter (void *)
788 * Note that the first two are char CONST *'s, not char *'s! The callback
789 * MUST not modify these strings!
791 * The return value indicates the number of times the callback function
794 int PROFILE_EnumerateWineIniSection(
796 void (*cbfn
)(char const *, char const *, void *),
799 PROFILESECTION
*scansect
;
803 EnterCriticalSection( &PROFILE_CritSect
);
805 /* Search for the correct section */
806 for(scansect
= PROFILE_WineProfile
; scansect
; scansect
= scansect
->next
) {
807 if(scansect
->name
&& !strcasecmp(scansect
->name
, section
)) {
809 /* Enumerate each key with the callback */
810 for(scankey
= scansect
->key
; scankey
; scankey
= scankey
->next
) {
812 /* Ignore blank entries -- these shouldn't exist, but let's
814 if (!scankey
->name
[0]) continue;
815 if (!scankey
->value
) cbfn(scankey
->name
, NULL
, userptr
);
819 PROFILE_CopyEntry(value
, scankey
->value
, sizeof(value
), TRUE
);
820 cbfn(scankey
->name
, value
, userptr
);
828 LeaveCriticalSection( &PROFILE_CritSect
);
834 /******************************************************************************
836 * int PROFILE_GetWineIniBool(
837 * char const *section,
838 * char const *key_name,
841 * Reads a boolean value from the wine.ini file. This function attempts to
842 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
843 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
844 * true. Anything else results in the return of the default value.
846 * This function uses 1 to indicate true, and 0 for false. You can check
847 * for existence by setting def to something other than 0 or 1 and
848 * examining the return value.
850 int PROFILE_GetWineIniBool(
852 char const *key_name
,
858 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
860 switch(key_value
[0]) {
881 TRACE("(\"%s\", \"%s\", %s), "
882 "[%c], ret %s.\n", section
, key_name
,
883 def
? "TRUE" : "FALSE", key_value
[0],
884 retval
? "TRUE" : "FALSE");
890 /***********************************************************************
891 * PROFILE_LoadWineIni
893 * Load the wine.ini file.
895 int PROFILE_LoadWineIni(void)
897 char buffer
[MAX_PATHNAME_LEN
];
901 InitializeCriticalSection( &PROFILE_CritSect
);
902 MakeCriticalSectionGlobal( &PROFILE_CritSect
);
904 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
906 /* Open -config specified file */
907 PROFILE_WineProfile
= PROFILE_Load ( f
);
909 strncpy(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
-1);
913 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
915 PROFILE_WineProfile
= PROFILE_Load( f
);
917 strncpy(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
-1);
920 if ((p
= getenv( "HOME" )) != NULL
)
922 lstrcpynA(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
923 strcat( buffer
, PROFILE_WineIniName
);
924 if ((f
= fopen( buffer
, "r" )) != NULL
)
926 PROFILE_WineProfile
= PROFILE_Load( f
);
928 strncpy(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
-1);
932 else WARN("could not get $HOME value for config file.\n" );
934 /* Try global file */
936 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
938 PROFILE_WineProfile
= PROFILE_Load( f
);
940 strncpy(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
-1);
943 MESSAGE( "Can't open configuration file %s or $HOME%s\n",
944 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
949 /***********************************************************************
950 * PROFILE_UsageWineIni
952 * Explain the wine.ini file to those who don't read documentation.
953 * Keep below one screenful in length so that error messages above are
956 void PROFILE_UsageWineIni(void)
958 MESSAGE("Perhaps you have not properly edited or created "
959 "your Wine configuration file.\n");
960 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
961 MESSAGE(" or it is determined by the -config option or from\n"
962 " the WINE_INI environment variable.\n");
963 if (*PROFILE_WineIniUsed
)
964 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
965 /* RTFM, so to say */
968 /***********************************************************************
969 * PROFILE_GetStringItem
971 * Convenience function that turns a string 'xxx, yyy, zzz' into
972 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
974 char* PROFILE_GetStringItem( char* start
)
978 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
982 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
984 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
986 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
989 if( lpch
) *lpch
= '\0';
993 /********************* API functions **********************************/
995 /***********************************************************************
996 * GetProfileInt16 (KERNEL.57)
998 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
1000 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
1004 /***********************************************************************
1005 * GetProfileInt32A (KERNEL32.264)
1007 UINT WINAPI
GetProfileIntA( LPCSTR section
, LPCSTR entry
, INT def_val
)
1009 return GetPrivateProfileIntA( section
, entry
, def_val
, "win.ini" );
1012 /***********************************************************************
1013 * GetProfileInt32W (KERNEL32.264)
1015 UINT WINAPI
GetProfileIntW( LPCWSTR section
, LPCWSTR entry
, INT def_val
)
1017 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1018 return GetPrivateProfileIntW( section
, entry
, def_val
, wininiW
);
1021 /***********************************************************************
1022 * GetProfileString16 (KERNEL.58)
1024 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1025 LPSTR buffer
, UINT16 len
)
1027 return GetPrivateProfileString16( section
, entry
, def_val
,
1028 buffer
, len
, "win.ini" );
1031 /***********************************************************************
1032 * GetProfileString32A (KERNEL32.268)
1034 INT WINAPI
GetProfileStringA( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1035 LPSTR buffer
, UINT len
)
1037 return GetPrivateProfileStringA( section
, entry
, def_val
,
1038 buffer
, len
, "win.ini" );
1041 /***********************************************************************
1042 * GetProfileString32W (KERNEL32.269)
1044 INT WINAPI
GetProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1045 LPCWSTR def_val
, LPWSTR buffer
, UINT len
)
1047 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1048 return GetPrivateProfileStringW( section
, entry
, def_val
,
1049 buffer
, len
, wininiW
);
1052 /***********************************************************************
1053 * WriteProfileString16 (KERNEL.59)
1055 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1058 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1061 /***********************************************************************
1062 * WriteProfileString32A (KERNEL32.587)
1064 BOOL WINAPI
WriteProfileStringA( LPCSTR section
, LPCSTR entry
,
1067 return WritePrivateProfileStringA( section
, entry
, string
, "win.ini" );
1070 /***********************************************************************
1071 * WriteProfileString32W (KERNEL32.588)
1073 BOOL WINAPI
WriteProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1076 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1077 return WritePrivateProfileStringW( section
, entry
, string
, wininiW
);
1081 /***********************************************************************
1082 * GetPrivateProfileInt16 (KERNEL.127)
1084 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1085 INT16 def_val
, LPCSTR filename
)
1087 long result
=(long)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
1089 if (result
> 65535) return 65535;
1090 if (result
>= 0) return (UINT16
)result
;
1091 if (result
< -32768) return -32768;
1092 return (UINT16
)(INT16
)result
;
1095 /***********************************************************************
1096 * GetPrivateProfileInt32A (KERNEL32.251)
1098 UINT WINAPI
GetPrivateProfileIntA( LPCSTR section
, LPCSTR entry
,
1099 INT def_val
, LPCSTR filename
)
1105 GetPrivateProfileStringA( section
, entry
, "",
1106 buffer
, sizeof(buffer
), filename
);
1107 if (!buffer
[0]) return (UINT
)def_val
;
1108 result
= strtol( buffer
, &p
, 0 );
1109 if (p
== buffer
) return 0; /* No digits at all */
1110 return (UINT
)result
;
1113 /***********************************************************************
1114 * GetPrivateProfileInt32W (KERNEL32.252)
1116 UINT WINAPI
GetPrivateProfileIntW( LPCWSTR section
, LPCWSTR entry
,
1117 INT def_val
, LPCWSTR filename
)
1119 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1120 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1121 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1122 UINT res
= GetPrivateProfileIntA(sectionA
, entryA
, def_val
, filenameA
);
1123 HeapFree( GetProcessHeap(), 0, sectionA
);
1124 HeapFree( GetProcessHeap(), 0, filenameA
);
1125 HeapFree( GetProcessHeap(), 0, entryA
);
1129 /***********************************************************************
1130 * GetPrivateProfileString16 (KERNEL.128)
1132 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1133 LPCSTR def_val
, LPSTR buffer
,
1134 UINT16 len
, LPCSTR filename
)
1136 return GetPrivateProfileStringA(section
,entry
,def_val
,buffer
,len
,filename
);
1139 /***********************************************************************
1140 * GetPrivateProfileString32A (KERNEL32.255)
1142 INT WINAPI
GetPrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1143 LPCSTR def_val
, LPSTR buffer
,
1144 UINT len
, LPCSTR filename
)
1149 filename
= "win.ini";
1151 EnterCriticalSection( &PROFILE_CritSect
);
1153 if (PROFILE_Open( filename
)) {
1154 ret
= PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1156 lstrcpynA( buffer
, def_val
, len
);
1157 ret
= strlen( buffer
);
1160 LeaveCriticalSection( &PROFILE_CritSect
);
1165 /***********************************************************************
1166 * GetPrivateProfileString32W (KERNEL32.256)
1168 INT WINAPI
GetPrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1169 LPCWSTR def_val
, LPWSTR buffer
,
1170 UINT len
, LPCWSTR filename
)
1172 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1173 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1174 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1175 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1176 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1177 INT ret
= GetPrivateProfileStringA( sectionA
, entryA
, def_valA
,
1178 bufferA
, len
, filenameA
);
1179 lstrcpynAtoW( buffer
, bufferA
, len
);
1180 HeapFree( GetProcessHeap(), 0, sectionA
);
1181 HeapFree( GetProcessHeap(), 0, entryA
);
1182 HeapFree( GetProcessHeap(), 0, filenameA
);
1183 HeapFree( GetProcessHeap(), 0, def_valA
);
1184 HeapFree( GetProcessHeap(), 0, bufferA
);
1188 /***********************************************************************
1189 * GetPrivateProfileSection16 (KERNEL.418)
1191 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
1192 UINT16 len
, LPCSTR filename
)
1194 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
1197 /***********************************************************************
1198 * GetPrivateProfileSection32A (KERNEL32.255)
1200 INT WINAPI
GetPrivateProfileSectionA( LPCSTR section
, LPSTR buffer
,
1201 DWORD len
, LPCSTR filename
)
1205 EnterCriticalSection( &PROFILE_CritSect
);
1207 if (PROFILE_Open( filename
))
1208 ret
= PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1211 LeaveCriticalSection( &PROFILE_CritSect
);
1216 /***********************************************************************
1217 * GetPrivateProfileSection32W (KERNEL32.256)
1220 INT WINAPI
GetPrivateProfileSectionW (LPCWSTR section
, LPWSTR buffer
,
1221 DWORD len
, LPCWSTR filename
)
1224 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1225 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1226 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1227 INT ret
= GetPrivateProfileSectionA( sectionA
, bufferA
, len
,
1229 MultiByteToWideChar(CP_ACP
,0,bufferA
,ret
,buffer
,len
);
1230 HeapFree( GetProcessHeap(), 0, sectionA
);
1231 HeapFree( GetProcessHeap(), 0, filenameA
);
1232 HeapFree( GetProcessHeap(), 0, bufferA
);
1236 /***********************************************************************
1237 * GetProfileSection16 (KERNEL.419)
1239 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
1241 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
1244 /***********************************************************************
1245 * GetProfileSection32A (KERNEL32.268)
1247 INT WINAPI
GetProfileSectionA( LPCSTR section
, LPSTR buffer
, DWORD len
)
1249 return GetPrivateProfileSectionA( section
, buffer
, len
, "win.ini" );
1252 /***********************************************************************
1253 * GetProfileSection32W (KERNEL32)
1255 INT WINAPI
GetProfileSectionW( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
1257 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1258 return GetPrivateProfileSectionW( section
, buffer
, len
, wininiW
);
1262 /***********************************************************************
1263 * WritePrivateProfileString16 (KERNEL.129)
1265 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1266 LPCSTR string
, LPCSTR filename
)
1268 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
1271 /***********************************************************************
1272 * WritePrivateProfileString32A (KERNEL32.582)
1274 BOOL WINAPI
WritePrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1275 LPCSTR string
, LPCSTR filename
)
1279 EnterCriticalSection( &PROFILE_CritSect
);
1281 if (PROFILE_Open( filename
))
1283 if (!section
&& !entry
&& !string
)
1284 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1286 ret
= PROFILE_SetString( section
, entry
, string
);
1289 LeaveCriticalSection( &PROFILE_CritSect
);
1293 /***********************************************************************
1294 * WritePrivateProfileString32W (KERNEL32.583)
1296 BOOL WINAPI
WritePrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1297 LPCWSTR string
, LPCWSTR filename
)
1299 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1300 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1301 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1302 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1303 BOOL res
= WritePrivateProfileStringA( sectionA
, entryA
,
1304 stringA
, filenameA
);
1305 HeapFree( GetProcessHeap(), 0, sectionA
);
1306 HeapFree( GetProcessHeap(), 0, entryA
);
1307 HeapFree( GetProcessHeap(), 0, stringA
);
1308 HeapFree( GetProcessHeap(), 0, filenameA
);
1312 /***********************************************************************
1313 * WritePrivateProfileSection16 (KERNEL.416)
1315 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
1316 LPCSTR string
, LPCSTR filename
)
1318 return WritePrivateProfileSectionA( section
, string
, filename
);
1321 /***********************************************************************
1322 * WritePrivateProfileSection32A (KERNEL32)
1324 BOOL WINAPI
WritePrivateProfileSectionA( LPCSTR section
,
1325 LPCSTR string
, LPCSTR filename
)
1327 char *p
=(char*)string
;
1329 FIXME("WritePrivateProfileSection32A empty stub\n");
1330 if (TRACE_ON(profile
)) {
1331 TRACE("(%s) => [%s]\n", filename
, section
);
1342 /***********************************************************************
1343 * WritePrivateProfileSection32W (KERNEL32)
1345 BOOL WINAPI
WritePrivateProfileSectionW( LPCWSTR section
,
1346 LPCWSTR string
, LPCWSTR filename
)
1349 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1350 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1351 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1352 BOOL res
= WritePrivateProfileSectionA( sectionA
, stringA
, filenameA
);
1353 HeapFree( GetProcessHeap(), 0, sectionA
);
1354 HeapFree( GetProcessHeap(), 0, stringA
);
1355 HeapFree( GetProcessHeap(), 0, filenameA
);
1359 /***********************************************************************
1360 * WriteProfileSection16 (KERNEL.417)
1362 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
1364 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
1367 /***********************************************************************
1368 * WriteProfileSection32A (KERNEL32.747)
1370 BOOL WINAPI
WriteProfileSectionA( LPCSTR section
, LPCSTR keys_n_values
)
1373 return WritePrivateProfileSectionA( section
, keys_n_values
, "win.ini");
1376 /***********************************************************************
1377 * WriteProfileSection32W (KERNEL32.748)
1379 BOOL WINAPI
WriteProfileSectionW( LPCWSTR section
, LPCWSTR keys_n_values
)
1381 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini");
1383 return (WritePrivateProfileSectionW (section
,keys_n_values
, wininiW
));
1386 /***********************************************************************
1387 * GetPrivateProfileSectionNames16 (KERNEL.143)
1389 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1394 EnterCriticalSection( &PROFILE_CritSect
);
1396 if (PROFILE_Open( filename
))
1397 ret
= PROFILE_GetSectionNames(buffer
, size
);
1399 LeaveCriticalSection( &PROFILE_CritSect
);
1405 /***********************************************************************
1406 * GetProfileSectionNames16 (KERNEL.142)
1408 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1411 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1415 /***********************************************************************
1416 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1418 DWORD WINAPI
GetPrivateProfileSectionNamesA( LPSTR buffer
, DWORD size
,
1422 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1426 /***********************************************************************
1427 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1429 DWORD WINAPI
GetPrivateProfileSectionNamesW( LPWSTR buffer
, DWORD size
,
1433 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1434 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1436 INT ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1437 lstrcpynAtoW( buffer
, bufferA
, size
);
1438 HeapFree( GetProcessHeap(), 0, bufferA
);
1439 HeapFree( GetProcessHeap(), 0, filenameA
);
1444 /***********************************************************************
1445 * GetPrivateProfileStruct16 (KERNEL.407)
1447 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
1448 LPVOID buf
, UINT16 len
, LPCSTR filename
)
1450 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
1453 /***********************************************************************
1454 * GetPrivateProfileStruct32A (KERNEL32.370)
1456 BOOL WINAPI
GetPrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1457 LPVOID buf
, UINT len
, LPCSTR filename
)
1461 EnterCriticalSection( &PROFILE_CritSect
);
1463 if (PROFILE_Open( filename
)) {
1464 PROFILEKEY
*k
= PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1466 lstrcpynA( buf
, k
->value
, strlen(k
->value
));
1470 LeaveCriticalSection( &PROFILE_CritSect
);
1475 /***********************************************************************
1476 * GetPrivateProfileStruct32W (KERNEL32.543)
1478 BOOL WINAPI
GetPrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1479 LPVOID buffer
, UINT len
, LPCWSTR filename
)
1481 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1482 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1483 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1484 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1486 INT ret
= GetPrivateProfileStructA( sectionA
, keyA
, bufferA
,
1488 lstrcpynAtoW( buffer
, bufferA
, len
);
1489 HeapFree( GetProcessHeap(), 0, bufferA
);
1490 HeapFree( GetProcessHeap(), 0, sectionA
);
1491 HeapFree( GetProcessHeap(), 0, keyA
);
1492 HeapFree( GetProcessHeap(), 0, filenameA
);
1499 /***********************************************************************
1500 * WritePrivateProfileStruct16 (KERNEL.406)
1502 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
1503 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
1505 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
1508 /***********************************************************************
1509 * WritePrivateProfileStruct32A (KERNEL32.744)
1511 BOOL WINAPI
WritePrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1512 LPVOID buf
, UINT bufsize
, LPCSTR filename
)
1516 if (!section
&& !key
&& !buf
) /* flush the cache */
1517 return WritePrivateProfileStringA( NULL
, NULL
, NULL
, filename
);
1519 EnterCriticalSection( &PROFILE_CritSect
);
1521 if (PROFILE_Open( filename
))
1522 ret
= PROFILE_SetString( section
, key
, buf
);
1524 LeaveCriticalSection( &PROFILE_CritSect
);
1529 /***********************************************************************
1530 * WritePrivateProfileStruct32W (KERNEL32.544)
1532 BOOL WINAPI
WritePrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1533 LPVOID buf
, UINT bufsize
, LPCWSTR filename
)
1535 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1536 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1537 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1538 INT ret
= WritePrivateProfileStructA( sectionA
, keyA
, buf
, bufsize
,
1540 HeapFree( GetProcessHeap(), 0, sectionA
);
1541 HeapFree( GetProcessHeap(), 0, keyA
);
1542 HeapFree( GetProcessHeap(), 0, filenameA
);
1548 /***********************************************************************
1549 * WriteOutProfiles (KERNEL.315)
1551 void WINAPI
WriteOutProfiles16(void)
1553 EnterCriticalSection( &PROFILE_CritSect
);
1554 PROFILE_FlushFile();
1555 LeaveCriticalSection( &PROFILE_CritSect
);