Built-in DLLs resources are now specified in spec file.
[wine/multimedia.git] / files / profile.c
blobf14abdc364024d538dad5fdf4a45ca6272cbfac8
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 "winerror.h"
16 #include "wine/winbase16.h"
17 #include "winuser.h"
18 #include "winnls.h"
19 #include "file.h"
20 #include "heap.h"
21 #include "debugtools.h"
22 #include "options.h"
24 DEFAULT_DEBUG_CHANNEL(profile)
26 typedef struct tagPROFILEKEY
28 char *name;
29 char *value;
30 struct tagPROFILEKEY *next;
31 } PROFILEKEY;
33 typedef struct tagPROFILESECTION
35 char *name;
36 struct tagPROFILEKEY *key;
37 struct tagPROFILESECTION *next;
38 } PROFILESECTION;
41 typedef struct
43 BOOL changed;
44 PROFILESECTION *section;
45 char *dos_name;
46 char *unix_name;
47 char *filename;
48 time_t mtime;
49 } PROFILE;
52 #define N_CACHED_PROFILES 10
54 /* Cached profile files */
55 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
57 #define CurProfile (MRUProfile[0])
59 /* wine.ini profile content */
60 static PROFILESECTION *PROFILE_WineProfile;
62 #define PROFILE_MAX_LINE_LEN 1024
64 /* Wine profile name in $HOME directory; must begin with slash */
65 static const char PROFILE_WineIniName[] = "/.winerc";
67 /* Wine profile: the profile file being used */
68 static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
70 /* Check for comments in profile */
71 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
73 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
75 static LPCWSTR wininiW = NULL;
77 static CRITICAL_SECTION PROFILE_CritSect;
79 /***********************************************************************
80 * PROFILE_CopyEntry
82 * Copy the content of an entry into a buffer, removing quotes, and possibly
83 * translating environment variables.
85 static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
86 int handle_env )
88 char quote = '\0';
89 const char *p;
91 if ((*value == '\'') || (*value == '\"'))
93 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
96 if (!handle_env)
98 lstrcpynA( buffer, value, len );
99 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
100 return;
103 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
105 if ((*p == '$') && (p[1] == '{'))
107 char env_val[1024];
108 const char *env_p;
109 const char *p2 = strchr( p, '}' );
110 if (!p2) continue; /* ignore it */
111 lstrcpynA(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
112 if ((env_p = getenv( env_val )) != NULL)
114 lstrcpynA( buffer, env_p, len );
115 buffer += strlen( buffer );
116 len -= strlen( buffer );
118 p = p2 + 1;
121 if (quote && (len > 1)) buffer--;
122 *buffer = '\0';
126 /***********************************************************************
127 * PROFILE_Save
129 * Save a profile tree to a file.
131 static void PROFILE_Save( FILE *file, PROFILESECTION *section )
133 PROFILEKEY *key;
135 for ( ; section; section = section->next)
137 if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
138 for (key = section->key; key; key = key->next)
140 fprintf( file, "%s", key->name );
141 if (key->value) fprintf( file, "=%s", key->value );
142 fprintf( file, "\r\n" );
148 /***********************************************************************
149 * PROFILE_Free
151 * Free a profile tree.
153 static void PROFILE_Free( PROFILESECTION *section )
155 PROFILESECTION *next_section;
156 PROFILEKEY *key, *next_key;
158 for ( ; section; section = next_section)
160 if (section->name) HeapFree( SystemHeap, 0, section->name );
161 for (key = section->key; key; key = next_key)
163 next_key = key->next;
164 if (key->name) HeapFree( SystemHeap, 0, key->name );
165 if (key->value) HeapFree( SystemHeap, 0, key->value );
166 HeapFree( SystemHeap, 0, key );
168 next_section = section->next;
169 HeapFree( SystemHeap, 0, section );
173 static int
174 PROFILE_isspace(char c) {
175 if (isspace(c)) return 1;
176 if (c=='\r' || c==0x1a) return 1;
177 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
178 return 0;
182 /***********************************************************************
183 * PROFILE_Load
185 * Load a profile tree from a file.
187 static PROFILESECTION *PROFILE_Load( FILE *file )
189 char buffer[PROFILE_MAX_LINE_LEN];
190 char *p, *p2;
191 int line = 0;
192 PROFILESECTION *section, *first_section;
193 PROFILESECTION **next_section;
194 PROFILEKEY *key, *prev_key, **next_key;
196 first_section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
197 first_section->name = NULL;
198 first_section->key = NULL;
199 first_section->next = NULL;
200 next_section = &first_section->next;
201 next_key = &first_section->key;
202 prev_key = NULL;
204 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
206 line++;
207 p = buffer;
208 while (*p && PROFILE_isspace(*p)) p++;
209 if (*p == '[') /* section start */
211 if (!(p2 = strrchr( p, ']' )))
213 WARN("Invalid section header at line %d: '%s'\n",
214 line, p );
216 else
218 *p2 = '\0';
219 p++;
220 section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
221 section->name = HEAP_strdupA( SystemHeap, 0, p );
222 section->key = NULL;
223 section->next = NULL;
224 *next_section = section;
225 next_section = &section->next;
226 next_key = &section->key;
227 prev_key = NULL;
229 TRACE("New section: '%s'\n",section->name);
231 continue;
235 p2=p+strlen(p) - 1;
236 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
238 if ((p2 = strchr( p, '=' )) != NULL)
240 char *p3 = p2 - 1;
241 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
242 *p2++ = '\0';
243 while (*p2 && PROFILE_isspace(*p2)) p2++;
246 if(*p || !prev_key || *prev_key->name)
248 key = HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
249 key->name = HEAP_strdupA( SystemHeap, 0, p );
250 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
251 key->next = NULL;
252 *next_key = key;
253 next_key = &key->next;
254 prev_key = key;
256 TRACE("New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)");
259 return first_section;
263 /***********************************************************************
264 * PROFILE_DeleteSection
266 * Delete a section from a profile tree.
268 static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
270 while (*section)
272 if ((*section)->name && !strcasecmp( (*section)->name, name ))
274 PROFILESECTION *to_del = *section;
275 *section = to_del->next;
276 to_del->next = NULL;
277 PROFILE_Free( to_del );
278 return TRUE;
280 section = &(*section)->next;
282 return FALSE;
286 /***********************************************************************
287 * PROFILE_DeleteKey
289 * Delete a key from a profile tree.
291 static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
292 LPCSTR section_name, LPCSTR key_name )
294 while (*section)
296 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
298 PROFILEKEY **key = &(*section)->key;
299 while (*key)
301 if (!strcasecmp( (*key)->name, key_name ))
303 PROFILEKEY *to_del = *key;
304 *key = to_del->next;
305 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
306 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
307 HeapFree( SystemHeap, 0, to_del );
308 return TRUE;
310 key = &(*key)->next;
313 section = &(*section)->next;
315 return FALSE;
319 /***********************************************************************
320 * PROFILE_Find
322 * Find a key in a profile tree, optionally creating it.
324 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
325 const char *section_name,
326 const char *key_name, int create )
328 while (*section)
330 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
332 PROFILEKEY **key = &(*section)->key;
333 while (*key)
335 if (!strcasecmp( (*key)->name, key_name )) return *key;
336 key = &(*key)->next;
338 if (!create) return NULL;
339 *key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
340 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
341 (*key)->value = NULL;
342 (*key)->next = NULL;
343 return *key;
345 section = &(*section)->next;
347 if (!create) return NULL;
348 *section = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
349 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
350 (*section)->next = NULL;
351 (*section)->key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
352 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
353 (*section)->key->value = NULL;
354 (*section)->key->next = NULL;
355 return (*section)->key;
359 /***********************************************************************
360 * PROFILE_FlushFile
362 * Flush the current profile to disk if changed.
364 static BOOL PROFILE_FlushFile(void)
366 char *p, buffer[MAX_PATHNAME_LEN];
367 const char *unix_name;
368 FILE *file = NULL;
369 struct stat buf;
371 if(!CurProfile)
373 WARN("No current profile!\n");
374 return FALSE;
377 if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
378 if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
380 /* Try to create it in $HOME/.wine */
381 /* FIXME: this will need a more general solution */
382 if ((p = getenv( "HOME" )) != NULL)
384 strcpy( buffer, p );
385 strcat( buffer, "/.wine/" );
386 p = buffer + strlen(buffer);
387 strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
388 CharLowerA( p );
389 file = fopen( buffer, "w" );
390 unix_name = buffer;
394 if (!file)
396 WARN("could not save profile file %s\n", CurProfile->dos_name);
397 return FALSE;
400 TRACE("Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name );
401 PROFILE_Save( file, CurProfile->section );
402 fclose( file );
403 CurProfile->changed = FALSE;
404 if(!stat(unix_name,&buf))
405 CurProfile->mtime=buf.st_mtime;
406 return TRUE;
410 /***********************************************************************
411 * PROFILE_ReleaseFile
413 * Flush the current profile to disk and remove it from the cache.
415 static void PROFILE_ReleaseFile(void)
417 PROFILE_FlushFile();
418 PROFILE_Free( CurProfile->section );
419 if (CurProfile->dos_name) HeapFree( SystemHeap, 0, CurProfile->dos_name );
420 if (CurProfile->unix_name) HeapFree( SystemHeap, 0, CurProfile->unix_name );
421 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
422 CurProfile->changed = FALSE;
423 CurProfile->section = NULL;
424 CurProfile->dos_name = NULL;
425 CurProfile->unix_name = NULL;
426 CurProfile->filename = NULL;
427 CurProfile->mtime = 0;
431 /***********************************************************************
432 * PROFILE_Open
434 * Open a profile file, checking the cached file first.
436 static BOOL PROFILE_Open( LPCSTR filename )
438 DOS_FULL_NAME full_name;
439 char buffer[MAX_PATHNAME_LEN];
440 char *newdos_name, *p;
441 FILE *file = NULL;
442 int i,j;
443 struct stat buf;
444 PROFILE *tempProfile;
446 /* First time around */
448 if(!CurProfile)
449 for(i=0;i<N_CACHED_PROFILES;i++)
451 MRUProfile[i]=HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );
452 MRUProfile[i]->changed=FALSE;
453 MRUProfile[i]->section=NULL;
454 MRUProfile[i]->dos_name=NULL;
455 MRUProfile[i]->unix_name=NULL;
456 MRUProfile[i]->filename=NULL;
457 MRUProfile[i]->mtime=0;
460 /* Check for a match */
462 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
463 strchr( filename, ':' ))
465 if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
467 else
469 GetWindowsDirectoryA( buffer, sizeof(buffer) );
470 strcat( buffer, "\\" );
471 strcat( buffer, filename );
472 if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
475 for(i=0;i<N_CACHED_PROFILES;i++)
477 if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )) ||
478 (MRUProfile[i]->dos_name && !strcmp( full_name.short_name, MRUProfile[i]->dos_name )))
480 if(i)
482 PROFILE_FlushFile();
483 tempProfile=MRUProfile[i];
484 for(j=i;j>0;j--)
485 MRUProfile[j]=MRUProfile[j-1];
486 CurProfile=tempProfile;
488 if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
489 TRACE("(%s): already opened (mru=%d)\n",
490 filename, i );
491 else
492 TRACE("(%s): already opened, needs refreshing (mru=%d)\n",
493 filename, i );
494 return TRUE;
498 /* Flush the old current profile */
499 PROFILE_FlushFile();
501 /* Make the oldest profile the current one only in order to get rid of it */
502 if(i==N_CACHED_PROFILES)
504 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
505 for(i=N_CACHED_PROFILES-1;i>0;i--)
506 MRUProfile[i]=MRUProfile[i-1];
507 CurProfile=tempProfile;
509 if(CurProfile->filename) PROFILE_ReleaseFile();
511 /* OK, now that CurProfile is definitely free we assign it our new file */
512 newdos_name = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
513 CurProfile->dos_name = newdos_name;
514 CurProfile->filename = HEAP_strdupA( SystemHeap, 0, filename );
516 /* Try to open the profile file, first in $HOME/.wine */
518 /* FIXME: this will need a more general solution */
519 if ((p = getenv( "HOME" )) != NULL)
521 strcpy( buffer, p );
522 strcat( buffer, "/.wine/" );
523 p = buffer + strlen(buffer);
524 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
525 CharLowerA( p );
526 if ((file = fopen( buffer, "r" )))
528 TRACE("(%s): found it in %s\n",
529 filename, buffer );
530 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
534 if (!file)
536 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0,
537 full_name.long_name );
538 if ((file = fopen( full_name.long_name, "r" )))
539 TRACE("(%s): found it in %s\n",
540 filename, full_name.long_name );
543 if (file)
545 CurProfile->section = PROFILE_Load( file );
546 fclose( file );
547 if(!stat(CurProfile->unix_name,&buf))
548 CurProfile->mtime=buf.st_mtime;
550 else
552 /* Does not exist yet, we will create it in PROFILE_FlushFile */
553 WARN("profile file %s not found\n", newdos_name );
555 return TRUE;
559 /***********************************************************************
560 * PROFILE_GetSection
562 * Returns all keys of a section.
563 * If return_values is TRUE, also include the corresponding values.
565 static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
566 LPSTR buffer, UINT len, BOOL handle_env,
567 BOOL return_values )
569 PROFILEKEY *key;
570 while (section)
572 if (section->name && !strcasecmp( section->name, section_name ))
574 UINT oldlen = len;
575 for (key = section->key; key; key = key->next)
577 if (len <= 2) break;
578 if (!*key->name) continue; /* Skip empty lines */
579 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
580 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
581 len -= strlen(buffer) + 1;
582 buffer += strlen(buffer) + 1;
583 if (return_values && key->value) {
584 buffer[-1] = '=';
585 PROFILE_CopyEntry ( buffer,
586 key->value, len - 1, handle_env );
587 len -= strlen(buffer) + 1;
588 buffer += strlen(buffer) + 1;
591 *buffer = '\0';
592 if (len <= 1)
593 /*If either lpszSection or lpszKey is NULL and the supplied
594 destination buffer is too small to hold all the strings,
595 the last string is truncated and followed by two null characters.
596 In this case, the return value is equal to cchReturnBuffer
597 minus two. */
599 buffer[-1] = '\0';
600 return oldlen - 2;
602 return oldlen - len;
604 section = section->next;
606 buffer[0] = buffer[1] = '\0';
607 return 0;
611 static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
613 LPSTR buf = buffer;
614 WORD l, cursize = 0;
615 PROFILESECTION *section;
617 for (section = CurProfile->section; section; section = section->next)
618 if (section->name) {
619 l = strlen(section->name);
620 cursize += l+1;
621 if (cursize > len+1)
622 return len-2;
624 strcpy(buf, section->name);
625 buf += l+1;
628 *buf=0;
629 buf++;
630 return buf-buffer;
634 /***********************************************************************
635 * PROFILE_GetString
637 * Get a profile string.
639 static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
640 LPCSTR def_val, LPSTR buffer, UINT len )
642 PROFILEKEY *key = NULL;
644 if (!def_val) def_val = "";
645 if (key_name && key_name[0])
647 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
648 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
649 len, FALSE );
650 TRACE("('%s','%s','%s'): returning '%s'\n",
651 section, key_name, def_val, buffer );
652 return strlen( buffer );
654 if (section && section[0])
655 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
656 FALSE, FALSE);
657 /* undocumented; both section and key_name are NULL */
658 return PROFILE_GetSectionNames(buffer, len);
662 /***********************************************************************
663 * PROFILE_SetString
665 * Set a profile string.
667 static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
668 LPCSTR value )
670 if (!key_name) /* Delete a whole section */
672 TRACE("('%s')\n", section_name);
673 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
674 section_name );
675 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
676 this is not an error on application's level.*/
678 else if (!value) /* Delete a key */
680 TRACE("('%s','%s')\n",
681 section_name, key_name );
682 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
683 section_name, key_name );
684 return TRUE; /* same error handling as above */
686 else /* Set the key value */
688 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
689 key_name, TRUE );
690 TRACE("('%s','%s','%s'): \n",
691 section_name, key_name, value );
692 if (!key) return FALSE;
693 if (key->value)
695 if (!strcmp( key->value, value ))
697 TRACE(" no change needed\n" );
698 return TRUE; /* No change needed */
700 TRACE(" replacing '%s'\n", key->value );
701 HeapFree( SystemHeap, 0, key->value );
703 else TRACE(" creating key\n" );
704 key->value = HEAP_strdupA( SystemHeap, 0, value );
705 CurProfile->changed = TRUE;
707 return TRUE;
711 /***********************************************************************
712 * PROFILE_GetWineIniString
714 * Get a config string from the wine.ini file.
716 int PROFILE_GetWineIniString( const char *section, const char *key_name,
717 const char *def, char *buffer, int len )
719 int ret;
721 EnterCriticalSection( &PROFILE_CritSect );
723 if (key_name)
725 PROFILEKEY *key = PROFILE_Find(&PROFILE_WineProfile, section, key_name, FALSE);
726 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
727 len, TRUE );
728 TRACE("('%s','%s','%s'): returning '%s'\n",
729 section, key_name, def, buffer );
730 ret = strlen( buffer );
732 else
734 ret = PROFILE_GetSection( PROFILE_WineProfile, section, buffer, len, TRUE, FALSE );
736 LeaveCriticalSection( &PROFILE_CritSect );
738 return ret;
742 /***********************************************************************
743 * PROFILE_GetWineIniInt
745 * Get a config integer from the wine.ini file.
747 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
749 char buffer[20];
750 char *p;
751 long result;
752 PROFILEKEY *key;
753 int ret;
755 EnterCriticalSection( &PROFILE_CritSect );
757 key = PROFILE_Find( &PROFILE_WineProfile, section, key_name, FALSE );
758 if (!key || !key->value) {
759 ret = def;
760 } else {
761 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
762 result = strtol( buffer, &p, 0 );
763 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result;
766 LeaveCriticalSection( &PROFILE_CritSect );
768 return ret;
772 /******************************************************************************
774 * int PROFILE_EnumerateWineIniSection(
775 * char const *section, #Name of the section to enumerate
776 * void (*cbfn)(char const *key, char const *value, void *user),
777 * # Address of the callback function
778 * void *user ) # User-specified pointer.
780 * For each entry in a section in the wine.conf file, this function will
781 * call the specified callback function, informing it of each key and
782 * value. An optional user pointer may be passed to it (if this is not
783 * needed, pass NULL through it and ignore the value in the callback
784 * function).
786 * The callback function must accept three parameters:
787 * The name of the key (char const *)
788 * The value of the key (char const *)
789 * A user-specified parameter (void *)
790 * Note that the first two are char CONST *'s, not char *'s! The callback
791 * MUST not modify these strings!
793 * The return value indicates the number of times the callback function
794 * was called.
796 int PROFILE_EnumerateWineIniSection(
797 char const *section,
798 void (*cbfn)(char const *, char const *, void *),
799 void *userptr )
801 PROFILESECTION *scansect;
802 PROFILEKEY *scankey;
803 int calls = 0;
805 EnterCriticalSection( &PROFILE_CritSect );
807 /* Search for the correct section */
808 for(scansect = PROFILE_WineProfile; scansect; scansect = scansect->next) {
809 if(scansect->name && !strcasecmp(scansect->name, section)) {
811 /* Enumerate each key with the callback */
812 for(scankey = scansect->key; scankey; scankey = scankey->next) {
814 /* Ignore blank entries -- these shouldn't exist, but let's
815 be extra careful */
816 if (!scankey->name[0]) continue;
817 if (!scankey->value) cbfn(scankey->name, NULL, userptr);
818 else
820 char value[1024];
821 PROFILE_CopyEntry(value, scankey->value, sizeof(value), TRUE);
822 cbfn(scankey->name, value, userptr);
824 ++calls;
827 break;
830 LeaveCriticalSection( &PROFILE_CritSect );
832 return calls;
836 /******************************************************************************
838 * int PROFILE_GetWineIniBool(
839 * char const *section,
840 * char const *key_name,
841 * int def )
843 * Reads a boolean value from the wine.ini file. This function attempts to
844 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
845 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
846 * true. Anything else results in the return of the default value.
848 * This function uses 1 to indicate true, and 0 for false. You can check
849 * for existence by setting def to something other than 0 or 1 and
850 * examining the return value.
852 int PROFILE_GetWineIniBool(
853 char const *section,
854 char const *key_name,
855 int def )
857 char key_value[2];
858 int retval;
860 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
862 switch(key_value[0]) {
863 case 'n':
864 case 'N':
865 case 'f':
866 case 'F':
867 case '0':
868 retval = 0;
869 break;
871 case 'y':
872 case 'Y':
873 case 't':
874 case 'T':
875 case '1':
876 retval = 1;
877 break;
879 default:
880 retval = def;
883 TRACE("(\"%s\", \"%s\", %s), "
884 "[%c], ret %s.\n", section, key_name,
885 def ? "TRUE" : "FALSE", key_value[0],
886 retval ? "TRUE" : "FALSE");
888 return retval;
892 /***********************************************************************
893 * PROFILE_LoadWineIni
895 * Load the wine.ini file.
897 int PROFILE_LoadWineIni(void)
899 char buffer[MAX_PATHNAME_LEN];
900 const char *p;
901 FILE *f;
903 InitializeCriticalSection( &PROFILE_CritSect );
904 MakeCriticalSectionGlobal( &PROFILE_CritSect );
906 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
908 /* Open -config specified file */
909 PROFILE_WineProfile = PROFILE_Load ( f);
910 fclose ( f );
911 lstrcpynA(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN);
912 return 1;
915 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
917 PROFILE_WineProfile = PROFILE_Load( f );
918 fclose( f );
919 lstrcpynA(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN);
920 return 1;
922 if ((p = getenv( "HOME" )) != NULL)
924 lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
925 strcat( buffer, PROFILE_WineIniName );
926 if ((f = fopen( buffer, "r" )) != NULL)
928 PROFILE_WineProfile = PROFILE_Load( f );
929 fclose( f );
930 lstrcpynA(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN);
931 return 1;
934 else WARN("could not get $HOME value for config file.\n" );
936 /* Try global file */
938 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
940 PROFILE_WineProfile = PROFILE_Load( f );
941 fclose( f );
942 lstrcpynA(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN);
943 return 1;
945 MESSAGE( "Can't open configuration file %s or $HOME%s\n",
946 WINE_INI_GLOBAL, PROFILE_WineIniName );
947 return 0;
951 /***********************************************************************
952 * PROFILE_UsageWineIni
954 * Explain the wine.ini file to those who don't read documentation.
955 * Keep below one screenful in length so that error messages above are
956 * noticed.
958 void PROFILE_UsageWineIni(void)
960 MESSAGE("Perhaps you have not properly edited or created "
961 "your Wine configuration file.\n");
962 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
963 MESSAGE(" or it is determined by the -config option or from\n"
964 " the WINE_INI environment variable.\n");
965 if (*PROFILE_WineIniUsed)
966 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
967 /* RTFM, so to say */
970 /***********************************************************************
971 * PROFILE_GetStringItem
973 * Convenience function that turns a string 'xxx, yyy, zzz' into
974 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
976 char* PROFILE_GetStringItem( char* start )
978 char* lpchX, *lpch;
980 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
982 if( *lpchX == ',' )
984 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
985 while( *(++lpchX) )
986 if( !PROFILE_isspace(*lpchX) ) return lpchX;
988 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
989 else lpch = NULL;
991 if( lpch ) *lpch = '\0';
992 return NULL;
995 /********************* API functions **********************************/
997 /***********************************************************************
998 * GetProfileInt16 (KERNEL.57)
1000 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
1002 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
1006 /***********************************************************************
1007 * GetProfileInt32A (KERNEL32.264)
1009 UINT WINAPI GetProfileIntA( LPCSTR section, LPCSTR entry, INT def_val )
1011 return GetPrivateProfileIntA( section, entry, def_val, "win.ini" );
1014 /***********************************************************************
1015 * GetProfileInt32W (KERNEL32.264)
1017 UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )
1019 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1020 return GetPrivateProfileIntW( section, entry, def_val, wininiW );
1023 /***********************************************************************
1024 * GetProfileString16 (KERNEL.58)
1026 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
1027 LPSTR buffer, UINT16 len )
1029 return GetPrivateProfileString16( section, entry, def_val,
1030 buffer, len, "win.ini" );
1033 /***********************************************************************
1034 * GetProfileString32A (KERNEL32.268)
1036 INT WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,
1037 LPSTR buffer, UINT len )
1039 return GetPrivateProfileStringA( section, entry, def_val,
1040 buffer, len, "win.ini" );
1043 /***********************************************************************
1044 * GetProfileString32W (KERNEL32.269)
1046 INT WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry,
1047 LPCWSTR def_val, LPWSTR buffer, UINT len )
1049 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1050 return GetPrivateProfileStringW( section, entry, def_val,
1051 buffer, len, wininiW );
1054 /***********************************************************************
1055 * WriteProfileString16 (KERNEL.59)
1057 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
1058 LPCSTR string )
1060 return WritePrivateProfileString16( section, entry, string, "win.ini" );
1063 /***********************************************************************
1064 * WriteProfileString32A (KERNEL32.587)
1066 BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry,
1067 LPCSTR string )
1069 return WritePrivateProfileStringA( section, entry, string, "win.ini" );
1072 /***********************************************************************
1073 * WriteProfileString32W (KERNEL32.588)
1075 BOOL WINAPI WriteProfileStringW( LPCWSTR section, LPCWSTR entry,
1076 LPCWSTR string )
1078 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1079 return WritePrivateProfileStringW( section, entry, string, wininiW );
1083 /***********************************************************************
1084 * GetPrivateProfileInt16 (KERNEL.127)
1086 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
1087 INT16 def_val, LPCSTR filename )
1089 long result=(long)GetPrivateProfileIntA(section,entry,def_val,filename);
1091 if (result > 65535) return 65535;
1092 if (result >= 0) return (UINT16)result;
1093 if (result < -32768) return -32768;
1094 return (UINT16)(INT16)result;
1097 /***********************************************************************
1098 * GetPrivateProfileInt32A (KERNEL32.251)
1100 UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
1101 INT def_val, LPCSTR filename )
1103 char buffer[20];
1104 char *p;
1105 long result;
1107 GetPrivateProfileStringA( section, entry, "",
1108 buffer, sizeof(buffer), filename );
1109 if (!buffer[0]) return (UINT)def_val;
1110 result = strtol( buffer, &p, 0 );
1111 if (p == buffer) return 0; /* No digits at all */
1112 return (UINT)result;
1115 /***********************************************************************
1116 * GetPrivateProfileInt32W (KERNEL32.252)
1118 UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,
1119 INT def_val, LPCWSTR filename )
1121 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1122 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1123 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1124 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
1125 HeapFree( GetProcessHeap(), 0, sectionA );
1126 HeapFree( GetProcessHeap(), 0, filenameA );
1127 HeapFree( GetProcessHeap(), 0, entryA );
1128 return res;
1131 /***********************************************************************
1132 * GetPrivateProfileString16 (KERNEL.128)
1134 INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
1135 LPCSTR def_val, LPSTR buffer,
1136 UINT16 len, LPCSTR filename )
1138 return GetPrivateProfileStringA(section,entry,def_val,buffer,len,filename);
1141 /***********************************************************************
1142 * GetPrivateProfileString32A (KERNEL32.255)
1144 INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
1145 LPCSTR def_val, LPSTR buffer,
1146 UINT len, LPCSTR filename )
1148 int ret;
1150 if (!filename)
1151 filename = "win.ini";
1153 EnterCriticalSection( &PROFILE_CritSect );
1155 if (PROFILE_Open( filename )) {
1156 ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1157 } else {
1158 lstrcpynA( buffer, def_val, len );
1159 ret = strlen( buffer );
1162 LeaveCriticalSection( &PROFILE_CritSect );
1164 return ret;
1167 /***********************************************************************
1168 * GetPrivateProfileString32W (KERNEL32.256)
1170 INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
1171 LPCWSTR def_val, LPWSTR buffer,
1172 UINT len, LPCWSTR filename )
1174 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1175 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1176 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1177 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1178 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1179 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
1180 bufferA, len, filenameA );
1181 lstrcpynAtoW( buffer, bufferA, len );
1182 HeapFree( GetProcessHeap(), 0, sectionA );
1183 HeapFree( GetProcessHeap(), 0, entryA );
1184 HeapFree( GetProcessHeap(), 0, filenameA );
1185 HeapFree( GetProcessHeap(), 0, def_valA );
1186 HeapFree( GetProcessHeap(), 0, bufferA);
1187 return ret;
1190 /***********************************************************************
1191 * GetPrivateProfileSection16 (KERNEL.418)
1193 INT16 WINAPI GetPrivateProfileSection16( LPCSTR section, LPSTR buffer,
1194 UINT16 len, LPCSTR filename )
1196 return GetPrivateProfileSectionA( section, buffer, len, filename );
1199 /***********************************************************************
1200 * GetPrivateProfileSection32A (KERNEL32.255)
1202 INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,
1203 DWORD len, LPCSTR filename )
1205 int ret = 0;
1207 EnterCriticalSection( &PROFILE_CritSect );
1209 if (PROFILE_Open( filename ))
1210 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
1211 FALSE, TRUE);
1213 LeaveCriticalSection( &PROFILE_CritSect );
1215 return ret;
1218 /***********************************************************************
1219 * GetPrivateProfileSection32W (KERNEL32.256)
1222 INT WINAPI GetPrivateProfileSectionW (LPCWSTR section, LPWSTR buffer,
1223 DWORD len, LPCWSTR filename )
1226 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1227 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1228 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1229 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
1230 filenameA );
1231 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
1232 HeapFree( GetProcessHeap(), 0, sectionA );
1233 HeapFree( GetProcessHeap(), 0, filenameA );
1234 HeapFree( GetProcessHeap(), 0, bufferA);
1235 return ret;
1238 /***********************************************************************
1239 * GetProfileSection16 (KERNEL.419)
1241 INT16 WINAPI GetProfileSection16( LPCSTR section, LPSTR buffer, UINT16 len )
1243 return GetPrivateProfileSection16( section, buffer, len, "win.ini" );
1246 /***********************************************************************
1247 * GetProfileSection32A (KERNEL32.268)
1249 INT WINAPI GetProfileSectionA( LPCSTR section, LPSTR buffer, DWORD len )
1251 return GetPrivateProfileSectionA( section, buffer, len, "win.ini" );
1254 /***********************************************************************
1255 * GetProfileSection32W (KERNEL32)
1257 INT WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len )
1259 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1260 return GetPrivateProfileSectionW( section, buffer, len, wininiW );
1264 /***********************************************************************
1265 * WritePrivateProfileString16 (KERNEL.129)
1267 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
1268 LPCSTR string, LPCSTR filename )
1270 return WritePrivateProfileStringA(section,entry,string,filename);
1273 /***********************************************************************
1274 * WritePrivateProfileString32A (KERNEL32.582)
1276 BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
1277 LPCSTR string, LPCSTR filename )
1279 BOOL ret = FALSE;
1281 EnterCriticalSection( &PROFILE_CritSect );
1283 if (PROFILE_Open( filename ))
1285 if (!section && !entry && !string)
1286 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1287 else
1288 ret = PROFILE_SetString( section, entry, string );
1291 LeaveCriticalSection( &PROFILE_CritSect );
1292 return ret;
1295 /***********************************************************************
1296 * WritePrivateProfileString32W (KERNEL32.583)
1298 BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
1299 LPCWSTR string, LPCWSTR filename )
1301 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1302 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1303 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1304 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1305 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
1306 stringA, filenameA );
1307 HeapFree( GetProcessHeap(), 0, sectionA );
1308 HeapFree( GetProcessHeap(), 0, entryA );
1309 HeapFree( GetProcessHeap(), 0, stringA );
1310 HeapFree( GetProcessHeap(), 0, filenameA );
1311 return res;
1314 /***********************************************************************
1315 * WritePrivateProfileSection16 (KERNEL.416)
1317 BOOL16 WINAPI WritePrivateProfileSection16( LPCSTR section,
1318 LPCSTR string, LPCSTR filename )
1320 return WritePrivateProfileSectionA( section, string, filename );
1323 /***********************************************************************
1324 * WritePrivateProfileSectionA (KERNEL32)
1326 BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section,
1327 LPCSTR string, LPCSTR filename )
1329 BOOL ret = FALSE;
1330 LPSTR p ;
1332 EnterCriticalSection( &PROFILE_CritSect );
1334 if (PROFILE_Open( filename )) {
1335 if (!section && !string && !filename)
1336 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1337 else {
1338 while(*string){
1339 LPSTR buf=HEAP_strdupA( GetProcessHeap(), 0, string );
1340 if((p=strchr( buf, '='))){
1341 *p='\0';
1342 ret = PROFILE_SetString( section, buf, p+1 );
1345 HeapFree( GetProcessHeap(), 0, buf );
1346 string += strlen(string)+1;
1352 LeaveCriticalSection( &PROFILE_CritSect );
1353 return ret;
1356 /***********************************************************************
1357 * WritePrivateProfileSection32W (KERNEL32)
1359 BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
1360 LPCWSTR string, LPCWSTR filename)
1363 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1364 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1365 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1366 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
1367 HeapFree( GetProcessHeap(), 0, sectionA );
1368 HeapFree( GetProcessHeap(), 0, stringA );
1369 HeapFree( GetProcessHeap(), 0, filenameA );
1370 return res;
1373 /***********************************************************************
1374 * WriteProfileSection16 (KERNEL.417)
1376 BOOL16 WINAPI WriteProfileSection16( LPCSTR section, LPCSTR keys_n_values)
1378 return WritePrivateProfileSection16( section, keys_n_values, "win.ini");
1381 /***********************************************************************
1382 * WriteProfileSection32A (KERNEL32.747)
1384 BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values)
1387 return WritePrivateProfileSectionA( section, keys_n_values, "win.ini");
1390 /***********************************************************************
1391 * WriteProfileSection32W (KERNEL32.748)
1393 BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values)
1395 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini");
1397 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW));
1400 /***********************************************************************
1401 * GetPrivateProfileSectionNames16 (KERNEL.143)
1403 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1404 LPCSTR filename )
1406 WORD ret = 0;
1408 EnterCriticalSection( &PROFILE_CritSect );
1410 if (PROFILE_Open( filename ))
1411 ret = PROFILE_GetSectionNames(buffer, size);
1413 LeaveCriticalSection( &PROFILE_CritSect );
1415 return ret;
1419 /***********************************************************************
1420 * GetProfileSectionNames16 (KERNEL.142)
1422 WORD WINAPI GetProfileSectionNames16( LPSTR buffer, WORD size)
1425 return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
1429 /***********************************************************************
1430 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1432 DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,
1433 LPCSTR filename)
1436 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1440 /***********************************************************************
1441 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1443 DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
1444 LPCWSTR filename)
1447 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1448 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, size);
1450 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1451 lstrcpynAtoW( buffer, bufferA, size);
1452 HeapFree( GetProcessHeap(), 0, bufferA);
1453 HeapFree( GetProcessHeap(), 0, filenameA );
1455 return ret;
1458 /***********************************************************************
1459 * GetPrivateProfileStruct16 (KERNEL.407)
1461 BOOL16 WINAPI GetPrivateProfileStruct16(LPCSTR section, LPCSTR key,
1462 LPVOID buf, UINT16 len, LPCSTR filename)
1464 return GetPrivateProfileStructA( section, key, buf, len, filename );
1467 /***********************************************************************
1468 * GetPrivateProfileStruct32A (KERNEL32.370)
1470 BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
1471 LPVOID buf, UINT len, LPCSTR filename)
1473 BOOL ret = FALSE;
1475 EnterCriticalSection( &PROFILE_CritSect );
1477 if (PROFILE_Open( filename )) {
1478 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1479 if (k) {
1480 lstrcpynA( buf, k->value, strlen(k->value));
1481 ret = TRUE;
1484 LeaveCriticalSection( &PROFILE_CritSect );
1486 return FALSE;
1489 /***********************************************************************
1490 * GetPrivateProfileStruct32W (KERNEL32.543)
1492 BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
1493 LPVOID buffer, UINT len, LPCWSTR filename)
1495 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1496 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1497 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1498 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1500 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
1501 len, filenameA );
1502 lstrcpynAtoW( buffer, bufferA, len );
1503 HeapFree( GetProcessHeap(), 0, bufferA);
1504 HeapFree( GetProcessHeap(), 0, sectionA );
1505 HeapFree( GetProcessHeap(), 0, keyA );
1506 HeapFree( GetProcessHeap(), 0, filenameA );
1508 return ret;
1513 /***********************************************************************
1514 * WritePrivateProfileStruct16 (KERNEL.406)
1516 BOOL16 WINAPI WritePrivateProfileStruct16 (LPCSTR section, LPCSTR key,
1517 LPVOID buf, UINT16 bufsize, LPCSTR filename)
1519 return WritePrivateProfileStructA( section, key, buf, bufsize, filename );
1522 /***********************************************************************
1523 * WritePrivateProfileStruct32A (KERNEL32.744)
1525 BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
1526 LPVOID buf, UINT bufsize, LPCSTR filename)
1528 BOOL ret = FALSE;
1530 if (!section && !key && !buf) /* flush the cache */
1531 return WritePrivateProfileStringA( NULL, NULL, NULL, filename );
1533 EnterCriticalSection( &PROFILE_CritSect );
1535 if (PROFILE_Open( filename ))
1536 ret = PROFILE_SetString( section, key, buf );
1538 LeaveCriticalSection( &PROFILE_CritSect );
1540 return ret;
1543 /***********************************************************************
1544 * WritePrivateProfileStruct32W (KERNEL32.544)
1546 BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
1547 LPVOID buf, UINT bufsize, LPCWSTR filename)
1549 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1550 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1551 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1552 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
1553 filenameA );
1554 HeapFree( GetProcessHeap(), 0, sectionA );
1555 HeapFree( GetProcessHeap(), 0, keyA );
1556 HeapFree( GetProcessHeap(), 0, filenameA );
1558 return ret;
1562 /***********************************************************************
1563 * WriteOutProfiles (KERNEL.315)
1565 void WINAPI WriteOutProfiles16(void)
1567 EnterCriticalSection( &PROFILE_CritSect );
1568 PROFILE_FlushFile();
1569 LeaveCriticalSection( &PROFILE_CritSect );
1572 /***********************************************************************
1573 * CloseProfileUserMapping (KERNEL.138)
1575 BOOL WINAPI CloseProfileUserMapping(void) {
1576 FIXME("(), stub!\n");
1577 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1578 return FALSE;