4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
15 #include "wine/winbase16.h"
22 typedef struct tagPROFILEKEY
26 struct tagPROFILEKEY *next;
29 typedef struct tagPROFILESECTION
32 struct tagPROFILEKEY *key;
33 struct tagPROFILESECTION *next;
40 PROFILESECTION *section;
48 #define N_CACHED_PROFILES 10
50 /* Cached profile files */
51 static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
53 #define CurProfile (MRUProfile[0])
55 /* wine.ini profile content */
56 static PROFILESECTION *WineProfile;
58 #define PROFILE_MAX_LINE_LEN 1024
60 /* Wine profile name in $HOME directory; must begin with slash */
61 static const char PROFILE_WineIniName[] = "/.winerc";
63 /* Wine profile: the profile file being used */
64 static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
66 /* Check for comments in profile */
67 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
69 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
71 static LPCWSTR wininiW = NULL;
73 /***********************************************************************
76 * Copy the content of an entry into a buffer, removing quotes, and possibly
77 * translating environment variables.
79 static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
85 if ((*value == '\'') || (*value == '\"'))
87 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
92 lstrcpyn32A( buffer, value, len );
93 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
97 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
99 if ((*p == '$') && (p[1] == '{'))
103 const char *p2 = strchr( p, '}' );
104 if (!p2) continue; /* ignore it */
105 lstrcpyn32A(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
106 if ((env_p = getenv( env_val )) != NULL)
108 lstrcpyn32A( buffer, env_p, len );
109 buffer += strlen( buffer );
110 len -= strlen( buffer );
119 /***********************************************************************
122 * Save a profile tree to a file.
124 static void PROFILE_Save( FILE *file, PROFILESECTION *section )
128 for ( ; section; section = section->next)
130 if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
131 for (key = section->key; key; key = key->next)
133 fprintf( file, "%s", key->name );
134 if (key->value) fprintf( file, "=%s", key->value );
135 fprintf( file, "\r\n" );
141 /***********************************************************************
144 * Free a profile tree.
146 static void PROFILE_Free( PROFILESECTION *section )
148 PROFILESECTION *next_section;
149 PROFILEKEY *key, *next_key;
151 for ( ; section; section = next_section)
153 if (section->name) HeapFree( SystemHeap, 0, section->name );
154 for (key = section->key; key; key = next_key)
156 next_key = key->next;
157 if (key->name) HeapFree( SystemHeap, 0, key->name );
158 if (key->value) HeapFree( SystemHeap, 0, key->value );
159 HeapFree( SystemHeap, 0, key );
161 next_section = section->next;
162 HeapFree( SystemHeap, 0, section );
167 PROFILE_isspace(char c) {
168 if (isspace(c)) return 1;
169 if (c=='\r' || c==0x1a) return 1;
170 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
175 /***********************************************************************
178 * Load a profile tree from a file.
180 static PROFILESECTION *PROFILE_Load( FILE *file )
182 char buffer[PROFILE_MAX_LINE_LEN];
185 PROFILESECTION *section, *first_section;
186 PROFILESECTION **next_section;
187 PROFILEKEY *key, *prev_key, **next_key;
189 first_section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
190 first_section->name = NULL;
191 first_section->key = NULL;
192 first_section->next = NULL;
193 next_section = &first_section->next;
194 next_key = &first_section->key;
197 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
201 while (*p && PROFILE_isspace(*p)) p++;
202 if (*p == '[') /* section start */
204 if (!(p2 = strrchr( p, ']' )))
206 WARN(profile, "Invalid section header at line %d: '%s'\n",
213 section = HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
214 section->name = HEAP_strdupA( SystemHeap, 0, p );
216 section->next = NULL;
217 *next_section = section;
218 next_section = §ion->next;
219 next_key = §ion->key;
222 TRACE(profile, "New section: '%s'\n",section->name);
229 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
231 if ((p2 = strchr( p, '=' )) != NULL)
234 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
236 while (*p2 && PROFILE_isspace(*p2)) p2++;
239 if(*p || !prev_key || *prev_key->name)
241 key = HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
242 key->name = HEAP_strdupA( SystemHeap, 0, p );
243 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
246 next_key = &key->next;
249 TRACE(profile, "New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)");
252 return first_section;
256 /***********************************************************************
257 * PROFILE_DeleteSection
259 * Delete a section from a profile tree.
261 static BOOL32 PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
265 if ((*section)->name && !strcasecmp( (*section)->name, name ))
267 PROFILESECTION *to_del = *section;
268 *section = to_del->next;
270 PROFILE_Free( to_del );
273 section = &(*section)->next;
279 /***********************************************************************
282 * Delete a key from a profile tree.
284 static BOOL32 PROFILE_DeleteKey( PROFILESECTION **section,
285 LPCSTR section_name, LPCSTR key_name )
289 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
291 PROFILEKEY **key = &(*section)->key;
294 if (!strcasecmp( (*key)->name, key_name ))
296 PROFILEKEY *to_del = *key;
298 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
299 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
300 HeapFree( SystemHeap, 0, to_del );
306 section = &(*section)->next;
312 /***********************************************************************
315 * Find a key in a profile tree, optionally creating it.
317 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
318 const char *section_name,
319 const char *key_name, int create )
323 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
325 PROFILEKEY **key = &(*section)->key;
328 if (!strcasecmp( (*key)->name, key_name )) return *key;
331 if (!create) return NULL;
332 *key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
333 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
334 (*key)->value = NULL;
338 section = &(*section)->next;
340 if (!create) return NULL;
341 *section = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
342 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
343 (*section)->next = NULL;
344 (*section)->key = HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
345 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
346 (*section)->key->value = NULL;
347 (*section)->key->next = NULL;
348 return (*section)->key;
352 /***********************************************************************
355 * Flush the current profile to disk if changed.
357 static BOOL32 PROFILE_FlushFile(void)
359 char *p, buffer[MAX_PATHNAME_LEN];
360 const char *unix_name;
366 WARN(profile, "No current profile!\n");
370 if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
371 if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
373 /* Try to create it in $HOME/.wine */
374 /* FIXME: this will need a more general solution */
375 if ((p = getenv( "HOME" )) != NULL)
378 strcat( buffer, "/.wine/" );
379 p = buffer + strlen(buffer);
380 strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
382 file = fopen( buffer, "w" );
389 WARN(profile, "could not save profile file %s\n", CurProfile->dos_name);
393 TRACE(profile, "Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name );
394 PROFILE_Save( file, CurProfile->section );
396 CurProfile->changed = FALSE;
397 if(!stat(unix_name,&buf))
398 CurProfile->mtime=buf.st_mtime;
403 /***********************************************************************
406 * Open a profile file, checking the cached file first.
408 static BOOL32 PROFILE_Open( LPCSTR filename )
410 DOS_FULL_NAME full_name;
411 char buffer[MAX_PATHNAME_LEN];
412 char *newdos_name, *p;
416 PROFILE *tempProfile;
418 /* First time around */
421 for(i=0;i<N_CACHED_PROFILES;i++)
423 MRUProfile[i]=HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );
424 MRUProfile[i]->changed=FALSE;
425 MRUProfile[i]->section=NULL;
426 MRUProfile[i]->dos_name=NULL;
427 MRUProfile[i]->unix_name=NULL;
428 MRUProfile[i]->filename=NULL;
429 MRUProfile[i]->mtime=0;
432 /* Check for a match */
434 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
435 strchr( filename, ':' ))
437 if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
441 GetWindowsDirectory32A( buffer, sizeof(buffer) );
442 strcat( buffer, "\\" );
443 strcat( buffer, filename );
444 if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
447 for(i=0;i<N_CACHED_PROFILES;i++)
449 if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )) ||
450 (MRUProfile[i]->dos_name && !strcmp( full_name.short_name, MRUProfile[i]->dos_name )))
455 tempProfile=MRUProfile[i];
457 MRUProfile[j]=MRUProfile[j-1];
458 CurProfile=tempProfile;
460 if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
461 TRACE(profile, "(%s): already opened (mru=%d)\n",
464 TRACE(profile, "(%s): already opened, needs refreshing (mru=%d)\n",
470 /* Rotate the oldest to the top to be replaced */
472 if(i==N_CACHED_PROFILES)
474 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
475 for(i=N_CACHED_PROFILES-1;i>0;i--)
476 MRUProfile[i]=MRUProfile[i-1];
477 CurProfile=tempProfile;
480 /* Flush the profile */
482 if(CurProfile->filename)
485 PROFILE_Free( CurProfile->section );
486 if (CurProfile->dos_name) HeapFree( SystemHeap, 0, CurProfile->dos_name );
487 if (CurProfile->unix_name) HeapFree( SystemHeap, 0, CurProfile->unix_name );
488 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
489 CurProfile->changed=FALSE;
490 CurProfile->section=NULL;
491 CurProfile->dos_name=NULL;
492 CurProfile->unix_name=NULL;
493 CurProfile->filename=NULL;
497 newdos_name = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
498 CurProfile->dos_name = newdos_name;
499 CurProfile->filename = HEAP_strdupA( SystemHeap, 0, filename );
501 /* Try to open the profile file, first in $HOME/.wine */
503 /* FIXME: this will need a more general solution */
504 if ((p = getenv( "HOME" )) != NULL)
507 strcat( buffer, "/.wine/" );
508 p = buffer + strlen(buffer);
509 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
511 if ((file = fopen( buffer, "r" )))
513 TRACE(profile, "(%s): found it in %s\n",
515 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
521 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0,
522 full_name.long_name );
523 if ((file = fopen( full_name.long_name, "r" )))
524 TRACE(profile, "(%s): found it in %s\n",
525 filename, full_name.long_name );
530 CurProfile->section = PROFILE_Load( file );
532 if(!stat(CurProfile->unix_name,&buf))
533 CurProfile->mtime=buf.st_mtime;
537 /* Does not exist yet, we will create it in PROFILE_FlushFile */
538 WARN(profile, "profile file %s not found\n", newdos_name );
544 /***********************************************************************
547 * Returns all keys of a section.
548 * If return_values is TRUE, also include the corresponding values.
550 static INT32 PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
551 LPSTR buffer, UINT32 len, BOOL32 handle_env,
552 BOOL32 return_values )
557 if (section->name && !strcasecmp( section->name, section_name ))
560 for (key = section->key; key; key = key->next)
563 if (!*key->name) continue; /* Skip empty lines */
564 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
565 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
566 len -= strlen(buffer) + 1;
567 buffer += strlen(buffer) + 1;
568 if (return_values && key->value) {
570 PROFILE_CopyEntry ( buffer,
571 key->value, len - 1, handle_env );
572 len -= strlen(buffer) + 1;
573 buffer += strlen(buffer) + 1;
578 /*If either lpszSection or lpszKey is NULL and the supplied
579 destination buffer is too small to hold all the strings,
580 the last string is truncated and followed by two null characters.
581 In this case, the return value is equal to cchReturnBuffer
589 section = section->next;
591 buffer[0] = buffer[1] = '\0';
596 /***********************************************************************
599 * Get a profile string.
601 static INT32 PROFILE_GetString( LPCSTR section, LPCSTR key_name,
602 LPCSTR def_val, LPSTR buffer, UINT32 len )
604 PROFILEKEY *key = NULL;
606 if (!def_val) def_val = "";
607 if (key_name && key_name[0])
609 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
610 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
612 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
613 section, key_name, def_val, buffer );
614 return strlen( buffer );
616 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
621 /***********************************************************************
624 * Set a profile string.
626 static BOOL32 PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
629 if (!key_name) /* Delete a whole section */
631 TRACE(profile, "('%s')\n", section_name);
632 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
634 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
635 this is not an error on application's level.*/
637 else if (!value) /* Delete a key */
639 TRACE(profile, "('%s','%s')\n",
640 section_name, key_name );
641 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
642 section_name, key_name );
643 return TRUE; /* same error handling as above */
645 else /* Set the key value */
647 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
649 TRACE(profile, "('%s','%s','%s'): \n",
650 section_name, key_name, value );
651 if (!key) return FALSE;
654 if (!strcmp( key->value, value ))
656 TRACE(profile, " no change needed\n" );
657 return TRUE; /* No change needed */
659 TRACE(profile, " replacing '%s'\n", key->value );
660 HeapFree( SystemHeap, 0, key->value );
662 else TRACE(profile, " creating key\n" );
663 key->value = HEAP_strdupA( SystemHeap, 0, value );
664 CurProfile->changed = TRUE;
670 /***********************************************************************
671 * PROFILE_GetWineIniString
673 * Get a config string from the wine.ini file.
675 int PROFILE_GetWineIniString( const char *section, const char *key_name,
676 const char *def, char *buffer, int len )
680 PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
681 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
683 TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
684 section, key_name, def, buffer );
685 return strlen( buffer );
687 return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE, FALSE );
691 /***********************************************************************
692 * PROFILE_GetWineIniInt
694 * Get a config integer from the wine.ini file.
696 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
702 PROFILEKEY *key = PROFILE_Find( &WineProfile, section, key_name, FALSE );
703 if (!key || !key->value) return def;
704 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
705 result = strtol( buffer, &p, 0 );
706 if (p == buffer) return 0; /* No digits at all */
711 /******************************************************************************
713 * int PROFILE_EnumerateWineIniSection(
714 * char const *section, #Name of the section to enumerate
715 * void (*cbfn)(char const *key, char const *value, void *user),
716 * # Address of the callback function
717 * void *user ) # User-specified pointer.
719 * For each entry in a section in the wine.conf file, this function will
720 * call the specified callback function, informing it of each key and
721 * value. An optional user pointer may be passed to it (if this is not
722 * needed, pass NULL through it and ignore the value in the callback
725 * The callback function must accept three parameters:
726 * The name of the key (char const *)
727 * The value of the key (char const *)
728 * A user-specified parameter (void *)
729 * Note that the first two are char CONST *'s, not char *'s! The callback
730 * MUST not modify these strings!
732 * The return value indicates the number of times the callback function
735 int PROFILE_EnumerateWineIniSection(
737 void (*cbfn)(char const *, char const *, void *),
740 PROFILESECTION *scansect;
744 /* Search for the correct section */
745 for(scansect = WineProfile; scansect; scansect = scansect->next) {
746 if(scansect->name && !strcasecmp(scansect->name, section)) {
748 /* Enumerate each key with the callback */
749 for(scankey = scansect->key; scankey; scankey = scankey->next) {
751 /* Ignore blank entries -- these shouldn't exist, but let's
753 if(scankey->name[0]) {
754 cbfn(scankey->name, scankey->value, userptr);
767 /******************************************************************************
769 * int PROFILE_GetWineIniBool(
770 * char const *section,
771 * char const *key_name,
774 * Reads a boolean value from the wine.ini file. This function attempts to
775 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
776 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
777 * true. Anything else results in the return of the default value.
779 * This function uses 1 to indicate true, and 0 for false. You can check
780 * for existence by setting def to something other than 0 or 1 and
781 * examining the return value.
783 int PROFILE_GetWineIniBool(
785 char const *key_name,
791 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
793 switch(key_value[0]) {
814 TRACE(profile, "(\"%s\", \"%s\", %s), "
815 "[%c], ret %s.\n", section, key_name,
816 def ? "TRUE" : "FALSE", key_value[0],
817 retval ? "TRUE" : "FALSE");
823 /***********************************************************************
824 * PROFILE_LoadWineIni
826 * Load the wine.ini file.
828 int PROFILE_LoadWineIni(void)
830 char buffer[MAX_PATHNAME_LEN];
834 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
836 /* Open -config specified file */
837 WineProfile = PROFILE_Load ( f);
839 strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);
843 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
845 WineProfile = PROFILE_Load( f );
847 strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);
850 if ((p = getenv( "HOME" )) != NULL)
852 lstrcpyn32A(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
853 strcat( buffer, PROFILE_WineIniName );
854 if ((f = fopen( buffer, "r" )) != NULL)
856 WineProfile = PROFILE_Load( f );
858 strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);
862 else WARN(profile, "could not get $HOME value for config file.\n" );
864 /* Try global file */
866 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
868 WineProfile = PROFILE_Load( f );
870 strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);
873 MSG( "Can't open configuration file %s or $HOME%s\n",
874 WINE_INI_GLOBAL, PROFILE_WineIniName );
879 /***********************************************************************
880 * PROFILE_UsageWineIni
882 * Explain the wine.ini file to those who don't read documentation.
883 * Keep below one screenful in length so that error messages above are
886 void PROFILE_UsageWineIni(void)
888 MSG("Perhaps you have not properly edited or created "
889 "your Wine configuration file.\n");
890 MSG("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
891 MSG(" or it is determined by the -config option or from\n"
892 " the WINE_INI environment variable.\n");
893 if (*PROFILE_WineIniUsed)
894 MSG("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
895 /* RTFM, so to say */
899 /***********************************************************************
900 * PROFILE_GetStringItem
902 * Convenience function that turns a string 'xxx, yyy, zzz' into
903 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
905 char* PROFILE_GetStringItem( char* start )
909 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
913 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
915 if( !PROFILE_isspace(*lpchX) ) return lpchX;
917 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
920 if( lpch ) *lpch = '\0';
925 /********************* API functions **********************************/
927 /***********************************************************************
928 * GetProfileInt16 (KERNEL.57)
930 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
932 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
936 /***********************************************************************
937 * GetProfileInt32A (KERNEL32.264)
939 UINT32 WINAPI GetProfileInt32A( LPCSTR section, LPCSTR entry, INT32 def_val )
941 return GetPrivateProfileInt32A( section, entry, def_val, "win.ini" );
944 /***********************************************************************
945 * GetProfileInt32W (KERNEL32.264)
947 UINT32 WINAPI GetProfileInt32W( LPCWSTR section, LPCWSTR entry, INT32 def_val )
949 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
950 return GetPrivateProfileInt32W( section, entry, def_val, wininiW );
953 /***********************************************************************
954 * GetProfileString16 (KERNEL.58)
956 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
957 LPSTR buffer, UINT16 len )
959 return GetPrivateProfileString16( section, entry, def_val,
960 buffer, len, "win.ini" );
963 /***********************************************************************
964 * GetProfileString32A (KERNEL32.268)
966 INT32 WINAPI GetProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR def_val,
967 LPSTR buffer, UINT32 len )
969 return GetPrivateProfileString32A( section, entry, def_val,
970 buffer, len, "win.ini" );
973 /***********************************************************************
974 * GetProfileString32W (KERNEL32.269)
976 INT32 WINAPI GetProfileString32W( LPCWSTR section, LPCWSTR entry,
977 LPCWSTR def_val, LPWSTR buffer, UINT32 len )
979 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
980 return GetPrivateProfileString32W( section, entry, def_val,
981 buffer, len, wininiW );
984 /***********************************************************************
985 * GetProfileSection32A (KERNEL32.268)
987 INT32 WINAPI GetProfileSection32A( LPCSTR section, LPSTR buffer, DWORD len )
989 return GetPrivateProfileSection32A( section, buffer, len, "win.ini" );
993 /***********************************************************************
994 * GetProfileSection32W (KERNEL32)
996 INT32 WINAPI GetProfileSection32W( LPCWSTR section, LPWSTR buffer, DWORD len )
998 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
999 return GetPrivateProfileSection32W( section, buffer, len, wininiW );
1006 /***********************************************************************
1007 * WriteProfileString16 (KERNEL.59)
1009 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
1012 return WritePrivateProfileString16( section, entry, string, "win.ini" );
1015 /***********************************************************************
1016 * WriteProfileString32A (KERNEL32.587)
1018 BOOL32 WINAPI WriteProfileString32A( LPCSTR section, LPCSTR entry,
1021 return WritePrivateProfileString32A( section, entry, string, "win.ini" );
1024 /***********************************************************************
1025 * WriteProfileString32W (KERNEL32.588)
1027 BOOL32 WINAPI WriteProfileString32W( LPCWSTR section, LPCWSTR entry,
1030 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1031 return WritePrivateProfileString32W( section, entry, string, wininiW );
1035 /***********************************************************************
1036 * GetPrivateProfileInt16 (KERNEL.127)
1038 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
1039 INT16 def_val, LPCSTR filename )
1041 long result=(long)GetPrivateProfileInt32A(section,entry,def_val,filename);
1043 if (result > 65535) return 65535;
1044 if (result >= 0) return (UINT16)result;
1045 if (result < -32768) return -32768;
1046 return (UINT16)(INT16)result;
1049 /***********************************************************************
1050 * GetPrivateProfileInt32A (KERNEL32.251)
1052 UINT32 WINAPI GetPrivateProfileInt32A( LPCSTR section, LPCSTR entry,
1053 INT32 def_val, LPCSTR filename )
1059 GetPrivateProfileString32A( section, entry, "",
1060 buffer, sizeof(buffer), filename );
1061 if (!buffer[0]) return (UINT32)def_val;
1062 result = strtol( buffer, &p, 0 );
1063 if (p == buffer) return 0; /* No digits at all */
1064 return (UINT32)result;
1067 /***********************************************************************
1068 * GetPrivateProfileInt32W (KERNEL32.252)
1070 UINT32 WINAPI GetPrivateProfileInt32W( LPCWSTR section, LPCWSTR entry,
1071 INT32 def_val, LPCWSTR filename )
1073 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1074 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1075 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1076 UINT32 res = GetPrivateProfileInt32A(sectionA, entryA, def_val, filenameA);
1077 HeapFree( GetProcessHeap(), 0, sectionA );
1078 HeapFree( GetProcessHeap(), 0, filenameA );
1079 HeapFree( GetProcessHeap(), 0, entryA );
1083 /***********************************************************************
1084 * GetPrivateProfileString16 (KERNEL.128)
1086 INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
1087 LPCSTR def_val, LPSTR buffer,
1088 UINT16 len, LPCSTR filename )
1090 return GetPrivateProfileString32A(section,entry,def_val,buffer,len,filename);
1093 /***********************************************************************
1094 * GetPrivateProfileString32A (KERNEL32.255)
1096 INT32 WINAPI GetPrivateProfileString32A( LPCSTR section, LPCSTR entry,
1097 LPCSTR def_val, LPSTR buffer,
1098 UINT32 len, LPCSTR filename )
1101 filename = "win.ini";
1102 if (PROFILE_Open( filename ))
1103 return PROFILE_GetString( section, entry, def_val, buffer, len );
1104 lstrcpyn32A( buffer, def_val, len );
1105 return strlen( buffer );
1108 /***********************************************************************
1109 * GetPrivateProfileString32W (KERNEL32.256)
1111 INT32 WINAPI GetPrivateProfileString32W( LPCWSTR section, LPCWSTR entry,
1112 LPCWSTR def_val, LPWSTR buffer,
1113 UINT32 len, LPCWSTR filename )
1115 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1116 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1117 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1118 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1119 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1120 INT32 ret = GetPrivateProfileString32A( sectionA, entryA, def_valA,
1121 bufferA, len, filenameA );
1122 lstrcpynAtoW( buffer, bufferA, len );
1123 HeapFree( GetProcessHeap(), 0, sectionA );
1124 HeapFree( GetProcessHeap(), 0, entryA );
1125 HeapFree( GetProcessHeap(), 0, filenameA );
1126 HeapFree( GetProcessHeap(), 0, def_valA );
1127 HeapFree( GetProcessHeap(), 0, bufferA);
1131 /***********************************************************************
1132 * GetPrivateProfileSection32A (KERNEL32.255)
1134 INT32 WINAPI GetPrivateProfileSection32A( LPCSTR section, LPSTR buffer,
1135 DWORD len, LPCSTR filename )
1137 if (PROFILE_Open( filename ))
1138 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
1144 /***********************************************************************
1145 * GetPrivateProfileSection32W (KERNEL32.256)
1148 INT32 WINAPI GetPrivateProfileSection32W (LPCWSTR section, LPWSTR buffer,
1149 DWORD len, LPCWSTR filename )
1152 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1153 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1154 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1155 INT32 ret = GetPrivateProfileSection32A( sectionA, bufferA, len,
1157 HeapFree( GetProcessHeap(), 0, sectionA );
1158 HeapFree( GetProcessHeap(), 0, filenameA );
1159 HeapFree( GetProcessHeap(), 0, bufferA);
1163 /***********************************************************************
1164 * WritePrivateProfileString16 (KERNEL.129)
1166 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
1167 LPCSTR string, LPCSTR filename )
1169 return WritePrivateProfileString32A(section,entry,string,filename);
1172 /***********************************************************************
1173 * WritePrivateProfileString32A (KERNEL32.582)
1175 BOOL32 WINAPI WritePrivateProfileString32A( LPCSTR section, LPCSTR entry,
1176 LPCSTR string, LPCSTR filename )
1178 if (!PROFILE_Open( filename )) return FALSE;
1179 if (!section) return PROFILE_FlushFile();
1180 return PROFILE_SetString( section, entry, string );
1183 /***********************************************************************
1184 * WritePrivateProfileString32W (KERNEL32.583)
1186 BOOL32 WINAPI WritePrivateProfileString32W( LPCWSTR section, LPCWSTR entry,
1187 LPCWSTR string, LPCWSTR filename )
1189 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1190 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1191 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1192 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1193 BOOL32 res = WritePrivateProfileString32A( sectionA, entryA,
1194 stringA, filenameA );
1195 HeapFree( GetProcessHeap(), 0, sectionA );
1196 HeapFree( GetProcessHeap(), 0, entryA );
1197 HeapFree( GetProcessHeap(), 0, stringA );
1198 HeapFree( GetProcessHeap(), 0, filenameA );
1202 /***********************************************************************
1203 * WritePrivateProfileSection32A (KERNEL32)
1205 BOOL32 WINAPI WritePrivateProfileSection32A( LPCSTR section,
1206 LPCSTR string, LPCSTR filename )
1208 char *p =(char*)string;
1210 FIXME(profile, "WritePrivateProfileSection32A empty stub\n");
1211 if (TRACE_ON(profile)) {
1212 TRACE(profile, "(%s) => [%s]\n", filename, section);
1214 TRACE(profile, "%s\n", p);
1223 /***********************************************************************
1224 * WritePrivateProfileSection32W (KERNEL32)
1226 BOOL32 WINAPI WritePrivateProfileSection32W( LPCWSTR section,
1227 LPCWSTR string, LPCWSTR filename)
1230 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1231 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1232 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1233 BOOL32 res = WritePrivateProfileSection32A( sectionA, stringA, filenameA );
1234 HeapFree( GetProcessHeap(), 0, sectionA );
1235 HeapFree( GetProcessHeap(), 0, stringA );
1236 HeapFree( GetProcessHeap(), 0, filenameA );
1241 /***********************************************************************
1242 * WriteProfileSection32A (KERNEL32.747)
1244 BOOL32 WINAPI WriteProfileSection32A( LPCSTR section, LPCSTR keys_n_values)
1247 return WritePrivateProfileSection32A( section, keys_n_values, "win.ini");
1250 /***********************************************************************
1251 * WriteProfileSection32W (KERNEL32.748)
1253 BOOL32 WINAPI WriteProfileSection32W( LPCWSTR section, LPCWSTR keys_n_values)
1255 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini");
1257 return (WritePrivateProfileSection32W (section,keys_n_values, wininiW));
1260 /***********************************************************************
1261 * GetPrivateProfileSectionNames16 (KERNEL.143)
1263 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1268 PROFILESECTION *section;
1270 if (PROFILE_Open( filename )) {
1273 section=CurProfile->section;
1274 for ( ; section; section = section->next)
1275 if (section->name) {
1276 l=strlen (section->name);
1278 if (cursize > size+1)
1280 strcpy (buf,section->name);
1287 return (buf-buffer);
1293 /***********************************************************************
1294 * GetProfileSectionNames16 (KERNEL.142)
1296 WORD WINAPI GetProfileSectionNames16( LPSTR buffer, WORD size)
1299 return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
1303 /***********************************************************************
1304 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1306 DWORD WINAPI GetPrivateProfileSectionNames32A( LPSTR buffer, DWORD size,
1310 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1314 /***********************************************************************
1315 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1317 DWORD WINAPI GetPrivateProfileSectionNames32W( LPWSTR buffer, DWORD size,
1321 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1322 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, size);
1324 INT32 ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1325 lstrcpynAtoW( buffer, bufferA, size);
1326 HeapFree( GetProcessHeap(), 0, bufferA);
1327 HeapFree( GetProcessHeap(), 0, filenameA );
1333 /***********************************************************************
1334 * GetPrivateProfileStruct32A (KERNEL32.370)
1336 BOOL32 WINAPI GetPrivateProfileStruct32A (LPCSTR section, LPCSTR key,
1337 LPVOID buf, UINT32 len, LPCSTR filename)
1341 if (PROFILE_Open( filename )) {
1342 k=PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1343 if (!k) return FALSE;
1344 lstrcpyn32A( buf, k->value, strlen(k->value));
1350 /***********************************************************************
1351 * GetPrivateProfileStruct32W (KERNEL32.543)
1353 BOOL32 WINAPI GetPrivateProfileStruct32W (LPCWSTR section, LPCWSTR key,
1354 LPVOID buffer, UINT32 len, LPCWSTR filename)
1356 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1357 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1358 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1359 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1361 INT32 ret = GetPrivateProfileStruct32A( sectionA, keyA, bufferA,
1363 lstrcpynAtoW( buffer, bufferA, len );
1364 HeapFree( GetProcessHeap(), 0, bufferA);
1365 HeapFree( GetProcessHeap(), 0, sectionA );
1366 HeapFree( GetProcessHeap(), 0, keyA );
1367 HeapFree( GetProcessHeap(), 0, filenameA );
1375 /***********************************************************************
1376 * WritePrivateProfileStruct32A (KERNEL32.744)
1378 BOOL32 WINAPI WritePrivateProfileStruct32A (LPCSTR section, LPCSTR key,
1379 LPVOID buf, UINT32 bufsize, LPCSTR filename)
1381 if ((!section) && (!key) && (!buf)) { /* flush the cache */
1382 PROFILE_FlushFile();
1386 if (!PROFILE_Open( filename )) return FALSE;
1387 return PROFILE_SetString( section, key, buf);
1390 /***********************************************************************
1391 * WritePrivateProfileStruct32W (KERNEL32.544)
1393 BOOL32 WINAPI WritePrivateProfileStruct32W (LPCWSTR section, LPCWSTR key,
1394 LPVOID buf, UINT32 bufsize, LPCWSTR filename)
1396 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1397 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1398 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1399 INT32 ret = WritePrivateProfileStruct32A( sectionA, keyA, buf, bufsize,
1401 HeapFree( GetProcessHeap(), 0, sectionA );
1402 HeapFree( GetProcessHeap(), 0, keyA );
1403 HeapFree( GetProcessHeap(), 0, filenameA );
1409 /***********************************************************************
1410 * WriteOutProfiles (KERNEL.315)
1412 void WINAPI WriteOutProfiles(void)
1414 PROFILE_FlushFile();