blob: 9448832a0909ac8b8c6ce07cc469a07af5b6594c [file] [log] [blame]
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001/*
2 * Profile functions
3 *
4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
6 */
7
8#include <ctype.h>
Alexandre Julliard02ed4c21996-03-02 19:34:10 +00009#include <stdlib.h>
Alexandre Julliard7e56f681996-01-31 19:02:28 +000010#include <string.h>
Jeremy Whited3e22d92000-02-10 19:03:02 +000011#include <stdio.h>
Alexandre Julliard829fe321998-07-26 14:27:39 +000012#include <sys/stat.h>
Alexandre Julliard647876e2000-01-25 01:35:01 +000013#include <sys/types.h>
14#include <pwd.h>
15#include <unistd.h>
Alexandre Julliard829fe321998-07-26 14:27:39 +000016
Marcus Meissner317af321999-02-17 13:51:06 +000017#include "winbase.h"
Marcus Meissner9b4fcf71999-12-04 04:19:55 +000018#include "winerror.h"
Marcus Meissner317af321999-02-17 13:51:06 +000019#include "wine/winbase16.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000020#include "windef.h"
21#include "wingdi.h"
Marcus Meissner317af321999-02-17 13:51:06 +000022#include "winuser.h"
Marcus Meissner264360f1999-05-08 10:02:05 +000023#include "winnls.h"
Alexandre Julliard00377a72000-02-19 20:50:00 +000024#include "winreg.h"
Alexandre Julliardc6c09441997-01-12 18:32:19 +000025#include "file.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000026#include "heap.h"
Alexandre Julliard359f497e1999-07-04 16:02:24 +000027#include "debugtools.h"
Alexandre Julliard647876e2000-01-25 01:35:01 +000028#include "xmalloc.h"
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000029#include "options.h"
Alexandre Julliard00377a72000-02-19 20:50:00 +000030#include "server.h"
Alexandre Julliard7e56f681996-01-31 19:02:28 +000031
Jeremy Whited3e22d92000-02-10 19:03:02 +000032DEFAULT_DEBUG_CHANNEL(profile);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000033
Alexandre Julliard7e56f681996-01-31 19:02:28 +000034typedef struct tagPROFILEKEY
35{
36 char *name;
37 char *value;
38 struct tagPROFILEKEY *next;
39} PROFILEKEY;
40
41typedef struct tagPROFILESECTION
42{
43 char *name;
44 struct tagPROFILEKEY *key;
45 struct tagPROFILESECTION *next;
46} PROFILESECTION;
47
48
49typedef struct
50{
Eric Poueched155751999-03-25 13:24:08 +000051 BOOL changed;
Alexandre Julliard7e56f681996-01-31 19:02:28 +000052 PROFILESECTION *section;
53 char *dos_name;
Alexandre Julliardc6c09441997-01-12 18:32:19 +000054 char *unix_name;
55 char *filename;
Alexandre Julliard829fe321998-07-26 14:27:39 +000056 time_t mtime;
Alexandre Julliard7e56f681996-01-31 19:02:28 +000057} PROFILE;
58
59
Alexandre Julliard829fe321998-07-26 14:27:39 +000060#define N_CACHED_PROFILES 10
61
62/* Cached profile files */
63static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
64
65#define CurProfile (MRUProfile[0])
Alexandre Julliard7e56f681996-01-31 19:02:28 +000066
Alexandre Julliard00377a72000-02-19 20:50:00 +000067/* wine.ini config file registry root */
68static HKEY wine_profile_key;
Alexandre Julliard7e56f681996-01-31 19:02:28 +000069
70#define PROFILE_MAX_LINE_LEN 1024
71
72/* Wine profile name in $HOME directory; must begin with slash */
73static const char PROFILE_WineIniName[] = "/.winerc";
74
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000075/* Wine profile: the profile file being used */
76static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
77
Alexandre Julliard7e56f681996-01-31 19:02:28 +000078/* Check for comments in profile */
79#define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
80
Alexandre Julliard18f92e71996-07-17 20:02:21 +000081#define WINE_INI_GLOBAL ETCDIR "/wine.conf"
Alexandre Julliard647876e2000-01-25 01:35:01 +000082#define WINE_CONFIG_DIR "/.wine" /* config dir inside $HOME */
Alexandre Julliard7e56f681996-01-31 19:02:28 +000083
Alexandre Julliard00377a72000-02-19 20:50:00 +000084static const WCHAR wininiW[] = { 'w','i','n','.','i','n','i',0 };
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000085
Eric Poueched155751999-03-25 13:24:08 +000086static CRITICAL_SECTION PROFILE_CritSect;
87
Andreas Mohr17b1f462000-01-30 21:15:14 +000088static const char hex[16] = "0123456789ABCDEF";
Alexandre Julliard647876e2000-01-25 01:35:01 +000089
90/***********************************************************************
91 * PROFILE_GetConfigDir
92 *
93 * Return the name of the configuration directory ($HOME/.wine)
94 */
95const char *PROFILE_GetConfigDir(void)
96{
97 static char *confdir;
98 if (!confdir)
99 {
100 const char *home = getenv( "HOME" );
101 if (!home)
102 {
103 struct passwd *pwd = getpwuid( getuid() );
104 if (!pwd)
105 {
106 fprintf( stderr, "wine: could not find your home directory\n" );
107 exit(1);
108 }
109 home = pwd->pw_dir;
110 }
111 confdir = xmalloc( strlen(home) + strlen(WINE_CONFIG_DIR) + 1 );
112 strcpy( confdir, home );
113 strcat( confdir, WINE_CONFIG_DIR );
114 mkdir( confdir, 0755 ); /* create it just in case */
115 }
116 return confdir;
117}
118
119
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000120/***********************************************************************
121 * PROFILE_CopyEntry
122 *
123 * Copy the content of an entry into a buffer, removing quotes, and possibly
124 * translating environment variables.
125 */
126static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
127 int handle_env )
128{
129 char quote = '\0';
130 const char *p;
131
132 if ((*value == '\'') || (*value == '\"'))
133 {
134 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
135 }
136
137 if (!handle_env)
138 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000139 lstrcpynA( buffer, value, len );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000140 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
141 return;
142 }
143
144 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
145 {
146 if ((*p == '$') && (p[1] == '{'))
147 {
148 char env_val[1024];
149 const char *env_p;
150 const char *p2 = strchr( p, '}' );
151 if (!p2) continue; /* ignore it */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000152 lstrcpynA(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000153 if ((env_p = getenv( env_val )) != NULL)
154 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000155 lstrcpynA( buffer, env_p, len );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000156 buffer += strlen( buffer );
157 len -= strlen( buffer );
158 }
159 p = p2 + 1;
160 }
161 }
Eric Pouechf54c95f1999-10-31 17:32:57 +0000162 if (quote && (len > 1)) buffer--;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000163 *buffer = '\0';
164}
165
166
167/***********************************************************************
168 * PROFILE_Save
169 *
170 * Save a profile tree to a file.
171 */
172static void PROFILE_Save( FILE *file, PROFILESECTION *section )
173{
174 PROFILEKEY *key;
175
176 for ( ; section; section = section->next)
177 {
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000178 if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000179 for (key = section->key; key; key = key->next)
180 {
181 fprintf( file, "%s", key->name );
182 if (key->value) fprintf( file, "=%s", key->value );
Alexandre Julliard7d654eb1996-02-25 11:36:22 +0000183 fprintf( file, "\r\n" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000184 }
185 }
186}
187
188
189/***********************************************************************
190 * PROFILE_Free
191 *
192 * Free a profile tree.
193 */
194static void PROFILE_Free( PROFILESECTION *section )
195{
196 PROFILESECTION *next_section;
197 PROFILEKEY *key, *next_key;
198
199 for ( ; section; section = next_section)
200 {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000201 if (section->name) HeapFree( GetProcessHeap(), 0, section->name );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000202 for (key = section->key; key; key = next_key)
203 {
204 next_key = key->next;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000205 if (key->name) HeapFree( GetProcessHeap(), 0, key->name );
206 if (key->value) HeapFree( GetProcessHeap(), 0, key->value );
207 HeapFree( GetProcessHeap(), 0, key );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000208 }
209 next_section = section->next;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000210 HeapFree( GetProcessHeap(), 0, section );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000211 }
212}
213
Andreas Mohr17b1f462000-01-30 21:15:14 +0000214static inline int PROFILE_isspace(char c)
215{
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000216 if (isspace(c)) return 1;
217 if (c=='\r' || c==0x1a) return 1;
218 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
219 return 0;
220}
221
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000222
223/***********************************************************************
224 * PROFILE_Load
225 *
226 * Load a profile tree from a file.
227 */
228static PROFILESECTION *PROFILE_Load( FILE *file )
229{
230 char buffer[PROFILE_MAX_LINE_LEN];
231 char *p, *p2;
232 int line = 0;
233 PROFILESECTION *section, *first_section;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000234 PROFILESECTION **next_section;
235 PROFILEKEY *key, *prev_key, **next_key;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000236
Alexandre Julliard90476d62000-02-16 22:47:24 +0000237 first_section = HEAP_xalloc( GetProcessHeap(), 0, sizeof(*section) );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000238 first_section->name = NULL;
239 first_section->key = NULL;
240 first_section->next = NULL;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000241 next_section = &first_section->next;
242 next_key = &first_section->key;
243 prev_key = NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000244
245 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
246 {
247 line++;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000248 p = buffer;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000249 while (*p && PROFILE_isspace(*p)) p++;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000250 if (*p == '[') /* section start */
251 {
252 if (!(p2 = strrchr( p, ']' )))
253 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000254 WARN("Invalid section header at line %d: '%s'\n",
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000255 line, p );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000256 }
257 else
258 {
259 *p2 = '\0';
260 p++;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000261 section = HEAP_xalloc( GetProcessHeap(), 0, sizeof(*section) );
262 section->name = HEAP_strdupA( GetProcessHeap(), 0, p );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000263 section->key = NULL;
264 section->next = NULL;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000265 *next_section = section;
266 next_section = &section->next;
267 next_key = &section->key;
268 prev_key = NULL;
Alexandre Julliard829fe321998-07-26 14:27:39 +0000269
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000270 TRACE("New section: '%s'\n",section->name);
Alexandre Julliard829fe321998-07-26 14:27:39 +0000271
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000272 continue;
273 }
274 }
Alexandre Julliard829fe321998-07-26 14:27:39 +0000275
276 p2=p+strlen(p) - 1;
277 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
278
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000279 if ((p2 = strchr( p, '=' )) != NULL)
280 {
281 char *p3 = p2 - 1;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000282 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000283 *p2++ = '\0';
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000284 while (*p2 && PROFILE_isspace(*p2)) p2++;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000285 }
Alexandre Julliard642d3131998-07-12 19:29:36 +0000286
287 if(*p || !prev_key || *prev_key->name)
288 {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000289 key = HEAP_xalloc( GetProcessHeap(), 0, sizeof(*key) );
290 key->name = HEAP_strdupA( GetProcessHeap(), 0, p );
291 key->value = p2 ? HEAP_strdupA( GetProcessHeap(), 0, p2 ) : NULL;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000292 key->next = NULL;
293 *next_key = key;
294 next_key = &key->next;
295 prev_key = key;
296
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000297 TRACE("New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)");
Alexandre Julliard642d3131998-07-12 19:29:36 +0000298 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000299 }
300 return first_section;
301}
302
303
304/***********************************************************************
Alexandre Julliard00377a72000-02-19 20:50:00 +0000305 * PROFILE_RegistryLoad
306 *
307 * Load a profile tree from a file into a registry key.
308 */
309static DWORD PROFILE_RegistryLoad( HKEY root, FILE *file )
310{
311 HKEY hkey = 0;
312 DWORD err = 0;
313 char buffer[PROFILE_MAX_LINE_LEN];
314 char *p, *p2;
315 int line = 0;
316
317 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
318 {
319 line++;
320 p = buffer;
321 while (*p && PROFILE_isspace(*p)) p++;
322 if (*p == '[') /* section start */
323 {
324 if (!(p2 = strrchr( p, ']' )))
325 {
326 WARN("Invalid section header at line %d: '%s'\n",
327 line, p );
328 }
329 else
330 {
331 *p2 = '\0';
332 p++;
333 if (hkey) RegCloseKey( hkey );
334 if ((err = RegCreateKeyExA( root, p, 0, NULL, REG_OPTION_VOLATILE,
335 KEY_ALL_ACCESS, NULL, &hkey, NULL ))) return err;
336 TRACE("New section: '%s'\n",p);
337 continue;
338 }
339 }
340
341 p2=p+strlen(p) - 1;
342 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
343
344 if ((p2 = strchr( p, '=' )) != NULL)
345 {
346 char *p3 = p2 - 1;
347 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
348 *p2++ = '\0';
349 while (*p2 && PROFILE_isspace(*p2)) p2++;
350 }
351
352 if (*p && hkey && !IS_ENTRY_COMMENT(p))
353 {
354 if (!p2) p2 = "";
355 if ((err = RegSetValueExA( hkey, p, 0, REG_SZ, p2, strlen(p2)+1 )))
356 {
357 RegCloseKey( hkey );
358 return err;
359 }
360 TRACE("New key: name='%s', value='%s'\n",p,p2);
361 }
362 }
363 if (hkey) RegCloseKey( hkey );
364 return 0;
365}
366
367
368/***********************************************************************
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000369 * PROFILE_DeleteSection
370 *
371 * Delete a section from a profile tree.
372 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000373static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000374{
375 while (*section)
376 {
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000377 if ((*section)->name && !strcasecmp( (*section)->name, name ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000378 {
379 PROFILESECTION *to_del = *section;
380 *section = to_del->next;
381 to_del->next = NULL;
382 PROFILE_Free( to_del );
383 return TRUE;
384 }
385 section = &(*section)->next;
386 }
387 return FALSE;
388}
389
390
391/***********************************************************************
392 * PROFILE_DeleteKey
393 *
394 * Delete a key from a profile tree.
395 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000396static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
Eric Poueched155751999-03-25 13:24:08 +0000397 LPCSTR section_name, LPCSTR key_name )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000398{
399 while (*section)
400 {
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000401 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000402 {
403 PROFILEKEY **key = &(*section)->key;
404 while (*key)
405 {
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000406 if (!strcasecmp( (*key)->name, key_name ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000407 {
408 PROFILEKEY *to_del = *key;
409 *key = to_del->next;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000410 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 );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000413 return TRUE;
414 }
415 key = &(*key)->next;
416 }
417 }
418 section = &(*section)->next;
419 }
420 return FALSE;
421}
422
423
424/***********************************************************************
425 * PROFILE_Find
426 *
427 * Find a key in a profile tree, optionally creating it.
428 */
429static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
430 const char *section_name,
431 const char *key_name, int create )
432{
Andreas Mohr17b1f462000-01-30 21:15:14 +0000433 const char *p;
434 int seclen, keylen;
435
436 while (PROFILE_isspace(*section_name)) section_name++;
437 p = section_name + strlen(section_name) - 1;
438 while ((p > section_name) && PROFILE_isspace(*p)) p--;
439 seclen = p - section_name + 1;
440
441 while (PROFILE_isspace(*key_name)) key_name++;
442 p = key_name + strlen(key_name) - 1;
443 while ((p > key_name) && PROFILE_isspace(*p)) p--;
444 keylen = p - key_name + 1;
445
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000446 while (*section)
447 {
Andreas Mohr17b1f462000-01-30 21:15:14 +0000448 if ( ((*section)->name)
449 && (!(strncasecmp( (*section)->name, section_name, seclen )))
450 && (((*section)->name)[seclen] == '\0') )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000451 {
452 PROFILEKEY **key = &(*section)->key;
453 while (*key)
454 {
Andreas Mohr17b1f462000-01-30 21:15:14 +0000455 if ( (!(strncasecmp( (*key)->name, key_name, keylen )))
456 && (((*key)->name)[keylen] == '\0') )
457 return *key;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000458 key = &(*key)->next;
459 }
460 if (!create) return NULL;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000461 *key = HEAP_xalloc( GetProcessHeap(), 0, sizeof(PROFILEKEY) );
462 (*key)->name = HEAP_strdupA( GetProcessHeap(), 0, key_name );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000463 (*key)->value = NULL;
464 (*key)->next = NULL;
465 return *key;
466 }
467 section = &(*section)->next;
468 }
469 if (!create) return NULL;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000470 *section = HEAP_xalloc( GetProcessHeap(), 0, sizeof(PROFILESECTION) );
471 (*section)->name = HEAP_strdupA( GetProcessHeap(), 0, section_name );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000472 (*section)->next = NULL;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000473 (*section)->key = HEAP_xalloc( GetProcessHeap(), 0, sizeof(PROFILEKEY) );
474 (*section)->key->name = HEAP_strdupA( GetProcessHeap(), 0, key_name );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000475 (*section)->key->value = NULL;
476 (*section)->key->next = NULL;
477 return (*section)->key;
478}
479
480
481/***********************************************************************
482 * PROFILE_FlushFile
483 *
484 * Flush the current profile to disk if changed.
485 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000486static BOOL PROFILE_FlushFile(void)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000487{
488 char *p, buffer[MAX_PATHNAME_LEN];
489 const char *unix_name;
490 FILE *file = NULL;
Alexandre Julliard829fe321998-07-26 14:27:39 +0000491 struct stat buf;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000492
Alexandre Julliard829fe321998-07-26 14:27:39 +0000493 if(!CurProfile)
494 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000495 WARN("No current profile!\n");
Alexandre Julliard829fe321998-07-26 14:27:39 +0000496 return FALSE;
497 }
498
499 if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
500 if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000501 {
502 /* Try to create it in $HOME/.wine */
503 /* FIXME: this will need a more general solution */
Alexandre Julliard647876e2000-01-25 01:35:01 +0000504 strcpy( buffer, PROFILE_GetConfigDir() );
505 p = buffer + strlen(buffer);
506 *p++ = '/';
507 strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
508 CharLowerA( p );
509 file = fopen( buffer, "w" );
510 unix_name = buffer;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000511 }
512
513 if (!file)
514 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000515 WARN("could not save profile file %s\n", CurProfile->dos_name);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000516 return FALSE;
517 }
518
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000519 TRACE("Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name );
Alexandre Julliard829fe321998-07-26 14:27:39 +0000520 PROFILE_Save( file, CurProfile->section );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000521 fclose( file );
Alexandre Julliard829fe321998-07-26 14:27:39 +0000522 CurProfile->changed = FALSE;
523 if(!stat(unix_name,&buf))
524 CurProfile->mtime=buf.st_mtime;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000525 return TRUE;
526}
527
528
529/***********************************************************************
Alexandre Julliarde61b7921999-07-31 19:24:11 +0000530 * PROFILE_ReleaseFile
531 *
532 * Flush the current profile to disk and remove it from the cache.
533 */
534static void PROFILE_ReleaseFile(void)
535{
536 PROFILE_FlushFile();
537 PROFILE_Free( CurProfile->section );
Alexandre Julliard90476d62000-02-16 22:47:24 +0000538 if (CurProfile->dos_name) HeapFree( GetProcessHeap(), 0, CurProfile->dos_name );
539 if (CurProfile->unix_name) HeapFree( GetProcessHeap(), 0, CurProfile->unix_name );
540 if (CurProfile->filename) HeapFree( GetProcessHeap(), 0, CurProfile->filename );
Alexandre Julliarde61b7921999-07-31 19:24:11 +0000541 CurProfile->changed = FALSE;
542 CurProfile->section = NULL;
543 CurProfile->dos_name = NULL;
544 CurProfile->unix_name = NULL;
545 CurProfile->filename = NULL;
546 CurProfile->mtime = 0;
547}
548
549
550/***********************************************************************
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000551 * PROFILE_Open
552 *
553 * Open a profile file, checking the cached file first.
554 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000555static BOOL PROFILE_Open( LPCSTR filename )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000556{
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000557 DOS_FULL_NAME full_name;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000558 char buffer[MAX_PATHNAME_LEN];
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000559 char *newdos_name, *p;
560 FILE *file = NULL;
Alexandre Julliard829fe321998-07-26 14:27:39 +0000561 int i,j;
562 struct stat buf;
563 PROFILE *tempProfile;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000564
Alexandre Julliard829fe321998-07-26 14:27:39 +0000565 /* First time around */
566
567 if(!CurProfile)
568 for(i=0;i<N_CACHED_PROFILES;i++)
569 {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000570 MRUProfile[i]=HEAP_xalloc( GetProcessHeap(), 0, sizeof(PROFILE) );
Alexandre Julliard829fe321998-07-26 14:27:39 +0000571 MRUProfile[i]->changed=FALSE;
572 MRUProfile[i]->section=NULL;
573 MRUProfile[i]->dos_name=NULL;
574 MRUProfile[i]->unix_name=NULL;
575 MRUProfile[i]->filename=NULL;
576 MRUProfile[i]->mtime=0;
577 }
578
579 /* Check for a match */
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000580
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000581 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
582 strchr( filename, ':' ))
583 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000584 if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000585 }
586 else
587 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000588 GetWindowsDirectoryA( buffer, sizeof(buffer) );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000589 strcat( buffer, "\\" );
590 strcat( buffer, filename );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000591 if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000592 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000593
Alexandre Julliard829fe321998-07-26 14:27:39 +0000594 for(i=0;i<N_CACHED_PROFILES;i++)
595 {
596 if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )) ||
597 (MRUProfile[i]->dos_name && !strcmp( full_name.short_name, MRUProfile[i]->dos_name )))
598 {
599 if(i)
600 {
601 PROFILE_FlushFile();
602 tempProfile=MRUProfile[i];
603 for(j=i;j>0;j--)
604 MRUProfile[j]=MRUProfile[j-1];
605 CurProfile=tempProfile;
606 }
607 if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000608 TRACE("(%s): already opened (mru=%d)\n",
Alexandre Julliard829fe321998-07-26 14:27:39 +0000609 filename, i );
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000610 else
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000611 TRACE("(%s): already opened, needs refreshing (mru=%d)\n",
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000612 filename, i );
613 return TRUE;
Alexandre Julliard829fe321998-07-26 14:27:39 +0000614 }
615 }
616
Andreas Mohr87bff281999-11-21 02:03:03 +0000617 /* Flush the old current profile */
618 PROFILE_FlushFile();
Alexandre Julliard829fe321998-07-26 14:27:39 +0000619
Andreas Mohr87bff281999-11-21 02:03:03 +0000620 /* Make the oldest profile the current one only in order to get rid of it */
Alexandre Julliard829fe321998-07-26 14:27:39 +0000621 if(i==N_CACHED_PROFILES)
622 {
623 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
624 for(i=N_CACHED_PROFILES-1;i>0;i--)
625 MRUProfile[i]=MRUProfile[i-1];
626 CurProfile=tempProfile;
627 }
Alexandre Julliarde61b7921999-07-31 19:24:11 +0000628 if(CurProfile->filename) PROFILE_ReleaseFile();
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000629
Andreas Mohr87bff281999-11-21 02:03:03 +0000630 /* OK, now that CurProfile is definitely free we assign it our new file */
Alexandre Julliard90476d62000-02-16 22:47:24 +0000631 newdos_name = HEAP_strdupA( GetProcessHeap(), 0, full_name.short_name );
Alexandre Julliard829fe321998-07-26 14:27:39 +0000632 CurProfile->dos_name = newdos_name;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000633 CurProfile->filename = HEAP_strdupA( GetProcessHeap(), 0, filename );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000634
635 /* Try to open the profile file, first in $HOME/.wine */
636
637 /* FIXME: this will need a more general solution */
Alexandre Julliard647876e2000-01-25 01:35:01 +0000638 strcpy( buffer, PROFILE_GetConfigDir() );
639 p = buffer + strlen(buffer);
640 *p++ = '/';
641 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
642 CharLowerA( p );
643 if ((file = fopen( buffer, "r" )))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000644 {
Alexandre Julliard647876e2000-01-25 01:35:01 +0000645 TRACE("(%s): found it in %s\n",
646 filename, buffer );
Alexandre Julliard90476d62000-02-16 22:47:24 +0000647 CurProfile->unix_name = HEAP_strdupA( GetProcessHeap(), 0, buffer );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000648 }
649
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000650 if (!file)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000651 {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000652 CurProfile->unix_name = HEAP_strdupA( GetProcessHeap(), 0,
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000653 full_name.long_name );
654 if ((file = fopen( full_name.long_name, "r" )))
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000655 TRACE("(%s): found it in %s\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000656 filename, full_name.long_name );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000657 }
658
659 if (file)
660 {
Alexandre Julliard829fe321998-07-26 14:27:39 +0000661 CurProfile->section = PROFILE_Load( file );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000662 fclose( file );
Alexandre Julliard829fe321998-07-26 14:27:39 +0000663 if(!stat(CurProfile->unix_name,&buf))
664 CurProfile->mtime=buf.st_mtime;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000665 }
666 else
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +0000667 {
668 /* Does not exist yet, we will create it in PROFILE_FlushFile */
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000669 WARN("profile file %s not found\n", newdos_name );
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +0000670 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000671 return TRUE;
672}
673
674
675/***********************************************************************
676 * PROFILE_GetSection
677 *
Alexandre Julliarda845b881998-06-01 10:44:35 +0000678 * Returns all keys of a section.
Alexandre Julliard642d3131998-07-12 19:29:36 +0000679 * If return_values is TRUE, also include the corresponding values.
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000680 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000681static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
Eric Poueched155751999-03-25 13:24:08 +0000682 LPSTR buffer, UINT len, BOOL handle_env,
683 BOOL return_values )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000684{
685 PROFILEKEY *key;
686 while (section)
687 {
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000688 if (section->name && !strcasecmp( section->name, section_name ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000689 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000690 UINT oldlen = len;
Alexandre Julliard9416aba1999-01-26 17:29:49 +0000691 for (key = section->key; key; key = key->next)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000692 {
693 if (len <= 2) break;
Alexandre Julliard9416aba1999-01-26 17:29:49 +0000694 if (!*key->name) continue; /* Skip empty lines */
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000695 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
696 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
Alexandre Julliard0c126c71996-02-18 18:44:41 +0000697 len -= strlen(buffer) + 1;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000698 buffer += strlen(buffer) + 1;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000699 if (return_values && key->value) {
700 buffer[-1] = '=';
701 PROFILE_CopyEntry ( buffer,
702 key->value, len - 1, handle_env );
703 len -= strlen(buffer) + 1;
704 buffer += strlen(buffer) + 1;
705 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000706 }
707 *buffer = '\0';
Marcus Meissneracfae0c1999-05-08 18:29:10 +0000708 if (len <= 1)
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000709 /*If either lpszSection or lpszKey is NULL and the supplied
710 destination buffer is too small to hold all the strings,
711 the last string is truncated and followed by two null characters.
712 In this case, the return value is equal to cchReturnBuffer
713 minus two. */
714 {
715 buffer[-1] = '\0';
716 return oldlen - 2;
717 }
Alexandre Julliard829fe321998-07-26 14:27:39 +0000718 return oldlen - len;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000719 }
720 section = section->next;
721 }
722 buffer[0] = buffer[1] = '\0';
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000723 return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000724}
725
726
Andreas Mohradfeec91999-05-22 16:04:57 +0000727static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
728{
729 LPSTR buf = buffer;
730 WORD l, cursize = 0;
731 PROFILESECTION *section;
732
733 for (section = CurProfile->section; section; section = section->next)
734 if (section->name) {
735 l = strlen(section->name);
736 cursize += l+1;
737 if (cursize > len+1)
738 return len-2;
739
740 strcpy(buf, section->name);
741 buf += l+1;
742 }
743
744 *buf=0;
745 buf++;
746 return buf-buffer;
747}
748
749
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000750/***********************************************************************
751 * PROFILE_GetString
752 *
753 * Get a profile string.
754 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000755static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
Eric Poueched155751999-03-25 13:24:08 +0000756 LPCSTR def_val, LPSTR buffer, UINT len )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000757{
758 PROFILEKEY *key = NULL;
759
760 if (!def_val) def_val = "";
Alexandre Julliard77b99181997-09-14 17:17:23 +0000761 if (key_name && key_name[0])
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000762 {
Alexandre Julliard829fe321998-07-26 14:27:39 +0000763 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000764 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
765 len, FALSE );
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000766 TRACE("('%s','%s','%s'): returning '%s'\n",
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000767 section, key_name, def_val, buffer );
768 return strlen( buffer );
769 }
Andreas Mohradfeec91999-05-22 16:04:57 +0000770 if (section && section[0])
771 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
Alexandre Julliarda845b881998-06-01 10:44:35 +0000772 FALSE, FALSE);
Andreas Mohradfeec91999-05-22 16:04:57 +0000773 /* undocumented; both section and key_name are NULL */
774 return PROFILE_GetSectionNames(buffer, len);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000775}
776
777
778/***********************************************************************
779 * PROFILE_SetString
780 *
781 * Set a profile string.
782 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000783static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
Eric Poueched155751999-03-25 13:24:08 +0000784 LPCSTR value )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000785{
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000786 if (!key_name) /* Delete a whole section */
787 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000788 TRACE("('%s')\n", section_name);
Alexandre Julliard829fe321998-07-26 14:27:39 +0000789 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
790 section_name );
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000791 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
792 this is not an error on application's level.*/
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000793 }
794 else if (!value) /* Delete a key */
795 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000796 TRACE("('%s','%s')\n",
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000797 section_name, key_name );
Alexandre Julliard829fe321998-07-26 14:27:39 +0000798 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
799 section_name, key_name );
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000800 return TRUE; /* same error handling as above */
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000801 }
802 else /* Set the key value */
803 {
Alexandre Julliard829fe321998-07-26 14:27:39 +0000804 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000805 key_name, TRUE );
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000806 TRACE("('%s','%s','%s'): \n",
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000807 section_name, key_name, value );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000808 if (!key) return FALSE;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000809 if (key->value)
810 {
811 if (!strcmp( key->value, value ))
812 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000813 TRACE(" no change needed\n" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000814 return TRUE; /* No change needed */
815 }
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000816 TRACE(" replacing '%s'\n", key->value );
Alexandre Julliard90476d62000-02-16 22:47:24 +0000817 HeapFree( GetProcessHeap(), 0, key->value );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000818 }
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000819 else TRACE(" creating key\n" );
Alexandre Julliard90476d62000-02-16 22:47:24 +0000820 key->value = HEAP_strdupA( GetProcessHeap(), 0, value );
Alexandre Julliard829fe321998-07-26 14:27:39 +0000821 CurProfile->changed = TRUE;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000822 }
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000823 return TRUE;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000824}
825
826
827/***********************************************************************
828 * PROFILE_GetWineIniString
829 *
830 * Get a config string from the wine.ini file.
831 */
832int PROFILE_GetWineIniString( const char *section, const char *key_name,
833 const char *def, char *buffer, int len )
834{
Alexandre Julliard00377a72000-02-19 20:50:00 +0000835 char tmp[PROFILE_MAX_LINE_LEN];
836 HKEY hkey;
837 DWORD err;
Eric Poueched155751999-03-25 13:24:08 +0000838
Alexandre Julliard00377a72000-02-19 20:50:00 +0000839 if (!(err = RegOpenKeyA( wine_profile_key, section, &hkey )))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000840 {
Alexandre Julliard00377a72000-02-19 20:50:00 +0000841 DWORD type;
842 DWORD count = sizeof(tmp);
843 err = RegQueryValueExA( hkey, key_name, 0, &type, tmp, &count );
844 RegCloseKey( hkey );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000845 }
Alexandre Julliard00377a72000-02-19 20:50:00 +0000846 PROFILE_CopyEntry( buffer, err ? def : tmp, len, TRUE );
847 TRACE( "('%s','%s','%s'): returning '%s'\n", section, key_name, def, buffer );
848 return strlen(buffer);
849}
Eric Poueched155751999-03-25 13:24:08 +0000850
Alexandre Julliard00377a72000-02-19 20:50:00 +0000851
852/***********************************************************************
853 * PROFILE_EnumWineIniString
854 *
855 * Get a config string from the wine.ini file.
856 */
857BOOL PROFILE_EnumWineIniString( const char *section, int index,
858 char *name, int name_len, char *buffer, int len )
859{
860 char tmp[PROFILE_MAX_LINE_LEN];
861 HKEY hkey;
862 DWORD err, type;
863 DWORD count = sizeof(tmp);
864
865 if (RegOpenKeyA( wine_profile_key, section, &hkey )) return FALSE;
866 err = RegEnumValueA( hkey, index, name, (DWORD*)&name_len, NULL, &type, tmp, &count );
867 RegCloseKey( hkey );
868 if (!err)
869 {
870 PROFILE_CopyEntry( buffer, tmp, len, TRUE );
871 TRACE( "('%s',%d): returning '%s'='%s'\n", section, index, name, buffer );
872 }
873 return !err;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000874}
875
876
877/***********************************************************************
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000878 * PROFILE_GetWineIniInt
879 *
880 * Get a config integer from the wine.ini file.
881 */
882int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
883{
884 char buffer[20];
885 char *p;
886 long result;
887
Alexandre Julliard00377a72000-02-19 20:50:00 +0000888 PROFILE_GetWineIniString( section, key_name, "", buffer, sizeof(buffer) );
889 if (!buffer[0]) return def;
890 result = strtol( buffer, &p, 0 );
891 return (p == buffer) ? 0 /* No digits at all */ : (int)result;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000892}
893
894
895/******************************************************************************
896 *
897 * int PROFILE_GetWineIniBool(
898 * char const *section,
899 * char const *key_name,
900 * int def )
901 *
902 * Reads a boolean value from the wine.ini file. This function attempts to
903 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
904 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
905 * true. Anything else results in the return of the default value.
906 *
907 * This function uses 1 to indicate true, and 0 for false. You can check
908 * for existence by setting def to something other than 0 or 1 and
909 * examining the return value.
910 */
911int PROFILE_GetWineIniBool(
912 char const *section,
913 char const *key_name,
914 int def )
915{
916 char key_value[2];
917 int retval;
918
919 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
920
921 switch(key_value[0]) {
922 case 'n':
923 case 'N':
924 case 'f':
925 case 'F':
926 case '0':
927 retval = 0;
928 break;
929
930 case 'y':
931 case 'Y':
932 case 't':
933 case 'T':
934 case '1':
935 retval = 1;
936 break;
937
938 default:
939 retval = def;
940 }
941
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000942 TRACE("(\"%s\", \"%s\", %s), "
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000943 "[%c], ret %s.\n", section, key_name,
944 def ? "TRUE" : "FALSE", key_value[0],
945 retval ? "TRUE" : "FALSE");
946
947 return retval;
948}
949
950
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000951/***********************************************************************
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000952 * PROFILE_LoadWineIni
953 *
954 * Load the wine.ini file.
955 */
956int PROFILE_LoadWineIni(void)
957{
958 char buffer[MAX_PATHNAME_LEN];
959 const char *p;
960 FILE *f;
Eric Pouech0521a542000-02-20 13:39:42 +0000961 HKEY hKeySW;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000962
Eric Pouech0521a542000-02-20 13:39:42 +0000963 /* make sure HKLM\\Software exists as non-volatile key */
964 if (RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software", &hKeySW ))
965 {
966 ERR("Cannot create config registry key\n" );
967 return 0;
968 }
969 RegCloseKey( hKeySW );
Alexandre Julliard00377a72000-02-19 20:50:00 +0000970 if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config", 0, NULL,
971 REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &wine_profile_key, NULL ))
972 {
973 ERR("Cannot create config registry key\n" );
974 return 0;
975 }
976
Eric Poueched155751999-03-25 13:24:08 +0000977 InitializeCriticalSection( &PROFILE_CritSect );
978 MakeCriticalSectionGlobal( &PROFILE_CritSect );
979
Alexandre Julliard00377a72000-02-19 20:50:00 +0000980 if (!CLIENT_IsBootThread()) return 1; /* already loaded */
981
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000982 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
983 {
984 /* Open -config specified file */
Francois Gougetbaa9bf91999-12-27 05:24:06 +0000985 lstrcpynA(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN);
Alexandre Julliard00377a72000-02-19 20:50:00 +0000986 goto found;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000987 }
988
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000989 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
Eric Poueched155751999-03-25 13:24:08 +0000990 {
Francois Gougetbaa9bf91999-12-27 05:24:06 +0000991 lstrcpynA(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN);
Alexandre Julliard00377a72000-02-19 20:50:00 +0000992 goto found;
Eric Poueched155751999-03-25 13:24:08 +0000993 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000994 if ((p = getenv( "HOME" )) != NULL)
995 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000996 lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000997 strcat( buffer, PROFILE_WineIniName );
998 if ((f = fopen( buffer, "r" )) != NULL)
999 {
Francois Gougetbaa9bf91999-12-27 05:24:06 +00001000 lstrcpynA(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN);
Alexandre Julliard00377a72000-02-19 20:50:00 +00001001 goto found;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001002 }
1003 }
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001004 else WARN("could not get $HOME value for config file.\n" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001005
1006 /* Try global file */
1007
1008 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
1009 {
Francois Gougetbaa9bf91999-12-27 05:24:06 +00001010 lstrcpynA(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN);
Alexandre Julliard00377a72000-02-19 20:50:00 +00001011 goto found;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001012 }
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001013 MESSAGE( "Can't open configuration file %s or $HOME%s\n",
Eric Pouech0521a542000-02-20 13:39:42 +00001014 WINE_INI_GLOBAL, PROFILE_WineIniName );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001015 return 0;
Alexandre Julliard00377a72000-02-19 20:50:00 +00001016
1017 found:
1018 PROFILE_RegistryLoad( wine_profile_key, f );
1019 fclose( f );
1020 return 1;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001021}
1022
1023
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001024/***********************************************************************
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001025 * PROFILE_UsageWineIni
1026 *
1027 * Explain the wine.ini file to those who don't read documentation.
1028 * Keep below one screenful in length so that error messages above are
1029 * noticed.
1030 */
1031void PROFILE_UsageWineIni(void)
1032{
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001033 MESSAGE("Perhaps you have not properly edited or created "
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001034 "your Wine configuration file.\n");
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001035 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
1036 MESSAGE(" or it is determined by the -config option or from\n"
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001037 " the WINE_INI environment variable.\n");
1038 if (*PROFILE_WineIniUsed)
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001039 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001040 /* RTFM, so to say */
1041}
1042
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001043/***********************************************************************
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001044 * PROFILE_GetStringItem
1045 *
1046 * Convenience function that turns a string 'xxx, yyy, zzz' into
1047 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
1048 */
1049char* PROFILE_GetStringItem( char* start )
1050{
1051 char* lpchX, *lpch;
1052
1053 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
1054 {
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001055 if( *lpchX == ',' )
1056 {
1057 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
1058 while( *(++lpchX) )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001059 if( !PROFILE_isspace(*lpchX) ) return lpchX;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001060 }
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001061 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001062 else lpch = NULL;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001063 }
1064 if( lpch ) *lpch = '\0';
1065 return NULL;
1066}
1067
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001068/********************* API functions **********************************/
1069
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001070/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001071 * GetProfileInt16 (KERNEL.57)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001072 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001073UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001074{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001075 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001076}
1077
1078
1079/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001080 * GetProfileInt32A (KERNEL32.264)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001081 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001082UINT WINAPI GetProfileIntA( LPCSTR section, LPCSTR entry, INT def_val )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001083{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001084 return GetPrivateProfileIntA( section, entry, def_val, "win.ini" );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001085}
1086
1087/***********************************************************************
1088 * GetProfileInt32W (KERNEL32.264)
1089 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001090UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001091{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001092 return GetPrivateProfileIntW( section, entry, def_val, wininiW );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001093}
1094
1095/***********************************************************************
1096 * GetProfileString16 (KERNEL.58)
1097 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001098INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001099 LPSTR buffer, UINT16 len )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001100{
1101 return GetPrivateProfileString16( section, entry, def_val,
1102 buffer, len, "win.ini" );
1103}
1104
1105/***********************************************************************
1106 * GetProfileString32A (KERNEL32.268)
1107 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001108INT WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,
Eric Poueched155751999-03-25 13:24:08 +00001109 LPSTR buffer, UINT len )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001110{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001111 return GetPrivateProfileStringA( section, entry, def_val,
Eric Poueched155751999-03-25 13:24:08 +00001112 buffer, len, "win.ini" );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001113}
1114
1115/***********************************************************************
1116 * GetProfileString32W (KERNEL32.269)
1117 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001118INT WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry,
Eric Poueched155751999-03-25 13:24:08 +00001119 LPCWSTR def_val, LPWSTR buffer, UINT len )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001120{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001121 return GetPrivateProfileStringW( section, entry, def_val,
Eric Poueched155751999-03-25 13:24:08 +00001122 buffer, len, wininiW );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001123}
1124
Alexandre Julliard77b99181997-09-14 17:17:23 +00001125/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001126 * WriteProfileString16 (KERNEL.59)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001127 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001128BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
1129 LPCSTR string )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001130{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001131 return WritePrivateProfileString16( section, entry, string, "win.ini" );
1132}
1133
1134/***********************************************************************
1135 * WriteProfileString32A (KERNEL32.587)
1136 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001137BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry,
Eric Poueched155751999-03-25 13:24:08 +00001138 LPCSTR string )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001139{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001140 return WritePrivateProfileStringA( section, entry, string, "win.ini" );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001141}
1142
1143/***********************************************************************
1144 * WriteProfileString32W (KERNEL32.588)
1145 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001146BOOL WINAPI WriteProfileStringW( LPCWSTR section, LPCWSTR entry,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001147 LPCWSTR string )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001148{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001149 return WritePrivateProfileStringW( section, entry, string, wininiW );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001150}
1151
1152
1153/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001154 * GetPrivateProfileInt16 (KERNEL.127)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001155 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001156UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
1157 INT16 def_val, LPCSTR filename )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001158{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001159 long result=(long)GetPrivateProfileIntA(section,entry,def_val,filename);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001160
1161 if (result > 65535) return 65535;
1162 if (result >= 0) return (UINT16)result;
1163 if (result < -32768) return -32768;
1164 return (UINT16)(INT16)result;
1165}
1166
1167/***********************************************************************
1168 * GetPrivateProfileInt32A (KERNEL32.251)
1169 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001170UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
Eric Poueched155751999-03-25 13:24:08 +00001171 INT def_val, LPCSTR filename )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001172{
1173 char buffer[20];
1174 char *p;
1175 long result;
1176
Alexandre Julliarda3960291999-02-26 11:11:13 +00001177 GetPrivateProfileStringA( section, entry, "",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001178 buffer, sizeof(buffer), filename );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001179 if (!buffer[0]) return (UINT)def_val;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001180 result = strtol( buffer, &p, 0 );
1181 if (p == buffer) return 0; /* No digits at all */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001182 return (UINT)result;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001183}
1184
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001185/***********************************************************************
1186 * GetPrivateProfileInt32W (KERNEL32.252)
1187 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001188UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,
Eric Poueched155751999-03-25 13:24:08 +00001189 INT def_val, LPCWSTR filename )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001190{
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001191 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1192 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1193 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001194 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001195 HeapFree( GetProcessHeap(), 0, sectionA );
1196 HeapFree( GetProcessHeap(), 0, filenameA );
1197 HeapFree( GetProcessHeap(), 0, entryA );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001198 return res;
1199}
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001200
1201/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001202 * GetPrivateProfileString16 (KERNEL.128)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001203 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001204INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
1205 LPCSTR def_val, LPSTR buffer,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001206 UINT16 len, LPCSTR filename )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001207{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001208 return GetPrivateProfileStringA(section,entry,def_val,buffer,len,filename);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001209}
1210
1211/***********************************************************************
1212 * GetPrivateProfileString32A (KERNEL32.255)
1213 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001214INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
Eric Poueched155751999-03-25 13:24:08 +00001215 LPCSTR def_val, LPSTR buffer,
1216 UINT len, LPCSTR filename )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001217{
Eric Poueched155751999-03-25 13:24:08 +00001218 int ret;
1219
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001220 if (!filename)
1221 filename = "win.ini";
Eric Poueched155751999-03-25 13:24:08 +00001222
1223 EnterCriticalSection( &PROFILE_CritSect );
1224
1225 if (PROFILE_Open( filename )) {
1226 ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1227 } else {
1228 lstrcpynA( buffer, def_val, len );
1229 ret = strlen( buffer );
1230 }
1231
1232 LeaveCriticalSection( &PROFILE_CritSect );
1233
1234 return ret;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001235}
1236
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001237/***********************************************************************
1238 * GetPrivateProfileString32W (KERNEL32.256)
1239 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001240INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
Eric Poueched155751999-03-25 13:24:08 +00001241 LPCWSTR def_val, LPWSTR buffer,
1242 UINT len, LPCWSTR filename )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001243{
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001244 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1245 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1246 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1247 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1248 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001249 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001250 bufferA, len, filenameA );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001251 lstrcpynAtoW( buffer, bufferA, len );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001252 HeapFree( GetProcessHeap(), 0, sectionA );
1253 HeapFree( GetProcessHeap(), 0, entryA );
1254 HeapFree( GetProcessHeap(), 0, filenameA );
1255 HeapFree( GetProcessHeap(), 0, def_valA );
1256 HeapFree( GetProcessHeap(), 0, bufferA);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001257 return ret;
1258}
1259
Alexandre Julliard77b99181997-09-14 17:17:23 +00001260/***********************************************************************
Ulrich Weigand8228bd61999-04-22 09:56:09 +00001261 * GetPrivateProfileSection16 (KERNEL.418)
1262 */
1263INT16 WINAPI GetPrivateProfileSection16( LPCSTR section, LPSTR buffer,
1264 UINT16 len, LPCSTR filename )
1265{
1266 return GetPrivateProfileSectionA( section, buffer, len, filename );
1267}
1268
1269/***********************************************************************
Alexandre Julliard77b99181997-09-14 17:17:23 +00001270 * GetPrivateProfileSection32A (KERNEL32.255)
1271 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001272INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,
Eric Poueched155751999-03-25 13:24:08 +00001273 DWORD len, LPCSTR filename )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001274{
Eric Poueched155751999-03-25 13:24:08 +00001275 int ret = 0;
1276
1277 EnterCriticalSection( &PROFILE_CritSect );
1278
Alexandre Julliard77b99181997-09-14 17:17:23 +00001279 if (PROFILE_Open( filename ))
Eric Poueched155751999-03-25 13:24:08 +00001280 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
1281 FALSE, TRUE);
1282
1283 LeaveCriticalSection( &PROFILE_CritSect );
Alexandre Julliarda845b881998-06-01 10:44:35 +00001284
Marcus Meissner264360f1999-05-08 10:02:05 +00001285 return ret;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001286}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001287
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001288/***********************************************************************
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001289 * GetPrivateProfileSection32W (KERNEL32.256)
1290 */
1291
Alexandre Julliarda3960291999-02-26 11:11:13 +00001292INT WINAPI GetPrivateProfileSectionW (LPCWSTR section, LPWSTR buffer,
Eric Poueched155751999-03-25 13:24:08 +00001293 DWORD len, LPCWSTR filename )
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001294
1295{
1296 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1297 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1298 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001299 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001300 filenameA );
Marcus Meissner264360f1999-05-08 10:02:05 +00001301 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001302 HeapFree( GetProcessHeap(), 0, sectionA );
1303 HeapFree( GetProcessHeap(), 0, filenameA );
1304 HeapFree( GetProcessHeap(), 0, bufferA);
1305 return ret;
1306}
1307
1308/***********************************************************************
Ulrich Weigand8228bd61999-04-22 09:56:09 +00001309 * GetProfileSection16 (KERNEL.419)
1310 */
1311INT16 WINAPI GetProfileSection16( LPCSTR section, LPSTR buffer, UINT16 len )
1312{
1313 return GetPrivateProfileSection16( section, buffer, len, "win.ini" );
1314}
1315
1316/***********************************************************************
1317 * GetProfileSection32A (KERNEL32.268)
1318 */
1319INT WINAPI GetProfileSectionA( LPCSTR section, LPSTR buffer, DWORD len )
1320{
1321 return GetPrivateProfileSectionA( section, buffer, len, "win.ini" );
1322}
1323
1324/***********************************************************************
1325 * GetProfileSection32W (KERNEL32)
1326 */
1327INT WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len )
1328{
Ulrich Weigand8228bd61999-04-22 09:56:09 +00001329 return GetPrivateProfileSectionW( section, buffer, len, wininiW );
1330}
1331
1332
1333/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001334 * WritePrivateProfileString16 (KERNEL.129)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001335 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001336BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
1337 LPCSTR string, LPCSTR filename )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001338{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001339 return WritePrivateProfileStringA(section,entry,string,filename);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001340}
1341
1342/***********************************************************************
1343 * WritePrivateProfileString32A (KERNEL32.582)
1344 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001345BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
Eric Poueched155751999-03-25 13:24:08 +00001346 LPCSTR string, LPCSTR filename )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001347{
Alexandre Julliarde61b7921999-07-31 19:24:11 +00001348 BOOL ret = FALSE;
Eric Poueched155751999-03-25 13:24:08 +00001349
1350 EnterCriticalSection( &PROFILE_CritSect );
1351
Alexandre Julliarde61b7921999-07-31 19:24:11 +00001352 if (PROFILE_Open( filename ))
1353 {
1354 if (!section && !entry && !string)
1355 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1356 else
1357 ret = PROFILE_SetString( section, entry, string );
Eric Poueched155751999-03-25 13:24:08 +00001358 }
1359
1360 LeaveCriticalSection( &PROFILE_CritSect );
Eric Poueched155751999-03-25 13:24:08 +00001361 return ret;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001362}
1363
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001364/***********************************************************************
1365 * WritePrivateProfileString32W (KERNEL32.583)
1366 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001367BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
Eric Poueched155751999-03-25 13:24:08 +00001368 LPCWSTR string, LPCWSTR filename )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001369{
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001370 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1371 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1372 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1373 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001374 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
Eric Poueched155751999-03-25 13:24:08 +00001375 stringA, filenameA );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001376 HeapFree( GetProcessHeap(), 0, sectionA );
1377 HeapFree( GetProcessHeap(), 0, entryA );
1378 HeapFree( GetProcessHeap(), 0, stringA );
1379 HeapFree( GetProcessHeap(), 0, filenameA );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001380 return res;
1381}
1382
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001383/***********************************************************************
Ulrich Weigand8228bd61999-04-22 09:56:09 +00001384 * WritePrivateProfileSection16 (KERNEL.416)
1385 */
1386BOOL16 WINAPI WritePrivateProfileSection16( LPCSTR section,
1387 LPCSTR string, LPCSTR filename )
1388{
1389 return WritePrivateProfileSectionA( section, string, filename );
1390}
1391
1392/***********************************************************************
Rein Klazes7458be02000-01-05 01:42:51 +00001393 * WritePrivateProfileSectionA (KERNEL32)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001394 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001395BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section,
Eric Poueched155751999-03-25 13:24:08 +00001396 LPCSTR string, LPCSTR filename )
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001397{
Rein Klazes7458be02000-01-05 01:42:51 +00001398 BOOL ret = FALSE;
1399 LPSTR p ;
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001400
Rein Klazes7458be02000-01-05 01:42:51 +00001401 EnterCriticalSection( &PROFILE_CritSect );
1402
1403 if (PROFILE_Open( filename )) {
1404 if (!section && !string && !filename)
1405 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1406 else {
1407 while(*string){
1408 LPSTR buf=HEAP_strdupA( GetProcessHeap(), 0, string );
1409 if((p=strchr( buf, '='))){
1410 *p='\0';
1411 ret = PROFILE_SetString( section, buf, p+1 );
1412
1413 }
1414 HeapFree( GetProcessHeap(), 0, buf );
1415 string += strlen(string)+1;
1416 }
1417
1418 }
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001419 }
Rein Klazes7458be02000-01-05 01:42:51 +00001420
1421 LeaveCriticalSection( &PROFILE_CritSect );
1422 return ret;
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001423}
1424
Alexandre Julliarda845b881998-06-01 10:44:35 +00001425/***********************************************************************
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001426 * WritePrivateProfileSection32W (KERNEL32)
1427 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001428BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
Eric Poueched155751999-03-25 13:24:08 +00001429 LPCWSTR string, LPCWSTR filename)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001430
1431{
1432 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1433 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1434 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001435 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001436 HeapFree( GetProcessHeap(), 0, sectionA );
1437 HeapFree( GetProcessHeap(), 0, stringA );
1438 HeapFree( GetProcessHeap(), 0, filenameA );
1439 return res;
1440}
1441
Ulrich Weigand8228bd61999-04-22 09:56:09 +00001442/***********************************************************************
1443 * WriteProfileSection16 (KERNEL.417)
1444 */
1445BOOL16 WINAPI WriteProfileSection16( LPCSTR section, LPCSTR keys_n_values)
1446{
1447 return WritePrivateProfileSection16( section, keys_n_values, "win.ini");
1448}
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001449
1450/***********************************************************************
1451 * WriteProfileSection32A (KERNEL32.747)
1452 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001453BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001454
1455{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001456 return WritePrivateProfileSectionA( section, keys_n_values, "win.ini");
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001457}
1458
1459/***********************************************************************
1460 * WriteProfileSection32W (KERNEL32.748)
1461 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001462BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001463{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001464 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW));
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001465}
1466
1467/***********************************************************************
Alexandre Julliarda845b881998-06-01 10:44:35 +00001468 * GetPrivateProfileSectionNames16 (KERNEL.143)
1469 */
1470WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1471 LPCSTR filename )
1472{
Andreas Mohradfeec91999-05-22 16:04:57 +00001473 WORD ret = 0;
Eric Poueched155751999-03-25 13:24:08 +00001474
1475 EnterCriticalSection( &PROFILE_CritSect );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001476
Andreas Mohradfeec91999-05-22 16:04:57 +00001477 if (PROFILE_Open( filename ))
1478 ret = PROFILE_GetSectionNames(buffer, size);
Eric Poueched155751999-03-25 13:24:08 +00001479
1480 LeaveCriticalSection( &PROFILE_CritSect );
1481
1482 return ret;
Alexandre Julliarda845b881998-06-01 10:44:35 +00001483}
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001484
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001485
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001486/***********************************************************************
1487 * GetProfileSectionNames16 (KERNEL.142)
1488 */
1489WORD WINAPI GetProfileSectionNames16( LPSTR buffer, WORD size)
1490
1491{
Eric Poueched155751999-03-25 13:24:08 +00001492 return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001493}
1494
1495
1496/***********************************************************************
1497 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1498 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001499DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,
Eric Poueched155751999-03-25 13:24:08 +00001500 LPCSTR filename)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001501
1502{
1503 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1504}
1505
1506
1507/***********************************************************************
1508 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1509 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001510DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
Eric Poueched155751999-03-25 13:24:08 +00001511 LPCWSTR filename)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001512
1513{
1514 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1515 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, size);
1516
Alexandre Julliarda3960291999-02-26 11:11:13 +00001517 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001518 lstrcpynAtoW( buffer, bufferA, size);
1519 HeapFree( GetProcessHeap(), 0, bufferA);
1520 HeapFree( GetProcessHeap(), 0, filenameA );
1521
1522 return ret;
1523}
1524
Ulrich Weigand8228bd61999-04-22 09:56:09 +00001525/***********************************************************************
1526 * GetPrivateProfileStruct16 (KERNEL.407)
1527 */
1528BOOL16 WINAPI GetPrivateProfileStruct16(LPCSTR section, LPCSTR key,
1529 LPVOID buf, UINT16 len, LPCSTR filename)
1530{
1531 return GetPrivateProfileStructA( section, key, buf, len, filename );
1532}
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001533
1534/***********************************************************************
1535 * GetPrivateProfileStruct32A (KERNEL32.370)
Andreas Mohr17b1f462000-01-30 21:15:14 +00001536 *
1537 * Should match Win95's behaviour pretty much
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001538 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001539BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
Eric Poueched155751999-03-25 13:24:08 +00001540 LPVOID buf, UINT len, LPCSTR filename)
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001541{
Eric Poueched155751999-03-25 13:24:08 +00001542 BOOL ret = FALSE;
1543
1544 EnterCriticalSection( &PROFILE_CritSect );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001545
1546 if (PROFILE_Open( filename )) {
Eric Poueched155751999-03-25 13:24:08 +00001547 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1548 if (k) {
Andreas Mohr17b1f462000-01-30 21:15:14 +00001549 TRACE("value (at %p): '%s'\n", k->value, k->value);
1550 if (((strlen(k->value) - 2) / 2) == len)
1551 {
1552 LPSTR end, p;
1553 BOOL valid = TRUE;
1554 CHAR c;
1555 DWORD chksum = 0;
1556
1557 end = k->value + strlen(k->value); /* -> '\0' */
1558 /* check for invalid chars in ASCII coded hex string */
1559 for (p=k->value; p < end; p++)
1560 {
1561 if (!isxdigit(*p))
1562 {
1563 WARN("invalid char '%c' in file '%s'->'[%s]'->'%s' !\n",
1564 *p, filename, section, key);
1565 valid = FALSE;
1566 break;
1567 }
1568 }
1569 if (valid)
1570 {
1571 BOOL highnibble = TRUE;
1572 BYTE b = 0, val;
1573 LPBYTE binbuf = (LPBYTE)buf;
1574
1575 end -= 2; /* don't include checksum in output data */
1576 /* translate ASCII hex format into binary data */
1577 for (p=k->value; p < end; p++)
1578 {
1579 c = toupper(*p);
1580 val = (c > '9') ?
1581 (c - 'A' + 10) : (c - '0');
1582
1583 if (highnibble)
1584 b = val << 4;
1585 else
1586 {
1587 b += val;
1588 *binbuf++ = b; /* feed binary data into output */
1589 chksum += b; /* calculate checksum */
1590 }
1591 highnibble ^= 1; /* toggle */
1592 }
1593 /* retrieve stored checksum value */
1594 c = toupper(*p++);
1595 b = ( (c > '9') ? (c - 'A' + 10) : (c - '0') ) << 4;
1596 c = toupper(*p);
1597 b += (c > '9') ? (c - 'A' + 10) : (c - '0');
1598 if (b == (chksum & 0xff)) /* checksums match ? */
1599 ret = TRUE;
1600 }
1601 }
Eric Poueched155751999-03-25 13:24:08 +00001602 }
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001603 }
Eric Poueched155751999-03-25 13:24:08 +00001604 LeaveCriticalSection( &PROFILE_CritSect );
1605
Andreas Mohr17b1f462000-01-30 21:15:14 +00001606 return ret;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001607}
1608
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001609/***********************************************************************
1610 * GetPrivateProfileStruct32W (KERNEL32.543)
1611 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001612BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
Eric Poueched155751999-03-25 13:24:08 +00001613 LPVOID buffer, UINT len, LPCWSTR filename)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001614{
1615 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1616 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1617 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1618 LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, len );
1619
Alexandre Julliarda3960291999-02-26 11:11:13 +00001620 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
Eric Poueched155751999-03-25 13:24:08 +00001621 len, filenameA );
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001622 lstrcpynAtoW( buffer, bufferA, len );
1623 HeapFree( GetProcessHeap(), 0, bufferA);
1624 HeapFree( GetProcessHeap(), 0, sectionA );
1625 HeapFree( GetProcessHeap(), 0, keyA );
1626 HeapFree( GetProcessHeap(), 0, filenameA );
1627
1628 return ret;
1629}
1630
1631
1632
Ulrich Weigand8228bd61999-04-22 09:56:09 +00001633/***********************************************************************
1634 * WritePrivateProfileStruct16 (KERNEL.406)
1635 */
1636BOOL16 WINAPI WritePrivateProfileStruct16 (LPCSTR section, LPCSTR key,
1637 LPVOID buf, UINT16 bufsize, LPCSTR filename)
1638{
1639 return WritePrivateProfileStructA( section, key, buf, bufsize, filename );
1640}
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001641
1642/***********************************************************************
1643 * WritePrivateProfileStruct32A (KERNEL32.744)
1644 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001645BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
Alexandre Julliarde61b7921999-07-31 19:24:11 +00001646 LPVOID buf, UINT bufsize, LPCSTR filename)
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001647{
Alexandre Julliarde61b7921999-07-31 19:24:11 +00001648 BOOL ret = FALSE;
Andreas Mohr17b1f462000-01-30 21:15:14 +00001649 LPBYTE binbuf;
1650 LPSTR outstring, p;
1651 DWORD sum = 0;
Alexandre Julliarde61b7921999-07-31 19:24:11 +00001652
1653 if (!section && !key && !buf) /* flush the cache */
1654 return WritePrivateProfileStringA( NULL, NULL, NULL, filename );
Eric Poueched155751999-03-25 13:24:08 +00001655
Andreas Mohr17b1f462000-01-30 21:15:14 +00001656 /* allocate string buffer for hex chars + checksum hex char + '\0' */
Alexandre Julliard90476d62000-02-16 22:47:24 +00001657 outstring = HeapAlloc( GetProcessHeap(), 0, bufsize*2 + 2 + 1);
Andreas Mohr17b1f462000-01-30 21:15:14 +00001658 p = outstring;
1659 for (binbuf = (LPBYTE)buf; binbuf < (LPBYTE)buf+bufsize; binbuf++) {
1660 *p++ = hex[*binbuf >> 4];
1661 *p++ = hex[*binbuf & 0xf];
1662 sum += *binbuf;
1663 }
1664 /* checksum is sum & 0xff */
1665 *p++ = hex[(sum & 0xf0) >> 4];
1666 *p++ = hex[sum & 0xf];
1667 *p++ = '\0';
1668
Eric Poueched155751999-03-25 13:24:08 +00001669 EnterCriticalSection( &PROFILE_CritSect );
1670
Alexandre Julliarde61b7921999-07-31 19:24:11 +00001671 if (PROFILE_Open( filename ))
Andreas Mohr17b1f462000-01-30 21:15:14 +00001672 ret = PROFILE_SetString( section, key, outstring );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001673
Eric Poueched155751999-03-25 13:24:08 +00001674 LeaveCriticalSection( &PROFILE_CritSect );
1675
Alexandre Julliard90476d62000-02-16 22:47:24 +00001676 HeapFree( GetProcessHeap(), 0, outstring );
Andreas Mohr17b1f462000-01-30 21:15:14 +00001677
Eric Poueched155751999-03-25 13:24:08 +00001678 return ret;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001679}
1680
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001681/***********************************************************************
1682 * WritePrivateProfileStruct32W (KERNEL32.544)
1683 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001684BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
Eric Poueched155751999-03-25 13:24:08 +00001685 LPVOID buf, UINT bufsize, LPCWSTR filename)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001686{
1687 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1688 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1689 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001690 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
Eric Poueched155751999-03-25 13:24:08 +00001691 filenameA );
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001692 HeapFree( GetProcessHeap(), 0, sectionA );
1693 HeapFree( GetProcessHeap(), 0, keyA );
1694 HeapFree( GetProcessHeap(), 0, filenameA );
1695
1696 return ret;
1697}
1698
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001699
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001700/***********************************************************************
1701 * WriteOutProfiles (KERNEL.315)
1702 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001703void WINAPI WriteOutProfiles16(void)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001704{
Eric Poueched155751999-03-25 13:24:08 +00001705 EnterCriticalSection( &PROFILE_CritSect );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001706 PROFILE_FlushFile();
Eric Poueched155751999-03-25 13:24:08 +00001707 LeaveCriticalSection( &PROFILE_CritSect );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001708}
Marcus Meissner9b4fcf71999-12-04 04:19:55 +00001709
1710/***********************************************************************
1711 * CloseProfileUserMapping (KERNEL.138)
1712 */
1713BOOL WINAPI CloseProfileUserMapping(void) {
1714 FIXME("(), stub!\n");
1715 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1716 return FALSE;
1717}