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

Last change on this file since 10574 was 10574, checked in by sandervl, 21 years ago

Profile: flush ini file after write actions

File size: 51.0 KB
Line 
1/* $Id: profile.cpp,v 1.37 2004-04-07 09:13:53 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 "winuser.h"
29#include "winnls.h"
30
31#include "profile.h"
32
33#define DBG_LOCALLOG DBG_profile
34#include "dbglocal.h"
35
36#include "initterm.h"
37
38ODINDEBUGCHANNEL(KERNEL32-PROFILE)
39
40
41// -------------------------
42// WINE compatibility macros
43// -------------------------
44
45#ifndef MAX_PATHNAME_LEN
46#define MAX_PATHNAME_LEN 260
47#endif
48
49#define SystemHeap GetProcessHeap()
50#define DOSFS_GetFullName(a,b,c) strcpy(c,a)
51
52
53typedef struct tagPROFILEKEY
54{
55 char *name;
56 char *value;
57 struct tagPROFILEKEY *next;
58} PROFILEKEY;
59
60typedef struct tagPROFILESECTION
61{
62 char *name;
63 struct tagPROFILEKEY *key;
64 struct tagPROFILESECTION *next;
65} PROFILESECTION;
66
67
68typedef struct
69{
70 BOOL changed;
71 PROFILESECTION *section;
72 char *filename; //first open name
73 char *fullname; //name with path
74 time_t mtime;
75} PROFILEROOT;
76
77
78
79#define N_CACHED_PROFILES 10
80
81/* Cached profile files */
82static PROFILEROOT *MRUProfile[N_CACHED_PROFILES]={NULL};
83
84#define CurProfile (MRUProfile[0])
85
86/* ODIN.INI profile content */
87BOOL OdinProfileChanged = FALSE;
88static PROFILESECTION *PROFILE_OdinProfile = NULL;
89
90#define PROFILE_MAX_LINE_LEN 1024
91#define WINININAME "WIN.INI"
92
93/* Odin profile: the profile file being used */
94static char PROFILE_OdinIniUsed[MAX_PATHNAME_LEN] = "";
95
96/* Check for comments in profile */
97#define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
98
99static LPCWSTR wininiW = NULL;
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 dprintf2(("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 dprintf2(("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 * PROFILE_DeleteKey
313 *
314 * Delete a key from a profile tree.
315 */
316static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
317 LPCSTR section_name, LPCSTR key_name )
318{
319 while (*section)
320 {
321 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
322 {
323 PROFILEKEY **key = &(*section)->key;
324 while (*key)
325 {
326 if (!strcasecmp( (*key)->name, key_name ))
327 {
328 PROFILEKEY *to_del = *key;
329 *key = to_del->next;
330 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
331 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
332 HeapFree( SystemHeap, 0, to_del );
333 return TRUE;
334 }
335 key = &(*key)->next;
336 }
337 }
338 section = &(*section)->next;
339 }
340 return FALSE;
341}
342
343/***********************************************************************
344 * PROFILE_DeleteAllKeys
345 *
346 * Delete all keys from a profile tree.
347 */
348void PROFILE_DeleteAllKeys( LPCSTR section_name)
349{
350 PROFILESECTION **section= &CurProfile->section;
351 while (*section)
352 {
353 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
354 {
355 PROFILEKEY **key = &(*section)->key;
356 while (*key)
357 {
358 PROFILEKEY *to_del = *key;
359 *key = to_del->next;
360 if (to_del->name) HeapFree( GetProcessHeap(), 0, to_del->name );
361 if (to_del->value) HeapFree( GetProcessHeap(), 0, to_del->value);
362 HeapFree( GetProcessHeap(), 0, to_del );
363 CurProfile->changed =TRUE;
364 }
365 }
366 section = &(*section)->next;
367 }
368}
369
370/***********************************************************************
371 * PROFILE_Find
372 *
373 * Find a key in a profile tree, optionally creating it.
374 */
375static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
376 const char *section_name,
377 const char *key_name, int create )
378{
379 while (*section)
380 {
381 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
382 {
383 PROFILEKEY **key = &(*section)->key;
384 while (*key)
385 {
386 if (!strcasecmp( (*key)->name, key_name )) return *key;
387 key = &(*key)->next;
388 }
389 if (!create) return NULL;
390 *key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
391 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
392 (*key)->value = NULL;
393 (*key)->next = NULL;
394 return *key;
395 }
396 section = &(*section)->next;
397 }
398 if (!create) return NULL;
399 *section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
400 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
401 (*section)->next = NULL;
402 (*section)->key = (tagPROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
403 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
404 (*section)->key->value = NULL;
405 (*section)->key->next = NULL;
406 return (*section)->key;
407}
408
409
410/***********************************************************************
411 * PROFILE_FlushFile
412 *
413 * Flush the current profile to disk if changed.
414 */
415static BOOL PROFILE_FlushFile(void)
416{
417 FILE *file = NULL;
418 struct stat buf;
419
420 if(!CurProfile)
421 {
422 dprintf(("Kernel32:Profile:No current profile!\n"));
423 return FALSE;
424 }
425
426 // not changed, return immediately
427 if (!CurProfile->changed)
428 return TRUE;
429
430 // try to open file
431 file = fopen(CurProfile->fullname, "w");
432 if (!file)
433 {
434 dprintf(("Kernel32:Profile:could not save profile file %s\n", CurProfile->fullname));
435 return FALSE;
436 }
437
438 dprintf(("Kernel32:Profile:Saving %s\n", CurProfile->fullname ));
439 PROFILE_Save( file, CurProfile->section );
440 fclose( file );
441 CurProfile->changed = FALSE;
442 if(!stat(CurProfile->fullname,&buf))
443 CurProfile->mtime=buf.st_mtime;
444 return TRUE;
445}
446
447
448/***********************************************************************
449 * PROFILE_ReleaseFile
450 *
451 * Flush the current profile to disk and remove it from the cache.
452 */
453static void PROFILE_ReleaseFile(void)
454{
455 PROFILE_FlushFile();
456 PROFILE_Free( CurProfile->section );
457 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
458 if (CurProfile->fullname) HeapFree(SystemHeap,0,CurProfile->fullname);
459 CurProfile->changed = FALSE;
460 CurProfile->section = NULL;
461 CurProfile->filename = NULL;
462 CurProfile->fullname = NULL;
463 CurProfile->mtime = 0;
464}
465
466
467/***********************************************************************
468 * PROFILE_Open
469 *
470 * Open a profile file, checking the cached file first.
471 */
472static BOOL PROFILE_Open( LPCSTR filename )
473{
474 FILE *file = NULL;
475 int i,j;
476 struct stat buf;
477 PROFILEROOT *tempProfile;
478
479 if (!filename || filename[0] == 0) return FALSE;
480
481 /* First time around */
482
483 if(!CurProfile)
484 for(i=0;i<N_CACHED_PROFILES;i++)
485 {
486 MRUProfile[i]= (PROFILEROOT*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEROOT) );
487 MRUProfile[i]->changed=FALSE;
488 MRUProfile[i]->section=NULL;
489 MRUProfile[i]->filename=NULL;
490 MRUProfile[i]->fullname=NULL;
491 MRUProfile[i]->mtime=0;
492 }
493
494 /* Check for a match */
495
496 for(i=0;i<N_CACHED_PROFILES;i++)
497 {
498 if (MRUProfile[i]->filename && (!stricmp(filename,MRUProfile[i]->filename) || !stricmp(filename,MRUProfile[i]->fullname)))
499 {
500 if(i)
501 {
502 PROFILE_FlushFile();
503 tempProfile=MRUProfile[i];
504 for(j=i;j>0;j--)
505 MRUProfile[j]=MRUProfile[j-1];
506 CurProfile=tempProfile;
507 }
508 if(!stat(CurProfile->fullname,&buf) && CurProfile->mtime==buf.st_mtime)
509 dprintf(("Kernel32:Profile:(%s): already opened (mru=%d)\n",
510 filename, i ));
511 else
512 dprintf(("Kernel32:Profile:(%s): already opened, needs refreshing (mru=%d)\n",
513 filename, i ));
514 return TRUE;
515 }
516 }
517
518 /* Rotate the oldest to the top to be replaced */
519
520 if(i==N_CACHED_PROFILES)
521 {
522 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
523 for(i=N_CACHED_PROFILES-1;i>0;i--)
524 MRUProfile[i]=MRUProfile[i-1];
525 CurProfile=tempProfile;
526 }
527
528 /* Flush the profile */
529
530 if(CurProfile->filename) PROFILE_ReleaseFile();
531
532 CurProfile->filename = HEAP_strdupA(SystemHeap,0,filename);
533
534 /* check for path */
535
536 if ((!strchr( filename,'/') &&
537 !strchr( filename,'\\')) ||
538 !strchr( filename,':'))
539 {
540 char fullname[MAX_PATHNAME_LEN];
541
542 GetWindowsDirectoryA(fullname,sizeof(fullname));
543 strcat(fullname,"\\");
544 strcat(fullname,filename);
545 CurProfile->fullname = HEAP_strdupA(SystemHeap,0,fullname);
546 } else CurProfile->fullname = HEAP_strdupA(SystemHeap,0,filename);
547
548 file = fopen(CurProfile->fullname,"r");
549 if (file)
550 {
551 dprintf(("Kernel32:Profile:(%s): found it in %s\n",
552 filename, CurProfile->fullname ));
553
554 CurProfile->section = PROFILE_Load( file );
555 fclose( file );
556 if(!stat(CurProfile->fullname,&buf))
557 CurProfile->mtime=buf.st_mtime;
558 }
559 else
560 {
561 /* Does not exist yet, we will create it in PROFILE_FlushFile */
562 dprintf(("Kernel32:Profile:profile file %s not found\n", CurProfile->fullname ));
563 }
564 return TRUE;
565}
566
567
568/***********************************************************************
569 * PROFILE_GetSection
570 *
571 * Returns all keys of a section.
572 * If return_values is TRUE, also include the corresponding values.
573 */
574static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
575 LPSTR buffer, UINT len, BOOL handle_env,
576 BOOL return_values )
577{
578 PROFILEKEY *key;
579 while (section)
580 {
581 if (section->name && !strcasecmp( section->name, section_name ))
582 {
583 UINT oldlen = len;
584 for (key = section->key; key; key = key->next)
585 {
586 if (len <= 2) break;
587 if (!*key->name) continue; /* Skip empty lines */
588 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
589 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
590
591#ifdef __WIN32OS2__
592 /* CW: This fixes a crash in Windows Media Player setup where GetPrivateProfileSectionA() is called with len=5
593 which is not enough for holding any key name. */
594 if(strlen(key->name)>len-2) {
595 buffer += len-1;
596 len=1; /* Causes the funktion to end with a return code of len-2 */
597 break;
598 }
599 /*****************************************/
600#endif
601
602 len -= strlen(buffer) + 1;
603 buffer += strlen(buffer) + 1;
604 if (return_values && key->value) {
605 buffer[-1] = '=';
606 PROFILE_CopyEntry ( buffer,
607 key->value, len - 1, handle_env );
608
609#ifdef __WIN32OS2__
610 /* CW: This is the same as above for the keyname. I don't have a crashing app to prove this code but
611 expect the same problem as with the key name if the len is to short. */
612 if(strlen(key->value)>len-2) {
613 buffer += len;
614 len=1;
615 break;
616 }
617 /*****************************************/
618#endif
619
620 len -= strlen(buffer) + 1;
621 buffer += strlen(buffer) + 1;
622 }
623 }
624 *buffer = '\0';
625 if (len <= 1)
626 /*If either lpszSection or lpszKey is NULL and the supplied
627 destination buffer is too small to hold all the strings,
628 the last string is truncated and followed by two null characters.
629 In this case, the return value is equal to cchReturnBuffer
630 minus two. */
631 {
632 buffer[-1] = '\0';
633 return oldlen - 2;
634 }
635 return oldlen - len;
636 }
637 section = section->next;
638 }
639 buffer[0] = buffer[1] = '\0';
640 return 0;
641}
642
643
644static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
645{
646 LPSTR buf = buffer;
647 WORD l, cursize = 0;
648 PROFILESECTION *section;
649
650 for (section = CurProfile->section; section; section = section->next)
651 if (section->name) {
652 l = strlen(section->name);
653 cursize += l+1;
654 if (cursize > len+1)
655 return len-2;
656
657 strcpy(buf, section->name);
658 buf += l+1;
659 }
660
661 *buf=0;
662 buf++;
663 return buf-buffer;
664}
665
666
667/***********************************************************************
668 * PROFILE_GetString
669 *
670 * Get a profile string.
671 */
672static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
673 LPCSTR def_val, LPSTR buffer, UINT len )
674{
675 PROFILEKEY *key = NULL;
676
677 if (!def_val) def_val = "";
678 if (key_name && key_name[0])
679 {
680 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
681 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
682 len, FALSE );
683 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",
684 section, key_name, def_val, buffer ));
685 return strlen( buffer );
686 }
687 if (section && section[0])
688 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
689 FALSE, FALSE);
690 /* undocumented; both section and key_name are NULL */
691 return PROFILE_GetSectionNames(buffer, len);
692}
693
694
695/***********************************************************************
696 * PROFILE_SetString
697 *
698 * Set a profile string.
699 */
700static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
701 LPCSTR value )
702{
703 if (!key_name) /* Delete a whole section */
704 {
705 dprintf(("Kernel32:Profile:('%s')\n", section_name));
706 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
707 section_name );
708 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
709 this is not an error on application's level.*/
710 }
711 else if (!value) /* Delete a key */
712 {
713 dprintf(("Kernel32:Profile:('%s','%s')\n",
714 section_name, key_name ));
715 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
716 section_name, key_name );
717 return TRUE; /* same error handling as above */
718 }
719 else /* Set the key value */
720 {
721 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
722 key_name, TRUE );
723 dprintf(("Kernel32:Profile:('%s','%s','%s'): \n",
724 section_name, key_name, value ));
725 if (!key) return FALSE;
726 if (key->value)
727 {
728 if (!strcmp( key->value, value ))
729 {
730 dprintf(("Kernel32:Profile: no change needed\n" ));
731 return TRUE; /* No change needed */
732 }
733 dprintf(("Kernel32:Profile: replacing '%s'\n", key->value ));
734 HeapFree( SystemHeap, 0, key->value );
735 }
736 else dprintf(("Kernel32:Profile: creating key\n" ));
737 key->value = HEAP_strdupA( SystemHeap, 0, value );
738 CurProfile->changed = TRUE;
739 }
740 return TRUE;
741}
742
743
744/***********************************************************************
745 * PROFILE_GetOdinIniString
746 *
747 * Get a config string from the odin.ini file.
748 */
749int WIN32API PROFILE_GetOdinIniString(LPCSTR section, LPCSTR key_name,
750 LPCSTR def, LPSTR buffer, UINT len)
751{
752 int ret;
753
754 EnterCriticalSection( &PROFILE_CritSect );
755
756 if (key_name)
757 {
758 PROFILEKEY *key = PROFILE_Find(&PROFILE_OdinProfile, section, key_name, FALSE);
759 PROFILE_CopyEntry( (char*)buffer, (key && key->value) ? key->value : def,
760 len, TRUE );
761 dprintf(("Kernel32:Odin profile:('%s','%s','%s'): returning '%s'\n",
762 section, key_name, def, buffer ));
763 ret = strlen( buffer );
764 }
765 else
766 {
767 ret = PROFILE_GetSection( PROFILE_OdinProfile, section, (char*)buffer, len, TRUE, FALSE );
768 }
769 LeaveCriticalSection( &PROFILE_CritSect );
770
771 return ret;
772}
773
774int WIN32API PROFILE_SetOdinIniString(LPCSTR section_name, LPCSTR key_name,
775 LPCSTR value)
776{
777 int ret;
778
779 EnterCriticalSection( &PROFILE_CritSect );
780
781 if (!key_name) /* Delete a whole section */
782 {
783 dprintf(("Kernel32:Odin profile:('%s')\n", section_name));
784 OdinProfileChanged |= PROFILE_DeleteSection( &PROFILE_OdinProfile,
785 section_name );
786 ret = TRUE; /* Even if PROFILE_DeleteSection() has failed,
787 this is not an error on application's level.*/
788 }
789 else if (!value) /* Delete a key */
790 {
791 dprintf(("Kernel32:Odin profile:('%s','%s')\n", section_name, key_name ));
792 OdinProfileChanged |= PROFILE_DeleteKey( &PROFILE_OdinProfile,
793 section_name, key_name );
794 ret = TRUE; /* same error handling as above */
795 }
796 else /* Set the key value */
797 {
798 PROFILEKEY *key = PROFILE_Find( &PROFILE_OdinProfile, section_name,
799 key_name, TRUE );
800 dprintf(("Kernel32:Odin profile:('%s','%s','%s'): \n",
801 section_name, key_name, value ));
802 if (!key) ret = FALSE; else
803 {
804 if (key->value && !strcmp(key->value,value))
805 {
806 dprintf(("Kernel32:Odin profile: no change needed\n" ));
807 /* No change needed */
808 } else
809 {
810 if (key->value)
811 {
812 dprintf(("Kernel32:Odin profile: replacing '%s'\n", key->value ));
813 HeapFree( SystemHeap, 0, key->value );
814 }
815 else dprintf(("Kernel32:Odin profile: creating key\n" ));
816 key->value = HEAP_strdupA( SystemHeap, 0, value );
817 OdinProfileChanged = TRUE;
818 }
819 ret = TRUE;
820 }
821 }
822
823 LeaveCriticalSection( &PROFILE_CritSect );
824
825 return ret;
826}
827
828
829/***********************************************************************
830 * PROFILE_GetOdinIniInt
831 *
832 * Get a config integer from the odin.ini file.
833 */
834int WIN32API PROFILE_GetOdinIniInt(LPCSTR section, LPCSTR key_name,
835 int def )
836{
837 char buffer[20];
838 char *p;
839 long result;
840 PROFILEKEY *key;
841 int ret;
842
843 EnterCriticalSection( &PROFILE_CritSect );
844
845 key = PROFILE_Find( &PROFILE_OdinProfile, section, key_name, FALSE );
846 if (!key || !key->value) {
847 ret = def;
848 } else {
849 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
850 result = strtol( buffer, &p, 0 );
851 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result;
852 }
853
854 LeaveCriticalSection( &PROFILE_CritSect );
855
856 return ret;
857}
858
859
860int WIN32API PROFILE_SetOdinIniInt(LPCSTR section, LPCSTR key_name, int value )
861{
862 char buffer[20];
863
864 sprintf(buffer,"%d",value);
865 return PROFILE_SetOdinIniString(section,key_name,buffer);
866}
867
868/******************************************************************************
869 *
870 * int PROFILE_EnumerateOdinIniSection(
871 * char const *section, #Name of the section to enumerate
872 * void (*cbfn)(char const *key, char const *value, void *user),
873 * # Address of the callback function
874 * void *user ) # User-specified pointer.
875 *
876 * For each entry in a section in the wine.conf file, this function will
877 * call the specified callback function, informing it of each key and
878 * value. An optional user pointer may be passed to it (if this is not
879 * needed, pass NULL through it and ignore the value in the callback
880 * function).
881 *
882 * The callback function must accept three parameters:
883 * The name of the key (char const *)
884 * The value of the key (char const *)
885 * A user-specified parameter (void *)
886 * Note that the first two are char CONST *'s, not char *'s! The callback
887 * MUST not modify these strings!
888 *
889 * The return value indicates the number of times the callback function
890 * was called.
891 */
892int PROFILE_EnumerateOdinIniSection(LPCSTR section,PVOID (*cbfn)(LPCSTR, LPCSTR, PVOID),PVOID userptr)
893{
894 PROFILESECTION *scansect;
895 PROFILEKEY *scankey;
896 int calls = 0;
897
898 EnterCriticalSection( &PROFILE_CritSect );
899
900 /* Search for the correct section */
901 for(scansect = PROFILE_OdinProfile; scansect; scansect = scansect->next) {
902 if(scansect->name && !strcasecmp(scansect->name, section)) {
903
904 /* Enumerate each key with the callback */
905 for(scankey = scansect->key; scankey; scankey = scankey->next) {
906
907 /* Ignore blank entries -- these shouldn't exist, but let's
908 be extra careful */
909 if(scankey->name[0]) {
910 cbfn(scankey->name, scankey->value, userptr);
911 ++calls;
912 }
913 }
914
915 break;
916 }
917 }
918 LeaveCriticalSection( &PROFILE_CritSect );
919
920 return calls;
921}
922
923
924/******************************************************************************
925 *
926 * int PROFILE_GetOdinIniBool(
927 * char const *section,
928 * char const *key_name,
929 * int def )
930 *
931 * Reads a boolean value from the odin.ini file. This function attempts to
932 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
933 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
934 * true. Anything else results in the return of the default value.
935 *
936 * This function uses 1 to indicate true, and 0 for false. You can check
937 * for existence by setting def to something other than 0 or 1 and
938 * examining the return value.
939 */
940int WIN32API PROFILE_GetOdinIniBool(LPCSTR section,
941 LPCSTR key_name,
942 int def)
943{
944 char key_value[2];
945 int retval;
946
947 PROFILE_GetOdinIniString(section, key_name, "~", key_value, 2);
948
949 switch(key_value[0]) {
950 case 'n':
951 case 'N':
952 case 'f':
953 case 'F':
954 case '0':
955 retval = 0;
956 break;
957
958 case 'y':
959 case 'Y':
960 case 't':
961 case 'T':
962 case '1':
963 retval = 1;
964 break;
965
966 default:
967 retval = def;
968 }
969
970 dprintf(("Kernel32:Odin profile:(\"%s\", \"%s\", %s), "
971 "[%c], ret %s.\n", section, key_name,
972 def ? "TRUE" : "FALSE", key_value[0],
973 retval ? "TRUE" : "FALSE"));
974
975 return retval;
976}
977
978
979int WIN32API PROFILE_SetOdinIniBool(LPCSTR section, LPCSTR key_name, int value)
980{
981 return PROFILE_SetOdinIniString(section,key_name,value ? "1":"0");
982}
983
984int WINAPI PROFILE_Initialize (void)
985{
986 InitializeCriticalSection( &PROFILE_CritSect );
987 MakeCriticalSectionGlobal( &PROFILE_CritSect );
988}
989
990/***********************************************************************
991 * LoadOdinIni
992 *
993 * Load the odin.ini file.
994 */
995int WINAPI PROFILE_LoadOdinIni()
996{
997 char buffer[MAX_PATHNAME_LEN];
998 const char *p;
999 FILE *f;
1000
1001 if ( (p = getenv( "ODIN_INI" )) && (f = fopen( p, "r" )) )
1002 {
1003 PROFILE_OdinProfile = PROFILE_Load( f );
1004 fclose( f );
1005 strncpy(PROFILE_OdinIniUsed,p,MAX_PATHNAME_LEN);
1006 PROFILE_OdinIniUsed[MAX_PATHNAME_LEN-1] = 0;
1007 }
1008 else
1009 {
1010 #if 0 /* Aug 27 2000 4:26am: Why not use the global kernel32Path
1011 * (LoadLibrary may cause harm if used...) */
1012 HINSTANCE hInstance = LoadLibraryA("KERNEL32.DLL");
1013 GetModuleFileNameA(hInstance,PROFILE_OdinIniUsed,sizeof(PROFILE_OdinIniUsed));
1014 FreeLibrary(hInstance);
1015 strcpy(strrchr(PROFILE_OdinIniUsed,'\\')+1,ODINININAME);
1016 #else
1017 strcpy(PROFILE_OdinIniUsed, kernel32Path);
1018 strcat(PROFILE_OdinIniUsed, ODINININAME);
1019 #endif
1020 f = fopen(PROFILE_OdinIniUsed, "r");
1021 PROFILE_OdinProfile = PROFILE_Load(f);
1022 fclose(f);
1023 }
1024
1025 dprintf(("Kernel32: Odin ini loaded: %s",PROFILE_OdinIniUsed));
1026
1027 return 1;
1028}
1029
1030static BOOL fDisableOdinIni = FALSE;
1031
1032void WIN32API DisableOdinIni()
1033{
1034 fDisableOdinIni = TRUE;
1035}
1036
1037int WIN32API PROFILE_SaveOdinIni()
1038{
1039 int ret;
1040 FILE *file;
1041
1042 if(fDisableOdinIni) return TRUE;
1043
1044 EnterCriticalSection( &PROFILE_CritSect );
1045
1046 if (OdinProfileChanged)
1047 {
1048 file = fopen(PROFILE_OdinIniUsed,"w");
1049 if (!file)
1050 {
1051 dprintf(("Kernel32:Odin profile:could not save profile file %s\n", PROFILE_OdinIniUsed));
1052 ret = FALSE;
1053 } else
1054 {
1055 dprintf(("Kernel32:Odin profile:Saving %s\n", PROFILE_OdinIniUsed ));
1056 PROFILE_Save( file, PROFILE_OdinProfile );
1057 fclose( file );
1058 OdinProfileChanged = FALSE;
1059 ret = TRUE;
1060 }
1061 }
1062
1063 LeaveCriticalSection( &PROFILE_CritSect );
1064
1065 return ret;
1066}
1067
1068#if 0
1069/***********************************************************************
1070 * PROFILE_UsageOdinIni
1071 *
1072 * Explain the wine.ini file to those who don't read documentation.
1073 * Keep below one screenful in length so that error messages above are
1074 * noticed.
1075 */
1076void PROFILE_UsageOdinIni(void)
1077{
1078 MESSAGE("Perhaps you have not properly edited or created "
1079 "your Odin configuration file.\n");
1080 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
1081 MESSAGE(" or it is determined by the -config option or from\n"
1082 " the WINE_INI environment variable.\n");
1083 if (*PROFILE_WineIniUsed)
1084 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
1085 /* RTFM, so to say */
1086}
1087#endif
1088
1089/***********************************************************************
1090 * PROFILE_GetStringItem
1091 *
1092 * Convenience function that turns a string 'xxx, yyy, zzz' into
1093 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
1094 */
1095char* PROFILE_GetStringItem( char* start )
1096{
1097 char* lpchX, *lpch;
1098
1099 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
1100 {
1101 if( *lpchX == ',' )
1102 {
1103 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
1104 while( *(++lpchX) )
1105 if( !PROFILE_isspace(*lpchX) ) return lpchX;
1106 }
1107 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
1108 else lpch = NULL;
1109 }
1110 if( lpch ) *lpch = '\0';
1111 return NULL;
1112}
1113
1114/********************* API functions **********************************/
1115
1116/***********************************************************************
1117 * GetProfileInt32A (KERNEL32.264)
1118 */
1119UINT WIN32API GetProfileIntA(LPCSTR section, LPCSTR entry, INT def_val)
1120{
1121 return GetPrivateProfileIntA( section, entry, def_val, WINININAME );
1122}
1123
1124/***********************************************************************
1125 * GetProfileInt32W (KERNEL32.264)
1126 */
1127UINT WIN32API GetProfileIntW(LPCWSTR section, LPCWSTR entry, INT def_val)
1128{
1129 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1130 return GetPrivateProfileIntW( section, entry, def_val, wininiW );
1131}
1132
1133/***********************************************************************
1134 * GetProfileString32A (KERNEL32.268)
1135 */
1136int WIN32API GetProfileStringA(LPCSTR section, LPCSTR entry,
1137 LPCSTR def_val,
1138 LPSTR buffer, UINT len)
1139{
1140 return GetPrivateProfileStringA( section, entry, def_val,
1141 buffer, len, WINININAME );
1142}
1143
1144/***********************************************************************
1145 * GetProfileString32W (KERNEL32.269)
1146 */
1147int WIN32API GetProfileStringW(LPCWSTR section, LPCWSTR entry,
1148 LPCWSTR def_val, LPWSTR buffer,
1149 UINT len)
1150{
1151 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1152 return GetPrivateProfileStringW( section, entry, def_val,
1153 buffer, len, wininiW );
1154}
1155
1156/***********************************************************************
1157 * WriteProfileString32A (KERNEL32.587)
1158 */
1159BOOL WIN32API WriteProfileStringA(LPCSTR section, LPCSTR entry,
1160 LPCSTR string)
1161{
1162 return WritePrivateProfileStringA( section, entry, string, WINININAME );
1163}
1164
1165/***********************************************************************
1166 * WriteProfileString32W (KERNEL32.588)
1167 */
1168BOOL WIN32API WriteProfileStringW(LPCWSTR section, LPCWSTR entry,
1169 LPCWSTR string)
1170{
1171 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1172 return WritePrivateProfileStringW( section, entry, string, wininiW );
1173}
1174
1175/***********************************************************************
1176 * GetPrivateProfileInt32A (KERNEL32.251)
1177 */
1178UINT WIN32API GetPrivateProfileIntA(LPCSTR section, LPCSTR entry,
1179 INT def_val, LPCSTR filename)
1180{
1181 char buffer[20];
1182 char *p;
1183 long result;
1184
1185 GetPrivateProfileStringA( section, entry, "",
1186 buffer, sizeof(buffer), filename );
1187 if (!buffer[0]) return (UINT)def_val;
1188 result = strtol( buffer, &p, 0 );
1189 if (p == buffer) return 0; /* No digits at all */
1190 return (UINT)result;
1191}
1192
1193/***********************************************************************
1194 * GetPrivateProfileInt32W (KERNEL32.252)
1195 */
1196UINT WIN32API GetPrivateProfileIntW(LPCWSTR section,
1197 LPCWSTR entry,
1198 INT def_val,
1199 LPCWSTR filename)
1200{
1201 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1202 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1203 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1204 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
1205 HeapFree( GetProcessHeap(), 0, sectionA );
1206 HeapFree( GetProcessHeap(), 0, filenameA );
1207 HeapFree( GetProcessHeap(), 0, entryA );
1208 return res;
1209}
1210
1211/***********************************************************************
1212 * GetPrivateProfileString32A (KERNEL32.255)
1213 */
1214INT WIN32API GetPrivateProfileStringA(LPCSTR section,
1215 LPCSTR entry,
1216 LPCSTR def_val,
1217 LPSTR buffer,
1218 UINT len,
1219 LPCSTR filename)
1220{
1221 int ret;
1222
1223 if (!filename)
1224 filename = WINININAME;
1225
1226 EnterCriticalSection( &PROFILE_CritSect );
1227
1228 if (PROFILE_Open( filename )) {
1229 ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1230 } else {
1231 lstrcpynA( buffer, def_val, len );
1232 ret = strlen( buffer );
1233 }
1234
1235 LeaveCriticalSection( &PROFILE_CritSect );
1236
1237 return ret;
1238}
1239
1240/***********************************************************************
1241 * GetPrivateProfileString32W (KERNEL32.256)
1242 */
1243INT WIN32API GetPrivateProfileStringW(LPCWSTR section,
1244 LPCWSTR entry,
1245 LPCWSTR def_val,
1246 LPWSTR buffer,
1247 UINT len,
1248 LPCWSTR filename)
1249{
1250 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1251 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1252 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1253 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1254 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1255 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
1256 bufferA, len, filenameA );
1257 lstrcpynAtoW( buffer, bufferA, len );
1258 HeapFree( GetProcessHeap(), 0, sectionA );
1259 HeapFree( GetProcessHeap(), 0, entryA );
1260 HeapFree( GetProcessHeap(), 0, filenameA );
1261 HeapFree( GetProcessHeap(), 0, def_valA );
1262 HeapFree( GetProcessHeap(), 0, bufferA);
1263 return ret;
1264}
1265
1266/***********************************************************************
1267 * GetPrivateProfileSection32A (KERNEL32.255)
1268 */
1269INT WIN32API GetPrivateProfileSectionA(LPCSTR section,
1270 LPSTR buffer,
1271 DWORD len,
1272 LPCSTR filename)
1273{
1274 int ret = 0;
1275
1276 EnterCriticalSection( &PROFILE_CritSect );
1277
1278 if (PROFILE_Open( filename ))
1279 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
1280 FALSE, TRUE);
1281
1282 LeaveCriticalSection( &PROFILE_CritSect );
1283
1284 return ret;
1285}
1286
1287/***********************************************************************
1288 * GetPrivateProfileSection32W (KERNEL32.256)
1289 */
1290
1291INT WIN32API GetPrivateProfileSectionW(LPCWSTR section,
1292 LPWSTR buffer,
1293 DWORD len,
1294 LPCWSTR filename)
1295
1296{
1297 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1298 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1299 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1300 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
1301 filenameA );
1302 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
1303 HeapFree( GetProcessHeap(), 0, sectionA );
1304 HeapFree( GetProcessHeap(), 0, filenameA );
1305 HeapFree( GetProcessHeap(), 0, bufferA);
1306 return ret;
1307}
1308
1309/***********************************************************************
1310 * GetProfileSection32A (KERNEL32.268)
1311 */
1312INT WIN32API GetProfileSectionA(LPCSTR section, LPSTR buffer,
1313 DWORD len)
1314{
1315 return GetPrivateProfileSectionA( section, buffer, len, WINININAME );
1316}
1317
1318/***********************************************************************
1319 * GetProfileSection32W (KERNEL32)
1320 */
1321INT WIN32API GetProfileSectionW(LPCWSTR section, LPWSTR buffer,
1322 DWORD len)
1323{
1324 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1325 return GetPrivateProfileSectionW( section, buffer, len, wininiW );
1326}
1327
1328/***********************************************************************
1329 * WritePrivateProfileString32A (KERNEL32.582)
1330 */
1331BOOL WIN32API WritePrivateProfileStringA(LPCSTR section,
1332 LPCSTR entry,
1333 LPCSTR string,
1334 LPCSTR filename)
1335{
1336 BOOL ret = FALSE;
1337
1338 EnterCriticalSection( &PROFILE_CritSect );
1339
1340 if (PROFILE_Open( filename ))
1341 {
1342 if (!section && !entry && !string)
1343 {
1344 PROFILE_FlushFile();
1345 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1346 }
1347 else
1348 {
1349 ret = PROFILE_SetString( section, entry, string );
1350 PROFILE_FlushFile();
1351 }
1352 }
1353
1354 LeaveCriticalSection( &PROFILE_CritSect );
1355 return ret;
1356}
1357
1358/***********************************************************************
1359 * WritePrivateProfileString32W (KERNEL32.583)
1360 */
1361BOOL WIN32API WritePrivateProfileStringW(LPCWSTR section,
1362 LPCWSTR entry,
1363 LPCWSTR string,
1364 LPCWSTR filename)
1365{
1366 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1367 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1368 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1369 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1370 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
1371 stringA, filenameA );
1372 HeapFree( GetProcessHeap(), 0, sectionA );
1373 HeapFree( GetProcessHeap(), 0, entryA );
1374 HeapFree( GetProcessHeap(), 0, stringA );
1375 HeapFree( GetProcessHeap(), 0, filenameA );
1376 return res;
1377}
1378
1379/***********************************************************************
1380 * WritePrivateProfileSection32A (KERNEL32)
1381 */
1382BOOL WIN32API WritePrivateProfileSectionA(LPCSTR section,
1383 LPCSTR string,
1384 LPCSTR filename)
1385{
1386 BOOL ret = FALSE;
1387 LPSTR p ;
1388
1389 dprintf(("WritePrivateProfileSectionA %s %s %s", section, string, filename));
1390
1391 EnterCriticalSection( &PROFILE_CritSect );
1392
1393 if (PROFILE_Open( filename )) {
1394 if (!section && !string)
1395 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1396 else if (!string) /* delete the named section*/
1397 {
1398 ret = PROFILE_SetString(section,NULL,NULL);
1399 PROFILE_FlushFile();
1400 }
1401 else {
1402 PROFILE_DeleteAllKeys(section);
1403 ret = TRUE;
1404 while(*string) {
1405 LPSTR buf=HEAP_strdupA( GetProcessHeap(), 0, string );
1406 if((p=strchr( buf, '='))){
1407 *p='\0';
1408 ret = PROFILE_SetString( section, buf, p+1 );
1409
1410 }
1411 HeapFree( GetProcessHeap(), 0, buf );
1412 string += strlen(string)+1;
1413 }
1414 PROFILE_FlushFile();
1415 }
1416 }
1417
1418 LeaveCriticalSection( &PROFILE_CritSect );
1419 return ret;
1420}
1421
1422/***********************************************************************
1423 * WritePrivateProfileSection32W (KERNEL32)
1424 */
1425BOOL WIN32API WritePrivateProfileSectionW(LPCWSTR section,
1426 LPCWSTR string,
1427 LPCWSTR filename)
1428{
1429 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1430 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1431 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1432 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
1433 HeapFree( GetProcessHeap(), 0, sectionA );
1434 HeapFree( GetProcessHeap(), 0, stringA );
1435 HeapFree( GetProcessHeap(), 0, filenameA );
1436 return res;
1437}
1438
1439/***********************************************************************
1440 * WriteProfileSection32A (KERNEL32.747)
1441 */
1442BOOL WIN32API WriteProfileSectionA(LPCSTR section, LPCSTR keys_n_values)
1443{
1444 return WritePrivateProfileSectionA( section, keys_n_values, WINININAME);
1445}
1446
1447/***********************************************************************
1448 * WriteProfileSection32W (KERNEL32.748)
1449 */
1450BOOL WIN32API WriteProfileSectionW(LPCWSTR section, LPCWSTR keys_n_values)
1451{
1452 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME);
1453
1454 return WritePrivateProfileSectionW(section,keys_n_values, wininiW);
1455}
1456
1457/***********************************************************************
1458 * GetPrivateProfileSectionNames16 (KERNEL.143)
1459 */
1460WORD WIN32API GetPrivateProfileSectionNames16(LPSTR buffer,
1461 WORD size,
1462 LPCSTR filename)
1463{
1464 WORD ret = 0;
1465
1466 EnterCriticalSection( &PROFILE_CritSect );
1467
1468 if (PROFILE_Open( filename ))
1469 ret = PROFILE_GetSectionNames(buffer, size);
1470
1471 LeaveCriticalSection( &PROFILE_CritSect );
1472
1473 return ret;
1474}
1475
1476/***********************************************************************
1477 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1478 */
1479DWORD WIN32API GetPrivateProfileSectionNamesA(LPSTR buffer,
1480 DWORD size,
1481 LPCSTR filename)
1482{
1483 return GetPrivateProfileSectionNames16(buffer,size,filename);
1484}
1485
1486/***********************************************************************
1487 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1488 */
1489DWORD WIN32API GetPrivateProfileSectionNamesW(LPWSTR buffer,
1490 DWORD size,
1491 LPCWSTR filename)
1492{
1493 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1494 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size);
1495
1496 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1497 lstrcpynAtoW( buffer, bufferA, size);
1498 HeapFree( GetProcessHeap(), 0, bufferA);
1499 HeapFree( GetProcessHeap(), 0, filenameA );
1500
1501 return ret;
1502}
1503
1504/***********************************************************************
1505 * GetPrivateProfileStruct32A (KERNEL32.370)
1506 */
1507BOOL WIN32API GetPrivateProfileStructA(LPCSTR section, LPCSTR key,
1508 LPVOID buf,
1509 UINT len,
1510 LPCSTR filename)
1511{
1512 BOOL ret = FALSE;
1513
1514 EnterCriticalSection( &PROFILE_CritSect );
1515
1516 if (PROFILE_Open( filename )) {
1517 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1518 if (k) {
1519 lstrcpynA( (LPSTR)buf, k->value, strlen(k->value));
1520 ret = TRUE;
1521 }
1522 }
1523 LeaveCriticalSection( &PROFILE_CritSect );
1524
1525 return FALSE;
1526}
1527
1528/***********************************************************************
1529 * GetPrivateProfileStruct32W (KERNEL32.543)
1530 */
1531BOOL WIN32API GetPrivateProfileStructW(LPCWSTR section,
1532 LPCWSTR key,
1533 LPVOID buffer,
1534 UINT len,
1535 LPCWSTR filename)
1536{
1537 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1538 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1539 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1540 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1541
1542 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
1543 len, filenameA );
1544 lstrcpynAtoW( (LPWSTR)buffer, bufferA, len );
1545 HeapFree( GetProcessHeap(), 0, bufferA);
1546 HeapFree( GetProcessHeap(), 0, sectionA );
1547 HeapFree( GetProcessHeap(), 0, keyA );
1548 HeapFree( GetProcessHeap(), 0, filenameA );
1549
1550 return ret;
1551}
1552
1553
1554/***********************************************************************
1555 * WritePrivateProfileStruct32A (KERNEL32.744)
1556 */
1557BOOL WIN32API WritePrivateProfileStructA(LPCSTR section,
1558 LPCSTR key,
1559 LPVOID buf,
1560 UINT bufsize,
1561 LPCSTR filename)
1562{
1563 BOOL ret = FALSE;
1564
1565 if (!section && !key && !buf) /* flush the cache */
1566 return WritePrivateProfileStringA( NULL, NULL, NULL, filename );
1567
1568 EnterCriticalSection( &PROFILE_CritSect );
1569
1570 if (PROFILE_Open( filename ))
1571 {
1572 ret = PROFILE_SetString( section, key, (LPCSTR)buf );
1573 PROFILE_FlushFile();
1574 }
1575 LeaveCriticalSection( &PROFILE_CritSect );
1576
1577 return ret;
1578}
1579
1580/***********************************************************************
1581 * WritePrivateProfileStruct32W (KERNEL32.544)
1582 */
1583BOOL WIN32API WritePrivateProfileStructW(LPCWSTR section,
1584 LPCWSTR key,
1585 LPVOID buf,
1586 UINT bufsize,
1587 LPCWSTR filename)
1588{
1589 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1590 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1591 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1592 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
1593 filenameA );
1594 HeapFree( GetProcessHeap(), 0, sectionA );
1595 HeapFree( GetProcessHeap(), 0, keyA );
1596 HeapFree( GetProcessHeap(), 0, filenameA );
1597
1598 return ret;
1599}
1600
1601/***********************************************************************
1602 * WriteOutProfiles (KERNEL.315)
1603 * CB: original: 16 bit function
1604 * here: necessary to save open ini files
1605 */
1606void WIN32API WriteOutProfiles()
1607{
1608 PROFILEROOT *lastCurProfile;
1609 INT x;
1610
1611 PROFILE_SaveOdinIni();
1612
1613 EnterCriticalSection(&PROFILE_CritSect);
1614
1615 if (CurProfile && CurProfile->filename)
1616 PROFILE_FlushFile(); //flash current
1617
1618 if (MRUProfile)
1619 {
1620 lastCurProfile = CurProfile;
1621 for(x = 1;x < N_CACHED_PROFILES;x++)
1622 {
1623 if (MRUProfile[x] && MRUProfile[x]->filename)
1624 {
1625 CurProfile = MRUProfile[x];
1626 PROFILE_FlushFile();
1627 }
1628 }
1629 CurProfile = lastCurProfile;
1630 }
1631 LeaveCriticalSection(&PROFILE_CritSect);
1632}
1633
1634
1635/***********************************************************************
1636 * CloseProfileUserMapping (KERNEL.138)
1637 */
1638BOOL WINAPI CloseProfileUserMapping(void)
1639{
1640 dprintf(("CloseProfileUserMapping: STUB"));
1641 return TRUE;
1642}
1643
1644BOOL WINAPI OpenProfileUserMapping(void)
1645{
1646 dprintf(("OpenProfileUserMapping: STUB"));
1647 return TRUE;
1648}
1649
Note: See TracBrowser for help on using the repository browser.