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

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

PROFILE_GetSection regression fix (heap corruption)

File size: 50.7 KB
Line 
1/* $Id: profile.cpp,v 1.36 2004-03-16 13:33:00 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 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1344 else
1345 ret = PROFILE_SetString( section, entry, string );
1346 }
1347
1348 LeaveCriticalSection( &PROFILE_CritSect );
1349 return ret;
1350}
1351
1352/***********************************************************************
1353 * WritePrivateProfileString32W (KERNEL32.583)
1354 */
1355BOOL WIN32API WritePrivateProfileStringW(LPCWSTR section,
1356 LPCWSTR entry,
1357 LPCWSTR string,
1358 LPCWSTR filename)
1359{
1360 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1361 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1362 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1363 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1364 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
1365 stringA, filenameA );
1366 HeapFree( GetProcessHeap(), 0, sectionA );
1367 HeapFree( GetProcessHeap(), 0, entryA );
1368 HeapFree( GetProcessHeap(), 0, stringA );
1369 HeapFree( GetProcessHeap(), 0, filenameA );
1370 return res;
1371}
1372
1373/***********************************************************************
1374 * WritePrivateProfileSection32A (KERNEL32)
1375 */
1376BOOL WIN32API WritePrivateProfileSectionA(LPCSTR section,
1377 LPCSTR string,
1378 LPCSTR filename)
1379{
1380 BOOL ret = FALSE;
1381 LPSTR p ;
1382
1383 dprintf(("WritePrivateProfileSectionA %s %s %s", section, string, filename));
1384
1385 EnterCriticalSection( &PROFILE_CritSect );
1386
1387 if (PROFILE_Open( filename )) {
1388 if (!section && !string)
1389 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1390 else if (!string) /* delete the named section*/
1391 ret = PROFILE_SetString(section,NULL,NULL);
1392 else {
1393 PROFILE_DeleteAllKeys(section);
1394 ret = TRUE;
1395 while(*string) {
1396 LPSTR buf=HEAP_strdupA( GetProcessHeap(), 0, string );
1397 if((p=strchr( buf, '='))){
1398 *p='\0';
1399 ret = PROFILE_SetString( section, buf, p+1 );
1400
1401 }
1402 HeapFree( GetProcessHeap(), 0, buf );
1403 string += strlen(string)+1;
1404 }
1405
1406 }
1407 }
1408
1409 LeaveCriticalSection( &PROFILE_CritSect );
1410 return ret;
1411}
1412
1413/***********************************************************************
1414 * WritePrivateProfileSection32W (KERNEL32)
1415 */
1416BOOL WIN32API WritePrivateProfileSectionW(LPCWSTR section,
1417 LPCWSTR string,
1418 LPCWSTR filename)
1419{
1420 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1421 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1422 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1423 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
1424 HeapFree( GetProcessHeap(), 0, sectionA );
1425 HeapFree( GetProcessHeap(), 0, stringA );
1426 HeapFree( GetProcessHeap(), 0, filenameA );
1427 return res;
1428}
1429
1430/***********************************************************************
1431 * WriteProfileSection32A (KERNEL32.747)
1432 */
1433BOOL WIN32API WriteProfileSectionA(LPCSTR section, LPCSTR keys_n_values)
1434{
1435 return WritePrivateProfileSectionA( section, keys_n_values, WINININAME);
1436}
1437
1438/***********************************************************************
1439 * WriteProfileSection32W (KERNEL32.748)
1440 */
1441BOOL WIN32API WriteProfileSectionW(LPCWSTR section, LPCWSTR keys_n_values)
1442{
1443 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME);
1444
1445 return WritePrivateProfileSectionW(section,keys_n_values, wininiW);
1446}
1447
1448/***********************************************************************
1449 * GetPrivateProfileSectionNames16 (KERNEL.143)
1450 */
1451WORD WIN32API GetPrivateProfileSectionNames16(LPSTR buffer,
1452 WORD size,
1453 LPCSTR filename)
1454{
1455 WORD ret = 0;
1456
1457 EnterCriticalSection( &PROFILE_CritSect );
1458
1459 if (PROFILE_Open( filename ))
1460 ret = PROFILE_GetSectionNames(buffer, size);
1461
1462 LeaveCriticalSection( &PROFILE_CritSect );
1463
1464 return ret;
1465}
1466
1467/***********************************************************************
1468 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1469 */
1470DWORD WIN32API GetPrivateProfileSectionNamesA(LPSTR buffer,
1471 DWORD size,
1472 LPCSTR filename)
1473{
1474 return GetPrivateProfileSectionNames16(buffer,size,filename);
1475}
1476
1477/***********************************************************************
1478 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1479 */
1480DWORD WIN32API GetPrivateProfileSectionNamesW(LPWSTR buffer,
1481 DWORD size,
1482 LPCWSTR filename)
1483{
1484 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1485 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size);
1486
1487 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1488 lstrcpynAtoW( buffer, bufferA, size);
1489 HeapFree( GetProcessHeap(), 0, bufferA);
1490 HeapFree( GetProcessHeap(), 0, filenameA );
1491
1492 return ret;
1493}
1494
1495/***********************************************************************
1496 * GetPrivateProfileStruct32A (KERNEL32.370)
1497 */
1498BOOL WIN32API GetPrivateProfileStructA(LPCSTR section, LPCSTR key,
1499 LPVOID buf,
1500 UINT len,
1501 LPCSTR filename)
1502{
1503 BOOL ret = FALSE;
1504
1505 EnterCriticalSection( &PROFILE_CritSect );
1506
1507 if (PROFILE_Open( filename )) {
1508 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1509 if (k) {
1510 lstrcpynA( (LPSTR)buf, k->value, strlen(k->value));
1511 ret = TRUE;
1512 }
1513 }
1514 LeaveCriticalSection( &PROFILE_CritSect );
1515
1516 return FALSE;
1517}
1518
1519/***********************************************************************
1520 * GetPrivateProfileStruct32W (KERNEL32.543)
1521 */
1522BOOL WIN32API GetPrivateProfileStructW(LPCWSTR section,
1523 LPCWSTR key,
1524 LPVOID buffer,
1525 UINT len,
1526 LPCWSTR filename)
1527{
1528 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1529 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1530 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1531 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1532
1533 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
1534 len, filenameA );
1535 lstrcpynAtoW( (LPWSTR)buffer, bufferA, len );
1536 HeapFree( GetProcessHeap(), 0, bufferA);
1537 HeapFree( GetProcessHeap(), 0, sectionA );
1538 HeapFree( GetProcessHeap(), 0, keyA );
1539 HeapFree( GetProcessHeap(), 0, filenameA );
1540
1541 return ret;
1542}
1543
1544
1545/***********************************************************************
1546 * WritePrivateProfileStruct32A (KERNEL32.744)
1547 */
1548BOOL WIN32API WritePrivateProfileStructA(LPCSTR section,
1549 LPCSTR key,
1550 LPVOID buf,
1551 UINT bufsize,
1552 LPCSTR filename)
1553{
1554 BOOL ret = FALSE;
1555
1556 if (!section && !key && !buf) /* flush the cache */
1557 return WritePrivateProfileStringA( NULL, NULL, NULL, filename );
1558
1559 EnterCriticalSection( &PROFILE_CritSect );
1560
1561 if (PROFILE_Open( filename ))
1562 ret = PROFILE_SetString( section, key, (LPCSTR)buf );
1563
1564 LeaveCriticalSection( &PROFILE_CritSect );
1565
1566 return ret;
1567}
1568
1569/***********************************************************************
1570 * WritePrivateProfileStruct32W (KERNEL32.544)
1571 */
1572BOOL WIN32API WritePrivateProfileStructW(LPCWSTR section,
1573 LPCWSTR key,
1574 LPVOID buf,
1575 UINT bufsize,
1576 LPCWSTR filename)
1577{
1578 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1579 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1580 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1581 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
1582 filenameA );
1583 HeapFree( GetProcessHeap(), 0, sectionA );
1584 HeapFree( GetProcessHeap(), 0, keyA );
1585 HeapFree( GetProcessHeap(), 0, filenameA );
1586
1587 return ret;
1588}
1589
1590/***********************************************************************
1591 * WriteOutProfiles (KERNEL.315)
1592 * CB: original: 16 bit function
1593 * here: necessary to save open ini files
1594 */
1595void WIN32API WriteOutProfiles()
1596{
1597 PROFILEROOT *lastCurProfile;
1598 INT x;
1599
1600 PROFILE_SaveOdinIni();
1601
1602 EnterCriticalSection(&PROFILE_CritSect);
1603
1604 if (CurProfile && CurProfile->filename)
1605 PROFILE_FlushFile(); //flash current
1606
1607 if (MRUProfile)
1608 {
1609 lastCurProfile = CurProfile;
1610 for(x = 1;x < N_CACHED_PROFILES;x++)
1611 {
1612 if (MRUProfile[x] && MRUProfile[x]->filename)
1613 {
1614 CurProfile = MRUProfile[x];
1615 PROFILE_FlushFile();
1616 }
1617 }
1618 CurProfile = lastCurProfile;
1619 }
1620 LeaveCriticalSection(&PROFILE_CritSect);
1621}
1622
1623
1624/***********************************************************************
1625 * CloseProfileUserMapping (KERNEL.138)
1626 */
1627BOOL WINAPI CloseProfileUserMapping(void)
1628{
1629 dprintf(("CloseProfileUserMapping: STUB"));
1630 return TRUE;
1631}
1632
1633BOOL WINAPI OpenProfileUserMapping(void)
1634{
1635 dprintf(("OpenProfileUserMapping: STUB"));
1636 return TRUE;
1637}
1638
Note: See TracBrowser for help on using the repository browser.