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

Last change on this file since 4387 was 4387, checked in by sandervl, 25 years ago

fixes for FS macro changes

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