4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
20 typedef struct tagPROFILEKEY
24 struct tagPROFILEKEY
*next
;
27 typedef struct tagPROFILESECTION
30 struct tagPROFILEKEY
*key
;
31 struct tagPROFILESECTION
*next
;
38 PROFILESECTION
*section
;
46 #define N_CACHED_PROFILES 10
48 /* Cached profile files */
49 static PROFILE
*MRUProfile
[N_CACHED_PROFILES
]={NULL
};
51 #define CurProfile (MRUProfile[0])
53 /* wine.ini profile content */
54 static PROFILESECTION
*WineProfile
;
56 #define PROFILE_MAX_LINE_LEN 1024
58 /* Wine profile name in $HOME directory; must begin with slash */
59 static const char PROFILE_WineIniName
[] = "/.winerc";
61 /* Wine profile: the profile file being used */
62 static char PROFILE_WineIniUsed
[MAX_PATHNAME_LEN
] = "";
64 /* Check for comments in profile */
65 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
67 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
69 static LPCWSTR wininiW
= NULL
;
71 /***********************************************************************
74 * Copy the content of an entry into a buffer, removing quotes, and possibly
75 * translating environment variables.
77 static void PROFILE_CopyEntry( char *buffer
, const char *value
, int len
,
83 if ((*value
== '\'') || (*value
== '\"'))
85 if (value
[1] && (value
[strlen(value
)-1] == *value
)) quote
= *value
++;
90 lstrcpyn32A( buffer
, value
, len
);
91 if (quote
&& (len
>= strlen(value
))) buffer
[strlen(buffer
)-1] = '\0';
95 for (p
= value
; (*p
&& (len
> 1)); *buffer
++ = *p
++, len
-- )
97 if ((*p
== '$') && (p
[1] == '{'))
101 const char *p2
= strchr( p
, '}' );
102 if (!p2
) continue; /* ignore it */
103 lstrcpyn32A(env_val
, p
+ 2, MIN( sizeof(env_val
), (int)(p2
-p
)-1 ));
104 if ((env_p
= getenv( env_val
)) != NULL
)
106 lstrcpyn32A( buffer
, env_p
, len
);
107 buffer
+= strlen( buffer
);
108 len
-= strlen( buffer
);
117 /***********************************************************************
120 * Save a profile tree to a file.
122 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
126 for ( ; section
; section
= section
->next
)
128 if (section
->name
) fprintf( file
, "\r\n[%s]\r\n", section
->name
);
129 for (key
= section
->key
; key
; key
= key
->next
)
131 fprintf( file
, "%s", key
->name
);
132 if (key
->value
) fprintf( file
, "=%s", key
->value
);
133 fprintf( file
, "\r\n" );
139 /***********************************************************************
142 * Free a profile tree.
144 static void PROFILE_Free( PROFILESECTION
*section
)
146 PROFILESECTION
*next_section
;
147 PROFILEKEY
*key
, *next_key
;
149 for ( ; section
; section
= next_section
)
151 if (section
->name
) HeapFree( SystemHeap
, 0, section
->name
);
152 for (key
= section
->key
; key
; key
= next_key
)
154 next_key
= key
->next
;
155 if (key
->name
) HeapFree( SystemHeap
, 0, key
->name
);
156 if (key
->value
) HeapFree( SystemHeap
, 0, key
->value
);
157 HeapFree( SystemHeap
, 0, key
);
159 next_section
= section
->next
;
160 HeapFree( SystemHeap
, 0, section
);
165 PROFILE_isspace(char c
) {
166 if (isspace(c
)) return 1;
167 if (c
=='\r' || c
==0x1a) return 1;
168 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
173 /***********************************************************************
176 * Load a profile tree from a file.
178 static PROFILESECTION
*PROFILE_Load( FILE *file
)
180 char buffer
[PROFILE_MAX_LINE_LEN
];
183 PROFILESECTION
*section
, *first_section
;
184 PROFILESECTION
**next_section
;
185 PROFILEKEY
*key
, *prev_key
, **next_key
;
187 first_section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
188 first_section
->name
= NULL
;
189 first_section
->key
= NULL
;
190 first_section
->next
= NULL
;
191 next_section
= &first_section
->next
;
192 next_key
= &first_section
->key
;
195 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
199 while (*p
&& PROFILE_isspace(*p
)) p
++;
200 if (*p
== '[') /* section start */
202 if (!(p2
= strrchr( p
, ']' )))
204 WARN(profile
, "Invalid section header at line %d: '%s'\n",
211 section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
212 section
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
214 section
->next
= NULL
;
215 *next_section
= section
;
216 next_section
= §ion
->next
;
217 next_key
= §ion
->key
;
220 TRACE(profile
, "New section: '%s'\n",section
->name
);
227 while ((p2
> p
) && ((*p2
== '\n') || PROFILE_isspace(*p2
))) *p2
--='\0';
229 if ((p2
= strchr( p
, '=' )) != NULL
)
232 while ((p3
> p
) && PROFILE_isspace(*p3
)) *p3
-- = '\0';
234 while (*p2
&& PROFILE_isspace(*p2
)) p2
++;
237 if(*p
|| !prev_key
|| *prev_key
->name
)
239 key
= HEAP_xalloc( SystemHeap
, 0, sizeof(*key
) );
240 key
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
241 key
->value
= p2
? HEAP_strdupA( SystemHeap
, 0, p2
) : NULL
;
244 next_key
= &key
->next
;
247 TRACE(profile
, "New key: name='%s', value='%s'\n",key
->name
,key
->value
?key
->value
:"(none)");
250 return first_section
;
254 /***********************************************************************
255 * PROFILE_DeleteSection
257 * Delete a section from a profile tree.
259 static BOOL32
PROFILE_DeleteSection( PROFILESECTION
**section
, LPCSTR name
)
263 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, name
))
265 PROFILESECTION
*to_del
= *section
;
266 *section
= to_del
->next
;
268 PROFILE_Free( to_del
);
271 section
= &(*section
)->next
;
277 /***********************************************************************
280 * Delete a key from a profile tree.
282 static BOOL32
PROFILE_DeleteKey( PROFILESECTION
**section
,
283 LPCSTR section_name
, LPCSTR key_name
)
287 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
289 PROFILEKEY
**key
= &(*section
)->key
;
292 if (!strcasecmp( (*key
)->name
, key_name
))
294 PROFILEKEY
*to_del
= *key
;
296 if (to_del
->name
) HeapFree( SystemHeap
, 0, to_del
->name
);
297 if (to_del
->value
) HeapFree( SystemHeap
, 0, to_del
->value
);
298 HeapFree( SystemHeap
, 0, to_del
);
304 section
= &(*section
)->next
;
310 /***********************************************************************
313 * Find a key in a profile tree, optionally creating it.
315 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
316 const char *section_name
,
317 const char *key_name
, int create
)
321 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
323 PROFILEKEY
**key
= &(*section
)->key
;
326 if (!strcasecmp( (*key
)->name
, key_name
)) return *key
;
329 if (!create
) return NULL
;
330 *key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
331 (*key
)->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
332 (*key
)->value
= NULL
;
336 section
= &(*section
)->next
;
338 if (!create
) return NULL
;
339 *section
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILESECTION
) );
340 (*section
)->name
= HEAP_strdupA( SystemHeap
, 0, section_name
);
341 (*section
)->next
= NULL
;
342 (*section
)->key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
343 (*section
)->key
->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
344 (*section
)->key
->value
= NULL
;
345 (*section
)->key
->next
= NULL
;
346 return (*section
)->key
;
350 /***********************************************************************
353 * Flush the current profile to disk if changed.
355 static BOOL32
PROFILE_FlushFile(void)
357 char *p
, buffer
[MAX_PATHNAME_LEN
];
358 const char *unix_name
;
364 WARN(profile
, "No current profile!\n");
368 if (!CurProfile
->changed
|| !CurProfile
->dos_name
) return TRUE
;
369 if (!(unix_name
= CurProfile
->unix_name
) || !(file
= fopen(unix_name
, "w")))
371 /* Try to create it in $HOME/.wine */
372 /* FIXME: this will need a more general solution */
373 if ((p
= getenv( "HOME" )) != NULL
)
376 strcat( buffer
, "/.wine/" );
377 p
= buffer
+ strlen(buffer
);
378 strcpy( p
, strrchr( CurProfile
->dos_name
, '\\' ) + 1 );
380 file
= fopen( buffer
, "w" );
387 WARN(profile
, "could not save profile file %s\n", CurProfile
->dos_name
);
391 TRACE(profile
, "Saving '%s' into '%s'\n", CurProfile
->dos_name
, unix_name
);
392 PROFILE_Save( file
, CurProfile
->section
);
394 CurProfile
->changed
= FALSE
;
395 if(!stat(unix_name
,&buf
))
396 CurProfile
->mtime
=buf
.st_mtime
;
401 /***********************************************************************
404 * Open a profile file, checking the cached file first.
406 static BOOL32
PROFILE_Open( LPCSTR filename
)
408 DOS_FULL_NAME full_name
;
409 char buffer
[MAX_PATHNAME_LEN
];
410 char *newdos_name
, *p
;
414 PROFILE
*tempProfile
;
416 /* First time around */
419 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
421 MRUProfile
[i
]=HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILE
) );
422 MRUProfile
[i
]->changed
=FALSE
;
423 MRUProfile
[i
]->section
=NULL
;
424 MRUProfile
[i
]->dos_name
=NULL
;
425 MRUProfile
[i
]->unix_name
=NULL
;
426 MRUProfile
[i
]->filename
=NULL
;
427 MRUProfile
[i
]->mtime
=0;
430 /* Check for a match */
432 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
433 strchr( filename
, ':' ))
435 if (!DOSFS_GetFullName( filename
, FALSE
, &full_name
)) return FALSE
;
439 GetWindowsDirectory32A( buffer
, sizeof(buffer
) );
440 strcat( buffer
, "\\" );
441 strcat( buffer
, filename
);
442 if (!DOSFS_GetFullName( buffer
, FALSE
, &full_name
)) return FALSE
;
445 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
447 if ((MRUProfile
[i
]->filename
&& !strcmp( filename
, MRUProfile
[i
]->filename
)) ||
448 (MRUProfile
[i
]->dos_name
&& !strcmp( full_name
.short_name
, MRUProfile
[i
]->dos_name
)))
453 tempProfile
=MRUProfile
[i
];
455 MRUProfile
[j
]=MRUProfile
[j
-1];
456 CurProfile
=tempProfile
;
458 if(!stat(CurProfile
->unix_name
,&buf
) && CurProfile
->mtime
==buf
.st_mtime
)
459 TRACE(profile
, "(%s): already opened (mru=%d)\n",
462 TRACE(profile
, "(%s): already opened, needs refreshing (mru=%d)\n",
468 /* Rotate the oldest to the top to be replaced */
470 if(i
==N_CACHED_PROFILES
)
472 tempProfile
=MRUProfile
[N_CACHED_PROFILES
-1];
473 for(i
=N_CACHED_PROFILES
-1;i
>0;i
--)
474 MRUProfile
[i
]=MRUProfile
[i
-1];
475 CurProfile
=tempProfile
;
478 /* Flush the profile */
480 if(CurProfile
->filename
)
483 PROFILE_Free( CurProfile
->section
);
484 if (CurProfile
->dos_name
) HeapFree( SystemHeap
, 0, CurProfile
->dos_name
);
485 if (CurProfile
->unix_name
) HeapFree( SystemHeap
, 0, CurProfile
->unix_name
);
486 if (CurProfile
->filename
) HeapFree( SystemHeap
, 0, CurProfile
->filename
);
487 CurProfile
->changed
=FALSE
;
488 CurProfile
->section
=NULL
;
489 CurProfile
->dos_name
=NULL
;
490 CurProfile
->unix_name
=NULL
;
491 CurProfile
->filename
=NULL
;
495 newdos_name
= HEAP_strdupA( SystemHeap
, 0, full_name
.short_name
);
496 CurProfile
->dos_name
= newdos_name
;
497 CurProfile
->filename
= HEAP_strdupA( SystemHeap
, 0, filename
);
499 /* Try to open the profile file, first in $HOME/.wine */
501 /* FIXME: this will need a more general solution */
502 if ((p
= getenv( "HOME" )) != NULL
)
505 strcat( buffer
, "/.wine/" );
506 p
= buffer
+ strlen(buffer
);
507 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
509 if ((file
= fopen( buffer
, "r" )))
511 TRACE(profile
, "(%s): found it in %s\n",
513 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0, buffer
);
519 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0,
520 full_name
.long_name
);
521 if ((file
= fopen( full_name
.long_name
, "r" )))
522 TRACE(profile
, "(%s): found it in %s\n",
523 filename
, full_name
.long_name
);
528 CurProfile
->section
= PROFILE_Load( file
);
530 if(!stat(CurProfile
->unix_name
,&buf
))
531 CurProfile
->mtime
=buf
.st_mtime
;
535 /* Does not exist yet, we will create it in PROFILE_FlushFile */
536 WARN(profile
, "profile file %s not found\n", newdos_name
);
542 /***********************************************************************
545 * Returns all keys of a section.
546 * If return_values is TRUE, also include the corresponding values.
548 static INT32
PROFILE_GetSection( PROFILESECTION
*section
, LPCSTR section_name
,
549 LPSTR buffer
, UINT32 len
, BOOL32 handle_env
,
550 BOOL32 return_values
)
555 if (section
->name
&& !strcasecmp( section
->name
, section_name
))
558 for (key
= section
->key
; key
; key
= key
->next
)
561 if (!*key
->name
) continue; /* Skip empty lines */
562 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
563 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
564 len
-= strlen(buffer
) + 1;
565 buffer
+= strlen(buffer
) + 1;
566 if (return_values
&& key
->value
) {
568 PROFILE_CopyEntry ( buffer
,
569 key
->value
, len
- 1, handle_env
);
570 len
-= strlen(buffer
) + 1;
571 buffer
+= strlen(buffer
) + 1;
576 /*If either lpszSection or lpszKey is NULL and the supplied
577 destination buffer is too small to hold all the strings,
578 the last string is truncated and followed by two null characters.
579 In this case, the return value is equal to cchReturnBuffer
587 section
= section
->next
;
589 buffer
[0] = buffer
[1] = '\0';
594 /***********************************************************************
597 * Get a profile string.
599 static INT32
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
600 LPCSTR def_val
, LPSTR buffer
, UINT32 len
)
602 PROFILEKEY
*key
= NULL
;
604 if (!def_val
) def_val
= "";
605 if (key_name
&& key_name
[0])
607 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
608 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
610 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
611 section
, key_name
, def_val
, buffer
);
612 return strlen( buffer
);
614 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
619 /***********************************************************************
622 * Set a profile string.
624 static BOOL32
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
627 if (!key_name
) /* Delete a whole section */
629 TRACE(profile
, "('%s')\n", section_name
);
630 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
632 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
633 this is not an error on application's level.*/
635 else if (!value
) /* Delete a key */
637 TRACE(profile
, "('%s','%s')\n",
638 section_name
, key_name
);
639 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
640 section_name
, key_name
);
641 return TRUE
; /* same error handling as above */
643 else /* Set the key value */
645 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
647 TRACE(profile
, "('%s','%s','%s'): \n",
648 section_name
, key_name
, value
);
649 if (!key
) return FALSE
;
652 if (!strcmp( key
->value
, value
))
654 TRACE(profile
, " no change needed\n" );
655 return TRUE
; /* No change needed */
657 TRACE(profile
, " replacing '%s'\n", key
->value
);
658 HeapFree( SystemHeap
, 0, key
->value
);
660 else TRACE(profile
, " creating key\n" );
661 key
->value
= HEAP_strdupA( SystemHeap
, 0, value
);
662 CurProfile
->changed
= TRUE
;
668 /***********************************************************************
669 * PROFILE_GetWineIniString
671 * Get a config string from the wine.ini file.
673 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
674 const char *def
, char *buffer
, int len
)
678 PROFILEKEY
*key
= PROFILE_Find(&WineProfile
, section
, key_name
, FALSE
);
679 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
681 TRACE(profile
, "('%s','%s','%s'): returning '%s'\n",
682 section
, key_name
, def
, buffer
);
683 return strlen( buffer
);
685 return PROFILE_GetSection( WineProfile
, section
, buffer
, len
, TRUE
, FALSE
);
689 /***********************************************************************
690 * PROFILE_GetWineIniInt
692 * Get a config integer from the wine.ini file.
694 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
700 PROFILEKEY
*key
= PROFILE_Find( &WineProfile
, section
, key_name
, FALSE
);
701 if (!key
|| !key
->value
) return def
;
702 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
703 result
= strtol( buffer
, &p
, 0 );
704 if (p
== buffer
) return 0; /* No digits at all */
709 /******************************************************************************
711 * int PROFILE_EnumerateWineIniSection(
712 * char const *section, #Name of the section to enumerate
713 * void (*cbfn)(char const *key, char const *value, void *user),
714 * # Address of the callback function
715 * void *user ) # User-specified pointer.
717 * For each entry in a section in the wine.conf file, this function will
718 * call the specified callback function, informing it of each key and
719 * value. An optional user pointer may be passed to it (if this is not
720 * needed, pass NULL through it and ignore the value in the callback
723 * The callback function must accept three parameters:
724 * The name of the key (char const *)
725 * The value of the key (char const *)
726 * A user-specified parameter (void *)
727 * Note that the first two are char CONST *'s, not char *'s! The callback
728 * MUST not modify these strings!
730 * The return value indicates the number of times the callback function
733 int PROFILE_EnumerateWineIniSection(
735 void (*cbfn
)(char const *, char const *, void *),
738 PROFILESECTION
*scansect
;
742 /* Search for the correct section */
743 for(scansect
= WineProfile
; scansect
; scansect
= scansect
->next
) {
744 if(scansect
->name
&& !strcasecmp(scansect
->name
, section
)) {
746 /* Enumerate each key with the callback */
747 for(scankey
= scansect
->key
; scankey
; scankey
= scankey
->next
) {
749 /* Ignore blank entries -- these shouldn't exist, but let's
751 if(scankey
->name
[0]) {
752 cbfn(scankey
->name
, scankey
->value
, userptr
);
765 /******************************************************************************
767 * int PROFILE_GetWineIniBool(
768 * char const *section,
769 * char const *key_name,
772 * Reads a boolean value from the wine.ini file. This function attempts to
773 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
774 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
775 * true. Anything else results in the return of the default value.
777 * This function uses 1 to indicate true, and 0 for false. You can check
778 * for existence by setting def to something other than 0 or 1 and
779 * examining the return value.
781 int PROFILE_GetWineIniBool(
783 char const *key_name
,
789 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
791 switch(key_value
[0]) {
812 TRACE(profile
, "(\"%s\", \"%s\", %s), "
813 "[%c], ret %s.\n", section
, key_name
,
814 def
? "TRUE" : "FALSE", key_value
[0],
815 retval
? "TRUE" : "FALSE");
821 /***********************************************************************
822 * PROFILE_LoadWineIni
824 * Load the wine.ini file.
826 int PROFILE_LoadWineIni(void)
828 char buffer
[MAX_PATHNAME_LEN
];
832 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
834 /* Open -config specified file */
835 WineProfile
= PROFILE_Load ( f
);
837 strncpy(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
-1);
841 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
843 WineProfile
= PROFILE_Load( f
);
845 strncpy(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
-1);
848 if ((p
= getenv( "HOME" )) != NULL
)
850 lstrcpyn32A(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
851 strcat( buffer
, PROFILE_WineIniName
);
852 if ((f
= fopen( buffer
, "r" )) != NULL
)
854 WineProfile
= PROFILE_Load( f
);
856 strncpy(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
-1);
860 else WARN(profile
, "could not get $HOME value for config file.\n" );
862 /* Try global file */
864 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
866 WineProfile
= PROFILE_Load( f
);
868 strncpy(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
-1);
871 MSG( "Can't open configuration file %s or $HOME%s\n",
872 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
877 /***********************************************************************
878 * PROFILE_UsageWineIni
880 * Explain the wine.ini file to those who don't read documentation.
881 * Keep below one screenful in length so that error messages above are
884 void PROFILE_UsageWineIni(void)
886 MSG("Perhaps you have not properly edited or created "
887 "your Wine configuration file.\n");
888 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
889 MSG(" or it is determined by the -config option or from\n"
890 " the WINE_INI environment variable.\n");
891 if (*PROFILE_WineIniUsed
)
892 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
893 /* RTFM, so to say */
897 /***********************************************************************
898 * PROFILE_GetStringItem
900 * Convenience function that turns a string 'xxx, yyy, zzz' into
901 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
903 char* PROFILE_GetStringItem( char* start
)
907 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
911 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
913 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
915 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
918 if( lpch
) *lpch
= '\0';
923 /********************* API functions **********************************/
925 /***********************************************************************
926 * GetProfileInt16 (KERNEL.57)
928 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
930 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
934 /***********************************************************************
935 * GetProfileInt32A (KERNEL32.264)
937 UINT32 WINAPI
GetProfileInt32A( LPCSTR section
, LPCSTR entry
, INT32 def_val
)
939 return GetPrivateProfileInt32A( section
, entry
, def_val
, "win.ini" );
942 /***********************************************************************
943 * GetProfileInt32W (KERNEL32.264)
945 UINT32 WINAPI
GetProfileInt32W( LPCWSTR section
, LPCWSTR entry
, INT32 def_val
)
947 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
948 return GetPrivateProfileInt32W( section
, entry
, def_val
, wininiW
);
951 /***********************************************************************
952 * GetProfileString16 (KERNEL.58)
954 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
955 LPSTR buffer
, UINT16 len
)
957 return GetPrivateProfileString16( section
, entry
, def_val
,
958 buffer
, len
, "win.ini" );
961 /***********************************************************************
962 * GetProfileString32A (KERNEL32.268)
964 INT32 WINAPI
GetProfileString32A( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
965 LPSTR buffer
, UINT32 len
)
967 return GetPrivateProfileString32A( section
, entry
, def_val
,
968 buffer
, len
, "win.ini" );
971 /***********************************************************************
972 * GetProfileString32W (KERNEL32.269)
974 INT32 WINAPI
GetProfileString32W( LPCWSTR section
, LPCWSTR entry
,
975 LPCWSTR def_val
, LPWSTR buffer
, UINT32 len
)
977 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
978 return GetPrivateProfileString32W( section
, entry
, def_val
,
979 buffer
, len
, wininiW
);
982 /***********************************************************************
983 * GetProfileSection32A (KERNEL32.268)
985 INT32 WINAPI
GetProfileSection32A( LPCSTR section
, LPSTR buffer
, DWORD len
)
987 return GetPrivateProfileSection32A( section
, buffer
, len
, "win.ini" );
991 /***********************************************************************
992 * GetProfileSection32W (KERNEL32)
994 INT32 WINAPI
GetProfileSection32W( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
996 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
997 return GetPrivateProfileSection32W( section
, buffer
, len
, wininiW
);
1004 /***********************************************************************
1005 * WriteProfileString16 (KERNEL.59)
1007 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1010 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1013 /***********************************************************************
1014 * WriteProfileString32A (KERNEL32.587)
1016 BOOL32 WINAPI
WriteProfileString32A( LPCSTR section
, LPCSTR entry
,
1019 return WritePrivateProfileString32A( section
, entry
, string
, "win.ini" );
1022 /***********************************************************************
1023 * WriteProfileString32W (KERNEL32.588)
1025 BOOL32 WINAPI
WriteProfileString32W( LPCWSTR section
, LPCWSTR entry
,
1028 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1029 return WritePrivateProfileString32W( section
, entry
, string
, wininiW
);
1033 /***********************************************************************
1034 * GetPrivateProfileInt16 (KERNEL.127)
1036 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1037 INT16 def_val
, LPCSTR filename
)
1039 long result
=(long)GetPrivateProfileInt32A(section
,entry
,def_val
,filename
);
1041 if (result
> 65535) return 65535;
1042 if (result
>= 0) return (UINT16
)result
;
1043 if (result
< -32768) return -32768;
1044 return (UINT16
)(INT16
)result
;
1047 /***********************************************************************
1048 * GetPrivateProfileInt32A (KERNEL32.251)
1050 UINT32 WINAPI
GetPrivateProfileInt32A( LPCSTR section
, LPCSTR entry
,
1051 INT32 def_val
, LPCSTR filename
)
1057 GetPrivateProfileString32A( section
, entry
, "",
1058 buffer
, sizeof(buffer
), filename
);
1059 if (!buffer
[0]) return (UINT32
)def_val
;
1060 result
= strtol( buffer
, &p
, 0 );
1061 if (p
== buffer
) return 0; /* No digits at all */
1062 return (UINT32
)result
;
1065 /***********************************************************************
1066 * GetPrivateProfileInt32W (KERNEL32.252)
1068 UINT32 WINAPI
GetPrivateProfileInt32W( LPCWSTR section
, LPCWSTR entry
,
1069 INT32 def_val
, LPCWSTR filename
)
1071 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1072 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1073 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1074 UINT32 res
= GetPrivateProfileInt32A(sectionA
, entryA
, def_val
, filenameA
);
1075 HeapFree( GetProcessHeap(), 0, sectionA
);
1076 HeapFree( GetProcessHeap(), 0, filenameA
);
1077 HeapFree( GetProcessHeap(), 0, entryA
);
1081 /***********************************************************************
1082 * GetPrivateProfileString16 (KERNEL.128)
1084 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1085 LPCSTR def_val
, LPSTR buffer
,
1086 UINT16 len
, LPCSTR filename
)
1088 return GetPrivateProfileString32A(section
,entry
,def_val
,buffer
,len
,filename
);
1091 /***********************************************************************
1092 * GetPrivateProfileString32A (KERNEL32.255)
1094 INT32 WINAPI
GetPrivateProfileString32A( LPCSTR section
, LPCSTR entry
,
1095 LPCSTR def_val
, LPSTR buffer
,
1096 UINT32 len
, LPCSTR filename
)
1099 filename
= "win.ini";
1100 if (PROFILE_Open( filename
))
1101 return PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1102 lstrcpyn32A( buffer
, def_val
, len
);
1103 return strlen( buffer
);
1106 /***********************************************************************
1107 * GetPrivateProfileString32W (KERNEL32.256)
1109 INT32 WINAPI
GetPrivateProfileString32W( LPCWSTR section
, LPCWSTR entry
,
1110 LPCWSTR def_val
, LPWSTR buffer
,
1111 UINT32 len
, LPCWSTR filename
)
1113 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1114 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1115 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1116 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1117 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1118 INT32 ret
= GetPrivateProfileString32A( sectionA
, entryA
, def_valA
,
1119 bufferA
, len
, filenameA
);
1120 lstrcpynAtoW( buffer
, bufferA
, len
);
1121 HeapFree( GetProcessHeap(), 0, sectionA
);
1122 HeapFree( GetProcessHeap(), 0, entryA
);
1123 HeapFree( GetProcessHeap(), 0, filenameA
);
1124 HeapFree( GetProcessHeap(), 0, def_valA
);
1125 HeapFree( GetProcessHeap(), 0, bufferA
);
1129 /***********************************************************************
1130 * GetPrivateProfileSection32A (KERNEL32.255)
1132 INT32 WINAPI
GetPrivateProfileSection32A( LPCSTR section
, LPSTR buffer
,
1133 DWORD len
, LPCSTR filename
)
1135 if (PROFILE_Open( filename
))
1136 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1142 /***********************************************************************
1143 * GetPrivateProfileSection32W (KERNEL32.256)
1146 INT32 WINAPI
GetPrivateProfileSection32W (LPCWSTR section
, LPWSTR buffer
,
1147 DWORD len
, LPCWSTR filename
)
1150 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1151 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1152 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1153 INT32 ret
= GetPrivateProfileSection32A( sectionA
, bufferA
, len
,
1155 HeapFree( GetProcessHeap(), 0, sectionA
);
1156 HeapFree( GetProcessHeap(), 0, filenameA
);
1157 HeapFree( GetProcessHeap(), 0, bufferA
);
1161 /***********************************************************************
1162 * WritePrivateProfileString16 (KERNEL.129)
1164 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1165 LPCSTR string
, LPCSTR filename
)
1167 return WritePrivateProfileString32A(section
,entry
,string
,filename
);
1170 /***********************************************************************
1171 * WritePrivateProfileString32A (KERNEL32.582)
1173 BOOL32 WINAPI
WritePrivateProfileString32A( LPCSTR section
, LPCSTR entry
,
1174 LPCSTR string
, LPCSTR filename
)
1176 if (!PROFILE_Open( filename
)) return FALSE
;
1177 if (!section
) return PROFILE_FlushFile();
1178 return PROFILE_SetString( section
, entry
, string
);
1181 /***********************************************************************
1182 * WritePrivateProfileString32W (KERNEL32.583)
1184 BOOL32 WINAPI
WritePrivateProfileString32W( LPCWSTR section
, LPCWSTR entry
,
1185 LPCWSTR string
, LPCWSTR filename
)
1187 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1188 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1189 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1190 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1191 BOOL32 res
= WritePrivateProfileString32A( sectionA
, entryA
,
1192 stringA
, filenameA
);
1193 HeapFree( GetProcessHeap(), 0, sectionA
);
1194 HeapFree( GetProcessHeap(), 0, entryA
);
1195 HeapFree( GetProcessHeap(), 0, stringA
);
1196 HeapFree( GetProcessHeap(), 0, filenameA
);
1200 /***********************************************************************
1201 * WritePrivateProfileSection32A (KERNEL32)
1203 BOOL32 WINAPI
WritePrivateProfileSection32A( LPCSTR section
,
1204 LPCSTR string
, LPCSTR filename
)
1206 char *p
=(char*)string
;
1208 FIXME(profile
, "WritePrivateProfileSection32A empty stub\n");
1209 if (TRACE_ON(profile
)) {
1210 TRACE(profile
, "(%s) => [%s]\n", filename
, section
);
1212 TRACE(profile
, "%s\n", p
);
1221 /***********************************************************************
1222 * WritePrivateProfileSection32W (KERNEL32)
1224 BOOL32 WINAPI
WritePrivateProfileSection32W( LPCWSTR section
,
1225 LPCWSTR string
, LPCWSTR filename
)
1228 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1229 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1230 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1231 BOOL32 res
= WritePrivateProfileSection32A( sectionA
, stringA
, filenameA
);
1232 HeapFree( GetProcessHeap(), 0, sectionA
);
1233 HeapFree( GetProcessHeap(), 0, stringA
);
1234 HeapFree( GetProcessHeap(), 0, filenameA
);
1239 /***********************************************************************
1240 * WriteProfileSection32A (KERNEL32.747)
1242 BOOL32 WINAPI
WriteProfileSection32A( LPCSTR section
, LPCSTR keys_n_values
)
1245 return WritePrivateProfileSection32A( section
, keys_n_values
, "win.ini");
1248 /***********************************************************************
1249 * WriteProfileSection32W (KERNEL32.748)
1251 BOOL32 WINAPI
WriteProfileSection32W( LPCWSTR section
, LPCWSTR keys_n_values
)
1253 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini");
1255 return (WritePrivateProfileSection32W (section
,keys_n_values
, wininiW
));
1258 /***********************************************************************
1259 * GetPrivateProfileSectionNames16 (KERNEL.143)
1261 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1266 PROFILESECTION
*section
;
1268 if (PROFILE_Open( filename
)) {
1271 section
=CurProfile
->section
;
1272 for ( ; section
; section
= section
->next
)
1273 if (section
->name
) {
1274 l
=strlen (section
->name
);
1276 if (cursize
> size
+1)
1278 strcpy (buf
,section
->name
);
1285 return (buf
-buffer
);
1291 /***********************************************************************
1292 * GetProfileSectionNames16 (KERNEL.142)
1294 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1297 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1301 /***********************************************************************
1302 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1304 DWORD WINAPI
GetPrivateProfileSectionNames32A( LPSTR buffer
, DWORD size
,
1308 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1312 /***********************************************************************
1313 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1315 DWORD WINAPI
GetPrivateProfileSectionNames32W( LPWSTR buffer
, DWORD size
,
1319 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1320 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1322 INT32 ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1323 lstrcpynAtoW( buffer
, bufferA
, size
);
1324 HeapFree( GetProcessHeap(), 0, bufferA
);
1325 HeapFree( GetProcessHeap(), 0, filenameA
);
1331 /***********************************************************************
1332 * GetPrivateProfileStruct32A (KERNEL32.370)
1334 BOOL32 WINAPI
GetPrivateProfileStruct32A (LPCSTR section
, LPCSTR key
,
1335 LPVOID buf
, UINT32 len
, LPCSTR filename
)
1339 if (PROFILE_Open( filename
)) {
1340 k
=PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1341 if (!k
) return FALSE
;
1342 lstrcpyn32A( buf
, k
->value
, strlen(k
->value
));
1348 /***********************************************************************
1349 * GetPrivateProfileStruct32W (KERNEL32.543)
1351 BOOL32 WINAPI
GetPrivateProfileStruct32W (LPCWSTR section
, LPCWSTR key
,
1352 LPVOID buffer
, UINT32 len
, LPCWSTR filename
)
1354 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1355 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1356 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1357 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1359 INT32 ret
= GetPrivateProfileStruct32A( sectionA
, keyA
, bufferA
,
1361 lstrcpynAtoW( buffer
, bufferA
, len
);
1362 HeapFree( GetProcessHeap(), 0, bufferA
);
1363 HeapFree( GetProcessHeap(), 0, sectionA
);
1364 HeapFree( GetProcessHeap(), 0, keyA
);
1365 HeapFree( GetProcessHeap(), 0, filenameA
);
1373 /***********************************************************************
1374 * WritePrivateProfileStruct32A (KERNEL32.744)
1376 BOOL32 WINAPI
WritePrivateProfileStruct32A (LPCSTR section
, LPCSTR key
,
1377 LPVOID buf
, UINT32 bufsize
, LPCSTR filename
)
1379 if ((!section
) && (!key
) && (!buf
)) { /* flush the cache */
1380 PROFILE_FlushFile();
1384 if (!PROFILE_Open( filename
)) return FALSE
;
1385 return PROFILE_SetString( section
, key
, buf
);
1388 /***********************************************************************
1389 * WritePrivateProfileStruct32W (KERNEL32.544)
1391 BOOL32 WINAPI
WritePrivateProfileStruct32W (LPCWSTR section
, LPCWSTR key
,
1392 LPVOID buf
, UINT32 bufsize
, LPCWSTR filename
)
1394 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1395 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1396 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1397 INT32 ret
= WritePrivateProfileStruct32A( sectionA
, keyA
, buf
, bufsize
,
1399 HeapFree( GetProcessHeap(), 0, sectionA
);
1400 HeapFree( GetProcessHeap(), 0, keyA
);
1401 HeapFree( GetProcessHeap(), 0, filenameA
);
1407 /***********************************************************************
1408 * WriteOutProfiles (KERNEL.315)
1410 void WINAPI
WriteOutProfiles(void)
1412 PROFILE_FlushFile();