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

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

CW: profile fix

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