4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
12 #include <sys/types.h>
18 #include "wine/winbase16.h"
23 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(profile
)
29 typedef struct tagPROFILEKEY
33 struct tagPROFILEKEY
*next
;
36 typedef struct tagPROFILESECTION
39 struct tagPROFILEKEY
*key
;
40 struct tagPROFILESECTION
*next
;
47 PROFILESECTION
*section
;
55 #define N_CACHED_PROFILES 10
57 /* Cached profile files */
58 static PROFILE
*MRUProfile
[N_CACHED_PROFILES
]={NULL
};
60 #define CurProfile (MRUProfile[0])
62 /* wine.ini profile content */
63 static PROFILESECTION
*PROFILE_WineProfile
;
65 #define PROFILE_MAX_LINE_LEN 1024
67 /* Wine profile name in $HOME directory; must begin with slash */
68 static const char PROFILE_WineIniName
[] = "/.winerc";
70 /* Wine profile: the profile file being used */
71 static char PROFILE_WineIniUsed
[MAX_PATHNAME_LEN
] = "";
73 /* Check for comments in profile */
74 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
76 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
77 #define WINE_CONFIG_DIR "/.wine" /* config dir inside $HOME */
79 static LPCWSTR wininiW
= NULL
;
81 static CRITICAL_SECTION PROFILE_CritSect
;
84 /***********************************************************************
85 * PROFILE_GetConfigDir
87 * Return the name of the configuration directory ($HOME/.wine)
89 const char *PROFILE_GetConfigDir(void)
94 const char *home
= getenv( "HOME" );
97 struct passwd
*pwd
= getpwuid( getuid() );
100 fprintf( stderr
, "wine: could not find your home directory\n" );
105 confdir
= xmalloc( strlen(home
) + strlen(WINE_CONFIG_DIR
) + 1 );
106 strcpy( confdir
, home
);
107 strcat( confdir
, WINE_CONFIG_DIR
);
108 mkdir( confdir
, 0755 ); /* create it just in case */
114 /***********************************************************************
117 * Copy the content of an entry into a buffer, removing quotes, and possibly
118 * translating environment variables.
120 static void PROFILE_CopyEntry( char *buffer
, const char *value
, int len
,
126 if ((*value
== '\'') || (*value
== '\"'))
128 if (value
[1] && (value
[strlen(value
)-1] == *value
)) quote
= *value
++;
133 lstrcpynA( buffer
, value
, len
);
134 if (quote
&& (len
>= strlen(value
))) buffer
[strlen(buffer
)-1] = '\0';
138 for (p
= value
; (*p
&& (len
> 1)); *buffer
++ = *p
++, len
-- )
140 if ((*p
== '$') && (p
[1] == '{'))
144 const char *p2
= strchr( p
, '}' );
145 if (!p2
) continue; /* ignore it */
146 lstrcpynA(env_val
, p
+ 2, MIN( sizeof(env_val
), (int)(p2
-p
)-1 ));
147 if ((env_p
= getenv( env_val
)) != NULL
)
149 lstrcpynA( buffer
, env_p
, len
);
150 buffer
+= strlen( buffer
);
151 len
-= strlen( buffer
);
156 if (quote
&& (len
> 1)) buffer
--;
161 /***********************************************************************
164 * Save a profile tree to a file.
166 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
170 for ( ; section
; section
= section
->next
)
172 if (section
->name
) fprintf( file
, "\r\n[%s]\r\n", section
->name
);
173 for (key
= section
->key
; key
; key
= key
->next
)
175 fprintf( file
, "%s", key
->name
);
176 if (key
->value
) fprintf( file
, "=%s", key
->value
);
177 fprintf( file
, "\r\n" );
183 /***********************************************************************
186 * Free a profile tree.
188 static void PROFILE_Free( PROFILESECTION
*section
)
190 PROFILESECTION
*next_section
;
191 PROFILEKEY
*key
, *next_key
;
193 for ( ; section
; section
= next_section
)
195 if (section
->name
) HeapFree( SystemHeap
, 0, section
->name
);
196 for (key
= section
->key
; key
; key
= next_key
)
198 next_key
= key
->next
;
199 if (key
->name
) HeapFree( SystemHeap
, 0, key
->name
);
200 if (key
->value
) HeapFree( SystemHeap
, 0, key
->value
);
201 HeapFree( SystemHeap
, 0, key
);
203 next_section
= section
->next
;
204 HeapFree( SystemHeap
, 0, section
);
209 PROFILE_isspace(char c
) {
210 if (isspace(c
)) return 1;
211 if (c
=='\r' || c
==0x1a) return 1;
212 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
217 /***********************************************************************
220 * Load a profile tree from a file.
222 static PROFILESECTION
*PROFILE_Load( FILE *file
)
224 char buffer
[PROFILE_MAX_LINE_LEN
];
227 PROFILESECTION
*section
, *first_section
;
228 PROFILESECTION
**next_section
;
229 PROFILEKEY
*key
, *prev_key
, **next_key
;
231 first_section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
232 first_section
->name
= NULL
;
233 first_section
->key
= NULL
;
234 first_section
->next
= NULL
;
235 next_section
= &first_section
->next
;
236 next_key
= &first_section
->key
;
239 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
243 while (*p
&& PROFILE_isspace(*p
)) p
++;
244 if (*p
== '[') /* section start */
246 if (!(p2
= strrchr( p
, ']' )))
248 WARN("Invalid section header at line %d: '%s'\n",
255 section
= HEAP_xalloc( SystemHeap
, 0, sizeof(*section
) );
256 section
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
258 section
->next
= NULL
;
259 *next_section
= section
;
260 next_section
= §ion
->next
;
261 next_key
= §ion
->key
;
264 TRACE("New section: '%s'\n",section
->name
);
271 while ((p2
> p
) && ((*p2
== '\n') || PROFILE_isspace(*p2
))) *p2
--='\0';
273 if ((p2
= strchr( p
, '=' )) != NULL
)
276 while ((p3
> p
) && PROFILE_isspace(*p3
)) *p3
-- = '\0';
278 while (*p2
&& PROFILE_isspace(*p2
)) p2
++;
281 if(*p
|| !prev_key
|| *prev_key
->name
)
283 key
= HEAP_xalloc( SystemHeap
, 0, sizeof(*key
) );
284 key
->name
= HEAP_strdupA( SystemHeap
, 0, p
);
285 key
->value
= p2
? HEAP_strdupA( SystemHeap
, 0, p2
) : NULL
;
288 next_key
= &key
->next
;
291 TRACE("New key: name='%s', value='%s'\n",key
->name
,key
->value
?key
->value
:"(none)");
294 return first_section
;
298 /***********************************************************************
299 * PROFILE_DeleteSection
301 * Delete a section from a profile tree.
303 static BOOL
PROFILE_DeleteSection( PROFILESECTION
**section
, LPCSTR name
)
307 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, name
))
309 PROFILESECTION
*to_del
= *section
;
310 *section
= to_del
->next
;
312 PROFILE_Free( to_del
);
315 section
= &(*section
)->next
;
321 /***********************************************************************
324 * Delete a key from a profile tree.
326 static BOOL
PROFILE_DeleteKey( PROFILESECTION
**section
,
327 LPCSTR section_name
, LPCSTR key_name
)
331 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
333 PROFILEKEY
**key
= &(*section
)->key
;
336 if (!strcasecmp( (*key
)->name
, key_name
))
338 PROFILEKEY
*to_del
= *key
;
340 if (to_del
->name
) HeapFree( SystemHeap
, 0, to_del
->name
);
341 if (to_del
->value
) HeapFree( SystemHeap
, 0, to_del
->value
);
342 HeapFree( SystemHeap
, 0, to_del
);
348 section
= &(*section
)->next
;
354 /***********************************************************************
357 * Find a key in a profile tree, optionally creating it.
359 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
360 const char *section_name
,
361 const char *key_name
, int create
)
365 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
367 PROFILEKEY
**key
= &(*section
)->key
;
370 if (!strcasecmp( (*key
)->name
, key_name
)) return *key
;
373 if (!create
) return NULL
;
374 *key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
375 (*key
)->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
376 (*key
)->value
= NULL
;
380 section
= &(*section
)->next
;
382 if (!create
) return NULL
;
383 *section
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILESECTION
) );
384 (*section
)->name
= HEAP_strdupA( SystemHeap
, 0, section_name
);
385 (*section
)->next
= NULL
;
386 (*section
)->key
= HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILEKEY
) );
387 (*section
)->key
->name
= HEAP_strdupA( SystemHeap
, 0, key_name
);
388 (*section
)->key
->value
= NULL
;
389 (*section
)->key
->next
= NULL
;
390 return (*section
)->key
;
394 /***********************************************************************
397 * Flush the current profile to disk if changed.
399 static BOOL
PROFILE_FlushFile(void)
401 char *p
, buffer
[MAX_PATHNAME_LEN
];
402 const char *unix_name
;
408 WARN("No current profile!\n");
412 if (!CurProfile
->changed
|| !CurProfile
->dos_name
) return TRUE
;
413 if (!(unix_name
= CurProfile
->unix_name
) || !(file
= fopen(unix_name
, "w")))
415 /* Try to create it in $HOME/.wine */
416 /* FIXME: this will need a more general solution */
417 strcpy( buffer
, PROFILE_GetConfigDir() );
418 p
= buffer
+ strlen(buffer
);
420 strcpy( p
, strrchr( CurProfile
->dos_name
, '\\' ) + 1 );
422 file
= fopen( buffer
, "w" );
428 WARN("could not save profile file %s\n", CurProfile
->dos_name
);
432 TRACE("Saving '%s' into '%s'\n", CurProfile
->dos_name
, unix_name
);
433 PROFILE_Save( file
, CurProfile
->section
);
435 CurProfile
->changed
= FALSE
;
436 if(!stat(unix_name
,&buf
))
437 CurProfile
->mtime
=buf
.st_mtime
;
442 /***********************************************************************
443 * PROFILE_ReleaseFile
445 * Flush the current profile to disk and remove it from the cache.
447 static void PROFILE_ReleaseFile(void)
450 PROFILE_Free( CurProfile
->section
);
451 if (CurProfile
->dos_name
) HeapFree( SystemHeap
, 0, CurProfile
->dos_name
);
452 if (CurProfile
->unix_name
) HeapFree( SystemHeap
, 0, CurProfile
->unix_name
);
453 if (CurProfile
->filename
) HeapFree( SystemHeap
, 0, CurProfile
->filename
);
454 CurProfile
->changed
= FALSE
;
455 CurProfile
->section
= NULL
;
456 CurProfile
->dos_name
= NULL
;
457 CurProfile
->unix_name
= NULL
;
458 CurProfile
->filename
= NULL
;
459 CurProfile
->mtime
= 0;
463 /***********************************************************************
466 * Open a profile file, checking the cached file first.
468 static BOOL
PROFILE_Open( LPCSTR filename
)
470 DOS_FULL_NAME full_name
;
471 char buffer
[MAX_PATHNAME_LEN
];
472 char *newdos_name
, *p
;
476 PROFILE
*tempProfile
;
478 /* First time around */
481 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
483 MRUProfile
[i
]=HEAP_xalloc( SystemHeap
, 0, sizeof(PROFILE
) );
484 MRUProfile
[i
]->changed
=FALSE
;
485 MRUProfile
[i
]->section
=NULL
;
486 MRUProfile
[i
]->dos_name
=NULL
;
487 MRUProfile
[i
]->unix_name
=NULL
;
488 MRUProfile
[i
]->filename
=NULL
;
489 MRUProfile
[i
]->mtime
=0;
492 /* Check for a match */
494 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
495 strchr( filename
, ':' ))
497 if (!DOSFS_GetFullName( filename
, FALSE
, &full_name
)) return FALSE
;
501 GetWindowsDirectoryA( buffer
, sizeof(buffer
) );
502 strcat( buffer
, "\\" );
503 strcat( buffer
, filename
);
504 if (!DOSFS_GetFullName( buffer
, FALSE
, &full_name
)) return FALSE
;
507 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
509 if ((MRUProfile
[i
]->filename
&& !strcmp( filename
, MRUProfile
[i
]->filename
)) ||
510 (MRUProfile
[i
]->dos_name
&& !strcmp( full_name
.short_name
, MRUProfile
[i
]->dos_name
)))
515 tempProfile
=MRUProfile
[i
];
517 MRUProfile
[j
]=MRUProfile
[j
-1];
518 CurProfile
=tempProfile
;
520 if(!stat(CurProfile
->unix_name
,&buf
) && CurProfile
->mtime
==buf
.st_mtime
)
521 TRACE("(%s): already opened (mru=%d)\n",
524 TRACE("(%s): already opened, needs refreshing (mru=%d)\n",
530 /* Flush the old current profile */
533 /* Make the oldest profile the current one only in order to get rid of it */
534 if(i
==N_CACHED_PROFILES
)
536 tempProfile
=MRUProfile
[N_CACHED_PROFILES
-1];
537 for(i
=N_CACHED_PROFILES
-1;i
>0;i
--)
538 MRUProfile
[i
]=MRUProfile
[i
-1];
539 CurProfile
=tempProfile
;
541 if(CurProfile
->filename
) PROFILE_ReleaseFile();
543 /* OK, now that CurProfile is definitely free we assign it our new file */
544 newdos_name
= HEAP_strdupA( SystemHeap
, 0, full_name
.short_name
);
545 CurProfile
->dos_name
= newdos_name
;
546 CurProfile
->filename
= HEAP_strdupA( SystemHeap
, 0, filename
);
548 /* Try to open the profile file, first in $HOME/.wine */
550 /* FIXME: this will need a more general solution */
551 strcpy( buffer
, PROFILE_GetConfigDir() );
552 p
= buffer
+ strlen(buffer
);
554 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
556 if ((file
= fopen( buffer
, "r" )))
558 TRACE("(%s): found it in %s\n",
560 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0, buffer
);
565 CurProfile
->unix_name
= HEAP_strdupA( SystemHeap
, 0,
566 full_name
.long_name
);
567 if ((file
= fopen( full_name
.long_name
, "r" )))
568 TRACE("(%s): found it in %s\n",
569 filename
, full_name
.long_name
);
574 CurProfile
->section
= PROFILE_Load( file
);
576 if(!stat(CurProfile
->unix_name
,&buf
))
577 CurProfile
->mtime
=buf
.st_mtime
;
581 /* Does not exist yet, we will create it in PROFILE_FlushFile */
582 WARN("profile file %s not found\n", newdos_name
);
588 /***********************************************************************
591 * Returns all keys of a section.
592 * If return_values is TRUE, also include the corresponding values.
594 static INT
PROFILE_GetSection( PROFILESECTION
*section
, LPCSTR section_name
,
595 LPSTR buffer
, UINT len
, BOOL handle_env
,
601 if (section
->name
&& !strcasecmp( section
->name
, section_name
))
604 for (key
= section
->key
; key
; key
= key
->next
)
607 if (!*key
->name
) continue; /* Skip empty lines */
608 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
609 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
610 len
-= strlen(buffer
) + 1;
611 buffer
+= strlen(buffer
) + 1;
612 if (return_values
&& key
->value
) {
614 PROFILE_CopyEntry ( buffer
,
615 key
->value
, len
- 1, handle_env
);
616 len
-= strlen(buffer
) + 1;
617 buffer
+= strlen(buffer
) + 1;
622 /*If either lpszSection or lpszKey is NULL and the supplied
623 destination buffer is too small to hold all the strings,
624 the last string is truncated and followed by two null characters.
625 In this case, the return value is equal to cchReturnBuffer
633 section
= section
->next
;
635 buffer
[0] = buffer
[1] = '\0';
640 static INT
PROFILE_GetSectionNames( LPSTR buffer
, UINT len
)
644 PROFILESECTION
*section
;
646 for (section
= CurProfile
->section
; section
; section
= section
->next
)
648 l
= strlen(section
->name
);
653 strcpy(buf
, section
->name
);
663 /***********************************************************************
666 * Get a profile string.
668 static INT
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
669 LPCSTR def_val
, LPSTR buffer
, UINT len
)
671 PROFILEKEY
*key
= NULL
;
673 if (!def_val
) def_val
= "";
674 if (key_name
&& key_name
[0])
676 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
677 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
679 TRACE("('%s','%s','%s'): returning '%s'\n",
680 section
, key_name
, def_val
, buffer
);
681 return strlen( buffer
);
683 if (section
&& section
[0])
684 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
686 /* undocumented; both section and key_name are NULL */
687 return PROFILE_GetSectionNames(buffer
, len
);
691 /***********************************************************************
694 * Set a profile string.
696 static BOOL
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
699 if (!key_name
) /* Delete a whole section */
701 TRACE("('%s')\n", section_name
);
702 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
704 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
705 this is not an error on application's level.*/
707 else if (!value
) /* Delete a key */
709 TRACE("('%s','%s')\n",
710 section_name
, key_name
);
711 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
712 section_name
, key_name
);
713 return TRUE
; /* same error handling as above */
715 else /* Set the key value */
717 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
719 TRACE("('%s','%s','%s'): \n",
720 section_name
, key_name
, value
);
721 if (!key
) return FALSE
;
724 if (!strcmp( key
->value
, value
))
726 TRACE(" no change needed\n" );
727 return TRUE
; /* No change needed */
729 TRACE(" replacing '%s'\n", key
->value
);
730 HeapFree( SystemHeap
, 0, key
->value
);
732 else TRACE(" creating key\n" );
733 key
->value
= HEAP_strdupA( SystemHeap
, 0, value
);
734 CurProfile
->changed
= TRUE
;
740 /***********************************************************************
741 * PROFILE_GetWineIniString
743 * Get a config string from the wine.ini file.
745 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
746 const char *def
, char *buffer
, int len
)
750 EnterCriticalSection( &PROFILE_CritSect
);
754 PROFILEKEY
*key
= PROFILE_Find(&PROFILE_WineProfile
, section
, key_name
, FALSE
);
755 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def
,
757 TRACE("('%s','%s','%s'): returning '%s'\n",
758 section
, key_name
, def
, buffer
);
759 ret
= strlen( buffer
);
763 ret
= PROFILE_GetSection( PROFILE_WineProfile
, section
, buffer
, len
, TRUE
, FALSE
);
765 LeaveCriticalSection( &PROFILE_CritSect
);
771 /***********************************************************************
772 * PROFILE_GetWineIniInt
774 * Get a config integer from the wine.ini file.
776 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
784 EnterCriticalSection( &PROFILE_CritSect
);
786 key
= PROFILE_Find( &PROFILE_WineProfile
, section
, key_name
, FALSE
);
787 if (!key
|| !key
->value
) {
790 PROFILE_CopyEntry( buffer
, key
->value
, sizeof(buffer
), TRUE
);
791 result
= strtol( buffer
, &p
, 0 );
792 ret
= (p
== buffer
) ? 0 /* No digits at all */ : (int)result
;
795 LeaveCriticalSection( &PROFILE_CritSect
);
801 /******************************************************************************
803 * int PROFILE_EnumerateWineIniSection(
804 * char const *section, #Name of the section to enumerate
805 * void (*cbfn)(char const *key, char const *value, void *user),
806 * # Address of the callback function
807 * void *user ) # User-specified pointer.
809 * For each entry in a section in the wine.conf file, this function will
810 * call the specified callback function, informing it of each key and
811 * value. An optional user pointer may be passed to it (if this is not
812 * needed, pass NULL through it and ignore the value in the callback
815 * The callback function must accept three parameters:
816 * The name of the key (char const *)
817 * The value of the key (char const *)
818 * A user-specified parameter (void *)
819 * Note that the first two are char CONST *'s, not char *'s! The callback
820 * MUST not modify these strings!
822 * The return value indicates the number of times the callback function
825 int PROFILE_EnumerateWineIniSection(
827 void (*cbfn
)(char const *, char const *, void *),
830 PROFILESECTION
*scansect
;
834 EnterCriticalSection( &PROFILE_CritSect
);
836 /* Search for the correct section */
837 for(scansect
= PROFILE_WineProfile
; scansect
; scansect
= scansect
->next
) {
838 if(scansect
->name
&& !strcasecmp(scansect
->name
, section
)) {
840 /* Enumerate each key with the callback */
841 for(scankey
= scansect
->key
; scankey
; scankey
= scankey
->next
) {
843 /* Ignore blank entries -- these shouldn't exist, but let's
845 if (!scankey
->name
[0]) continue;
846 if (!scankey
->value
) cbfn(scankey
->name
, NULL
, userptr
);
850 PROFILE_CopyEntry(value
, scankey
->value
, sizeof(value
), TRUE
);
851 cbfn(scankey
->name
, value
, userptr
);
859 LeaveCriticalSection( &PROFILE_CritSect
);
865 /******************************************************************************
867 * int PROFILE_GetWineIniBool(
868 * char const *section,
869 * char const *key_name,
872 * Reads a boolean value from the wine.ini file. This function attempts to
873 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
874 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
875 * true. Anything else results in the return of the default value.
877 * This function uses 1 to indicate true, and 0 for false. You can check
878 * for existence by setting def to something other than 0 or 1 and
879 * examining the return value.
881 int PROFILE_GetWineIniBool(
883 char const *key_name
,
889 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
891 switch(key_value
[0]) {
912 TRACE("(\"%s\", \"%s\", %s), "
913 "[%c], ret %s.\n", section
, key_name
,
914 def
? "TRUE" : "FALSE", key_value
[0],
915 retval
? "TRUE" : "FALSE");
921 /***********************************************************************
922 * PROFILE_LoadWineIni
924 * Load the wine.ini file.
926 int PROFILE_LoadWineIni(void)
928 char buffer
[MAX_PATHNAME_LEN
];
932 InitializeCriticalSection( &PROFILE_CritSect
);
933 MakeCriticalSectionGlobal( &PROFILE_CritSect
);
935 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
937 /* Open -config specified file */
938 PROFILE_WineProfile
= PROFILE_Load ( f
);
940 lstrcpynA(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
);
944 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
946 PROFILE_WineProfile
= PROFILE_Load( f
);
948 lstrcpynA(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
);
951 if ((p
= getenv( "HOME" )) != NULL
)
953 lstrcpynA(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
954 strcat( buffer
, PROFILE_WineIniName
);
955 if ((f
= fopen( buffer
, "r" )) != NULL
)
957 PROFILE_WineProfile
= PROFILE_Load( f
);
959 lstrcpynA(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
);
963 else WARN("could not get $HOME value for config file.\n" );
965 /* Try global file */
967 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
969 PROFILE_WineProfile
= PROFILE_Load( f
);
971 lstrcpynA(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
);
974 MESSAGE( "Can't open configuration file %s or $HOME%s\n",
975 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
980 /***********************************************************************
981 * PROFILE_UsageWineIni
983 * Explain the wine.ini file to those who don't read documentation.
984 * Keep below one screenful in length so that error messages above are
987 void PROFILE_UsageWineIni(void)
989 MESSAGE("Perhaps you have not properly edited or created "
990 "your Wine configuration file.\n");
991 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
992 MESSAGE(" or it is determined by the -config option or from\n"
993 " the WINE_INI environment variable.\n");
994 if (*PROFILE_WineIniUsed
)
995 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
996 /* RTFM, so to say */
999 /***********************************************************************
1000 * PROFILE_GetStringItem
1002 * Convenience function that turns a string 'xxx, yyy, zzz' into
1003 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
1005 char* PROFILE_GetStringItem( char* start
)
1009 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
1013 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
1015 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
1017 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
1020 if( lpch
) *lpch
= '\0';
1024 /********************* API functions **********************************/
1026 /***********************************************************************
1027 * GetProfileInt16 (KERNEL.57)
1029 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
1031 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
1035 /***********************************************************************
1036 * GetProfileInt32A (KERNEL32.264)
1038 UINT WINAPI
GetProfileIntA( LPCSTR section
, LPCSTR entry
, INT def_val
)
1040 return GetPrivateProfileIntA( section
, entry
, def_val
, "win.ini" );
1043 /***********************************************************************
1044 * GetProfileInt32W (KERNEL32.264)
1046 UINT WINAPI
GetProfileIntW( LPCWSTR section
, LPCWSTR entry
, INT def_val
)
1048 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1049 return GetPrivateProfileIntW( section
, entry
, def_val
, wininiW
);
1052 /***********************************************************************
1053 * GetProfileString16 (KERNEL.58)
1055 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1056 LPSTR buffer
, UINT16 len
)
1058 return GetPrivateProfileString16( section
, entry
, def_val
,
1059 buffer
, len
, "win.ini" );
1062 /***********************************************************************
1063 * GetProfileString32A (KERNEL32.268)
1065 INT WINAPI
GetProfileStringA( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1066 LPSTR buffer
, UINT len
)
1068 return GetPrivateProfileStringA( section
, entry
, def_val
,
1069 buffer
, len
, "win.ini" );
1072 /***********************************************************************
1073 * GetProfileString32W (KERNEL32.269)
1075 INT WINAPI
GetProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1076 LPCWSTR def_val
, LPWSTR buffer
, UINT len
)
1078 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1079 return GetPrivateProfileStringW( section
, entry
, def_val
,
1080 buffer
, len
, wininiW
);
1083 /***********************************************************************
1084 * WriteProfileString16 (KERNEL.59)
1086 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1089 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1092 /***********************************************************************
1093 * WriteProfileString32A (KERNEL32.587)
1095 BOOL WINAPI
WriteProfileStringA( LPCSTR section
, LPCSTR entry
,
1098 return WritePrivateProfileStringA( section
, entry
, string
, "win.ini" );
1101 /***********************************************************************
1102 * WriteProfileString32W (KERNEL32.588)
1104 BOOL WINAPI
WriteProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1107 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1108 return WritePrivateProfileStringW( section
, entry
, string
, wininiW
);
1112 /***********************************************************************
1113 * GetPrivateProfileInt16 (KERNEL.127)
1115 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1116 INT16 def_val
, LPCSTR filename
)
1118 long result
=(long)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
1120 if (result
> 65535) return 65535;
1121 if (result
>= 0) return (UINT16
)result
;
1122 if (result
< -32768) return -32768;
1123 return (UINT16
)(INT16
)result
;
1126 /***********************************************************************
1127 * GetPrivateProfileInt32A (KERNEL32.251)
1129 UINT WINAPI
GetPrivateProfileIntA( LPCSTR section
, LPCSTR entry
,
1130 INT def_val
, LPCSTR filename
)
1136 GetPrivateProfileStringA( section
, entry
, "",
1137 buffer
, sizeof(buffer
), filename
);
1138 if (!buffer
[0]) return (UINT
)def_val
;
1139 result
= strtol( buffer
, &p
, 0 );
1140 if (p
== buffer
) return 0; /* No digits at all */
1141 return (UINT
)result
;
1144 /***********************************************************************
1145 * GetPrivateProfileInt32W (KERNEL32.252)
1147 UINT WINAPI
GetPrivateProfileIntW( LPCWSTR section
, LPCWSTR entry
,
1148 INT def_val
, LPCWSTR filename
)
1150 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1151 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1152 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1153 UINT res
= GetPrivateProfileIntA(sectionA
, entryA
, def_val
, filenameA
);
1154 HeapFree( GetProcessHeap(), 0, sectionA
);
1155 HeapFree( GetProcessHeap(), 0, filenameA
);
1156 HeapFree( GetProcessHeap(), 0, entryA
);
1160 /***********************************************************************
1161 * GetPrivateProfileString16 (KERNEL.128)
1163 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1164 LPCSTR def_val
, LPSTR buffer
,
1165 UINT16 len
, LPCSTR filename
)
1167 return GetPrivateProfileStringA(section
,entry
,def_val
,buffer
,len
,filename
);
1170 /***********************************************************************
1171 * GetPrivateProfileString32A (KERNEL32.255)
1173 INT WINAPI
GetPrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1174 LPCSTR def_val
, LPSTR buffer
,
1175 UINT len
, LPCSTR filename
)
1180 filename
= "win.ini";
1182 EnterCriticalSection( &PROFILE_CritSect
);
1184 if (PROFILE_Open( filename
)) {
1185 ret
= PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1187 lstrcpynA( buffer
, def_val
, len
);
1188 ret
= strlen( buffer
);
1191 LeaveCriticalSection( &PROFILE_CritSect
);
1196 /***********************************************************************
1197 * GetPrivateProfileString32W (KERNEL32.256)
1199 INT WINAPI
GetPrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1200 LPCWSTR def_val
, LPWSTR buffer
,
1201 UINT len
, LPCWSTR filename
)
1203 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1204 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1205 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1206 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1207 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1208 INT ret
= GetPrivateProfileStringA( sectionA
, entryA
, def_valA
,
1209 bufferA
, len
, filenameA
);
1210 lstrcpynAtoW( buffer
, bufferA
, len
);
1211 HeapFree( GetProcessHeap(), 0, sectionA
);
1212 HeapFree( GetProcessHeap(), 0, entryA
);
1213 HeapFree( GetProcessHeap(), 0, filenameA
);
1214 HeapFree( GetProcessHeap(), 0, def_valA
);
1215 HeapFree( GetProcessHeap(), 0, bufferA
);
1219 /***********************************************************************
1220 * GetPrivateProfileSection16 (KERNEL.418)
1222 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
1223 UINT16 len
, LPCSTR filename
)
1225 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
1228 /***********************************************************************
1229 * GetPrivateProfileSection32A (KERNEL32.255)
1231 INT WINAPI
GetPrivateProfileSectionA( LPCSTR section
, LPSTR buffer
,
1232 DWORD len
, LPCSTR filename
)
1236 EnterCriticalSection( &PROFILE_CritSect
);
1238 if (PROFILE_Open( filename
))
1239 ret
= PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1242 LeaveCriticalSection( &PROFILE_CritSect
);
1247 /***********************************************************************
1248 * GetPrivateProfileSection32W (KERNEL32.256)
1251 INT WINAPI
GetPrivateProfileSectionW (LPCWSTR section
, LPWSTR buffer
,
1252 DWORD len
, LPCWSTR filename
)
1255 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1256 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1257 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1258 INT ret
= GetPrivateProfileSectionA( sectionA
, bufferA
, len
,
1260 MultiByteToWideChar(CP_ACP
,0,bufferA
,ret
,buffer
,len
);
1261 HeapFree( GetProcessHeap(), 0, sectionA
);
1262 HeapFree( GetProcessHeap(), 0, filenameA
);
1263 HeapFree( GetProcessHeap(), 0, bufferA
);
1267 /***********************************************************************
1268 * GetProfileSection16 (KERNEL.419)
1270 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
1272 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
1275 /***********************************************************************
1276 * GetProfileSection32A (KERNEL32.268)
1278 INT WINAPI
GetProfileSectionA( LPCSTR section
, LPSTR buffer
, DWORD len
)
1280 return GetPrivateProfileSectionA( section
, buffer
, len
, "win.ini" );
1283 /***********************************************************************
1284 * GetProfileSection32W (KERNEL32)
1286 INT WINAPI
GetProfileSectionW( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
1288 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini" );
1289 return GetPrivateProfileSectionW( section
, buffer
, len
, wininiW
);
1293 /***********************************************************************
1294 * WritePrivateProfileString16 (KERNEL.129)
1296 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1297 LPCSTR string
, LPCSTR filename
)
1299 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
1302 /***********************************************************************
1303 * WritePrivateProfileString32A (KERNEL32.582)
1305 BOOL WINAPI
WritePrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1306 LPCSTR string
, LPCSTR filename
)
1310 EnterCriticalSection( &PROFILE_CritSect
);
1312 if (PROFILE_Open( filename
))
1314 if (!section
&& !entry
&& !string
)
1315 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1317 ret
= PROFILE_SetString( section
, entry
, string
);
1320 LeaveCriticalSection( &PROFILE_CritSect
);
1324 /***********************************************************************
1325 * WritePrivateProfileString32W (KERNEL32.583)
1327 BOOL WINAPI
WritePrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1328 LPCWSTR string
, LPCWSTR filename
)
1330 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1331 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1332 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1333 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1334 BOOL res
= WritePrivateProfileStringA( sectionA
, entryA
,
1335 stringA
, filenameA
);
1336 HeapFree( GetProcessHeap(), 0, sectionA
);
1337 HeapFree( GetProcessHeap(), 0, entryA
);
1338 HeapFree( GetProcessHeap(), 0, stringA
);
1339 HeapFree( GetProcessHeap(), 0, filenameA
);
1343 /***********************************************************************
1344 * WritePrivateProfileSection16 (KERNEL.416)
1346 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
1347 LPCSTR string
, LPCSTR filename
)
1349 return WritePrivateProfileSectionA( section
, string
, filename
);
1352 /***********************************************************************
1353 * WritePrivateProfileSectionA (KERNEL32)
1355 BOOL WINAPI
WritePrivateProfileSectionA( LPCSTR section
,
1356 LPCSTR string
, LPCSTR filename
)
1361 EnterCriticalSection( &PROFILE_CritSect
);
1363 if (PROFILE_Open( filename
)) {
1364 if (!section
&& !string
&& !filename
)
1365 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1368 LPSTR buf
=HEAP_strdupA( GetProcessHeap(), 0, string
);
1369 if((p
=strchr( buf
, '='))){
1371 ret
= PROFILE_SetString( section
, buf
, p
+1 );
1374 HeapFree( GetProcessHeap(), 0, buf
);
1375 string
+= strlen(string
)+1;
1381 LeaveCriticalSection( &PROFILE_CritSect
);
1385 /***********************************************************************
1386 * WritePrivateProfileSection32W (KERNEL32)
1388 BOOL WINAPI
WritePrivateProfileSectionW( LPCWSTR section
,
1389 LPCWSTR string
, LPCWSTR filename
)
1392 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1393 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1394 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1395 BOOL res
= WritePrivateProfileSectionA( sectionA
, stringA
, filenameA
);
1396 HeapFree( GetProcessHeap(), 0, sectionA
);
1397 HeapFree( GetProcessHeap(), 0, stringA
);
1398 HeapFree( GetProcessHeap(), 0, filenameA
);
1402 /***********************************************************************
1403 * WriteProfileSection16 (KERNEL.417)
1405 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
1407 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
1410 /***********************************************************************
1411 * WriteProfileSection32A (KERNEL32.747)
1413 BOOL WINAPI
WriteProfileSectionA( LPCSTR section
, LPCSTR keys_n_values
)
1416 return WritePrivateProfileSectionA( section
, keys_n_values
, "win.ini");
1419 /***********************************************************************
1420 * WriteProfileSection32W (KERNEL32.748)
1422 BOOL WINAPI
WriteProfileSectionW( LPCWSTR section
, LPCWSTR keys_n_values
)
1424 if (!wininiW
) wininiW
= HEAP_strdupAtoW( SystemHeap
, 0, "win.ini");
1426 return (WritePrivateProfileSectionW (section
,keys_n_values
, wininiW
));
1429 /***********************************************************************
1430 * GetPrivateProfileSectionNames16 (KERNEL.143)
1432 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1437 EnterCriticalSection( &PROFILE_CritSect
);
1439 if (PROFILE_Open( filename
))
1440 ret
= PROFILE_GetSectionNames(buffer
, size
);
1442 LeaveCriticalSection( &PROFILE_CritSect
);
1448 /***********************************************************************
1449 * GetProfileSectionNames16 (KERNEL.142)
1451 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1454 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1458 /***********************************************************************
1459 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1461 DWORD WINAPI
GetPrivateProfileSectionNamesA( LPSTR buffer
, DWORD size
,
1465 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1469 /***********************************************************************
1470 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1472 DWORD WINAPI
GetPrivateProfileSectionNamesW( LPWSTR buffer
, DWORD size
,
1476 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1477 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1479 INT ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1480 lstrcpynAtoW( buffer
, bufferA
, size
);
1481 HeapFree( GetProcessHeap(), 0, bufferA
);
1482 HeapFree( GetProcessHeap(), 0, filenameA
);
1487 /***********************************************************************
1488 * GetPrivateProfileStruct16 (KERNEL.407)
1490 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
1491 LPVOID buf
, UINT16 len
, LPCSTR filename
)
1493 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
1496 /***********************************************************************
1497 * GetPrivateProfileStruct32A (KERNEL32.370)
1499 BOOL WINAPI
GetPrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1500 LPVOID buf
, UINT len
, LPCSTR filename
)
1504 EnterCriticalSection( &PROFILE_CritSect
);
1506 if (PROFILE_Open( filename
)) {
1507 PROFILEKEY
*k
= PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1509 lstrcpynA( buf
, k
->value
, strlen(k
->value
));
1513 LeaveCriticalSection( &PROFILE_CritSect
);
1518 /***********************************************************************
1519 * GetPrivateProfileStruct32W (KERNEL32.543)
1521 BOOL WINAPI
GetPrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1522 LPVOID buffer
, UINT len
, LPCWSTR filename
)
1524 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1525 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1526 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1527 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1529 INT ret
= GetPrivateProfileStructA( sectionA
, keyA
, bufferA
,
1531 lstrcpynAtoW( buffer
, bufferA
, len
);
1532 HeapFree( GetProcessHeap(), 0, bufferA
);
1533 HeapFree( GetProcessHeap(), 0, sectionA
);
1534 HeapFree( GetProcessHeap(), 0, keyA
);
1535 HeapFree( GetProcessHeap(), 0, filenameA
);
1542 /***********************************************************************
1543 * WritePrivateProfileStruct16 (KERNEL.406)
1545 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
1546 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
1548 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
1551 /***********************************************************************
1552 * WritePrivateProfileStruct32A (KERNEL32.744)
1554 BOOL WINAPI
WritePrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1555 LPVOID buf
, UINT bufsize
, LPCSTR filename
)
1559 if (!section
&& !key
&& !buf
) /* flush the cache */
1560 return WritePrivateProfileStringA( NULL
, NULL
, NULL
, filename
);
1562 EnterCriticalSection( &PROFILE_CritSect
);
1564 if (PROFILE_Open( filename
))
1565 ret
= PROFILE_SetString( section
, key
, buf
);
1567 LeaveCriticalSection( &PROFILE_CritSect
);
1572 /***********************************************************************
1573 * WritePrivateProfileStruct32W (KERNEL32.544)
1575 BOOL WINAPI
WritePrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1576 LPVOID buf
, UINT bufsize
, LPCWSTR filename
)
1578 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1579 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1580 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1581 INT ret
= WritePrivateProfileStructA( sectionA
, keyA
, buf
, bufsize
,
1583 HeapFree( GetProcessHeap(), 0, sectionA
);
1584 HeapFree( GetProcessHeap(), 0, keyA
);
1585 HeapFree( GetProcessHeap(), 0, filenameA
);
1591 /***********************************************************************
1592 * WriteOutProfiles (KERNEL.315)
1594 void WINAPI
WriteOutProfiles16(void)
1596 EnterCriticalSection( &PROFILE_CritSect
);
1597 PROFILE_FlushFile();
1598 LeaveCriticalSection( &PROFILE_CritSect
);
1601 /***********************************************************************
1602 * CloseProfileUserMapping (KERNEL.138)
1604 BOOL WINAPI
CloseProfileUserMapping(void) {
1605 FIXME("(), stub!\n");
1606 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);