diff options
Diffstat (limited to 'storage/connect/inihandl.c')
-rw-r--r-- | storage/connect/inihandl.c | 2650 |
1 files changed, 1325 insertions, 1325 deletions
diff --git a/storage/connect/inihandl.c b/storage/connect/inihandl.c index 91fb95a2df9..6c13faf58c8 100644 --- a/storage/connect/inihandl.c +++ b/storage/connect/inihandl.c @@ -1,1325 +1,1325 @@ -/*
- * Profile functions
- *
- * Copyright 1993 Miguel de Icaza
- * Copyright 1996 Alexandre Julliard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <ctype.h>
-//#include <errno.h>
-#include <fcntl.h>
-//#include <io.h> commented this line out to compile for solaris
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/stat.h>
-//#include <sys/types.h>
-//#include <memory.h>
-#include "my_global.h"
-//#include "osutil.h"
-#include "global.h"
-
-
-// The types and variables used locally
-//typedef int bool;
-typedef unsigned int uint;
-#define DWORD int
-#define TRUE 1
-#define FALSE 0
-#define SVP(S) ((S) ? S : "<null>")
-#define _strlwr(P) strlwr(P) //OB: changed this line
-#define MAX_PATHNAME_LEN 256
-#define N_CACHED_PROFILES 10
-#ifndef WIN32
-#define stricmp strcasecmp
-#define _strnicmp strncasecmp
-#endif // !WIN32
-#define EnterCriticalSection(x)
-#define LeaveCriticalSection(x)
-
-#if defined(TEST_MODULE)
-// Stand alone test program
-#include <stdarg.h>
- int trace = 0;
-void htrc(char const *fmt, ...)
-{
- va_list ap;
- va_start (ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end (ap);
-} /* end of htrc */
-#else // !TEST_MODULE
-// Normal included functions
-extern int trace;
-void htrc(char const *fmt, ...);
-#endif // !TEST MODULE
-
-
-typedef struct tagPROFILEKEY {
- char *value;
- struct tagPROFILEKEY *next;
- char name[1];
- } PROFILEKEY;
-
-typedef struct tagPROFILESECTION {
- struct tagPROFILEKEY *key;
- struct tagPROFILESECTION *next;
- char name[1];
- } PROFILESECTION;
-
-typedef struct {
- bool changed;
- PROFILESECTION *section;
-//char *dos_name;
-//char *unix_name;
- char *filename;
- time_t mtime;
- } PROFILE;
-
-#define memfree(P) if (P) free(P)
-
-/* Cached profile files */
-static PROFILE *MRUProfile[N_CACHED_PROFILES] = {NULL};
-
-#define CurProfile (MRUProfile[0])
-
-/* wine.ini config file registry root */
-//static HKEY wine_profile_key;
-
-#define PROFILE_MAX_LINE_LEN 1024
-
-/* Wine profile name in $HOME directory; must begin with slash */
-static const char PROFILE_WineIniName[] = "/.winerc";
-
-/* Wine profile: the profile file being used */
-static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
-
-/* Check for comments in profile */
-#define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
-
-//static const WCHAR wininiW[] = { 'w','i','n','.','i','n','i',0 };
-
-//static CRITICAL_SECTION PROFILE_CritSect = CRITICAL_SECTION_INIT("PROFILE_CritSect");
-
-static const char hex[16] = "0123456789ABCDEF";
-
-bool WritePrivateProfileString(LPCSTR section, LPCSTR entry,
- LPCSTR string, LPCSTR filename );
-/***********************************************************************
- * PROFILE_CopyEntry
- *
- * Copy the content of an entry into a buffer, removing quotes,
- * and possibly translating environment variables.
- ***********************************************************************/
-static void PROFILE_CopyEntry( char *buffer, const char *value, uint len,
- int handle_env )
-{
- const char *p;
- char quote = '\0';
-
- if (!buffer)
- return;
-
- if ((*value == '\'') || (*value == '\"'))
- if (value[1] && (value[strlen(value)-1] == *value))
- quote = *value++;
-
- if (!handle_env) {
- strncpy(buffer, value, len);
-
- if (quote && (len >= strlen(value)))
- buffer[strlen(buffer)-1] = '\0';
-
- return;
- } // endif handle
-
- for (p = value; (*p && (len > 1)); *buffer++ = *p++, len--) {
- if ((*p == '$') && (p[1] == '{')) {
- char env_val[1024];
- const char *env_p;
- const char *p2 = strchr(p, '}');
-
- if (!p2)
- continue; /* ignore it */
-
- strncpy(env_val, p + 2, min(sizeof(env_val), (int)(p2-p)-1));
-
- if ((env_p = getenv(env_val)) != NULL) {
- int buffer_len;
-
- strncpy( buffer, env_p, len );
- buffer_len = strlen( buffer );
- buffer += buffer_len;
- len -= buffer_len;
- } // endif env_p
-
- p = p2 + 1;
- } // endif p
-
- } // endfor p
-
- if (quote && (len > 1))
- buffer--;
-
- *buffer = '\0';
-} // end of PROFILE_CopyEntry
-
-
-/***********************************************************************
- * PROFILE_Save
- *
- * Save a profile tree to a file.
- ***********************************************************************/
-static void PROFILE_Save( FILE *file, PROFILESECTION *section )
-{
- PROFILEKEY *key;
-
- for (; section; section = section->next) {
- if (section->name[0])
- fprintf(file, "\n[%s]\n", SVP(section->name));
-
- for (key = section->key; key; key = key->next)
- if (key->name && key->name[0]) {
- fprintf(file, "%s", SVP(key->name));
-
- if (key->value)
- fprintf(file, "=%s", SVP(key->value));
-
- fprintf(file, "\n");
- } // endif key->name
-
- } // endfor section
-
-} // end of PROFILE_Save
-
-
-/***********************************************************************
- * PROFILE_Free
- *
- * Free a profile tree.
- ***********************************************************************/
-static void PROFILE_Free( PROFILESECTION *section )
-{
- PROFILESECTION *next_section;
- PROFILEKEY *key, *next_key;
-
- for (; section; section = next_section) {
- for (key = section->key; key; key = next_key) {
- next_key = key->next;
- memfree(key->value);
- free(key);
- } // endfor key
-
- next_section = section->next;
- free(section);
- } // endfor section
-
-} // end of PROFILE_Free
-
-static int PROFILE_isspace(char c)
-{
- /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
- if (isspace(c) || c=='\r' || c==0x1a)
- return 1;
-
- return 0;
-} // end of PROFILE_isspace
-
-
-/***********************************************************************
- * PROFILE_Load
- *
- * Load a profile tree from a file.
- ***********************************************************************/
-static PROFILESECTION *PROFILE_Load( FILE *file )
-{
- char buffer[PROFILE_MAX_LINE_LEN];
- char *p, *p2;
- int line = 0;
- PROFILESECTION *section, *first_section;
- PROFILESECTION* *next_section;
- PROFILEKEY *key, *prev_key, **next_key;
-
- first_section = malloc(sizeof(*section));
-
- if (first_section == NULL)
- return NULL;
-
- first_section->name[0] = 0;
- first_section->key = NULL;
- first_section->next = NULL;
- next_section = &first_section->next;
- next_key = &first_section->key;
- prev_key = NULL;
-
- while (fgets(buffer, PROFILE_MAX_LINE_LEN, file)) {
- line++;
- p = buffer;
-
- while (*p && PROFILE_isspace(*p))
- p++;
-
- if (*p == '[') { /* section start */
- if (!(p2 = strrchr( p, ']'))) {
- fprintf(stderr, "Invalid section header at line %d: '%s'\n",
- line, p);
- } else {
- *p2 = '\0';
- p++;
-
- if (!(section = malloc(sizeof(*section) + strlen(p))))
- break;
-
- strcpy(section->name, p);
- section->key = NULL;
- section->next = NULL;
- *next_section = section;
- next_section = §ion->next;
- next_key = §ion->key;
- prev_key = NULL;
-
- if (trace > 1)
- htrc("New section: '%s'\n",section->name);
-
- continue;
- } // endif p2
-
- } // endif p
-
- p2 = p + strlen(p) - 1;
-
- while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2)))
- *p2-- = '\0';
-
- if ((p2 = strchr(p, '=')) != NULL) {
- char *p3 = p2 - 1;
-
- while ((p3 > p) && PROFILE_isspace(*p3))
- *p3-- = '\0';
-
- *p2++ = '\0';
-
- while (*p2 && PROFILE_isspace(*p2))
- p2++;
-
- } // endif p2
-
- if (*p || !prev_key || *prev_key->name) {
- if (!(key = malloc(sizeof(*key) + strlen(p))))
- break;
-
- strcpy(key->name, p);
-
- if (p2) {
- key->value = malloc(strlen(p2)+1);
- strcpy(key->value, p2);
- } else
- key->value = NULL;
-
- key->next = NULL;
- *next_key = key;
- next_key = &key->next;
- prev_key = key;
-
- if (trace > 1)
- htrc("New key: name='%s', value='%s'\n",
- key->name,key->value?key->value:"(none)");
-
- } // endif p || prev_key
-
- } // endif *p
-
- return first_section;
-} // end of PROFILE_Load
-
-/***********************************************************************
- * PROFILE_FlushFile
- *
- * Flush the current profile to disk if changed.
- ***********************************************************************/
-static bool PROFILE_FlushFile(void)
-{
-//char *p, buffer[MAX_PATHNAME_LEN];
-//const char *unix_name;
- FILE *file = NULL;
- struct stat buf;
-
- if (trace > 1)
- htrc("PROFILE_FlushFile: CurProfile=%p\n", CurProfile);
-
- if (!CurProfile) {
- fprintf(stderr, "No current profile!\n");
- return FALSE;
- } // endif !CurProfile
-
- if (!CurProfile->changed || !CurProfile->filename)
- return TRUE;
-
-#if 0
- if (!(file = fopen(unix_name, "w"))) {
- /* Try to create it in $HOME/.wine */
- /* FIXME: this will need a more general solution */
- //strcpy( buffer, get_config_dir() );
- //p = buffer + strlen(buffer);
- //*p++ = '/';
- char *p1 = strrchr(CurProfile->filename, '\\');
-
- p = buffer; // OB: To be elaborate
-
- if (p1)
- p1++;
- else
- p1 = CurProfile->dos_name;
-
- strcpy(p, p1);
- _strlwr(p);
- file = fopen(buffer, "w");
- unix_name = buffer;
- } // endif !unix_name
-#endif // 0
-
- if (!(file = fopen(CurProfile->filename, "w"))) {
- fprintf(stderr, "could not save profile file %s\n", CurProfile->filename);
- return FALSE;
- } // endif !file
-
- if (trace > 1)
- htrc("Saving '%s'\n", CurProfile->filename);
-
- PROFILE_Save(file, CurProfile->section);
- fclose(file);
- CurProfile->changed = FALSE;
-
- if (!stat(CurProfile->filename, &buf))
- CurProfile->mtime = buf.st_mtime;
-
- return TRUE;
-} // end of PROFILE_FlushFile
-
-
-/***********************************************************************
- * PROFILE_ReleaseFile
- *
- * Flush the current profile to disk and remove it from the cache.
- ***********************************************************************/
-static void PROFILE_ReleaseFile(void)
-{
- PROFILE_FlushFile();
- PROFILE_Free(CurProfile->section);
-//memfree(CurProfile->dos_name);
-//memfree(CurProfile->unix_name);
- memfree(CurProfile->filename);
- CurProfile->changed = FALSE;
- CurProfile->section = NULL;
-//CurProfile->dos_name = NULL;
-//CurProfile->unix_name = NULL;
- CurProfile->filename = NULL;
- CurProfile->mtime = 0;
-} // end of PROFILE_ReleaseFile
-
-
-/***********************************************************************
- * PROFILE_Open
- *
- * Open a profile file, checking the cached file first.
- ***********************************************************************/
-static bool PROFILE_Open(LPCSTR filename)
-{
-//char buffer[MAX_PATHNAME_LEN];
-//char *p;
- FILE *file = NULL;
- int i, j;
- struct stat buf;
- PROFILE *tempProfile;
-
- if (trace > 1)
- htrc("PROFILE_Open: CurProfile=%p N=%d\n", CurProfile, N_CACHED_PROFILES);
-
- /* First time around */
- if (!CurProfile)
- for (i = 0; i < N_CACHED_PROFILES; i++) {
- MRUProfile[i] = malloc(sizeof(PROFILE));
-
- if (MRUProfile[i] == NULL)
- break;
-
- MRUProfile[i]->changed=FALSE;
- MRUProfile[i]->section=NULL;
-// MRUProfile[i]->dos_name=NULL;
-// MRUProfile[i]->unix_name=NULL;
- MRUProfile[i]->filename=NULL;
- MRUProfile[i]->mtime=0;
- } // endfor i
-
- /* Check for a match */
- for (i = 0; i < N_CACHED_PROFILES; i++) {
- if (trace > 1)
- htrc("MRU=%s i=%d\n", SVP(MRUProfile[i]->filename), i);
-
- if (MRUProfile[i]->filename && !strcmp(filename, MRUProfile[i]->filename)) {
- if (i) {
- PROFILE_FlushFile();
- tempProfile = MRUProfile[i];
-
- for (j = i; j > 0; j--)
- MRUProfile[j] = MRUProfile[j-1];
-
- CurProfile=tempProfile;
- } // endif i
-
- if (!stat(CurProfile->filename, &buf) && CurProfile->mtime == buf.st_mtime) {
- if (trace > 1)
- htrc("(%s): already opened (mru=%d)\n", filename, i);
-
- } else {
- if (trace > 1)
- htrc("(%s): already opened, needs refreshing (mru=%d)\n", filename, i);
-
- } // endif stat
-
- return TRUE;
- } // endif filename
-
- } // endfor i
-
- /* Flush the old current profile */
- PROFILE_FlushFile();
-
- /* Make the oldest profile the current one only in order to get rid of it */
- if (i == N_CACHED_PROFILES) {
- tempProfile = MRUProfile[N_CACHED_PROFILES-1];
-
- for(i = N_CACHED_PROFILES-1; i > 0; i--)
- MRUProfile[i] = MRUProfile[i-1];
-
- CurProfile = tempProfile;
- } // endif i
-
- if (CurProfile->filename)
- PROFILE_ReleaseFile();
-
- /* OK, now that CurProfile is definitely free we assign it our new file */
-// newdos_name = HeapAlloc( GetProcessHeap(), 0, strlen(full_name.short_name)+1 );
-// strcpy( newdos_name, full_name.short_name );
-
-// newdos_name = malloc(strlen(filename)+1);
-// strcpy(newdos_name, filename);
-
-// CurProfile->dos_name = newdos_name;
- CurProfile->filename = malloc(strlen(filename) + 1);
- strcpy(CurProfile->filename, filename);
-
- /* Try to open the profile file, first in $HOME/.wine */
-
- /* FIXME: this will need a more general solution */
-// strcpy( buffer, get_config_dir() );
-// p = buffer + strlen(buffer);
-// *p++ = '/';
-// strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
-// p = buffer;
-// strcpy(p, filename);
-// _strlwr(p);
-
- if (trace > 1)
- htrc("Opening %s\n", filename);
-
- if ((file = fopen(filename, "r"))) {
- if (trace > 1)
- htrc("(%s): found it\n", filename);
-
-// CurProfile->unix_name = malloc(strlen(buffer)+1);
-// strcpy(CurProfile->unix_name, buffer);
- } /* endif file */
-
- if (file) {
- CurProfile->section = PROFILE_Load(file);
- fclose(file);
-
- if (!stat(CurProfile->filename, &buf))
- CurProfile->mtime = buf.st_mtime;
-
- } else {
- /* Does not exist yet, we will create it in PROFILE_FlushFile */
- fprintf(stderr, "profile file %s not found\n", filename);
- } /* endif file */
-
- return TRUE;
-}
-
-
-/***********************************************************************
- * PROFILE_DeleteSection
- *
- * Delete a section from a profile tree.
- ***********************************************************************/
-static bool PROFILE_DeleteSection(PROFILESECTION* *section, LPCSTR name)
-{
- while (*section) {
- if ((*section)->name[0] && !stricmp((*section)->name, name)) {
- PROFILESECTION *to_del = *section;
-
- *section = to_del->next;
- to_del->next = NULL;
- PROFILE_Free(to_del);
- return TRUE;
- } // endif section
-
- section = &(*section)->next;
- } // endwhile section
-
- return FALSE;
-} // end of PROFILE_DeleteSection
-
-
-/***********************************************************************
- * PROFILE_DeleteKey
- *
- * Delete a key from a profile tree.
- ***********************************************************************/
-static bool PROFILE_DeleteKey(PROFILESECTION* *section,
- LPCSTR section_name, LPCSTR key_name)
-{
- while (*section) {
- if ((*section)->name[0] && !stricmp((*section)->name, section_name)) {
- PROFILEKEY* *key = &(*section)->key;
-
- while (*key) {
- if (!stricmp((*key)->name, key_name)) {
- PROFILEKEY *to_del = *key;
-
- *key = to_del->next;
- memfree(to_del->value);
- free(to_del);
- return TRUE;
- } // endif name
-
- key = &(*key)->next;
- } // endwhile *key
-
- } // endif section->name
-
- section = &(*section)->next;
- } // endwhile *section
-
- return FALSE;
-} // end of PROFILE_DeleteKey
-
-
-/***********************************************************************
- * PROFILE_DeleteAllKeys
- *
- * Delete all keys from a profile tree.
- ***********************************************************************/
-void PROFILE_DeleteAllKeys(LPCSTR section_name)
-{
- PROFILESECTION* *section= &CurProfile->section;
-
- while (*section) {
- if ((*section)->name[0] && !stricmp((*section)->name, section_name)) {
- PROFILEKEY* *key = &(*section)->key;
-
- while (*key) {
- PROFILEKEY *to_del = *key;
-
- *key = to_del->next;
- memfree(to_del->value);
- free(to_del);
- CurProfile->changed = TRUE;
- } // endwhile *key
-
- } // endif section->name
-
- section = &(*section)->next;
- } // endwhile *section
-
-} // end of PROFILE_DeleteAllKeys
-
-
-/***********************************************************************
- * PROFILE_Find
- *
- * Find a key in a profile tree, optionally creating it.
- ***********************************************************************/
-static PROFILEKEY *PROFILE_Find(PROFILESECTION* *section,
- const char *section_name,
- const char *key_name,
- bool create, bool create_always)
-{
- const char *p;
- int seclen, keylen;
-
- while (PROFILE_isspace(*section_name))
- section_name++;
-
- p = section_name + strlen(section_name) - 1;
-
- while ((p > section_name) && PROFILE_isspace(*p))
- p--;
-
- seclen = p - section_name + 1;
-
- while (PROFILE_isspace(*key_name))
- key_name++;
-
- p = key_name + strlen(key_name) - 1;
-
- while ((p > key_name) && PROFILE_isspace(*p))
- p--;
-
- keylen = p - key_name + 1;
-
- while (*section) {
- if (((*section)->name[0])
- && (!(_strnicmp((*section)->name, section_name, seclen )))
- && (((*section)->name)[seclen] == '\0')) {
- PROFILEKEY* *key = &(*section)->key;
-
- while (*key) {
- /* If create_always is FALSE then we check if the keyname already exists.
- * Otherwise we add it regardless of its existence, to allow
- * keys to be added more then once in some cases.
- */
- if (!create_always) {
- if ((!(_strnicmp( (*key)->name, key_name, keylen )))
- && (((*key)->name)[keylen] == '\0'))
- return *key;
-
- } // endif !create_always
-
- key = &(*key)->next;
- } // endwhile *key
-
- if (!create)
- return NULL;
-
- if (!(*key = malloc(sizeof(PROFILEKEY) + strlen(key_name))))
- return NULL;
-
- strcpy((*key)->name, key_name);
- (*key)->value = NULL;
- (*key)->next = NULL;
- return *key;
- } // endifsection->name
-
- section = &(*section)->next;
- } // endwhile *section
-
- if (!create)
- return NULL;
-
- *section = malloc(sizeof(PROFILESECTION) + strlen(section_name));
-
- if (*section == NULL)
- return NULL;
-
- strcpy((*section)->name, section_name);
- (*section)->next = NULL;
-
- if (!((*section)->key = malloc(sizeof(PROFILEKEY) + strlen(key_name)))) {
- free(*section);
- return NULL;
- } // endif malloc
-
- strcpy((*section)->key->name, key_name);
- (*section)->key->value = NULL;
- (*section)->key->next = NULL;
- return (*section)->key;
-} // end of PROFILE_Find
-
-
-/***********************************************************************
- * PROFILE_GetSection
- *
- * Returns all keys of a section.
- * If return_values is TRUE, also include the corresponding values.
- ***********************************************************************/
-static int PROFILE_GetSection(PROFILESECTION *section, LPCSTR section_name,
- LPSTR buffer, uint len, bool handle_env,
- bool return_values)
-{
- PROFILEKEY *key;
-
- if(!buffer)
- return 0;
-
- while (section) {
- if (section->name[0] && !stricmp(section->name, section_name)) {
- uint oldlen = len;
-
- for (key = section->key; key; key = key->next) {
- if (len <= 2)
- break;
-
- if (!*key->name)
- continue; /* Skip empty lines */
-
- if (IS_ENTRY_COMMENT(key->name))
- continue; /* Skip comments */
-
- PROFILE_CopyEntry(buffer, key->name, len - 1, handle_env);
- len -= strlen(buffer) + 1;
- buffer += strlen(buffer) + 1;
-
- if (len < 2)
- break;
-
- if (return_values && key->value) {
- buffer[-1] = '=';
- PROFILE_CopyEntry(buffer, key->value, len - 1, handle_env);
- len -= strlen(buffer) + 1;
- buffer += strlen(buffer) + 1;
- } // endif return_values
-
- } // endfor key
-
- *buffer = '\0';
-
- if (len <= 1) {
- /*If either lpszSection or lpszKey is NULL and the supplied
- destination buffer is too small to hold all the strings,
- the last string is truncated and followed by two null characters.
- In this case, the return value is equal to cchReturnBuffer
- minus two. */
- buffer[-1] = '\0';
- return oldlen - 2;
- } // endif len
-
- return oldlen - len;
- } // endif section->name
-
- section = section->next;
- } // endwhile section
-
- buffer[0] = buffer[1] = '\0';
- return 0;
-} // end of PROFILE_GetSection
-
-
-/* See GetPrivateProfileSectionNamesA for documentation */
-static int PROFILE_GetSectionNames(LPSTR buffer, uint len)
-{
- LPSTR buf;
- uint f,l;
- PROFILESECTION *section;
-
- if (trace > 1)
- htrc("GetSectionNames: buffer=%p len=%u\n", buffer, len);
-
- if (!buffer || !len)
- return 0;
-
- if (len == 1) {
- *buffer='\0';
- return 0;
- } // endif len
-
- f = len - 1;
- buf = buffer;
- section = CurProfile->section;
-
- if (trace > 1)
- htrc("GetSectionNames: section=%p\n", section);
-
- while (section != NULL) {
- if (trace > 1)
- htrc("section=%s\n", section->name);
-
- if (section->name[0]) {
- l = strlen(section->name) + 1;
-
- if (trace > 1)
- htrc("l=%u f=%u\n", l, f);
-
- if (l > f) {
- if (f > 0) {
- strncpy(buf, section->name, f-1);
- buf += f-1;
- *buf++='\0';
- } // endif f
-
- *buf = '\0';
- return len - 2;
- } // endif l
-
- strcpy(buf, section->name);
- buf += l;
- f -= l;
- } // endif section->name
-
- section = section->next;
- } // endwhile section
-
- *buf='\0';
- return buf-buffer;
-} // end of PROFILE_GetSectionNames
-
-
-/***********************************************************************
- * PROFILE_GetString
- *
- * Get a profile string.
- *
- * Tests with GetPrivateProfileString16, W95a,
- * with filled buffer ("****...") and section "set1" and key_name "1" valid:
- * section key_name def_val res buffer
- * "set1" "1" "x" 43 [data]
- * "set1" "1 " "x" 43 [data] (!)
- * "set1" " 1 "' "x" 43 [data] (!)
- * "set1" "" "x" 1 "x"
- * "set1" "" "x " 1 "x" (!)
- * "set1" "" " x " 3 " x" (!)
- * "set1" NULL "x" 6 "1\02\03\0\0"
- * "set1" "" "x" 1 "x"
- * NULL "1" "x" 0 "" (!)
- * "" "1" "x" 1 "x"
- * NULL NULL "" 0 ""
- *
- *************************************************************************/
-static int PROFILE_GetString(LPCSTR section, LPCSTR key_name,
- LPCSTR def_val, LPSTR buffer, uint len)
-{
- PROFILEKEY *key = NULL;
-
- if(!buffer)
- return 0;
-
- if (!def_val)
- def_val = "";
-
- if (key_name && key_name[0]) {
- key = PROFILE_Find(&CurProfile->section, section, key_name, FALSE, FALSE);
- PROFILE_CopyEntry(buffer, (key && key->value) ? key->value : def_val, len, FALSE);
-
- if (trace > 1)
- htrc("('%s','%s','%s'): returning '%s'\n",
- section, key_name, def_val, buffer );
-
- return strlen(buffer);
- } // endif key_name
-
- if (key_name && !(key_name[0]))
- /* Win95 returns 0 on keyname "". Tested with Likse32 bon 000227 */
- return 0;
-
- if (section && section[0])
- return PROFILE_GetSection(CurProfile->section, section, buffer, len,
- FALSE, FALSE);
- buffer[0] = '\0';
- return 0;
-} // end of PROFILE_GetString
-
-
-/***********************************************************************
- * PROFILE_SetString
- *
- * Set a profile string.
- ***********************************************************************/
-static bool PROFILE_SetString(LPCSTR section_name, LPCSTR key_name,
- LPCSTR value, bool create_always)
-{
- if (!key_name) { /* Delete a whole section */
- if (trace > 1)
- htrc("Deleting('%s')\n", section_name);
-
- CurProfile->changed |= PROFILE_DeleteSection(&CurProfile->section,
- section_name);
- return TRUE; /* Even if PROFILE_DeleteSection() has failed,
- this is not an error on application's level.*/
- } else if (!value) { /* Delete a key */
- if (trace > 1)
- htrc("Deleting('%s','%s')\n", section_name, key_name);
-
- CurProfile->changed |= PROFILE_DeleteKey(&CurProfile->section,
- section_name, key_name);
- return TRUE; /* same error handling as above */
- } else { /* Set the key value */
- PROFILEKEY *key = PROFILE_Find(&CurProfile->section, section_name,
- key_name, TRUE, create_always);
- if (trace > 1)
- htrc("Setting('%s','%s','%s')\n", section_name, key_name, value);
-
- if (!key)
- return FALSE;
-
- if (key->value) {
- /* strip the leading spaces. We can safely strip \n\r and
- * friends too, they should not happen here anyway. */
- while (PROFILE_isspace(*value))
- value++;
-
- if (!strcmp(key->value, value)) {
- if (trace > 1)
- htrc(" no change needed\n" );
-
- return TRUE; /* No change needed */
- } // endif value
-
- if (trace > 1)
- htrc(" replacing '%s'\n", key->value);
-
- free(key->value);
- } else if (trace > 1)
- htrc(" creating key\n" );
-
- key->value = malloc(strlen(value) + 1);
- strcpy(key->value, value);
- CurProfile->changed = TRUE;
- } // endelse
-
- return TRUE;
-} // end of PROFILE_SetString
-
-
-/***********************************************************************
- * PROFILE_GetStringItem
- *
- * Convenience function that turns a string 'xxx, yyy, zzz' into
- * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
- ***********************************************************************/
-char *PROFILE_GetStringItem(char* start)
-{
- char *lpchX, *lpch;
-
- for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++) {
- if (*lpchX == ',') {
- if (lpch)
- *lpch = '\0';
- else
- *lpchX = '\0';
-
- while(*(++lpchX))
- if (!PROFILE_isspace(*lpchX))
- return lpchX;
-
- } else if (PROFILE_isspace(*lpchX) && !lpch) {
- lpch = lpchX;
- } else
- lpch = NULL;
-
- } // endfor lpchX
-
- if (lpch)
- *lpch = '\0';
-
- return NULL;
-} // end of PROFILE_GetStringItem
-
-/**********************************************************************
- * if allow_section_name_copy is TRUE, allow the copying :
- * - of Section names if 'section' is NULL
- * - of Keys in a Section if 'entry' is NULL
- * (see MSDN doc for GetPrivateProfileString)
- **********************************************************************/
-static int PROFILE_GetPrivateProfileString(LPCSTR section, LPCSTR entry,
- LPCSTR def_val, LPSTR buffer,
- uint len, LPCSTR filename,
- bool allow_section_name_copy)
-{
- int ret;
- LPSTR pDefVal = NULL;
-
- if (!filename)
- filename = "win.ini";
-
- /* strip any trailing ' ' of def_val. */
- if (def_val) {
- LPSTR p = (LPSTR)&def_val[strlen(def_val)]; // even "" works !
-
- while (p > def_val)
- if ((*(--p)) != ' ')
- break;
-
- if (*p == ' ') { /* ouch, contained trailing ' ' */
- int len = p - (LPSTR)def_val;
-
- pDefVal = malloc(len + 1);
- strncpy(pDefVal, def_val, len);
- pDefVal[len] = '\0';
- } // endif *p
-
- } // endif def_val
-
- if (!pDefVal)
- pDefVal = (LPSTR)def_val;
-
- EnterCriticalSection(&PROFILE_CritSect);
-
- if (PROFILE_Open(filename)) {
- if ((allow_section_name_copy) && (section == NULL))
- ret = PROFILE_GetSectionNames(buffer, len);
- else
- /* PROFILE_GetString already handles the 'entry == NULL' case */
- ret = PROFILE_GetString(section, entry, pDefVal, buffer, len);
-
- } else {
- strncpy(buffer, pDefVal, len);
- ret = strlen(buffer);
- } // endif Open
-
- LeaveCriticalSection(&PROFILE_CritSect);
-
- if (pDefVal != def_val) /* allocated */
- memfree(pDefVal);
-
- return ret;
-} // end of PROFILE_GetPrivateProfileString
-
-/********************** API functions **********************************/
-
-/***********************************************************************
- * GetPrivateProfileStringA (KERNEL32.@)
- ***********************************************************************/
-int GetPrivateProfileString(LPCSTR section, LPCSTR entry, LPCSTR def_val,
- LPSTR buffer, uint len, LPCSTR filename)
-{
- return PROFILE_GetPrivateProfileString(section, entry, def_val,
- buffer, len, filename, TRUE);
-} // end of GetPrivateProfileString
-
-
-/***********************************************************************
- * GetPrivateProfileIntA (KERNEL32.@)
- ***********************************************************************/
-uint GetPrivateProfileInt(LPCSTR section, LPCSTR entry,
- int def_val, LPCSTR filename)
-{
- char buffer[20];
- int result;
-
- if (!PROFILE_GetPrivateProfileString(section, entry, "", buffer,
- sizeof(buffer), filename, FALSE))
- return def_val;
-
- /* FIXME: if entry can be found but it's empty, then Win16 is
- * supposed to return 0 instead of def_val ! Difficult/problematic
- * to implement (every other failure also returns zero buffer),
- * thus wait until testing framework avail for making sure nothing
- * else gets broken that way. */
- if (!buffer[0])
- return (uint)def_val;
-
- /* Don't use strtol() here !
- * (returns LONG_MAX/MIN on overflow instead of "proper" overflow)
- YES, scan for unsigned format ! (otherwise compatibility error) */
- if (!sscanf(buffer, "%u", &result))
- return 0;
-
- return (uint)result;
-} // end of GetPrivateProfileInt
-
-
-/***********************************************************************
- * GetPrivateProfileSectionA (KERNEL32.@)
- ***********************************************************************/
-int GetPrivateProfileSection(LPCSTR section, LPSTR buffer,
- DWORD len, LPCSTR filename)
-{
- int ret = 0;
-
- EnterCriticalSection( &PROFILE_CritSect );
-
- if (PROFILE_Open(filename))
- ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
- FALSE, TRUE);
-
- LeaveCriticalSection( &PROFILE_CritSect );
- return ret;
-} // end of GetPrivateProfileSection
-
-
-/***********************************************************************
- * WritePrivateProfileStringA (KERNEL32.@)
- ***********************************************************************/
-bool WritePrivateProfileString(LPCSTR section, LPCSTR entry,
- LPCSTR string, LPCSTR filename)
-{
- bool ret = FALSE;
-
- EnterCriticalSection( &PROFILE_CritSect );
-
- if (PROFILE_Open(filename)) {
- if (!section && !entry && !string) /* documented "file flush" case */
- PROFILE_ReleaseFile(); /* always return FALSE in this case */
- else {
- if (!section) {
- //FIXME("(NULL?,%s,%s,%s)? \n",entry,string,filename);
- } else {
- ret = PROFILE_SetString(section, entry, string, FALSE);
-
- if (ret)
- ret = PROFILE_FlushFile();
-
- } // endif section
-
- } // endif section || entry|| string
-
- } // endif Open
-
- LeaveCriticalSection( &PROFILE_CritSect );
- return ret;
-} // end of WritePrivateProfileString
-
-
-/***********************************************************************
- * WritePrivateProfileSectionA (KERNEL32.@)
- ***********************************************************************/
-bool WritePrivateProfileSection(LPCSTR section,
- LPCSTR string, LPCSTR filename )
-{
- bool ret = FALSE;
- LPSTR p ;
-
- EnterCriticalSection(&PROFILE_CritSect);
-
- if (PROFILE_Open(filename)) {
- if (!section && !string)
- PROFILE_ReleaseFile(); /* always return FALSE in this case */
- else if (!string) { /* delete the named section*/
- ret = PROFILE_SetString(section, NULL, NULL, FALSE);
-
- if (ret)
- ret = PROFILE_FlushFile();
- } else {
- PROFILE_DeleteAllKeys(section);
- ret = TRUE;
-
- while (*string) {
- LPSTR buf = malloc(strlen(string) + 1);
- strcpy(buf, string);
-
- if ((p = strchr(buf, '='))) {
- *p='\0';
- ret = PROFILE_SetString(section, buf, p+1, TRUE);
- } // endif p
-
- free(buf);
- string += strlen(string) + 1;
-
- if (ret)
- ret = PROFILE_FlushFile();
-
- } // endwhile *string
-
- } // endelse
-
- } // endif Open
-
- LeaveCriticalSection(&PROFILE_CritSect);
- return ret;
-} // end of WritePrivateProfileSection
-
-
-/***********************************************************************
- * GetPrivateProfileSectionNamesA (KERNEL32.@)
- *
- * Returns the section names contained in the specified file.
- * FIXME: Where do we find this file when the path is relative?
- * The section names are returned as a list of strings with an extra
- * '\0' to mark the end of the list. Except for that the behavior
- * depends on the Windows version.
- *
- * Win95:
- * - if the buffer is 0 or 1 character long then it is as if it was of
- * infinite length.
- * - otherwise, if the buffer is to small only the section names that fit
- * are returned.
- * - note that this means if the buffer was to small to return even just
- * the first section name then a single '\0' will be returned.
- * - the return value is the number of characters written in the buffer,
- * except if the buffer was too smal in which case len-2 is returned
- *
- * Win2000:
- * - if the buffer is 0, 1 or 2 characters long then it is filled with
- * '\0' and the return value is 0
- * - otherwise if the buffer is too small then the first section name that
- * does not fit is truncated so that the string list can be terminated
- * correctly (double '\0')
- * - the return value is the number of characters written in the buffer
- * except for the trailing '\0'. If the buffer is too small, then the
- * return value is len-2
- * - Win2000 has a bug that triggers when the section names and the
- * trailing '\0' fit exactly in the buffer. In that case the trailing
- * '\0' is missing.
- *
- * Wine implements the observed Win2000 behavior (except for the bug).
- *
- * Note that when the buffer is big enough then the return value may be any
- * value between 1 and len-1 (or len in Win95), including len-2.
- */
-DWORD GetPrivateProfileSectionNames(LPSTR buffer, DWORD size, LPCSTR filename)
-{
- DWORD ret = 0;
-
- if (trace > 1)
- htrc("GPPSN: filename=%s\n", filename);
-
- EnterCriticalSection(&PROFILE_CritSect);
-
- if (PROFILE_Open(filename))
- ret = PROFILE_GetSectionNames(buffer, size);
-
- LeaveCriticalSection(&PROFILE_CritSect);
- return ret;
-} // end of GetPrivateProfileSectionNames
-
-
-/************************************************************************
- * Program to test the above
- ************************************************************************/
-#ifdef TEST_MODULE
-int main(int argc, char**argv) {
- char buff[128];
- char *p, *inifile = "D:\\Plug\\Data\\contact.ini";
- DWORD n;
-
- n = GetPrivateProfileSectionNames(buff, 128, inifile);
- printf("Sections: n=%d\n", n);
-
- for (p = buff; *p; p += (strlen(p) + 1))
- printf("section=[%s]\n", p);
-
- GetPrivateProfileString("BER", "name", "?", buff, 128, inifile);
- printf("[BER](name) = %s\n", buff);
-
- WritePrivateProfileString("FOO", "city", NULL, inifile);
- GetPrivateProfileString("FOO", "city", "?", buff, 128, inifile);
- printf("[FOO](city) = %s\n", buff);
-
- printf("FOO city: ");
- fgets(buff, sizeof(buff), stdin);
- if (buff[strlen(buff) - 1] == '\n')
- buff[strlen(buff) - 1] = '\0';
- WritePrivateProfileString("FOO", "city", buff, inifile);
- GetPrivateProfileString("FOO", "city", "???", buff, 128, inifile);
- printf("After write, [FOO](City) = %s\n", buff);
-
- printf("New city: ");
- fgets(buff, sizeof(buff), stdin);
- if (buff[strlen(buff) - 1] == '\n')
- buff[strlen(buff) - 1] = '\0';
- WritePrivateProfileString("FOO", "city", buff, inifile);
- GetPrivateProfileString("FOO", "city", "???", buff, 128, inifile);
- printf("After update, [FOO](City) = %s\n", buff);
-
- printf("FOO name: ");
- fgets(buff, sizeof(buff), stdin);
- if (buff[strlen(buff) - 1] == '\n')
- buff[strlen(buff) - 1] = '\0';
- WritePrivateProfileString("FOO", "name", buff, inifile);
- GetPrivateProfileString("FOO", "name", "X", buff, 128, inifile);
- printf("[FOO](name) = %s\n", buff);
-} // end of main
-#endif // TEST_MODULE
+/* + * Profile functions + * + * Copyright 1993 Miguel de Icaza + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <ctype.h> +//#include <errno.h> +#include <fcntl.h> +//#include <io.h> commented this line out to compile for solaris +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/stat.h> +//#include <sys/types.h> +//#include <memory.h> +#include "my_global.h" +//#include "osutil.h" +#include "global.h" + + +// The types and variables used locally +//typedef int bool; +typedef unsigned int uint; +#define DWORD int +#define TRUE 1 +#define FALSE 0 +#define SVP(S) ((S) ? S : "<null>") +#define _strlwr(P) strlwr(P) //OB: changed this line +#define MAX_PATHNAME_LEN 256 +#define N_CACHED_PROFILES 10 +#ifndef WIN32 +#define stricmp strcasecmp +#define _strnicmp strncasecmp +#endif // !WIN32 +#define EnterCriticalSection(x) +#define LeaveCriticalSection(x) + +#if defined(TEST_MODULE) +// Stand alone test program +#include <stdarg.h> + int trace = 0; +void htrc(char const *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + vfprintf(stderr, fmt, ap); + va_end (ap); +} /* end of htrc */ +#else // !TEST_MODULE +// Normal included functions +extern int trace; +void htrc(char const *fmt, ...); +#endif // !TEST MODULE + + +typedef struct tagPROFILEKEY { + char *value; + struct tagPROFILEKEY *next; + char name[1]; + } PROFILEKEY; + +typedef struct tagPROFILESECTION { + struct tagPROFILEKEY *key; + struct tagPROFILESECTION *next; + char name[1]; + } PROFILESECTION; + +typedef struct { + bool changed; + PROFILESECTION *section; +//char *dos_name; +//char *unix_name; + char *filename; + time_t mtime; + } PROFILE; + +#define memfree(P) if (P) free(P) + +/* Cached profile files */ +static PROFILE *MRUProfile[N_CACHED_PROFILES] = {NULL}; + +#define CurProfile (MRUProfile[0]) + +/* wine.ini config file registry root */ +//static HKEY wine_profile_key; + +#define PROFILE_MAX_LINE_LEN 1024 + +/* Wine profile name in $HOME directory; must begin with slash */ +static const char PROFILE_WineIniName[] = "/.winerc"; + +/* Wine profile: the profile file being used */ +static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = ""; + +/* Check for comments in profile */ +#define IS_ENTRY_COMMENT(str) ((str)[0] == ';') + +//static const WCHAR wininiW[] = { 'w','i','n','.','i','n','i',0 }; + +//static CRITICAL_SECTION PROFILE_CritSect = CRITICAL_SECTION_INIT("PROFILE_CritSect"); + +static const char hex[16] = "0123456789ABCDEF"; + +bool WritePrivateProfileString(LPCSTR section, LPCSTR entry, + LPCSTR string, LPCSTR filename ); +/*********************************************************************** + * PROFILE_CopyEntry + * + * Copy the content of an entry into a buffer, removing quotes, + * and possibly translating environment variables. + ***********************************************************************/ +static void PROFILE_CopyEntry( char *buffer, const char *value, uint len, + int handle_env ) +{ + const char *p; + char quote = '\0'; + + if (!buffer) + return; + + if ((*value == '\'') || (*value == '\"')) + if (value[1] && (value[strlen(value)-1] == *value)) + quote = *value++; + + if (!handle_env) { + strncpy(buffer, value, len); + + if (quote && (len >= strlen(value))) + buffer[strlen(buffer)-1] = '\0'; + + return; + } // endif handle + + for (p = value; (*p && (len > 1)); *buffer++ = *p++, len--) { + if ((*p == '$') && (p[1] == '{')) { + char env_val[1024]; + const char *env_p; + const char *p2 = strchr(p, '}'); + + if (!p2) + continue; /* ignore it */ + + strncpy(env_val, p + 2, min(sizeof(env_val), (int)(p2-p)-1)); + + if ((env_p = getenv(env_val)) != NULL) { + int buffer_len; + + strncpy( buffer, env_p, len ); + buffer_len = strlen( buffer ); + buffer += buffer_len; + len -= buffer_len; + } // endif env_p + + p = p2 + 1; + } // endif p + + } // endfor p + + if (quote && (len > 1)) + buffer--; + + *buffer = '\0'; +} // end of PROFILE_CopyEntry + + +/*********************************************************************** + * PROFILE_Save + * + * Save a profile tree to a file. + ***********************************************************************/ +static void PROFILE_Save( FILE *file, PROFILESECTION *section ) +{ + PROFILEKEY *key; + + for (; section; section = section->next) { + if (section->name[0]) + fprintf(file, "\n[%s]\n", SVP(section->name)); + + for (key = section->key; key; key = key->next) + if (key->name && key->name[0]) { + fprintf(file, "%s", SVP(key->name)); + + if (key->value) + fprintf(file, "=%s", SVP(key->value)); + + fprintf(file, "\n"); + } // endif key->name + + } // endfor section + +} // end of PROFILE_Save + + +/*********************************************************************** + * PROFILE_Free + * + * Free a profile tree. + ***********************************************************************/ +static void PROFILE_Free( PROFILESECTION *section ) +{ + PROFILESECTION *next_section; + PROFILEKEY *key, *next_key; + + for (; section; section = next_section) { + for (key = section->key; key; key = next_key) { + next_key = key->next; + memfree(key->value); + free(key); + } // endfor key + + next_section = section->next; + free(section); + } // endfor section + +} // end of PROFILE_Free + +static int PROFILE_isspace(char c) +{ + /* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */ + if (isspace(c) || c=='\r' || c==0x1a) + return 1; + + return 0; +} // end of PROFILE_isspace + + +/*********************************************************************** + * PROFILE_Load + * + * Load a profile tree from a file. + ***********************************************************************/ +static PROFILESECTION *PROFILE_Load( FILE *file ) +{ + char buffer[PROFILE_MAX_LINE_LEN]; + char *p, *p2; + int line = 0; + PROFILESECTION *section, *first_section; + PROFILESECTION* *next_section; + PROFILEKEY *key, *prev_key, **next_key; + + first_section = malloc(sizeof(*section)); + + if (first_section == NULL) + return NULL; + + first_section->name[0] = 0; + first_section->key = NULL; + first_section->next = NULL; + next_section = &first_section->next; + next_key = &first_section->key; + prev_key = NULL; + + while (fgets(buffer, PROFILE_MAX_LINE_LEN, file)) { + line++; + p = buffer; + + while (*p && PROFILE_isspace(*p)) + p++; + + if (*p == '[') { /* section start */ + if (!(p2 = strrchr( p, ']'))) { + fprintf(stderr, "Invalid section header at line %d: '%s'\n", + line, p); + } else { + *p2 = '\0'; + p++; + + if (!(section = malloc(sizeof(*section) + strlen(p)))) + break; + + strcpy(section->name, p); + section->key = NULL; + section->next = NULL; + *next_section = section; + next_section = §ion->next; + next_key = §ion->key; + prev_key = NULL; + + if (trace > 1) + htrc("New section: '%s'\n",section->name); + + continue; + } // endif p2 + + } // endif p + + p2 = p + strlen(p) - 1; + + while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) + *p2-- = '\0'; + + if ((p2 = strchr(p, '=')) != NULL) { + char *p3 = p2 - 1; + + while ((p3 > p) && PROFILE_isspace(*p3)) + *p3-- = '\0'; + + *p2++ = '\0'; + + while (*p2 && PROFILE_isspace(*p2)) + p2++; + + } // endif p2 + + if (*p || !prev_key || *prev_key->name) { + if (!(key = malloc(sizeof(*key) + strlen(p)))) + break; + + strcpy(key->name, p); + + if (p2) { + key->value = malloc(strlen(p2)+1); + strcpy(key->value, p2); + } else + key->value = NULL; + + key->next = NULL; + *next_key = key; + next_key = &key->next; + prev_key = key; + + if (trace > 1) + htrc("New key: name='%s', value='%s'\n", + key->name,key->value?key->value:"(none)"); + + } // endif p || prev_key + + } // endif *p + + return first_section; +} // end of PROFILE_Load + +/*********************************************************************** + * PROFILE_FlushFile + * + * Flush the current profile to disk if changed. + ***********************************************************************/ +static bool PROFILE_FlushFile(void) +{ +//char *p, buffer[MAX_PATHNAME_LEN]; +//const char *unix_name; + FILE *file = NULL; + struct stat buf; + + if (trace > 1) + htrc("PROFILE_FlushFile: CurProfile=%p\n", CurProfile); + + if (!CurProfile) { + fprintf(stderr, "No current profile!\n"); + return FALSE; + } // endif !CurProfile + + if (!CurProfile->changed || !CurProfile->filename) + return TRUE; + +#if 0 + if (!(file = fopen(unix_name, "w"))) { + /* Try to create it in $HOME/.wine */ + /* FIXME: this will need a more general solution */ + //strcpy( buffer, get_config_dir() ); + //p = buffer + strlen(buffer); + //*p++ = '/'; + char *p1 = strrchr(CurProfile->filename, '\\'); + + p = buffer; // OB: To be elaborate + + if (p1) + p1++; + else + p1 = CurProfile->dos_name; + + strcpy(p, p1); + _strlwr(p); + file = fopen(buffer, "w"); + unix_name = buffer; + } // endif !unix_name +#endif // 0 + + if (!(file = fopen(CurProfile->filename, "w"))) { + fprintf(stderr, "could not save profile file %s\n", CurProfile->filename); + return FALSE; + } // endif !file + + if (trace > 1) + htrc("Saving '%s'\n", CurProfile->filename); + + PROFILE_Save(file, CurProfile->section); + fclose(file); + CurProfile->changed = FALSE; + + if (!stat(CurProfile->filename, &buf)) + CurProfile->mtime = buf.st_mtime; + + return TRUE; +} // end of PROFILE_FlushFile + + +/*********************************************************************** + * PROFILE_ReleaseFile + * + * Flush the current profile to disk and remove it from the cache. + ***********************************************************************/ +static void PROFILE_ReleaseFile(void) +{ + PROFILE_FlushFile(); + PROFILE_Free(CurProfile->section); +//memfree(CurProfile->dos_name); +//memfree(CurProfile->unix_name); + memfree(CurProfile->filename); + CurProfile->changed = FALSE; + CurProfile->section = NULL; +//CurProfile->dos_name = NULL; +//CurProfile->unix_name = NULL; + CurProfile->filename = NULL; + CurProfile->mtime = 0; +} // end of PROFILE_ReleaseFile + + +/*********************************************************************** + * PROFILE_Open + * + * Open a profile file, checking the cached file first. + ***********************************************************************/ +static bool PROFILE_Open(LPCSTR filename) +{ +//char buffer[MAX_PATHNAME_LEN]; +//char *p; + FILE *file = NULL; + int i, j; + struct stat buf; + PROFILE *tempProfile; + + if (trace > 1) + htrc("PROFILE_Open: CurProfile=%p N=%d\n", CurProfile, N_CACHED_PROFILES); + + /* First time around */ + if (!CurProfile) + for (i = 0; i < N_CACHED_PROFILES; i++) { + MRUProfile[i] = malloc(sizeof(PROFILE)); + + if (MRUProfile[i] == NULL) + break; + + MRUProfile[i]->changed=FALSE; + MRUProfile[i]->section=NULL; +// MRUProfile[i]->dos_name=NULL; +// MRUProfile[i]->unix_name=NULL; + MRUProfile[i]->filename=NULL; + MRUProfile[i]->mtime=0; + } // endfor i + + /* Check for a match */ + for (i = 0; i < N_CACHED_PROFILES; i++) { + if (trace > 1) + htrc("MRU=%s i=%d\n", SVP(MRUProfile[i]->filename), i); + + if (MRUProfile[i]->filename && !strcmp(filename, MRUProfile[i]->filename)) { + if (i) { + PROFILE_FlushFile(); + tempProfile = MRUProfile[i]; + + for (j = i; j > 0; j--) + MRUProfile[j] = MRUProfile[j-1]; + + CurProfile=tempProfile; + } // endif i + + if (!stat(CurProfile->filename, &buf) && CurProfile->mtime == buf.st_mtime) { + if (trace > 1) + htrc("(%s): already opened (mru=%d)\n", filename, i); + + } else { + if (trace > 1) + htrc("(%s): already opened, needs refreshing (mru=%d)\n", filename, i); + + } // endif stat + + return TRUE; + } // endif filename + + } // endfor i + + /* Flush the old current profile */ + PROFILE_FlushFile(); + + /* Make the oldest profile the current one only in order to get rid of it */ + if (i == N_CACHED_PROFILES) { + tempProfile = MRUProfile[N_CACHED_PROFILES-1]; + + for(i = N_CACHED_PROFILES-1; i > 0; i--) + MRUProfile[i] = MRUProfile[i-1]; + + CurProfile = tempProfile; + } // endif i + + if (CurProfile->filename) + PROFILE_ReleaseFile(); + + /* OK, now that CurProfile is definitely free we assign it our new file */ +// newdos_name = HeapAlloc( GetProcessHeap(), 0, strlen(full_name.short_name)+1 ); +// strcpy( newdos_name, full_name.short_name ); + +// newdos_name = malloc(strlen(filename)+1); +// strcpy(newdos_name, filename); + +// CurProfile->dos_name = newdos_name; + CurProfile->filename = malloc(strlen(filename) + 1); + strcpy(CurProfile->filename, filename); + + /* Try to open the profile file, first in $HOME/.wine */ + + /* FIXME: this will need a more general solution */ +// strcpy( buffer, get_config_dir() ); +// p = buffer + strlen(buffer); +// *p++ = '/'; +// strcpy( p, strrchr( newdos_name, '\\' ) + 1 ); +// p = buffer; +// strcpy(p, filename); +// _strlwr(p); + + if (trace > 1) + htrc("Opening %s\n", filename); + + if ((file = fopen(filename, "r"))) { + if (trace > 1) + htrc("(%s): found it\n", filename); + +// CurProfile->unix_name = malloc(strlen(buffer)+1); +// strcpy(CurProfile->unix_name, buffer); + } /* endif file */ + + if (file) { + CurProfile->section = PROFILE_Load(file); + fclose(file); + + if (!stat(CurProfile->filename, &buf)) + CurProfile->mtime = buf.st_mtime; + + } else { + /* Does not exist yet, we will create it in PROFILE_FlushFile */ + fprintf(stderr, "profile file %s not found\n", filename); + } /* endif file */ + + return TRUE; +} + + +/*********************************************************************** + * PROFILE_DeleteSection + * + * Delete a section from a profile tree. + ***********************************************************************/ +static bool PROFILE_DeleteSection(PROFILESECTION* *section, LPCSTR name) +{ + while (*section) { + if ((*section)->name[0] && !stricmp((*section)->name, name)) { + PROFILESECTION *to_del = *section; + + *section = to_del->next; + to_del->next = NULL; + PROFILE_Free(to_del); + return TRUE; + } // endif section + + section = &(*section)->next; + } // endwhile section + + return FALSE; +} // end of PROFILE_DeleteSection + + +/*********************************************************************** + * PROFILE_DeleteKey + * + * Delete a key from a profile tree. + ***********************************************************************/ +static bool PROFILE_DeleteKey(PROFILESECTION* *section, + LPCSTR section_name, LPCSTR key_name) +{ + while (*section) { + if ((*section)->name[0] && !stricmp((*section)->name, section_name)) { + PROFILEKEY* *key = &(*section)->key; + + while (*key) { + if (!stricmp((*key)->name, key_name)) { + PROFILEKEY *to_del = *key; + + *key = to_del->next; + memfree(to_del->value); + free(to_del); + return TRUE; + } // endif name + + key = &(*key)->next; + } // endwhile *key + + } // endif section->name + + section = &(*section)->next; + } // endwhile *section + + return FALSE; +} // end of PROFILE_DeleteKey + + +/*********************************************************************** + * PROFILE_DeleteAllKeys + * + * Delete all keys from a profile tree. + ***********************************************************************/ +void PROFILE_DeleteAllKeys(LPCSTR section_name) +{ + PROFILESECTION* *section= &CurProfile->section; + + while (*section) { + if ((*section)->name[0] && !stricmp((*section)->name, section_name)) { + PROFILEKEY* *key = &(*section)->key; + + while (*key) { + PROFILEKEY *to_del = *key; + + *key = to_del->next; + memfree(to_del->value); + free(to_del); + CurProfile->changed = TRUE; + } // endwhile *key + + } // endif section->name + + section = &(*section)->next; + } // endwhile *section + +} // end of PROFILE_DeleteAllKeys + + +/*********************************************************************** + * PROFILE_Find + * + * Find a key in a profile tree, optionally creating it. + ***********************************************************************/ +static PROFILEKEY *PROFILE_Find(PROFILESECTION* *section, + const char *section_name, + const char *key_name, + bool create, bool create_always) +{ + const char *p; + int seclen, keylen; + + while (PROFILE_isspace(*section_name)) + section_name++; + + p = section_name + strlen(section_name) - 1; + + while ((p > section_name) && PROFILE_isspace(*p)) + p--; + + seclen = p - section_name + 1; + + while (PROFILE_isspace(*key_name)) + key_name++; + + p = key_name + strlen(key_name) - 1; + + while ((p > key_name) && PROFILE_isspace(*p)) + p--; + + keylen = p - key_name + 1; + + while (*section) { + if (((*section)->name[0]) + && (!(_strnicmp((*section)->name, section_name, seclen ))) + && (((*section)->name)[seclen] == '\0')) { + PROFILEKEY* *key = &(*section)->key; + + while (*key) { + /* If create_always is FALSE then we check if the keyname already exists. + * Otherwise we add it regardless of its existence, to allow + * keys to be added more then once in some cases. + */ + if (!create_always) { + if ((!(_strnicmp( (*key)->name, key_name, keylen ))) + && (((*key)->name)[keylen] == '\0')) + return *key; + + } // endif !create_always + + key = &(*key)->next; + } // endwhile *key + + if (!create) + return NULL; + + if (!(*key = malloc(sizeof(PROFILEKEY) + strlen(key_name)))) + return NULL; + + strcpy((*key)->name, key_name); + (*key)->value = NULL; + (*key)->next = NULL; + return *key; + } // endifsection->name + + section = &(*section)->next; + } // endwhile *section + + if (!create) + return NULL; + + *section = malloc(sizeof(PROFILESECTION) + strlen(section_name)); + + if (*section == NULL) + return NULL; + + strcpy((*section)->name, section_name); + (*section)->next = NULL; + + if (!((*section)->key = malloc(sizeof(PROFILEKEY) + strlen(key_name)))) { + free(*section); + return NULL; + } // endif malloc + + strcpy((*section)->key->name, key_name); + (*section)->key->value = NULL; + (*section)->key->next = NULL; + return (*section)->key; +} // end of PROFILE_Find + + +/*********************************************************************** + * PROFILE_GetSection + * + * Returns all keys of a section. + * If return_values is TRUE, also include the corresponding values. + ***********************************************************************/ +static int PROFILE_GetSection(PROFILESECTION *section, LPCSTR section_name, + LPSTR buffer, uint len, bool handle_env, + bool return_values) +{ + PROFILEKEY *key; + + if(!buffer) + return 0; + + while (section) { + if (section->name[0] && !stricmp(section->name, section_name)) { + uint oldlen = len; + + for (key = section->key; key; key = key->next) { + if (len <= 2) + break; + + if (!*key->name) + continue; /* Skip empty lines */ + + if (IS_ENTRY_COMMENT(key->name)) + continue; /* Skip comments */ + + PROFILE_CopyEntry(buffer, key->name, len - 1, handle_env); + len -= strlen(buffer) + 1; + buffer += strlen(buffer) + 1; + + if (len < 2) + break; + + if (return_values && key->value) { + buffer[-1] = '='; + PROFILE_CopyEntry(buffer, key->value, len - 1, handle_env); + len -= strlen(buffer) + 1; + buffer += strlen(buffer) + 1; + } // endif return_values + + } // endfor key + + *buffer = '\0'; + + if (len <= 1) { + /*If either lpszSection or lpszKey is NULL and the supplied + destination buffer is too small to hold all the strings, + the last string is truncated and followed by two null characters. + In this case, the return value is equal to cchReturnBuffer + minus two. */ + buffer[-1] = '\0'; + return oldlen - 2; + } // endif len + + return oldlen - len; + } // endif section->name + + section = section->next; + } // endwhile section + + buffer[0] = buffer[1] = '\0'; + return 0; +} // end of PROFILE_GetSection + + +/* See GetPrivateProfileSectionNamesA for documentation */ +static int PROFILE_GetSectionNames(LPSTR buffer, uint len) +{ + LPSTR buf; + uint f,l; + PROFILESECTION *section; + + if (trace > 1) + htrc("GetSectionNames: buffer=%p len=%u\n", buffer, len); + + if (!buffer || !len) + return 0; + + if (len == 1) { + *buffer='\0'; + return 0; + } // endif len + + f = len - 1; + buf = buffer; + section = CurProfile->section; + + if (trace > 1) + htrc("GetSectionNames: section=%p\n", section); + + while (section != NULL) { + if (trace > 1) + htrc("section=%s\n", section->name); + + if (section->name[0]) { + l = strlen(section->name) + 1; + + if (trace > 1) + htrc("l=%u f=%u\n", l, f); + + if (l > f) { + if (f > 0) { + strncpy(buf, section->name, f-1); + buf += f-1; + *buf++='\0'; + } // endif f + + *buf = '\0'; + return len - 2; + } // endif l + + strcpy(buf, section->name); + buf += l; + f -= l; + } // endif section->name + + section = section->next; + } // endwhile section + + *buf='\0'; + return buf-buffer; +} // end of PROFILE_GetSectionNames + + +/*********************************************************************** + * PROFILE_GetString + * + * Get a profile string. + * + * Tests with GetPrivateProfileString16, W95a, + * with filled buffer ("****...") and section "set1" and key_name "1" valid: + * section key_name def_val res buffer + * "set1" "1" "x" 43 [data] + * "set1" "1 " "x" 43 [data] (!) + * "set1" " 1 "' "x" 43 [data] (!) + * "set1" "" "x" 1 "x" + * "set1" "" "x " 1 "x" (!) + * "set1" "" " x " 3 " x" (!) + * "set1" NULL "x" 6 "1\02\03\0\0" + * "set1" "" "x" 1 "x" + * NULL "1" "x" 0 "" (!) + * "" "1" "x" 1 "x" + * NULL NULL "" 0 "" + * + *************************************************************************/ +static int PROFILE_GetString(LPCSTR section, LPCSTR key_name, + LPCSTR def_val, LPSTR buffer, uint len) +{ + PROFILEKEY *key = NULL; + + if(!buffer) + return 0; + + if (!def_val) + def_val = ""; + + if (key_name && key_name[0]) { + key = PROFILE_Find(&CurProfile->section, section, key_name, FALSE, FALSE); + PROFILE_CopyEntry(buffer, (key && key->value) ? key->value : def_val, len, FALSE); + + if (trace > 1) + htrc("('%s','%s','%s'): returning '%s'\n", + section, key_name, def_val, buffer ); + + return strlen(buffer); + } // endif key_name + + if (key_name && !(key_name[0])) + /* Win95 returns 0 on keyname "". Tested with Likse32 bon 000227 */ + return 0; + + if (section && section[0]) + return PROFILE_GetSection(CurProfile->section, section, buffer, len, + FALSE, FALSE); + buffer[0] = '\0'; + return 0; +} // end of PROFILE_GetString + + +/*********************************************************************** + * PROFILE_SetString + * + * Set a profile string. + ***********************************************************************/ +static bool PROFILE_SetString(LPCSTR section_name, LPCSTR key_name, + LPCSTR value, bool create_always) +{ + if (!key_name) { /* Delete a whole section */ + if (trace > 1) + htrc("Deleting('%s')\n", section_name); + + CurProfile->changed |= PROFILE_DeleteSection(&CurProfile->section, + section_name); + return TRUE; /* Even if PROFILE_DeleteSection() has failed, + this is not an error on application's level.*/ + } else if (!value) { /* Delete a key */ + if (trace > 1) + htrc("Deleting('%s','%s')\n", section_name, key_name); + + CurProfile->changed |= PROFILE_DeleteKey(&CurProfile->section, + section_name, key_name); + return TRUE; /* same error handling as above */ + } else { /* Set the key value */ + PROFILEKEY *key = PROFILE_Find(&CurProfile->section, section_name, + key_name, TRUE, create_always); + if (trace > 1) + htrc("Setting('%s','%s','%s')\n", section_name, key_name, value); + + if (!key) + return FALSE; + + if (key->value) { + /* strip the leading spaces. We can safely strip \n\r and + * friends too, they should not happen here anyway. */ + while (PROFILE_isspace(*value)) + value++; + + if (!strcmp(key->value, value)) { + if (trace > 1) + htrc(" no change needed\n" ); + + return TRUE; /* No change needed */ + } // endif value + + if (trace > 1) + htrc(" replacing '%s'\n", key->value); + + free(key->value); + } else if (trace > 1) + htrc(" creating key\n" ); + + key->value = malloc(strlen(value) + 1); + strcpy(key->value, value); + CurProfile->changed = TRUE; + } // endelse + + return TRUE; +} // end of PROFILE_SetString + + +/*********************************************************************** + * PROFILE_GetStringItem + * + * Convenience function that turns a string 'xxx, yyy, zzz' into + * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'. + ***********************************************************************/ +char *PROFILE_GetStringItem(char* start) +{ + char *lpchX, *lpch; + + for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++) { + if (*lpchX == ',') { + if (lpch) + *lpch = '\0'; + else + *lpchX = '\0'; + + while(*(++lpchX)) + if (!PROFILE_isspace(*lpchX)) + return lpchX; + + } else if (PROFILE_isspace(*lpchX) && !lpch) { + lpch = lpchX; + } else + lpch = NULL; + + } // endfor lpchX + + if (lpch) + *lpch = '\0'; + + return NULL; +} // end of PROFILE_GetStringItem + +/********************************************************************** + * if allow_section_name_copy is TRUE, allow the copying : + * - of Section names if 'section' is NULL + * - of Keys in a Section if 'entry' is NULL + * (see MSDN doc for GetPrivateProfileString) + **********************************************************************/ +static int PROFILE_GetPrivateProfileString(LPCSTR section, LPCSTR entry, + LPCSTR def_val, LPSTR buffer, + uint len, LPCSTR filename, + bool allow_section_name_copy) +{ + int ret; + LPSTR pDefVal = NULL; + + if (!filename) + filename = "win.ini"; + + /* strip any trailing ' ' of def_val. */ + if (def_val) { + LPSTR p = (LPSTR)&def_val[strlen(def_val)]; // even "" works ! + + while (p > def_val) + if ((*(--p)) != ' ') + break; + + if (*p == ' ') { /* ouch, contained trailing ' ' */ + int len = p - (LPSTR)def_val; + + pDefVal = malloc(len + 1); + strncpy(pDefVal, def_val, len); + pDefVal[len] = '\0'; + } // endif *p + + } // endif def_val + + if (!pDefVal) + pDefVal = (LPSTR)def_val; + + EnterCriticalSection(&PROFILE_CritSect); + + if (PROFILE_Open(filename)) { + if ((allow_section_name_copy) && (section == NULL)) + ret = PROFILE_GetSectionNames(buffer, len); + else + /* PROFILE_GetString already handles the 'entry == NULL' case */ + ret = PROFILE_GetString(section, entry, pDefVal, buffer, len); + + } else { + strncpy(buffer, pDefVal, len); + ret = strlen(buffer); + } // endif Open + + LeaveCriticalSection(&PROFILE_CritSect); + + if (pDefVal != def_val) /* allocated */ + memfree(pDefVal); + + return ret; +} // end of PROFILE_GetPrivateProfileString + +/********************** API functions **********************************/ + +/*********************************************************************** + * GetPrivateProfileStringA (KERNEL32.@) + ***********************************************************************/ +int GetPrivateProfileString(LPCSTR section, LPCSTR entry, LPCSTR def_val, + LPSTR buffer, uint len, LPCSTR filename) +{ + return PROFILE_GetPrivateProfileString(section, entry, def_val, + buffer, len, filename, TRUE); +} // end of GetPrivateProfileString + + +/*********************************************************************** + * GetPrivateProfileIntA (KERNEL32.@) + ***********************************************************************/ +uint GetPrivateProfileInt(LPCSTR section, LPCSTR entry, + int def_val, LPCSTR filename) +{ + char buffer[20]; + int result; + + if (!PROFILE_GetPrivateProfileString(section, entry, "", buffer, + sizeof(buffer), filename, FALSE)) + return def_val; + + /* FIXME: if entry can be found but it's empty, then Win16 is + * supposed to return 0 instead of def_val ! Difficult/problematic + * to implement (every other failure also returns zero buffer), + * thus wait until testing framework avail for making sure nothing + * else gets broken that way. */ + if (!buffer[0]) + return (uint)def_val; + + /* Don't use strtol() here ! + * (returns LONG_MAX/MIN on overflow instead of "proper" overflow) + YES, scan for unsigned format ! (otherwise compatibility error) */ + if (!sscanf(buffer, "%u", &result)) + return 0; + + return (uint)result; +} // end of GetPrivateProfileInt + + +/*********************************************************************** + * GetPrivateProfileSectionA (KERNEL32.@) + ***********************************************************************/ +int GetPrivateProfileSection(LPCSTR section, LPSTR buffer, + DWORD len, LPCSTR filename) +{ + int ret = 0; + + EnterCriticalSection( &PROFILE_CritSect ); + + if (PROFILE_Open(filename)) + ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, + FALSE, TRUE); + + LeaveCriticalSection( &PROFILE_CritSect ); + return ret; +} // end of GetPrivateProfileSection + + +/*********************************************************************** + * WritePrivateProfileStringA (KERNEL32.@) + ***********************************************************************/ +bool WritePrivateProfileString(LPCSTR section, LPCSTR entry, + LPCSTR string, LPCSTR filename) +{ + bool ret = FALSE; + + EnterCriticalSection( &PROFILE_CritSect ); + + if (PROFILE_Open(filename)) { + if (!section && !entry && !string) /* documented "file flush" case */ + PROFILE_ReleaseFile(); /* always return FALSE in this case */ + else { + if (!section) { + //FIXME("(NULL?,%s,%s,%s)? \n",entry,string,filename); + } else { + ret = PROFILE_SetString(section, entry, string, FALSE); + + if (ret) + ret = PROFILE_FlushFile(); + + } // endif section + + } // endif section || entry|| string + + } // endif Open + + LeaveCriticalSection( &PROFILE_CritSect ); + return ret; +} // end of WritePrivateProfileString + + +/*********************************************************************** + * WritePrivateProfileSectionA (KERNEL32.@) + ***********************************************************************/ +bool WritePrivateProfileSection(LPCSTR section, + LPCSTR string, LPCSTR filename ) +{ + bool ret = FALSE; + LPSTR p ; + + EnterCriticalSection(&PROFILE_CritSect); + + if (PROFILE_Open(filename)) { + if (!section && !string) + PROFILE_ReleaseFile(); /* always return FALSE in this case */ + else if (!string) { /* delete the named section*/ + ret = PROFILE_SetString(section, NULL, NULL, FALSE); + + if (ret) + ret = PROFILE_FlushFile(); + } else { + PROFILE_DeleteAllKeys(section); + ret = TRUE; + + while (*string) { + LPSTR buf = malloc(strlen(string) + 1); + strcpy(buf, string); + + if ((p = strchr(buf, '='))) { + *p='\0'; + ret = PROFILE_SetString(section, buf, p+1, TRUE); + } // endif p + + free(buf); + string += strlen(string) + 1; + + if (ret) + ret = PROFILE_FlushFile(); + + } // endwhile *string + + } // endelse + + } // endif Open + + LeaveCriticalSection(&PROFILE_CritSect); + return ret; +} // end of WritePrivateProfileSection + + +/*********************************************************************** + * GetPrivateProfileSectionNamesA (KERNEL32.@) + * + * Returns the section names contained in the specified file. + * FIXME: Where do we find this file when the path is relative? + * The section names are returned as a list of strings with an extra + * '\0' to mark the end of the list. Except for that the behavior + * depends on the Windows version. + * + * Win95: + * - if the buffer is 0 or 1 character long then it is as if it was of + * infinite length. + * - otherwise, if the buffer is to small only the section names that fit + * are returned. + * - note that this means if the buffer was to small to return even just + * the first section name then a single '\0' will be returned. + * - the return value is the number of characters written in the buffer, + * except if the buffer was too smal in which case len-2 is returned + * + * Win2000: + * - if the buffer is 0, 1 or 2 characters long then it is filled with + * '\0' and the return value is 0 + * - otherwise if the buffer is too small then the first section name that + * does not fit is truncated so that the string list can be terminated + * correctly (double '\0') + * - the return value is the number of characters written in the buffer + * except for the trailing '\0'. If the buffer is too small, then the + * return value is len-2 + * - Win2000 has a bug that triggers when the section names and the + * trailing '\0' fit exactly in the buffer. In that case the trailing + * '\0' is missing. + * + * Wine implements the observed Win2000 behavior (except for the bug). + * + * Note that when the buffer is big enough then the return value may be any + * value between 1 and len-1 (or len in Win95), including len-2. + */ +DWORD GetPrivateProfileSectionNames(LPSTR buffer, DWORD size, LPCSTR filename) +{ + DWORD ret = 0; + + if (trace > 1) + htrc("GPPSN: filename=%s\n", filename); + + EnterCriticalSection(&PROFILE_CritSect); + + if (PROFILE_Open(filename)) + ret = PROFILE_GetSectionNames(buffer, size); + + LeaveCriticalSection(&PROFILE_CritSect); + return ret; +} // end of GetPrivateProfileSectionNames + + +/************************************************************************ + * Program to test the above + ************************************************************************/ +#ifdef TEST_MODULE +int main(int argc, char**argv) { + char buff[128]; + char *p, *inifile = "D:\\Plug\\Data\\contact.ini"; + DWORD n; + + n = GetPrivateProfileSectionNames(buff, 128, inifile); + printf("Sections: n=%d\n", n); + + for (p = buff; *p; p += (strlen(p) + 1)) + printf("section=[%s]\n", p); + + GetPrivateProfileString("BER", "name", "?", buff, 128, inifile); + printf("[BER](name) = %s\n", buff); + + WritePrivateProfileString("FOO", "city", NULL, inifile); + GetPrivateProfileString("FOO", "city", "?", buff, 128, inifile); + printf("[FOO](city) = %s\n", buff); + + printf("FOO city: "); + fgets(buff, sizeof(buff), stdin); + if (buff[strlen(buff) - 1] == '\n') + buff[strlen(buff) - 1] = '\0'; + WritePrivateProfileString("FOO", "city", buff, inifile); + GetPrivateProfileString("FOO", "city", "???", buff, 128, inifile); + printf("After write, [FOO](City) = %s\n", buff); + + printf("New city: "); + fgets(buff, sizeof(buff), stdin); + if (buff[strlen(buff) - 1] == '\n') + buff[strlen(buff) - 1] = '\0'; + WritePrivateProfileString("FOO", "city", buff, inifile); + GetPrivateProfileString("FOO", "city", "???", buff, 128, inifile); + printf("After update, [FOO](City) = %s\n", buff); + + printf("FOO name: "); + fgets(buff, sizeof(buff), stdin); + if (buff[strlen(buff) - 1] == '\n') + buff[strlen(buff) - 1] = '\0'; + WritePrivateProfileString("FOO", "name", buff, inifile); + GetPrivateProfileString("FOO", "name", "X", buff, 128, inifile); + printf("[FOO](name) = %s\n", buff); +} // end of main +#endif // TEST_MODULE |