4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
15 #include "wine/winbase16.h"
22 typedef struct tagPROFILEKEY
26 struct tagPROFILEKEY
*next
;
29 typedef struct tagPROFILESECTION
32 struct tagPROFILEKEY
*key
;
33 struct tagPROFILESECTION
*next
;
40 PROFILESECTION
*section
;
48 #define N_CACHED_PROFILES 10
50 /* Cached profile files */
51 static PROFILE
*MRUProfile
[N_CACHED_PROFILES
]={NULL
};
53 #define CurProfile (MRUProfile[0])
55 /* wine.ini profile content */
56 static PROFILESECTION
*WineProfile
;
58 #define PROFILE_MAX_LINE_LEN 1024
60 /* Wine profile name in $HOME directory; must begin with slash */
61 static const char PROFILE_WineIniName
[] = "/.winerc";
63 /* Wine profile: the profile file being used */
64 static char PROFILE_WineIniUsed
[MAX_PATHNAME_LEN
] = "";
66 /* Check for comments in profile */
67 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
69 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
71 static LPCWSTR wininiW
= NULL
;
73 /***********************************************************************
76 * Copy the content of an entry into a buffer, removing quotes, and possibly
77 * translating environment variables.
79 static void PROFILE_CopyEntry( char *buffer
, const char *value
, int len
,
85 if ((*value
== '\'') || (*value
== '\"'))
87 if (value
[1] && (value
[strlen(value
)-1] == *value
)) quote
= *value
++;
92 lstrcpynA( buffer
, value
, len
);
93 if (quote
&& (len
>= strlen(value
))) buffer
[strlen(buffer
)-1] = '\0';
97 for (p
= value
; (*p
&& (len
> 1)); *buffer
++ = *p
++, len
-- )
99 if ((*p
== '$') && (p
[1] == '{'))
103 const char *p2
= strchr( p
, '}' );
104 if (!p2
) continue; /* ignore it */
105 lstrcpynA(env_val
, p
+ 2, MIN( sizeof(env_val
), (int)(p2
-p
)-1 ));
106 if ((env_p
= getenv( env_val
)) != NULL
)
108 lstrcpynA( buffer
, env_p
, len
);
109 buffer
+= strlen( buffer
);
110 len
-= strlen( buffer
);
119 /***********************************************************************
122 * Save a profile tree to a file.
124 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
128 for ( ; section
; section
= section
->next
)
130 if (section
->name
) fprintf( file
, "\r\n[%s]\r\n", section
->name
);
131 for (key
= section
->key
; key
; key
= key
->next
)
133 fprintf( file
, "%s", key
->name
);
134 if (key
->value
) fprintf( file
, "=%s", key
->value
);
135 fprintf( file
, "\r\n" );
141 /***********************************************************************
144 * Free a profile tree.
146 static void PROFILE_Free( PROFILESECTION
*section
)
148 PROFILESECTION
*next_section
;
149 PROFILEKEY
*key
, *next_key
;
151 for ( ; section
; section
= next_section
)
153 if (section
->name
) HeapFree( SystemHeap
, 0, section
->name
);
154 for (key
= section
->key
; key
; key
= next_key
)
156 next_key
= key
->next
;
157 if (key
->name
) HeapFree( SystemHeap
, 0, key
->name
);
158 if (key
->value
) HeapFree( SystemHeap
, 0, key
->value
);
159 HeapFree( SystemHeap
, 0, key
);
161 next_section
= section
->next
;
162 HeapFree( SystemHeap
, 0, section
);
167 PROFILE_isspace(char c
) {
168 if (isspace(c
)) return 1;
169 if (c
=='\r' || c
==0x1a) return 1;
170 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
175 /***********************************************************************
178 * Load a profile tree from a file.
180 static PROFILESECTION
*PROFILE_Load( FILE *file
)
182 char buffer
[PROFILE_MAX_LINE_LEN
];
185 PROFILESECTION
*section
, *first_section
;
186 PROFILESECTION
**next_section
;
187 PROFILEKEY
*key
, *prev_key
, **next_key
;
189 first_section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
190 first_section
->name
= NULL
;
191 first_section
->key
= NULL
;
192 first_section
->next
= NULL
;
193 next_section
= &first_section
->next
;
194 next_key
= &first_section
->key
;
197 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
201 while (*p
&& PROFILE_isspace(*p
)) p
++;
202 if (*p
== '[') /* section start */
204 if (!(p2
= strrchr( p
, ']' )))
206 WARN(profile
, "Invalid section header at line %d: '%s'\n",
213 section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
214 section
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
216 section
->next
= NULL
;
217 *next_section
= section
;
218 next_section
= §ion
->next
;
219 next_key
= §ion
->key
;
222 TRACE(profile
, "New section: '%s'\n",section
->name
);
229 while ((p2
> p
) && ((*p2
== '\n') || PROFILE_isspace(*p2
))) *p2
--='\0';
231 if ((p2
= strchr( p
, '=' )) != NULL
)
234 while ((p3
> p
) && PROFILE_isspace(*p3
)) *p3
-- = '\0';
236 while (*p2
&& PROFILE_isspace(*p2
)) p2
++;
239 if(*p
|| !prev_key
|| *prev_key
->name
)
241 key
= HEAP_xalloc( SystemHeap
, 0, sizeof(*key
) );
242 key
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
243 key
->value
= p2
? HEAP_strdupA( SystemHeap
, 0, p2
) : NULL
;
246 next_key
= &key
->next
;
249 TRACE(profile
, "New key: name='%s', value='%s'\n",key
->name
,key
->value
?key
->value
:"(none)");
252 return first_section
;
256 /***********************************************************************
257 * PROFILE_DeleteSection
259 * Delete a section from a profile tree.
261 static BOOL
PROFILE_DeleteSection( PROFILESECTION
**section
, LPCSTR name
)
265 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, name
))
267 PROFILESECTION
*to_del
= *section
;
268 *section
= to_del
->next
;
270 PROFILE_Free( to_del
);
273 section
= &(*section
)->next
;
279 /***********************************************************************
282 * Delete a key from a profile tree.
284 static BOOL
PROFILE_DeleteKey( PROFILESECTION
**section
,
285 LPCSTR section_name
, LPCSTR key_name
)
289 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
291 PROFILEKEY
**key
= &(*section
)->key
;
294 if (!strcasecmp( (*key
)->name
, key_name
))
296 PROFILEKEY
*to_del
= *key
;
298 if (to_del
->name
) HeapFree( SystemHeap
, 0, to_del
->name
);
299 if (to_del
->value
) HeapFree( SystemHeap
, 0, to_del
->value
);
300 HeapFree( SystemHeap
, 0, to_del
);
306 section
= &(*section
)->next
;
312 /***********************************************************************
315 * Find a key in a profile tree, optionally creating it.
317 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
318 const char *section_name
,
319 const char *key_name
, int create
)
323 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
325 PROFILEKEY
**key
= &(*section
)->key
;
328 if (!strcasecmp( (*key
)->name
, key_name
)) return *key
;
331 if (!create
) return NULL
;
332 *key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
333 (*key
)->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
334 (*key
)->value
= NULL
;
338 section
= &(*section
)->next
;
340 if (!create
) return NULL
;
341 *section
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILESECTION
) );
342 (*section
)->name
= HEAP_strdupA( SystemHeap
, 0, section_name
);
343 (*section
)->next
= NULL
;
344 (*section
)->key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
345 (*section
)->key
->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
346 (*section
)->key
->value
= NULL
;
347 (*section
)->key
->next
= NULL
;
348 return (*section
)->key
;
352 /***********************************************************************
355 * Flush the current profile to disk if changed.
357 static BOOL
PROFILE_FlushFile(void)
359 char *p
, buffer
[MAX_PATHNAME_LEN
];
360 const char *unix_name
;
366 WARN(profile
, "No current profile!\n");
370 if (!CurProfile
->changed
|| !CurProfile
->dos_name
) return TRUE
;
371 if (!(unix_name
= CurProfile
->unix_name
) || !(file
= fopen(unix_name
, "w")))
373 /* Try to create it in $HOME/.wine */
374 /* FIXME: this will need a more general solution */
375 if ((p
= getenv( "HOME" )) != NULL
)
378 strcat( buffer
, "/.wine/" );
379 p
= buffer
+ strlen(buffer
);
380 strcpy( p
, strrchr( CurProfile
->dos_name
, '\\' ) + 1 );
382 file
= fopen( buffer
, "w" );
389 WARN(profile
, "could not save profile file %s\n", CurProfile
->dos_name
);
393 TRACE(profile
, "Saving '%s' into '%s'\n", CurProfile
->dos_name
, unix_name
);
394 PROFILE_Save( file
, CurProfile
->section
);
396 CurProfile
->changed
= FALSE
;
397 if(!stat(unix_name
,&buf
))
398 CurProfile
->mtime
=buf
.st_mtime
;
403 /***********************************************************************
406 * Open a profile file, checking the cached file first.
408 static BOOL
PROFILE_Open( LPCSTR filename
)
410 DOS_FULL_NAME full_name
;
411 char buffer
[MAX_PATHNAME_LEN
];
412 char *newdos_name
, *p
;
416 PROFILE
*tempProfile
;
418 /* First time around */
421 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
423 MRUProfile
[i
]=HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILE
) );
424 MRUProfile
[i
]->changed
=FALSE
;
425 MRUProfile
[i
]->section
=NULL
;
426 MRUProfile
[i
]->dos_name
=NULL
;
427 MRUProfile
[i
]->unix_name
=NULL
;
428 MRUProfile
[i
]->filename
=NULL
;
429 MRUProfile
[i
]->mtime
=0;
432 /* Check for a match */
434 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
435 strchr( filename
, ':' ))
437 if (!DOSFS_GetFullName( filename
, FALSE
, &full_name
)) return FALSE
;
441 GetWindowsDirectoryA( buffer
, sizeof(buffer
) );
442 strcat( buffer
, "\\" );
443 strcat( buffer
, filename
);
444 if (!DOSFS_GetFullName( buffer
, FALSE
, &full_name
)) return FALSE
;
447 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
449 if ((MRUProfile
[i
]->filename
&& !strcmp( filename
, MRUProfile
[i
]->filename
)) ||
450 (MRUProfile
[i
]->dos_name
&& !strcmp( full_name
.short_name
, MRUProfile
[i
]->dos_name
)))
455 tempProfile
=MRUProfile
[i
];
457 MRUProfile
[j
]=MRUProfile
[j
-1];
458 CurProfile
=tempProfile
;
460 if(!stat(CurProfile
->unix_name
,&buf
) && CurProfile
->mtime
==buf
.st_mtime
)
461 TRACE(profile
, "(%s): already opened (mru=%d)\n",
464 TRACE(profile
, "(%s): already opened, needs refreshing (mru=%d)\n",
470 /* Rotate the oldest to the top to be replaced */
472 if(i
==N_CACHED_PROFILES
)
474 tempProfile
=MRUProfile
[N_CACHED_PROFILES
-1];
475 for(i
=N_CACHED_PROFILES
-1;i
>0;i
--)
476 MRUProfile
[i
]=MRUProfile
[i
-1];
477 CurProfile
=tempProfile
;
480 /* Flush the profile */
482 if(CurProfile
->filename
)
485 PROFILE_Free( CurProfile
->section
);
486 if (CurProfile
->dos_name
) HeapFree( SystemHeap
, 0, CurProfile
->dos_name
);
487 if (CurProfile
->unix_name
) HeapFree( SystemHeap
, 0, CurProfile
->unix_name
);
488 if (CurProfile
->filename
) HeapFree( SystemHeap
, 0, CurProfile
->filename
);
489 CurProfile
->changed
=FALSE
;
490 CurProfile
->section
=NULL
;
491 CurProfile
->dos_name
=NULL
;
492 CurProfile
->unix_name
=NULL
;
493 CurProfile
->filename
=NULL
;
497 newdos_name
= HEAP_strdupA( SystemHeap
, 0, full_name
.short_name
);
498 CurProfile
->dos_name
= newdos_name
;
499 CurProfile
->filename
= HEAP_strdupA( SystemHeap
, 0, filename
);
501 /* Try to open the profile file, first in $HOME/.wine */
503 /* FIXME: this will need a more general solution */
504 if ((p
= getenv( "HOME" )) != NULL
)
507 strcat( buffer
, "/.wine/" );
508 p
= buffer
+ strlen(buffer
);
509 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
511 if ((file
= fopen( buffer
, "r" )))
513 TRACE(profile
, "(%s): found it in %s\n",
515 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0, buffer
);
521 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0,
522 full_name
.long_name
);
523 if ((file
= fopen( full_name
.long_name
, "r" )))
524 TRACE(profile
, "(%s): found it in %s\n",
525 filename
, full_name
.long_name
);
530 CurProfile
->section
= PROFILE_Load( file
);
532 if(!stat(CurProfile
->unix_name
,&buf
))
533 CurProfile
->mtime
=buf
.st_mtime
;
537 /* Does not exist yet, we will create it in PROFILE_FlushFile */
538 WARN(profile
, "profile file %s not found\n", newdos_name
);
544 /***********************************************************************
547 * Returns all keys of a section.
548 * If return_values is TRUE, also include the corresponding values.
550 static INT
PROFILE_GetSection( PROFILESECTION
*section
, LPCSTR section_name
,
551 LPSTR buffer
, UINT len
, BOOL handle_env
,
557 if (section
->name
&& !strcasecmp( section
->name
, section_name
))
560 for (key
= section
->key
; key
; key
= key
->next
)
563 if (!*key
->name
) continue; /* Skip empty lines */
564 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
565 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
566 len
-= strlen(buffer
) + 1;
567 buffer
+= strlen(buffer
) + 1;
568 if (return_values
&& key
->value
) {
570 PROFILE_CopyEntry ( buffer
,
571 key
->value
, len
- 1, handle_env
);
572 len
-= strlen(buffer
) + 1;
573 buffer
+= strlen(buffer
) + 1;
578 /*If either lpszSection or lpszKey is NULL and the supplied
579 destination buffer is too small to hold all the strings,
580 the last string is truncated and followed by two null characters.
581 In this case, the return value is equal to cchReturnBuffer
589 section
= section
->next
;
591 buffer
[0] = buffer
[1] = '\0';
596 /***********************************************************************
599 * Get a profile string.
601 static INT
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
602 LPCSTR def_val
, LPSTR buffer
, UINT len
)
604 PROFILEKEY
*key
= NULL
;
606 if (!def_val
) def_val
= "";
607 if (key_name
&& key_name
[0])
609 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
610 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
612 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
613 section
, key_name
, def_val
, buffer
);
614 return strlen( buffer
);
616 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
621 /***********************************************************************
624 * Set a profile string.
626 static BOOL
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
629 if (!key_name
) /* Delete a whole section */
631 TRACE(profile
, "('%s')\n", section_name
);
632 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
634 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
635 this is not an error on application's level.*/
637 else if (!value
) /* Delete a key */
639 TRACE(profile
, "('%s','%s')\n",
640 section_name
, key_name
);
641 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
642 section_name
, key_name
);
643 return TRUE
; /* same error handling as above */
645 else /* Set the key value */
647 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
649 TRACE(profile
, "('%s','%s','%s'): \n",
650 section_name
, key_name
, value
);
651 if (!key
) return FALSE
;
654 if (!strcmp( key
->value
, value
))
656 TRACE(profile
, " no change needed\n" );
657 return TRUE
; /* No change needed */
659 TRACE(profile
, " replacing '%s'\n", key
->value
);
660 HeapFree( SystemHeap
, 0, key
->value
);
662 else TRACE(profile
, " creating key\n" );
663 key
->value
= HEAP_strdupA( SystemHeap
, 0, value
);
664 CurProfile
->changed
= TRUE
;
670 /***********************************************************************
671 * PROFILE_GetWineIniString
673 * Get a config string from the wine.ini file.
675 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
676 const char *def
, char *buffer
, int len
)
680 PROFILEKEY
*key
= PROFILE_Find(&WineProfile
, section
, key_name
, FALSE
);
681 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
683 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
684 section
, key_name
, def
, buffer
);
685 return strlen( buffer
);
687 return PROFILE_GetSection( WineProfile
, section
, buffer
, len
, TRUE
, FALSE
);
691 /***********************************************************************
692 * PROFILE_GetWineIniInt
694 * Get a config integer from the wine.ini file.
696 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
702 PROFILEKEY
*key
= PROFILE_Find( &WineProfile
, section
, key_name
, FALSE
);
703 if (!key
|| !key
->value
) return def
;
704 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
705 result
= strtol( buffer
, &p
, 0 );
706 if (p
== buffer
) return 0; /* No digits at all */
711 /******************************************************************************
713 * int PROFILE_EnumerateWineIniSection(
714 * char const *section, #Name of the section to enumerate
715 * void (*cbfn)(char const *key, char const *value, void *user),
716 * # Address of the callback function
717 * void *user ) # User-specified pointer.
719 * For each entry in a section in the wine.conf file, this function will
720 * call the specified callback function, informing it of each key and
721 * value. An optional user pointer may be passed to it (if this is not
722 * needed, pass NULL through it and ignore the value in the callback
725 * The callback function must accept three parameters:
726 * The name of the key (char const *)
727 * The value of the key (char const *)
728 * A user-specified parameter (void *)
729 * Note that the first two are char CONST *'s, not char *'s! The callback
730 * MUST not modify these strings!
732 * The return value indicates the number of times the callback function
735 int PROFILE_EnumerateWineIniSection(
737 void (*cbfn
)(char const *, char const *, void *),
740 PROFILESECTION
*scansect
;
744 /* Search for the correct section */
745 for(scansect
= WineProfile
; scansect
; scansect
= scansect
->next
) {
746 if(scansect
->name
&& !strcasecmp(scansect
->name
, section
)) {
748 /* Enumerate each key with the callback */
749 for(scankey
= scansect
->key
; scankey
; scankey
= scankey
->next
) {
751 /* Ignore blank entries -- these shouldn't exist, but let's
753 if(scankey
->name
[0]) {
754 cbfn(scankey
->name
, scankey
->value
, userptr
);
767 /******************************************************************************
769 * int PROFILE_GetWineIniBool(
770 * char const *section,
771 * char const *key_name,
774 * Reads a boolean value from the wine.ini file. This function attempts to
775 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
776 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
777 * true. Anything else results in the return of the default value.
779 * This function uses 1 to indicate true, and 0 for false. You can check
780 * for existence by setting def to something other than 0 or 1 and
781 * examining the return value.
783 int PROFILE_GetWineIniBool(
785 char const *key_name
,
791 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
793 switch(key_value
[0]) {
814 TRACE(profile
, "(\"%s\", \"%s\", %s), "
815 "[%c], ret %s.\n", section
, key_name
,
816 def
? "TRUE" : "FALSE", key_value
[0],
817 retval
? "TRUE" : "FALSE");
823 /***********************************************************************
824 * PROFILE_LoadWineIni
826 * Load the wine.ini file.
828 int PROFILE_LoadWineIni(void)
830 char buffer
[MAX_PATHNAME_LEN
];
834 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
836 /* Open -config specified file */
837 WineProfile
= PROFILE_Load ( f
);
839 strncpy(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
-1);
843 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
845 WineProfile
= PROFILE_Load( f
);
847 strncpy(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
-1);
850 if ((p
= getenv( "HOME" )) != NULL
)
852 lstrcpynA(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
853 strcat( buffer
, PROFILE_WineIniName
);
854 if ((f
= fopen( buffer
, "r" )) != NULL
)
856 WineProfile
= PROFILE_Load( f
);
858 strncpy(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
-1);
862 else WARN(profile
, "could not get $HOME value for config file.\n" );
864 /* Try global file */
866 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
868 WineProfile
= PROFILE_Load( f
);
870 strncpy(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
-1);
873 MSG( "Can't open configuration file %s or $HOME%s\n",
874 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
879 /***********************************************************************
880 * PROFILE_UsageWineIni
882 * Explain the wine.ini file to those who don't read documentation.
883 * Keep below one screenful in length so that error messages above are
886 void PROFILE_UsageWineIni(void)
888 MSG("Perhaps you have not properly edited or created "
889 "your Wine configuration file.\n");
890 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
891 MSG(" or it is determined by the -config option or from\n"
892 " the WINE_INI environment variable.\n");
893 if (*PROFILE_WineIniUsed
)
894 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
895 /* RTFM, so to say */
899 /***********************************************************************
900 * PROFILE_GetStringItem
902 * Convenience function that turns a string 'xxx, yyy, zzz' into
903 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
905 char* PROFILE_GetStringItem( char* start
)
909 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
913 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
915 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
917 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
920 if( lpch
) *lpch
= '\0';
925 /********************* API functions **********************************/
927 /***********************************************************************
928 * GetProfileInt16 (KERNEL.57)
930 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
932 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
936 /***********************************************************************
937 * GetProfileInt32A (KERNEL32.264)
939 UINT WINAPI
GetProfileIntA( LPCSTR section
, LPCSTR entry
, INT def_val
)
941 return GetPrivateProfileIntA( section
, entry
, def_val
, "win.ini" );
944 /***********************************************************************
945 * GetProfileInt32W (KERNEL32.264)
947 UINT WINAPI
GetProfileIntW( LPCWSTR section
, LPCWSTR entry
, INT def_val
)
949 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
950 return GetPrivateProfileIntW( section
, entry
, def_val
, wininiW
);
953 /***********************************************************************
954 * GetProfileString16 (KERNEL.58)
956 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
957 LPSTR buffer
, UINT16 len
)
959 return GetPrivateProfileString16( section
, entry
, def_val
,
960 buffer
, len
, "win.ini" );
963 /***********************************************************************
964 * GetProfileString32A (KERNEL32.268)
966 INT WINAPI
GetProfileStringA( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
967 LPSTR buffer
, UINT len
)
969 return GetPrivateProfileStringA( section
, entry
, def_val
,
970 buffer
, len
, "win.ini" );
973 /***********************************************************************
974 * GetProfileString32W (KERNEL32.269)
976 INT WINAPI
GetProfileStringW( LPCWSTR section
, LPCWSTR entry
,
977 LPCWSTR def_val
, LPWSTR buffer
, UINT len
)
979 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
980 return GetPrivateProfileStringW( section
, entry
, def_val
,
981 buffer
, len
, wininiW
);
984 /***********************************************************************
985 * GetProfileSection32A (KERNEL32.268)
987 INT WINAPI
GetProfileSectionA( LPCSTR section
, LPSTR buffer
, DWORD len
)
989 return GetPrivateProfileSectionA( section
, buffer
, len
, "win.ini" );
993 /***********************************************************************
994 * GetProfileSection32W (KERNEL32)
996 INT WINAPI
GetProfileSectionW( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
998 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
999 return GetPrivateProfileSectionW( section
, buffer
, len
, wininiW
);
1006 /***********************************************************************
1007 * WriteProfileString16 (KERNEL.59)
1009 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1012 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1015 /***********************************************************************
1016 * WriteProfileString32A (KERNEL32.587)
1018 BOOL WINAPI
WriteProfileStringA( LPCSTR section
, LPCSTR entry
,
1021 return WritePrivateProfileStringA( section
, entry
, string
, "win.ini" );
1024 /***********************************************************************
1025 * WriteProfileString32W (KERNEL32.588)
1027 BOOL WINAPI
WriteProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1030 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1031 return WritePrivateProfileStringW( section
, entry
, string
, wininiW
);
1035 /***********************************************************************
1036 * GetPrivateProfileInt16 (KERNEL.127)
1038 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1039 INT16 def_val
, LPCSTR filename
)
1041 long result
=(long)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
1043 if (result
> 65535) return 65535;
1044 if (result
>= 0) return (UINT16
)result
;
1045 if (result
< -32768) return -32768;
1046 return (UINT16
)(INT16
)result
;
1049 /***********************************************************************
1050 * GetPrivateProfileInt32A (KERNEL32.251)
1052 UINT WINAPI
GetPrivateProfileIntA( LPCSTR section
, LPCSTR entry
,
1053 INT def_val
, LPCSTR filename
)
1059 GetPrivateProfileStringA( section
, entry
, "",
1060 buffer
, sizeof(buffer
), filename
);
1061 if (!buffer
[0]) return (UINT
)def_val
;
1062 result
= strtol( buffer
, &p
, 0 );
1063 if (p
== buffer
) return 0; /* No digits at all */
1064 return (UINT
)result
;
1067 /***********************************************************************
1068 * GetPrivateProfileInt32W (KERNEL32.252)
1070 UINT WINAPI
GetPrivateProfileIntW( LPCWSTR section
, LPCWSTR entry
,
1071 INT def_val
, LPCWSTR filename
)
1073 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1074 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1075 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1076 UINT res
= GetPrivateProfileIntA(sectionA
, entryA
, def_val
, filenameA
);
1077 HeapFree( GetProcessHeap(), 0, sectionA
);
1078 HeapFree( GetProcessHeap(), 0, filenameA
);
1079 HeapFree( GetProcessHeap(), 0, entryA
);
1083 /***********************************************************************
1084 * GetPrivateProfileString16 (KERNEL.128)
1086 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1087 LPCSTR def_val
, LPSTR buffer
,
1088 UINT16 len
, LPCSTR filename
)
1090 return GetPrivateProfileStringA(section
,entry
,def_val
,buffer
,len
,filename
);
1093 /***********************************************************************
1094 * GetPrivateProfileString32A (KERNEL32.255)
1096 INT WINAPI
GetPrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1097 LPCSTR def_val
, LPSTR buffer
,
1098 UINT len
, LPCSTR filename
)
1101 filename
= "win.ini";
1102 if (PROFILE_Open( filename
))
1103 return PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1104 lstrcpynA( buffer
, def_val
, len
);
1105 return strlen( buffer
);
1108 /***********************************************************************
1109 * GetPrivateProfileString32W (KERNEL32.256)
1111 INT WINAPI
GetPrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1112 LPCWSTR def_val
, LPWSTR buffer
,
1113 UINT len
, LPCWSTR filename
)
1115 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1116 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1117 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1118 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1119 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1120 INT ret
= GetPrivateProfileStringA( sectionA
, entryA
, def_valA
,
1121 bufferA
, len
, filenameA
);
1122 lstrcpynAtoW( buffer
, bufferA
, len
);
1123 HeapFree( GetProcessHeap(), 0, sectionA
);
1124 HeapFree( GetProcessHeap(), 0, entryA
);
1125 HeapFree( GetProcessHeap(), 0, filenameA
);
1126 HeapFree( GetProcessHeap(), 0, def_valA
);
1127 HeapFree( GetProcessHeap(), 0, bufferA
);
1131 /***********************************************************************
1132 * GetPrivateProfileSection32A (KERNEL32.255)
1134 INT WINAPI
GetPrivateProfileSectionA( LPCSTR section
, LPSTR buffer
,
1135 DWORD len
, LPCSTR filename
)
1137 if (PROFILE_Open( filename
))
1138 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1144 /***********************************************************************
1145 * GetPrivateProfileSection32W (KERNEL32.256)
1148 INT WINAPI
GetPrivateProfileSectionW (LPCWSTR section
, LPWSTR buffer
,
1149 DWORD len
, LPCWSTR filename
)
1152 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1153 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1154 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1155 INT ret
= GetPrivateProfileSectionA( sectionA
, bufferA
, len
,
1157 HeapFree( GetProcessHeap(), 0, sectionA
);
1158 HeapFree( GetProcessHeap(), 0, filenameA
);
1159 HeapFree( GetProcessHeap(), 0, bufferA
);
1163 /***********************************************************************
1164 * WritePrivateProfileString16 (KERNEL.129)
1166 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1167 LPCSTR string
, LPCSTR filename
)
1169 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
1172 /***********************************************************************
1173 * WritePrivateProfileString32A (KERNEL32.582)
1175 BOOL WINAPI
WritePrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1176 LPCSTR string
, LPCSTR filename
)
1178 if (!PROFILE_Open( filename
)) return FALSE
;
1179 if (!section
) return PROFILE_FlushFile();
1180 return PROFILE_SetString( section
, entry
, string
);
1183 /***********************************************************************
1184 * WritePrivateProfileString32W (KERNEL32.583)
1186 BOOL WINAPI
WritePrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1187 LPCWSTR string
, LPCWSTR filename
)
1189 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1190 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1191 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1192 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1193 BOOL res
= WritePrivateProfileStringA( sectionA
, entryA
,
1194 stringA
, filenameA
);
1195 HeapFree( GetProcessHeap(), 0, sectionA
);
1196 HeapFree( GetProcessHeap(), 0, entryA
);
1197 HeapFree( GetProcessHeap(), 0, stringA
);
1198 HeapFree( GetProcessHeap(), 0, filenameA
);
1202 /***********************************************************************
1203 * WritePrivateProfileSection32A (KERNEL32)
1205 BOOL WINAPI
WritePrivateProfileSectionA( LPCSTR section
,
1206 LPCSTR string
, LPCSTR filename
)
1208 char *p
=(char*)string
;
1210 FIXME(profile
, "WritePrivateProfileSection32A empty stub\n");
1211 if (TRACE_ON(profile
)) {
1212 TRACE(profile
, "(%s) => [%s]\n", filename
, section
);
1214 TRACE(profile
, "%s\n", p
);
1223 /***********************************************************************
1224 * WritePrivateProfileSection32W (KERNEL32)
1226 BOOL WINAPI
WritePrivateProfileSectionW( LPCWSTR section
,
1227 LPCWSTR string
, LPCWSTR filename
)
1230 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1231 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1232 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1233 BOOL res
= WritePrivateProfileSectionA( sectionA
, stringA
, filenameA
);
1234 HeapFree( GetProcessHeap(), 0, sectionA
);
1235 HeapFree( GetProcessHeap(), 0, stringA
);
1236 HeapFree( GetProcessHeap(), 0, filenameA
);
1241 /***********************************************************************
1242 * WriteProfileSection32A (KERNEL32.747)
1244 BOOL WINAPI
WriteProfileSectionA( LPCSTR section
, LPCSTR keys_n_values
)
1247 return WritePrivateProfileSectionA( section
, keys_n_values
, "win.ini");
1250 /***********************************************************************
1251 * WriteProfileSection32W (KERNEL32.748)
1253 BOOL WINAPI
WriteProfileSectionW( LPCWSTR section
, LPCWSTR keys_n_values
)
1255 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini");
1257 return (WritePrivateProfileSectionW (section
,keys_n_values
, wininiW
));
1260 /***********************************************************************
1261 * GetPrivateProfileSectionNames16 (KERNEL.143)
1263 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1268 PROFILESECTION
*section
;
1270 if (PROFILE_Open( filename
)) {
1273 section
=CurProfile
->section
;
1274 for ( ; section
; section
= section
->next
)
1275 if (section
->name
) {
1276 l
=strlen (section
->name
);
1278 if (cursize
> size
+1)
1280 strcpy (buf
,section
->name
);
1287 return (buf
-buffer
);
1293 /***********************************************************************
1294 * GetProfileSectionNames16 (KERNEL.142)
1296 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1299 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1303 /***********************************************************************
1304 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1306 DWORD WINAPI
GetPrivateProfileSectionNamesA( LPSTR buffer
, DWORD size
,
1310 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1314 /***********************************************************************
1315 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1317 DWORD WINAPI
GetPrivateProfileSectionNamesW( LPWSTR buffer
, DWORD size
,
1321 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1322 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1324 INT ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1325 lstrcpynAtoW( buffer
, bufferA
, size
);
1326 HeapFree( GetProcessHeap(), 0, bufferA
);
1327 HeapFree( GetProcessHeap(), 0, filenameA
);
1333 /***********************************************************************
1334 * GetPrivateProfileStruct32A (KERNEL32.370)
1336 BOOL WINAPI
GetPrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1337 LPVOID buf
, UINT len
, LPCSTR filename
)
1341 if (PROFILE_Open( filename
)) {
1342 k
=PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1343 if (!k
) return FALSE
;
1344 lstrcpynA( buf
, k
->value
, strlen(k
->value
));
1350 /***********************************************************************
1351 * GetPrivateProfileStruct32W (KERNEL32.543)
1353 BOOL WINAPI
GetPrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1354 LPVOID buffer
, UINT len
, LPCWSTR filename
)
1356 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1357 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1358 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1359 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1361 INT ret
= GetPrivateProfileStructA( sectionA
, keyA
, bufferA
,
1363 lstrcpynAtoW( buffer
, bufferA
, len
);
1364 HeapFree( GetProcessHeap(), 0, bufferA
);
1365 HeapFree( GetProcessHeap(), 0, sectionA
);
1366 HeapFree( GetProcessHeap(), 0, keyA
);
1367 HeapFree( GetProcessHeap(), 0, filenameA
);
1375 /***********************************************************************
1376 * WritePrivateProfileStruct32A (KERNEL32.744)
1378 BOOL WINAPI
WritePrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1379 LPVOID buf
, UINT bufsize
, LPCSTR filename
)
1381 if ((!section
) && (!key
) && (!buf
)) { /* flush the cache */
1382 PROFILE_FlushFile();
1386 if (!PROFILE_Open( filename
)) return FALSE
;
1387 return PROFILE_SetString( section
, key
, buf
);
1390 /***********************************************************************
1391 * WritePrivateProfileStruct32W (KERNEL32.544)
1393 BOOL WINAPI
WritePrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1394 LPVOID buf
, UINT bufsize
, LPCWSTR filename
)
1396 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1397 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1398 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1399 INT ret
= WritePrivateProfileStructA( sectionA
, keyA
, buf
, bufsize
,
1401 HeapFree( GetProcessHeap(), 0, sectionA
);
1402 HeapFree( GetProcessHeap(), 0, keyA
);
1403 HeapFree( GetProcessHeap(), 0, filenameA
);
1409 /***********************************************************************
1410 * WriteOutProfiles (KERNEL.315)
1412 void WINAPI
WriteOutProfiles16(void)
1414 PROFILE_FlushFile();