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

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

custom build update

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