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

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

strncpy call changes + language api updates/fixes

File size: 46.6 KB
Line 
1/* $Id: profile.cpp,v 1.23 2000-07-06 21:18:44 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);
968 PROFILE_OdinIniUsed[MAX_PATHNAME_LEN-1] = 0;
969 }
970 else
971 {
972 HINSTANCE hInstance = LoadLibraryA("KERNEL32.DLL");
973 GetModuleFileNameA(hInstance,PROFILE_OdinIniUsed,sizeof(PROFILE_OdinIniUsed));
974 FreeLibrary(hInstance);
975 strcpy(strrchr(PROFILE_OdinIniUsed,'\\')+1,ODINININAME);
976 f = fopen(PROFILE_OdinIniUsed,"r");
977 PROFILE_OdinProfile = PROFILE_Load(f);
978 fclose(f);
979 }
980
981 dprintf(("Kernel32: Odin ini loaded: %s",PROFILE_OdinIniUsed));
982
983 return 1;
984}
985
986ODINFUNCTION0(int,PROFILE_SaveOdinIni)
987{
988 int ret;
989 FILE *file;
990
991 EnterCriticalSection( &PROFILE_CritSect );
992
993 if (OdinProfileChanged)
994 {
995 file = fopen(PROFILE_OdinIniUsed,"w");
996 if (!file)
997 {
998 dprintf(("Kernel32:Odin profile:could not save profile file %s\n", PROFILE_OdinIniUsed));
999 ret = FALSE;
1000 } else
1001 {
1002 dprintf(("Kernel32:Odin profile:Saving %s\n", PROFILE_OdinIniUsed ));
1003 PROFILE_Save( file, PROFILE_OdinProfile );
1004 fclose( file );
1005 OdinProfileChanged = FALSE;
1006 ret = TRUE;
1007 }
1008 }
1009
1010 LeaveCriticalSection( &PROFILE_CritSect );
1011
1012 return ret;
1013}
1014
1015#if 0
1016/***********************************************************************
1017 * PROFILE_UsageOdinIni
1018 *
1019 * Explain the wine.ini file to those who don't read documentation.
1020 * Keep below one screenful in length so that error messages above are
1021 * noticed.
1022 */
1023void PROFILE_UsageOdinIni(void)
1024{
1025 MESSAGE("Perhaps you have not properly edited or created "
1026 "your Odin configuration file.\n");
1027 MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
1028 MESSAGE(" or it is determined by the -config option or from\n"
1029 " the WINE_INI environment variable.\n");
1030 if (*PROFILE_WineIniUsed)
1031 MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
1032 /* RTFM, so to say */
1033}
1034#endif
1035
1036/***********************************************************************
1037 * PROFILE_GetStringItem
1038 *
1039 * Convenience function that turns a string 'xxx, yyy, zzz' into
1040 * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
1041 */
1042char* PROFILE_GetStringItem( char* start )
1043{
1044 char* lpchX, *lpch;
1045
1046 for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
1047 {
1048 if( *lpchX == ',' )
1049 {
1050 if( lpch ) *lpch = '\0'; else *lpchX = '\0';
1051 while( *(++lpchX) )
1052 if( !PROFILE_isspace(*lpchX) ) return lpchX;
1053 }
1054 else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
1055 else lpch = NULL;
1056 }
1057 if( lpch ) *lpch = '\0';
1058 return NULL;
1059}
1060
1061/********************* API functions **********************************/
1062
1063/***********************************************************************
1064 * GetProfileInt32A (KERNEL32.264)
1065 */
1066ODINFUNCTION3(UINT, GetProfileIntA,
1067 LPCSTR, section,
1068 LPCSTR, entry,
1069 INT, def_val)
1070{
1071 return GetPrivateProfileIntA( section, entry, def_val, WINININAME );
1072}
1073
1074/***********************************************************************
1075 * GetProfileInt32W (KERNEL32.264)
1076 */
1077ODINFUNCTION3(UINT, GetProfileIntW,
1078 LPCWSTR, section,
1079 LPCWSTR, entry,
1080 INT, def_val)
1081{
1082 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1083 return GetPrivateProfileIntW( section, entry, def_val, wininiW );
1084}
1085
1086/***********************************************************************
1087 * GetProfileString32A (KERNEL32.268)
1088 */
1089ODINFUNCTION5(INT, GetProfileStringA,
1090 LPCSTR, section,
1091 LPCSTR, entry,
1092 LPCSTR, def_val,
1093 LPSTR, buffer,
1094 UINT, len)
1095{
1096 return GetPrivateProfileStringA( section, entry, def_val,
1097 buffer, len, WINININAME );
1098}
1099
1100/***********************************************************************
1101 * GetProfileString32W (KERNEL32.269)
1102 */
1103ODINFUNCTION5(INT, GetProfileStringW,
1104 LPCWSTR, section,
1105 LPCWSTR, entry,
1106 LPCWSTR, def_val,
1107 LPWSTR, buffer,
1108 UINT, len)
1109{
1110 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1111 return GetPrivateProfileStringW( section, entry, def_val,
1112 buffer, len, wininiW );
1113}
1114
1115/***********************************************************************
1116 * WriteProfileString32A (KERNEL32.587)
1117 */
1118ODINFUNCTION3(BOOL, WriteProfileStringA,
1119 LPCSTR, section,
1120 LPCSTR, entry,
1121 LPCSTR, string)
1122{
1123 return WritePrivateProfileStringA( section, entry, string, WINININAME );
1124}
1125
1126/***********************************************************************
1127 * WriteProfileString32W (KERNEL32.588)
1128 */
1129ODINFUNCTION3(BOOL, WriteProfileStringW,
1130 LPCWSTR, section,
1131 LPCWSTR, entry,
1132 LPCWSTR, string)
1133{
1134 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1135 return WritePrivateProfileStringW( section, entry, string, wininiW );
1136}
1137
1138/***********************************************************************
1139 * GetPrivateProfileInt32A (KERNEL32.251)
1140 */
1141ODINFUNCTION4(UINT, GetPrivateProfileIntA,
1142 LPCSTR, section,
1143 LPCSTR, entry,
1144 INT, def_val,
1145 LPCSTR, filename)
1146{
1147 char buffer[20];
1148 char *p;
1149 long result;
1150
1151 GetPrivateProfileStringA( section, entry, "",
1152 buffer, sizeof(buffer), filename );
1153 if (!buffer[0]) return (UINT)def_val;
1154 result = strtol( buffer, &p, 0 );
1155 if (p == buffer) return 0; /* No digits at all */
1156 return (UINT)result;
1157}
1158
1159/***********************************************************************
1160 * GetPrivateProfileInt32W (KERNEL32.252)
1161 */
1162ODINFUNCTION4(UINT, GetPrivateProfileIntW,
1163 LPCWSTR, section,
1164 LPCWSTR, entry,
1165 INT, def_val,
1166 LPCWSTR, filename)
1167{
1168 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1169 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1170 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1171 UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
1172 HeapFree( GetProcessHeap(), 0, sectionA );
1173 HeapFree( GetProcessHeap(), 0, filenameA );
1174 HeapFree( GetProcessHeap(), 0, entryA );
1175 return res;
1176}
1177
1178/***********************************************************************
1179 * GetPrivateProfileString32A (KERNEL32.255)
1180 */
1181ODINFUNCTION6(INT, GetPrivateProfileStringA,
1182 LPCSTR, section,
1183 LPCSTR, entry,
1184 LPCSTR, def_val,
1185 LPSTR, buffer,
1186 UINT, len,
1187 LPCSTR, filename)
1188{
1189 int ret;
1190
1191 if (!filename)
1192 filename = WINININAME;
1193
1194 EnterCriticalSection( &PROFILE_CritSect );
1195
1196 if (PROFILE_Open( filename )) {
1197 ret = PROFILE_GetString( section, entry, def_val, buffer, len );
1198 } else {
1199 lstrcpynA( buffer, def_val, len );
1200 ret = strlen( buffer );
1201 }
1202
1203 LeaveCriticalSection( &PROFILE_CritSect );
1204
1205 return ret;
1206}
1207
1208/***********************************************************************
1209 * GetPrivateProfileString32W (KERNEL32.256)
1210 */
1211ODINFUNCTION6(INT, GetPrivateProfileStringW,
1212 LPCWSTR, section,
1213 LPCWSTR, entry,
1214 LPCWSTR, def_val,
1215 LPWSTR, buffer,
1216 UINT, len,
1217 LPCWSTR, filename)
1218{
1219 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1220 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1221 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1222 LPSTR def_valA = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
1223 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1224 INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
1225 bufferA, len, filenameA );
1226 lstrcpynAtoW( buffer, bufferA, len );
1227 HeapFree( GetProcessHeap(), 0, sectionA );
1228 HeapFree( GetProcessHeap(), 0, entryA );
1229 HeapFree( GetProcessHeap(), 0, filenameA );
1230 HeapFree( GetProcessHeap(), 0, def_valA );
1231 HeapFree( GetProcessHeap(), 0, bufferA);
1232 return ret;
1233}
1234
1235/***********************************************************************
1236 * GetPrivateProfileSection32A (KERNEL32.255)
1237 */
1238ODINFUNCTION4(INT, GetPrivateProfileSectionA,
1239 LPCSTR, section,
1240 LPSTR, buffer,
1241 DWORD, len,
1242 LPCSTR, filename)
1243{
1244 int ret = 0;
1245
1246 EnterCriticalSection( &PROFILE_CritSect );
1247
1248 if (PROFILE_Open( filename ))
1249 ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
1250 FALSE, TRUE);
1251
1252 LeaveCriticalSection( &PROFILE_CritSect );
1253
1254 return ret;
1255}
1256
1257/***********************************************************************
1258 * GetPrivateProfileSection32W (KERNEL32.256)
1259 */
1260
1261ODINFUNCTION4(INT, GetPrivateProfileSectionW,
1262 LPCWSTR, section,
1263 LPWSTR, buffer,
1264 DWORD, len,
1265 LPCWSTR, filename)
1266
1267{
1268 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1269 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1270 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1271 INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
1272 filenameA );
1273 MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
1274 HeapFree( GetProcessHeap(), 0, sectionA );
1275 HeapFree( GetProcessHeap(), 0, filenameA );
1276 HeapFree( GetProcessHeap(), 0, bufferA);
1277 return ret;
1278}
1279
1280/***********************************************************************
1281 * GetProfileSection32A (KERNEL32.268)
1282 */
1283ODINFUNCTION3(INT, GetProfileSectionA,
1284 LPCSTR, section,
1285 LPSTR, buffer,
1286 DWORD, len)
1287{
1288 return GetPrivateProfileSectionA( section, buffer, len, WINININAME );
1289}
1290
1291/***********************************************************************
1292 * GetProfileSection32W (KERNEL32)
1293 */
1294ODINFUNCTION3(INT, GetProfileSectionW,
1295 LPCWSTR, section,
1296 LPWSTR, buffer,
1297 DWORD, len)
1298{
1299 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME );
1300 return GetPrivateProfileSectionW( section, buffer, len, wininiW );
1301}
1302
1303/***********************************************************************
1304 * WritePrivateProfileString32A (KERNEL32.582)
1305 */
1306ODINFUNCTION4(BOOL, WritePrivateProfileStringA,
1307 LPCSTR, section,
1308 LPCSTR, entry,
1309 LPCSTR, string,
1310 LPCSTR, filename)
1311{
1312 BOOL ret = FALSE;
1313
1314 EnterCriticalSection( &PROFILE_CritSect );
1315
1316 if (PROFILE_Open( filename ))
1317 {
1318 if (!section && !entry && !string)
1319 PROFILE_ReleaseFile(); /* always return FALSE in this case */
1320 else
1321 ret = PROFILE_SetString( section, entry, string );
1322 }
1323
1324 LeaveCriticalSection( &PROFILE_CritSect );
1325 return ret;
1326}
1327
1328/***********************************************************************
1329 * WritePrivateProfileString32W (KERNEL32.583)
1330 */
1331ODINFUNCTION4(BOOL, WritePrivateProfileStringW,
1332 LPCWSTR, section,
1333 LPCWSTR, entry,
1334 LPCWSTR, string,
1335 LPCWSTR, filename)
1336{
1337 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1338 LPSTR entryA = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
1339 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1340 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1341 BOOL res = WritePrivateProfileStringA( sectionA, entryA,
1342 stringA, filenameA );
1343 HeapFree( GetProcessHeap(), 0, sectionA );
1344 HeapFree( GetProcessHeap(), 0, entryA );
1345 HeapFree( GetProcessHeap(), 0, stringA );
1346 HeapFree( GetProcessHeap(), 0, filenameA );
1347 return res;
1348}
1349
1350/***********************************************************************
1351 * WritePrivateProfileSection32A (KERNEL32)
1352 */
1353ODINFUNCTION3(BOOL, WritePrivateProfileSectionA,
1354 LPCSTR, section,
1355 LPCSTR, string,
1356 LPCSTR, filename)
1357{
1358 char *p =(char*)string;
1359
1360 dprintf(("Kernel32:Profile:fixme WritePrivateProfileSection32A empty stub\n"));
1361 return FALSE;
1362}
1363
1364/***********************************************************************
1365 * WritePrivateProfileSection32W (KERNEL32)
1366 */
1367ODINFUNCTION3(BOOL, WritePrivateProfileSectionW,
1368 LPCWSTR, section,
1369 LPCWSTR, string,
1370 LPCWSTR, filename)
1371{
1372 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1373 LPSTR stringA = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
1374 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1375 BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
1376 HeapFree( GetProcessHeap(), 0, sectionA );
1377 HeapFree( GetProcessHeap(), 0, stringA );
1378 HeapFree( GetProcessHeap(), 0, filenameA );
1379 return res;
1380}
1381
1382/***********************************************************************
1383 * WriteProfileSection32A (KERNEL32.747)
1384 */
1385ODINFUNCTION2(BOOL, WriteProfileSectionA,
1386 LPCSTR, section,
1387 LPCSTR, keys_n_values)
1388{
1389 return WritePrivateProfileSectionA( section, keys_n_values, WINININAME);
1390}
1391
1392/***********************************************************************
1393 * WriteProfileSection32W (KERNEL32.748)
1394 */
1395ODINFUNCTION2(BOOL, WriteProfileSectionW,
1396 LPCWSTR, section,
1397 LPCWSTR, keys_n_values)
1398{
1399 if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, WINININAME);
1400
1401 return (WritePrivateProfileSectionW (section,keys_n_values, wininiW));
1402}
1403
1404/***********************************************************************
1405 * GetPrivateProfileSectionNames16 (KERNEL.143)
1406 */
1407ODINFUNCTION3(WORD, GetPrivateProfileSectionNames16,
1408 LPSTR, buffer,
1409 WORD, size,
1410 LPCSTR, filename)
1411{
1412 WORD ret = 0;
1413
1414 EnterCriticalSection( &PROFILE_CritSect );
1415
1416 if (PROFILE_Open( filename ))
1417 ret = PROFILE_GetSectionNames(buffer, size);
1418
1419 LeaveCriticalSection( &PROFILE_CritSect );
1420
1421 return ret;
1422}
1423
1424/***********************************************************************
1425 * GetPrivateProfileSectionNames32A (KERNEL32.365)
1426 */
1427ODINFUNCTION3(DWORD, GetPrivateProfileSectionNamesA,
1428 LPSTR, buffer,
1429 DWORD, size,
1430 LPCSTR, filename)
1431{
1432 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
1433}
1434
1435/***********************************************************************
1436 * GetPrivateProfileSectionNames32W (KERNEL32.366)
1437 */
1438ODINFUNCTION3(DWORD, GetPrivateProfileSectionNamesW,
1439 LPWSTR, buffer,
1440 DWORD, size,
1441 LPCWSTR, filename)
1442{
1443 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1444 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size);
1445
1446 INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
1447 lstrcpynAtoW( buffer, bufferA, size);
1448 HeapFree( GetProcessHeap(), 0, bufferA);
1449 HeapFree( GetProcessHeap(), 0, filenameA );
1450
1451 return ret;
1452}
1453
1454/***********************************************************************
1455 * GetPrivateProfileStruct32A (KERNEL32.370)
1456 */
1457ODINFUNCTION5(BOOL, GetPrivateProfileStructA,
1458 LPCSTR, section,
1459 LPCSTR, key,
1460 LPVOID, buf,
1461 UINT, len,
1462 LPCSTR, filename)
1463{
1464 BOOL ret = FALSE;
1465
1466 EnterCriticalSection( &PROFILE_CritSect );
1467
1468 if (PROFILE_Open( filename )) {
1469 PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
1470 if (k) {
1471 lstrcpynA( (LPSTR)buf, k->value, strlen(k->value));
1472 ret = TRUE;
1473 }
1474 }
1475 LeaveCriticalSection( &PROFILE_CritSect );
1476
1477 return FALSE;
1478}
1479
1480/***********************************************************************
1481 * GetPrivateProfileStruct32W (KERNEL32.543)
1482 */
1483ODINFUNCTION5(BOOL, GetPrivateProfileStructW,
1484 LPCWSTR, section,
1485 LPCWSTR, key,
1486 LPVOID, buffer,
1487 UINT, len,
1488 LPCWSTR, filename)
1489{
1490 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1491 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1492 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1493 LPSTR bufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
1494
1495 INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
1496 len, filenameA );
1497 lstrcpynAtoW( (LPWSTR)buffer, bufferA, len );
1498 HeapFree( GetProcessHeap(), 0, bufferA);
1499 HeapFree( GetProcessHeap(), 0, sectionA );
1500 HeapFree( GetProcessHeap(), 0, keyA );
1501 HeapFree( GetProcessHeap(), 0, filenameA );
1502
1503 return ret;
1504}
1505
1506
1507/***********************************************************************
1508 * WritePrivateProfileStruct32A (KERNEL32.744)
1509 */
1510ODINFUNCTION5(BOOL, WritePrivateProfileStructA,
1511 LPCSTR, section,
1512 LPCSTR, key,
1513 LPVOID, buf,
1514 UINT, bufsize,
1515 LPCSTR, filename)
1516{
1517 BOOL ret = FALSE;
1518
1519 if (!section && !key && !buf) /* flush the cache */
1520 return WritePrivateProfileStringA( NULL, NULL, NULL, filename );
1521
1522 EnterCriticalSection( &PROFILE_CritSect );
1523
1524 if (PROFILE_Open( filename ))
1525 ret = PROFILE_SetString( section, key, (LPCSTR)buf );
1526
1527 LeaveCriticalSection( &PROFILE_CritSect );
1528
1529 return ret;
1530}
1531
1532/***********************************************************************
1533 * WritePrivateProfileStruct32W (KERNEL32.544)
1534 */
1535ODINFUNCTION5(BOOL, WritePrivateProfileStructW,
1536 LPCWSTR, section,
1537 LPCWSTR, key,
1538 LPVOID, buf,
1539 UINT, bufsize,
1540 LPCWSTR, filename)
1541{
1542 LPSTR sectionA = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
1543 LPSTR keyA = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
1544 LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
1545 INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
1546 filenameA );
1547 HeapFree( GetProcessHeap(), 0, sectionA );
1548 HeapFree( GetProcessHeap(), 0, keyA );
1549 HeapFree( GetProcessHeap(), 0, filenameA );
1550
1551 return ret;
1552}
1553
1554/***********************************************************************
1555 * WriteOutProfiles (KERNEL.315)
1556 * CB: original: 16 bit function
1557 * here: necessary to save open ini files
1558 */
1559ODINPROCEDURE0(WriteOutProfiles)
1560{
1561 PROFILE *lastCurProfile;
1562 INT x;
1563
1564 PROFILE_SaveOdinIni();
1565
1566 EnterCriticalSection(&PROFILE_CritSect);
1567
1568 if (CurProfile && CurProfile->filename)
1569 PROFILE_FlushFile(); //flash current
1570
1571 if (MRUProfile)
1572 {
1573 lastCurProfile = CurProfile;
1574 for(x = 1;x < N_CACHED_PROFILES;x++)
1575 {
1576 if (MRUProfile[x] && MRUProfile[x]->filename)
1577 {
1578 CurProfile = MRUProfile[x];
1579 PROFILE_FlushFile();
1580 }
1581 }
1582 CurProfile = lastCurProfile;
1583 }
1584 LeaveCriticalSection(&PROFILE_CritSect);
1585}
1586
1587
1588
Note: See TracBrowser for help on using the repository browser.