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

Last change on this file since 7029 was 7004, checked in by phaller, 24 years ago

profile compatibility (conflict w/ PROFILE macro)

File size: 50.1 KB
Line 
1/* $Id: profile.cpp,v 1.32 2001-10-10 22:24:35 phaller 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
1044ODINFUNCTION0(int,PROFILE_SaveOdinIni)
1045{
1046 int ret;
1047 FILE *file;
1048
1049 EnterCriticalSection( &PROFILE_CritSect );
1050
1051 if (OdinProfileChanged)
1052 {
1053 file = fopen(PROFILE_OdinIniUsed,"w");
1054 if (!file)
1055 {
1056 dprintf(("Kernel32:Odin profile:could not save profile file %s\n", PROFILE_OdinIniUsed));
1057 ret = FALSE;
1058 } else
1059 {
1060 dprintf(("Kernel32:Odin profile:Saving %s\n", PROFILE_OdinIniUsed ));
1061 PROFILE_Save( file, PROFILE_OdinProfile );
1062 fclose( file );
1063 OdinProfileChanged = FALSE;
1064 ret = TRUE;
1065 }
1066 }
1067
1068 LeaveCriticalSection( &PROFILE_CritSect );
1069
1070 return ret;
1071}
1072
1073#if 0
1074/***********************************************************************
1075 * PROFILE_UsageOdinIni
1076 *
1077 * Explain the wine.ini file to those who don't read documentation.
1078 * Keep below one screenful in length so that error messages above are
1079 * noticed.
1080 */
1081void PROFILE_UsageOdinIni(void)
1082{
1083 MESSAGE("Perhaps you have not properly edited or created "
1084 "your Odin configuration file.\n");
1085 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
1086 MESSAGE(" or it is determined by the -config option or from\n"
1087 " the WINE_INI environment variable.\n");
1088 if (*PROFILE_WineIniUsed)
1089 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
1090 /* RTFM, so to say */
1091}
1092#endif
1093
1094/***********************************************************************
1095 * PROFILE_GetStringItem
1096 *
1097 * Convenience function that turns a string 'xxx, yyy, zzz' into
1098 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
1099 */
1100char* PROFILE_GetStringItem( char* start )
1101{
1102 char* lpchX, *lpch;
1103
1104 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
1105 {
1106 if( *lpchX == ',' )
1107 {
1108 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
1109 while( *(++lpchX) )
1110 if( !PROFILE_isspace(*lpchX) ) return lpchX;
1111 }
1112 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
1113 else lpch = NULL;
1114 }
1115 if( lpch ) *lpch = '\0';
1116 return NULL;
1117}
1118
1119/********************* API functions **********************************/
1120
1121/***********************************************************************
1122 * GetProfileInt32A (KERNEL32.264)
1123 */
1124ODINFUNCTION3(UINT, GetProfileIntA,
1125 LPCSTR, section,
1126 LPCSTR, entry,
1127 INT, def_val)
1128{
1129 return CALL_ODINFUNC(GetPrivateProfileIntA)( section, entry, def_val, WINININAME );
1130}
1131
1132/***********************************************************************
1133 * GetProfileInt32W (KERNEL32.264)
1134 */
1135ODINFUNCTION3(UINT, GetProfileIntW,
1136 LPCWSTR, section,
1137 LPCWSTR, entry,
1138 INT, def_val)
1139{
1140 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1141 return CALL_ODINFUNC(GetPrivateProfileIntW)( section, entry, def_val, wininiW );
1142}
1143
1144/***********************************************************************
1145 * GetProfileString32A (KERNEL32.268)
1146 */
1147ODINFUNCTION5(INT, GetProfileStringA,
1148 LPCSTR, section,
1149 LPCSTR, entry,
1150 LPCSTR, def_val,
1151 LPSTR, buffer,
1152 UINT, len)
1153{
1154 return CALL_ODINFUNC(GetPrivateProfileStringA)( section, entry, def_val,
1155 buffer, len, WINININAME );
1156}
1157
1158/***********************************************************************
1159 * GetProfileString32W (KERNEL32.269)
1160 */
1161ODINFUNCTION5(INT, GetProfileStringW,
1162 LPCWSTR, section,
1163 LPCWSTR, entry,
1164 LPCWSTR, def_val,
1165 LPWSTR, buffer,
1166 UINT, len)
1167{
1168 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1169 return CALL_ODINFUNC(GetPrivateProfileStringW)( section, entry, def_val,
1170 buffer, len, wininiW );
1171}
1172
1173/***********************************************************************
1174 * WriteProfileString32A (KERNEL32.587)
1175 */
1176ODINFUNCTION3(BOOL, WriteProfileStringA,
1177 LPCSTR, section,
1178 LPCSTR, entry,
1179 LPCSTR, string)
1180{
1181 return CALL_ODINFUNC(WritePrivateProfileStringA)( section, entry, string, WINININAME );
1182}
1183
1184/***********************************************************************
1185 * WriteProfileString32W (KERNEL32.588)
1186 */
1187ODINFUNCTION3(BOOL, WriteProfileStringW,
1188 LPCWSTR, section,
1189 LPCWSTR, entry,
1190 LPCWSTR, string)
1191{
1192 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1193 return CALL_ODINFUNC(WritePrivateProfileStringW)( section, entry, string, wininiW );
1194}
1195
1196/***********************************************************************
1197 * GetPrivateProfileInt32A (KERNEL32.251)
1198 */
1199ODINFUNCTION4(UINT, GetPrivateProfileIntA,
1200 LPCSTR, section,
1201 LPCSTR, entry,
1202 INT, def_val,
1203 LPCSTR, filename)
1204{
1205 char buffer[20];
1206 char *p;
1207 long result;
1208
1209 CALL_ODINFUNC(GetPrivateProfileStringA)( section, entry, "",
1210 buffer, sizeof(buffer), filename );
1211 if (!buffer[0]) return (UINT)def_val;
1212 result = strtol( buffer, &p, 0 );
1213 if (p == buffer) return 0; /* No digits at all */
1214 return (UINT)result;
1215}
1216
1217/***********************************************************************
1218 * GetPrivateProfileInt32W (KERNEL32.252)
1219 */
1220ODINFUNCTION4(UINT, GetPrivateProfileIntW,
1221 LPCWSTR, section,
1222 LPCWSTR, entry,
1223 INT, def_val,
1224 LPCWSTR, filename)
1225{
1226 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1227 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1228 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1229 UINT res = CALL_ODINFUNC(GetPrivateProfileIntA)(sectionA, entryA, def_val, filenameA);
1230 HeapFree( GetProcessHeap(), 0, sectionA );
1231 HeapFree( GetProcessHeap(), 0, filenameA );
1232 HeapFree( GetProcessHeap(), 0, entryA );
1233 return res;
1234}
1235
1236/***********************************************************************
1237 * GetPrivateProfileString32A (KERNEL32.255)
1238 */
1239ODINFUNCTION6(INT, GetPrivateProfileStringA,
1240 LPCSTR, section,
1241 LPCSTR, entry,
1242 LPCSTR, def_val,
1243 LPSTR, buffer,
1244 UINT, len,
1245 LPCSTR, filename)
1246{
1247 int ret;
1248
1249 if (!filename)
1250 filename = WINININAME;
1251
1252 EnterCriticalSection( &PROFILE_CritSect );
1253
1254 if (PROFILE_Open( filename )) {
1255 ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1256 } else {
1257 lstrcpynA( buffer, def_val, len );
1258 ret = strlen( buffer );
1259 }
1260
1261 LeaveCriticalSection( &PROFILE_CritSect );
1262
1263 return ret;
1264}
1265
1266/***********************************************************************
1267 * GetPrivateProfileString32W (KERNEL32.256)
1268 */
1269ODINFUNCTION6(INT, GetPrivateProfileStringW,
1270 LPCWSTR, section,
1271 LPCWSTR, entry,
1272 LPCWSTR, def_val,
1273 LPWSTR, buffer,
1274 UINT, len,
1275 LPCWSTR, filename)
1276{
1277 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1278 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1279 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1280 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1281 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1282 INT ret = CALL_ODINFUNC(GetPrivateProfileStringA)( sectionA, entryA, def_valA,
1283 bufferA, len, filenameA );
1284 lstrcpynAtoW( buffer, bufferA, len );
1285 HeapFree( GetProcessHeap(), 0, sectionA );
1286 HeapFree( GetProcessHeap(), 0, entryA );
1287 HeapFree( GetProcessHeap(), 0, filenameA );
1288 HeapFree( GetProcessHeap(), 0, def_valA );
1289 HeapFree( GetProcessHeap(), 0, bufferA);
1290 return ret;
1291}
1292
1293/***********************************************************************
1294 * GetPrivateProfileSection32A (KERNEL32.255)
1295 */
1296ODINFUNCTION4(INT, GetPrivateProfileSectionA,
1297 LPCSTR, section,
1298 LPSTR, buffer,
1299 DWORD, len,
1300 LPCSTR, filename)
1301{
1302 int ret = 0;
1303
1304 EnterCriticalSection( &PROFILE_CritSect );
1305
1306 if (PROFILE_Open( filename ))
1307 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
1308 FALSE, TRUE);
1309
1310 LeaveCriticalSection( &PROFILE_CritSect );
1311
1312 return ret;
1313}
1314
1315/***********************************************************************
1316 * GetPrivateProfileSection32W (KERNEL32.256)
1317 */
1318
1319ODINFUNCTION4(INT, GetPrivateProfileSectionW,
1320 LPCWSTR, section,
1321 LPWSTR, buffer,
1322 DWORD, len,
1323 LPCWSTR, filename)
1324
1325{
1326 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1327 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1328 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1329 INT ret = CALL_ODINFUNC(GetPrivateProfileSectionA)( sectionA, bufferA, len,
1330 filenameA );
1331 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
1332 HeapFree( GetProcessHeap(), 0, sectionA );
1333 HeapFree( GetProcessHeap(), 0, filenameA );
1334 HeapFree( GetProcessHeap(), 0, bufferA);
1335 return ret;
1336}
1337
1338/***********************************************************************
1339 * GetProfileSection32A (KERNEL32.268)
1340 */
1341ODINFUNCTION3(INT, GetProfileSectionA,
1342 LPCSTR, section,
1343 LPSTR, buffer,
1344 DWORD, len)
1345{
1346 return CALL_ODINFUNC(GetPrivateProfileSectionA)( section, buffer, len, WINININAME );
1347}
1348
1349/***********************************************************************
1350 * GetProfileSection32W (KERNEL32)
1351 */
1352ODINFUNCTION3(INT, GetProfileSectionW,
1353 LPCWSTR, section,
1354 LPWSTR, buffer,
1355 DWORD, len)
1356{
1357 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1358 return CALL_ODINFUNC(GetPrivateProfileSectionW)( section, buffer, len, wininiW );
1359}
1360
1361/***********************************************************************
1362 * WritePrivateProfileString32A (KERNEL32.582)
1363 */
1364ODINFUNCTION4(BOOL, WritePrivateProfileStringA,
1365 LPCSTR, section,
1366 LPCSTR, entry,
1367 LPCSTR, string,
1368 LPCSTR, filename)
1369{
1370 BOOL ret = FALSE;
1371
1372 EnterCriticalSection( &PROFILE_CritSect );
1373
1374 if (PROFILE_Open( filename ))
1375 {
1376 if (!section && !entry && !string)
1377 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1378 else
1379 ret = PROFILE_SetString( section, entry, string );
1380 }
1381
1382 LeaveCriticalSection( &PROFILE_CritSect );
1383 return ret;
1384}
1385
1386/***********************************************************************
1387 * WritePrivateProfileString32W (KERNEL32.583)
1388 */
1389ODINFUNCTION4(BOOL, WritePrivateProfileStringW,
1390 LPCWSTR, section,
1391 LPCWSTR, entry,
1392 LPCWSTR, string,
1393 LPCWSTR, filename)
1394{
1395 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1396 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1397 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1398 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1399 BOOL res = CALL_ODINFUNC(WritePrivateProfileStringA)( sectionA, entryA,
1400 stringA, filenameA );
1401 HeapFree( GetProcessHeap(), 0, sectionA );
1402 HeapFree( GetProcessHeap(), 0, entryA );
1403 HeapFree( GetProcessHeap(), 0, stringA );
1404 HeapFree( GetProcessHeap(), 0, filenameA );
1405 return res;
1406}
1407
1408/***********************************************************************
1409 * WritePrivateProfileSection32A (KERNEL32)
1410 */
1411ODINFUNCTION3(BOOL, WritePrivateProfileSectionA,
1412 LPCSTR, section,
1413 LPCSTR, string,
1414 LPCSTR, filename)
1415{
1416 BOOL ret = FALSE;
1417 LPSTR p ;
1418
1419 dprintf(("WritePrivateProfileSectionA %s %s %s", section, string, filename));
1420
1421 EnterCriticalSection( &PROFILE_CritSect );
1422
1423 if (PROFILE_Open( filename )) {
1424 if (!section && !string)
1425 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1426 else if (!string) /* delete the named section*/
1427 ret = PROFILE_SetString(section,NULL,NULL);
1428 else {
1429 PROFILE_DeleteAllKeys(section);
1430 ret = TRUE;
1431 while(*string) {
1432 LPSTR buf=HEAP_strdupA( GetProcessHeap(), 0, string );
1433 if((p=strchr( buf, '='))){
1434 *p='\0';
1435 ret = PROFILE_SetString( section, buf, p+1 );
1436
1437 }
1438 HeapFree( GetProcessHeap(), 0, buf );
1439 string += strlen(string)+1;
1440 }
1441
1442 }
1443 }
1444
1445 LeaveCriticalSection( &PROFILE_CritSect );
1446 return ret;
1447}
1448
1449/***********************************************************************
1450 * WritePrivateProfileSection32W (KERNEL32)
1451 */
1452ODINFUNCTION3(BOOL, WritePrivateProfileSectionW,
1453 LPCWSTR, section,
1454 LPCWSTR, string,
1455 LPCWSTR, filename)
1456{
1457 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1458 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1459 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1460 BOOL res = CALL_ODINFUNC(WritePrivateProfileSectionA)( sectionA, stringA, filenameA );
1461 HeapFree( GetProcessHeap(), 0, sectionA );
1462 HeapFree( GetProcessHeap(), 0, stringA );
1463 HeapFree( GetProcessHeap(), 0, filenameA );
1464 return res;
1465}
1466
1467/***********************************************************************
1468 * WriteProfileSection32A (KERNEL32.747)
1469 */
1470ODINFUNCTION2(BOOL, WriteProfileSectionA,
1471 LPCSTR, section,
1472 LPCSTR, keys_n_values)
1473{
1474 return CALL_ODINFUNC(WritePrivateProfileSectionA)( section, keys_n_values, WINININAME);
1475}
1476
1477/***********************************************************************
1478 * WriteProfileSection32W (KERNEL32.748)
1479 */
1480ODINFUNCTION2(BOOL, WriteProfileSectionW,
1481 LPCWSTR, section,
1482 LPCWSTR, keys_n_values)
1483{
1484 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME);
1485
1486 return (CALL_ODINFUNC(WritePrivateProfileSectionW) (section,keys_n_values, wininiW));
1487}
1488
1489/***********************************************************************
1490 * GetPrivateProfileSectionNames16 (KERNEL.143)
1491 */
1492ODINFUNCTION3(WORD, GetPrivateProfileSectionNames16,
1493 LPSTR, buffer,
1494 WORD, size,
1495 LPCSTR, filename)
1496{
1497 WORD ret = 0;
1498
1499 EnterCriticalSection( &PROFILE_CritSect );
1500
1501 if (PROFILE_Open( filename ))
1502 ret = PROFILE_GetSectionNames(buffer, size);
1503
1504 LeaveCriticalSection( &PROFILE_CritSect );
1505
1506 return ret;
1507}
1508
1509/***********************************************************************
1510 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1511 */
1512ODINFUNCTION3(DWORD, GetPrivateProfileSectionNamesA,
1513 LPSTR, buffer,
1514 DWORD, size,
1515 LPCSTR, filename)
1516{
1517 return (CALL_ODINFUNC(GetPrivateProfileSectionNames16) (buffer,size,filename));
1518}
1519
1520/***********************************************************************
1521 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1522 */
1523ODINFUNCTION3(DWORD, GetPrivateProfileSectionNamesW,
1524 LPWSTR, buffer,
1525 DWORD, size,
1526 LPCWSTR, filename)
1527{
1528 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1529 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size);
1530
1531 INT ret = CALL_ODINFUNC(GetPrivateProfileSectionNames16) (bufferA, size, filenameA);
1532 lstrcpynAtoW( buffer, bufferA, size);
1533 HeapFree( GetProcessHeap(), 0, bufferA);
1534 HeapFree( GetProcessHeap(), 0, filenameA );
1535
1536 return ret;
1537}
1538
1539/***********************************************************************
1540 * GetPrivateProfileStruct32A (KERNEL32.370)
1541 */
1542ODINFUNCTION5(BOOL, GetPrivateProfileStructA,
1543 LPCSTR, section,
1544 LPCSTR, key,
1545 LPVOID, buf,
1546 UINT, len,
1547 LPCSTR, filename)
1548{
1549 BOOL ret = FALSE;
1550
1551 EnterCriticalSection( &PROFILE_CritSect );
1552
1553 if (PROFILE_Open( filename )) {
1554 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1555 if (k) {
1556 lstrcpynA( (LPSTR)buf, k->value, strlen(k->value));
1557 ret = TRUE;
1558 }
1559 }
1560 LeaveCriticalSection( &PROFILE_CritSect );
1561
1562 return FALSE;
1563}
1564
1565/***********************************************************************
1566 * GetPrivateProfileStruct32W (KERNEL32.543)
1567 */
1568ODINFUNCTION5(BOOL, GetPrivateProfileStructW,
1569 LPCWSTR, section,
1570 LPCWSTR, key,
1571 LPVOID, buffer,
1572 UINT, len,
1573 LPCWSTR, filename)
1574{
1575 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1576 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1577 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1578 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1579
1580 INT ret = CALL_ODINFUNC(GetPrivateProfileStructA)( sectionA, keyA, bufferA,
1581 len, filenameA );
1582 lstrcpynAtoW( (LPWSTR)buffer, bufferA, len );
1583 HeapFree( GetProcessHeap(), 0, bufferA);
1584 HeapFree( GetProcessHeap(), 0, sectionA );
1585 HeapFree( GetProcessHeap(), 0, keyA );
1586 HeapFree( GetProcessHeap(), 0, filenameA );
1587
1588 return ret;
1589}
1590
1591
1592/***********************************************************************
1593 * WritePrivateProfileStruct32A (KERNEL32.744)
1594 */
1595ODINFUNCTION5(BOOL, WritePrivateProfileStructA,
1596 LPCSTR, section,
1597 LPCSTR, key,
1598 LPVOID, buf,
1599 UINT, bufsize,
1600 LPCSTR, filename)
1601{
1602 BOOL ret = FALSE;
1603
1604 if (!section && !key && !buf) /* flush the cache */
1605 return CALL_ODINFUNC(WritePrivateProfileStringA)( NULL, NULL, NULL, filename );
1606
1607 EnterCriticalSection( &PROFILE_CritSect );
1608
1609 if (PROFILE_Open( filename ))
1610 ret = PROFILE_SetString( section, key, (LPCSTR)buf );
1611
1612 LeaveCriticalSection( &PROFILE_CritSect );
1613
1614 return ret;
1615}
1616
1617/***********************************************************************
1618 * WritePrivateProfileStruct32W (KERNEL32.544)
1619 */
1620ODINFUNCTION5(BOOL, WritePrivateProfileStructW,
1621 LPCWSTR, section,
1622 LPCWSTR, key,
1623 LPVOID, buf,
1624 UINT, bufsize,
1625 LPCWSTR, filename)
1626{
1627 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1628 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1629 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1630 INT ret = CALL_ODINFUNC(WritePrivateProfileStructA)( sectionA, keyA, buf, bufsize,
1631 filenameA );
1632 HeapFree( GetProcessHeap(), 0, sectionA );
1633 HeapFree( GetProcessHeap(), 0, keyA );
1634 HeapFree( GetProcessHeap(), 0, filenameA );
1635
1636 return ret;
1637}
1638
1639/***********************************************************************
1640 * WriteOutProfiles (KERNEL.315)
1641 * CB: original: 16 bit function
1642 * here: necessary to save open ini files
1643 */
1644ODINPROCEDURE0(WriteOutProfiles)
1645{
1646 PROFILEROOT *lastCurProfile;
1647 INT x;
1648
1649 PROFILE_SaveOdinIni();
1650
1651 EnterCriticalSection(&PROFILE_CritSect);
1652
1653 if (CurProfile && CurProfile->filename)
1654 PROFILE_FlushFile(); //flash current
1655
1656 if (MRUProfile)
1657 {
1658 lastCurProfile = CurProfile;
1659 for(x = 1;x < N_CACHED_PROFILES;x++)
1660 {
1661 if (MRUProfile[x] && MRUProfile[x]->filename)
1662 {
1663 CurProfile = MRUProfile[x];
1664 PROFILE_FlushFile();
1665 }
1666 }
1667 CurProfile = lastCurProfile;
1668 }
1669 LeaveCriticalSection(&PROFILE_CritSect);
1670}
1671
1672
1673/***********************************************************************
1674 * CloseProfileUserMapping (KERNEL.138)
1675 */
1676BOOL WINAPI CloseProfileUserMapping(void)
1677{
1678 dprintf(("CloseProfileUserMapping: STUB"));
1679 return TRUE;
1680}
1681
1682BOOL WINAPI OpenProfileUserMapping(void)
1683{
1684 dprintf(("OpenProfileUserMapping: STUB"));
1685 return TRUE;
1686}
1687
Note: See TracBrowser for help on using the repository browser.