source: trunk/src/kernel32/old/profile.cpp@ 1036

Last change on this file since 1036 was 955, checked in by sandervl, 26 years ago

Backup copy of old kernel32

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