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