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

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

Added new logging feature

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