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

Last change on this file since 4353 was 4353, checked in by phaller, 25 years ago

Optimization

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