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

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

heapstring fixes + dll renaming support added

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