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