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

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

Rewrite of PE loader code, EB's fixes + VirtualProtect bugfix

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