4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
15 #include "wine/winbase16.h"
22 DEFAULT_DEBUG_CHANNEL(profile
)
24 typedef struct tagPROFILEKEY
28 struct tagPROFILEKEY
*next
;
31 typedef struct tagPROFILESECTION
34 struct tagPROFILEKEY
*key
;
35 struct tagPROFILESECTION
*next
;
42 PROFILESECTION
*section
;
50 #define N_CACHED_PROFILES 10
52 /* Cached profile files */
53 static PROFILE
*MRUProfile
[N_CACHED_PROFILES
]={NULL
};
55 #define CurProfile (MRUProfile[0])
57 /* wine.ini profile content */
58 static PROFILESECTION
*PROFILE_WineProfile
;
60 #define PROFILE_MAX_LINE_LEN 1024
62 /* Wine profile name in $HOME directory; must begin with slash */
63 static const char PROFILE_WineIniName
[] = "/.winerc";
65 /* Wine profile: the profile file being used */
66 static char PROFILE_WineIniUsed
[MAX_PATHNAME_LEN
] = "";
68 /* Check for comments in profile */
69 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
71 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
73 static LPCWSTR wininiW
= NULL
;
75 static CRITICAL_SECTION PROFILE_CritSect
;
77 /***********************************************************************
80 * Copy the content of an entry into a buffer, removing quotes, and possibly
81 * translating environment variables.
83 static void PROFILE_CopyEntry( char *buffer
, const char *value
, int len
,
89 if ((*value
== '\'') || (*value
== '\"'))
91 if (value
[1] && (value
[strlen(value
)-1] == *value
)) quote
= *value
++;
96 lstrcpynA( buffer
, value
, len
);
97 if (quote
&& (len
>= strlen(value
))) buffer
[strlen(buffer
)-1] = '\0';
101 for (p
= value
; (*p
&& (len
> 1)); *buffer
++ = *p
++, len
-- )
103 if ((*p
== '$') && (p
[1] == '{'))
107 const char *p2
= strchr( p
, '}' );
108 if (!p2
) continue; /* ignore it */
109 lstrcpynA(env_val
, p
+ 2, MIN( sizeof(env_val
), (int)(p2
-p
)-1 ));
110 if ((env_p
= getenv( env_val
)) != NULL
)
112 lstrcpynA( buffer
, env_p
, len
);
113 buffer
+= strlen( buffer
);
114 len
-= strlen( buffer
);
123 /***********************************************************************
126 * Save a profile tree to a file.
128 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
132 for ( ; section
; section
= section
->next
)
134 if (section
->name
) fprintf( file
, "\r\n[%s]\r\n", section
->name
);
135 for (key
= section
->key
; key
; key
= key
->next
)
137 fprintf( file
, "%s", key
->name
);
138 if (key
->value
) fprintf( file
, "=%s", key
->value
);
139 fprintf( file
, "\r\n" );
145 /***********************************************************************
148 * Free a profile tree.
150 static void PROFILE_Free( PROFILESECTION
*section
)
152 PROFILESECTION
*next_section
;
153 PROFILEKEY
*key
, *next_key
;
155 for ( ; section
; section
= next_section
)
157 if (section
->name
) HeapFree( SystemHeap
, 0, section
->name
);
158 for (key
= section
->key
; key
; key
= next_key
)
160 next_key
= key
->next
;
161 if (key
->name
) HeapFree( SystemHeap
, 0, key
->name
);
162 if (key
->value
) HeapFree( SystemHeap
, 0, key
->value
);
163 HeapFree( SystemHeap
, 0, key
);
165 next_section
= section
->next
;
166 HeapFree( SystemHeap
, 0, section
);
171 PROFILE_isspace(char c
) {
172 if (isspace(c
)) return 1;
173 if (c
=='\r' || c
==0x1a) return 1;
174 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
179 /***********************************************************************
182 * Load a profile tree from a file.
184 static PROFILESECTION
*PROFILE_Load( FILE *file
)
186 char buffer
[PROFILE_MAX_LINE_LEN
];
189 PROFILESECTION
*section
, *first_section
;
190 PROFILESECTION
**next_section
;
191 PROFILEKEY
*key
, *prev_key
, **next_key
;
193 first_section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
194 first_section
->name
= NULL
;
195 first_section
->key
= NULL
;
196 first_section
->next
= NULL
;
197 next_section
= &first_section
->next
;
198 next_key
= &first_section
->key
;
201 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
205 while (*p
&& PROFILE_isspace(*p
)) p
++;
206 if (*p
== '[') /* section start */
208 if (!(p2
= strrchr( p
, ']' )))
210 WARN(profile
, "Invalid section header at line %d: '%s'\n",
217 section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
218 section
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
220 section
->next
= NULL
;
221 *next_section
= section
;
222 next_section
= §ion
->next
;
223 next_key
= §ion
->key
;
226 TRACE(profile
, "New section: '%s'\n",section
->name
);
233 while ((p2
> p
) && ((*p2
== '\n') || PROFILE_isspace(*p2
))) *p2
--='\0';
235 if ((p2
= strchr( p
, '=' )) != NULL
)
238 while ((p3
> p
) && PROFILE_isspace(*p3
)) *p3
-- = '\0';
240 while (*p2
&& PROFILE_isspace(*p2
)) p2
++;
243 if(*p
|| !prev_key
|| *prev_key
->name
)
245 key
= HEAP_xalloc( SystemHeap
, 0, sizeof(*key
) );
246 key
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
247 key
->value
= p2
? HEAP_strdupA( SystemHeap
, 0, p2
) : NULL
;
250 next_key
= &key
->next
;
253 TRACE(profile
, "New key: name='%s', value='%s'\n",key
->name
,key
->value
?key
->value
:"(none)");
256 return first_section
;
260 /***********************************************************************
261 * PROFILE_DeleteSection
263 * Delete a section from a profile tree.
265 static BOOL
PROFILE_DeleteSection( PROFILESECTION
**section
, LPCSTR name
)
269 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, name
))
271 PROFILESECTION
*to_del
= *section
;
272 *section
= to_del
->next
;
274 PROFILE_Free( to_del
);
277 section
= &(*section
)->next
;
283 /***********************************************************************
286 * Delete a key from a profile tree.
288 static BOOL
PROFILE_DeleteKey( PROFILESECTION
**section
,
289 LPCSTR section_name
, LPCSTR key_name
)
293 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
295 PROFILEKEY
**key
= &(*section
)->key
;
298 if (!strcasecmp( (*key
)->name
, key_name
))
300 PROFILEKEY
*to_del
= *key
;
302 if (to_del
->name
) HeapFree( SystemHeap
, 0, to_del
->name
);
303 if (to_del
->value
) HeapFree( SystemHeap
, 0, to_del
->value
);
304 HeapFree( SystemHeap
, 0, to_del
);
310 section
= &(*section
)->next
;
316 /***********************************************************************
319 * Find a key in a profile tree, optionally creating it.
321 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
322 const char *section_name
,
323 const char *key_name
, int create
)
327 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
329 PROFILEKEY
**key
= &(*section
)->key
;
332 if (!strcasecmp( (*key
)->name
, key_name
)) return *key
;
335 if (!create
) return NULL
;
336 *key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
337 (*key
)->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
338 (*key
)->value
= NULL
;
342 section
= &(*section
)->next
;
344 if (!create
) return NULL
;
345 *section
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILESECTION
) );
346 (*section
)->name
= HEAP_strdupA( SystemHeap
, 0, section_name
);
347 (*section
)->next
= NULL
;
348 (*section
)->key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
349 (*section
)->key
->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
350 (*section
)->key
->value
= NULL
;
351 (*section
)->key
->next
= NULL
;
352 return (*section
)->key
;
356 /***********************************************************************
359 * Flush the current profile to disk if changed.
361 static BOOL
PROFILE_FlushFile(void)
363 char *p
, buffer
[MAX_PATHNAME_LEN
];
364 const char *unix_name
;
370 WARN(profile
, "No current profile!\n");
374 if (!CurProfile
->changed
|| !CurProfile
->dos_name
) return TRUE
;
375 if (!(unix_name
= CurProfile
->unix_name
) || !(file
= fopen(unix_name
, "w")))
377 /* Try to create it in $HOME/.wine */
378 /* FIXME: this will need a more general solution */
379 if ((p
= getenv( "HOME" )) != NULL
)
382 strcat( buffer
, "/.wine/" );
383 p
= buffer
+ strlen(buffer
);
384 strcpy( p
, strrchr( CurProfile
->dos_name
, '\\' ) + 1 );
386 file
= fopen( buffer
, "w" );
393 WARN(profile
, "could not save profile file %s\n", CurProfile
->dos_name
);
397 TRACE(profile
, "Saving '%s' into '%s'\n", CurProfile
->dos_name
, unix_name
);
398 PROFILE_Save( file
, CurProfile
->section
);
400 CurProfile
->changed
= FALSE
;
401 if(!stat(unix_name
,&buf
))
402 CurProfile
->mtime
=buf
.st_mtime
;
407 /***********************************************************************
410 * Open a profile file, checking the cached file first.
412 static BOOL
PROFILE_Open( LPCSTR filename
)
414 DOS_FULL_NAME full_name
;
415 char buffer
[MAX_PATHNAME_LEN
];
416 char *newdos_name
, *p
;
420 PROFILE
*tempProfile
;
422 /* First time around */
425 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
427 MRUProfile
[i
]=HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILE
) );
428 MRUProfile
[i
]->changed
=FALSE
;
429 MRUProfile
[i
]->section
=NULL
;
430 MRUProfile
[i
]->dos_name
=NULL
;
431 MRUProfile
[i
]->unix_name
=NULL
;
432 MRUProfile
[i
]->filename
=NULL
;
433 MRUProfile
[i
]->mtime
=0;
436 /* Check for a match */
438 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
439 strchr( filename
, ':' ))
441 if (!DOSFS_GetFullName( filename
, FALSE
, &full_name
)) return FALSE
;
445 GetWindowsDirectoryA( buffer
, sizeof(buffer
) );
446 strcat( buffer
, "\\" );
447 strcat( buffer
, filename
);
448 if (!DOSFS_GetFullName( buffer
, FALSE
, &full_name
)) return FALSE
;
451 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
453 if ((MRUProfile
[i
]->filename
&& !strcmp( filename
, MRUProfile
[i
]->filename
)) ||
454 (MRUProfile
[i
]->dos_name
&& !strcmp( full_name
.short_name
, MRUProfile
[i
]->dos_name
)))
459 tempProfile
=MRUProfile
[i
];
461 MRUProfile
[j
]=MRUProfile
[j
-1];
462 CurProfile
=tempProfile
;
464 if(!stat(CurProfile
->unix_name
,&buf
) && CurProfile
->mtime
==buf
.st_mtime
)
465 TRACE(profile
, "(%s): already opened (mru=%d)\n",
468 TRACE(profile
, "(%s): already opened, needs refreshing (mru=%d)\n",
474 /* Rotate the oldest to the top to be replaced */
476 if(i
==N_CACHED_PROFILES
)
478 tempProfile
=MRUProfile
[N_CACHED_PROFILES
-1];
479 for(i
=N_CACHED_PROFILES
-1;i
>0;i
--)
480 MRUProfile
[i
]=MRUProfile
[i
-1];
481 CurProfile
=tempProfile
;
484 /* Flush the profile */
486 if(CurProfile
->filename
)
489 PROFILE_Free( CurProfile
->section
);
490 if (CurProfile
->dos_name
) HeapFree( SystemHeap
, 0, CurProfile
->dos_name
);
491 if (CurProfile
->unix_name
) HeapFree( SystemHeap
, 0, CurProfile
->unix_name
);
492 if (CurProfile
->filename
) HeapFree( SystemHeap
, 0, CurProfile
->filename
);
493 CurProfile
->changed
=FALSE
;
494 CurProfile
->section
=NULL
;
495 CurProfile
->dos_name
=NULL
;
496 CurProfile
->unix_name
=NULL
;
497 CurProfile
->filename
=NULL
;
501 newdos_name
= HEAP_strdupA( SystemHeap
, 0, full_name
.short_name
);
502 CurProfile
->dos_name
= newdos_name
;
503 CurProfile
->filename
= HEAP_strdupA( SystemHeap
, 0, filename
);
505 /* Try to open the profile file, first in $HOME/.wine */
507 /* FIXME: this will need a more general solution */
508 if ((p
= getenv( "HOME" )) != NULL
)
511 strcat( buffer
, "/.wine/" );
512 p
= buffer
+ strlen(buffer
);
513 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
515 if ((file
= fopen( buffer
, "r" )))
517 TRACE(profile
, "(%s): found it in %s\n",
519 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0, buffer
);
525 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0,
526 full_name
.long_name
);
527 if ((file
= fopen( full_name
.long_name
, "r" )))
528 TRACE(profile
, "(%s): found it in %s\n",
529 filename
, full_name
.long_name
);
534 CurProfile
->section
= PROFILE_Load( file
);
536 if(!stat(CurProfile
->unix_name
,&buf
))
537 CurProfile
->mtime
=buf
.st_mtime
;
541 /* Does not exist yet, we will create it in PROFILE_FlushFile */
542 WARN(profile
, "profile file %s not found\n", newdos_name
);
548 /***********************************************************************
551 * Returns all keys of a section.
552 * If return_values is TRUE, also include the corresponding values.
554 static INT
PROFILE_GetSection( PROFILESECTION
*section
, LPCSTR section_name
,
555 LPSTR buffer
, UINT len
, BOOL handle_env
,
561 if (section
->name
&& !strcasecmp( section
->name
, section_name
))
564 for (key
= section
->key
; key
; key
= key
->next
)
567 if (!*key
->name
) continue; /* Skip empty lines */
568 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
569 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
570 len
-= strlen(buffer
) + 1;
571 buffer
+= strlen(buffer
) + 1;
572 if (return_values
&& key
->value
) {
574 PROFILE_CopyEntry ( buffer
,
575 key
->value
, len
- 1, handle_env
);
576 len
-= strlen(buffer
) + 1;
577 buffer
+= strlen(buffer
) + 1;
582 /*If either lpszSection or lpszKey is NULL and the supplied
583 destination buffer is too small to hold all the strings,
584 the last string is truncated and followed by two null characters.
585 In this case, the return value is equal to cchReturnBuffer
593 section
= section
->next
;
595 buffer
[0] = buffer
[1] = '\0';
600 /***********************************************************************
603 * Get a profile string.
605 static INT
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
606 LPCSTR def_val
, LPSTR buffer
, UINT len
)
608 PROFILEKEY
*key
= NULL
;
610 if (!def_val
) def_val
= "";
611 if (key_name
&& key_name
[0])
613 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
614 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
616 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
617 section
, key_name
, def_val
, buffer
);
618 return strlen( buffer
);
620 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
625 /***********************************************************************
628 * Set a profile string.
630 static BOOL
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
633 if (!key_name
) /* Delete a whole section */
635 TRACE(profile
, "('%s')\n", section_name
);
636 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
638 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
639 this is not an error on application's level.*/
641 else if (!value
) /* Delete a key */
643 TRACE(profile
, "('%s','%s')\n",
644 section_name
, key_name
);
645 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
646 section_name
, key_name
);
647 return TRUE
; /* same error handling as above */
649 else /* Set the key value */
651 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
653 TRACE(profile
, "('%s','%s','%s'): \n",
654 section_name
, key_name
, value
);
655 if (!key
) return FALSE
;
658 if (!strcmp( key
->value
, value
))
660 TRACE(profile
, " no change needed\n" );
661 return TRUE
; /* No change needed */
663 TRACE(profile
, " replacing '%s'\n", key
->value
);
664 HeapFree( SystemHeap
, 0, key
->value
);
666 else TRACE(profile
, " creating key\n" );
667 key
->value
= HEAP_strdupA( SystemHeap
, 0, value
);
668 CurProfile
->changed
= TRUE
;
674 /***********************************************************************
675 * PROFILE_GetWineIniString
677 * Get a config string from the wine.ini file.
679 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
680 const char *def
, char *buffer
, int len
)
684 EnterCriticalSection( &PROFILE_CritSect
);
688 PROFILEKEY
*key
= PROFILE_Find(&PROFILE_WineProfile
, section
, key_name
, FALSE
);
689 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
691 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
692 section
, key_name
, def
, buffer
);
693 ret
= strlen( buffer
);
697 ret
= PROFILE_GetSection( PROFILE_WineProfile
, section
, buffer
, len
, TRUE
, FALSE
);
699 LeaveCriticalSection( &PROFILE_CritSect
);
705 /***********************************************************************
706 * PROFILE_GetWineIniInt
708 * Get a config integer from the wine.ini file.
710 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
718 EnterCriticalSection( &PROFILE_CritSect
);
720 key
= PROFILE_Find( &PROFILE_WineProfile
, section
, key_name
, FALSE
);
721 if (!key
|| !key
->value
) {
724 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
725 result
= strtol( buffer
, &p
, 0 );
726 ret
= (p
== buffer
) ? 0 /* No digits at all */ : (int)result
;
729 LeaveCriticalSection( &PROFILE_CritSect
);
735 /******************************************************************************
737 * int PROFILE_EnumerateWineIniSection(
738 * char const *section, #Name of the section to enumerate
739 * void (*cbfn)(char const *key, char const *value, void *user),
740 * # Address of the callback function
741 * void *user ) # User-specified pointer.
743 * For each entry in a section in the wine.conf file, this function will
744 * call the specified callback function, informing it of each key and
745 * value. An optional user pointer may be passed to it (if this is not
746 * needed, pass NULL through it and ignore the value in the callback
749 * The callback function must accept three parameters:
750 * The name of the key (char const *)
751 * The value of the key (char const *)
752 * A user-specified parameter (void *)
753 * Note that the first two are char CONST *'s, not char *'s! The callback
754 * MUST not modify these strings!
756 * The return value indicates the number of times the callback function
759 int PROFILE_EnumerateWineIniSection(
761 void (*cbfn
)(char const *, char const *, void *),
764 PROFILESECTION
*scansect
;
768 EnterCriticalSection( &PROFILE_CritSect
);
770 /* Search for the correct section */
771 for(scansect
= PROFILE_WineProfile
; scansect
; scansect
= scansect
->next
) {
772 if(scansect
->name
&& !strcasecmp(scansect
->name
, section
)) {
774 /* Enumerate each key with the callback */
775 for(scankey
= scansect
->key
; scankey
; scankey
= scankey
->next
) {
777 /* Ignore blank entries -- these shouldn't exist, but let's
779 if(scankey
->name
[0]) {
780 cbfn(scankey
->name
, scankey
->value
, userptr
);
788 LeaveCriticalSection( &PROFILE_CritSect
);
794 /******************************************************************************
796 * int PROFILE_GetWineIniBool(
797 * char const *section,
798 * char const *key_name,
801 * Reads a boolean value from the wine.ini file. This function attempts to
802 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
803 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
804 * true. Anything else results in the return of the default value.
806 * This function uses 1 to indicate true, and 0 for false. You can check
807 * for existence by setting def to something other than 0 or 1 and
808 * examining the return value.
810 int PROFILE_GetWineIniBool(
812 char const *key_name
,
818 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
820 switch(key_value
[0]) {
841 TRACE(profile
, "(\"%s\", \"%s\", %s), "
842 "[%c], ret %s.\n", section
, key_name
,
843 def
? "TRUE" : "FALSE", key_value
[0],
844 retval
? "TRUE" : "FALSE");
850 /***********************************************************************
851 * PROFILE_LoadWineIni
853 * Load the wine.ini file.
855 int PROFILE_LoadWineIni(void)
857 char buffer
[MAX_PATHNAME_LEN
];
861 InitializeCriticalSection( &PROFILE_CritSect
);
862 MakeCriticalSectionGlobal( &PROFILE_CritSect
);
864 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
866 /* Open -config specified file */
867 PROFILE_WineProfile
= PROFILE_Load ( f
);
869 strncpy(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
-1);
873 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
875 PROFILE_WineProfile
= PROFILE_Load( f
);
877 strncpy(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
-1);
880 if ((p
= getenv( "HOME" )) != NULL
)
882 lstrcpynA(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
883 strcat( buffer
, PROFILE_WineIniName
);
884 if ((f
= fopen( buffer
, "r" )) != NULL
)
886 PROFILE_WineProfile
= PROFILE_Load( f
);
888 strncpy(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
-1);
892 else WARN(profile
, "could not get $HOME value for config file.\n" );
894 /* Try global file */
896 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
898 PROFILE_WineProfile
= PROFILE_Load( f
);
900 strncpy(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
-1);
903 MSG( "Can't open configuration file %s or $HOME%s\n",
904 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
909 /***********************************************************************
910 * PROFILE_UsageWineIni
912 * Explain the wine.ini file to those who don't read documentation.
913 * Keep below one screenful in length so that error messages above are
916 void PROFILE_UsageWineIni(void)
918 MSG("Perhaps you have not properly edited or created "
919 "your Wine configuration file.\n");
920 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
921 MSG(" or it is determined by the -config option or from\n"
922 " the WINE_INI environment variable.\n");
923 if (*PROFILE_WineIniUsed
)
924 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
925 /* RTFM, so to say */
928 /***********************************************************************
929 * PROFILE_GetStringItem
931 * Convenience function that turns a string 'xxx, yyy, zzz' into
932 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
934 char* PROFILE_GetStringItem( char* start
)
938 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
942 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
944 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
946 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
949 if( lpch
) *lpch
= '\0';
953 /********************* API functions **********************************/
955 /***********************************************************************
956 * GetProfileInt16 (KERNEL.57)
958 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
960 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
964 /***********************************************************************
965 * GetProfileInt32A (KERNEL32.264)
967 UINT WINAPI
GetProfileIntA( LPCSTR section
, LPCSTR entry
, INT def_val
)
969 return GetPrivateProfileIntA( section
, entry
, def_val
, "win.ini" );
972 /***********************************************************************
973 * GetProfileInt32W (KERNEL32.264)
975 UINT WINAPI
GetProfileIntW( LPCWSTR section
, LPCWSTR entry
, INT def_val
)
977 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
978 return GetPrivateProfileIntW( section
, entry
, def_val
, wininiW
);
981 /***********************************************************************
982 * GetProfileString16 (KERNEL.58)
984 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
985 LPSTR buffer
, UINT16 len
)
987 return GetPrivateProfileString16( section
, entry
, def_val
,
988 buffer
, len
, "win.ini" );
991 /***********************************************************************
992 * GetProfileString32A (KERNEL32.268)
994 INT WINAPI
GetProfileStringA( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
995 LPSTR buffer
, UINT len
)
997 return GetPrivateProfileStringA( section
, entry
, def_val
,
998 buffer
, len
, "win.ini" );
1001 /***********************************************************************
1002 * GetProfileString32W (KERNEL32.269)
1004 INT WINAPI
GetProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1005 LPCWSTR def_val
, LPWSTR buffer
, UINT len
)
1007 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1008 return GetPrivateProfileStringW( section
, entry
, def_val
,
1009 buffer
, len
, wininiW
);
1012 /***********************************************************************
1013 * WriteProfileString16 (KERNEL.59)
1015 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1018 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1021 /***********************************************************************
1022 * WriteProfileString32A (KERNEL32.587)
1024 BOOL WINAPI
WriteProfileStringA( LPCSTR section
, LPCSTR entry
,
1027 return WritePrivateProfileStringA( section
, entry
, string
, "win.ini" );
1030 /***********************************************************************
1031 * WriteProfileString32W (KERNEL32.588)
1033 BOOL WINAPI
WriteProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1036 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1037 return WritePrivateProfileStringW( section
, entry
, string
, wininiW
);
1041 /***********************************************************************
1042 * GetPrivateProfileInt16 (KERNEL.127)
1044 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1045 INT16 def_val
, LPCSTR filename
)
1047 long result
=(long)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
1049 if (result
> 65535) return 65535;
1050 if (result
>= 0) return (UINT16
)result
;
1051 if (result
< -32768) return -32768;
1052 return (UINT16
)(INT16
)result
;
1055 /***********************************************************************
1056 * GetPrivateProfileInt32A (KERNEL32.251)
1058 UINT WINAPI
GetPrivateProfileIntA( LPCSTR section
, LPCSTR entry
,
1059 INT def_val
, LPCSTR filename
)
1065 GetPrivateProfileStringA( section
, entry
, "",
1066 buffer
, sizeof(buffer
), filename
);
1067 if (!buffer
[0]) return (UINT
)def_val
;
1068 result
= strtol( buffer
, &p
, 0 );
1069 if (p
== buffer
) return 0; /* No digits at all */
1070 return (UINT
)result
;
1073 /***********************************************************************
1074 * GetPrivateProfileInt32W (KERNEL32.252)
1076 UINT WINAPI
GetPrivateProfileIntW( LPCWSTR section
, LPCWSTR entry
,
1077 INT def_val
, LPCWSTR filename
)
1079 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1080 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1081 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1082 UINT res
= GetPrivateProfileIntA(sectionA
, entryA
, def_val
, filenameA
);
1083 HeapFree( GetProcessHeap(), 0, sectionA
);
1084 HeapFree( GetProcessHeap(), 0, filenameA
);
1085 HeapFree( GetProcessHeap(), 0, entryA
);
1089 /***********************************************************************
1090 * GetPrivateProfileString16 (KERNEL.128)
1092 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1093 LPCSTR def_val
, LPSTR buffer
,
1094 UINT16 len
, LPCSTR filename
)
1096 return GetPrivateProfileStringA(section
,entry
,def_val
,buffer
,len
,filename
);
1099 /***********************************************************************
1100 * GetPrivateProfileString32A (KERNEL32.255)
1102 INT WINAPI
GetPrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1103 LPCSTR def_val
, LPSTR buffer
,
1104 UINT len
, LPCSTR filename
)
1109 filename
= "win.ini";
1111 EnterCriticalSection( &PROFILE_CritSect
);
1113 if (PROFILE_Open( filename
)) {
1114 ret
= PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1116 lstrcpynA( buffer
, def_val
, len
);
1117 ret
= strlen( buffer
);
1120 LeaveCriticalSection( &PROFILE_CritSect
);
1125 /***********************************************************************
1126 * GetPrivateProfileString32W (KERNEL32.256)
1128 INT WINAPI
GetPrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1129 LPCWSTR def_val
, LPWSTR buffer
,
1130 UINT len
, LPCWSTR filename
)
1132 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1133 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1134 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1135 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1136 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1137 INT ret
= GetPrivateProfileStringA( sectionA
, entryA
, def_valA
,
1138 bufferA
, len
, filenameA
);
1139 lstrcpynAtoW( buffer
, bufferA
, len
);
1140 HeapFree( GetProcessHeap(), 0, sectionA
);
1141 HeapFree( GetProcessHeap(), 0, entryA
);
1142 HeapFree( GetProcessHeap(), 0, filenameA
);
1143 HeapFree( GetProcessHeap(), 0, def_valA
);
1144 HeapFree( GetProcessHeap(), 0, bufferA
);
1148 /***********************************************************************
1149 * GetPrivateProfileSection16 (KERNEL.418)
1151 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
1152 UINT16 len
, LPCSTR filename
)
1154 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
1157 /***********************************************************************
1158 * GetPrivateProfileSection32A (KERNEL32.255)
1160 INT WINAPI
GetPrivateProfileSectionA( LPCSTR section
, LPSTR buffer
,
1161 DWORD len
, LPCSTR filename
)
1165 EnterCriticalSection( &PROFILE_CritSect
);
1167 if (PROFILE_Open( filename
))
1168 ret
= PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1171 LeaveCriticalSection( &PROFILE_CritSect
);
1176 /***********************************************************************
1177 * GetPrivateProfileSection32W (KERNEL32.256)
1180 INT WINAPI
GetPrivateProfileSectionW (LPCWSTR section
, LPWSTR buffer
,
1181 DWORD len
, LPCWSTR filename
)
1184 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1185 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1186 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1187 INT ret
= GetPrivateProfileSectionA( sectionA
, bufferA
, len
,
1189 HeapFree( GetProcessHeap(), 0, sectionA
);
1190 HeapFree( GetProcessHeap(), 0, filenameA
);
1191 HeapFree( GetProcessHeap(), 0, bufferA
);
1195 /***********************************************************************
1196 * GetProfileSection16 (KERNEL.419)
1198 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
1200 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
1203 /***********************************************************************
1204 * GetProfileSection32A (KERNEL32.268)
1206 INT WINAPI
GetProfileSectionA( LPCSTR section
, LPSTR buffer
, DWORD len
)
1208 return GetPrivateProfileSectionA( section
, buffer
, len
, "win.ini" );
1211 /***********************************************************************
1212 * GetProfileSection32W (KERNEL32)
1214 INT WINAPI
GetProfileSectionW( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
1216 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1217 return GetPrivateProfileSectionW( section
, buffer
, len
, wininiW
);
1221 /***********************************************************************
1222 * WritePrivateProfileString16 (KERNEL.129)
1224 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1225 LPCSTR string
, LPCSTR filename
)
1227 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
1230 /***********************************************************************
1231 * WritePrivateProfileString32A (KERNEL32.582)
1233 BOOL WINAPI
WritePrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1234 LPCSTR string
, LPCSTR filename
)
1238 EnterCriticalSection( &PROFILE_CritSect
);
1240 if (!PROFILE_Open( filename
)) {
1242 } else if (!section
) {
1243 ret
= PROFILE_FlushFile();
1245 ret
= PROFILE_SetString( section
, entry
, string
);
1248 LeaveCriticalSection( &PROFILE_CritSect
);
1253 /***********************************************************************
1254 * WritePrivateProfileString32W (KERNEL32.583)
1256 BOOL WINAPI
WritePrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1257 LPCWSTR string
, LPCWSTR filename
)
1259 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1260 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1261 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1262 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1263 BOOL res
= WritePrivateProfileStringA( sectionA
, entryA
,
1264 stringA
, filenameA
);
1265 HeapFree( GetProcessHeap(), 0, sectionA
);
1266 HeapFree( GetProcessHeap(), 0, entryA
);
1267 HeapFree( GetProcessHeap(), 0, stringA
);
1268 HeapFree( GetProcessHeap(), 0, filenameA
);
1272 /***********************************************************************
1273 * WritePrivateProfileSection16 (KERNEL.416)
1275 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
1276 LPCSTR string
, LPCSTR filename
)
1278 return WritePrivateProfileSectionA( section
, string
, filename
);
1281 /***********************************************************************
1282 * WritePrivateProfileSection32A (KERNEL32)
1284 BOOL WINAPI
WritePrivateProfileSectionA( LPCSTR section
,
1285 LPCSTR string
, LPCSTR filename
)
1287 char *p
=(char*)string
;
1289 FIXME(profile
, "WritePrivateProfileSection32A empty stub\n");
1290 if (TRACE_ON(profile
)) {
1291 TRACE(profile
, "(%s) => [%s]\n", filename
, section
);
1293 TRACE(profile
, "%s\n", p
);
1302 /***********************************************************************
1303 * WritePrivateProfileSection32W (KERNEL32)
1305 BOOL WINAPI
WritePrivateProfileSectionW( LPCWSTR section
,
1306 LPCWSTR string
, LPCWSTR filename
)
1309 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1310 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1311 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1312 BOOL res
= WritePrivateProfileSectionA( sectionA
, stringA
, filenameA
);
1313 HeapFree( GetProcessHeap(), 0, sectionA
);
1314 HeapFree( GetProcessHeap(), 0, stringA
);
1315 HeapFree( GetProcessHeap(), 0, filenameA
);
1319 /***********************************************************************
1320 * WriteProfileSection16 (KERNEL.417)
1322 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
1324 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
1327 /***********************************************************************
1328 * WriteProfileSection32A (KERNEL32.747)
1330 BOOL WINAPI
WriteProfileSectionA( LPCSTR section
, LPCSTR keys_n_values
)
1333 return WritePrivateProfileSectionA( section
, keys_n_values
, "win.ini");
1336 /***********************************************************************
1337 * WriteProfileSection32W (KERNEL32.748)
1339 BOOL WINAPI
WriteProfileSectionW( LPCWSTR section
, LPCWSTR keys_n_values
)
1341 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini");
1343 return (WritePrivateProfileSectionW (section
,keys_n_values
, wininiW
));
1346 /***********************************************************************
1347 * GetPrivateProfileSectionNames16 (KERNEL.143)
1349 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1354 PROFILESECTION
*section
;
1357 EnterCriticalSection( &PROFILE_CritSect
);
1359 if (PROFILE_Open( filename
)) {
1362 section
= CurProfile
->section
;
1363 for ( ; section
; section
= section
->next
)
1364 if (section
->name
) {
1365 l
= strlen (section
->name
);
1367 if (cursize
> size
+1) {
1368 LeaveCriticalSection( &PROFILE_CritSect
);
1371 strcpy (buf
,section
->name
);
1381 LeaveCriticalSection( &PROFILE_CritSect
);
1387 /***********************************************************************
1388 * GetProfileSectionNames16 (KERNEL.142)
1390 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1393 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1397 /***********************************************************************
1398 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1400 DWORD WINAPI
GetPrivateProfileSectionNamesA( LPSTR buffer
, DWORD size
,
1404 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1408 /***********************************************************************
1409 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1411 DWORD WINAPI
GetPrivateProfileSectionNamesW( LPWSTR buffer
, DWORD size
,
1415 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1416 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1418 INT ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1419 lstrcpynAtoW( buffer
, bufferA
, size
);
1420 HeapFree( GetProcessHeap(), 0, bufferA
);
1421 HeapFree( GetProcessHeap(), 0, filenameA
);
1426 /***********************************************************************
1427 * GetPrivateProfileStruct16 (KERNEL.407)
1429 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
1430 LPVOID buf
, UINT16 len
, LPCSTR filename
)
1432 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
1435 /***********************************************************************
1436 * GetPrivateProfileStruct32A (KERNEL32.370)
1438 BOOL WINAPI
GetPrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1439 LPVOID buf
, UINT len
, LPCSTR filename
)
1443 EnterCriticalSection( &PROFILE_CritSect
);
1445 if (PROFILE_Open( filename
)) {
1446 PROFILEKEY
*k
= PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1448 lstrcpynA( buf
, k
->value
, strlen(k
->value
));
1452 LeaveCriticalSection( &PROFILE_CritSect
);
1457 /***********************************************************************
1458 * GetPrivateProfileStruct32W (KERNEL32.543)
1460 BOOL WINAPI
GetPrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1461 LPVOID buffer
, UINT len
, LPCWSTR filename
)
1463 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1464 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1465 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1466 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1468 INT ret
= GetPrivateProfileStructA( sectionA
, keyA
, bufferA
,
1470 lstrcpynAtoW( buffer
, bufferA
, len
);
1471 HeapFree( GetProcessHeap(), 0, bufferA
);
1472 HeapFree( GetProcessHeap(), 0, sectionA
);
1473 HeapFree( GetProcessHeap(), 0, keyA
);
1474 HeapFree( GetProcessHeap(), 0, filenameA
);
1481 /***********************************************************************
1482 * WritePrivateProfileStruct16 (KERNEL.406)
1484 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
1485 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
1487 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
1490 /***********************************************************************
1491 * WritePrivateProfileStruct32A (KERNEL32.744)
1493 BOOL WINAPI
WritePrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1494 LPVOID buf
, UINT bufsize
, LPCSTR filename
)
1498 EnterCriticalSection( &PROFILE_CritSect
);
1500 if ((!section
) && (!key
) && (!buf
)) { /* flush the cache */
1501 PROFILE_FlushFile();
1504 if (!PROFILE_Open( filename
))
1507 ret
= PROFILE_SetString( section
, key
, buf
);
1510 LeaveCriticalSection( &PROFILE_CritSect
);
1515 /***********************************************************************
1516 * WritePrivateProfileStruct32W (KERNEL32.544)
1518 BOOL WINAPI
WritePrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1519 LPVOID buf
, UINT bufsize
, LPCWSTR filename
)
1521 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1522 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1523 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1524 INT ret
= WritePrivateProfileStructA( sectionA
, keyA
, buf
, bufsize
,
1526 HeapFree( GetProcessHeap(), 0, sectionA
);
1527 HeapFree( GetProcessHeap(), 0, keyA
);
1528 HeapFree( GetProcessHeap(), 0, filenameA
);
1534 /***********************************************************************
1535 * WriteOutProfiles (KERNEL.315)
1537 void WINAPI
WriteOutProfiles16(void)
1539 EnterCriticalSection( &PROFILE_CritSect
);
1540 PROFILE_FlushFile();
1541 LeaveCriticalSection( &PROFILE_CritSect
);