/* * Initialization-File Functions. * * Copyright (c) 1993 Miguel de Icaza * * 1/Dec o Corrected return values for Get*ProfileString * * o Now, if AppName == NULL in Get*ProfileString it returns a list * of the KeyNames (as documented in the MS-SDK). * * o if KeyValue == NULL now clears the value in Get*ProfileString * * 20/Apr SL - I'm not sure where these definitions came from, but my SDK * has a NULL KeyValue returning a list of KeyNames, and a NULL * AppName undefined. I changed GetSetProfile to match. This makes * PROGMAN.EXE do the right thing. * static char Copyright [] = "Copyright (C) 1993 Miguel de Icaza"; */ #include #include #include #include "wine.h" #include "windows.h" #include "dos_fs.h" #include "stddebug.h" /* #define DEBUG_PROFILE */ #include "debug.h" #define STRSIZE 255 #define xmalloc(x) malloc(x) #define overflow (next == &CharBuffer [STRSIZE-1]) enum { FirstBrace, OnSecHeader, IgnoreToEOL, KeyDef, KeyValue }; typedef struct TKeys { char *KeyName; char *Value; struct TKeys *link; } TKeys; typedef struct TSecHeader { char *AppName; TKeys *Keys; struct TSecHeader *link; } TSecHeader; typedef struct TProfile { char *FileName; TSecHeader *Section; struct TProfile *link; int changed; } TProfile; TProfile *Current = 0; TProfile *Base = 0; static TSecHeader *is_loaded (char *FileName) { TProfile *p = Base; while (p){ if (!strcasecmp (FileName, p->FileName)){ Current = p; return p->Section; } p = p->link; } return 0; } static char *GetIniFileName(char *name) { char temp[256]; if (strchr(name, '/')) return name; if (strchr(name, '\\')) return DOS_GetUnixFileName(name); GetWindowsDirectory(temp, sizeof(temp) ); strcat(temp, "\\"); strcat(temp, name); return DOS_GetUnixFileName(temp); } static TSecHeader *load (char *filename) { FILE *f; int state; TSecHeader *SecHeader = 0; char CharBuffer [STRSIZE]; char *next, *file; char c; file = GetIniFileName(filename); dprintf_profile(stddeb,"Load %s\n", file); if ((f = fopen (file, "r"))==NULL) return NULL; dprintf_profile(stddeb,"Loading %s\n", file); state = FirstBrace; while ((c = getc (f)) != EOF){ if (c == '\r') /* Ignore Carriage Return */ continue; switch (state){ case OnSecHeader: if (c == ']' || overflow){ *next = '\0'; next = CharBuffer; SecHeader->AppName = strdup (CharBuffer); state = IgnoreToEOL; dprintf_profile(stddeb,"%s: section %s\n", file, CharBuffer); } else *next++ = c; break; case IgnoreToEOL: if (c == '\n'){ state = KeyDef; next = CharBuffer; } break; case FirstBrace: case KeyDef: if (c == '['){ TSecHeader *temp; temp = SecHeader; SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader)); SecHeader->link = temp; SecHeader->Keys = 0; state = OnSecHeader; next = CharBuffer; break; } if (state == FirstBrace) /* On first pass, don't allow dangling keys */ break; if (c == '\t') break; if (c == '\n' || c == ';' || overflow) /* Abort Definition */ next = CharBuffer; if (c == ';') { state = IgnoreToEOL; break; } if (c == '=' || overflow){ TKeys *temp; temp = SecHeader->Keys; while(next[-1]==' ')next--; *next = '\0'; SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys)); SecHeader->Keys->link = temp; SecHeader->Keys->KeyName = strdup (CharBuffer); state = KeyValue; next = CharBuffer; dprintf_profile(stddeb,"%s: key %s\n", file, CharBuffer); } else *next++ = c; break; case KeyValue: if (overflow || c == '\n'){ *next = '\0'; SecHeader->Keys->Value = strdup (CharBuffer); state = c == '\n' ? KeyDef : IgnoreToEOL; next = CharBuffer; dprintf_profile (stddeb, "[%s] (%s)=%s\n", SecHeader->AppName, SecHeader->Keys->KeyName, SecHeader->Keys->Value); } else *next++ = c; break; } /* switch */ } /* while ((c = getc (f)) != EOF) */ return SecHeader; } static void new_key (TSecHeader *section, char *KeyName, char *Value) { TKeys *key; key = (TKeys *) xmalloc (sizeof (TKeys)); key->KeyName = strdup (KeyName); key->Value = strdup (Value); key->link = section->Keys; section->Keys = key; } static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName, LPSTR Default, LPSTR ReturnedString, short Size, LPSTR FileName) { TProfile *New; TSecHeader *section; TKeys *key; /* Supposedly Default should NEVER be NULL. But sometimes it is. */ if (Default == NULL) Default = ""; if (!(section = is_loaded (FileName))){ New = (TProfile *) xmalloc (sizeof (TProfile)); New->link = Base; New->FileName = strdup (FileName); New->Section = load (FileName); New->changed = FALSE; Base = New; section = New->Section; Current = New; } /* Start search */ for (; section; section = section->link){ if (strcasecmp (section->AppName, AppName)) continue; /* If no key value given, then list all the keys */ if ((!KeyName) && (!set)){ char *p = ReturnedString; int left = Size - 2; int slen; dprintf_profile(stddeb,"GetSetProfile // KeyName == NULL, Enumeration !\n"); for (key = section->Keys; key; key = key->link){ if (left < 1) { dprintf_profile(stddeb,"GetSetProfile // No more storage for enum !\n"); return (Size - 2); } slen = min(strlen(key->KeyName) + 1, left); dprintf_profile(stddeb,"GetSetProfile // strncpy(%p, %p, %d);\n", ReturnedString, key->Value, slen); strncpy (p, key->KeyName, slen); dprintf_profile(stddeb,"GetSetProfile // enum '%s' !\n", p); left -= slen; p += slen; } *p = '\0'; dprintf_profile(stddeb,"GetSetProfile // normal end of enum !\n"); return (Size - 2 - left); } for (key = section->Keys; key; key = key->link){ if (strcasecmp (key->KeyName, KeyName)) continue; if (set){ free (key->Value); key->Value = strdup (Default ? Default : ""); Current->changed=TRUE; return 1; } ReturnedString [Size-1] = 0; strncpy (ReturnedString, key->Value, Size-1); return 1; } /* If Getting the information, then don't write the information to the INI file, need to run a couple of tests with windog */ /* No key found */ if (set) new_key (section, KeyName, Default); else { ReturnedString [Size-1] = 0; strncpy (ReturnedString, Default, Size-1); } return 1; } /* Non existent section */ if (set){ section = (TSecHeader *) xmalloc (sizeof (TSecHeader)); section->AppName = strdup (AppName); section->Keys = 0; new_key (section, KeyName, Default); section->link = Current->Section; Current->Section = section; Current->changed = TRUE; } else { ReturnedString [Size-1] = 0; strncpy (ReturnedString, Default, Size-1); } return 1; } short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default, LPSTR ReturnedString, short Size, LPSTR FileName) { int v; dprintf_profile(stddeb,"GetPrivateProfileString ('%s', '%s', '%s', %p, %d, %s\n", AppName, KeyName, Default, ReturnedString, Size, FileName); v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName); if (AppName) return strlen (ReturnedString); else return Size - v; } int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default, LPSTR ReturnedString, int Size) { return GetPrivateProfileString (AppName, KeyName, Default, ReturnedString, Size, WIN_INI); } WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default, LPSTR File) { static char IntBuf [6]; static char buf [6]; sprintf (buf, "%d", Default); /* Check the exact semantic with the SDK */ GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 6, File); if (!strcasecmp (IntBuf, "true")) return 1; if (!strcasecmp (IntBuf, "yes")) return 1; return atoi (IntBuf); } WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default) { return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI); } BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String, LPSTR FileName) { return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName); } BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String) { return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI)); } static void dump_keys (FILE *profile, TKeys *p) { if (!p) return; dump_keys (profile, p->link); fprintf (profile, "%s=%s\r\n", p->KeyName, p->Value); } static void dump_sections (FILE *profile, TSecHeader *p) { if (!p) return; dump_sections (profile, p->link); fprintf (profile, "\r\n[%s]\r\n", p->AppName); dump_keys (profile, p->Keys); } static void dump_profile (TProfile *p) { FILE *profile; if (!p) return; dump_profile (p->link); if(!p->changed) return; if ((profile = fopen (GetIniFileName(p->FileName), "w")) != NULL){ dump_sections (profile, p->Section); fclose (profile); } } void sync_profiles (void) { dump_profile (Base); }