Release 951226
[wine/gsoc-2012-control.git] / misc / profile.c
blobecd1b72a0311dd0bb62f336f91adb09a3f9c4541
1 /*
2 * Initialization-File Functions.
4 * Copyright (c) 1993 Miguel de Icaza
6 * 1/Dec o Corrected return values for Get*ProfileString
8 * o Now, if AppName == NULL in Get*ProfileString it returns a list
9 * of the KeyNames (as documented in the MS-SDK).
11 * o if KeyValue == NULL now clears the value in Get*ProfileString
13 * 20/Apr SL - I'm not sure where these definitions came from, but my SDK
14 * has a NULL KeyValue returning a list of KeyNames, and a NULL
15 * AppName undefined. I changed GetSetProfile to match. This makes
16 * PROGMAN.EXE do the right thing.
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
23 #include "wine.h"
24 #include "windows.h"
25 #include "dos_fs.h"
26 #include "toolhelp.h"
27 #include "stddebug.h"
28 #include "debug.h"
29 #include "xmalloc.h"
31 #define STRSIZE 255
33 typedef struct TKeys {
34 char *KeyName;
35 char *Value;
36 struct TKeys *link;
37 } TKeys;
39 typedef struct TSecHeader {
40 char *AppName;
41 TKeys *Keys;
42 struct TSecHeader *link;
43 } TSecHeader;
45 typedef struct TProfile {
46 char *FileName;
47 char *FullName;
48 TSecHeader *Section;
49 struct TProfile *link;
50 int changed;
51 } TProfile;
53 TProfile *Current = 0;
54 TProfile *Base = 0;
56 static TSecHeader *is_loaded (char *FileName)
58 TProfile *p = Base;
60 while (p){
61 if (!strcasecmp (FileName, p->FileName)){
62 Current = p;
63 return p->Section;
65 p = p->link;
67 return 0;
70 static char *GetIniFileName(char *name, char *dir)
72 char temp[256];
74 if (strchr(name, '/'))
75 return name;
77 if (strlen(dir)) {
78 strcpy(temp, dir);
79 strcat(temp, "\\");
80 strcat(temp, name);
82 else
83 strcpy(temp, name);
84 return DOS_GetUnixFileName(temp);
87 static TSecHeader *load (char *filename, char **pfullname)
89 FILE *f;
90 TSecHeader *SecHeader = 0;
91 char CharBuffer [STRSIZE];
92 char *bufptr;
93 char *lastnonspc;
94 int bufsize;
95 char *file, *purefilename;
96 int c;
97 char path[MAX_PATH+1];
98 BOOL firstbrace;
100 *pfullname = NULL;
102 dprintf_profile(stddeb,"Trying to load file %s \n", filename);
104 /* First try it as is */
105 file = GetIniFileName(filename, "");
106 f = fopen(file, "r");
108 if (f == NULL) {
110 if ((purefilename = strrchr( filename, '\\' )))
111 purefilename++;
112 else if ((purefilename = strrchr( filename, '/' )))
113 purefilename++;
114 else
115 purefilename = filename;
116 ToUnix(purefilename);
118 /* Now try the Windows directory */
119 GetWindowsDirectory(path, sizeof(path));
120 file = GetIniFileName(purefilename, path);
121 dprintf_profile(stddeb,"Trying to load in windows directory file %s\n",
122 file);
123 f = fopen(file, "r");
125 if (f == NULL) { /* Try the path of the current executable */
127 if (GetCurrentTask())
129 char *p;
130 GetModuleFileName( GetCurrentTask(), path, MAX_PATH );
131 if ((p = strrchr( path, '\\' )))
133 p[0] = '\0'; /* Remove trailing slash */
134 file = GetIniFileName(purefilename, path);
135 dprintf_profile(stddeb,
136 "Trying to load in current directory%s\n",
137 file);
138 f = fopen(file, "r");
142 if (f == NULL) { /* And now in $HOME/.wine */
144 strcpy(file,getenv("HOME"));
145 strcat(file, "/.wine/");
146 strcat(file, purefilename);
147 dprintf_profile(stddeb,"Trying to load in user-directory %s\n", file);
148 f = fopen(file, "r");
151 if (f == NULL) {
152 /* FIXED: we ought to create it now (in which directory?) */
153 /* lets do it in ~/.wine */
154 strcpy(file,getenv("HOME"));
155 strcat(file, "/.wine/");
156 strcat(file, purefilename);
157 dprintf_profile(stddeb,"Creating %s\n", file);
158 f = fopen(file, "w+");
159 if (f == NULL) {
160 fprintf(stderr, "profile.c: load() can't find file %s\n", filename);
161 return NULL;
166 *pfullname = strdup(file);
167 dprintf_profile(stddeb,"Loading %s\n", file);
169 firstbrace = TRUE;
170 for(;;) {
171 c = fgetc(f);
172 if (c == EOF) goto finished;
174 if (isspace(c))
175 continue;
176 if (c == ';') {
177 do {
178 c = fgetc(f);
179 } while (!(c == EOF || c == '\n'));
180 if (c == EOF) goto finished;
182 if (c == '[') {
183 TSecHeader *temp = SecHeader;
185 SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader));
186 SecHeader->link = temp;
187 SecHeader->Keys = NULL;
188 do {
189 c = fgetc(f);
190 if (c == EOF) goto bad_file;
191 } while (isspace(c));
192 bufptr = lastnonspc = CharBuffer;
193 bufsize = 0;
194 do {
195 if (c != ']') {
196 bufsize++;
197 *bufptr++ = c;
198 if (!isspace(c))
199 lastnonspc = bufptr;
200 } else
201 break;
202 c = fgetc(f);
203 if (c == EOF) goto bad_file;
204 } while(bufsize < STRSIZE-1);
205 *lastnonspc = 0;
206 if (!strlen(CharBuffer))
207 fprintf(stderr, "warning: empty section name in ini file\n");
208 SecHeader->AppName = strdup (CharBuffer);
209 dprintf_profile(stddeb,"%s: section %s\n", file, CharBuffer);
210 firstbrace = FALSE;
211 } else if (SecHeader) {
212 TKeys *temp = SecHeader->Keys;
213 BOOL skipspc;
215 if (firstbrace)
216 goto bad_file;
217 bufptr = lastnonspc = CharBuffer;
218 bufsize = 0;
219 do {
220 if (c != '=') {
221 bufsize++;
222 *bufptr++ = c;
223 if (!isspace(c))
224 lastnonspc = bufptr;
225 } else
226 break;
227 c = fgetc(f);
228 if (c == EOF) goto bad_file;
229 } while(bufsize < STRSIZE-1);
230 *lastnonspc = 0;
231 if (!strlen(CharBuffer))
232 fprintf(stderr, "warning: empty key name in ini file\n");
233 SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys));
234 SecHeader->Keys->link = temp;
235 SecHeader->Keys->KeyName = strdup (CharBuffer);
237 dprintf_profile(stddeb,"%s: key %s\n", file, CharBuffer);
239 bufptr = lastnonspc = CharBuffer;
240 bufsize = 0;
241 skipspc = TRUE;
242 do {
243 c = fgetc(f);
244 if (c == EOF || c == '\n') break;
245 if (!isspace(c) || !skipspc) {
246 skipspc = FALSE;
247 bufsize++;
248 *bufptr++ = c;
249 if (!isspace(c))
250 lastnonspc = bufptr;
252 } while(bufsize < STRSIZE-1);
253 *lastnonspc = 0;
254 SecHeader->Keys->Value = strdup (CharBuffer);
255 dprintf_profile (stddeb, "[%s] (%s)=%s\n", SecHeader->AppName,
256 SecHeader->Keys->KeyName, SecHeader->Keys->Value);
257 if (c == ';') {
258 do {
259 c = fgetc(f);
260 } while (!(c == EOF || c == '\n'));
261 if (c == EOF)
262 goto finished;
267 bad_file:
268 fprintf(stderr, "warning: bad ini file\n");
269 finished:
270 return SecHeader;
273 static void new_key (TSecHeader *section, char *KeyName, char *Value)
275 TKeys *key;
277 key = (TKeys *) xmalloc (sizeof (TKeys));
278 key->KeyName = strdup (KeyName);
279 key->Value = strdup (Value);
280 key->link = section->Keys;
281 section->Keys = key;
284 static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
285 LPSTR Default, LPSTR ReturnedString, short Size,
286 LPSTR FileName)
289 TProfile *New;
290 TSecHeader *section;
291 TKeys *key;
293 /* Supposedly Default should NEVER be NULL. But sometimes it is. */
294 if (Default == NULL)
295 Default = "";
297 if (!(section = is_loaded (FileName))){
298 New = (TProfile *) xmalloc (sizeof (TProfile));
299 New->link = Base;
300 New->FileName = strdup (FileName);
301 New->Section = load (FileName, &New->FullName);
302 New->changed = FALSE;
303 Base = New;
304 section = New->Section;
305 Current = New;
308 /* Start search */
309 for (; section; section = section->link){
310 if (strcasecmp (section->AppName, AppName))
311 continue;
313 /* If no key value given, then list all the keys */
314 if ((!KeyName) && (!set)){
315 char *p = ReturnedString;
316 int left = Size - 2;
317 int slen;
319 dprintf_profile(stddeb,"GetSetProfile // KeyName == NULL, Enumeration !\n");
320 for (key = section->Keys; key; key = key->link){
321 if (left < 1) {
322 dprintf_profile(stddeb,"GetSetProfile // No more storage for enum !\n");
323 return Size - 2;
325 slen = MIN(strlen(key->KeyName) + 1, left);
326 lstrcpyn(p, key->KeyName, slen);
327 dprintf_profile(stddeb,"GetSetProfile // enum '%s' !\n", p);
328 left -= slen;
329 p += slen;
331 *p = '\0';
332 return Size - 2 - left;
334 for (key = section->Keys; key; key = key->link){
335 int slen;
336 if (strcasecmp (key->KeyName, KeyName))
337 continue;
338 if (set){
339 free (key->Value);
340 key->Value = strdup (Default ? Default : "");
341 Current->changed=TRUE;
342 return 1;
344 slen = MIN(strlen(key->Value)+1, Size);
345 lstrcpyn(ReturnedString, key->Value, slen);
346 dprintf_profile(stddeb,"GetSetProfile // Return ``%s''\n", ReturnedString);
347 return 1;
349 /* If Getting the information, then don't write the information
350 to the INI file, need to run a couple of tests with windog */
351 /* No key found */
352 if (set) {
353 new_key (section, KeyName, Default);
354 } else {
355 int slen = MIN(strlen(Default)+1, Size);
356 lstrcpyn(ReturnedString, Default, slen);
357 dprintf_profile(stddeb,"GetSetProfile // Key not found\n");
359 return 1;
362 /* Non existent section */
363 if (set){
364 section = (TSecHeader *) xmalloc (sizeof (TSecHeader));
365 section->AppName = strdup (AppName);
366 section->Keys = 0;
367 new_key (section, KeyName, Default);
368 section->link = Current->Section;
369 Current->Section = section;
370 Current->changed = TRUE;
371 } else {
372 int slen = MIN(strlen(Default)+1, Size);
373 lstrcpyn(ReturnedString, Default, slen);
374 dprintf_profile(stddeb,"GetSetProfile // Section not found\n");
376 return 1;
379 short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
380 LPSTR Default, LPSTR ReturnedString,
381 short Size, LPSTR FileName)
383 int v;
385 dprintf_profile(stddeb,"GetPrivateProfileString ('%s', '%s', '%s', %p, %d, %s\n",
386 AppName, KeyName, Default, ReturnedString, Size, FileName);
387 v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
388 if (AppName)
389 return strlen (ReturnedString);
390 else
391 return Size - v;
394 int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default,
395 LPSTR ReturnedString, int Size)
397 return GetPrivateProfileString (AppName, KeyName, Default,
398 ReturnedString, Size, WIN_INI);
401 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
402 LPSTR File)
404 static char IntBuf[10];
405 static char buf[10];
407 sprintf (buf, "%d", Default);
409 /* Check the exact semantic with the SDK */
410 GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 10, File);
411 if (!strcasecmp (IntBuf, "true"))
412 return 1;
413 if (!strcasecmp (IntBuf, "yes"))
414 return 1;
415 return strtoul( IntBuf, NULL, 0 );
418 WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
420 return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
423 BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
424 LPSTR FileName)
426 if (!AppName || !KeyName || !String) /* Flush file to disk */
427 return TRUE;
428 return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
431 BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String)
433 return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI));
436 static void dump_keys (FILE *profile, TKeys *p)
438 if (!p)
439 return;
440 dump_keys (profile, p->link);
441 fprintf (profile, "%s=%s\r\n", p->KeyName, p->Value);
444 static void dump_sections (FILE *profile, TSecHeader *p)
446 if (!p)
447 return;
448 dump_sections (profile, p->link);
449 fprintf (profile, "\r\n[%s]\r\n", p->AppName);
450 dump_keys (profile, p->Keys);
453 static void dump_profile (TProfile *p)
455 FILE *profile;
457 if (!p)
458 return;
459 dump_profile (p->link);
460 if(!p->changed)
461 return;
462 if (p->FullName && (profile = fopen (p->FullName, "w")) != NULL){
463 dump_sections (profile, p->Section);
464 fclose (profile);
468 void sync_profiles (void)
470 dump_profile (Base);