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

Last change on this file since 9597 was 9597, checked in by sandervl, 23 years ago

changed calling convention of custom odin functions

File size: 50.7 KB
Line 
1/* $Id: profile.cpp,v 1.35 2003-01-03 16:34:33 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;
596 len=1; /* Causes the funktion to end with a return code of len-2 */
597 break;
598 }
599 /*****************************************/
600#endif
601
602 len -= strlen(buffer) + 1;
603 buffer += strlen(buffer) + 1;
604 if (return_values && key->value) {
605 buffer[-1] = '=';
606 PROFILE_CopyEntry ( buffer,
607 key->value, len - 1, handle_env );
608
609#ifdef __WIN32OS2__
610 /* CW: This is the same as above for the keyname. I don't have a crashing app to prove this code but
611 expect the same problem as with the key name if the len is to short. */
612 if(strlen(key->value)>len-2) {
613 buffer += len;
614 len=1;
615 break;
616 }
617 /*****************************************/
618#endif
619
620 len -= strlen(buffer) + 1;
621 buffer += strlen(buffer) + 1;
622 }
623 }
624 *buffer = '\0';
625 if (len <= 1)
626 /*If either lpszSection or lpszKey is NULL and the supplied
627 destination buffer is too small to hold all the strings,
628 the last string is truncated and followed by two null characters.
629 In this case, the return value is equal to cchReturnBuffer
630 minus two. */
631 {
632 buffer[-1] = '\0';
633 return oldlen - 2;
634 }
635 return oldlen - len;
636 }
637 section = section->next;
638 }
639 buffer[0] = buffer[1] = '\0';
640 return 0;
641}
642
643
644static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
645{
646 LPSTR buf = buffer;
647 WORD l, cursize = 0;
648 PROFILESECTION *section;
649
650 for (section = CurProfile->section; section; section = section->next)
651 if (section->name) {
652 l = strlen(section->name);
653 cursize += l+1;
654 if (cursize > len+1)
655 return len-2;
656
657 strcpy(buf, section->name);
658 buf += l+1;
659 }
660
661 *buf=0;
662 buf++;
663 return buf-buffer;
664}
665
666
667/***********************************************************************
668 * PROFILE_GetString
669 *
670 * Get a profile string.
671 */
672static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
673 LPCSTR def_val, LPSTR buffer, UINT len )
674{
675 PROFILEKEY *key = NULL;
676
677 if (!def_val) def_val = "";
678 if (key_name && key_name[0])
679 {
680 key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
681 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
682 len, FALSE );
683 dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",
684 section, key_name, def_val, buffer ));
685 return strlen( buffer );
686 }
687 if (section && section[0])
688 return PROFILE_GetSection(CurProfile->section, section, buffer, len,
689 FALSE, FALSE);
690 /* undocumented; both section and key_name are NULL */
691 return PROFILE_GetSectionNames(buffer, len);
692}
693
694
695/***********************************************************************
696 * PROFILE_SetString
697 *
698 * Set a profile string.
699 */
700static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
701 LPCSTR value )
702{
703 if (!key_name) /* Delete a whole section */
704 {
705 dprintf(("Kernel32:Profile:('%s')\n", section_name));
706 CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
707 section_name );
708 return TRUE; /* Even if PROFILE_DeleteSection() has failed,
709 this is not an error on application's level.*/
710 }
711 else if (!value) /* Delete a key */
712 {
713 dprintf(("Kernel32:Profile:('%s','%s')\n",
714 section_name, key_name ));
715 CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
716 section_name, key_name );
717 return TRUE; /* same error handling as above */
718 }
719 else /* Set the key value */
720 {
721 PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
722 key_name, TRUE );
723 dprintf(("Kernel32:Profile:('%s','%s','%s'): \n",
724 section_name, key_name, value ));
725 if (!key) return FALSE;
726 if (key->value)
727 {
728 if (!strcmp( key->value, value ))
729 {
730 dprintf(("Kernel32:Profile: no change needed\n" ));
731 return TRUE; /* No change needed */
732 }
733 dprintf(("Kernel32:Profile: replacing '%s'\n", key->value ));
734 HeapFree( SystemHeap, 0, key->value );
735 }
736 else dprintf(("Kernel32:Profile: creating key\n" ));
737 key->value = HEAP_strdupA( SystemHeap, 0, value );
738 CurProfile->changed = TRUE;
739 }
740 return TRUE;
741}
742
743
744/***********************************************************************
745 * PROFILE_GetOdinIniString
746 *
747 * Get a config string from the odin.ini file.
748 */
749int WIN32API PROFILE_GetOdinIniString(LPCSTR section, LPCSTR key_name,
750 LPCSTR def, LPSTR buffer, UINT len)
751{
752 int ret;
753
754 EnterCriticalSection( &PROFILE_CritSect );
755
756 if (key_name)
757 {
758 PROFILEKEY *key = PROFILE_Find(&PROFILE_OdinProfile, section, key_name, FALSE);
759 PROFILE_CopyEntry( (char*)buffer, (key && key->value) ? key->value : def,
760 len, TRUE );
761 dprintf(("Kernel32:Odin profile:('%s','%s','%s'): returning '%s'\n",
762 section, key_name, def, buffer ));
763 ret = strlen( buffer );
764 }
765 else
766 {
767 ret = PROFILE_GetSection( PROFILE_OdinProfile, section, (char*)buffer, len, TRUE, FALSE );
768 }
769 LeaveCriticalSection( &PROFILE_CritSect );
770
771 return ret;
772}
773
774int WIN32API PROFILE_SetOdinIniString(LPCSTR section_name, LPCSTR key_name,
775 LPCSTR value)
776{
777 int ret;
778
779 EnterCriticalSection( &PROFILE_CritSect );
780
781 if (!key_name) /* Delete a whole section */
782 {
783 dprintf(("Kernel32:Odin profile:('%s')\n", section_name));
784 OdinProfileChanged |= PROFILE_DeleteSection( &PROFILE_OdinProfile,
785 section_name );
786 ret = TRUE; /* Even if PROFILE_DeleteSection() has failed,
787 this is not an error on application's level.*/
788 }
789 else if (!value) /* Delete a key */
790 {
791 dprintf(("Kernel32:Odin profile:('%s','%s')\n", section_name, key_name ));
792 OdinProfileChanged |= PROFILE_DeleteKey( &PROFILE_OdinProfile,
793 section_name, key_name );
794 ret = TRUE; /* same error handling as above */
795 }
796 else /* Set the key value */
797 {
798 PROFILEKEY *key = PROFILE_Find( &PROFILE_OdinProfile, section_name,
799 key_name, TRUE );
800 dprintf(("Kernel32:Odin profile:('%s','%s','%s'): \n",
801 section_name, key_name, value ));
802 if (!key) ret = FALSE; else
803 {
804 if (key->value && !strcmp(key->value,value))
805 {
806 dprintf(("Kernel32:Odin profile: no change needed\n" ));
807 /* No change needed */
808 } else
809 {
810 if (key->value)
811 {
812 dprintf(("Kernel32:Odin profile: replacing '%s'\n", key->value ));
813 HeapFree( SystemHeap, 0, key->value );
814 }
815 else dprintf(("Kernel32:Odin profile: creating key\n" ));
816 key->value = HEAP_strdupA( SystemHeap, 0, value );
817 OdinProfileChanged = TRUE;
818 }
819 ret = TRUE;
820 }
821 }
822
823 LeaveCriticalSection( &PROFILE_CritSect );
824
825 return ret;
826}
827
828
829/***********************************************************************
830 * PROFILE_GetOdinIniInt
831 *
832 * Get a config integer from the odin.ini file.
833 */
834int WIN32API PROFILE_GetOdinIniInt(LPCSTR section, LPCSTR key_name,
835 int def )
836{
837 char buffer[20];
838 char *p;
839 long result;
840 PROFILEKEY *key;
841 int ret;
842
843 EnterCriticalSection( &PROFILE_CritSect );
844
845 key = PROFILE_Find( &PROFILE_OdinProfile, section, key_name, FALSE );
846 if (!key || !key->value) {
847 ret = def;
848 } else {
849 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
850 result = strtol( buffer, &p, 0 );
851 ret = (p == buffer) ? 0 /* No digits at all */ : (int)result;
852 }
853
854 LeaveCriticalSection( &PROFILE_CritSect );
855
856 return ret;
857}
858
859
860int WIN32API PROFILE_SetOdinIniInt(LPCSTR section, LPCSTR key_name, int value )
861{
862 char buffer[20];
863
864 sprintf(buffer,"%d",value);
865 return PROFILE_SetOdinIniString(section,key_name,buffer);
866}
867
868/******************************************************************************
869 *
870 * int PROFILE_EnumerateOdinIniSection(
871 * char const *section, #Name of the section to enumerate
872 * void (*cbfn)(char const *key, char const *value, void *user),
873 * # Address of the callback function
874 * void *user ) # User-specified pointer.
875 *
876 * For each entry in a section in the wine.conf file, this function will
877 * call the specified callback function, informing it of each key and
878 * value. An optional user pointer may be passed to it (if this is not
879 * needed, pass NULL through it and ignore the value in the callback
880 * function).
881 *
882 * The callback function must accept three parameters:
883 * The name of the key (char const *)
884 * The value of the key (char const *)
885 * A user-specified parameter (void *)
886 * Note that the first two are char CONST *'s, not char *'s! The callback
887 * MUST not modify these strings!
888 *
889 * The return value indicates the number of times the callback function
890 * was called.
891 */
892int PROFILE_EnumerateOdinIniSection(LPCSTR section,PVOID (*cbfn)(LPCSTR, LPCSTR, PVOID),PVOID userptr)
893{
894 PROFILESECTION *scansect;
895 PROFILEKEY *scankey;
896 int calls = 0;
897
898 EnterCriticalSection( &PROFILE_CritSect );
899
900 /* Search for the correct section */
901 for(scansect = PROFILE_OdinProfile; scansect; scansect = scansect->next) {
902 if(scansect->name && !strcasecmp(scansect->name, section)) {
903
904 /* Enumerate each key with the callback */
905 for(scankey = scansect->key; scankey; scankey = scankey->next) {
906
907 /* Ignore blank entries -- these shouldn't exist, but let's
908 be extra careful */
909 if(scankey->name[0]) {
910 cbfn(scankey->name, scankey->value, userptr);
911 ++calls;
912 }
913 }
914
915 break;
916 }
917 }
918 LeaveCriticalSection( &PROFILE_CritSect );
919
920 return calls;
921}
922
923
924/******************************************************************************
925 *
926 * int PROFILE_GetOdinIniBool(
927 * char const *section,
928 * char const *key_name,
929 * int def )
930 *
931 * Reads a boolean value from the odin.ini file. This function attempts to
932 * be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
933 * (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
934 * true. Anything else results in the return of the default value.
935 *
936 * This function uses 1 to indicate true, and 0 for false. You can check
937 * for existence by setting def to something other than 0 or 1 and
938 * examining the return value.
939 */
940int WIN32API PROFILE_GetOdinIniBool(LPCSTR section,
941 LPCSTR key_name,
942 int def)
943{
944 char key_value[2];
945 int retval;
946
947 PROFILE_GetOdinIniString(section, key_name, "~", key_value, 2);
948
949 switch(key_value[0]) {
950 case 'n':
951 case 'N':
952 case 'f':
953 case 'F':
954 case '0':
955 retval = 0;
956 break;
957
958 case 'y':
959 case 'Y':
960 case 't':
961 case 'T':
962 case '1':
963 retval = 1;
964 break;
965
966 default:
967 retval = def;
968 }
969
970 dprintf(("Kernel32:Odin profile:(\"%s\", \"%s\", %s), "
971 "[%c], ret %s.\n", section, key_name,
972 def ? "TRUE" : "FALSE", key_value[0],
973 retval ? "TRUE" : "FALSE"));
974
975 return retval;
976}
977
978
979int WIN32API PROFILE_SetOdinIniBool(LPCSTR section, LPCSTR key_name, int value)
980{
981 return PROFILE_SetOdinIniString(section,key_name,value ? "1":"0");
982}
983
984
985/***********************************************************************
986 * LoadOdinIni
987 *
988 * Load the odin.ini file.
989 */
990int WINAPI PROFILE_LoadOdinIni()
991{
992 char buffer[MAX_PATHNAME_LEN];
993 const char *p;
994 FILE *f;
995
996 InitializeCriticalSection( &PROFILE_CritSect );
997 MakeCriticalSectionGlobal( &PROFILE_CritSect );
998
999 if ( (p = getenv( "ODIN_INI" )) && (f = fopen( p, "r" )) )
1000 {
1001 PROFILE_OdinProfile = PROFILE_Load( f );
1002 fclose( f );
1003 strncpy(PROFILE_OdinIniUsed,p,MAX_PATHNAME_LEN);
1004 PROFILE_OdinIniUsed[MAX_PATHNAME_LEN-1] = 0;
1005 }
1006 else
1007 {
1008 #if 0 /* Aug 27 2000 4:26am: Why not use the global kernel32Path
1009 * (LoadLibrary may cause harm if used...) */
1010 HINSTANCE hInstance = LoadLibraryA("KERNEL32.DLL");
1011 GetModuleFileNameA(hInstance,PROFILE_OdinIniUsed,sizeof(PROFILE_OdinIniUsed));
1012 FreeLibrary(hInstance);
1013 strcpy(strrchr(PROFILE_OdinIniUsed,'\\')+1,ODINININAME);
1014 #else
1015 strcpy(PROFILE_OdinIniUsed, kernel32Path);
1016 strcat(PROFILE_OdinIniUsed, ODINININAME);
1017 #endif
1018 f = fopen(PROFILE_OdinIniUsed, "r");
1019 PROFILE_OdinProfile = PROFILE_Load(f);
1020 fclose(f);
1021 }
1022
1023 dprintf(("Kernel32: Odin ini loaded: %s",PROFILE_OdinIniUsed));
1024
1025 return 1;
1026}
1027
1028static BOOL fDisableOdinIni = FALSE;
1029
1030void WIN32API DisableOdinIni()
1031{
1032 fDisableOdinIni = TRUE;
1033}
1034
1035int WIN32API PROFILE_SaveOdinIni()
1036{
1037 int ret;
1038 FILE *file;
1039
1040 if(fDisableOdinIni) return TRUE;
1041
1042 EnterCriticalSection( &PROFILE_CritSect );
1043
1044 if (OdinProfileChanged)
1045 {
1046 file = fopen(PROFILE_OdinIniUsed,"w");
1047 if (!file)
1048 {
1049 dprintf(("Kernel32:Odin profile:could not save profile file %s\n", PROFILE_OdinIniUsed));
1050 ret = FALSE;
1051 } else
1052 {
1053 dprintf(("Kernel32:Odin profile:Saving %s\n", PROFILE_OdinIniUsed ));
1054 PROFILE_Save( file, PROFILE_OdinProfile );
1055 fclose( file );
1056 OdinProfileChanged = FALSE;
1057 ret = TRUE;
1058 }
1059 }
1060
1061 LeaveCriticalSection( &PROFILE_CritSect );
1062
1063 return ret;
1064}
1065
1066#if 0
1067/***********************************************************************
1068 * PROFILE_UsageOdinIni
1069 *
1070 * Explain the wine.ini file to those who don't read documentation.
1071 * Keep below one screenful in length so that error messages above are
1072 * noticed.
1073 */
1074void PROFILE_UsageOdinIni(void)
1075{
1076 MESSAGE("Perhaps you have not properly edited or created "
1077 "your Odin configuration file.\n");
1078 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
1079 MESSAGE(" or it is determined by the -config option or from\n"
1080 " the WINE_INI environment variable.\n");
1081 if (*PROFILE_WineIniUsed)
1082 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
1083 /* RTFM, so to say */
1084}
1085#endif
1086
1087/***********************************************************************
1088 * PROFILE_GetStringItem
1089 *
1090 * Convenience function that turns a string 'xxx, yyy, zzz' into
1091 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
1092 */
1093char* PROFILE_GetStringItem( char* start )
1094{
1095 char* lpchX, *lpch;
1096
1097 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
1098 {
1099 if( *lpchX == ',' )
1100 {
1101 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
1102 while( *(++lpchX) )
1103 if( !PROFILE_isspace(*lpchX) ) return lpchX;
1104 }
1105 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
1106 else lpch = NULL;
1107 }
1108 if( lpch ) *lpch = '\0';
1109 return NULL;
1110}
1111
1112/********************* API functions **********************************/
1113
1114/***********************************************************************
1115 * GetProfileInt32A (KERNEL32.264)
1116 */
1117UINT WIN32API GetProfileIntA(LPCSTR section, LPCSTR entry, INT def_val)
1118{
1119 return GetPrivateProfileIntA( section, entry, def_val, WINININAME );
1120}
1121
1122/***********************************************************************
1123 * GetProfileInt32W (KERNEL32.264)
1124 */
1125UINT WIN32API GetProfileIntW(LPCWSTR section, LPCWSTR entry, INT def_val)
1126{
1127 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1128 return GetPrivateProfileIntW( section, entry, def_val, wininiW );
1129}
1130
1131/***********************************************************************
1132 * GetProfileString32A (KERNEL32.268)
1133 */
1134int WIN32API GetProfileStringA(LPCSTR section, LPCSTR entry,
1135 LPCSTR def_val,
1136 LPSTR buffer, UINT len)
1137{
1138 return GetPrivateProfileStringA( section, entry, def_val,
1139 buffer, len, WINININAME );
1140}
1141
1142/***********************************************************************
1143 * GetProfileString32W (KERNEL32.269)
1144 */
1145int WIN32API GetProfileStringW(LPCWSTR section, LPCWSTR entry,
1146 LPCWSTR def_val, LPWSTR buffer,
1147 UINT len)
1148{
1149 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1150 return GetPrivateProfileStringW( section, entry, def_val,
1151 buffer, len, wininiW );
1152}
1153
1154/***********************************************************************
1155 * WriteProfileString32A (KERNEL32.587)
1156 */
1157BOOL WIN32API WriteProfileStringA(LPCSTR section, LPCSTR entry,
1158 LPCSTR string)
1159{
1160 return WritePrivateProfileStringA( section, entry, string, WINININAME );
1161}
1162
1163/***********************************************************************
1164 * WriteProfileString32W (KERNEL32.588)
1165 */
1166BOOL WIN32API WriteProfileStringW(LPCWSTR section, LPCWSTR entry,
1167 LPCWSTR string)
1168{
1169 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1170 return WritePrivateProfileStringW( section, entry, string, wininiW );
1171}
1172
1173/***********************************************************************
1174 * GetPrivateProfileInt32A (KERNEL32.251)
1175 */
1176UINT WIN32API GetPrivateProfileIntA(LPCSTR section, LPCSTR entry,
1177 INT def_val, LPCSTR filename)
1178{
1179 char buffer[20];
1180 char *p;
1181 long result;
1182
1183 GetPrivateProfileStringA( section, entry, "",
1184 buffer, sizeof(buffer), filename );
1185 if (!buffer[0]) return (UINT)def_val;
1186 result = strtol( buffer, &p, 0 );
1187 if (p == buffer) return 0; /* No digits at all */
1188 return (UINT)result;
1189}
1190
1191/***********************************************************************
1192 * GetPrivateProfileInt32W (KERNEL32.252)
1193 */
1194UINT WIN32API GetPrivateProfileIntW(LPCWSTR section,
1195 LPCWSTR entry,
1196 INT def_val,
1197 LPCWSTR filename)
1198{
1199 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1200 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1201 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1202 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
1203 HeapFree( GetProcessHeap(), 0, sectionA );
1204 HeapFree( GetProcessHeap(), 0, filenameA );
1205 HeapFree( GetProcessHeap(), 0, entryA );
1206 return res;
1207}
1208
1209/***********************************************************************
1210 * GetPrivateProfileString32A (KERNEL32.255)
1211 */
1212INT WIN32API GetPrivateProfileStringA(LPCSTR section,
1213 LPCSTR entry,
1214 LPCSTR def_val,
1215 LPSTR buffer,
1216 UINT len,
1217 LPCSTR filename)
1218{
1219 int ret;
1220
1221 if (!filename)
1222 filename = WINININAME;
1223
1224 EnterCriticalSection( &PROFILE_CritSect );
1225
1226 if (PROFILE_Open( filename )) {
1227 ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1228 } else {
1229 lstrcpynA( buffer, def_val, len );
1230 ret = strlen( buffer );
1231 }
1232
1233 LeaveCriticalSection( &PROFILE_CritSect );
1234
1235 return ret;
1236}
1237
1238/***********************************************************************
1239 * GetPrivateProfileString32W (KERNEL32.256)
1240 */
1241INT WIN32API GetPrivateProfileStringW(LPCWSTR section,
1242 LPCWSTR entry,
1243 LPCWSTR def_val,
1244 LPWSTR buffer,
1245 UINT len,
1246 LPCWSTR filename)
1247{
1248 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1249 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1250 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1251 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1252 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1253 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
1254 bufferA, len, filenameA );
1255 lstrcpynAtoW( buffer, bufferA, len );
1256 HeapFree( GetProcessHeap(), 0, sectionA );
1257 HeapFree( GetProcessHeap(), 0, entryA );
1258 HeapFree( GetProcessHeap(), 0, filenameA );
1259 HeapFree( GetProcessHeap(), 0, def_valA );
1260 HeapFree( GetProcessHeap(), 0, bufferA);
1261 return ret;
1262}
1263
1264/***********************************************************************
1265 * GetPrivateProfileSection32A (KERNEL32.255)
1266 */
1267INT WIN32API GetPrivateProfileSectionA(LPCSTR section,
1268 LPSTR buffer,
1269 DWORD len,
1270 LPCSTR filename)
1271{
1272 int ret = 0;
1273
1274 EnterCriticalSection( &PROFILE_CritSect );
1275
1276 if (PROFILE_Open( filename ))
1277 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
1278 FALSE, TRUE);
1279
1280 LeaveCriticalSection( &PROFILE_CritSect );
1281
1282 return ret;
1283}
1284
1285/***********************************************************************
1286 * GetPrivateProfileSection32W (KERNEL32.256)
1287 */
1288
1289INT WIN32API GetPrivateProfileSectionW(LPCWSTR section,
1290 LPWSTR buffer,
1291 DWORD len,
1292 LPCWSTR filename)
1293
1294{
1295 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1296 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1297 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1298 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
1299 filenameA );
1300 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
1301 HeapFree( GetProcessHeap(), 0, sectionA );
1302 HeapFree( GetProcessHeap(), 0, filenameA );
1303 HeapFree( GetProcessHeap(), 0, bufferA);
1304 return ret;
1305}
1306
1307/***********************************************************************
1308 * GetProfileSection32A (KERNEL32.268)
1309 */
1310INT WIN32API GetProfileSectionA(LPCSTR section, LPSTR buffer,
1311 DWORD len)
1312{
1313 return GetPrivateProfileSectionA( section, buffer, len, WINININAME );
1314}
1315
1316/***********************************************************************
1317 * GetProfileSection32W (KERNEL32)
1318 */
1319INT WIN32API GetProfileSectionW(LPCWSTR section, LPWSTR buffer,
1320 DWORD len)
1321{
1322 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1323 return GetPrivateProfileSectionW( section, buffer, len, wininiW );
1324}
1325
1326/***********************************************************************
1327 * WritePrivateProfileString32A (KERNEL32.582)
1328 */
1329BOOL WIN32API WritePrivateProfileStringA(LPCSTR section,
1330 LPCSTR entry,
1331 LPCSTR string,
1332 LPCSTR filename)
1333{
1334 BOOL ret = FALSE;
1335
1336 EnterCriticalSection( &PROFILE_CritSect );
1337
1338 if (PROFILE_Open( filename ))
1339 {
1340 if (!section && !entry && !string)
1341 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1342 else
1343 ret = PROFILE_SetString( section, entry, string );
1344 }
1345
1346 LeaveCriticalSection( &PROFILE_CritSect );
1347 return ret;
1348}
1349
1350/***********************************************************************
1351 * WritePrivateProfileString32W (KERNEL32.583)
1352 */
1353BOOL WIN32API WritePrivateProfileStringW(LPCWSTR section,
1354 LPCWSTR entry,
1355 LPCWSTR string,
1356 LPCWSTR filename)
1357{
1358 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1359 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1360 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1361 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1362 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
1363 stringA, filenameA );
1364 HeapFree( GetProcessHeap(), 0, sectionA );
1365 HeapFree( GetProcessHeap(), 0, entryA );
1366 HeapFree( GetProcessHeap(), 0, stringA );
1367 HeapFree( GetProcessHeap(), 0, filenameA );
1368 return res;
1369}
1370
1371/***********************************************************************
1372 * WritePrivateProfileSection32A (KERNEL32)
1373 */
1374BOOL WIN32API WritePrivateProfileSectionA(LPCSTR section,
1375 LPCSTR string,
1376 LPCSTR filename)
1377{
1378 BOOL ret = FALSE;
1379 LPSTR p ;
1380
1381 dprintf(("WritePrivateProfileSectionA %s %s %s", section, string, filename));
1382
1383 EnterCriticalSection( &PROFILE_CritSect );
1384
1385 if (PROFILE_Open( filename )) {
1386 if (!section && !string)
1387 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1388 else if (!string) /* delete the named section*/
1389 ret = PROFILE_SetString(section,NULL,NULL);
1390 else {
1391 PROFILE_DeleteAllKeys(section);
1392 ret = TRUE;
1393 while(*string) {
1394 LPSTR buf=HEAP_strdupA( GetProcessHeap(), 0, string );
1395 if((p=strchr( buf, '='))){
1396 *p='\0';
1397 ret = PROFILE_SetString( section, buf, p+1 );
1398
1399 }
1400 HeapFree( GetProcessHeap(), 0, buf );
1401 string += strlen(string)+1;
1402 }
1403
1404 }
1405 }
1406
1407 LeaveCriticalSection( &PROFILE_CritSect );
1408 return ret;
1409}
1410
1411/***********************************************************************
1412 * WritePrivateProfileSection32W (KERNEL32)
1413 */
1414BOOL WIN32API WritePrivateProfileSectionW(LPCWSTR section,
1415 LPCWSTR string,
1416 LPCWSTR filename)
1417{
1418 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1419 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1420 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1421 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
1422 HeapFree( GetProcessHeap(), 0, sectionA );
1423 HeapFree( GetProcessHeap(), 0, stringA );
1424 HeapFree( GetProcessHeap(), 0, filenameA );
1425 return res;
1426}
1427
1428/***********************************************************************
1429 * WriteProfileSection32A (KERNEL32.747)
1430 */
1431BOOL WIN32API WriteProfileSectionA(LPCSTR section, LPCSTR keys_n_values)
1432{
1433 return WritePrivateProfileSectionA( section, keys_n_values, WINININAME);
1434}
1435
1436/***********************************************************************
1437 * WriteProfileSection32W (KERNEL32.748)
1438 */
1439BOOL WIN32API WriteProfileSectionW(LPCWSTR section, LPCWSTR keys_n_values)
1440{
1441 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME);
1442
1443 return WritePrivateProfileSectionW(section,keys_n_values, wininiW);
1444}
1445
1446/***********************************************************************
1447 * GetPrivateProfileSectionNames16 (KERNEL.143)
1448 */
1449WORD WIN32API GetPrivateProfileSectionNames16(LPSTR buffer,
1450 WORD size,
1451 LPCSTR filename)
1452{
1453 WORD ret = 0;
1454
1455 EnterCriticalSection( &PROFILE_CritSect );
1456
1457 if (PROFILE_Open( filename ))
1458 ret = PROFILE_GetSectionNames(buffer, size);
1459
1460 LeaveCriticalSection( &PROFILE_CritSect );
1461
1462 return ret;
1463}
1464
1465/***********************************************************************
1466 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1467 */
1468DWORD WIN32API GetPrivateProfileSectionNamesA(LPSTR buffer,
1469 DWORD size,
1470 LPCSTR filename)
1471{
1472 return GetPrivateProfileSectionNames16(buffer,size,filename);
1473}
1474
1475/***********************************************************************
1476 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1477 */
1478DWORD WIN32API GetPrivateProfileSectionNamesW(LPWSTR buffer,
1479 DWORD size,
1480 LPCWSTR filename)
1481{
1482 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1483 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size);
1484
1485 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1486 lstrcpynAtoW( buffer, bufferA, size);
1487 HeapFree( GetProcessHeap(), 0, bufferA);
1488 HeapFree( GetProcessHeap(), 0, filenameA );
1489
1490 return ret;
1491}
1492
1493/***********************************************************************
1494 * GetPrivateProfileStruct32A (KERNEL32.370)
1495 */
1496BOOL WIN32API GetPrivateProfileStructA(LPCSTR section, LPCSTR key,
1497 LPVOID buf,
1498 UINT len,
1499 LPCSTR filename)
1500{
1501 BOOL ret = FALSE;
1502
1503 EnterCriticalSection( &PROFILE_CritSect );
1504
1505 if (PROFILE_Open( filename )) {
1506 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1507 if (k) {
1508 lstrcpynA( (LPSTR)buf, k->value, strlen(k->value));
1509 ret = TRUE;
1510 }
1511 }
1512 LeaveCriticalSection( &PROFILE_CritSect );
1513
1514 return FALSE;
1515}
1516
1517/***********************************************************************
1518 * GetPrivateProfileStruct32W (KERNEL32.543)
1519 */
1520BOOL WIN32API GetPrivateProfileStructW(LPCWSTR section,
1521 LPCWSTR key,
1522 LPVOID buffer,
1523 UINT len,
1524 LPCWSTR filename)
1525{
1526 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1527 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1528 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1529 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1530
1531 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
1532 len, filenameA );
1533 lstrcpynAtoW( (LPWSTR)buffer, bufferA, len );
1534 HeapFree( GetProcessHeap(), 0, bufferA);
1535 HeapFree( GetProcessHeap(), 0, sectionA );
1536 HeapFree( GetProcessHeap(), 0, keyA );
1537 HeapFree( GetProcessHeap(), 0, filenameA );
1538
1539 return ret;
1540}
1541
1542
1543/***********************************************************************
1544 * WritePrivateProfileStruct32A (KERNEL32.744)
1545 */
1546BOOL WIN32API WritePrivateProfileStructA(LPCSTR section,
1547 LPCSTR key,
1548 LPVOID buf,
1549 UINT bufsize,
1550 LPCSTR filename)
1551{
1552 BOOL ret = FALSE;
1553
1554 if (!section && !key && !buf) /* flush the cache */
1555 return WritePrivateProfileStringA( NULL, NULL, NULL, filename );
1556
1557 EnterCriticalSection( &PROFILE_CritSect );
1558
1559 if (PROFILE_Open( filename ))
1560 ret = PROFILE_SetString( section, key, (LPCSTR)buf );
1561
1562 LeaveCriticalSection( &PROFILE_CritSect );
1563
1564 return ret;
1565}
1566
1567/***********************************************************************
1568 * WritePrivateProfileStruct32W (KERNEL32.544)
1569 */
1570BOOL WIN32API WritePrivateProfileStructW(LPCWSTR section,
1571 LPCWSTR key,
1572 LPVOID buf,
1573 UINT bufsize,
1574 LPCWSTR filename)
1575{
1576 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1577 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1578 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1579 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
1580 filenameA );
1581 HeapFree( GetProcessHeap(), 0, sectionA );
1582 HeapFree( GetProcessHeap(), 0, keyA );
1583 HeapFree( GetProcessHeap(), 0, filenameA );
1584
1585 return ret;
1586}
1587
1588/***********************************************************************
1589 * WriteOutProfiles (KERNEL.315)
1590 * CB: original: 16 bit function
1591 * here: necessary to save open ini files
1592 */
1593void WIN32API WriteOutProfiles()
1594{
1595 PROFILEROOT *lastCurProfile;
1596 INT x;
1597
1598 PROFILE_SaveOdinIni();
1599
1600 EnterCriticalSection(&PROFILE_CritSect);
1601
1602 if (CurProfile && CurProfile->filename)
1603 PROFILE_FlushFile(); //flash current
1604
1605 if (MRUProfile)
1606 {
1607 lastCurProfile = CurProfile;
1608 for(x = 1;x < N_CACHED_PROFILES;x++)
1609 {
1610 if (MRUProfile[x] && MRUProfile[x]->filename)
1611 {
1612 CurProfile = MRUProfile[x];
1613 PROFILE_FlushFile();
1614 }
1615 }
1616 CurProfile = lastCurProfile;
1617 }
1618 LeaveCriticalSection(&PROFILE_CritSect);
1619}
1620
1621
1622/***********************************************************************
1623 * CloseProfileUserMapping (KERNEL.138)
1624 */
1625BOOL WINAPI CloseProfileUserMapping(void)
1626{
1627 dprintf(("CloseProfileUserMapping: STUB"));
1628 return TRUE;
1629}
1630
1631BOOL WINAPI OpenProfileUserMapping(void)
1632{
1633 dprintf(("OpenProfileUserMapping: STUB"));
1634 return TRUE;
1635}
1636
Note: See TracBrowser for help on using the repository browser.