source: trunk/src/kernel32/profile.cpp@ 408

Last change on this file since 408 was 408, checked in by phaller, 26 years ago

Fix: Win3-Style Profile support ported from WINE. Also removes Open32 dependency

File size: 44.1 KB
Line 
1/* $Id: profile.cpp,v 1.5 1999-08-04 00:44:33 phaller Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 *
6 * Win32 profile API functions
7 *
8 * Copyright 1993 Miguel de Icaza
9 * Copyright 1996 Alexandre Julliard
10 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
11 * Copyright 1998 Patrick Haller
12 */
13
14#include <os2win.h>
15#include <ctype.h>
16#include <stdlib.h>
17#include <string.h>
18#include <stdio.h>
19#include <unicode.h>
20//#include "heap.h"
21
22#include <sys/stat.h>
23
24#include "winbase.h"
25//#include "wine/winbase16.h"
26#include "winuser.h"
27#include "winnls.h"
28//#include "heap.h"
29//#include "debugtools.h"
30//#include "options.h"
31
32
33// -------------------------
34// WINE compatibility macros
35// -------------------------
36
37#ifndef MAX_PATHNAME_LEN
38#define MAX_PATHNAME_LEN 260
39#endif
40
41#define HeapFree(a,b,c) free(c)
42#define HEAP_xalloc(a,b,c) malloc(c)
43#define HEAP_strdupA(a,b,c) strdup(c)
44#define strcasecmp strcmp
45#define DOSFS_GetFullName(a,b,c) strcpy(c,a)
46#define HEAP_strdupAtoW(a,b,c) AsciiToUnicodeString((char *)c)
47#define HEAP_strdupWtoA(a,b,c) UnicodeToAsciiString((LPWSTR)c)
48#define lstrcpynAtoW(a,b,c) AsciiToUnicodeN((char*)a,(LPWSTR)b,(int)c)
49#define lstrcpynWtoA(a,b,c) UnicodeToAsciiN((LPWSTR)a,(char*)b,(int)c)
50#define lstrcpynA(a,b,c) strncpy((char*)a,(char*)b,(int)c)
51#define CharLowerA(a) (a)
52
53
54typedef struct tagPROFILEKEY
55{
56 char *name;
57 char *value;
58 struct tagPROFILEKEY *next;
59} PROFILEKEY;
60
61typedef struct tagPROFILESECTION
62{
63 char *name;
64 struct tagPROFILEKEY *key;
65 struct tagPROFILESECTION *next;
66} PROFILESECTION;
67
68
69typedef struct
70{
71 BOOL changed;
72 PROFILESECTION *section;
73 char *dos_name;
74 char *unix_name;
75 char *filename;
76 time_t mtime;
77} PROFILE;
78
79
80#define N_CACHED_PROFILES 10
81
82/* Cached profile files */
83static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
84
85#define CurProfile (MRUProfile[0])
86
87/* wine.ini profile content */
88static PROFILESECTION *PROFILE_WineProfile;
89
90#define PROFILE_MAX_LINE_LEN 1024
91
92/* Wine profile name in $HOME directory; must begin with slash */
93static const char PROFILE_WineIniName[] = "/.winerc";
94
95/* Wine profile: the profile file being used */
96static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
97
98/* Check for comments in profile */
99#define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
100
101#define WINE_INI_GLOBAL ETCDIR "/wine.conf"
102
103static LPCWSTR wininiW = NULL;
104
105static CRITICAL_SECTION PROFILE_CritSect;
106
107
108/***********************************************************************
109 * PROFILE_CopyEntry
110 *
111 * Copy the content of an entry into a buffer, removing quotes, and possibly
112 * translating environment variables.
113 */
114static void PROFILE_CopyEntry( char *buffer,
115 const char *value,
116 int len,
117 int handle_env )
118{
119 char quote = '\0';
120 const char *p;
121
122 if ((*value == '\'') || (*value == '\"'))
123 {
124 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
125 }
126
127 if (!handle_env)
128 {
129 lstrcpynA( buffer, value, len );
130 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
131 return;
132 }
133
134 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
135 {
136 if ((*p == '$') && (p[1] == '{'))
137 {
138 char env_val[1024];
139 const char *env_p;
140 const char *p2 = strchr( p, '}' );
141 if (!p2) continue; /* ignore it */
142 lstrcpynA(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
143 if ((env_p = getenv( env_val )) != NULL)
144 {
145 lstrcpynA( buffer, env_p, len );
146 buffer += strlen( buffer );
147 len -= strlen( buffer );
148 }
149 p = p2 + 1;
150 }
151 }
152 *buffer = '\0';
153}
154
155
156/***********************************************************************
157 * PROFILE_Save
158 *
159 * Save a profile tree to a file.
160 */
161static void PROFILE_Save( FILE *file, PROFILESECTION *section )
162{
163 PROFILEKEY *key;
164
165 for ( ; section; section = section->next)
166 {
167 if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
168 for (key = section->key; key; key = key->next)
169 {
170 fprintf( file, "%s", key->name );
171 if (key->value) fprintf( file, "=%s", key->value );
172 fprintf( file, "\r\n" );
173 }
174 }
175}
176
177
178/***********************************************************************
179 * PROFILE_Free
180 *
181 * Free a profile tree.
182 */
183static void PROFILE_Free( PROFILESECTION *section )
184{
185 PROFILESECTION *next_section;
186 PROFILEKEY *key, *next_key;
187
188 for ( ; section; section = next_section)
189 {
190 if (section->name) HeapFree( SystemHeap, 0, section->name );
191 for (key = section->key; key; key = next_key)
192 {
193 next_key = key->next;
194 if (key->name) HeapFree( SystemHeap, 0, key->name );
195 if (key->value) HeapFree( SystemHeap, 0, key->value );
196 HeapFree( SystemHeap, 0, key );
197 }
198 next_section = section->next;
199 HeapFree( SystemHeap, 0, section );
200 }
201}
202
203static int
204PROFILE_isspace(char c) {
205 if (isspace(c)) return 1;
206 if (c=='\r' || c==0x1a) return 1;
207 /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
208 return 0;
209}
210
211
212/***********************************************************************
213 * PROFILE_Load
214 *
215 * Load a profile tree from a file.
216 */
217static PROFILESECTION *PROFILE_Load( FILE *file )
218{
219 char buffer[PROFILE_MAX_LINE_LEN];
220 char *p, *p2;
221 int line = 0;
222 PROFILESECTION *section, *first_section;
223 PROFILESECTION **next_section;
224 PROFILEKEY *key, *prev_key, **next_key;
225
226 first_section = (PROFILESECTION *)HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
227 first_section->name = NULL;
228 first_section->key = NULL;
229 first_section->next = NULL;
230 next_section = &first_section->next;
231 next_key = &first_section->key;
232 prev_key = NULL;
233
234 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
235 {
236 line++;
237 p = buffer;
238 while (*p && PROFILE_isspace(*p)) p++;
239 if (*p == '[') /* section start */
240 {
241 if (!(p2 = strrchr( p, ']' )))
242 {
243 dprintf(("Kernel32:Profile:Invalid section header at line %d: '%s'\n",
244 line, p ));
245 }
246 else
247 {
248 *p2 = '\0';
249 p++;
250 section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
251 section->name = HEAP_strdupA( SystemHeap, 0, p );
252 section->key = NULL;
253 section->next = NULL;
254 *next_section = section;
255 next_section = &section->next;
256 next_key = &section->key;
257 prev_key = NULL;
258
259 dprintf(("Kernel32:Profile:New section: '%s'\n",section->name));
260
261 continue;
262 }
263 }
264
265 p2=p+strlen(p) - 1;
266 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
267
268 if ((p2 = strchr( p, '=' )) != NULL)
269 {
270 char *p3 = p2 - 1;
271 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
272 *p2++ = '\0';
273 while (*p2 && PROFILE_isspace(*p2)) p2++;
274 }
275
276 if(*p || !prev_key || *prev_key->name)
277 {
278 key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
279 key->name = HEAP_strdupA( SystemHeap, 0, p );
280 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
281 key->next = NULL;
282 *next_key = key;
283 next_key = &key->next;
284 prev_key = key;
285
286 dprintf(("Kernel32:Profile:New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)"));
287 }
288 }
289 return first_section;
290}
291
292
293/***********************************************************************
294 * PROFILE_DeleteSection
295 *
296 * Delete a section from a profile tree.
297 */
298static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
299{
300 while (*section)
301 {
302 if ((*section)->name && !strcasecmp( (*section)->name, name ))
303 {
304 PROFILESECTION *to_del = *section;
305 *section = to_del->next;
306 to_del->next = NULL;
307 PROFILE_Free( to_del );
308 return TRUE;
309 }
310 section = &(*section)->next;
311 }
312 return FALSE;
313}
314
315
316/***********************************************************************
317 * PROFILE_DeleteKey
318 *
319 * Delete a key from a profile tree.
320 */
321static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
322 LPCSTR section_name, LPCSTR key_name )
323{
324 while (*section)
325 {
326 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
327 {
328 PROFILEKEY **key = &(*section)->key;
329 while (*key)
330 {
331 if (!strcasecmp( (*key)->name, key_name ))
332 {
333 PROFILEKEY *to_del = *key;
334 *key = to_del->next;
335 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
336 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
337 HeapFree( SystemHeap, 0, to_del );
338 return TRUE;
339 }
340 key = &(*key)->next;
341 }
342 }
343 section = &(*section)->next;
344 }
345 return FALSE;
346}
347
348
349/***********************************************************************
350 * PROFILE_Find
351 *
352 * Find a key in a profile tree, optionally creating it.
353 */
354static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
355 const char *section_name,
356 const char *key_name, int create )
357{
358 while (*section)
359 {
360 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
361 {
362 PROFILEKEY **key = &(*section)->key;
363 while (*key)
364 {
365 if (!strcasecmp( (*key)->name, key_name )) return *key;
366 key = &(*key)->next;
367 }
368 if (!create) return NULL;
369 *key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
370 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
371 (*key)->value = NULL;
372 (*key)->next = NULL;
373 return *key;
374 }
375 section = &(*section)->next;
376 }
377 if (!create) return NULL;
378 *section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
379 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
380 (*section)->next = NULL;
381 (*section)->key = (tagPROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
382 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
383 (*section)->key->value = NULL;
384 (*section)->key->next = NULL;
385 return (*section)->key;
386}
387
388
389/***********************************************************************
390 * PROFILE_FlushFile
391 *
392 * Flush the current profile to disk if changed.
393 */
394static BOOL PROFILE_FlushFile(void)
395{
396 char *p, buffer[MAX_PATHNAME_LEN];
397 const char *unix_name;
398 FILE *file = NULL;
399 struct stat buf;
400
401 if(!CurProfile)
402 {
403 dprintf(("Kernel32:Profile:No current profile!\n"));
404 return FALSE;
405 }
406
407 if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
408 if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
409 {
410 /* Try to create it in $HOME/.wine */
411 /* FIXME: this will need a more general solution */
412 if ((p = getenv( "HOME" )) != NULL)
413 {
414 strcpy( buffer, p );
415 strcat( buffer, "/.wine/" );
416 p = buffer + strlen(buffer);
417 strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
418 CharLowerA( p );
419 file = fopen( buffer, "w" );
420 unix_name = buffer;
421 }
422 }
423
424 if (!file)
425 {
426 dprintf(("Kernel32:Profile:could not save profile file %s\n", CurProfile->dos_name));
427 return FALSE;
428 }
429
430 dprintf(("Kernel32:Profile:Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name ));
431 PROFILE_Save( file, CurProfile->section );
432 fclose( file );
433 CurProfile->changed = FALSE;
434 if(!stat(unix_name,&buf))
435 CurProfile->mtime=buf.st_mtime;
436 return TRUE;
437}
438
439
440/***********************************************************************
441 * PROFILE_ReleaseFile
442 *
443 * Flush the current profile to disk and remove it from the cache.
444 */
445static void PROFILE_ReleaseFile(void)
446{
447 PROFILE_FlushFile();
448 PROFILE_Free( CurProfile->section );
449 if (CurProfile->dos_name) HeapFree( SystemHeap, 0, CurProfile->dos_name );
450 if (CurProfile->unix_name) HeapFree( SystemHeap, 0, CurProfile->unix_name );
451 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
452 CurProfile->changed = FALSE;
453 CurProfile->section = NULL;
454 CurProfile->dos_name = NULL;
455 CurProfile->unix_name = NULL;
456 CurProfile->filename = NULL;
457 CurProfile->mtime = 0;
458}
459
460
461/***********************************************************************
462 * PROFILE_Open
463 *
464 * Open a profile file, checking the cached file first.
465 */
466static BOOL PROFILE_Open( LPCSTR filename )
467{
468 char buffer[MAX_PATHNAME_LEN];
469 char *newdos_name, *p;
470 FILE *file = NULL;
471 int i,j;
472 struct stat buf;
473 PROFILE *tempProfile;
474
475 /* First time around */
476
477 if(!CurProfile)
478 for(i=0;i<N_CACHED_PROFILES;i++)
479 {
480 MRUProfile[i]= (PROFILE*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );
481 MRUProfile[i]->changed=FALSE;
482 MRUProfile[i]->section=NULL;
483 MRUProfile[i]->dos_name=NULL;
484 MRUProfile[i]->unix_name=NULL;
485 MRUProfile[i]->filename=NULL;
486 MRUProfile[i]->mtime=0;
487 }
488
489 /* Check for a match */
490
491 if (!strchr( filename, '/' ) &&
492 !strchr( filename, '\\' ) &&
493 !strchr( filename, ':' ))
494 {
495 GetWindowsDirectoryA( buffer, sizeof(buffer) );
496 strcat( buffer, "\\" );
497 strcat( buffer, filename );
498 }
499
500 for(i=0;i<N_CACHED_PROFILES;i++)
501 {
502 if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )))
503 {
504 if(i)
505 {
506 PROFILE_FlushFile();
507 tempProfile=MRUProfile[i];
508 for(j=i;j>0;j--)
509 MRUProfile[j]=MRUProfile[j-1];
510 CurProfile=tempProfile;
511 }
512 if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
513 dprintf(("Kernel32:Profile:(%s): already opened (mru=%d)\n",
514 filename, i ));
515 else
516 dprintf(("Kernel32:Profile:(%s): already opened, needs refreshing (mru=%d)\n",
517 filename, i ));
518 return TRUE;
519 }
520 }
521
522 /* Rotate the oldest to the top to be replaced */
523
524 if(i==N_CACHED_PROFILES)
525 {
526 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
527 for(i=N_CACHED_PROFILES-1;i>0;i--)
528 MRUProfile[i]=MRUProfile[i-1];
529 CurProfile=tempProfile;
530 }
531
532 /* Flush the profile */
533
534 if(CurProfile->filename) PROFILE_ReleaseFile();
535
536 newdos_name = HEAP_strdupA( SystemHeap, 0, filename );
537 CurProfile->dos_name = newdos_name;
538 CurProfile->filename = HEAP_strdupA( SystemHeap, 0, filename );
539
540 /* Try to open the profile file, first in $HOME/.wine */
541
542 /* FIXME: this will need a more general solution */
543 if ((p = getenv( "HOME" )) != NULL)
544 {
545 strcpy( buffer, p );
546 strcat( buffer, "/.wine/" );
547 p = buffer + strlen(buffer);
548 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
549 CharLowerA( p );
550 if ((file = fopen( buffer, "r" )))
551 {
552 dprintf(("Kernel32:Profile:(%s): found it in %s\n",
553 filename, buffer ));
554 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
555 }
556 }
557
558 if (!file)
559 {
560 CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0,
561 filename );
562 if ((file = fopen( filename, "r" )))
563 dprintf(("Kernel32:Profile:(%s): found it in %s\n",
564 filename, filename ));
565 }
566
567 if (file)
568 {
569 CurProfile->section = PROFILE_Load( file );
570 fclose( file );
571 if(!stat(CurProfile->unix_name,&buf))
572 CurProfile->mtime=buf.st_mtime;
573 }
574 else
575 {
576 /* Does not exist yet, we will create it in PROFILE_FlushFile */
577 dprintf(("Kernel32:Profile:profile file %s not found\n", newdos_name ));
578 }
579 return TRUE;
580}
581
582
583/***********************************************************************
584 * PROFILE_GetSection
585 *
586 * Returns all keys of a section.
587 * If return_values is TRUE, also include the corresponding values.
588 */
589static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
590 LPSTR buffer, UINT len, BOOL handle_env,
591 BOOL return_values )
592{
593 PROFILEKEY *key;
594 while (section)
595 {
596 if (section->name && !strcasecmp( section->name, section_name ))
597 {
598 UINT oldlen = len;
599 for (key = section->key; key; key = key->next)
600 {
601 if (len <= 2) break;
602 if (!*key->name) continue; /* Skip empty lines */
603 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
604 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
605 len -= strlen(buffer) + 1;
606 buffer += strlen(buffer) + 1;
607 if (return_values && key->value) {
608 buffer[-1] = '=';
609 PROFILE_CopyEntry ( buffer,
610 key->value, len - 1, handle_env );
611 len -= strlen(buffer) + 1;
612 buffer += strlen(buffer) + 1;
613 }
614 }
615 *buffer = '\0';
616 if (len <= 1)
617 /*If either lpszSection or lpszKey is NULL and the supplied
618 destination buffer is too small to hold all the strings,
619 the last string is truncated and followed by two null characters.
620 In this case, the return value is equal to cchReturnBuffer
621 minus two. */
622 {
623 buffer[-1] = '\0';
624 return oldlen - 2;
625 }
626 return oldlen - len;
627 }
628 section = section->next;
629 }
630 buffer[0] = buffer[1] = '\0';
631 return 0;
632}
633
634
635static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
636{
637 LPSTR buf = buffer;
638 WORD l, cursize = 0;
639 PROFILESECTION *section;
640
641 for (section = CurProfile->section; section; section = section->next)
642 if (section->name) {
643 l = strlen(section->name);
644 cursize += l+1;
645 if (cursize > len+1)
646 return len-2;
647
648 strcpy(buf, section->name);
649 buf += l+1;
650 }
651
652 *buf=0;
653 buf++;
654 return buf-buffer;
655}
656
657
658/***********************************************************************
659 * PROFILE_GetString
660 *
661 * Get a profile string.
662 */
663static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
664 LPCSTR def_val, LPSTR buffer, UINT len )
665{
666 PROFILEKEY *key = NULL;
667
668 if (!def_val) def_val = "";
669 if (key_name && key_name[0])
670 {
671 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
672 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
673 len, FALSE );
674 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",
675 section, key_name, def_val, buffer ));
676 return strlen( buffer );
677 }
678 if (section && section[0])
679 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
680 FALSE, FALSE);
681 /* undocumented; both section and key_name are NULL */
682 return PROFILE_GetSectionNames(buffer, len);
683}
684
685
686/***********************************************************************
687 * PROFILE_SetString
688 *
689 * Set a profile string.
690 */
691static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
692 LPCSTR value )
693{
694 if (!key_name) /* Delete a whole section */
695 {
696 dprintf(("Kernel32:Profile:('%s')\n", section_name));
697 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
698 section_name );
699 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
700 this is not an error on application's level.*/
701 }
702 else if (!value) /* Delete a key */
703 {
704 dprintf(("Kernel32:Profile:('%s','%s')\n",
705 section_name, key_name ));
706 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
707 section_name, key_name );
708 return TRUE; /* same error handling as above */
709 }
710 else /* Set the key value */
711 {
712 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
713 key_name, TRUE );
714 dprintf(("Kernel32:Profile:('%s','%s','%s'): \n",
715 section_name, key_name, value ));
716 if (!key) return FALSE;
717 if (key->value)
718 {
719 if (!strcmp( key->value, value ))
720 {
721 dprintf(("Kernel32:Profile: no change needed\n" ));
722 return TRUE; /* No change needed */
723 }
724 dprintf(("Kernel32:Profile: replacing '%s'\n", key->value ));
725 HeapFree( SystemHeap, 0, key->value );
726 }
727 else dprintf(("Kernel32:Profile: creating key\n" ));
728 key->value = HEAP_strdupA( SystemHeap, 0, value );
729 CurProfile->changed = TRUE;
730 }
731 return TRUE;
732}
733
734
735/***********************************************************************
736 * PROFILE_GetWineIniString
737 *
738 * Get a config string from the wine.ini file.
739 */
740int PROFILE_GetWineIniString( const char *section, const char *key_name,
741 const char *def, char *buffer, int len )
742{
743 int ret;
744
745 EnterCriticalSection( &PROFILE_CritSect );
746
747 if (key_name)
748 {
749 PROFILEKEY *key = PROFILE_Find(&PROFILE_WineProfile, section, key_name, FALSE);
750 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
751 len, TRUE );
752 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",
753 section, key_name, def, buffer ));
754 ret = strlen( buffer );
755 }
756 else
757 {
758 ret = PROFILE_GetSection( PROFILE_WineProfile, section, buffer, len, TRUE, FALSE );
759 }
760 LeaveCriticalSection( &PROFILE_CritSect );
761
762 return ret;
763}
764
765
766/***********************************************************************
767 * PROFILE_GetWineIniInt
768 *
769 * Get a config integer from the wine.ini file.
770 */
771int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
772{
773 char buffer[20];
774 char *p;
775 long result;
776 PROFILEKEY *key;
777 int ret;
778
779 EnterCriticalSection( &PROFILE_CritSect );
780
781 key = PROFILE_Find( &PROFILE_WineProfile, section, key_name, FALSE );
782 if (!key || !key->value) {
783 ret = def;
784 } else {
785 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
786 result = strtol( buffer, &p, 0 );
787 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result;
788 }
789
790 LeaveCriticalSection( &PROFILE_CritSect );
791
792 return ret;
793}
794
795
796/******************************************************************************
797 *
798 * int PROFILE_EnumerateWineIniSection(
799 * char const *section, #Name of the section to enumerate
800 * void (*cbfn)(char const *key, char const *value, void *user),
801 * # Address of the callback function
802 * void *user ) # User-specified pointer.
803 *
804 * For each entry in a section in the wine.conf file, this function will
805 * call the specified callback function, informing it of each key and
806 * value. An optional user pointer may be passed to it (if this is not
807 * needed, pass NULL through it and ignore the value in the callback
808 * function).
809 *
810 * The callback function must accept three parameters:
811 * The name of the key (char const *)
812 * The value of the key (char const *)
813 * A user-specified parameter (void *)
814 * Note that the first two are char CONST *'s, not char *'s! The callback
815 * MUST not modify these strings!
816 *
817 * The return value indicates the number of times the callback function
818 * was called.
819 */
820int PROFILE_EnumerateWineIniSection(
821 char const *section,
822 void (*cbfn)(char const *, char const *, void *),
823 void *userptr )
824{
825 PROFILESECTION *scansect;
826 PROFILEKEY *scankey;
827 int calls = 0;
828
829 EnterCriticalSection( &PROFILE_CritSect );
830
831 /* Search for the correct section */
832 for(scansect = PROFILE_WineProfile; scansect; scansect = scansect->next) {
833 if(scansect->name && !strcasecmp(scansect->name, section)) {
834
835 /* Enumerate each key with the callback */
836 for(scankey = scansect->key; scankey; scankey = scankey->next) {
837
838 /* Ignore blank entries -- these shouldn't exist, but let's
839 be extra careful */
840 if(scankey->name[0]) {
841 cbfn(scankey->name, scankey->value, userptr);
842 ++calls;
843 }
844 }
845
846 break;
847 }
848 }
849 LeaveCriticalSection( &PROFILE_CritSect );
850
851 return calls;
852}
853
854
855/******************************************************************************
856 *
857 * int PROFILE_GetWineIniBool(
858 * char const *section,
859 * char const *key_name,
860 * int def )
861 *
862 * Reads a boolean value from the wine.ini file. This function attempts to
863 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
864 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
865 * true. Anything else results in the return of the default value.
866 *
867 * This function uses 1 to indicate true, and 0 for false. You can check
868 * for existence by setting def to something other than 0 or 1 and
869 * examining the return value.
870 */
871int PROFILE_GetWineIniBool(
872 char const *section,
873 char const *key_name,
874 int def )
875{
876 char key_value[2];
877 int retval;
878
879 PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
880
881 switch(key_value[0]) {
882 case 'n':
883 case 'N':
884 case 'f':
885 case 'F':
886 case '0':
887 retval = 0;
888 break;
889
890 case 'y':
891 case 'Y':
892 case 't':
893 case 'T':
894 case '1':
895 retval = 1;
896 break;
897
898 default:
899 retval = def;
900 }
901
902 dprintf(("Kernel32:Profile:(\"%s\", \"%s\", %s), "
903 "[%c], ret %s.\n", section, key_name,
904 def ? "TRUE" : "FALSE", key_value[0],
905 retval ? "TRUE" : "FALSE"));
906
907 return retval;
908}
909
910
911#if 0
912/***********************************************************************
913 * PROFILE_LoadWineIni
914 *
915 * Load the wine.ini file.
916 */
917int PROFILE_LoadWineIni(void)
918{
919 char buffer[MAX_PATHNAME_LEN];
920 const char *p;
921 FILE *f;
922
923 InitializeCriticalSection( &PROFILE_CritSect );
924 MakeCriticalSectionGlobal( &PROFILE_CritSect );
925
926 if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
927 {
928 /* Open -config specified file */
929 PROFILE_WineProfile = PROFILE_Load ( f);
930 fclose ( f );
931 strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);
932 return 1;
933 }
934
935 if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
936 {
937 PROFILE_WineProfile = PROFILE_Load( f );
938 fclose( f );
939 strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);
940 return 1;
941 }
942 if ((p = getenv( "HOME" )) != NULL)
943 {
944 lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
945 strcat( buffer, PROFILE_WineIniName );
946 if ((f = fopen( buffer, "r" )) != NULL)
947 {
948 PROFILE_WineProfile = PROFILE_Load( f );
949 fclose( f );
950 strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);
951 return 1;
952 }
953 }
954 else dprintf(("Kernel32:Profile:could not get $HOME value for config file.\n" ));
955
956 /* Try global file */
957
958 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
959 {
960 PROFILE_WineProfile = PROFILE_Load( f );
961 fclose( f );
962 strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);
963 return 1;
964 }
965 MESSAGE( "Can't open configuration file %s or $HOME%s\n",
966 WINE_INI_GLOBAL, PROFILE_WineIniName );
967 return 0;
968}
969
970
971/***********************************************************************
972 * PROFILE_UsageWineIni
973 *
974 * Explain the wine.ini file to those who don't read documentation.
975 * Keep below one screenful in length so that error messages above are
976 * noticed.
977 */
978void PROFILE_UsageWineIni(void)
979{
980 MESSAGE("Perhaps you have not properly edited or created "
981 "your Wine configuration file.\n");
982 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
983 MESSAGE(" or it is determined by the -config option or from\n"
984 " the WINE_INI environment variable.\n");
985 if (*PROFILE_WineIniUsed)
986 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
987 /* RTFM, so to say */
988}
989#endif
990
991/***********************************************************************
992 * PROFILE_GetStringItem
993 *
994 * Convenience function that turns a string 'xxx, yyy, zzz' into
995 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
996 */
997char* PROFILE_GetStringItem( char* start )
998{
999 char* lpchX, *lpch;
1000
1001 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
1002 {
1003 if( *lpchX == ',' )
1004 {
1005 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
1006 while( *(++lpchX) )
1007 if( !PROFILE_isspace(*lpchX) ) return lpchX;
1008 }
1009 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
1010 else lpch = NULL;
1011 }
1012 if( lpch ) *lpch = '\0';
1013 return NULL;
1014}
1015
1016/********************* API functions **********************************/
1017
1018/***********************************************************************
1019 * GetProfileInt32A (KERNEL32.264)
1020 */
1021UINT WINAPI GetProfileIntA( LPCSTR section, LPCSTR entry, INT def_val )
1022{
1023 return GetPrivateProfileIntA( section, entry, def_val, "win.ini" );
1024}
1025
1026/***********************************************************************
1027 * GetProfileInt32W (KERNEL32.264)
1028 */
1029UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )
1030{
1031 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1032 return GetPrivateProfileIntW( section, entry, def_val, wininiW );
1033}
1034
1035/***********************************************************************
1036 * GetProfileString32A (KERNEL32.268)
1037 */
1038INT WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,
1039 LPSTR buffer, UINT len )
1040{
1041 return GetPrivateProfileStringA( section, entry, def_val,
1042 buffer, len, "win.ini" );
1043}
1044
1045/***********************************************************************
1046 * GetProfileString32W (KERNEL32.269)
1047 */
1048INT WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry,
1049 LPCWSTR def_val, LPWSTR buffer, UINT len )
1050{
1051 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1052 return GetPrivateProfileStringW( section, entry, def_val,
1053 buffer, len, wininiW );
1054}
1055
1056/***********************************************************************
1057 * WriteProfileString32A (KERNEL32.587)
1058 */
1059BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry,
1060 LPCSTR string )
1061{
1062 return WritePrivateProfileStringA( section, entry, string, "win.ini" );
1063}
1064
1065/***********************************************************************
1066 * WriteProfileString32W (KERNEL32.588)
1067 */
1068BOOL WINAPI WriteProfileStringW( LPCWSTR section, LPCWSTR entry,
1069 LPCWSTR string )
1070{
1071 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1072 return WritePrivateProfileStringW( section, entry, string, wininiW );
1073}
1074
1075/***********************************************************************
1076 * GetPrivateProfileInt32A (KERNEL32.251)
1077 */
1078UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
1079 INT def_val, LPCSTR filename )
1080{
1081 char buffer[20];
1082 char *p;
1083 long result;
1084
1085 GetPrivateProfileStringA( section, entry, "",
1086 buffer, sizeof(buffer), filename );
1087 if (!buffer[0]) return (UINT)def_val;
1088 result = strtol( buffer, &p, 0 );
1089 if (p == buffer) return 0; /* No digits at all */
1090 return (UINT)result;
1091}
1092
1093/***********************************************************************
1094 * GetPrivateProfileInt32W (KERNEL32.252)
1095 */
1096UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,
1097 INT def_val, LPCWSTR filename )
1098{
1099 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1100 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1101 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1102 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
1103 HeapFree( GetProcessHeap(), 0, sectionA );
1104 HeapFree( GetProcessHeap(), 0, filenameA );
1105 HeapFree( GetProcessHeap(), 0, entryA );
1106 return res;
1107}
1108
1109/***********************************************************************
1110 * GetPrivateProfileString32A (KERNEL32.255)
1111 */
1112INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
1113 LPCSTR def_val, LPSTR buffer,
1114 UINT len, LPCSTR filename )
1115{
1116 int ret;
1117
1118 if (!filename)
1119 filename = "win.ini";
1120
1121 EnterCriticalSection( &PROFILE_CritSect );
1122
1123 if (PROFILE_Open( filename )) {
1124 ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1125 } else {
1126 lstrcpynA( buffer, def_val, len );
1127 ret = strlen( buffer );
1128 }
1129
1130 LeaveCriticalSection( &PROFILE_CritSect );
1131
1132 return ret;
1133}
1134
1135/***********************************************************************
1136 * GetPrivateProfileString32W (KERNEL32.256)
1137 */
1138INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
1139 LPCWSTR def_val, LPWSTR buffer,
1140 UINT len, LPCWSTR filename )
1141{
1142 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1143 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1144 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1145 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1146 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1147 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
1148 bufferA, len, filenameA );
1149 lstrcpynAtoW( buffer, bufferA, len );
1150 HeapFree( GetProcessHeap(), 0, sectionA );
1151 HeapFree( GetProcessHeap(), 0, entryA );
1152 HeapFree( GetProcessHeap(), 0, filenameA );
1153 HeapFree( GetProcessHeap(), 0, def_valA );
1154 HeapFree( GetProcessHeap(), 0, bufferA);
1155 return ret;
1156}
1157
1158/***********************************************************************
1159 * GetPrivateProfileSection32A (KERNEL32.255)
1160 */
1161INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,
1162 DWORD len, LPCSTR filename )
1163{
1164 int ret = 0;
1165
1166 EnterCriticalSection( &PROFILE_CritSect );
1167
1168 if (PROFILE_Open( filename ))
1169 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
1170 FALSE, TRUE);
1171
1172 LeaveCriticalSection( &PROFILE_CritSect );
1173
1174 return ret;
1175}
1176
1177/***********************************************************************
1178 * GetPrivateProfileSection32W (KERNEL32.256)
1179 */
1180
1181INT WINAPI GetPrivateProfileSectionW (LPCWSTR section, LPWSTR buffer,
1182 DWORD len, LPCWSTR filename )
1183
1184{
1185 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1186 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1187 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1188 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
1189 filenameA );
1190 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
1191 HeapFree( GetProcessHeap(), 0, sectionA );
1192 HeapFree( GetProcessHeap(), 0, filenameA );
1193 HeapFree( GetProcessHeap(), 0, bufferA);
1194 return ret;
1195}
1196
1197/***********************************************************************
1198 * GetProfileSection32A (KERNEL32.268)
1199 */
1200INT WINAPI GetProfileSectionA( LPCSTR section, LPSTR buffer, DWORD len )
1201{
1202 return GetPrivateProfileSectionA( section, buffer, len, "win.ini" );
1203}
1204
1205/***********************************************************************
1206 * GetProfileSection32W (KERNEL32)
1207 */
1208INT WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len )
1209{
1210 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
1211 return GetPrivateProfileSectionW( section, buffer, len, wininiW );
1212}
1213
1214/***********************************************************************
1215 * WritePrivateProfileString32A (KERNEL32.582)
1216 */
1217BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
1218 LPCSTR string, LPCSTR filename )
1219{
1220 BOOL ret = FALSE;
1221
1222 EnterCriticalSection( &PROFILE_CritSect );
1223
1224 if (PROFILE_Open( filename ))
1225 {
1226 if (!section && !entry && !string)
1227 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1228 else
1229 ret = PROFILE_SetString( section, entry, string );
1230 }
1231
1232 LeaveCriticalSection( &PROFILE_CritSect );
1233 return ret;
1234}
1235
1236/***********************************************************************
1237 * WritePrivateProfileString32W (KERNEL32.583)
1238 */
1239BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
1240 LPCWSTR string, LPCWSTR filename )
1241{
1242 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1243 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1244 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1245 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1246 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
1247 stringA, filenameA );
1248 HeapFree( GetProcessHeap(), 0, sectionA );
1249 HeapFree( GetProcessHeap(), 0, entryA );
1250 HeapFree( GetProcessHeap(), 0, stringA );
1251 HeapFree( GetProcessHeap(), 0, filenameA );
1252 return res;
1253}
1254
1255/***********************************************************************
1256 * WritePrivateProfileSection32A (KERNEL32)
1257 */
1258BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section,
1259 LPCSTR string, LPCSTR filename )
1260{
1261 char *p =(char*)string;
1262
1263 dprintf(("Kernel32:Profile:fixme WritePrivateProfileSection32A empty stub\n"));
1264 return FALSE;
1265}
1266
1267/***********************************************************************
1268 * WritePrivateProfileSection32W (KERNEL32)
1269 */
1270BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
1271 LPCWSTR string, LPCWSTR filename)
1272
1273{
1274 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1275 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1276 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1277 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
1278 HeapFree( GetProcessHeap(), 0, sectionA );
1279 HeapFree( GetProcessHeap(), 0, stringA );
1280 HeapFree( GetProcessHeap(), 0, filenameA );
1281 return res;
1282}
1283
1284/***********************************************************************
1285 * WriteProfileSection32A (KERNEL32.747)
1286 */
1287BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values)
1288
1289{
1290 return WritePrivateProfileSectionA( section, keys_n_values, "win.ini");
1291}
1292
1293/***********************************************************************
1294 * WriteProfileSection32W (KERNEL32.748)
1295 */
1296BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values)
1297{
1298 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini");
1299
1300 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW));
1301}
1302
1303/***********************************************************************
1304 * GetPrivateProfileSectionNames16 (KERNEL.143)
1305 */
1306WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
1307 LPCSTR filename )
1308{
1309 WORD ret = 0;
1310
1311 EnterCriticalSection( &PROFILE_CritSect );
1312
1313 if (PROFILE_Open( filename ))
1314 ret = PROFILE_GetSectionNames(buffer, size);
1315
1316 LeaveCriticalSection( &PROFILE_CritSect );
1317
1318 return ret;
1319}
1320
1321/***********************************************************************
1322 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1323 */
1324DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,
1325 LPCSTR filename)
1326
1327{
1328 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1329}
1330
1331/***********************************************************************
1332 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1333 */
1334DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
1335 LPCWSTR filename)
1336
1337{
1338 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1339 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size);
1340
1341 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1342 lstrcpynAtoW( buffer, bufferA, size);
1343 HeapFree( GetProcessHeap(), 0, bufferA);
1344 HeapFree( GetProcessHeap(), 0, filenameA );
1345
1346 return ret;
1347}
1348
1349/***********************************************************************
1350 * GetPrivateProfileStruct32A (KERNEL32.370)
1351 */
1352BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
1353 LPVOID buf, UINT len, LPCSTR filename)
1354{
1355 BOOL ret = FALSE;
1356
1357 EnterCriticalSection( &PROFILE_CritSect );
1358
1359 if (PROFILE_Open( filename )) {
1360 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1361 if (k) {
1362 lstrcpynA( buf, k->value, strlen(k->value));
1363 ret = TRUE;
1364 }
1365 }
1366 LeaveCriticalSection( &PROFILE_CritSect );
1367
1368 return FALSE;
1369}
1370
1371/***********************************************************************
1372 * GetPrivateProfileStruct32W (KERNEL32.543)
1373 */
1374BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
1375 LPVOID buffer, UINT len, LPCWSTR filename)
1376{
1377 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1378 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1379 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1380 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1381
1382 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
1383 len, filenameA );
1384 lstrcpynAtoW( buffer, bufferA, len );
1385 HeapFree( GetProcessHeap(), 0, bufferA);
1386 HeapFree( GetProcessHeap(), 0, sectionA );
1387 HeapFree( GetProcessHeap(), 0, keyA );
1388 HeapFree( GetProcessHeap(), 0, filenameA );
1389
1390 return ret;
1391}
1392
1393
1394/***********************************************************************
1395 * WritePrivateProfileStruct32A (KERNEL32.744)
1396 */
1397BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
1398 LPVOID buf, UINT bufsize, LPCSTR filename)
1399{
1400 BOOL ret = FALSE;
1401
1402 if (!section && !key && !buf) /* flush the cache */
1403 return WritePrivateProfileStringA( NULL, NULL, NULL, filename );
1404
1405 EnterCriticalSection( &PROFILE_CritSect );
1406
1407 if (PROFILE_Open( filename ))
1408 ret = PROFILE_SetString( section, key, (LPCSTR)buf );
1409
1410 LeaveCriticalSection( &PROFILE_CritSect );
1411
1412 return ret;
1413}
1414
1415/***********************************************************************
1416 * WritePrivateProfileStruct32W (KERNEL32.544)
1417 */
1418BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
1419 LPVOID buf, UINT bufsize, LPCWSTR filename)
1420{
1421 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1422 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1423 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1424 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
1425 filenameA );
1426 HeapFree( GetProcessHeap(), 0, sectionA );
1427 HeapFree( GetProcessHeap(), 0, keyA );
1428 HeapFree( GetProcessHeap(), 0, filenameA );
1429
1430 return ret;
1431}
Note: See TracBrowser for help on using the repository browser.