4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
13 #include <sys/types.h>
19 #include "wine/winbase16.h"
25 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(profile
);
31 typedef struct tagPROFILEKEY
35 struct tagPROFILEKEY
*next
;
38 typedef struct tagPROFILESECTION
41 struct tagPROFILEKEY
*key
;
42 struct tagPROFILESECTION
*next
;
49 PROFILESECTION
*section
;
57 #define N_CACHED_PROFILES 10
59 /* Cached profile files */
60 static PROFILE
*MRUProfile
[N_CACHED_PROFILES
]={NULL
};
62 #define CurProfile (MRUProfile[0])
64 /* wine.ini config file registry root */
65 static HKEY wine_profile_key
;
67 #define PROFILE_MAX_LINE_LEN 1024
69 /* Wine profile name in $HOME directory; must begin with slash */
70 static const char PROFILE_WineIniName
[] = "/.winerc";
72 /* Wine profile: the profile file being used */
73 static char PROFILE_WineIniUsed
[MAX_PATHNAME_LEN
] = "";
75 /* Check for comments in profile */
76 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
78 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
80 static const WCHAR wininiW
[] = { 'w','i','n','.','i','n','i',0 };
82 static CRITICAL_SECTION PROFILE_CritSect
= CRITICAL_SECTION_INIT
;
84 static const char hex
[16] = "0123456789ABCDEF";
86 /***********************************************************************
89 * Copy the content of an entry into a buffer, removing quotes, and possibly
90 * translating environment variables.
92 static void PROFILE_CopyEntry( char *buffer
, const char *value
, int len
,
98 if ((*value
== '\'') || (*value
== '\"'))
100 if (value
[1] && (value
[strlen(value
)-1] == *value
)) quote
= *value
++;
105 lstrcpynA( buffer
, value
, len
);
106 if (quote
&& (len
>= strlen(value
))) buffer
[strlen(buffer
)-1] = '\0';
110 for (p
= value
; (*p
&& (len
> 1)); *buffer
++ = *p
++, len
-- )
112 if ((*p
== '$') && (p
[1] == '{'))
116 const char *p2
= strchr( p
, '}' );
117 if (!p2
) continue; /* ignore it */
118 lstrcpynA(env_val
, p
+ 2, min( sizeof(env_val
), (int)(p2
-p
)-1 ));
119 if ((env_p
= getenv( env_val
)) != NULL
)
121 lstrcpynA( buffer
, env_p
, len
);
122 buffer
+= strlen( buffer
);
123 len
-= strlen( buffer
);
128 if (quote
&& (len
> 1)) buffer
--;
133 /***********************************************************************
136 * Save a profile tree to a file.
138 static void PROFILE_Save( FILE *file
, PROFILESECTION
*section
)
142 for ( ; section
; section
= section
->next
)
144 if (section
->name
) fprintf( file
, "\r\n[%s]\r\n", section
->name
);
145 for (key
= section
->key
; key
; key
= key
->next
)
147 fprintf( file
, "%s", key
->name
);
148 if (key
->value
) fprintf( file
, "=%s", key
->value
);
149 fprintf( file
, "\r\n" );
155 /***********************************************************************
158 * Free a profile tree.
160 static void PROFILE_Free( PROFILESECTION
*section
)
162 PROFILESECTION
*next_section
;
163 PROFILEKEY
*key
, *next_key
;
165 for ( ; section
; section
= next_section
)
167 if (section
->name
) HeapFree( GetProcessHeap(), 0, section
->name
);
168 for (key
= section
->key
; key
; key
= next_key
)
170 next_key
= key
->next
;
171 if (key
->name
) HeapFree( GetProcessHeap(), 0, key
->name
);
172 if (key
->value
) HeapFree( GetProcessHeap(), 0, key
->value
);
173 HeapFree( GetProcessHeap(), 0, key
);
175 next_section
= section
->next
;
176 HeapFree( GetProcessHeap(), 0, section
);
180 static inline int PROFILE_isspace(char c
)
182 if (isspace(c
)) return 1;
183 if (c
=='\r' || c
==0x1a) return 1;
184 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
189 /***********************************************************************
192 * Load a profile tree from a file.
194 static PROFILESECTION
*PROFILE_Load( FILE *file
)
196 char buffer
[PROFILE_MAX_LINE_LEN
];
199 PROFILESECTION
*section
, *first_section
;
200 PROFILESECTION
**next_section
;
201 PROFILEKEY
*key
, *prev_key
, **next_key
;
203 first_section
= HeapAlloc( GetProcessHeap(), 0, sizeof(*section
) );
204 if(first_section
== NULL
) return NULL
;
205 first_section
->name
= NULL
;
206 first_section
->key
= NULL
;
207 first_section
->next
= NULL
;
208 next_section
= &first_section
->next
;
209 next_key
= &first_section
->key
;
212 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
216 while (*p
&& PROFILE_isspace(*p
)) p
++;
217 if (*p
== '[') /* section start */
219 if (!(p2
= strrchr( p
, ']' )))
221 WARN("Invalid section header at line %d: '%s'\n",
228 section
= HeapAlloc( GetProcessHeap(), 0, sizeof(*section
) );
229 if(section
== NULL
) break;
230 section
->name
= HEAP_strdupA( GetProcessHeap(), 0, p
);
232 section
->next
= NULL
;
233 *next_section
= section
;
234 next_section
= §ion
->next
;
235 next_key
= §ion
->key
;
238 TRACE("New section: '%s'\n",section
->name
);
245 while ((p2
> p
) && ((*p2
== '\n') || PROFILE_isspace(*p2
))) *p2
--='\0';
247 if ((p2
= strchr( p
, '=' )) != NULL
)
250 while ((p3
> p
) && PROFILE_isspace(*p3
)) *p3
-- = '\0';
252 while (*p2
&& PROFILE_isspace(*p2
)) p2
++;
255 if(*p
|| !prev_key
|| *prev_key
->name
)
257 key
= HeapAlloc( GetProcessHeap(), 0, sizeof(*key
) );
258 if(key
== NULL
) break;
259 key
->name
= HEAP_strdupA( GetProcessHeap(), 0, p
);
260 key
->value
= p2
? HEAP_strdupA( GetProcessHeap(), 0, p2
) : NULL
;
263 next_key
= &key
->next
;
266 TRACE("New key: name='%s', value='%s'\n",key
->name
,key
->value
?key
->value
:"(none)");
269 return first_section
;
273 /***********************************************************************
274 * PROFILE_RegistryLoad
276 * Load a profile tree from a file into a registry key.
278 static DWORD
PROFILE_RegistryLoad( HKEY root
, FILE *file
)
282 char buffer
[PROFILE_MAX_LINE_LEN
];
286 while (fgets( buffer
, PROFILE_MAX_LINE_LEN
, file
))
290 while (*p
&& PROFILE_isspace(*p
)) p
++;
291 if (*p
== '[') /* section start */
293 if (!(p2
= strrchr( p
, ']' )))
295 WARN("Invalid section header at line %d: '%s'\n",
302 if (hkey
) RegCloseKey( hkey
);
303 if ((err
= RegCreateKeyExA( root
, p
, 0, NULL
, REG_OPTION_VOLATILE
,
304 KEY_ALL_ACCESS
, NULL
, &hkey
, NULL
))) return err
;
305 TRACE("New section: '%s'\n",p
);
311 while ((p2
> p
) && ((*p2
== '\n') || PROFILE_isspace(*p2
))) *p2
--='\0';
313 if ((p2
= strchr( p
, '=' )) != NULL
)
316 while ((p3
> p
) && PROFILE_isspace(*p3
)) *p3
-- = '\0';
318 while (*p2
&& PROFILE_isspace(*p2
)) p2
++;
321 if (*p
&& hkey
&& !IS_ENTRY_COMMENT(p
))
324 if ((err
= RegSetValueExA( hkey
, p
, 0, REG_SZ
, p2
, strlen(p2
)+1 )))
329 TRACE("New key: name='%s', value='%s'\n",p
,p2
);
332 if (hkey
) RegCloseKey( hkey
);
337 /***********************************************************************
338 * PROFILE_DeleteSection
340 * Delete a section from a profile tree.
342 static BOOL
PROFILE_DeleteSection( PROFILESECTION
**section
, LPCSTR name
)
346 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, name
))
348 PROFILESECTION
*to_del
= *section
;
349 *section
= to_del
->next
;
351 PROFILE_Free( to_del
);
354 section
= &(*section
)->next
;
360 /***********************************************************************
363 * Delete a key from a profile tree.
365 static BOOL
PROFILE_DeleteKey( PROFILESECTION
**section
,
366 LPCSTR section_name
, LPCSTR key_name
)
370 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
372 PROFILEKEY
**key
= &(*section
)->key
;
375 if (!strcasecmp( (*key
)->name
, key_name
))
377 PROFILEKEY
*to_del
= *key
;
379 if (to_del
->name
) HeapFree( GetProcessHeap(), 0, to_del
->name
);
380 if (to_del
->value
) HeapFree( GetProcessHeap(), 0, to_del
->value
);
381 HeapFree( GetProcessHeap(), 0, to_del
);
387 section
= &(*section
)->next
;
393 /***********************************************************************
394 * PROFILE_DeleteAllKeys
396 * Delete all keys from a profile tree.
398 void PROFILE_DeleteAllKeys( LPCSTR section_name
)
400 PROFILESECTION
**section
= &CurProfile
->section
;
403 if ((*section
)->name
&& !strcasecmp( (*section
)->name
, section_name
))
405 PROFILEKEY
**key
= &(*section
)->key
;
408 PROFILEKEY
*to_del
= *key
;
410 if (to_del
->name
) HeapFree( GetProcessHeap(), 0, to_del
->name
);
411 if (to_del
->value
) HeapFree( GetProcessHeap(), 0, to_del
->value
);
412 HeapFree( GetProcessHeap(), 0, to_del
);
413 CurProfile
->changed
=TRUE
;
416 section
= &(*section
)->next
;
421 /***********************************************************************
424 * Find a key in a profile tree, optionally creating it.
426 static PROFILEKEY
*PROFILE_Find( PROFILESECTION
**section
,
427 const char *section_name
,
428 const char *key_name
, int create
)
433 while (PROFILE_isspace(*section_name
)) section_name
++;
434 p
= section_name
+ strlen(section_name
) - 1;
435 while ((p
> section_name
) && PROFILE_isspace(*p
)) p
--;
436 seclen
= p
- section_name
+ 1;
438 while (PROFILE_isspace(*key_name
)) key_name
++;
439 p
= key_name
+ strlen(key_name
) - 1;
440 while ((p
> key_name
) && PROFILE_isspace(*p
)) p
--;
441 keylen
= p
- key_name
+ 1;
445 if ( ((*section
)->name
)
446 && (!(strncasecmp( (*section
)->name
, section_name
, seclen
)))
447 && (((*section
)->name
)[seclen
] == '\0') )
449 PROFILEKEY
**key
= &(*section
)->key
;
452 if ( (!(strncasecmp( (*key
)->name
, key_name
, keylen
)))
453 && (((*key
)->name
)[keylen
] == '\0') )
457 if (!create
) return NULL
;
458 *key
= HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILEKEY
) );
459 if(*key
== NULL
) return NULL
;
460 (*key
)->name
= HEAP_strdupA( GetProcessHeap(), 0, key_name
);
461 (*key
)->value
= NULL
;
465 section
= &(*section
)->next
;
467 if (!create
) return NULL
;
468 *section
= HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILESECTION
) );
469 if(*section
== NULL
) return NULL
;
470 (*section
)->name
= HEAP_strdupA( GetProcessHeap(), 0, section_name
);
471 (*section
)->next
= NULL
;
472 (*section
)->key
= HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILEKEY
) );
473 if((*section
)->key
== NULL
)
475 HeapFree(GetProcessHeap(), 0, *section
);
478 (*section
)->key
->name
= HEAP_strdupA( GetProcessHeap(), 0, key_name
);
479 (*section
)->key
->value
= NULL
;
480 (*section
)->key
->next
= NULL
;
481 return (*section
)->key
;
485 /***********************************************************************
488 * Flush the current profile to disk if changed.
490 static BOOL
PROFILE_FlushFile(void)
492 char *p
, buffer
[MAX_PATHNAME_LEN
];
493 const char *unix_name
;
499 WARN("No current profile!\n");
503 if (!CurProfile
->changed
|| !CurProfile
->dos_name
) return TRUE
;
504 if (!(unix_name
= CurProfile
->unix_name
) || !(file
= fopen(unix_name
, "w")))
506 /* Try to create it in $HOME/.wine */
507 /* FIXME: this will need a more general solution */
508 strcpy( buffer
, get_config_dir() );
509 p
= buffer
+ strlen(buffer
);
511 strcpy( p
, strrchr( CurProfile
->dos_name
, '\\' ) + 1 );
513 file
= fopen( buffer
, "w" );
519 WARN("could not save profile file %s\n", CurProfile
->dos_name
);
523 TRACE("Saving '%s' into '%s'\n", CurProfile
->dos_name
, unix_name
);
524 PROFILE_Save( file
, CurProfile
->section
);
526 CurProfile
->changed
= FALSE
;
527 if(!stat(unix_name
,&buf
))
528 CurProfile
->mtime
=buf
.st_mtime
;
533 /***********************************************************************
534 * PROFILE_ReleaseFile
536 * Flush the current profile to disk and remove it from the cache.
538 static void PROFILE_ReleaseFile(void)
541 PROFILE_Free( CurProfile
->section
);
542 if (CurProfile
->dos_name
) HeapFree( GetProcessHeap(), 0, CurProfile
->dos_name
);
543 if (CurProfile
->unix_name
) HeapFree( GetProcessHeap(), 0, CurProfile
->unix_name
);
544 if (CurProfile
->filename
) HeapFree( GetProcessHeap(), 0, CurProfile
->filename
);
545 CurProfile
->changed
= FALSE
;
546 CurProfile
->section
= NULL
;
547 CurProfile
->dos_name
= NULL
;
548 CurProfile
->unix_name
= NULL
;
549 CurProfile
->filename
= NULL
;
550 CurProfile
->mtime
= 0;
554 /***********************************************************************
557 * Open a profile file, checking the cached file first.
559 static BOOL
PROFILE_Open( LPCSTR filename
)
561 DOS_FULL_NAME full_name
;
562 char buffer
[MAX_PATHNAME_LEN
];
563 char *newdos_name
, *p
;
567 PROFILE
*tempProfile
;
569 /* First time around */
572 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
574 MRUProfile
[i
]=HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILE
) );
575 if(MRUProfile
[i
] == NULL
) break;
576 MRUProfile
[i
]->changed
=FALSE
;
577 MRUProfile
[i
]->section
=NULL
;
578 MRUProfile
[i
]->dos_name
=NULL
;
579 MRUProfile
[i
]->unix_name
=NULL
;
580 MRUProfile
[i
]->filename
=NULL
;
581 MRUProfile
[i
]->mtime
=0;
584 /* Check for a match */
586 if (strchr( filename
, '/' ) || strchr( filename
, '\\' ) ||
587 strchr( filename
, ':' ))
589 if (!DOSFS_GetFullName( filename
, FALSE
, &full_name
)) return FALSE
;
593 GetWindowsDirectoryA( buffer
, sizeof(buffer
) );
594 strcat( buffer
, "\\" );
595 strcat( buffer
, filename
);
596 if (!DOSFS_GetFullName( buffer
, FALSE
, &full_name
)) return FALSE
;
599 for(i
=0;i
<N_CACHED_PROFILES
;i
++)
601 if ((MRUProfile
[i
]->filename
&& !strcmp( filename
, MRUProfile
[i
]->filename
)) ||
602 (MRUProfile
[i
]->dos_name
&& !strcmp( full_name
.short_name
, MRUProfile
[i
]->dos_name
)))
607 tempProfile
=MRUProfile
[i
];
609 MRUProfile
[j
]=MRUProfile
[j
-1];
610 CurProfile
=tempProfile
;
612 if(!stat(CurProfile
->unix_name
,&buf
) && CurProfile
->mtime
==buf
.st_mtime
)
613 TRACE("(%s): already opened (mru=%d)\n",
616 TRACE("(%s): already opened, needs refreshing (mru=%d)\n",
622 /* Flush the old current profile */
625 /* Make the oldest profile the current one only in order to get rid of it */
626 if(i
==N_CACHED_PROFILES
)
628 tempProfile
=MRUProfile
[N_CACHED_PROFILES
-1];
629 for(i
=N_CACHED_PROFILES
-1;i
>0;i
--)
630 MRUProfile
[i
]=MRUProfile
[i
-1];
631 CurProfile
=tempProfile
;
633 if(CurProfile
->filename
) PROFILE_ReleaseFile();
635 /* OK, now that CurProfile is definitely free we assign it our new file */
636 newdos_name
= HEAP_strdupA( GetProcessHeap(), 0, full_name
.short_name
);
637 CurProfile
->dos_name
= newdos_name
;
638 CurProfile
->filename
= HEAP_strdupA( GetProcessHeap(), 0, filename
);
640 /* Try to open the profile file, first in $HOME/.wine */
642 /* FIXME: this will need a more general solution */
643 strcpy( buffer
, get_config_dir() );
644 p
= buffer
+ strlen(buffer
);
646 strcpy( p
, strrchr( newdos_name
, '\\' ) + 1 );
648 if ((file
= fopen( buffer
, "r" )))
650 TRACE("(%s): found it in %s\n",
652 CurProfile
->unix_name
= HEAP_strdupA( GetProcessHeap(), 0, buffer
);
657 CurProfile
->unix_name
= HEAP_strdupA( GetProcessHeap(), 0,
658 full_name
.long_name
);
659 if ((file
= fopen( full_name
.long_name
, "r" )))
660 TRACE("(%s): found it in %s\n",
661 filename
, full_name
.long_name
);
666 CurProfile
->section
= PROFILE_Load( file
);
668 if(!stat(CurProfile
->unix_name
,&buf
))
669 CurProfile
->mtime
=buf
.st_mtime
;
673 /* Does not exist yet, we will create it in PROFILE_FlushFile */
674 WARN("profile file %s not found\n", newdos_name
);
680 /***********************************************************************
683 * Returns all keys of a section.
684 * If return_values is TRUE, also include the corresponding values.
686 static INT
PROFILE_GetSection( PROFILESECTION
*section
, LPCSTR section_name
,
687 LPSTR buffer
, UINT len
, BOOL handle_env
,
693 if (section
->name
&& !strcasecmp( section
->name
, section_name
))
696 for (key
= section
->key
; key
; key
= key
->next
)
699 if (!*key
->name
) continue; /* Skip empty lines */
700 if (IS_ENTRY_COMMENT(key
->name
)) continue; /* Skip comments */
701 PROFILE_CopyEntry( buffer
, key
->name
, len
- 1, handle_env
);
702 len
-= strlen(buffer
) + 1;
703 buffer
+= strlen(buffer
) + 1;
704 if (return_values
&& key
->value
) {
706 PROFILE_CopyEntry ( buffer
,
707 key
->value
, len
- 1, handle_env
);
708 len
-= strlen(buffer
) + 1;
709 buffer
+= strlen(buffer
) + 1;
714 /*If either lpszSection or lpszKey is NULL and the supplied
715 destination buffer is too small to hold all the strings,
716 the last string is truncated and followed by two null characters.
717 In this case, the return value is equal to cchReturnBuffer
725 section
= section
->next
;
727 buffer
[0] = buffer
[1] = '\0';
732 static INT
PROFILE_GetSectionNames( LPSTR buffer
, UINT len
)
736 PROFILESECTION
*section
;
738 for (section
= CurProfile
->section
; section
; section
= section
->next
)
740 l
= strlen(section
->name
);
745 strcpy(buf
, section
->name
);
755 /***********************************************************************
758 * Get a profile string.
760 static INT
PROFILE_GetString( LPCSTR section
, LPCSTR key_name
,
761 LPCSTR def_val
, LPSTR buffer
, UINT len
)
763 PROFILEKEY
*key
= NULL
;
765 if (!def_val
) def_val
= "";
766 if (key_name
&& key_name
[0])
768 key
= PROFILE_Find( &CurProfile
->section
, section
, key_name
, FALSE
);
769 PROFILE_CopyEntry( buffer
, (key
&& key
->value
) ? key
->value
: def_val
,
771 TRACE("('%s','%s','%s'): returning '%s'\n",
772 section
, key_name
, def_val
, buffer
);
773 return strlen( buffer
);
775 if (key_name
&& !(key_name
[0]))
776 /* Win95 returns 0 on keyname "". Tested with Likse32 bon 000227*/
778 if (section
&& section
[0])
779 return PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
781 /* undocumented; both section and key_name are NULL */
782 return PROFILE_GetSectionNames(buffer
, len
);
786 /***********************************************************************
789 * Set a profile string.
791 static BOOL
PROFILE_SetString( LPCSTR section_name
, LPCSTR key_name
,
794 if (!key_name
) /* Delete a whole section */
796 TRACE("('%s')\n", section_name
);
797 CurProfile
->changed
|= PROFILE_DeleteSection( &CurProfile
->section
,
799 return TRUE
; /* Even if PROFILE_DeleteSection() has failed,
800 this is not an error on application's level.*/
802 else if (!value
) /* Delete a key */
804 TRACE("('%s','%s')\n",
805 section_name
, key_name
);
806 CurProfile
->changed
|= PROFILE_DeleteKey( &CurProfile
->section
,
807 section_name
, key_name
);
808 return TRUE
; /* same error handling as above */
810 else /* Set the key value */
812 PROFILEKEY
*key
= PROFILE_Find( &CurProfile
->section
, section_name
,
814 TRACE("('%s','%s','%s'): \n",
815 section_name
, key_name
, value
);
816 if (!key
) return FALSE
;
819 /* strip the leading spaces. We can safely strip \n\r and
820 * friends too, they should not happen here anyway. */
821 while (PROFILE_isspace(*value
)) value
++;
823 if (!strcmp( key
->value
, value
))
825 TRACE(" no change needed\n" );
826 return TRUE
; /* No change needed */
828 TRACE(" replacing '%s'\n", key
->value
);
829 HeapFree( GetProcessHeap(), 0, key
->value
);
831 else TRACE(" creating key\n" );
832 key
->value
= HEAP_strdupA( GetProcessHeap(), 0, value
);
833 CurProfile
->changed
= TRUE
;
839 /***********************************************************************
840 * PROFILE_GetWineIniString
842 * Get a config string from the wine.ini file.
844 int PROFILE_GetWineIniString( const char *section
, const char *key_name
,
845 const char *def
, char *buffer
, int len
)
847 char tmp
[PROFILE_MAX_LINE_LEN
];
851 if (!(err
= RegOpenKeyA( wine_profile_key
, section
, &hkey
)))
854 DWORD count
= sizeof(tmp
);
855 err
= RegQueryValueExA( hkey
, key_name
, 0, &type
, tmp
, &count
);
858 PROFILE_CopyEntry( buffer
, err
? def
: tmp
, len
, TRUE
);
859 TRACE( "('%s','%s','%s'): returning '%s'\n", section
, key_name
, def
, buffer
);
860 return strlen(buffer
);
864 /***********************************************************************
865 * PROFILE_EnumWineIniString
867 * Get a config string from the wine.ini file.
869 BOOL
PROFILE_EnumWineIniString( const char *section
, int index
,
870 char *name
, int name_len
, char *buffer
, int len
)
872 char tmp
[PROFILE_MAX_LINE_LEN
];
875 DWORD count
= sizeof(tmp
);
877 if (RegOpenKeyA( wine_profile_key
, section
, &hkey
)) return FALSE
;
878 err
= RegEnumValueA( hkey
, index
, name
, (DWORD
*)&name_len
, NULL
, &type
, tmp
, &count
);
882 PROFILE_CopyEntry( buffer
, tmp
, len
, TRUE
);
883 TRACE( "('%s',%d): returning '%s'='%s'\n", section
, index
, name
, buffer
);
889 /***********************************************************************
890 * PROFILE_GetWineIniInt
892 * Get a config integer from the wine.ini file.
894 int PROFILE_GetWineIniInt( const char *section
, const char *key_name
, int def
)
900 PROFILE_GetWineIniString( section
, key_name
, "", buffer
, sizeof(buffer
) );
901 if (!buffer
[0]) return def
;
902 result
= strtol( buffer
, &p
, 0 );
903 return (p
== buffer
) ? 0 /* No digits at all */ : (int)result
;
907 /******************************************************************************
909 * int PROFILE_GetWineIniBool(
910 * char const *section,
911 * char const *key_name,
914 * Reads a boolean value from the wine.ini file. This function attempts to
915 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
916 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
917 * true. Anything else results in the return of the default value.
919 * This function uses 1 to indicate true, and 0 for false. You can check
920 * for existence by setting def to something other than 0 or 1 and
921 * examining the return value.
923 int PROFILE_GetWineIniBool(
925 char const *key_name
,
931 PROFILE_GetWineIniString(section
, key_name
, "~", key_value
, 2);
933 switch(key_value
[0]) {
954 TRACE("(\"%s\", \"%s\", %s), "
955 "[%c], ret %s.\n", section
, key_name
,
956 def
? "TRUE" : "FALSE", key_value
[0],
957 retval
? "TRUE" : "FALSE");
963 /***********************************************************************
964 * PROFILE_LoadWineIni
966 * Load the wine.ini file.
968 int PROFILE_LoadWineIni(void)
970 char buffer
[MAX_PATHNAME_LEN
];
975 /* make sure HKLM\\Software\\Wine\\Wine exists as non-volatile key */
976 if (RegCreateKeyA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine", &hKeySW
))
978 ERR("Cannot create config registry key\n" );
981 RegCloseKey( hKeySW
);
982 if (RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config", 0, NULL
,
983 REG_OPTION_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &wine_profile_key
, NULL
))
985 ERR("Cannot create config registry key\n" );
989 if (!CLIENT_IsBootThread()) return 1; /* already loaded */
991 if ( (Options
.configFileName
!=NULL
) && (f
= fopen(Options
.configFileName
, "r")) )
993 /* Open -config specified file */
994 lstrcpynA(PROFILE_WineIniUsed
,Options
.configFileName
,MAX_PATHNAME_LEN
);
998 if ( (p
= getenv( "WINE_INI" )) && (f
= fopen( p
, "r" )) )
1000 lstrcpynA(PROFILE_WineIniUsed
,p
,MAX_PATHNAME_LEN
);
1003 if ((p
= getenv( "HOME" )) != NULL
)
1005 lstrcpynA(buffer
, p
, MAX_PATHNAME_LEN
- sizeof(PROFILE_WineIniName
));
1006 strcat( buffer
, PROFILE_WineIniName
);
1007 if ((f
= fopen( buffer
, "r" )) != NULL
)
1009 lstrcpynA(PROFILE_WineIniUsed
,buffer
,MAX_PATHNAME_LEN
);
1013 else WARN("could not get $HOME value for config file.\n" );
1015 /* Try global file */
1017 if ((f
= fopen( WINE_INI_GLOBAL
, "r" )) != NULL
)
1019 lstrcpynA(PROFILE_WineIniUsed
,WINE_INI_GLOBAL
,MAX_PATHNAME_LEN
);
1022 MESSAGE( "Can't open configuration file %s or $HOME%s\n",
1023 WINE_INI_GLOBAL
, PROFILE_WineIniName
);
1027 PROFILE_RegistryLoad( wine_profile_key
, f
);
1033 /***********************************************************************
1034 * PROFILE_UsageWineIni
1036 * Explain the wine.ini file to those who don't read documentation.
1037 * Keep below one screenful in length so that error messages above are
1040 void PROFILE_UsageWineIni(void)
1042 MESSAGE("Perhaps you have not properly edited or created "
1043 "your Wine configuration file.\n");
1044 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL
,PROFILE_WineIniName
);
1045 MESSAGE(" or it is determined by the -config option or from\n"
1046 " the WINE_INI environment variable.\n");
1047 if (*PROFILE_WineIniUsed
)
1048 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed
);
1049 /* RTFM, so to say */
1052 /***********************************************************************
1053 * PROFILE_GetStringItem
1055 * Convenience function that turns a string 'xxx, yyy, zzz' into
1056 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
1058 char* PROFILE_GetStringItem( char* start
)
1062 for (lpchX
= start
, lpch
= NULL
; *lpchX
!= '\0'; lpchX
++ )
1066 if( lpch
) *lpch
= '\0'; else *lpchX
= '\0';
1068 if( !PROFILE_isspace(*lpchX
) ) return lpchX
;
1070 else if( PROFILE_isspace( *lpchX
) && !lpch
) lpch
= lpchX
;
1073 if( lpch
) *lpch
= '\0';
1077 /********************* API functions **********************************/
1079 /***********************************************************************
1080 * GetProfileInt16 (KERNEL.57)
1082 UINT16 WINAPI
GetProfileInt16( LPCSTR section
, LPCSTR entry
, INT16 def_val
)
1084 return GetPrivateProfileInt16( section
, entry
, def_val
, "win.ini" );
1088 /***********************************************************************
1089 * GetProfileIntA (KERNEL32.264)
1091 UINT WINAPI
GetProfileIntA( LPCSTR section
, LPCSTR entry
, INT def_val
)
1093 return GetPrivateProfileIntA( section
, entry
, def_val
, "win.ini" );
1096 /***********************************************************************
1097 * GetProfileIntW (KERNEL32.264)
1099 UINT WINAPI
GetProfileIntW( LPCWSTR section
, LPCWSTR entry
, INT def_val
)
1101 return GetPrivateProfileIntW( section
, entry
, def_val
, wininiW
);
1104 /***********************************************************************
1105 * GetProfileString16 (KERNEL.58)
1107 INT16 WINAPI
GetProfileString16( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1108 LPSTR buffer
, UINT16 len
)
1110 return GetPrivateProfileString16( section
, entry
, def_val
,
1111 buffer
, len
, "win.ini" );
1114 /***********************************************************************
1115 * GetProfileStringA (KERNEL32.268)
1117 INT WINAPI
GetProfileStringA( LPCSTR section
, LPCSTR entry
, LPCSTR def_val
,
1118 LPSTR buffer
, UINT len
)
1120 return GetPrivateProfileStringA( section
, entry
, def_val
,
1121 buffer
, len
, "win.ini" );
1124 /***********************************************************************
1125 * GetProfileStringW (KERNEL32.269)
1127 INT WINAPI
GetProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1128 LPCWSTR def_val
, LPWSTR buffer
, UINT len
)
1130 return GetPrivateProfileStringW( section
, entry
, def_val
,
1131 buffer
, len
, wininiW
);
1134 /***********************************************************************
1135 * WriteProfileString16 (KERNEL.59)
1137 BOOL16 WINAPI
WriteProfileString16( LPCSTR section
, LPCSTR entry
,
1140 return WritePrivateProfileString16( section
, entry
, string
, "win.ini" );
1143 /***********************************************************************
1144 * WriteProfileStringA (KERNEL32.587)
1146 BOOL WINAPI
WriteProfileStringA( LPCSTR section
, LPCSTR entry
,
1149 return WritePrivateProfileStringA( section
, entry
, string
, "win.ini" );
1152 /***********************************************************************
1153 * WriteProfileStringW (KERNEL32.588)
1155 BOOL WINAPI
WriteProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1158 return WritePrivateProfileStringW( section
, entry
, string
, wininiW
);
1162 /***********************************************************************
1163 * GetPrivateProfileInt16 (KERNEL.127)
1165 UINT16 WINAPI
GetPrivateProfileInt16( LPCSTR section
, LPCSTR entry
,
1166 INT16 def_val
, LPCSTR filename
)
1168 long result
=(long)GetPrivateProfileIntA(section
,entry
,def_val
,filename
);
1170 if (result
> 65535) return 65535;
1171 if (result
>= 0) return (UINT16
)result
;
1172 if (result
< -32768) return -32768;
1173 return (UINT16
)(INT16
)result
;
1176 /***********************************************************************
1177 * GetPrivateProfileIntA (KERNEL32.251)
1179 UINT WINAPI
GetPrivateProfileIntA( LPCSTR section
, LPCSTR entry
,
1180 INT def_val
, LPCSTR filename
)
1186 GetPrivateProfileStringA( section
, entry
, "",
1187 buffer
, sizeof(buffer
), filename
);
1188 if (!buffer
[0]) return (UINT
)def_val
;
1189 result
= strtol( buffer
, &p
, 0 );
1190 if (p
== buffer
) return 0; /* No digits at all */
1191 return (UINT
)result
;
1194 /***********************************************************************
1195 * GetPrivateProfileIntW (KERNEL32.252)
1197 UINT WINAPI
GetPrivateProfileIntW( LPCWSTR section
, LPCWSTR entry
,
1198 INT def_val
, LPCWSTR filename
)
1200 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1201 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1202 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1203 UINT res
= GetPrivateProfileIntA(sectionA
, entryA
, def_val
, filenameA
);
1204 HeapFree( GetProcessHeap(), 0, sectionA
);
1205 HeapFree( GetProcessHeap(), 0, filenameA
);
1206 HeapFree( GetProcessHeap(), 0, entryA
);
1210 /***********************************************************************
1211 * GetPrivateProfileString16 (KERNEL.128)
1213 INT16 WINAPI
GetPrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1214 LPCSTR def_val
, LPSTR buffer
,
1215 UINT16 len
, LPCSTR filename
)
1217 return GetPrivateProfileStringA(section
,entry
,def_val
,buffer
,len
,filename
);
1220 /***********************************************************************
1221 * GetPrivateProfileStringA (KERNEL32.255)
1223 INT WINAPI
GetPrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1224 LPCSTR def_val
, LPSTR buffer
,
1225 UINT len
, LPCSTR filename
)
1230 filename
= "win.ini";
1232 EnterCriticalSection( &PROFILE_CritSect
);
1234 if (PROFILE_Open( filename
)) {
1235 ret
= PROFILE_GetString( section
, entry
, def_val
, buffer
, len
);
1237 lstrcpynA( buffer
, def_val
, len
);
1238 ret
= strlen( buffer
);
1241 LeaveCriticalSection( &PROFILE_CritSect
);
1246 /***********************************************************************
1247 * GetPrivateProfileStringW (KERNEL32.256)
1249 INT WINAPI
GetPrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1250 LPCWSTR def_val
, LPWSTR buffer
,
1251 UINT len
, LPCWSTR filename
)
1253 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1254 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1255 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1256 LPSTR def_valA
= HEAP_strdupWtoA( GetProcessHeap(), 0, def_val
);
1257 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1258 INT ret
= GetPrivateProfileStringA( sectionA
, entryA
, def_valA
,
1259 bufferA
, len
, filenameA
);
1260 lstrcpynAtoW( buffer
, bufferA
, len
);
1261 HeapFree( GetProcessHeap(), 0, sectionA
);
1262 HeapFree( GetProcessHeap(), 0, entryA
);
1263 HeapFree( GetProcessHeap(), 0, filenameA
);
1264 HeapFree( GetProcessHeap(), 0, def_valA
);
1265 HeapFree( GetProcessHeap(), 0, bufferA
);
1269 /***********************************************************************
1270 * GetPrivateProfileSection16 (KERNEL.418)
1272 INT16 WINAPI
GetPrivateProfileSection16( LPCSTR section
, LPSTR buffer
,
1273 UINT16 len
, LPCSTR filename
)
1275 return GetPrivateProfileSectionA( section
, buffer
, len
, filename
);
1278 /***********************************************************************
1279 * GetPrivateProfileSectionA (KERNEL32.255)
1281 INT WINAPI
GetPrivateProfileSectionA( LPCSTR section
, LPSTR buffer
,
1282 DWORD len
, LPCSTR filename
)
1286 EnterCriticalSection( &PROFILE_CritSect
);
1288 if (PROFILE_Open( filename
))
1289 ret
= PROFILE_GetSection(CurProfile
->section
, section
, buffer
, len
,
1292 LeaveCriticalSection( &PROFILE_CritSect
);
1297 /***********************************************************************
1298 * GetPrivateProfileSectionW (KERNEL32.256)
1301 INT WINAPI
GetPrivateProfileSectionW (LPCWSTR section
, LPWSTR buffer
,
1302 DWORD len
, LPCWSTR filename
)
1305 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1306 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1307 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1308 INT ret
= GetPrivateProfileSectionA( sectionA
, bufferA
, len
,
1310 MultiByteToWideChar(CP_ACP
,0,bufferA
,ret
,buffer
,len
);
1311 HeapFree( GetProcessHeap(), 0, sectionA
);
1312 HeapFree( GetProcessHeap(), 0, filenameA
);
1313 HeapFree( GetProcessHeap(), 0, bufferA
);
1317 /***********************************************************************
1318 * GetProfileSection16 (KERNEL.419)
1320 INT16 WINAPI
GetProfileSection16( LPCSTR section
, LPSTR buffer
, UINT16 len
)
1322 return GetPrivateProfileSection16( section
, buffer
, len
, "win.ini" );
1325 /***********************************************************************
1326 * GetProfileSectionA (KERNEL32.268)
1328 INT WINAPI
GetProfileSectionA( LPCSTR section
, LPSTR buffer
, DWORD len
)
1330 return GetPrivateProfileSectionA( section
, buffer
, len
, "win.ini" );
1333 /***********************************************************************
1334 * GetProfileSectionW (KERNEL32)
1336 INT WINAPI
GetProfileSectionW( LPCWSTR section
, LPWSTR buffer
, DWORD len
)
1338 return GetPrivateProfileSectionW( section
, buffer
, len
, wininiW
);
1342 /***********************************************************************
1343 * WritePrivateProfileString16 (KERNEL.129)
1345 BOOL16 WINAPI
WritePrivateProfileString16( LPCSTR section
, LPCSTR entry
,
1346 LPCSTR string
, LPCSTR filename
)
1348 return WritePrivateProfileStringA(section
,entry
,string
,filename
);
1351 /***********************************************************************
1352 * WritePrivateProfileStringA (KERNEL32.582)
1354 BOOL WINAPI
WritePrivateProfileStringA( LPCSTR section
, LPCSTR entry
,
1355 LPCSTR string
, LPCSTR filename
)
1359 EnterCriticalSection( &PROFILE_CritSect
);
1361 if (PROFILE_Open( filename
))
1363 if (!section
&& !entry
&& !string
)
1364 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1366 ret
= PROFILE_SetString( section
, entry
, string
);
1369 LeaveCriticalSection( &PROFILE_CritSect
);
1373 /***********************************************************************
1374 * WritePrivateProfileStringW (KERNEL32.583)
1376 BOOL WINAPI
WritePrivateProfileStringW( LPCWSTR section
, LPCWSTR entry
,
1377 LPCWSTR string
, LPCWSTR filename
)
1379 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1380 LPSTR entryA
= HEAP_strdupWtoA( GetProcessHeap(), 0, entry
);
1381 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1382 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1383 BOOL res
= WritePrivateProfileStringA( sectionA
, entryA
,
1384 stringA
, filenameA
);
1385 HeapFree( GetProcessHeap(), 0, sectionA
);
1386 HeapFree( GetProcessHeap(), 0, entryA
);
1387 HeapFree( GetProcessHeap(), 0, stringA
);
1388 HeapFree( GetProcessHeap(), 0, filenameA
);
1392 /***********************************************************************
1393 * WritePrivateProfileSection16 (KERNEL.416)
1395 BOOL16 WINAPI
WritePrivateProfileSection16( LPCSTR section
,
1396 LPCSTR string
, LPCSTR filename
)
1398 return WritePrivateProfileSectionA( section
, string
, filename
);
1401 /***********************************************************************
1402 * WritePrivateProfileSectionA (KERNEL32)
1404 BOOL WINAPI
WritePrivateProfileSectionA( LPCSTR section
,
1405 LPCSTR string
, LPCSTR filename
)
1410 EnterCriticalSection( &PROFILE_CritSect
);
1412 if (PROFILE_Open( filename
)) {
1413 if (!section
&& !string
&& !filename
)
1414 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1415 else if (!string
) /* delete the named section*/
1416 ret
= PROFILE_SetString(section
,NULL
,NULL
);
1418 PROFILE_DeleteAllKeys(section
);
1421 LPSTR buf
=HEAP_strdupA( GetProcessHeap(), 0, string
);
1422 if((p
=strchr( buf
, '='))){
1424 ret
= PROFILE_SetString( section
, buf
, p
+1 );
1427 HeapFree( GetProcessHeap(), 0, buf
);
1428 string
+= strlen(string
)+1;
1434 LeaveCriticalSection( &PROFILE_CritSect
);
1438 /***********************************************************************
1439 * WritePrivateProfileSectionW (KERNEL32)
1441 BOOL WINAPI
WritePrivateProfileSectionW( LPCWSTR section
,
1442 LPCWSTR string
, LPCWSTR filename
)
1445 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1446 LPSTR stringA
= HEAP_strdupWtoA( GetProcessHeap(), 0, string
);
1447 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1448 BOOL res
= WritePrivateProfileSectionA( sectionA
, stringA
, filenameA
);
1449 HeapFree( GetProcessHeap(), 0, sectionA
);
1450 HeapFree( GetProcessHeap(), 0, stringA
);
1451 HeapFree( GetProcessHeap(), 0, filenameA
);
1455 /***********************************************************************
1456 * WriteProfileSection16 (KERNEL.417)
1458 BOOL16 WINAPI
WriteProfileSection16( LPCSTR section
, LPCSTR keys_n_values
)
1460 return WritePrivateProfileSection16( section
, keys_n_values
, "win.ini");
1463 /***********************************************************************
1464 * WriteProfileSectionA (KERNEL32.747)
1466 BOOL WINAPI
WriteProfileSectionA( LPCSTR section
, LPCSTR keys_n_values
)
1469 return WritePrivateProfileSectionA( section
, keys_n_values
, "win.ini");
1472 /***********************************************************************
1473 * WriteProfileSectionW (KERNEL32.748)
1475 BOOL WINAPI
WriteProfileSectionW( LPCWSTR section
, LPCWSTR keys_n_values
)
1477 return (WritePrivateProfileSectionW (section
,keys_n_values
, wininiW
));
1480 /***********************************************************************
1481 * GetPrivateProfileSectionNames16 (KERNEL.143)
1483 WORD WINAPI
GetPrivateProfileSectionNames16( LPSTR buffer
, WORD size
,
1488 EnterCriticalSection( &PROFILE_CritSect
);
1490 if (PROFILE_Open( filename
))
1491 ret
= PROFILE_GetSectionNames(buffer
, size
);
1493 LeaveCriticalSection( &PROFILE_CritSect
);
1499 /***********************************************************************
1500 * GetProfileSectionNames16 (KERNEL.142)
1502 WORD WINAPI
GetProfileSectionNames16( LPSTR buffer
, WORD size
)
1505 return (GetPrivateProfileSectionNames16 (buffer
,size
,"win.ini"));
1509 /***********************************************************************
1510 * GetPrivateProfileSectionNamesA (KERNEL32.365)
1512 DWORD WINAPI
GetPrivateProfileSectionNamesA( LPSTR buffer
, DWORD size
,
1516 return (GetPrivateProfileSectionNames16 (buffer
,size
,filename
));
1520 /***********************************************************************
1521 * GetPrivateProfileSectionNamesW (KERNEL32.366)
1523 DWORD WINAPI
GetPrivateProfileSectionNamesW( LPWSTR buffer
, DWORD size
,
1527 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1528 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, size
);
1530 INT ret
= GetPrivateProfileSectionNames16 (bufferA
, size
, filenameA
);
1531 lstrcpynAtoW( buffer
, bufferA
, size
);
1532 HeapFree( GetProcessHeap(), 0, bufferA
);
1533 HeapFree( GetProcessHeap(), 0, filenameA
);
1538 /***********************************************************************
1539 * GetPrivateProfileStruct16 (KERNEL.407)
1541 BOOL16 WINAPI
GetPrivateProfileStruct16(LPCSTR section
, LPCSTR key
,
1542 LPVOID buf
, UINT16 len
, LPCSTR filename
)
1544 return GetPrivateProfileStructA( section
, key
, buf
, len
, filename
);
1547 /***********************************************************************
1548 * GetPrivateProfileStructA (KERNEL32.370)
1550 * Should match Win95's behaviour pretty much
1552 BOOL WINAPI
GetPrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1553 LPVOID buf
, UINT len
, LPCSTR filename
)
1557 EnterCriticalSection( &PROFILE_CritSect
);
1559 if (PROFILE_Open( filename
)) {
1560 PROFILEKEY
*k
= PROFILE_Find ( &CurProfile
->section
, section
, key
, FALSE
);
1562 TRACE("value (at %p): '%s'\n", k
->value
, k
->value
);
1563 if (((strlen(k
->value
) - 2) / 2) == len
)
1570 end
= k
->value
+ strlen(k
->value
); /* -> '\0' */
1571 /* check for invalid chars in ASCII coded hex string */
1572 for (p
=k
->value
; p
< end
; p
++)
1576 WARN("invalid char '%c' in file '%s'->'[%s]'->'%s' !\n",
1577 *p
, filename
, section
, key
);
1584 BOOL highnibble
= TRUE
;
1586 LPBYTE binbuf
= (LPBYTE
)buf
;
1588 end
-= 2; /* don't include checksum in output data */
1589 /* translate ASCII hex format into binary data */
1590 for (p
=k
->value
; p
< end
; p
++)
1594 (c
- 'A' + 10) : (c
- '0');
1601 *binbuf
++ = b
; /* feed binary data into output */
1602 chksum
+= b
; /* calculate checksum */
1604 highnibble
^= 1; /* toggle */
1606 /* retrieve stored checksum value */
1608 b
= ( (c
> '9') ? (c
- 'A' + 10) : (c
- '0') ) << 4;
1610 b
+= (c
> '9') ? (c
- 'A' + 10) : (c
- '0');
1611 if (b
== (chksum
& 0xff)) /* checksums match ? */
1617 LeaveCriticalSection( &PROFILE_CritSect
);
1622 /***********************************************************************
1623 * GetPrivateProfileStructW (KERNEL32.543)
1625 BOOL WINAPI
GetPrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1626 LPVOID buffer
, UINT len
, LPCWSTR filename
)
1628 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1629 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1630 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1631 LPSTR bufferA
= HeapAlloc( GetProcessHeap(), 0, len
);
1633 INT ret
= GetPrivateProfileStructA( sectionA
, keyA
, bufferA
,
1635 lstrcpynAtoW( buffer
, bufferA
, len
);
1636 HeapFree( GetProcessHeap(), 0, bufferA
);
1637 HeapFree( GetProcessHeap(), 0, sectionA
);
1638 HeapFree( GetProcessHeap(), 0, keyA
);
1639 HeapFree( GetProcessHeap(), 0, filenameA
);
1646 /***********************************************************************
1647 * WritePrivateProfileStruct16 (KERNEL.406)
1649 BOOL16 WINAPI
WritePrivateProfileStruct16 (LPCSTR section
, LPCSTR key
,
1650 LPVOID buf
, UINT16 bufsize
, LPCSTR filename
)
1652 return WritePrivateProfileStructA( section
, key
, buf
, bufsize
, filename
);
1655 /***********************************************************************
1656 * WritePrivateProfileStructA (KERNEL32.744)
1658 BOOL WINAPI
WritePrivateProfileStructA (LPCSTR section
, LPCSTR key
,
1659 LPVOID buf
, UINT bufsize
, LPCSTR filename
)
1666 if (!section
&& !key
&& !buf
) /* flush the cache */
1667 return WritePrivateProfileStringA( NULL
, NULL
, NULL
, filename
);
1669 /* allocate string buffer for hex chars + checksum hex char + '\0' */
1670 outstring
= HeapAlloc( GetProcessHeap(), 0, bufsize
*2 + 2 + 1);
1672 for (binbuf
= (LPBYTE
)buf
; binbuf
< (LPBYTE
)buf
+bufsize
; binbuf
++) {
1673 *p
++ = hex
[*binbuf
>> 4];
1674 *p
++ = hex
[*binbuf
& 0xf];
1677 /* checksum is sum & 0xff */
1678 *p
++ = hex
[(sum
& 0xf0) >> 4];
1679 *p
++ = hex
[sum
& 0xf];
1682 EnterCriticalSection( &PROFILE_CritSect
);
1684 if (PROFILE_Open( filename
))
1685 ret
= PROFILE_SetString( section
, key
, outstring
);
1687 LeaveCriticalSection( &PROFILE_CritSect
);
1689 HeapFree( GetProcessHeap(), 0, outstring
);
1694 /***********************************************************************
1695 * WritePrivateProfileStructW (KERNEL32.544)
1697 BOOL WINAPI
WritePrivateProfileStructW (LPCWSTR section
, LPCWSTR key
,
1698 LPVOID buf
, UINT bufsize
, LPCWSTR filename
)
1700 LPSTR sectionA
= HEAP_strdupWtoA( GetProcessHeap(), 0, section
);
1701 LPSTR keyA
= HEAP_strdupWtoA( GetProcessHeap(), 0, key
);
1702 LPSTR filenameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
1703 INT ret
= WritePrivateProfileStructA( sectionA
, keyA
, buf
, bufsize
,
1705 HeapFree( GetProcessHeap(), 0, sectionA
);
1706 HeapFree( GetProcessHeap(), 0, keyA
);
1707 HeapFree( GetProcessHeap(), 0, filenameA
);
1713 /***********************************************************************
1714 * WriteOutProfiles (KERNEL.315)
1716 void WINAPI
WriteOutProfiles16(void)
1718 EnterCriticalSection( &PROFILE_CritSect
);
1719 PROFILE_FlushFile();
1720 LeaveCriticalSection( &PROFILE_CritSect
);
1723 /***********************************************************************
1724 * CloseProfileUserMapping (KERNEL.138)
1726 BOOL WINAPI
CloseProfileUserMapping(void) {
1727 FIXME("(), stub!\n");
1728 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);