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

Last change on this file since 22018 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 50.7 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 if (file == NULL)
223 return NULL;
224
225 first_section = (PROFILESECTION *)HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
226 first_section->name = NULL;
227 first_section->key = NULL;
228 first_section->next = NULL;
229 next_section = &first_section->next;
230 next_key = &first_section->key;
231 prev_key = NULL;
232
233 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
234 {
235 line++;
236 p = buffer;
237 while (*p && PROFILE_isspace(*p)) p++;
238 if (*p == '[') /* section start */
239 {
240 if (!(p2 = strrchr( p, ']' )))
241 {
242 dprintf(("Kernel32:Profile:Invalid section header at line %d: '%s'\n",
243 line, p ));
244 }
245 else
246 {
247 *p2 = '\0';
248 p++;
249 section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
250 section->name = HEAP_strdupA( SystemHeap, 0, p );
251 section->key = NULL;
252 section->next = NULL;
253 *next_section = section;
254 next_section = &section->next;
255 next_key = &section->key;
256 prev_key = NULL;
257
258 dprintf2(("Kernel32:Profile:New section: '%s'\n",section->name));
259
260 continue;
261 }
262 }
263
264 p2=p+strlen(p) - 1;
265 while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
266
267 if ((p2 = strchr( p, '=' )) != NULL)
268 {
269 char *p3 = p2 - 1;
270 while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
271 *p2++ = '\0';
272 while (*p2 && PROFILE_isspace(*p2)) p2++;
273 }
274
275 if(*p || !prev_key || *prev_key->name)
276 {
277 key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
278 key->name = HEAP_strdupA( SystemHeap, 0, p );
279 key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
280 key->next = NULL;
281 *next_key = key;
282 next_key = &key->next;
283 prev_key = key;
284
285 dprintf2(("Kernel32:Profile:New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)"));
286 }
287 }
288 return first_section;
289}
290
291
292/***********************************************************************
293 * PROFILE_DeleteSection
294 *
295 * Delete a section from a profile tree.
296 */
297static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
298{
299 while (*section)
300 {
301 if ((*section)->name && !strcasecmp( (*section)->name, name ))
302 {
303 PROFILESECTION *to_del = *section;
304 *section = to_del->next;
305 to_del->next = NULL;
306 PROFILE_Free( to_del );
307 return TRUE;
308 }
309 section = &(*section)->next;
310 }
311 return FALSE;
312}
313
314/***********************************************************************
315 * PROFILE_DeleteKey
316 *
317 * Delete a key from a profile tree.
318 */
319static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
320 LPCSTR section_name, LPCSTR key_name )
321{
322 while (*section)
323 {
324 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
325 {
326 PROFILEKEY **key = &(*section)->key;
327 while (*key)
328 {
329 if (!strcasecmp( (*key)->name, key_name ))
330 {
331 PROFILEKEY *to_del = *key;
332 *key = to_del->next;
333 if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
334 if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
335 HeapFree( SystemHeap, 0, to_del );
336 return TRUE;
337 }
338 key = &(*key)->next;
339 }
340 }
341 section = &(*section)->next;
342 }
343 return FALSE;
344}
345
346/***********************************************************************
347 * PROFILE_DeleteAllKeys
348 *
349 * Delete all keys from a profile tree.
350 */
351void PROFILE_DeleteAllKeys( LPCSTR section_name)
352{
353 PROFILESECTION **section= &CurProfile->section;
354 while (*section)
355 {
356 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
357 {
358 PROFILEKEY **key = &(*section)->key;
359 while (*key)
360 {
361 PROFILEKEY *to_del = *key;
362 *key = to_del->next;
363 if (to_del->name) HeapFree( GetProcessHeap(), 0, to_del->name );
364 if (to_del->value) HeapFree( GetProcessHeap(), 0, to_del->value);
365 HeapFree( GetProcessHeap(), 0, to_del );
366 CurProfile->changed =TRUE;
367 }
368 }
369 section = &(*section)->next;
370 }
371}
372
373/***********************************************************************
374 * PROFILE_Find
375 *
376 * Find a key in a profile tree, optionally creating it.
377 */
378static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
379 const char *section_name,
380 const char *key_name, int create )
381{
382 while (*section)
383 {
384 if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
385 {
386 PROFILEKEY **key = &(*section)->key;
387 while (*key)
388 {
389 if (!strcasecmp( (*key)->name, key_name )) return *key;
390 key = &(*key)->next;
391 }
392 if (!create) return NULL;
393 *key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
394 (*key)->name = HEAP_strdupA( SystemHeap, 0, key_name );
395 (*key)->value = NULL;
396 (*key)->next = NULL;
397 return *key;
398 }
399 section = &(*section)->next;
400 }
401 if (!create) return NULL;
402 *section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
403 (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
404 (*section)->next = NULL;
405 (*section)->key = (tagPROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
406 (*section)->key->name = HEAP_strdupA( SystemHeap, 0, key_name );
407 (*section)->key->value = NULL;
408 (*section)->key->next = NULL;
409 return (*section)->key;
410}
411
412
413/***********************************************************************
414 * PROFILE_FlushFile
415 *
416 * Flush the current profile to disk if changed.
417 */
418static BOOL PROFILE_FlushFile(void)
419{
420 FILE *file = NULL;
421 struct stat buf;
422
423 if(!CurProfile)
424 {
425 dprintf(("Kernel32:Profile:No current profile!\n"));
426 return FALSE;
427 }
428
429 // not changed, return immediately
430 if (!CurProfile->changed)
431 return TRUE;
432
433 // try to open file
434 file = fopen(CurProfile->fullname, "w");
435 if (!file)
436 {
437 dprintf(("Kernel32:Profile:could not save profile file %s\n", CurProfile->fullname));
438 return FALSE;
439 }
440
441 dprintf(("Kernel32:Profile:Saving %s\n", CurProfile->fullname ));
442 PROFILE_Save( file, CurProfile->section );
443 fclose( file );
444 CurProfile->changed = FALSE;
445 if(!stat(CurProfile->fullname,&buf))
446 CurProfile->mtime=buf.st_mtime;
447 return TRUE;
448}
449
450
451/***********************************************************************
452 * PROFILE_ReleaseFile
453 *
454 * Flush the current profile to disk and remove it from the cache.
455 */
456static void PROFILE_ReleaseFile(void)
457{
458 PROFILE_FlushFile();
459 PROFILE_Free( CurProfile->section );
460 if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
461 if (CurProfile->fullname) HeapFree(SystemHeap,0,CurProfile->fullname);
462 CurProfile->changed = FALSE;
463 CurProfile->section = NULL;
464 CurProfile->filename = NULL;
465 CurProfile->fullname = NULL;
466 CurProfile->mtime = 0;
467}
468
469
470/***********************************************************************
471 * PROFILE_Open
472 *
473 * Open a profile file, checking the cached file first.
474 */
475static BOOL PROFILE_Open( LPCSTR filename )
476{
477 FILE *file = NULL;
478 int i,j;
479 struct stat buf;
480 PROFILEROOT *tempProfile;
481
482 if (!filename || filename[0] == 0) return FALSE;
483
484 /* First time around */
485
486 if(!CurProfile)
487 for(i=0;i<N_CACHED_PROFILES;i++)
488 {
489 MRUProfile[i]= (PROFILEROOT*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEROOT) );
490 MRUProfile[i]->changed=FALSE;
491 MRUProfile[i]->section=NULL;
492 MRUProfile[i]->filename=NULL;
493 MRUProfile[i]->fullname=NULL;
494 MRUProfile[i]->mtime=0;
495 }
496
497 /* Check for a match */
498
499 for(i=0;i<N_CACHED_PROFILES;i++)
500 {
501 if (MRUProfile[i]->filename && (!stricmp(filename,MRUProfile[i]->filename) || !stricmp(filename,MRUProfile[i]->fullname)))
502 {
503 if(i)
504 {
505 PROFILE_FlushFile();
506 tempProfile=MRUProfile[i];
507 for(j=i;j>0;j--)
508 MRUProfile[j]=MRUProfile[j-1];
509 CurProfile=tempProfile;
510 }
511 if(!stat(CurProfile->fullname,&buf) && CurProfile->mtime==buf.st_mtime)
512 dprintf(("Kernel32:Profile:(%s): already opened (mru=%d)\n",
513 filename, i ));
514 else
515 dprintf(("Kernel32:Profile:(%s): already opened, needs refreshing (mru=%d)\n",
516 filename, i ));
517 return TRUE;
518 }
519 }
520
521 /* Rotate the oldest to the top to be replaced */
522
523 if(i==N_CACHED_PROFILES)
524 {
525 tempProfile=MRUProfile[N_CACHED_PROFILES-1];
526 for(i=N_CACHED_PROFILES-1;i>0;i--)
527 MRUProfile[i]=MRUProfile[i-1];
528 CurProfile=tempProfile;
529 }
530
531 /* Flush the profile */
532
533 if(CurProfile->filename) PROFILE_ReleaseFile();
534
535 CurProfile->filename = HEAP_strdupA(SystemHeap,0,filename);
536
537 /* check for path */
538
539 if ((!strchr( filename,'/') &&
540 !strchr( filename,'\\')) ||
541 !strchr( filename,':'))
542 {
543 char fullname[MAX_PATHNAME_LEN];
544
545 GetWindowsDirectoryA(fullname,sizeof(fullname));
546 strcat(fullname,"\\");
547 strcat(fullname,filename);
548 CurProfile->fullname = HEAP_strdupA(SystemHeap,0,fullname);
549 } else CurProfile->fullname = HEAP_strdupA(SystemHeap,0,filename);
550
551 file = fopen(CurProfile->fullname,"r");
552 if (file)
553 {
554 dprintf(("Kernel32:Profile:(%s): found it in %s\n",
555 filename, CurProfile->fullname ));
556
557 CurProfile->section = PROFILE_Load( file );
558 fclose( file );
559 if(!stat(CurProfile->fullname,&buf))
560 CurProfile->mtime=buf.st_mtime;
561 }
562 else
563 {
564 /* Does not exist yet, we will create it in PROFILE_FlushFile */
565 dprintf(("Kernel32:Profile:profile file %s not found\n", CurProfile->fullname ));
566 }
567 return TRUE;
568}
569
570
571/***********************************************************************
572 * PROFILE_GetSection
573 *
574 * Returns all keys of a section.
575 * If return_values is TRUE, also include the corresponding values.
576 */
577static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
578 LPSTR buffer, UINT len, BOOL handle_env,
579 BOOL return_values )
580{
581 PROFILEKEY *key;
582 while (section)
583 {
584 if (section->name && !strcasecmp( section->name, section_name ))
585 {
586 UINT oldlen = len;
587 for (key = section->key; key; key = key->next)
588 {
589 if (len <= 2) break;
590 if (!*key->name) continue; /* Skip empty lines */
591 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
592 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
593
594#ifdef __WIN32OS2__
595 /* CW: This fixes a crash in Windows Media Player setup where GetPrivateProfileSectionA() is called with len=5
596 which is not enough for holding any key name. */
597 if(strlen(key->name)>len-2) {
598 buffer += len-1;
599 len=1; /* Causes the funktion to end with a return code of len-2 */
600 break;
601 }
602 /*****************************************/
603#endif
604
605 len -= strlen(buffer) + 1;
606 buffer += strlen(buffer) + 1;
607 if (return_values && key->value) {
608 buffer[-1] = '=';
609 PROFILE_CopyEntry ( buffer,
610 key->value, len - 1, handle_env );
611
612#ifdef __WIN32OS2__
613 /* CW: This is the same as above for the keyname. I don't have a crashing app to prove this code but
614 expect the same problem as with the key name if the len is to short. */
615 if(strlen(key->value)>len-2) {
616 buffer += len;
617 len=1;
618 break;
619 }
620 /*****************************************/
621#endif
622
623 len -= strlen(buffer) + 1;
624 buffer += strlen(buffer) + 1;
625 }
626 }
627 *buffer = '\0';
628 if (len <= 1)
629 /*If either lpszSection or lpszKey is NULL and the supplied
630 destination buffer is too small to hold all the strings,
631 the last string is truncated and followed by two null characters.
632 In this case, the return value is equal to cchReturnBuffer
633 minus two. */
634 {
635 buffer[-1] = '\0';
636 return oldlen - 2;
637 }
638 return oldlen - len;
639 }
640 section = section->next;
641 }
642 buffer[0] = buffer[1] = '\0';
643 return 0;
644}
645
646
647static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
648{
649 LPSTR buf = buffer;
650 WORD l, cursize = 0;
651 PROFILESECTION *section;
652
653 for (section = CurProfile->section; section; section = section->next)
654 if (section->name) {
655 l = strlen(section->name);
656 cursize += l+1;
657 if (cursize > len+1)
658 return len-2;
659
660 strcpy(buf, section->name);
661 buf += l+1;
662 }
663
664 *buf=0;
665 buf++;
666 return buf-buffer;
667}
668
669
670/***********************************************************************
671 * PROFILE_GetString
672 *
673 * Get a profile string.
674 */
675static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
676 LPCSTR def_val, LPSTR buffer, UINT len )
677{
678 PROFILEKEY *key = NULL;
679
680 if (!def_val) def_val = "";
681 if (key_name && key_name[0])
682 {
683 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
684 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
685 len, FALSE );
686 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",
687 section, key_name, def_val, buffer ));
688 return strlen( buffer );
689 }
690 if (section && section[0])
691 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
692 FALSE, FALSE);
693 /* undocumented; both section and key_name are NULL */
694 return PROFILE_GetSectionNames(buffer, len);
695}
696
697
698/***********************************************************************
699 * PROFILE_SetString
700 *
701 * Set a profile string.
702 */
703static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
704 LPCSTR value )
705{
706 if (!key_name) /* Delete a whole section */
707 {
708 dprintf(("Kernel32:Profile:('%s')\n", section_name));
709 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
710 section_name );
711 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
712 this is not an error on application's level.*/
713 }
714 else if (!value) /* Delete a key */
715 {
716 dprintf(("Kernel32:Profile:('%s','%s')\n",
717 section_name, key_name ));
718 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
719 section_name, key_name );
720 return TRUE; /* same error handling as above */
721 }
722 else /* Set the key value */
723 {
724 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
725 key_name, TRUE );
726 dprintf(("Kernel32:Profile:('%s','%s','%s'): \n",
727 section_name, key_name, value ));
728 if (!key) return FALSE;
729 if (key->value)
730 {
731 if (!strcmp( key->value, value ))
732 {
733 dprintf(("Kernel32:Profile: no change needed\n" ));
734 return TRUE; /* No change needed */
735 }
736 dprintf(("Kernel32:Profile: replacing '%s'\n", key->value ));
737 HeapFree( SystemHeap, 0, key->value );
738 }
739 else dprintf(("Kernel32:Profile: creating key\n" ));
740 key->value = HEAP_strdupA( SystemHeap, 0, value );
741 CurProfile->changed = TRUE;
742 }
743 return TRUE;
744}
745
746
747/***********************************************************************
748 * PROFILE_GetOdinIniString
749 *
750 * Get a config string from the odin.ini file.
751 */
752int WIN32API PROFILE_GetOdinIniString(LPCSTR section, LPCSTR key_name,
753 LPCSTR def, LPSTR buffer, UINT len)
754{
755 int ret;
756
757 EnterCriticalSection( &PROFILE_CritSect );
758
759 if (key_name)
760 {
761 PROFILEKEY *key = PROFILE_Find(&PROFILE_OdinProfile, section, key_name, FALSE);
762 PROFILE_CopyEntry( (char*)buffer, (key && key->value) ? key->value : def,
763 len, TRUE );
764 dprintf(("Kernel32:Odin profile:('%s','%s','%s'): returning '%s'\n",
765 section, key_name, def, buffer ));
766 ret = strlen( buffer );
767 }
768 else
769 {
770 ret = PROFILE_GetSection( PROFILE_OdinProfile, section, (char*)buffer, len, TRUE, FALSE );
771 }
772 LeaveCriticalSection( &PROFILE_CritSect );
773
774 return ret;
775}
776
777extern "C" {
778
779int WIN32API PROFILE_SetOdinIniString(LPCSTR section_name, LPCSTR key_name,
780 LPCSTR value)
781{
782 int ret;
783
784 EnterCriticalSection( &PROFILE_CritSect );
785
786 if (!key_name) /* Delete a whole section */
787 {
788 dprintf(("Kernel32:Odin profile:('%s')\n", section_name));
789 OdinProfileChanged |= PROFILE_DeleteSection( &PROFILE_OdinProfile,
790 section_name );
791 ret = TRUE; /* Even if PROFILE_DeleteSection() has failed,
792 this is not an error on application's level.*/
793 }
794 else if (!value) /* Delete a key */
795 {
796 dprintf(("Kernel32:Odin profile:('%s','%s')\n", section_name, key_name ));
797 OdinProfileChanged |= PROFILE_DeleteKey( &PROFILE_OdinProfile,
798 section_name, key_name );
799 ret = TRUE; /* same error handling as above */
800 }
801 else /* Set the key value */
802 {
803 PROFILEKEY *key = PROFILE_Find( &PROFILE_OdinProfile, section_name,
804 key_name, TRUE );
805 dprintf(("Kernel32:Odin profile:('%s','%s','%s'): \n",
806 section_name, key_name, value ));
807 if (!key) ret = FALSE; else
808 {
809 if (key->value && !strcmp(key->value,value))
810 {
811 dprintf(("Kernel32:Odin profile: no change needed\n" ));
812 /* No change needed */
813 } else
814 {
815 if (key->value)
816 {
817 dprintf(("Kernel32:Odin profile: replacing '%s'\n", key->value ));
818 HeapFree( SystemHeap, 0, key->value );
819 }
820 else dprintf(("Kernel32:Odin profile: creating key\n" ));
821 key->value = HEAP_strdupA( SystemHeap, 0, value );
822 OdinProfileChanged = TRUE;
823 }
824 ret = TRUE;
825 }
826 }
827
828 LeaveCriticalSection( &PROFILE_CritSect );
829
830 return ret;
831}
832
833
834/***********************************************************************
835 * PROFILE_GetOdinIniInt
836 *
837 * Get a config integer from the odin.ini file.
838 */
839int WIN32API PROFILE_GetOdinIniInt(LPCSTR section, LPCSTR key_name,
840 int def )
841{
842 char buffer[20];
843 char *p;
844 long result;
845 PROFILEKEY *key;
846 int ret;
847
848 EnterCriticalSection( &PROFILE_CritSect );
849
850 key = PROFILE_Find( &PROFILE_OdinProfile, section, key_name, FALSE );
851 if (!key || !key->value) {
852 ret = def;
853 } else {
854 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
855 result = strtol( buffer, &p, 0 );
856 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result;
857 }
858
859 LeaveCriticalSection( &PROFILE_CritSect );
860
861 return ret;
862}
863
864
865int WIN32API PROFILE_SetOdinIniInt(LPCSTR section, LPCSTR key_name, int value )
866{
867 char buffer[20];
868
869 sprintf(buffer,"%d",value);
870 return PROFILE_SetOdinIniString(section,key_name,buffer);
871}
872
873/******************************************************************************
874 *
875 * int PROFILE_EnumerateOdinIniSection(
876 * char const *section, #Name of the section to enumerate
877 * void (*cbfn)(char const *key, char const *value, void *user),
878 * # Address of the callback function
879 * void *user ) # User-specified pointer.
880 *
881 * For each entry in a section in the wine.conf file, this function will
882 * call the specified callback function, informing it of each key and
883 * value. An optional user pointer may be passed to it (if this is not
884 * needed, pass NULL through it and ignore the value in the callback
885 * function).
886 *
887 * The callback function must accept three parameters:
888 * The name of the key (char const *)
889 * The value of the key (char const *)
890 * A user-specified parameter (void *)
891 * Note that the first two are char CONST *'s, not char *'s! The callback
892 * MUST not modify these strings!
893 *
894 * The return value indicates the number of times the callback function
895 * was called.
896 */
897int PROFILE_EnumerateOdinIniSection(LPCSTR section,PVOID (*cbfn)(LPCSTR, LPCSTR, PVOID),PVOID userptr)
898{
899 PROFILESECTION *scansect;
900 PROFILEKEY *scankey;
901 int calls = 0;
902
903 EnterCriticalSection( &PROFILE_CritSect );
904
905 /* Search for the correct section */
906 for(scansect = PROFILE_OdinProfile; scansect; scansect = scansect->next) {
907 if(scansect->name && !strcasecmp(scansect->name, section)) {
908
909 /* Enumerate each key with the callback */
910 for(scankey = scansect->key; scankey; scankey = scankey->next) {
911
912 /* Ignore blank entries -- these shouldn't exist, but let's
913 be extra careful */
914 if(scankey->name[0]) {
915 cbfn(scankey->name, scankey->value, userptr);
916 ++calls;
917 }
918 }
919
920 break;
921 }
922 }
923 LeaveCriticalSection( &PROFILE_CritSect );
924
925 return calls;
926}
927
928
929/******************************************************************************
930 *
931 * int PROFILE_GetOdinIniBool(
932 * char const *section,
933 * char const *key_name,
934 * int def )
935 *
936 * Reads a boolean value from the odin.ini file. This function attempts to
937 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
938 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
939 * true. Anything else results in the return of the default value.
940 *
941 * This function uses 1 to indicate true, and 0 for false. You can check
942 * for existence by setting def to something other than 0 or 1 and
943 * examining the return value.
944 */
945int WIN32API PROFILE_GetOdinIniBool(LPCSTR section,
946 LPCSTR key_name,
947 int def)
948{
949 char key_value[2];
950 int retval;
951
952 PROFILE_GetOdinIniString(section, key_name, "~", key_value, 2);
953
954 switch(key_value[0]) {
955 case 'n':
956 case 'N':
957 case 'f':
958 case 'F':
959 case '0':
960 retval = 0;
961 break;
962
963 case 'y':
964 case 'Y':
965 case 't':
966 case 'T':
967 case '1':
968 retval = 1;
969 break;
970
971 default:
972 retval = def;
973 }
974
975 dprintf(("Kernel32:Odin profile:(\"%s\", \"%s\", %s), "
976 "[%c], ret %s.\n", section, key_name,
977 def ? "TRUE" : "FALSE", key_value[0],
978 retval ? "TRUE" : "FALSE"));
979
980 return retval;
981}
982
983
984int WIN32API PROFILE_SetOdinIniBool(LPCSTR section, LPCSTR key_name, int value)
985{
986 return PROFILE_SetOdinIniString(section,key_name,value ? "1":"0");
987}
988
989int WINAPI PROFILE_Initialize (void)
990{
991 InitializeCriticalSection( &PROFILE_CritSect );
992 MakeCriticalSectionGlobal( &PROFILE_CritSect );
993 return 1;
994}
995
996/***********************************************************************
997 * LoadOdinIni
998 *
999 * Load the odin.ini file.
1000 */
1001int WINAPI PROFILE_LoadOdinIni()
1002{
1003 char buffer[MAX_PATHNAME_LEN];
1004 const char *p;
1005 FILE *f;
1006
1007 if ( (p = getenv( "ODIN_INI" )) && (f = fopen( p, "r" )) )
1008 {
1009 PROFILE_OdinProfile = PROFILE_Load( f );
1010 fclose( f );
1011 strncpy(PROFILE_OdinIniUsed,p,MAX_PATHNAME_LEN);
1012 PROFILE_OdinIniUsed[MAX_PATHNAME_LEN-1] = 0;
1013 }
1014 else
1015 {
1016 strcpy(PROFILE_OdinIniUsed, kernel32Path);
1017 strcat(PROFILE_OdinIniUsed, ODINININAME);
1018 if ((f = fopen(PROFILE_OdinIniUsed, "r")))
1019 {
1020 PROFILE_OdinProfile = PROFILE_Load(f);
1021 fclose(f);
1022 }
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, '=')) != NULL){
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
1650} // extern "C"
1651
Note: See TracBrowser for help on using the repository browser.