source: branches/gcc-kmk/src/kernel32/profile.cpp@ 21755

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

Extern "C".

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