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

Last change on this file since 21355 was 21355, checked in by rlwalsh, 15 years ago

eliminate VACPP warning & info msgs - see Ticket #1

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