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 /***********************************************************************
604 * Get a profile string.
606 static INT
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
607 LPCSTR def_val
, LPSTR buffer
, UINT len
)
609 PROFILEKEY
*key
= NULL
;
611 if (!def_val
) def_val
= "";
612 if (key_name
&& key_name
[0])
614 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
615 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
617 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
618 section
, key_name
, def_val
, buffer
);
619 return strlen( buffer
);
621 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
626 /***********************************************************************
629 * Set a profile string.
631 static BOOL
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
634 if (!key_name
) /* Delete a whole section */
636 TRACE(profile
, "('%s')\n", section_name
);
637 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
639 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
640 this is not an error on application's level.*/
642 else if (!value
) /* Delete a key */
644 TRACE(profile
, "('%s','%s')\n",
645 section_name
, key_name
);
646 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
647 section_name
, key_name
);
648 return TRUE
; /* same error handling as above */
650 else /* Set the key value */
652 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
654 TRACE(profile
, "('%s','%s','%s'): \n",
655 section_name
, key_name
, value
);
656 if (!key
) return FALSE
;
659 if (!strcmp( key
->value
, value
))
661 TRACE(profile
, " no change needed\n" );
662 return TRUE
; /* No change needed */
664 TRACE(profile
, " replacing '%s'\n", key
->value
);
665 HeapFree( SystemHeap
, 0, key
->value
);
667 else TRACE(profile
, " creating key\n" );
668 key
->value
= HEAP_strdupA( SystemHeap
, 0, value
);
669 CurProfile
->changed
= TRUE
;
675 /***********************************************************************
676 * PROFILE_GetWineIniString
678 * Get a config string from the wine.ini file.
680 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
681 const char *def
, char *buffer
, int len
)
685 EnterCriticalSection( &PROFILE_CritSect
);
689 PROFILEKEY
*key
= PROFILE_Find(&PROFILE_WineProfile
, section
, key_name
, FALSE
);
690 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
692 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
693 section
, key_name
, def
, buffer
);
694 ret
= strlen( buffer
);
698 ret
= PROFILE_GetSection( PROFILE_WineProfile
, section
, buffer
, len
, TRUE
, FALSE
);
700 LeaveCriticalSection( &PROFILE_CritSect
);
706 /***********************************************************************
707 * PROFILE_GetWineIniInt
709 * Get a config integer from the wine.ini file.
711 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
719 EnterCriticalSection( &PROFILE_CritSect
);
721 key
= PROFILE_Find( &PROFILE_WineProfile
, section
, key_name
, FALSE
);
722 if (!key
|| !key
->value
) {
725 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
726 result
= strtol( buffer
, &p
, 0 );
727 ret
= (p
== buffer
) ? 0 /* No digits at all */ : (int)result
;
730 LeaveCriticalSection( &PROFILE_CritSect
);
736 /******************************************************************************
738 * int PROFILE_EnumerateWineIniSection(
739 * char const *section, #Name of the section to enumerate
740 * void (*cbfn)(char const *key, char const *value, void *user),
741 * # Address of the callback function
742 * void *user ) # User-specified pointer.
744 * For each entry in a section in the wine.conf file, this function will
745 * call the specified callback function, informing it of each key and
746 * value. An optional user pointer may be passed to it (if this is not
747 * needed, pass NULL through it and ignore the value in the callback
750 * The callback function must accept three parameters:
751 * The name of the key (char const *)
752 * The value of the key (char const *)
753 * A user-specified parameter (void *)
754 * Note that the first two are char CONST *'s, not char *'s! The callback
755 * MUST not modify these strings!
757 * The return value indicates the number of times the callback function
760 int PROFILE_EnumerateWineIniSection(
762 void (*cbfn
)(char const *, char const *, void *),
765 PROFILESECTION
*scansect
;
769 EnterCriticalSection( &PROFILE_CritSect
);
771 /* Search for the correct section */
772 for(scansect
= PROFILE_WineProfile
; scansect
; scansect
= scansect
->next
) {
773 if(scansect
->name
&& !strcasecmp(scansect
->name
, section
)) {
775 /* Enumerate each key with the callback */
776 for(scankey
= scansect
->key
; scankey
; scankey
= scankey
->next
) {
778 /* Ignore blank entries -- these shouldn't exist, but let's
780 if(scankey
->name
[0]) {
781 cbfn(scankey
->name
, scankey
->value
, userptr
);
789 LeaveCriticalSection( &PROFILE_CritSect
);
795 /******************************************************************************
797 * int PROFILE_GetWineIniBool(
798 * char const *section,
799 * char const *key_name,
802 * Reads a boolean value from the wine.ini file. This function attempts to
803 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
804 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
805 * true. Anything else results in the return of the default value.
807 * This function uses 1 to indicate true, and 0 for false. You can check
808 * for existence by setting def to something other than 0 or 1 and
809 * examining the return value.
811 int PROFILE_GetWineIniBool(
813 char const *key_name
,
819 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
821 switch(key_value
[0]) {
842 TRACE(profile
, "(\"%s\", \"%s\", %s), "
843 "[%c], ret %s.\n", section
, key_name
,
844 def
? "TRUE" : "FALSE", key_value
[0],
845 retval
? "TRUE" : "FALSE");
851 /***********************************************************************
852 * PROFILE_LoadWineIni
854 * Load the wine.ini file.
856 int PROFILE_LoadWineIni(void)
858 char buffer
[MAX_PATHNAME_LEN
];
862 InitializeCriticalSection( &PROFILE_CritSect
);
863 MakeCriticalSectionGlobal( &PROFILE_CritSect
);
865 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
867 /* Open -config specified file */
868 PROFILE_WineProfile
= PROFILE_Load ( f
);
870 strncpy(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
-1);
874 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
876 PROFILE_WineProfile
= PROFILE_Load( f
);
878 strncpy(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
-1);
881 if ((p
= getenv( "HOME" )) != NULL
)
883 lstrcpynA(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
884 strcat( buffer
, PROFILE_WineIniName
);
885 if ((f
= fopen( buffer
, "r" )) != NULL
)
887 PROFILE_WineProfile
= PROFILE_Load( f
);
889 strncpy(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
-1);
893 else WARN(profile
, "could not get $HOME value for config file.\n" );
895 /* Try global file */
897 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
899 PROFILE_WineProfile
= PROFILE_Load( f
);
901 strncpy(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
-1);
904 MSG( "Can't open configuration file %s or $HOME%s\n",
905 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
910 /***********************************************************************
911 * PROFILE_UsageWineIni
913 * Explain the wine.ini file to those who don't read documentation.
914 * Keep below one screenful in length so that error messages above are
917 void PROFILE_UsageWineIni(void)
919 MSG("Perhaps you have not properly edited or created "
920 "your Wine configuration file.\n");
921 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
922 MSG(" or it is determined by the -config option or from\n"
923 " the WINE_INI environment variable.\n");
924 if (*PROFILE_WineIniUsed
)
925 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
926 /* RTFM, so to say */
929 /***********************************************************************
930 * PROFILE_GetStringItem
932 * Convenience function that turns a string 'xxx, yyy, zzz' into
933 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
935 char* PROFILE_GetStringItem( char* start
)
939 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
943 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
945 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
947 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
950 if( lpch
) *lpch
= '\0';
954 /********************* API functions **********************************/
956 /***********************************************************************
957 * GetProfileInt16 (KERNEL.57)
959 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
961 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
965 /***********************************************************************
966 * GetProfileInt32A (KERNEL32.264)
968 UINT WINAPI
GetProfileIntA( LPCSTR section
, LPCSTR entry
, INT def_val
)
970 return GetPrivateProfileIntA( section
, entry
, def_val
, "win.ini" );
973 /***********************************************************************
974 * GetProfileInt32W (KERNEL32.264)
976 UINT WINAPI
GetProfileIntW( LPCWSTR section
, LPCWSTR entry
, INT def_val
)
978 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
979 return GetPrivateProfileIntW( section
, entry
, def_val
, wininiW
);
982 /***********************************************************************
983 * GetProfileString16 (KERNEL.58)
985 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
986 LPSTR buffer
, UINT16 len
)
988 return GetPrivateProfileString16( section
, entry
, def_val
,
989 buffer
, len
, "win.ini" );
992 /***********************************************************************
993 * GetProfileString32A (KERNEL32.268)
995 INT WINAPI
GetProfileStringA( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
996 LPSTR buffer
, UINT len
)
998 return GetPrivateProfileStringA( section
, entry
, def_val
,
999 buffer
, len
, "win.ini" );
1002 /***********************************************************************
1003 * GetProfileString32W (KERNEL32.269)
1005 INT WINAPI
GetProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1006 LPCWSTR def_val
, LPWSTR buffer
, UINT len
)
1008 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1009 return GetPrivateProfileStringW( section
, entry
, def_val
,
1010 buffer
, len
, wininiW
);
1013 /***********************************************************************
1014 * WriteProfileString16 (KERNEL.59)
1016 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1019 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1022 /***********************************************************************
1023 * WriteProfileString32A (KERNEL32.587)
1025 BOOL WINAPI
WriteProfileStringA( LPCSTR section
, LPCSTR entry
,
1028 return WritePrivateProfileStringA( section
, entry
, string
, "win.ini" );
1031 /***********************************************************************
1032 * WriteProfileString32W (KERNEL32.588)
1034 BOOL WINAPI
WriteProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1037 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1038 return WritePrivateProfileStringW( section
, entry
, string
, wininiW
);
1042 /***********************************************************************
1043 * GetPrivateProfileInt16 (KERNEL.127)
1045 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1046 INT16 def_val
, LPCSTR filename
)
1048 long result
=(long)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
1050 if (result
> 65535) return 65535;
1051 if (result
>= 0) return (UINT16
)result
;
1052 if (result
< -32768) return -32768;
1053 return (UINT16
)(INT16
)result
;
1056 /***********************************************************************
1057 * GetPrivateProfileInt32A (KERNEL32.251)
1059 UINT WINAPI
GetPrivateProfileIntA( LPCSTR section
, LPCSTR entry
,
1060 INT def_val
, LPCSTR filename
)
1066 GetPrivateProfileStringA( section
, entry
, "",
1067 buffer
, sizeof(buffer
), filename
);
1068 if (!buffer
[0]) return (UINT
)def_val
;
1069 result
= strtol( buffer
, &p
, 0 );
1070 if (p
== buffer
) return 0; /* No digits at all */
1071 return (UINT
)result
;
1074 /***********************************************************************
1075 * GetPrivateProfileInt32W (KERNEL32.252)
1077 UINT WINAPI
GetPrivateProfileIntW( LPCWSTR section
, LPCWSTR entry
,
1078 INT def_val
, LPCWSTR filename
)
1080 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1081 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1082 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1083 UINT res
= GetPrivateProfileIntA(sectionA
, entryA
, def_val
, filenameA
);
1084 HeapFree( GetProcessHeap(), 0, sectionA
);
1085 HeapFree( GetProcessHeap(), 0, filenameA
);
1086 HeapFree( GetProcessHeap(), 0, entryA
);
1090 /***********************************************************************
1091 * GetPrivateProfileString16 (KERNEL.128)
1093 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1094 LPCSTR def_val
, LPSTR buffer
,
1095 UINT16 len
, LPCSTR filename
)
1097 return GetPrivateProfileStringA(section
,entry
,def_val
,buffer
,len
,filename
);
1100 /***********************************************************************
1101 * GetPrivateProfileString32A (KERNEL32.255)
1103 INT WINAPI
GetPrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1104 LPCSTR def_val
, LPSTR buffer
,
1105 UINT len
, LPCSTR filename
)
1110 filename
= "win.ini";
1112 EnterCriticalSection( &PROFILE_CritSect
);
1114 if (PROFILE_Open( filename
)) {
1115 ret
= PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1117 lstrcpynA( buffer
, def_val
, len
);
1118 ret
= strlen( buffer
);
1121 LeaveCriticalSection( &PROFILE_CritSect
);
1126 /***********************************************************************
1127 * GetPrivateProfileString32W (KERNEL32.256)
1129 INT WINAPI
GetPrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1130 LPCWSTR def_val
, LPWSTR buffer
,
1131 UINT len
, LPCWSTR filename
)
1133 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1134 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1135 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1136 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1137 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1138 INT ret
= GetPrivateProfileStringA( sectionA
, entryA
, def_valA
,
1139 bufferA
, len
, filenameA
);
1140 lstrcpynAtoW( buffer
, bufferA
, len
);
1141 HeapFree( GetProcessHeap(), 0, sectionA
);
1142 HeapFree( GetProcessHeap(), 0, entryA
);
1143 HeapFree( GetProcessHeap(), 0, filenameA
);
1144 HeapFree( GetProcessHeap(), 0, def_valA
);
1145 HeapFree( GetProcessHeap(), 0, bufferA
);
1149 /***********************************************************************
1150 * GetPrivateProfileSection16 (KERNEL.418)
1152 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
1153 UINT16 len
, LPCSTR filename
)
1155 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
1158 /***********************************************************************
1159 * GetPrivateProfileSection32A (KERNEL32.255)
1161 INT WINAPI
GetPrivateProfileSectionA( LPCSTR section
, LPSTR buffer
,
1162 DWORD len
, LPCSTR filename
)
1166 EnterCriticalSection( &PROFILE_CritSect
);
1168 if (PROFILE_Open( filename
))
1169 ret
= PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1172 LeaveCriticalSection( &PROFILE_CritSect
);
1177 /***********************************************************************
1178 * GetPrivateProfileSection32W (KERNEL32.256)
1181 INT WINAPI
GetPrivateProfileSectionW (LPCWSTR section
, LPWSTR buffer
,
1182 DWORD len
, LPCWSTR filename
)
1185 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1186 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1187 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1188 INT ret
= GetPrivateProfileSectionA( sectionA
, bufferA
, len
,
1190 MultiByteToWideChar(CP_ACP
,0,bufferA
,ret
,buffer
,len
);
1191 HeapFree( GetProcessHeap(), 0, sectionA
);
1192 HeapFree( GetProcessHeap(), 0, filenameA
);
1193 HeapFree( GetProcessHeap(), 0, bufferA
);
1197 /***********************************************************************
1198 * GetProfileSection16 (KERNEL.419)
1200 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
1202 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
1205 /***********************************************************************
1206 * GetProfileSection32A (KERNEL32.268)
1208 INT WINAPI
GetProfileSectionA( LPCSTR section
, LPSTR buffer
, DWORD len
)
1210 return GetPrivateProfileSectionA( section
, buffer
, len
, "win.ini" );
1213 /***********************************************************************
1214 * GetProfileSection32W (KERNEL32)
1216 INT WINAPI
GetProfileSectionW( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
1218 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1219 return GetPrivateProfileSectionW( section
, buffer
, len
, wininiW
);
1223 /***********************************************************************
1224 * WritePrivateProfileString16 (KERNEL.129)
1226 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1227 LPCSTR string
, LPCSTR filename
)
1229 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
1232 /***********************************************************************
1233 * WritePrivateProfileString32A (KERNEL32.582)
1235 BOOL WINAPI
WritePrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1236 LPCSTR string
, LPCSTR filename
)
1240 EnterCriticalSection( &PROFILE_CritSect
);
1242 if (!PROFILE_Open( filename
)) {
1244 } else if (!section
) {
1245 ret
= PROFILE_FlushFile();
1247 ret
= PROFILE_SetString( section
, entry
, string
);
1250 LeaveCriticalSection( &PROFILE_CritSect
);
1255 /***********************************************************************
1256 * WritePrivateProfileString32W (KERNEL32.583)
1258 BOOL WINAPI
WritePrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1259 LPCWSTR string
, LPCWSTR filename
)
1261 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1262 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1263 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1264 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1265 BOOL res
= WritePrivateProfileStringA( sectionA
, entryA
,
1266 stringA
, filenameA
);
1267 HeapFree( GetProcessHeap(), 0, sectionA
);
1268 HeapFree( GetProcessHeap(), 0, entryA
);
1269 HeapFree( GetProcessHeap(), 0, stringA
);
1270 HeapFree( GetProcessHeap(), 0, filenameA
);
1274 /***********************************************************************
1275 * WritePrivateProfileSection16 (KERNEL.416)
1277 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
1278 LPCSTR string
, LPCSTR filename
)
1280 return WritePrivateProfileSectionA( section
, string
, filename
);
1283 /***********************************************************************
1284 * WritePrivateProfileSection32A (KERNEL32)
1286 BOOL WINAPI
WritePrivateProfileSectionA( LPCSTR section
,
1287 LPCSTR string
, LPCSTR filename
)
1289 char *p
=(char*)string
;
1291 FIXME(profile
, "WritePrivateProfileSection32A empty stub\n");
1292 if (TRACE_ON(profile
)) {
1293 TRACE(profile
, "(%s) => [%s]\n", filename
, section
);
1295 TRACE(profile
, "%s\n", p
);
1304 /***********************************************************************
1305 * WritePrivateProfileSection32W (KERNEL32)
1307 BOOL WINAPI
WritePrivateProfileSectionW( LPCWSTR section
,
1308 LPCWSTR string
, LPCWSTR filename
)
1311 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1312 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1313 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1314 BOOL res
= WritePrivateProfileSectionA( sectionA
, stringA
, filenameA
);
1315 HeapFree( GetProcessHeap(), 0, sectionA
);
1316 HeapFree( GetProcessHeap(), 0, stringA
);
1317 HeapFree( GetProcessHeap(), 0, filenameA
);
1321 /***********************************************************************
1322 * WriteProfileSection16 (KERNEL.417)
1324 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
1326 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
1329 /***********************************************************************
1330 * WriteProfileSection32A (KERNEL32.747)
1332 BOOL WINAPI
WriteProfileSectionA( LPCSTR section
, LPCSTR keys_n_values
)
1335 return WritePrivateProfileSectionA( section
, keys_n_values
, "win.ini");
1338 /***********************************************************************
1339 * WriteProfileSection32W (KERNEL32.748)
1341 BOOL WINAPI
WriteProfileSectionW( LPCWSTR section
, LPCWSTR keys_n_values
)
1343 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini");
1345 return (WritePrivateProfileSectionW (section
,keys_n_values
, wininiW
));
1348 /***********************************************************************
1349 * GetPrivateProfileSectionNames16 (KERNEL.143)
1351 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1356 PROFILESECTION
*section
;
1359 EnterCriticalSection( &PROFILE_CritSect
);
1361 if (PROFILE_Open( filename
)) {
1364 section
= CurProfile
->section
;
1365 for ( ; section
; section
= section
->next
)
1366 if (section
->name
) {
1367 l
= strlen (section
->name
);
1369 if (cursize
> size
+1) {
1370 LeaveCriticalSection( &PROFILE_CritSect
);
1373 strcpy (buf
,section
->name
);
1383 LeaveCriticalSection( &PROFILE_CritSect
);
1389 /***********************************************************************
1390 * GetProfileSectionNames16 (KERNEL.142)
1392 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1395 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1399 /***********************************************************************
1400 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1402 DWORD WINAPI
GetPrivateProfileSectionNamesA( LPSTR buffer
, DWORD size
,
1406 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1410 /***********************************************************************
1411 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1413 DWORD WINAPI
GetPrivateProfileSectionNamesW( LPWSTR buffer
, DWORD size
,
1417 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1418 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1420 INT ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1421 lstrcpynAtoW( buffer
, bufferA
, size
);
1422 HeapFree( GetProcessHeap(), 0, bufferA
);
1423 HeapFree( GetProcessHeap(), 0, filenameA
);
1428 /***********************************************************************
1429 * GetPrivateProfileStruct16 (KERNEL.407)
1431 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
1432 LPVOID buf
, UINT16 len
, LPCSTR filename
)
1434 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
1437 /***********************************************************************
1438 * GetPrivateProfileStruct32A (KERNEL32.370)
1440 BOOL WINAPI
GetPrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1441 LPVOID buf
, UINT len
, LPCSTR filename
)
1445 EnterCriticalSection( &PROFILE_CritSect
);
1447 if (PROFILE_Open( filename
)) {
1448 PROFILEKEY
*k
= PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1450 lstrcpynA( buf
, k
->value
, strlen(k
->value
));
1454 LeaveCriticalSection( &PROFILE_CritSect
);
1459 /***********************************************************************
1460 * GetPrivateProfileStruct32W (KERNEL32.543)
1462 BOOL WINAPI
GetPrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1463 LPVOID buffer
, UINT len
, LPCWSTR filename
)
1465 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1466 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1467 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1468 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1470 INT ret
= GetPrivateProfileStructA( sectionA
, keyA
, bufferA
,
1472 lstrcpynAtoW( buffer
, bufferA
, len
);
1473 HeapFree( GetProcessHeap(), 0, bufferA
);
1474 HeapFree( GetProcessHeap(), 0, sectionA
);
1475 HeapFree( GetProcessHeap(), 0, keyA
);
1476 HeapFree( GetProcessHeap(), 0, filenameA
);
1483 /***********************************************************************
1484 * WritePrivateProfileStruct16 (KERNEL.406)
1486 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
1487 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
1489 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
1492 /***********************************************************************
1493 * WritePrivateProfileStruct32A (KERNEL32.744)
1495 BOOL WINAPI
WritePrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1496 LPVOID buf
, UINT bufsize
, LPCSTR filename
)
1500 EnterCriticalSection( &PROFILE_CritSect
);
1502 if ((!section
) && (!key
) && (!buf
)) { /* flush the cache */
1503 PROFILE_FlushFile();
1506 if (!PROFILE_Open( filename
))
1509 ret
= PROFILE_SetString( section
, key
, buf
);
1512 LeaveCriticalSection( &PROFILE_CritSect
);
1517 /***********************************************************************
1518 * WritePrivateProfileStruct32W (KERNEL32.544)
1520 BOOL WINAPI
WritePrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1521 LPVOID buf
, UINT bufsize
, LPCWSTR filename
)
1523 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1524 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1525 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1526 INT ret
= WritePrivateProfileStructA( sectionA
, keyA
, buf
, bufsize
,
1528 HeapFree( GetProcessHeap(), 0, sectionA
);
1529 HeapFree( GetProcessHeap(), 0, keyA
);
1530 HeapFree( GetProcessHeap(), 0, filenameA
);
1536 /***********************************************************************
1537 * WriteOutProfiles (KERNEL.315)
1539 void WINAPI
WriteOutProfiles16(void)
1541 EnterCriticalSection( &PROFILE_CritSect
);
1542 PROFILE_FlushFile();
1543 LeaveCriticalSection( &PROFILE_CritSect
);