Fixes for compile on non-Intel platforms.
[wine/hacks.git] / files / profile.c
blob0d5a13300931c8fb99f92b28041ebad9845884fe
1 /*
2 * Profile functions
4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
6 */
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <string.h>
12 #include <sys/stat.h>
14 #include "winbase.h"
15 #include "wine/winbase16.h"
16 #include "winuser.h"
17 #include "winnls.h"
18 #include "file.h"
19 #include "heap.h"
20 #include "debug.h"
21 #include "options.h"
23 DEFAULT_DEBUG_CHANNEL(profile)
25 typedef struct tagPROFILEKEY
27 char *name;
28 char *value;
29 struct tagPROFILEKEY *next;
30 } PROFILEKEY;
32 typedef struct tagPROFILESECTION
34 char *name;
35 struct tagPROFILEKEY *key;
36 struct tagPROFILESECTION *next;
37 } PROFILESECTION;
40 typedef struct
42 BOOL changed;
43 PROFILESECTION *section;
44 char *dos_name;
45 char *unix_name;
46 char *filename;
47 time_t mtime;
48 } PROFILE;
51 #define N_CACHED_PROFILES 10
53 /* Cached profile files */
54 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
56 #define CurProfile (MRUProfile[0])
58 /* wine.ini profile content */
59 static PROFILESECTION *PROFILE_WineProfile;
61 #define PROFILE_MAX_LINE_LEN 1024
63 /* Wine profile name in $HOME directory; must begin with slash */
64 static const char PROFILE_WineIniName[] = "/.winerc";
66 /* Wine profile: the profile file being used */
67 static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
69 /* Check for comments in profile */
70 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
72 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
74 static LPCWSTR wininiW = NULL;
76 static CRITICAL_SECTION PROFILE_CritSect;
78 /***********************************************************************
79 * PROFILE_CopyEntry
81 * Copy the content of an entry into a buffer, removing quotes, and possibly
82 * translating environment variables.
84 static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
85 int handle_env )
87 char quote = '\0';
88 const char *p;
90 if ((*value == '\'') || (*value == '\"'))
92 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
95 if (!handle_env)
97 lstrcpynA( buffer, value, len );
98 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
99 return;
102 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
104 if ((*p == '$') && (p[1] == '{'))
106 char env_val[1024];
107 const char *env_p;
108 const char *p2 = strchr( p, '}' );
109 if (!p2) continue; /* ignore it */
110 lstrcpynA(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
111 if ((env_p = getenv( env_val )) != NULL)
113 lstrcpynA( buffer, env_p, len );
114 buffer += strlen( buffer );
115 len -= strlen( buffer );
117 p = p2 + 1;
120 *buffer = '\0';
124 /***********************************************************************
125 * PROFILE_Save
127 * Save a profile tree to a file.
129 static void PROFILE_Save( FILE *file, PROFILESECTION *section )
131 PROFILEKEY *key;
133 for ( ; section; section = section->next)
135 if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
136 for (key = section->key; key; key = key->next)
138 fprintf( file, "%s", key->name );
139 if (key->value) fprintf( file, "=%s", key->value );
140 fprintf( file, "\r\n" );
146 /***********************************************************************
147 * PROFILE_Free
149 * Free a profile tree.
151 static void PROFILE_Free( PROFILESECTION *section )
153 PROFILESECTION *next_section;
154 PROFILEKEY *key, *next_key;
156 for ( ; section; section = next_section)
158 if (section->name) HeapFree( SystemHeap, 0, section->name );
159 for (key = section->key; key; key = next_key)
161 next_key = key->next;
162 if (key->name) HeapFree( SystemHeap, 0, key->name );
163 if (key->value) HeapFree( SystemHeap, 0, key->value );
164 HeapFree( SystemHeap, 0, key );
166 next_section = section->next;
167 HeapFree( SystemHeap, 0, section );
171 static int
172 PROFILE_isspace(char c) {
173 if (isspace(c)) return 1;
174 if (c=='\r' || c==0x1a) return 1;
175 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
176 return 0;
180 /***********************************************************************
181 * PROFILE_Load
183 * Load a profile tree from a file.
185 static PROFILESECTION *PROFILE_Load( FILE *file )
187 char buffer[PROFILE_MAX_LINE_LEN];
188 char *p, *p2;
189 int line = 0;
190 PROFILESECTION *section, *first_section;
191 PROFILESECTION **next_section;
192 PROFILEKEY *key, *prev_key, **next_key;
194 first_section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
195 first_section->name = NULL;
196 first_section->key = NULL;
197 first_section->next = NULL;
198 next_section = &first_section->next;
199 next_key = &first_section->key;
200 prev_key = NULL;
202 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
204 line++;
205 p = buffer;
206 while (*p && PROFILE_isspace(*p)) p++;
207 if (*p == '[') /* section start */
209 if (!(p2 = strrchr( p, ']' )))
211 WARN(profile, "Invalid section header at line %d: '%s'\n",
212 line, p );
214 else
216 *p2 = '\0';
217 p++;
218 section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
219 section->name = HEAP_strdupA( SystemHeap, 0, p );
220 section->key = NULL;
221 section->next = NULL;
222 *next_section = section;
223 next_section = &section->next;
224 next_key = &section->key;
225 prev_key = NULL;
227 TRACE(profile, "New section: '%s'\n",section->name);
229 continue;
233 p2=p+strlen(p) - 1;
234 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
236 if ((p2 = strchr( p, '=' )) != NULL)
238 char *p3 = p2 - 1;
239 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
240 *p2++ = '\0';
241 while (*p2 && PROFILE_isspace(*p2)) p2++;
244 if(*p || !prev_key || *prev_key->name)
246 key = HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
247 key->name = HEAP_strdupA( SystemHeap, 0, p );
248 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
249 key->next = NULL;
250 *next_key = key;
251 next_key = &key->next;
252 prev_key = key;
254 TRACE(profile, "New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)");
257 return first_section;
261 /***********************************************************************
262 * PROFILE_DeleteSection
264 * Delete a section from a profile tree.
266 static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
268 while (*section)
270 if ((*section)->name && !strcasecmp( (*section)->name, name ))
272 PROFILESECTION *to_del = *section;
273 *section = to_del->next;
274 to_del->next = NULL;
275 PROFILE_Free( to_del );
276 return TRUE;
278 section = &(*section)->next;
280 return FALSE;
284 /***********************************************************************
285 * PROFILE_DeleteKey
287 * Delete a key from a profile tree.
289 static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
290 LPCSTR section_name, LPCSTR key_name )
292 while (*section)
294 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
296 PROFILEKEY **key = &(*section)->key;
297 while (*key)
299 if (!strcasecmp( (*key)->name, key_name ))
301 PROFILEKEY *to_del = *key;
302 *key = to_del->next;
303 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
304 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
305 HeapFree( SystemHeap, 0, to_del );
306 return TRUE;
308 key = &(*key)->next;
311 section = &(*section)->next;
313 return FALSE;
317 /***********************************************************************
318 * PROFILE_Find
320 * Find a key in a profile tree, optionally creating it.
322 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
323 const char *section_name,
324 const char *key_name, int create )
326 while (*section)
328 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
330 PROFILEKEY **key = &(*section)->key;
331 while (*key)
333 if (!strcasecmp( (*key)->name, key_name )) return *key;
334 key = &(*key)->next;
336 if (!create) return NULL;
337 *key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
338 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
339 (*key)->value = NULL;
340 (*key)->next = NULL;
341 return *key;
343 section = &(*section)->next;
345 if (!create) return NULL;
346 *section = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
347 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
348 (*section)->next = NULL;
349 (*section)->key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
350 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
351 (*section)->key->value = NULL;
352 (*section)->key->next = NULL;
353 return (*section)->key;
357 /***********************************************************************
358 * PROFILE_FlushFile
360 * Flush the current profile to disk if changed.
362 static BOOL PROFILE_FlushFile(void)
364 char *p, buffer[MAX_PATHNAME_LEN];
365 const char *unix_name;
366 FILE *file = NULL;
367 struct stat buf;
369 if(!CurProfile)
371 WARN(profile, "No current profile!\n");
372 return FALSE;
375 if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
376 if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
378 /* Try to create it in $HOME/.wine */
379 /* FIXME: this will need a more general solution */
380 if ((p = getenv( "HOME" )) != NULL)
382 strcpy( buffer, p );
383 strcat( buffer, "/.wine/" );
384 p = buffer + strlen(buffer);
385 strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
386 CharLowerA( p );
387 file = fopen( buffer, "w" );
388 unix_name = buffer;
392 if (!file)
394 WARN(profile, "could not save profile file %s\n", CurProfile->dos_name);
395 return FALSE;
398 TRACE(profile, "Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name );
399 PROFILE_Save( file, CurProfile->section );
400 fclose( file );
401 CurProfile->changed = FALSE;
402 if(!stat(unix_name,&buf))
403 CurProfile->mtime=buf.st_mtime;
404 return TRUE;
408 /***********************************************************************
409 * PROFILE_Open
411 * Open a profile file, checking the cached file first.
413 static BOOL PROFILE_Open( LPCSTR filename )
415 DOS_FULL_NAME full_name;
416 char buffer[MAX_PATHNAME_LEN];
417 char *newdos_name, *p;
418 FILE *file = NULL;
419 int i,j;
420 struct stat buf;
421 PROFILE *tempProfile;
423 /* First time around */
425 if(!CurProfile)
426 for(i=0;i<N_CACHED_PROFILES;i++)
428 MRUProfile[i]=HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );
429 MRUProfile[i]->changed=FALSE;
430 MRUProfile[i]->section=NULL;
431 MRUProfile[i]->dos_name=NULL;
432 MRUProfile[i]->unix_name=NULL;
433 MRUProfile[i]->filename=NULL;
434 MRUProfile[i]->mtime=0;
437 /* Check for a match */
439 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
440 strchr( filename, ':' ))
442 if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
444 else
446 GetWindowsDirectoryA( buffer, sizeof(buffer) );
447 strcat( buffer, "\\" );
448 strcat( buffer, filename );
449 if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
452 for(i=0;i<N_CACHED_PROFILES;i++)
454 if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )) ||
455 (MRUProfile[i]->dos_name && !strcmp( full_name.short_name, MRUProfile[i]->dos_name )))
457 if(i)
459 PROFILE_FlushFile();
460 tempProfile=MRUProfile[i];
461 for(j=i;j>0;j--)
462 MRUProfile[j]=MRUProfile[j-1];
463 CurProfile=tempProfile;
465 if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
466 TRACE(profile, "(%s): already opened (mru=%d)\n",
467 filename, i );
468 else
469 TRACE(profile, "(%s): already opened, needs refreshing (mru=%d)\n",
470 filename, i );
471 return TRUE;
475 /* Rotate the oldest to the top to be replaced */
477 if(i==N_CACHED_PROFILES)
479 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
480 for(i=N_CACHED_PROFILES-1;i>0;i--)
481 MRUProfile[i]=MRUProfile[i-1];
482 CurProfile=tempProfile;
485 /* Flush the profile */
487 if(CurProfile->filename)
489 PROFILE_FlushFile();
490 PROFILE_Free( CurProfile->section );
491 if (CurProfile->dos_name) HeapFree( SystemHeap, 0, CurProfile->dos_name );
492 if (CurProfile->unix_name) HeapFree( SystemHeap, 0, CurProfile->unix_name );
493 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
494 CurProfile->changed=FALSE;
495 CurProfile->section=NULL;
496 CurProfile->dos_name=NULL;
497 CurProfile->unix_name=NULL;
498 CurProfile->filename=NULL;
499 CurProfile->mtime=0;
502 newdos_name = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
503 CurProfile->dos_name = newdos_name;
504 CurProfile->filename = HEAP_strdupA( SystemHeap, 0, filename );
506 /* Try to open the profile file, first in $HOME/.wine */
508 /* FIXME: this will need a more general solution */
509 if ((p = getenv( "HOME" )) != NULL)
511 strcpy( buffer, p );
512 strcat( buffer, "/.wine/" );
513 p = buffer + strlen(buffer);
514 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
515 CharLowerA( p );
516 if ((file = fopen( buffer, "r" )))
518 TRACE(profile, "(%s): found it in %s\n",
519 filename, buffer );
520 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
524 if (!file)
526 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0,
527 full_name.long_name );
528 if ((file = fopen( full_name.long_name, "r" )))
529 TRACE(profile, "(%s): found it in %s\n",
530 filename, full_name.long_name );
533 if (file)
535 CurProfile->section = PROFILE_Load( file );
536 fclose( file );
537 if(!stat(CurProfile->unix_name,&buf))
538 CurProfile->mtime=buf.st_mtime;
540 else
542 /* Does not exist yet, we will create it in PROFILE_FlushFile */
543 WARN(profile, "profile file %s not found\n", newdos_name );
545 return TRUE;
549 /***********************************************************************
550 * PROFILE_GetSection
552 * Returns all keys of a section.
553 * If return_values is TRUE, also include the corresponding values.
555 static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
556 LPSTR buffer, UINT len, BOOL handle_env,
557 BOOL return_values )
559 PROFILEKEY *key;
560 while (section)
562 if (section->name && !strcasecmp( section->name, section_name ))
564 UINT oldlen = len;
565 for (key = section->key; key; key = key->next)
567 if (len <= 2) break;
568 if (!*key->name) continue; /* Skip empty lines */
569 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
570 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
571 len -= strlen(buffer) + 1;
572 buffer += strlen(buffer) + 1;
573 if (return_values && key->value) {
574 buffer[-1] = '=';
575 PROFILE_CopyEntry ( buffer,
576 key->value, len - 1, handle_env );
577 len -= strlen(buffer) + 1;
578 buffer += strlen(buffer) + 1;
581 *buffer = '\0';
582 if (len <= 1)
583 /*If either lpszSection or lpszKey is NULL and the supplied
584 destination buffer is too small to hold all the strings,
585 the last string is truncated and followed by two null characters.
586 In this case, the return value is equal to cchReturnBuffer
587 minus two. */
589 buffer[-1] = '\0';
590 return oldlen - 2;
592 return oldlen - len;
594 section = section->next;
596 buffer[0] = buffer[1] = '\0';
597 return 0;
601 static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
603 LPSTR buf = buffer;
604 WORD l, cursize = 0;
605 PROFILESECTION *section;
607 for (section = CurProfile->section; section; section = section->next)
608 if (section->name) {
609 l = strlen(section->name);
610 cursize += l+1;
611 if (cursize > len+1)
612 return len-2;
614 strcpy(buf, section->name);
615 buf += l+1;
618 *buf=0;
619 buf++;
620 return buf-buffer;
624 /***********************************************************************
625 * PROFILE_GetString
627 * Get a profile string.
629 static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
630 LPCSTR def_val, LPSTR buffer, UINT len )
632 PROFILEKEY *key = NULL;
634 if (!def_val) def_val = "";
635 if (key_name && key_name[0])
637 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
638 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
639 len, FALSE );
640 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
641 section, key_name, def_val, buffer );
642 return strlen( buffer );
644 if (section && section[0])
645 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
646 FALSE, FALSE);
647 /* undocumented; both section and key_name are NULL */
648 return PROFILE_GetSectionNames(buffer, len);
652 /***********************************************************************
653 * PROFILE_SetString
655 * Set a profile string.
657 static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
658 LPCSTR value )
660 if (!key_name) /* Delete a whole section */
662 TRACE(profile, "('%s')\n", section_name);
663 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
664 section_name );
665 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
666 this is not an error on application's level.*/
668 else if (!value) /* Delete a key */
670 TRACE(profile, "('%s','%s')\n",
671 section_name, key_name );
672 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
673 section_name, key_name );
674 return TRUE; /* same error handling as above */
676 else /* Set the key value */
678 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
679 key_name, TRUE );
680 TRACE(profile, "('%s','%s','%s'): \n",
681 section_name, key_name, value );
682 if (!key) return FALSE;
683 if (key->value)
685 if (!strcmp( key->value, value ))
687 TRACE(profile, " no change needed\n" );
688 return TRUE; /* No change needed */
690 TRACE(profile, " replacing '%s'\n", key->value );
691 HeapFree( SystemHeap, 0, key->value );
693 else TRACE(profile, " creating key\n" );
694 key->value = HEAP_strdupA( SystemHeap, 0, value );
695 CurProfile->changed = TRUE;
697 return TRUE;
701 /***********************************************************************
702 * PROFILE_GetWineIniString
704 * Get a config string from the wine.ini file.
706 int PROFILE_GetWineIniString( const char *section, const char *key_name,
707 const char *def, char *buffer, int len )
709 int ret;
711 EnterCriticalSection( &PROFILE_CritSect );
713 if (key_name)
715 PROFILEKEY *key = PROFILE_Find(&PROFILE_WineProfile, section, key_name, FALSE);
716 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
717 len, TRUE );
718 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
719 section, key_name, def, buffer );
720 ret = strlen( buffer );
722 else
724 ret = PROFILE_GetSection( PROFILE_WineProfile, section, buffer, len, TRUE, FALSE );
726 LeaveCriticalSection( &PROFILE_CritSect );
728 return ret;
732 /***********************************************************************
733 * PROFILE_GetWineIniInt
735 * Get a config integer from the wine.ini file.
737 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
739 char buffer[20];
740 char *p;
741 long result;
742 PROFILEKEY *key;
743 int ret;
745 EnterCriticalSection( &PROFILE_CritSect );
747 key = PROFILE_Find( &PROFILE_WineProfile, section, key_name, FALSE );
748 if (!key || !key->value) {
749 ret = def;
750 } else {
751 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
752 result = strtol( buffer, &p, 0 );
753 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result;
756 LeaveCriticalSection( &PROFILE_CritSect );
758 return ret;
762 /******************************************************************************
764 * int PROFILE_EnumerateWineIniSection(
765 * char const *section, #Name of the section to enumerate
766 * void (*cbfn)(char const *key, char const *value, void *user),
767 * # Address of the callback function
768 * void *user ) # User-specified pointer.
770 * For each entry in a section in the wine.conf file, this function will
771 * call the specified callback function, informing it of each key and
772 * value. An optional user pointer may be passed to it (if this is not
773 * needed, pass NULL through it and ignore the value in the callback
774 * function).
776 * The callback function must accept three parameters:
777 * The name of the key (char const *)
778 * The value of the key (char const *)
779 * A user-specified parameter (void *)
780 * Note that the first two are char CONST *'s, not char *'s! The callback
781 * MUST not modify these strings!
783 * The return value indicates the number of times the callback function
784 * was called.
786 int PROFILE_EnumerateWineIniSection(
787 char const *section,
788 void (*cbfn)(char const *, char const *, void *),
789 void *userptr )
791 PROFILESECTION *scansect;
792 PROFILEKEY *scankey;
793 int calls = 0;
795 EnterCriticalSection( &PROFILE_CritSect );
797 /* Search for the correct section */
798 for(scansect = PROFILE_WineProfile; scansect; scansect = scansect->next) {
799 if(scansect->name && !strcasecmp(scansect->name, section)) {
801 /* Enumerate each key with the callback */
802 for(scankey = scansect->key; scankey; scankey = scankey->next) {
804 /* Ignore blank entries -- these shouldn't exist, but let's
805 be extra careful */
806 if(scankey->name[0]) {
807 cbfn(scankey->name, scankey->value, userptr);
808 ++calls;
812 break;
815 LeaveCriticalSection( &PROFILE_CritSect );
817 return calls;
821 /******************************************************************************
823 * int PROFILE_GetWineIniBool(
824 * char const *section,
825 * char const *key_name,
826 * int def )
828 * Reads a boolean value from the wine.ini file. This function attempts to
829 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
830 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
831 * true. Anything else results in the return of the default value.
833 * This function uses 1 to indicate true, and 0 for false. You can check
834 * for existence by setting def to something other than 0 or 1 and
835 * examining the return value.
837 int PROFILE_GetWineIniBool(
838 char const *section,
839 char const *key_name,
840 int def )
842 char key_value[2];
843 int retval;
845 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
847 switch(key_value[0]) {
848 case 'n':
849 case 'N':
850 case 'f':
851 case 'F':
852 case '0':
853 retval = 0;
854 break;
856 case 'y':
857 case 'Y':
858 case 't':
859 case 'T':
860 case '1':
861 retval = 1;
862 break;
864 default:
865 retval = def;
868 TRACE(profile, "(\"%s\", \"%s\", %s), "
869 "[%c], ret %s.\n", section, key_name,
870 def ? "TRUE" : "FALSE", key_value[0],
871 retval ? "TRUE" : "FALSE");
873 return retval;
877 /***********************************************************************
878 * PROFILE_LoadWineIni
880 * Load the wine.ini file.
882 int PROFILE_LoadWineIni(void)
884 char buffer[MAX_PATHNAME_LEN];
885 const char *p;
886 FILE *f;
888 InitializeCriticalSection( &PROFILE_CritSect );
889 MakeCriticalSectionGlobal( &PROFILE_CritSect );
891 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
893 /* Open -config specified file */
894 PROFILE_WineProfile = PROFILE_Load ( f);
895 fclose ( f );
896 strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);
897 return 1;
900 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
902 PROFILE_WineProfile = PROFILE_Load( f );
903 fclose( f );
904 strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);
905 return 1;
907 if ((p = getenv( "HOME" )) != NULL)
909 lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
910 strcat( buffer, PROFILE_WineIniName );
911 if ((f = fopen( buffer, "r" )) != NULL)
913 PROFILE_WineProfile = PROFILE_Load( f );
914 fclose( f );
915 strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);
916 return 1;
919 else WARN(profile, "could not get $HOME value for config file.\n" );
921 /* Try global file */
923 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
925 PROFILE_WineProfile = PROFILE_Load( f );
926 fclose( f );
927 strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);
928 return 1;
930 MSG( "Can't open configuration file %s or $HOME%s\n",
931 WINE_INI_GLOBAL, PROFILE_WineIniName );
932 return 0;
936 /***********************************************************************
937 * PROFILE_UsageWineIni
939 * Explain the wine.ini file to those who don't read documentation.
940 * Keep below one screenful in length so that error messages above are
941 * noticed.
943 void PROFILE_UsageWineIni(void)
945 MSG("Perhaps you have not properly edited or created "
946 "your Wine configuration file.\n");
947 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
948 MSG(" or it is determined by the -config option or from\n"
949 " the WINE_INI environment variable.\n");
950 if (*PROFILE_WineIniUsed)
951 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
952 /* RTFM, so to say */
955 /***********************************************************************
956 * PROFILE_GetStringItem
958 * Convenience function that turns a string 'xxx, yyy, zzz' into
959 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
961 char* PROFILE_GetStringItem( char* start )
963 char* lpchX, *lpch;
965 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
967 if( *lpchX == ',' )
969 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
970 while( *(++lpchX) )
971 if( !PROFILE_isspace(*lpchX) ) return lpchX;
973 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
974 else lpch = NULL;
976 if( lpch ) *lpch = '\0';
977 return NULL;
980 /********************* API functions **********************************/
982 /***********************************************************************
983 * GetProfileInt16 (KERNEL.57)
985 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
987 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
991 /***********************************************************************
992 * GetProfileInt32A (KERNEL32.264)
994 UINT WINAPI GetProfileIntA( LPCSTR section, LPCSTR entry, INT def_val )
996 return GetPrivateProfileIntA( section, entry, def_val, "win.ini" );
999 /***********************************************************************
1000 * GetProfileInt32W (KERNEL32.264)
1002 UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )
1004 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1005 return GetPrivateProfileIntW( section, entry, def_val, wininiW );
1008 /***********************************************************************
1009 * GetProfileString16 (KERNEL.58)
1011 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
1012 LPSTR buffer, UINT16 len )
1014 return GetPrivateProfileString16( section, entry, def_val,
1015 buffer, len, "win.ini" );
1018 /***********************************************************************
1019 * GetProfileString32A (KERNEL32.268)
1021 INT WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,
1022 LPSTR buffer, UINT len )
1024 return GetPrivateProfileStringA( section, entry, def_val,
1025 buffer, len, "win.ini" );
1028 /***********************************************************************
1029 * GetProfileString32W (KERNEL32.269)
1031 INT WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry,
1032 LPCWSTR def_val, LPWSTR buffer, UINT len )
1034 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1035 return GetPrivateProfileStringW( section, entry, def_val,
1036 buffer, len, wininiW );
1039 /***********************************************************************
1040 * WriteProfileString16 (KERNEL.59)
1042 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
1043 LPCSTR string )
1045 return WritePrivateProfileString16( section, entry, string, "win.ini" );
1048 /***********************************************************************
1049 * WriteProfileString32A (KERNEL32.587)
1051 BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry,
1052 LPCSTR string )
1054 return WritePrivateProfileStringA( section, entry, string, "win.ini" );
1057 /***********************************************************************
1058 * WriteProfileString32W (KERNEL32.588)
1060 BOOL WINAPI WriteProfileStringW( LPCWSTR section, LPCWSTR entry,
1061 LPCWSTR string )
1063 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1064 return WritePrivateProfileStringW( section, entry, string, wininiW );
1068 /***********************************************************************
1069 * GetPrivateProfileInt16 (KERNEL.127)
1071 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
1072 INT16 def_val, LPCSTR filename )
1074 long result=(long)GetPrivateProfileIntA(section,entry,def_val,filename);
1076 if (result > 65535) return 65535;
1077 if (result >= 0) return (UINT16)result;
1078 if (result < -32768) return -32768;
1079 return (UINT16)(INT16)result;
1082 /***********************************************************************
1083 * GetPrivateProfileInt32A (KERNEL32.251)
1085 UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
1086 INT def_val, LPCSTR filename )
1088 char buffer[20];
1089 char *p;
1090 long result;
1092 GetPrivateProfileStringA( section, entry, "",
1093 buffer, sizeof(buffer), filename );
1094 if (!buffer[0]) return (UINT)def_val;
1095 result = strtol( buffer, &p, 0 );
1096 if (p == buffer) return 0; /* No digits at all */
1097 return (UINT)result;
1100 /***********************************************************************
1101 * GetPrivateProfileInt32W (KERNEL32.252)
1103 UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,
1104 INT def_val, LPCWSTR filename )
1106 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1107 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1108 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1109 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
1110 HeapFree( GetProcessHeap(), 0, sectionA );
1111 HeapFree( GetProcessHeap(), 0, filenameA );
1112 HeapFree( GetProcessHeap(), 0, entryA );
1113 return res;
1116 /***********************************************************************
1117 * GetPrivateProfileString16 (KERNEL.128)
1119 INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
1120 LPCSTR def_val, LPSTR buffer,
1121 UINT16 len, LPCSTR filename )
1123 return GetPrivateProfileStringA(section,entry,def_val,buffer,len,filename);
1126 /***********************************************************************
1127 * GetPrivateProfileString32A (KERNEL32.255)
1129 INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
1130 LPCSTR def_val, LPSTR buffer,
1131 UINT len, LPCSTR filename )
1133 int ret;
1135 if (!filename)
1136 filename = "win.ini";
1138 EnterCriticalSection( &PROFILE_CritSect );
1140 if (PROFILE_Open( filename )) {
1141 ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1142 } else {
1143 lstrcpynA( buffer, def_val, len );
1144 ret = strlen( buffer );
1147 LeaveCriticalSection( &PROFILE_CritSect );
1149 return ret;
1152 /***********************************************************************
1153 * GetPrivateProfileString32W (KERNEL32.256)
1155 INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
1156 LPCWSTR def_val, LPWSTR buffer,
1157 UINT len, LPCWSTR filename )
1159 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1160 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1161 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1162 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1163 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1164 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
1165 bufferA, len, filenameA );
1166 lstrcpynAtoW( buffer, bufferA, len );
1167 HeapFree( GetProcessHeap(), 0, sectionA );
1168 HeapFree( GetProcessHeap(), 0, entryA );
1169 HeapFree( GetProcessHeap(), 0, filenameA );
1170 HeapFree( GetProcessHeap(), 0, def_valA );
1171 HeapFree( GetProcessHeap(), 0, bufferA);
1172 return ret;
1175 /***********************************************************************
1176 * GetPrivateProfileSection16 (KERNEL.418)
1178 INT16 WINAPI GetPrivateProfileSection16( LPCSTR section, LPSTR buffer,
1179 UINT16 len, LPCSTR filename )
1181 return GetPrivateProfileSectionA( section, buffer, len, filename );
1184 /***********************************************************************
1185 * GetPrivateProfileSection32A (KERNEL32.255)
1187 INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,
1188 DWORD len, LPCSTR filename )
1190 int ret = 0;
1192 EnterCriticalSection( &PROFILE_CritSect );
1194 if (PROFILE_Open( filename ))
1195 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
1196 FALSE, TRUE);
1198 LeaveCriticalSection( &PROFILE_CritSect );
1200 return ret;
1203 /***********************************************************************
1204 * GetPrivateProfileSection32W (KERNEL32.256)
1207 INT WINAPI GetPrivateProfileSectionW (LPCWSTR section, LPWSTR buffer,
1208 DWORD len, LPCWSTR filename )
1211 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1212 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1213 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1214 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
1215 filenameA );
1216 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
1217 HeapFree( GetProcessHeap(), 0, sectionA );
1218 HeapFree( GetProcessHeap(), 0, filenameA );
1219 HeapFree( GetProcessHeap(), 0, bufferA);
1220 return ret;
1223 /***********************************************************************
1224 * GetProfileSection16 (KERNEL.419)
1226 INT16 WINAPI GetProfileSection16( LPCSTR section, LPSTR buffer, UINT16 len )
1228 return GetPrivateProfileSection16( section, buffer, len, "win.ini" );
1231 /***********************************************************************
1232 * GetProfileSection32A (KERNEL32.268)
1234 INT WINAPI GetProfileSectionA( LPCSTR section, LPSTR buffer, DWORD len )
1236 return GetPrivateProfileSectionA( section, buffer, len, "win.ini" );
1239 /***********************************************************************
1240 * GetProfileSection32W (KERNEL32)
1242 INT WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len )
1244 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1245 return GetPrivateProfileSectionW( section, buffer, len, wininiW );
1249 /***********************************************************************
1250 * WritePrivateProfileString16 (KERNEL.129)
1252 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
1253 LPCSTR string, LPCSTR filename )
1255 return WritePrivateProfileStringA(section,entry,string,filename);
1258 /***********************************************************************
1259 * WritePrivateProfileString32A (KERNEL32.582)
1261 BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
1262 LPCSTR string, LPCSTR filename )
1264 BOOL ret;
1266 EnterCriticalSection( &PROFILE_CritSect );
1268 if (!PROFILE_Open( filename )) {
1269 ret = FALSE;
1270 } else if (!section) {
1271 ret = PROFILE_FlushFile();
1272 } else {
1273 ret = PROFILE_SetString( section, entry, string );
1276 LeaveCriticalSection( &PROFILE_CritSect );
1278 return ret;
1281 /***********************************************************************
1282 * WritePrivateProfileString32W (KERNEL32.583)
1284 BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
1285 LPCWSTR string, LPCWSTR filename )
1287 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1288 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1289 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1290 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1291 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
1292 stringA, filenameA );
1293 HeapFree( GetProcessHeap(), 0, sectionA );
1294 HeapFree( GetProcessHeap(), 0, entryA );
1295 HeapFree( GetProcessHeap(), 0, stringA );
1296 HeapFree( GetProcessHeap(), 0, filenameA );
1297 return res;
1300 /***********************************************************************
1301 * WritePrivateProfileSection16 (KERNEL.416)
1303 BOOL16 WINAPI WritePrivateProfileSection16( LPCSTR section,
1304 LPCSTR string, LPCSTR filename )
1306 return WritePrivateProfileSectionA( section, string, filename );
1309 /***********************************************************************
1310 * WritePrivateProfileSection32A (KERNEL32)
1312 BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section,
1313 LPCSTR string, LPCSTR filename )
1315 char *p =(char*)string;
1317 FIXME(profile, "WritePrivateProfileSection32A empty stub\n");
1318 if (TRACE_ON(profile)) {
1319 TRACE(profile, "(%s) => [%s]\n", filename, section);
1320 while (*(p+1)) {
1321 TRACE(profile, "%s\n", p);
1322 p += strlen(p);
1323 p += 1;
1327 return FALSE;
1330 /***********************************************************************
1331 * WritePrivateProfileSection32W (KERNEL32)
1333 BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
1334 LPCWSTR string, LPCWSTR filename)
1337 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1338 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1339 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1340 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
1341 HeapFree( GetProcessHeap(), 0, sectionA );
1342 HeapFree( GetProcessHeap(), 0, stringA );
1343 HeapFree( GetProcessHeap(), 0, filenameA );
1344 return res;
1347 /***********************************************************************
1348 * WriteProfileSection16 (KERNEL.417)
1350 BOOL16 WINAPI WriteProfileSection16( LPCSTR section, LPCSTR keys_n_values)
1352 return WritePrivateProfileSection16( section, keys_n_values, "win.ini");
1355 /***********************************************************************
1356 * WriteProfileSection32A (KERNEL32.747)
1358 BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values)
1361 return WritePrivateProfileSectionA( section, keys_n_values, "win.ini");
1364 /***********************************************************************
1365 * WriteProfileSection32W (KERNEL32.748)
1367 BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values)
1369 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini");
1371 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW));
1374 /***********************************************************************
1375 * GetPrivateProfileSectionNames16 (KERNEL.143)
1377 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1378 LPCSTR filename )
1380 WORD ret = 0;
1382 EnterCriticalSection( &PROFILE_CritSect );
1384 if (PROFILE_Open( filename ))
1385 ret = PROFILE_GetSectionNames(buffer, size);
1387 LeaveCriticalSection( &PROFILE_CritSect );
1389 return ret;
1393 /***********************************************************************
1394 * GetProfileSectionNames16 (KERNEL.142)
1396 WORD WINAPI GetProfileSectionNames16( LPSTR buffer, WORD size)
1399 return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
1403 /***********************************************************************
1404 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1406 DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,
1407 LPCSTR filename)
1410 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1414 /***********************************************************************
1415 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1417 DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
1418 LPCWSTR filename)
1421 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1422 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, size);
1424 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1425 lstrcpynAtoW( buffer, bufferA, size);
1426 HeapFree( GetProcessHeap(), 0, bufferA);
1427 HeapFree( GetProcessHeap(), 0, filenameA );
1429 return ret;
1432 /***********************************************************************
1433 * GetPrivateProfileStruct16 (KERNEL.407)
1435 BOOL16 WINAPI GetPrivateProfileStruct16(LPCSTR section, LPCSTR key,
1436 LPVOID buf, UINT16 len, LPCSTR filename)
1438 return GetPrivateProfileStructA( section, key, buf, len, filename );
1441 /***********************************************************************
1442 * GetPrivateProfileStruct32A (KERNEL32.370)
1444 BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
1445 LPVOID buf, UINT len, LPCSTR filename)
1447 BOOL ret = FALSE;
1449 EnterCriticalSection( &PROFILE_CritSect );
1451 if (PROFILE_Open( filename )) {
1452 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1453 if (k) {
1454 lstrcpynA( buf, k->value, strlen(k->value));
1455 ret = TRUE;
1458 LeaveCriticalSection( &PROFILE_CritSect );
1460 return FALSE;
1463 /***********************************************************************
1464 * GetPrivateProfileStruct32W (KERNEL32.543)
1466 BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
1467 LPVOID buffer, UINT len, LPCWSTR filename)
1469 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1470 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1471 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1472 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1474 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
1475 len, filenameA );
1476 lstrcpynAtoW( buffer, bufferA, len );
1477 HeapFree( GetProcessHeap(), 0, bufferA);
1478 HeapFree( GetProcessHeap(), 0, sectionA );
1479 HeapFree( GetProcessHeap(), 0, keyA );
1480 HeapFree( GetProcessHeap(), 0, filenameA );
1482 return ret;
1487 /***********************************************************************
1488 * WritePrivateProfileStruct16 (KERNEL.406)
1490 BOOL16 WINAPI WritePrivateProfileStruct16 (LPCSTR section, LPCSTR key,
1491 LPVOID buf, UINT16 bufsize, LPCSTR filename)
1493 return WritePrivateProfileStructA( section, key, buf, bufsize, filename );
1496 /***********************************************************************
1497 * WritePrivateProfileStruct32A (KERNEL32.744)
1499 BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
1500 LPVOID buf, UINT bufsize, LPCSTR filename)
1502 BOOL ret;
1504 EnterCriticalSection( &PROFILE_CritSect );
1506 if ((!section) && (!key) && (!buf)) { /* flush the cache */
1507 PROFILE_FlushFile();
1508 ret = FALSE;
1509 } else {
1510 if (!PROFILE_Open( filename ))
1511 ret = FALSE;
1512 else
1513 ret = PROFILE_SetString( section, key, buf);
1516 LeaveCriticalSection( &PROFILE_CritSect );
1518 return ret;
1521 /***********************************************************************
1522 * WritePrivateProfileStruct32W (KERNEL32.544)
1524 BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
1525 LPVOID buf, UINT bufsize, LPCWSTR filename)
1527 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1528 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1529 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1530 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
1531 filenameA );
1532 HeapFree( GetProcessHeap(), 0, sectionA );
1533 HeapFree( GetProcessHeap(), 0, keyA );
1534 HeapFree( GetProcessHeap(), 0, filenameA );
1536 return ret;
1540 /***********************************************************************
1541 * WriteOutProfiles (KERNEL.315)
1543 void WINAPI WriteOutProfiles16(void)
1545 EnterCriticalSection( &PROFILE_CritSect );
1546 PROFILE_FlushFile();
1547 LeaveCriticalSection( &PROFILE_CritSect );