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

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

version changes + misc fixes/changes

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