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

Last change on this file since 5939 was 5939, checked in by sandervl, 24 years ago

turned off heapcheck in writelogmisc.cpp

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