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

Last change on this file since 1370 was 1370, checked in by sandervl, 26 years ago

Odin ini changes

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