Ignore:
Timestamp:
Aug 4, 1999, 2:46:14 AM (26 years ago)
Author:
phaller
Message:

Fix: Win3-Style Profile support ported from WINE. Also removes Open32 dependency

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/profile.cpp

    r100 r408  
    1 /* $Id: profile.cpp,v 1.4 1999-06-10 20:48:01 phaller Exp $ */
     1/* $Id: profile.cpp,v 1.5 1999-08-04 00:44:33 phaller Exp $ */
    22
    33/*
    4  *
    54 * Project Odin Software License can be found in LICENSE.TXT
    65 *
    7  */
    8 /*
    96 * Win32 profile API functions
    107 *
     8 * Copyright 1993 Miguel de Icaza
     9 * Copyright 1996 Alexandre Julliard
    1110 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
    1211 * Copyright 1998 Patrick Haller
    13  *
    14  */
     12 */
     13
    1514#include <os2win.h>
     15#include <ctype.h>
    1616#include <stdlib.h>
    1717#include <string.h>
    18 #include "unicode.h"
    19 
    20 //******************************************************************************
    21 //******************************************************************************
    22 UINT WIN32API GetPrivateProfileIntA(LPCSTR arg1, LPCSTR arg2, INT arg3, LPCSTR  arg4)
    23 {
    24     dprintf(("KERNEL32:  OS2GetPrivateProfileIntA %s, %s, file %s\n", arg1, arg2, arg4));
    25     return O32_GetPrivateProfileInt(arg1, arg2, arg3, arg4);
    26 }
    27 //******************************************************************************
    28 //******************************************************************************
    29 UINT WIN32API GetPrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName,
    30                                     INT nDefault, LPCWSTR lpFileName)
    31 {
    32   char *asciiapp, *asciikey, *asciifile;
    33   UINT  rc;
    34 
    35     dprintf(("KERNEL32:  OS2GetPrivateProfileIntW\n"));
    36     asciiapp  = UnicodeToAsciiString((LPWSTR)lpAppName);
    37     asciikey  = UnicodeToAsciiString((LPWSTR)lpKeyName);
    38     asciifile = UnicodeToAsciiString((LPWSTR)lpFileName);
    39     rc = O32_GetPrivateProfileInt(asciiapp, asciikey, nDefault, asciifile);
    40     FreeAsciiString(asciifile);
    41     FreeAsciiString(asciikey);
    42     FreeAsciiString(asciiapp);
    43     return(rc);
    44 }
    45 //******************************************************************************
    46 //******************************************************************************
    47 UINT WIN32API GetProfileIntA( LPCSTR arg1, LPCSTR arg2, INT  arg3)
    48 {
    49  UINT rc;
    50 
    51     rc = O32_GetProfileInt(arg1, arg2, arg3);
    52     dprintf(("KERNEL32:  OS2GetProfileIntA %s %s returned %d\n", arg1, arg2, rc));
    53     return(rc);
    54 }
    55 //******************************************************************************
    56 //******************************************************************************
    57 UINT WIN32API GetProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, int nDefault)
    58 {
    59   char *asciiapp, *asciikey;
    60   UINT  rc;
    61 
    62     dprintf(("KERNEL32:  OS2GetProfileIntW\n"));
    63     asciiapp  = UnicodeToAsciiString((LPWSTR)lpAppName);
    64     asciikey  = UnicodeToAsciiString((LPWSTR)lpKeyName);
    65     rc = O32_GetProfileInt(asciiapp, asciikey, nDefault);
    66     FreeAsciiString(asciikey);
    67     FreeAsciiString(asciiapp);
    68     return(rc);
    69 }
    70 //******************************************************************************
    71 //******************************************************************************
    72 INT WIN32API GetPrivateProfileStringA(LPCSTR arg1,
    73                                       LPCSTR arg2,
    74                                       LPCSTR arg3,
    75                                       LPSTR  arg4,
    76                                       UINT  arg5,
    77                                       LPCSTR arg6)
    78 {
    79   dprintf(("KERNEL32: GetPrivateProfileStringA(%s,%s,%s,%08xh,%u,%s)\n",
    80            arg1,
    81            arg2,
    82            arg3,
    83            arg4,
    84            arg5,
    85            arg6));
    86 
    87   return O32_GetPrivateProfileString(arg1,
    88                                  arg2,
    89                                  arg3,
    90                                  arg4,
    91                                  arg5,
    92                                  arg6);
    93 }
    94 //******************************************************************************
    95 //******************************************************************************
    96 INT WIN32API GetPrivateProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName,
    97                                       LPCWSTR lpDefault, LPWSTR lpReturnedString,
    98                                       UINT nSize, LPCWSTR lpFileName)
    99 {
    100   char *asciiapp, *asciikey, *asciifile, *asciidefault;
    101   char *asciistring = (char *)malloc(nSize+1);
    102   UINT  rc;
    103 
    104     dprintf(("KERNEL32:  OS2GetPrivateProfileStringW\n"));
    105     asciiapp     = UnicodeToAsciiString((LPWSTR)lpAppName);
    106     asciikey     = UnicodeToAsciiString((LPWSTR)lpKeyName);
    107     asciifile    = UnicodeToAsciiString((LPWSTR)lpFileName);
    108     asciidefault = UnicodeToAsciiString((LPWSTR)lpDefault);
    109     rc = O32_GetPrivateProfileString(asciiapp, asciikey, asciidefault, asciistring,
    110                                  nSize, asciifile);
    111     if(rc)      AsciiToUnicode(asciistring, lpReturnedString);
    112     FreeAsciiString(asciidefault);
    113     FreeAsciiString(asciifile);
    114     FreeAsciiString(asciikey);
    115     FreeAsciiString(asciiapp);
    116     free(asciistring);
    117     return(rc);
    118 }
    119 //******************************************************************************
    120 //******************************************************************************
    121 INT WIN32API GetProfileStringA( LPCSTR arg1, LPCSTR arg2, LPCSTR arg3, LPSTR arg4, UINT arg5)
    122 {
    123     dprintf(("KERNEL32:  GetProfileString %s\n", arg1));
    124     return O32_GetProfileString(arg1, arg2, arg3, arg4, arg5);
    125 }
    126 //******************************************************************************
    127 //******************************************************************************
    128 INT WIN32API GetProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName,
    129                                LPCWSTR lpDefault, LPWSTR lpReturnedString,
    130                                UINT nSize)
    131 {
    132   char *asciiapp, *asciikey, *asciifile, *asciidefault;
    133   char *asciistring = (char *)malloc(nSize+1);
    134   UINT  rc;
    135 
    136     dprintf(("KERNEL32:  OS2GetProfileStringW\n"));
    137     asciiapp     = UnicodeToAsciiString((LPWSTR)lpAppName);
    138     asciikey     = UnicodeToAsciiString((LPWSTR)lpKeyName);
    139     asciidefault = UnicodeToAsciiString((LPWSTR)lpDefault);
    140     rc = O32_GetProfileString(asciiapp, asciikey, asciidefault, asciistring, nSize);
    141     if(rc)      AsciiToUnicode(asciistring, lpReturnedString);
    142     FreeAsciiString(asciidefault);
    143     FreeAsciiString(asciikey);
    144     FreeAsciiString(asciiapp);
    145     free(asciistring);
    146     return(rc);
    147 }
    148 //******************************************************************************
    149 //******************************************************************************
    150 BOOL WIN32API WriteProfileStringA(LPCSTR arg1, LPCSTR arg2, LPCSTR  arg3)
    151 {
    152     dprintf(("KERNEL32:  WriteProfileString %s key %s value %s\n", arg1, arg2, arg3));
    153     return O32_WriteProfileString(arg1, arg2, arg3);
    154 }
    155 //******************************************************************************
    156 //******************************************************************************
    157 BOOL WIN32API WriteProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName,
    158                                   LPCWSTR lpString)
    159 {
    160   char *asciiapp, *asciikey, *asciistring;
    161   UINT  rc;
    162 
    163     dprintf(("KERNEL32:  OS2WriteProfileStringW\n"));
    164     asciiapp     = UnicodeToAsciiString((LPWSTR)lpAppName);
    165     asciikey     = UnicodeToAsciiString((LPWSTR)lpKeyName);
    166     asciistring  = UnicodeToAsciiString((LPWSTR)lpString);
    167     rc = O32_WriteProfileString(asciiapp, asciikey, asciistring);
    168     FreeAsciiString(asciistring);
    169     FreeAsciiString(asciikey);
    170     FreeAsciiString(asciiapp);
    171     return(rc);
    172 }
    173 //******************************************************************************
    174 //******************************************************************************
    175 BOOL WIN32API WritePrivateProfileStringA( LPCSTR arg1, LPCSTR arg2, LPCSTR arg3, LPCSTR  arg4)
    176 {
    177     dprintf(("KERNEL32:  WritePrivateProfileString\n"));
    178     return O32_WritePrivateProfileString(arg1, arg2, arg3, arg4);
    179 }
    180 //******************************************************************************
    181 //******************************************************************************
    182 BOOL WIN32API WritePrivateProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName,
    183                                          LPCWSTR lpString, LPCWSTR lpFileName)
    184 {
    185   char *asciiapp, *asciikey, *asciifile, *asciistring;
    186   UINT  rc;
    187 
    188     dprintf(("KERNEL32:  OS2WritePrivateProfileStringW\n"));
    189     asciiapp     = UnicodeToAsciiString((LPWSTR)lpAppName);
    190     asciikey     = UnicodeToAsciiString((LPWSTR)lpKeyName);
    191     asciifile    = UnicodeToAsciiString((LPWSTR)lpFileName);
    192     asciistring  = UnicodeToAsciiString((LPWSTR)lpString);
    193     rc = O32_WritePrivateProfileString(asciiapp, asciikey, asciistring, asciifile);
    194     FreeAsciiString(asciistring);
    195     FreeAsciiString(asciifile);
    196     FreeAsciiString(asciikey);
    197     FreeAsciiString(asciiapp);
    198     return(rc);
    199 }
    200 //******************************************************************************
    201 //******************************************************************************
    202 INT WIN32API GetProfileSectionA(LPCSTR lpszSection, LPSTR lpszReturnBuffer,
    203                                 DWORD cchBuffer)
    204 {
    205   dprintf(("KERNEL32:  OS2GetProfileSectionA %s, not implemented\n", lpszSection));
    206   return(0);
    207 }
    208 //******************************************************************************
    209 INT WIN32API GetProfileSectionW(LPCWSTR lpszSection,
    210                                 LPWSTR lpszReturnBuffer,
    211                                 DWORD cchBuffer)
    212 {
    213   dprintf(("KERNEL32:  OS2GetProfileSectionW %s, not implemented\n", lpszSection));
    214   return(0);
    215 }
    216 
    217 INT WIN32API GetPrivateProfileSectionA(
    218     LPCSTR lpszSection,    /* address of section name      */
    219     LPSTR lpszReturnBuffer,/* address of return buffer     */
    220     DWORD cchBuffer,        /* size of return buffer        */
    221     LPCSTR lpszFile)       /* address of initialization filename   */
    222 
    223 
    224    /* The GetPrivateProfileSection function retrieves all of the keys
    225     * and values for the specified section from the given initialization
    226     * file. This function is provided for compatibility with 16-bit
    227     * applications written for Windows. New applications should store
    228     * initialization information in the registry.
    229     */
    230 {
    231     dprintf(("GetPrivateProfileSection(%s, %s, %d) - not implemented\n",
    232             lpszFile, lpszSection, cchBuffer));
    233     return FALSE;   // return error
    234 }
    235 
    236 
    237 INT WIN32API GetPrivateProfileSectionW(
    238     LPCWSTR lpszSection,    /* address of section name      */
    239     LPWSTR lpszReturnBuffer,/* address of return buffer     */
    240     DWORD cchBuffer,        /* size of return buffer        */
    241     LPCWSTR lpszFile)       /* address of initialization filename   */
    242 
    243 
    244    /* The GetPrivateProfileSection function retrieves all of the keys
    245     * and values for the specified section from the given initialization
    246     * file. This function is provided for compatibility with 16-bit
    247     * applications written for Windows. New applications should store
    248     * initialization information in the registry.
    249     */
    250 {
    251     dprintf(("GetPrivateProfileSectionW(%s, %s, %d) - not implemented\n",
    252             lpszFile, lpszSection, cchBuffer));
    253     return FALSE;   // return error
    254 }
    255 /*****************************************************************************
    256  * Name      : BOOL WriteProfileSectionA
    257  * Purpose   : The WriteProfileSection function replaces the contents of the
    258  *             specified section in the WIN.INI file with the specified keys and values.
    259  *             This function is provided for compatibility with 16-bit Windows
    260  *             applications. Win32-based applications should store initialization
    261  *             information in the registry.
    262  * Parameters: LPCTSTR lpszSection       address of string with section name
    263  *             LPCTSTR lpszKeysAndValues address of string with data
    264  * Variables :
    265  * Result    : TRUE / FALSE
    266  * Remark    :
    267  * Status    : UNTESTED STUB
    268  *
    269  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    270  *****************************************************************************/
    271 
    272 BOOL WIN32API WriteProfileSectionA(LPCTSTR lpszSection,
    273                                    LPCTSTR lpszKeysAndValues)
    274 {
    275   dprintf(("KERNEL32: WriteProfileSectionA(%s,%s,%s) not implemented.\n",
    276            lpszSection,
    277            lpszKeysAndValues));
    278 
    279   return (FALSE);
    280 }
    281 
    282 
    283 /*****************************************************************************
    284  * Name      : BOOL WriteProfileSectionW
    285  * Purpose   : The WriteProfileSection function replaces the contents of the
    286  *             specified section in the WIN.INI file with the specified keys and values.
    287  *             This function is provided for compatibility with 16-bit Windows
    288  *             applications. Win32-based applications should store initialization
    289  *             information in the registry.
    290  * Parameters: LPCWSTR lpszSection       address of string with section name
    291  *             LPCWSTR lpszKeysAndValues address of string with data
    292  * Variables :
    293  * Result    : TRUE / FALSE
    294  * Remark    :
    295  * Status    : UNTESTED STUB
    296  *
    297  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    298  *****************************************************************************/
    299 
    300 BOOL WIN32API WriteProfileSectionW(LPCWSTR lpszSection,
    301                                    LPCWSTR lpszKeysAndValues)
    302 {
    303   dprintf(("KERNEL32: WriteProfileSectionW(%s,%s,%s) not implemented.\n",
    304            lpszSection,
    305            lpszKeysAndValues));
    306 
    307   return (FALSE);
    308 }
    309 /*****************************************************************************
    310  * Name      : BOOL GetPrivateProfileStructA
    311  * Purpose   : The GetPrivateProfileStructA function retrieves the data associated
    312  *             with the specified key in the given section of an initialization
    313  *             file. As it retrieves the data, the function calculates a checksum
    314  *             and compares it with the checksum calculated by the WritePrivateProfileStruct
    315  *             function when the data was added to the file. This function is provided
    316  *             for compatibility with 16-bit Windows-based applications. Win32-based
    317  *             applications should store initialization information in the registry.
    318  * Parameters: LPCTSTR lpszSection  address of section name
    319  *             LPCTSTR lpszKey      address of key name
    320  *             LPVOID  lpStruct     address of return buffer
    321  *             UINT    uSizeStruct  size of return buffer
    322  *             LPCTSTR szFile       address of initialization filename
    323  * Variables :
    324  * Result    : TRUE / FALSE
    325  * Remark    :
    326  * Status    : UNTESTED STUB
    327  *
    328  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    329  *****************************************************************************/
    330 
    331 BOOL WIN32API GetPrivateProfileStructA(LPCTSTR lpszSection,
    332                                           LPCTSTR lpszKey,
    333                                           LPVOID  lpStruct,
    334                                           UINT    uSizeStruct,
    335                                           LPCTSTR szFile)
    336 {
    337   dprintf(("KERNEL32: GetPrivateProfileStructA(%s,%s,%08xh,%08xh,%s) not implemented.\n",
    338            lpszSection,
    339            lpszKey,
    340            lpStruct,
    341            uSizeStruct,
    342            szFile));
    343 
     18#include <stdio.h>
     19#include <unicode.h>
     20//#include "heap.h"
     21
     22#include <sys/stat.h>
     23
     24#include "winbase.h"
     25//#include "wine/winbase16.h"
     26#include "winuser.h"
     27#include "winnls.h"
     28//#include "heap.h"
     29//#include "debugtools.h"
     30//#include "options.h"
     31
     32
     33// -------------------------
     34// WINE compatibility macros
     35// -------------------------
     36
     37#ifndef MAX_PATHNAME_LEN
     38#define MAX_PATHNAME_LEN 260
     39#endif
     40
     41#define HeapFree(a,b,c)          free(c)
     42#define HEAP_xalloc(a,b,c)       malloc(c)
     43#define HEAP_strdupA(a,b,c)      strdup(c)
     44#define strcasecmp               strcmp
     45#define DOSFS_GetFullName(a,b,c) strcpy(c,a)
     46#define HEAP_strdupAtoW(a,b,c)   AsciiToUnicodeString((char *)c)
     47#define HEAP_strdupWtoA(a,b,c)   UnicodeToAsciiString((LPWSTR)c)
     48#define lstrcpynAtoW(a,b,c)      AsciiToUnicodeN((char*)a,(LPWSTR)b,(int)c)
     49#define lstrcpynWtoA(a,b,c)      UnicodeToAsciiN((LPWSTR)a,(char*)b,(int)c)
     50#define lstrcpynA(a,b,c)         strncpy((char*)a,(char*)b,(int)c)
     51#define CharLowerA(a)            (a)
     52
     53
     54typedef struct tagPROFILEKEY
     55{
     56    char                  *name;
     57    char                  *value;
     58    struct tagPROFILEKEY  *next;
     59} PROFILEKEY;
     60
     61typedef struct tagPROFILESECTION
     62{
     63    char                       *name;
     64    struct tagPROFILEKEY       *key;
     65    struct tagPROFILESECTION   *next;
     66} PROFILESECTION;
     67
     68
     69typedef struct
     70{
     71    BOOL             changed;
     72    PROFILESECTION  *section;
     73    char            *dos_name;
     74    char            *unix_name;
     75    char            *filename;
     76    time_t           mtime;
     77} PROFILE;
     78
     79
     80#define N_CACHED_PROFILES 10
     81
     82/* Cached profile files */
     83static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
     84
     85#define CurProfile (MRUProfile[0])
     86
     87/* wine.ini profile content */
     88static PROFILESECTION *PROFILE_WineProfile;
     89
     90#define PROFILE_MAX_LINE_LEN   1024
     91
     92/* Wine profile name in $HOME directory; must begin with slash */
     93static const char PROFILE_WineIniName[] = "/.winerc";
     94
     95/* Wine profile: the profile file being used */
     96static char PROFILE_WineIniUsed[MAX_PATHNAME_LEN] = "";
     97
     98/* Check for comments in profile */
     99#define IS_ENTRY_COMMENT(str)  ((str)[0] == ';')
     100
     101#define WINE_INI_GLOBAL ETCDIR "/wine.conf"
     102
     103static LPCWSTR wininiW = NULL;
     104
     105static CRITICAL_SECTION PROFILE_CritSect;
     106
     107
     108/***********************************************************************
     109 *           PROFILE_CopyEntry
     110 *
     111 * Copy the content of an entry into a buffer, removing quotes, and possibly
     112 * translating environment variables.
     113 */
     114static void PROFILE_CopyEntry( char *buffer,
     115                               const char *value,
     116                               int len,
     117                               int handle_env )
     118{
     119    char quote = '\0';
     120    const char *p;
     121
     122    if ((*value == '\'') || (*value == '\"'))
     123    {
     124        if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
     125    }
     126
     127    if (!handle_env)
     128    {
     129        lstrcpynA( buffer, value, len );
     130        if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
     131        return;
     132    }
     133
     134    for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
     135    {
     136        if ((*p == '$') && (p[1] == '{'))
     137        {
     138            char env_val[1024];
     139            const char *env_p;
     140            const char *p2 = strchr( p, '}' );
     141            if (!p2) continue;  /* ignore it */
     142            lstrcpynA(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
     143            if ((env_p = getenv( env_val )) != NULL)
     144            {
     145                lstrcpynA( buffer, env_p, len );
     146                buffer += strlen( buffer );
     147                len -= strlen( buffer );
     148            }
     149            p = p2 + 1;
     150        }
     151    }
     152    *buffer = '\0';
     153}
     154
     155
     156/***********************************************************************
     157 *           PROFILE_Save
     158 *
     159 * Save a profile tree to a file.
     160 */
     161static void PROFILE_Save( FILE *file, PROFILESECTION *section )
     162{
     163    PROFILEKEY *key;
     164
     165    for ( ; section; section = section->next)
     166    {
     167        if (section->name) fprintf( file, "\r\n[%s]\r\n", section->name );
     168        for (key = section->key; key; key = key->next)
     169        {
     170            fprintf( file, "%s", key->name );
     171            if (key->value) fprintf( file, "=%s", key->value );
     172            fprintf( file, "\r\n" );
     173        }
     174    }
     175}
     176
     177
     178/***********************************************************************
     179 *           PROFILE_Free
     180 *
     181 * Free a profile tree.
     182 */
     183static void PROFILE_Free( PROFILESECTION *section )
     184{
     185    PROFILESECTION *next_section;
     186    PROFILEKEY *key, *next_key;
     187
     188    for ( ; section; section = next_section)
     189    {
     190        if (section->name) HeapFree( SystemHeap, 0, section->name );
     191        for (key = section->key; key; key = next_key)
     192        {
     193            next_key = key->next;
     194            if (key->name) HeapFree( SystemHeap, 0, key->name );
     195            if (key->value) HeapFree( SystemHeap, 0, key->value );
     196            HeapFree( SystemHeap, 0, key );
     197        }
     198        next_section = section->next;
     199        HeapFree( SystemHeap, 0, section );
     200    }
     201}
     202
     203static int
     204PROFILE_isspace(char c) {
     205   if (isspace(c)) return 1;
     206   if (c=='\r' || c==0x1a) return 1;
     207   /* CR and ^Z (DOS EOF) are spaces too  (found on CD-ROMs) */
     208   return 0;
     209}
     210
     211
     212/***********************************************************************
     213 *           PROFILE_Load
     214 *
     215 * Load a profile tree from a file.
     216 */
     217static PROFILESECTION *PROFILE_Load( FILE *file )
     218{
     219    char buffer[PROFILE_MAX_LINE_LEN];
     220    char *p, *p2;
     221    int line = 0;
     222    PROFILESECTION *section, *first_section;
     223    PROFILESECTION **next_section;
     224    PROFILEKEY *key, *prev_key, **next_key;
     225
     226    first_section = (PROFILESECTION *)HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
     227    first_section->name = NULL;
     228    first_section->key  = NULL;
     229    first_section->next = NULL;
     230    next_section = &first_section->next;
     231    next_key     = &first_section->key;
     232    prev_key     = NULL;
     233
     234    while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
     235    {
     236        line++;
     237        p = buffer;
     238        while (*p && PROFILE_isspace(*p)) p++;
     239        if (*p == '[')  /* section start */
     240        {
     241            if (!(p2 = strrchr( p, ']' )))
     242            {
     243                dprintf(("Kernel32:Profile:Invalid section header at line %d: '%s'\n",
     244           line, p ));
     245            }
     246            else
     247            {
     248                *p2 = '\0';
     249                p++;
     250                section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(*section) );
     251                section->name = HEAP_strdupA( SystemHeap, 0, p );
     252                section->key  = NULL;
     253                section->next = NULL;
     254                *next_section = section;
     255                next_section  = &section->next;
     256                next_key      = &section->key;
     257                prev_key      = NULL;
     258
     259                dprintf(("Kernel32:Profile:New section: '%s'\n",section->name));
     260
     261                continue;
     262            }
     263        }
     264
     265        p2=p+strlen(p) - 1;
     266        while ((p2 > p) && ((*p2 == '\n') || PROFILE_isspace(*p2))) *p2--='\0';
     267
     268        if ((p2 = strchr( p, '=' )) != NULL)
     269        {
     270            char *p3 = p2 - 1;
     271            while ((p3 > p) && PROFILE_isspace(*p3)) *p3-- = '\0';
     272            *p2++ = '\0';
     273            while (*p2 && PROFILE_isspace(*p2)) p2++;
     274        }
     275
     276        if(*p || !prev_key || *prev_key->name)
     277          {
     278           key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(*key) );
     279           key->name  = HEAP_strdupA( SystemHeap, 0, p );
     280           key->value = p2 ? HEAP_strdupA( SystemHeap, 0, p2 ) : NULL;
     281           key->next  = NULL;
     282           *next_key  = key;
     283           next_key   = &key->next;
     284           prev_key   = key;
     285
     286           dprintf(("Kernel32:Profile:New key: name='%s', value='%s'\n",key->name,key->value?key->value:"(none)"));
     287          }
     288    }
     289    return first_section;
     290}
     291
     292
     293/***********************************************************************
     294 *           PROFILE_DeleteSection
     295 *
     296 * Delete a section from a profile tree.
     297 */
     298static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
     299{
     300    while (*section)
     301    {
     302        if ((*section)->name && !strcasecmp( (*section)->name, name ))
     303        {
     304            PROFILESECTION *to_del = *section;
     305            *section = to_del->next;
     306            to_del->next = NULL;
     307            PROFILE_Free( to_del );
     308            return TRUE;
     309        }
     310        section = &(*section)->next;
     311    }
     312    return FALSE;
     313}
     314
     315
     316/***********************************************************************
     317 *           PROFILE_DeleteKey
     318 *
     319 * Delete a key from a profile tree.
     320 */
     321static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
     322                LPCSTR section_name, LPCSTR key_name )
     323{
     324    while (*section)
     325    {
     326        if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
     327        {
     328            PROFILEKEY **key = &(*section)->key;
     329            while (*key)
     330            {
     331                if (!strcasecmp( (*key)->name, key_name ))
     332                {
     333                    PROFILEKEY *to_del = *key;
     334                    *key = to_del->next;
     335                    if (to_del->name) HeapFree( SystemHeap, 0, to_del->name );
     336                    if (to_del->value) HeapFree( SystemHeap, 0, to_del->value);
     337                    HeapFree( SystemHeap, 0, to_del );
     338                    return TRUE;
     339                }
     340                key = &(*key)->next;
     341            }
     342        }
     343        section = &(*section)->next;
     344    }
     345    return FALSE;
     346}
     347
     348
     349/***********************************************************************
     350 *           PROFILE_Find
     351 *
     352 * Find a key in a profile tree, optionally creating it.
     353 */
     354static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
     355                                 const char *section_name,
     356                                 const char *key_name, int create )
     357{
     358    while (*section)
     359    {
     360        if ((*section)->name && !strcasecmp( (*section)->name, section_name ))
     361        {
     362            PROFILEKEY **key = &(*section)->key;
     363            while (*key)
     364            {
     365                if (!strcasecmp( (*key)->name, key_name )) return *key;
     366                key = &(*key)->next;
     367            }
     368            if (!create) return NULL;
     369            *key = (PROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
     370            (*key)->name  = HEAP_strdupA( SystemHeap, 0, key_name );
     371            (*key)->value = NULL;
     372            (*key)->next  = NULL;
     373            return *key;
     374        }
     375        section = &(*section)->next;
     376    }
     377    if (!create) return NULL;
     378    *section = (PROFILESECTION*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILESECTION) );
     379    (*section)->name = HEAP_strdupA( SystemHeap, 0, section_name );
     380    (*section)->next = NULL;
     381    (*section)->key  = (tagPROFILEKEY*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILEKEY) );
     382    (*section)->key->name  = HEAP_strdupA( SystemHeap, 0, key_name );
     383    (*section)->key->value = NULL;
     384    (*section)->key->next  = NULL;
     385    return (*section)->key;
     386}
     387
     388
     389/***********************************************************************
     390 *           PROFILE_FlushFile
     391 *
     392 * Flush the current profile to disk if changed.
     393 */
     394static BOOL PROFILE_FlushFile(void)
     395{
     396    char *p, buffer[MAX_PATHNAME_LEN];
     397    const char *unix_name;
     398    FILE *file = NULL;
     399    struct stat buf;
     400
     401    if(!CurProfile)
     402    {
     403        dprintf(("Kernel32:Profile:No current profile!\n"));
     404        return FALSE;
     405    }
     406
     407    if (!CurProfile->changed || !CurProfile->dos_name) return TRUE;
     408    if (!(unix_name = CurProfile->unix_name) || !(file = fopen(unix_name, "w")))
     409    {
     410        /* Try to create it in $HOME/.wine */
     411        /* FIXME: this will need a more general solution */
     412        if ((p = getenv( "HOME" )) != NULL)
     413        {
     414            strcpy( buffer, p );
     415            strcat( buffer, "/.wine/" );
     416            p = buffer + strlen(buffer);
     417            strcpy( p, strrchr( CurProfile->dos_name, '\\' ) + 1 );
     418            CharLowerA( p );
     419            file = fopen( buffer, "w" );
     420            unix_name = buffer;
     421        }
     422    }
     423
     424    if (!file)
     425    {
     426        dprintf(("Kernel32:Profile:could not save profile file %s\n", CurProfile->dos_name));
     427        return FALSE;
     428    }
     429
     430    dprintf(("Kernel32:Profile:Saving '%s' into '%s'\n", CurProfile->dos_name, unix_name ));
     431    PROFILE_Save( file, CurProfile->section );
     432    fclose( file );
     433    CurProfile->changed = FALSE;
     434    if(!stat(unix_name,&buf))
     435       CurProfile->mtime=buf.st_mtime;
     436    return TRUE;
     437}
     438
     439
     440/***********************************************************************
     441 *           PROFILE_ReleaseFile
     442 *
     443 * Flush the current profile to disk and remove it from the cache.
     444 */
     445static void PROFILE_ReleaseFile(void)
     446{
     447    PROFILE_FlushFile();
     448    PROFILE_Free( CurProfile->section );
     449    if (CurProfile->dos_name) HeapFree( SystemHeap, 0, CurProfile->dos_name );
     450    if (CurProfile->unix_name) HeapFree( SystemHeap, 0, CurProfile->unix_name );
     451    if (CurProfile->filename) HeapFree( SystemHeap, 0, CurProfile->filename );
     452    CurProfile->changed   = FALSE;
     453    CurProfile->section   = NULL;
     454    CurProfile->dos_name  = NULL;
     455    CurProfile->unix_name = NULL;
     456    CurProfile->filename  = NULL;
     457    CurProfile->mtime     = 0;
     458}
     459
     460
     461/***********************************************************************
     462 *           PROFILE_Open
     463 *
     464 * Open a profile file, checking the cached file first.
     465 */
     466static BOOL PROFILE_Open( LPCSTR filename )
     467{
     468    char buffer[MAX_PATHNAME_LEN];
     469    char *newdos_name, *p;
     470    FILE *file = NULL;
     471    int i,j;
     472    struct stat buf;
     473    PROFILE *tempProfile;
     474
     475    /* First time around */
     476
     477    if(!CurProfile)
     478       for(i=0;i<N_CACHED_PROFILES;i++)
     479         {
     480          MRUProfile[i]= (PROFILE*)HEAP_xalloc( SystemHeap, 0, sizeof(PROFILE) );
     481          MRUProfile[i]->changed=FALSE;
     482          MRUProfile[i]->section=NULL;
     483          MRUProfile[i]->dos_name=NULL;
     484          MRUProfile[i]->unix_name=NULL;
     485          MRUProfile[i]->filename=NULL;
     486          MRUProfile[i]->mtime=0;
     487         }
     488
     489    /* Check for a match */
     490
     491    if (!strchr( filename, '/' ) &&
     492        !strchr( filename, '\\' ) &&
     493        !strchr( filename, ':' ))
     494    {
     495        GetWindowsDirectoryA( buffer, sizeof(buffer) );
     496        strcat( buffer, "\\" );
     497        strcat( buffer, filename );
     498    }
     499
     500    for(i=0;i<N_CACHED_PROFILES;i++)
     501      {
     502       if ((MRUProfile[i]->filename && !strcmp( filename, MRUProfile[i]->filename )))
     503         {
     504          if(i)
     505            {
     506             PROFILE_FlushFile();
     507             tempProfile=MRUProfile[i];
     508             for(j=i;j>0;j--)
     509                MRUProfile[j]=MRUProfile[j-1];
     510             CurProfile=tempProfile;
     511            }
     512          if(!stat(CurProfile->unix_name,&buf) && CurProfile->mtime==buf.st_mtime)
     513             dprintf(("Kernel32:Profile:(%s): already opened (mru=%d)\n",
     514                              filename, i ));
     515          else
     516              dprintf(("Kernel32:Profile:(%s): already opened, needs refreshing (mru=%d)\n",
     517                             filename, i ));
     518     return TRUE;
     519         }
     520      }
     521
     522    /* Rotate the oldest to the top to be replaced */
     523
     524    if(i==N_CACHED_PROFILES)
     525      {
     526       tempProfile=MRUProfile[N_CACHED_PROFILES-1];
     527       for(i=N_CACHED_PROFILES-1;i>0;i--)
     528          MRUProfile[i]=MRUProfile[i-1];
     529       CurProfile=tempProfile;
     530      }
     531
     532    /* Flush the profile */
     533
     534    if(CurProfile->filename) PROFILE_ReleaseFile();
     535
     536    newdos_name = HEAP_strdupA( SystemHeap, 0, filename );
     537    CurProfile->dos_name  = newdos_name;
     538    CurProfile->filename  = HEAP_strdupA( SystemHeap, 0, filename );
     539
     540    /* Try to open the profile file, first in $HOME/.wine */
     541
     542    /* FIXME: this will need a more general solution */
     543    if ((p = getenv( "HOME" )) != NULL)
     544    {
     545        strcpy( buffer, p );
     546        strcat( buffer, "/.wine/" );
     547        p = buffer + strlen(buffer);
     548        strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
     549        CharLowerA( p );
     550        if ((file = fopen( buffer, "r" )))
     551        {
     552            dprintf(("Kernel32:Profile:(%s): found it in %s\n",
     553                             filename, buffer ));
     554            CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
     555        }
     556    }
     557
     558    if (!file)
     559    {
     560        CurProfile->unix_name = HEAP_strdupA( SystemHeap, 0,
     561                                             filename );
     562        if ((file = fopen( filename, "r" )))
     563            dprintf(("Kernel32:Profile:(%s): found it in %s\n",
     564                             filename, filename ));
     565    }
     566
     567    if (file)
     568    {
     569        CurProfile->section = PROFILE_Load( file );
     570        fclose( file );
     571        if(!stat(CurProfile->unix_name,&buf))
     572           CurProfile->mtime=buf.st_mtime;
     573    }
     574    else
     575    {
     576        /* Does not exist yet, we will create it in PROFILE_FlushFile */
     577        dprintf(("Kernel32:Profile:profile file %s not found\n", newdos_name ));
     578    }
     579    return TRUE;
     580}
     581
     582
     583/***********************************************************************
     584 *           PROFILE_GetSection
     585 *
     586 * Returns all keys of a section.
     587 * If return_values is TRUE, also include the corresponding values.
     588 */
     589static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
     590                LPSTR buffer, UINT len, BOOL handle_env,
     591                BOOL return_values )
     592{
     593    PROFILEKEY *key;
     594    while (section)
     595    {
     596        if (section->name && !strcasecmp( section->name, section_name ))
     597        {
     598            UINT oldlen = len;
     599            for (key = section->key; key; key = key->next)
     600            {
     601                if (len <= 2) break;
     602                if (!*key->name) continue;  /* Skip empty lines */
     603                if (IS_ENTRY_COMMENT(key->name)) continue;  /* Skip comments */
     604                PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
     605                len -= strlen(buffer) + 1;
     606                buffer += strlen(buffer) + 1;
     607      if (return_values && key->value) {
     608         buffer[-1] = '=';
     609         PROFILE_CopyEntry ( buffer,
     610            key->value, len - 1, handle_env );
     611         len -= strlen(buffer) + 1;
     612         buffer += strlen(buffer) + 1;
     613                }
     614            }
     615            *buffer = '\0';
     616            if (len <= 1)
     617                /*If either lpszSection or lpszKey is NULL and the supplied
     618                  destination buffer is too small to hold all the strings,
     619                  the last string is truncated and followed by two null characters.
     620                  In this case, the return value is equal to cchReturnBuffer
     621                  minus two. */
     622            {
     623      buffer[-1] = '\0';
     624                return oldlen - 2;
     625            }
     626            return oldlen - len;
     627        }
     628        section = section->next;
     629    }
     630    buffer[0] = buffer[1] = '\0';
     631    return 0;
     632}
     633
     634
     635static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
     636{
     637    LPSTR buf = buffer;
     638    WORD l, cursize = 0;
     639    PROFILESECTION *section;
     640
     641    for (section = CurProfile->section; section; section = section->next)
     642   if (section->name) {
     643       l = strlen(section->name);
     644       cursize += l+1;
     645       if (cursize > len+1)
     646      return len-2;
     647
     648       strcpy(buf, section->name);
     649       buf += l+1;
     650   }
     651
     652    *buf=0;
     653    buf++;
     654    return buf-buffer;
     655}
     656
     657
     658/***********************************************************************
     659 *           PROFILE_GetString
     660 *
     661 * Get a profile string.
     662 */
     663static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
     664               LPCSTR def_val, LPSTR buffer, UINT len )
     665{
     666    PROFILEKEY *key = NULL;
     667
     668    if (!def_val) def_val = "";
     669    if (key_name && key_name[0])
     670    {
     671        key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE );
     672        PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
     673                           len, FALSE );
     674        dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",
     675                         section, key_name, def_val, buffer ));
     676        return strlen( buffer );
     677    }
     678    if (section && section[0])
     679        return PROFILE_GetSection(CurProfile->section, section, buffer, len,
     680            FALSE, FALSE);
     681    /* undocumented; both section and key_name are NULL */
     682    return PROFILE_GetSectionNames(buffer, len);
     683}
     684
     685
     686/***********************************************************************
     687 *           PROFILE_SetString
     688 *
     689 * Set a profile string.
     690 */
     691static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
     692                LPCSTR value )
     693{
     694    if (!key_name)  /* Delete a whole section */
     695    {
     696        dprintf(("Kernel32:Profile:('%s')\n", section_name));
     697        CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section,
     698                                                      section_name );
     699        return TRUE;         /* Even if PROFILE_DeleteSection() has failed,
     700                                this is not an error on application's level.*/
     701    }
     702    else if (!value)  /* Delete a key */
     703    {
     704        dprintf(("Kernel32:Profile:('%s','%s')\n",
     705                         section_name, key_name ));
     706        CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section,
     707                                                  section_name, key_name );
     708        return TRUE;          /* same error handling as above */
     709    }
     710    else  /* Set the key value */
     711    {
     712        PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section_name,
     713                                        key_name, TRUE );
     714        dprintf(("Kernel32:Profile:('%s','%s','%s'): \n",
     715                         section_name, key_name, value ));
     716        if (!key) return FALSE;
     717        if (key->value)
     718        {
     719            if (!strcmp( key->value, value ))
     720            {
     721                dprintf(("Kernel32:Profile:  no change needed\n" ));
     722                return TRUE;  /* No change needed */
     723            }
     724            dprintf(("Kernel32:Profile:  replacing '%s'\n", key->value ));
     725            HeapFree( SystemHeap, 0, key->value );
     726        }
     727        else dprintf(("Kernel32:Profile:  creating key\n" ));
     728        key->value = HEAP_strdupA( SystemHeap, 0, value );
     729        CurProfile->changed = TRUE;
     730    }
     731    return TRUE;
     732}
     733
     734
     735/***********************************************************************
     736 *           PROFILE_GetWineIniString
     737 *
     738 * Get a config string from the wine.ini file.
     739 */
     740int PROFILE_GetWineIniString( const char *section, const char *key_name,
     741                              const char *def, char *buffer, int len )
     742{
     743    int  ret;
     744
     745    EnterCriticalSection( &PROFILE_CritSect );
     746
     747    if (key_name)
     748    {
     749        PROFILEKEY *key = PROFILE_Find(&PROFILE_WineProfile, section, key_name, FALSE);
     750        PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
     751                           len, TRUE );
     752        dprintf(("Kernel32:Profile:('%s','%s','%s'): returning '%s'\n",
     753                         section, key_name, def, buffer ));
     754        ret = strlen( buffer );
     755    }
     756    else
     757    {
     758       ret = PROFILE_GetSection( PROFILE_WineProfile, section, buffer, len, TRUE, FALSE );
     759    }
     760    LeaveCriticalSection( &PROFILE_CritSect );
     761
     762    return ret;
     763}
     764
     765
     766/***********************************************************************
     767 *           PROFILE_GetWineIniInt
     768 *
     769 * Get a config integer from the wine.ini file.
     770 */
     771int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
     772{
     773    char buffer[20];
     774    char *p;
     775    long result;
     776    PROFILEKEY *key;
     777    int  ret;
     778
     779    EnterCriticalSection( &PROFILE_CritSect );
     780
     781    key = PROFILE_Find( &PROFILE_WineProfile, section, key_name, FALSE );
     782    if (!key || !key->value) {
     783       ret = def;
     784    } else {
     785       PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
     786       result = strtol( buffer, &p, 0 );
     787       ret = (p == buffer) ? 0  /* No digits at all */ : (int)result;
     788    }
     789
     790    LeaveCriticalSection( &PROFILE_CritSect );
     791
     792    return ret;
     793}
     794
     795
     796/******************************************************************************
     797 *
     798 *   int  PROFILE_EnumerateWineIniSection(
     799 *     char const  *section,  #Name of the section to enumerate
     800 *     void  (*cbfn)(char const *key, char const *value, void *user),
     801 *                            # Address of the callback function
     802 *     void  *user )          # User-specified pointer.
     803 *
     804 *   For each entry in a section in the wine.conf file, this function will
     805 *   call the specified callback function, informing it of each key and
     806 *   value.  An optional user pointer may be passed to it (if this is not
     807 *   needed, pass NULL through it and ignore the value in the callback
     808 *   function).
     809 *
     810 *   The callback function must accept three parameters:
     811 *      The name of the key (char const *)
     812 *      The value of the key (char const *)
     813 *      A user-specified parameter (void *)
     814 *   Note that the first two are char CONST *'s, not char *'s!  The callback
     815 *   MUST not modify these strings!
     816 *
     817 *   The return value indicates the number of times the callback function
     818 *   was called.
     819 */
     820int  PROFILE_EnumerateWineIniSection(
     821    char const  *section,
     822    void  (*cbfn)(char const *, char const *, void *),
     823    void  *userptr )
     824{
     825    PROFILESECTION  *scansect;
     826    PROFILEKEY  *scankey;
     827    int  calls = 0;
     828
     829    EnterCriticalSection( &PROFILE_CritSect );
     830
     831    /* Search for the correct section */
     832    for(scansect = PROFILE_WineProfile; scansect; scansect = scansect->next) {
     833   if(scansect->name && !strcasecmp(scansect->name, section)) {
     834
     835       /* Enumerate each key with the callback */
     836       for(scankey = scansect->key; scankey; scankey = scankey->next) {
     837
     838      /* Ignore blank entries -- these shouldn't exist, but let's
     839         be extra careful */
     840      if(scankey->name[0]) {
     841          cbfn(scankey->name, scankey->value, userptr);
     842          ++calls;
     843      }
     844       }
     845
     846       break;
     847   }
     848    }
     849    LeaveCriticalSection( &PROFILE_CritSect );
     850
     851    return calls;
     852}
     853
     854
     855/******************************************************************************
     856 *
     857 *   int  PROFILE_GetWineIniBool(
     858 *      char const  *section,
     859 *      char const  *key_name,
     860 *      int  def )
     861 *
     862 *   Reads a boolean value from the wine.ini file.  This function attempts to
     863 *   be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
     864 *   (zero) for false, 'y', 'Y' (yes), 't', 'T' (true), or '1' (one) for
     865 *   true.  Anything else results in the return of the default value.
     866 *
     867 *   This function uses 1 to indicate true, and 0 for false.  You can check
     868 *   for existence by setting def to something other than 0 or 1 and
     869 *   examining the return value.
     870 */
     871int  PROFILE_GetWineIniBool(
     872    char const  *section,
     873    char const  *key_name,
     874    int  def )
     875{
     876    char  key_value[2];
     877    int  retval;
     878
     879    PROFILE_GetWineIniString(section, key_name, "~", key_value, 2);
     880
     881    switch(key_value[0]) {
     882    case 'n':
     883    case 'N':
     884    case 'f':
     885    case 'F':
     886    case '0':
     887   retval = 0;
     888   break;
     889
     890    case 'y':
     891    case 'Y':
     892    case 't':
     893    case 'T':
     894    case '1':
     895   retval = 1;
     896   break;
     897
     898    default:
     899   retval = def;
     900    }
     901
     902    dprintf(("Kernel32:Profile:(\"%s\", \"%s\", %s), "
     903          "[%c], ret %s.\n", section, key_name,
     904          def ? "TRUE" : "FALSE", key_value[0],
     905          retval ? "TRUE" : "FALSE"));
     906
     907    return retval;
     908}
     909
     910
     911#if 0
     912/***********************************************************************
     913 *           PROFILE_LoadWineIni
     914 *
     915 * Load the wine.ini file.
     916 */
     917int PROFILE_LoadWineIni(void)
     918{
     919    char buffer[MAX_PATHNAME_LEN];
     920    const char *p;
     921    FILE *f;
     922
     923    InitializeCriticalSection( &PROFILE_CritSect );
     924    MakeCriticalSectionGlobal( &PROFILE_CritSect );
     925
     926    if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
     927    {
     928      /* Open -config specified file */
     929      PROFILE_WineProfile = PROFILE_Load ( f);
     930      fclose ( f );
     931      strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);
     932      return 1;
     933    }
     934
     935    if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
     936    {
     937   PROFILE_WineProfile = PROFILE_Load( f );
     938   fclose( f );
     939   strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);
     940   return 1;
     941    }
     942    if ((p = getenv( "HOME" )) != NULL)
     943    {
     944        lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
     945        strcat( buffer, PROFILE_WineIniName );
     946        if ((f = fopen( buffer, "r" )) != NULL)
     947        {
     948            PROFILE_WineProfile = PROFILE_Load( f );
     949            fclose( f );
     950       strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);
     951            return 1;
     952        }
     953    }
     954    else dprintf(("Kernel32:Profile:could not get $HOME value for config file.\n" ));
     955
     956    /* Try global file */
     957
     958    if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
     959    {
     960        PROFILE_WineProfile = PROFILE_Load( f );
     961        fclose( f );
     962   strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);
     963        return 1;
     964    }
     965    MESSAGE( "Can't open configuration file %s or $HOME%s\n",
     966    WINE_INI_GLOBAL, PROFILE_WineIniName );
     967    return 0;
     968}
     969
     970
     971/***********************************************************************
     972 *           PROFILE_UsageWineIni
     973 *
     974 * Explain the wine.ini file to those who don't read documentation.
     975 * Keep below one screenful in length so that error messages above are
     976 * noticed.
     977 */
     978void PROFILE_UsageWineIni(void)
     979{
     980    MESSAGE("Perhaps you have not properly edited or created "
     981   "your Wine configuration file.\n");
     982    MESSAGE("This is either %s or $HOME%s\n",WINE_INI_GLOBAL,PROFILE_WineIniName);
     983    MESSAGE("  or it is determined by the -config option or from\n"
     984        "  the WINE_INI environment variable.\n");
     985    if (*PROFILE_WineIniUsed)
     986   MESSAGE("Wine has used %s as configuration file.\n", PROFILE_WineIniUsed);
     987    /* RTFM, so to say */
     988}
     989#endif
     990
     991/***********************************************************************
     992 *           PROFILE_GetStringItem
     993 *
     994 *  Convenience function that turns a string 'xxx, yyy, zzz' into
     995 *  the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'.
     996 */
     997char* PROFILE_GetStringItem( char* start )
     998{
     999    char* lpchX, *lpch;
     1000
     1001    for (lpchX = start, lpch = NULL; *lpchX != '\0'; lpchX++ )
     1002    {
     1003        if( *lpchX == ',' )
     1004        {
     1005            if( lpch ) *lpch = '\0'; else *lpchX = '\0';
     1006            while( *(++lpchX) )
     1007                if( !PROFILE_isspace(*lpchX) ) return lpchX;
     1008        }
     1009   else if( PROFILE_isspace( *lpchX ) && !lpch ) lpch = lpchX;
     1010        else lpch = NULL;
     1011    }
     1012    if( lpch ) *lpch = '\0';
     1013    return NULL;
     1014}
     1015
     1016/********************* API functions **********************************/
     1017
     1018/***********************************************************************
     1019 *           GetProfileInt32A   (KERNEL32.264)
     1020 */
     1021UINT WINAPI GetProfileIntA( LPCSTR section, LPCSTR entry, INT def_val )
     1022{
     1023    return GetPrivateProfileIntA( section, entry, def_val, "win.ini" );
     1024}
     1025
     1026/***********************************************************************
     1027 *           GetProfileInt32W   (KERNEL32.264)
     1028 */
     1029UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )
     1030{
     1031    if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
     1032    return GetPrivateProfileIntW( section, entry, def_val, wininiW );
     1033}
     1034
     1035/***********************************************************************
     1036 *           GetProfileString32A   (KERNEL32.268)
     1037 */
     1038INT WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,
     1039               LPSTR buffer, UINT len )
     1040{
     1041    return GetPrivateProfileStringA( section, entry, def_val,
     1042                 buffer, len, "win.ini" );
     1043}
     1044
     1045/***********************************************************************
     1046 *           GetProfileString32W   (KERNEL32.269)
     1047 */
     1048INT WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry,
     1049               LPCWSTR def_val, LPWSTR buffer, UINT len )
     1050{
     1051    if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
     1052    return GetPrivateProfileStringW( section, entry, def_val,
     1053                 buffer, len, wininiW );
     1054}
     1055
     1056/***********************************************************************
     1057 *           WriteProfileString32A   (KERNEL32.587)
     1058 */
     1059BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry,
     1060             LPCSTR string )
     1061{
     1062    return WritePrivateProfileStringA( section, entry, string, "win.ini" );
     1063}
     1064
     1065/***********************************************************************
     1066 *           WriteProfileString32W   (KERNEL32.588)
     1067 */
     1068BOOL WINAPI WriteProfileStringW( LPCWSTR section, LPCWSTR entry,
     1069                                     LPCWSTR string )
     1070{
     1071    if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
     1072    return WritePrivateProfileStringW( section, entry, string, wininiW );
     1073}
     1074
     1075/***********************************************************************
     1076 *           GetPrivateProfileInt32A   (KERNEL32.251)
     1077 */
     1078UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
     1079               INT def_val, LPCSTR filename )
     1080{
     1081    char buffer[20];
     1082    char *p;
     1083    long result;
     1084
     1085    GetPrivateProfileStringA( section, entry, "",
     1086                                buffer, sizeof(buffer), filename );
     1087    if (!buffer[0]) return (UINT)def_val;
     1088    result = strtol( buffer, &p, 0 );
     1089    if (p == buffer) return 0;  /* No digits at all */
     1090    return (UINT)result;
     1091}
     1092
     1093/***********************************************************************
     1094 *           GetPrivateProfileInt32W   (KERNEL32.252)
     1095 */
     1096UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,
     1097               INT def_val, LPCWSTR filename )
     1098{
     1099    LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     1100    LPSTR entryA    = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
     1101    LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     1102    UINT res = GetPrivateProfileIntA(sectionA, entryA, def_val, filenameA);
     1103    HeapFree( GetProcessHeap(), 0, sectionA );
     1104    HeapFree( GetProcessHeap(), 0, filenameA );
     1105    HeapFree( GetProcessHeap(), 0, entryA );
     1106    return res;
     1107}
     1108
     1109/***********************************************************************
     1110 *           GetPrivateProfileString32A   (KERNEL32.255)
     1111 */
     1112INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
     1113                 LPCSTR def_val, LPSTR buffer,
     1114                 UINT len, LPCSTR filename )
     1115{
     1116    int     ret;
     1117
     1118    if (!filename)
     1119   filename = "win.ini";
     1120
     1121    EnterCriticalSection( &PROFILE_CritSect );
     1122
     1123    if (PROFILE_Open( filename )) {
     1124        ret = PROFILE_GetString( section, entry, def_val, buffer, len );
     1125    } else {
     1126       lstrcpynA( buffer, def_val, len );
     1127       ret = strlen( buffer );
     1128    }
     1129
     1130    LeaveCriticalSection( &PROFILE_CritSect );
     1131
     1132    return ret;
     1133}
     1134
     1135/***********************************************************************
     1136 *           GetPrivateProfileString32W   (KERNEL32.256)
     1137 */
     1138INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
     1139                 LPCWSTR def_val, LPWSTR buffer,
     1140                 UINT len, LPCWSTR filename )
     1141{
     1142    LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     1143    LPSTR entryA    = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
     1144    LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     1145    LPSTR def_valA  = HEAP_strdupWtoA( GetProcessHeap(), 0, def_val );
     1146    LPSTR bufferA   = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
     1147    INT ret = GetPrivateProfileStringA( sectionA, entryA, def_valA,
     1148                                            bufferA, len, filenameA );
     1149    lstrcpynAtoW( buffer, bufferA, len );
     1150    HeapFree( GetProcessHeap(), 0, sectionA );
     1151    HeapFree( GetProcessHeap(), 0, entryA );
     1152    HeapFree( GetProcessHeap(), 0, filenameA );
     1153    HeapFree( GetProcessHeap(), 0, def_valA );
     1154    HeapFree( GetProcessHeap(), 0, bufferA);
     1155    return ret;
     1156}
     1157
     1158/***********************************************************************
     1159 *           GetPrivateProfileSection32A   (KERNEL32.255)
     1160 */
     1161INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,
     1162                  DWORD len, LPCSTR filename )
     1163{
     1164    int     ret = 0;
     1165
     1166    EnterCriticalSection( &PROFILE_CritSect );
     1167
     1168    if (PROFILE_Open( filename ))
     1169        ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
     1170             FALSE, TRUE);
     1171
     1172    LeaveCriticalSection( &PROFILE_CritSect );
     1173
     1174    return ret;
     1175}
     1176
     1177/***********************************************************************
     1178 *           GetPrivateProfileSection32W   (KERNEL32.256)
     1179 */
     1180
     1181INT WINAPI GetPrivateProfileSectionW (LPCWSTR section, LPWSTR buffer,
     1182                  DWORD len, LPCWSTR filename )
     1183
     1184{
     1185    LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     1186    LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     1187    LPSTR bufferA   = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
     1188    INT ret = GetPrivateProfileSectionA( sectionA, bufferA, len,
     1189                  filenameA );
     1190    MultiByteToWideChar(CP_ACP,0,bufferA,ret,buffer,len);
     1191    HeapFree( GetProcessHeap(), 0, sectionA );
     1192    HeapFree( GetProcessHeap(), 0, filenameA );
     1193    HeapFree( GetProcessHeap(), 0, bufferA);
     1194    return ret;
     1195}
     1196
     1197/***********************************************************************
     1198 *           GetProfileSection32A   (KERNEL32.268)
     1199 */
     1200INT WINAPI GetProfileSectionA( LPCSTR section, LPSTR buffer, DWORD len )
     1201{
     1202    return GetPrivateProfileSectionA( section, buffer, len, "win.ini" );
     1203}
     1204
     1205/***********************************************************************
     1206 *           GetProfileSection32W   (KERNEL32)
     1207 */
     1208INT WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len )
     1209{
     1210    if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
     1211    return GetPrivateProfileSectionW( section, buffer, len, wininiW );
     1212}
     1213
     1214/***********************************************************************
     1215 *           WritePrivateProfileString32A   (KERNEL32.582)
     1216 */
     1217BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
     1218               LPCSTR string, LPCSTR filename )
     1219{
     1220    BOOL ret = FALSE;
     1221
     1222    EnterCriticalSection( &PROFILE_CritSect );
     1223
     1224    if (PROFILE_Open( filename ))
     1225    {
     1226        if (!section && !entry && !string)
     1227            PROFILE_ReleaseFile();  /* always return FALSE in this case */
     1228        else
     1229            ret = PROFILE_SetString( section, entry, string );
     1230    }
     1231
     1232    LeaveCriticalSection( &PROFILE_CritSect );
     1233    return ret;
     1234}
     1235
     1236/***********************************************************************
     1237 *           WritePrivateProfileString32W   (KERNEL32.583)
     1238 */
     1239BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
     1240               LPCWSTR string, LPCWSTR filename )
     1241{
     1242    LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     1243    LPSTR entryA    = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
     1244    LPSTR stringA   = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
     1245    LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     1246    BOOL res = WritePrivateProfileStringA( sectionA, entryA,
     1247                  stringA, filenameA );
     1248    HeapFree( GetProcessHeap(), 0, sectionA );
     1249    HeapFree( GetProcessHeap(), 0, entryA );
     1250    HeapFree( GetProcessHeap(), 0, stringA );
     1251    HeapFree( GetProcessHeap(), 0, filenameA );
     1252    return res;
     1253}
     1254
     1255/***********************************************************************
     1256 *           WritePrivateProfileSection32A   (KERNEL32)
     1257 */
     1258BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section,
     1259                LPCSTR string, LPCSTR filename )
     1260{
     1261  char *p =(char*)string;
     1262
     1263  dprintf(("Kernel32:Profile:fixme WritePrivateProfileSection32A empty stub\n"));
    3441264  return FALSE;
    3451265}
    3461266
    347 
    348 /*****************************************************************************
    349  * Name      : BOOL GetPrivateProfileStructW
    350  * Purpose   : The GetPrivateProfileStructW function retrieves the data associated
    351  *             with the specified key in the given section of an initialization
    352  *             file. As it retrieves the data, the function calculates a checksum
    353  *             and compares it with the checksum calculated by the WritePrivateProfileStruct
    354  *             function when the data was added to the file. This function is provided
    355  *             for compatibility with 16-bit Windows-based applications. Win32-based
    356  *             applications should store initialization information in the registry.
    357  * Parameters: LPCWSTR lpszSection  address of section name
    358  *             LPCWSTR lpszKey      address of key name
    359  *             LPVOID  lpStruct     address of return buffer
    360  *             UINT    uSizeStruct  size of return buffer
    361  *             LPCWSTR szFile       address of initialization filename
    362  * Variables :
    363  * Result    : TRUE / FALSE
    364  * Remark    :
    365  * Status    : UNTESTED STUB
    366  *
    367  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    368  *****************************************************************************/
    369 
    370 BOOL WIN32API GetPrivateProfileStructW(LPCWSTR lpszSection,
    371                                           LPCWSTR lpszKey,
    372                                           LPVOID  lpStruct,
    373                                           UINT    uSizeStruct,
    374                                           LPCWSTR szFile)
    375 {
    376   dprintf(("KERNEL32: GetPrivateProfileStructW(%s,%s,%08xh,%08xh,%s) not implemented.\n",
    377            lpszSection,
    378            lpszKey,
    379            lpStruct,
    380            uSizeStruct,
    381            szFile));
    382 
    383   return FALSE;
    384 }
    385 
    386 
    387 /*****************************************************************************
    388  * Name      : BOOL GetPrivateProfileSectionNamesA
    389  * Purpose   : The GetPrivateProfileSectionNames function retrieves the names
    390  *             of all sections in an initialization file. This function is
    391  *             provided for compatibility with 16-bit Windows-based applications.
    392  *             Win32-based applications should store initialization information
    393  *             in the registry.
    394  * Parameters: LPTSTR  lpszReturnBuffer address of return buffer
    395  *             DWORD   nSize            size of return buffer
    396  *             LPCTSTR lpFileName       address of initialization filename
    397  * Variables :
    398  * Result    : TRUE / FALSE
    399  * Remark    :
    400  * Status    : UNTESTED STUB
    401  *
    402  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    403  *****************************************************************************/
    404 
    405 DWORD WIN32API GetPrivateProfileSectionNamesA(LPTSTR  lpszReturnBuffer,
    406                                                  DWORD   nSize,
    407                                                  LPCTSTR lpFileName)
    408 {
    409   dprintf(("KERNEL32: GetPrivateProfileSectionNamesA(%08xh,%08xh,%s) not implemented.\n",
    410            lpszReturnBuffer,
    411            nSize,
    412            lpFileName));
    413 
    414   return FALSE;
    415 }
    416 
    417 
    418 /*****************************************************************************
    419  * Name      : BOOL GetPrivateProfileSectionNamesW
    420  * Purpose   : The GetPrivateProfileSectionNames function retrieves the names
    421  *             of all sections in an initialization file. This function is
    422  *             provided for compatibility with 16-bit Windows-based applications.
    423  *             Win32-based applications should store initialization information
    424  *             in the registry.
    425  * Parameters: LPWSTR  lpszReturnBuffer address of return buffer
    426  *             DWORD   nSize            size of return buffer
    427  *             LPCTSTR lpFileName       address of initialization filename
    428  * Variables :
    429  * Result    : TRUE / FALSE
    430  * Remark    :
    431  * Status    : UNTESTED STUB
    432  *
    433  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    434  *****************************************************************************/
    435 
    436 DWORD WIN32API GetPrivateProfileSectionNamesW(LPWSTR  lpszReturnBuffer,
    437                                               DWORD   nSize,
    438                                               LPCWSTR lpFileName)
    439 {
    440   dprintf(("KERNEL32: GetPrivateProfileSectionNamesW(%08xh,%08xh,%s) not implemented.\n",
    441            lpszReturnBuffer,
    442            nSize,
    443            lpFileName));
    444 
    445   return FALSE;
    446 }
    447 /*****************************************************************************
    448  * Name      : BOOL WritePrivateProfileSectionA
    449  * Purpose   : The WritePrivateProfileSection function replaces the keys and
    450  *             values under the specified section in an initialization file.
    451  *             This function is provided for compatibility with 16-bit
    452  *             Windows-based applications. Win32-based applications should
    453  *             store initialization information in the registry.
    454  * Parameters: LPCTSTR lpszSection       address of string with section name
    455  *             LPCTSTR lpszKeysAndValues address of string with data
    456  *             LPCTSTR lpszFile          address of string with filename
    457  * Variables :
    458  * Result    : TRUE / FALSE
    459  * Remark    :
    460  * Status    : UNTESTED STUB
    461  *
    462  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    463  *****************************************************************************/
    464 
    465 BOOL WIN32API WritePrivateProfileSectionA(LPCTSTR lpszSection,
    466                                              LPCTSTR lpszKeysAndValues,
    467                                              LPCTSTR lpszFile)
    468 {
    469   dprintf(("KERNEL32: WritePrivateProfileSectionA(%s,%s,%s) not implemented.\n",
    470            lpszSection,
    471            lpszKeysAndValues,
    472            lpszFile));
    473 
    474   return (FALSE);
    475 }
    476 
    477 
    478 /*****************************************************************************
    479  * Name      : BOOL WritePrivateProfileSectionW
    480  * Purpose   : The WritePrivateProfileSection function replaces the keys and
    481  *             values under the specified section in an initialization file.
    482  *             This function is provided for compatibility with 16-bit
    483  *             Windows-based applications. Win32-based applications should
    484  *             store initialization information in the registry.
    485  * Parameters: LPCWSTR lpszSection       address of string with section name
    486  *             LPCWSTR lpszKeysAndValues address of string with data
    487  *             LPCWSTR lpszFile          address of string with filename
    488  * Variables :
    489  * Result    : TRUE / FALSE
    490  * Remark    :
    491  * Status    : UNTESTED STUB
    492  *
    493  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    494  *****************************************************************************/
    495 
    496 BOOL WIN32API WritePrivateProfileSectionW(LPCWSTR lpszSection,
    497                                              LPCWSTR lpszKeysAndValues,
    498                                              LPCWSTR lpszFile)
    499 {
    500   dprintf(("KERNEL32: WritePrivateProfileSectionW(%s,%s,%s) not implemented.\n",
    501            lpszSection,
    502            lpszKeysAndValues,
    503            lpszFile));
    504 
    505   return (FALSE);
    506 }
    507 
    508 
    509 /*****************************************************************************
    510  * Name      : BOOL WritePrivateProfileStructA
    511  * Purpose   : The WritePrivateProfileStruct function copies data into the
    512  *             specified key in the given section of an initialization file.
    513  *             As it copies the data, the function calculates a checksum and
    514  *             appends it to the end of the data. The GetPrivateProfileStruct
    515  *             function uses the checksum to ensure the integrity of the data.
    516  *             This function is provided for compatibility with 16-bit
    517  *             Windows-based applications. Win32-based applications should store
    518  *             initialization information in the registry.
    519  * Parameters: LPCTSTR lpszSection address of section name
    520  *             LPCTSTR lpszKey     address of key name
    521  *             LPVOID  lpvStruct   address of buffer that contains data to add
    522  *             UINT    uSizeStruct size, in bytes, of the buffer
    523  *             LPCTSTR lpszFile    address of initialization filename
    524  * Variables :
    525  * Result    : TRUE / FALSE
    526  * Remark    :
    527  * Status    : UNTESTED STUB
    528  *
    529  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    530  *****************************************************************************/
    531 
    532 BOOL WIN32API WritePrivateProfileStructA(LPCTSTR lpszSection,
    533                                             LPCTSTR lpszKey,
    534                                             LPVOID  lpvStruct,
    535                                             UINT    uSizeStruct,
    536                                             LPCTSTR lpszFile)
    537 {
    538   dprintf(("KERNEL32: WritePrivateProfileStructA(%s,%s,%08xh,%u,%s) not implemented.\n",
    539            lpszSection,
    540            lpszKey,
    541            lpvStruct,
    542            uSizeStruct,
    543            lpszFile));
    544 
    545   return (FALSE);
    546 }
    547 
    548 
    549 /*****************************************************************************
    550  * Name      : BOOL WritePrivateProfileStructW
    551  * Purpose   : The WritePrivateProfileStruct function copies data into the
    552  *             specified key in the given section of an initialization file.
    553  *             As it copies the data, the function calculates a checksum and
    554  *             appends it to the end of the data. The GetPrivateProfileStruct
    555  *             function uses the checksum to ensure the integrity of the data.
    556  *             This function is provided for compatibility with 16-bit
    557  *             Windows-based applications. Win32-based applications should store
    558  *             initialization information in the registry.
    559  * Parameters: LPCWSTR lpszSection address of section name
    560  *             LPCWSTR lpszKey     address of key name
    561  *             LPVOID  lpvStruct   address of buffer that contains data to add
    562  *             UINT    uSizeStruct size, in bytes, of the buffer
    563  *             LPCWSTR lpszFile    address of initialization filename
    564  * Variables :
    565  * Result    : TRUE / FALSE
    566  * Remark    :
    567  * Status    : UNTESTED STUB
    568  *
    569  * Author    : Patrick Haller [Mon, 1998/06/15 08:00]
    570  *****************************************************************************/
    571 
    572 BOOL WIN32API WritePrivateProfileStructW(LPCWSTR lpszSection,
    573                                             LPCWSTR lpszKey,
    574                                             LPVOID  lpvStruct,
    575                                             UINT    uSizeStruct,
    576                                             LPCWSTR lpszFile)
    577 {
    578   dprintf(("KERNEL32: WritePrivateProfileStructW(%s,%s,%08xh,%u,%s) not implemented.\n",
    579            lpszSection,
    580            lpszKey,
    581            lpvStruct,
    582            uSizeStruct,
    583            lpszFile));
    584 
    585   return (FALSE);
    586 }
     1267/***********************************************************************
     1268 *           WritePrivateProfileSection32W   (KERNEL32)
     1269 */
     1270BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
     1271                LPCWSTR string, LPCWSTR filename)
     1272
     1273{
     1274    LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     1275    LPSTR stringA   = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
     1276    LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     1277    BOOL res = WritePrivateProfileSectionA( sectionA, stringA, filenameA );
     1278    HeapFree( GetProcessHeap(), 0, sectionA );
     1279    HeapFree( GetProcessHeap(), 0, stringA );
     1280    HeapFree( GetProcessHeap(), 0, filenameA );
     1281    return res;
     1282}
     1283
     1284/***********************************************************************
     1285 *           WriteProfileSection32A   (KERNEL32.747)
     1286 */
     1287BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values)
     1288
     1289{
     1290    return WritePrivateProfileSectionA( section, keys_n_values, "win.ini");
     1291}
     1292
     1293/***********************************************************************
     1294 *           WriteProfileSection32W   (KERNEL32.748)
     1295 */
     1296BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values)
     1297{
     1298   if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini");
     1299
     1300   return (WritePrivateProfileSectionW (section,keys_n_values, wininiW));
     1301}
     1302
     1303/***********************************************************************
     1304 *           GetPrivateProfileSectionNames16   (KERNEL.143)
     1305 */
     1306WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
     1307                                             LPCSTR filename )
     1308{
     1309    WORD ret = 0;
     1310
     1311    EnterCriticalSection( &PROFILE_CritSect );
     1312
     1313    if (PROFILE_Open( filename ))
     1314      ret = PROFILE_GetSectionNames(buffer, size);
     1315
     1316    LeaveCriticalSection( &PROFILE_CritSect );
     1317
     1318    return ret;
     1319}
     1320
     1321/***********************************************************************
     1322 *           GetPrivateProfileSectionNames32A  (KERNEL32.365)
     1323 */
     1324DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,
     1325                    LPCSTR filename)
     1326
     1327{
     1328 return (GetPrivateProfileSectionNames16 (buffer,size,filename));
     1329}
     1330
     1331/***********************************************************************
     1332 *           GetPrivateProfileSectionNames32W  (KERNEL32.366)
     1333 */
     1334DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
     1335                    LPCWSTR filename)
     1336
     1337{
     1338   LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     1339   LPSTR bufferA   = (LPSTR)HeapAlloc( GetProcessHeap(), 0, size);
     1340
     1341   INT ret = GetPrivateProfileSectionNames16 (bufferA, size, filenameA);
     1342   lstrcpynAtoW( buffer, bufferA, size);
     1343   HeapFree( GetProcessHeap(), 0, bufferA);
     1344   HeapFree( GetProcessHeap(), 0, filenameA );
     1345
     1346   return ret;
     1347}
     1348
     1349/***********************************************************************
     1350 *           GetPrivateProfileStruct32A (KERNEL32.370)
     1351 */
     1352BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
     1353                  LPVOID buf, UINT len, LPCSTR filename)
     1354{
     1355    BOOL ret = FALSE;
     1356
     1357    EnterCriticalSection( &PROFILE_CritSect );
     1358
     1359    if (PROFILE_Open( filename )) {
     1360        PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
     1361   if (k) {
     1362      lstrcpynA( buf, k->value, strlen(k->value));
     1363      ret = TRUE;
     1364   }
     1365    }
     1366    LeaveCriticalSection( &PROFILE_CritSect );
     1367
     1368    return FALSE;
     1369}
     1370
     1371/***********************************************************************
     1372 *           GetPrivateProfileStruct32W (KERNEL32.543)
     1373 */
     1374BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
     1375                  LPVOID buffer, UINT len, LPCWSTR filename)
     1376{
     1377    LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     1378    LPSTR keyA      = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
     1379    LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     1380    LPSTR bufferA   = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len );
     1381
     1382    INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
     1383               len, filenameA );
     1384    lstrcpynAtoW( buffer, bufferA, len );
     1385    HeapFree( GetProcessHeap(), 0, bufferA);
     1386    HeapFree( GetProcessHeap(), 0, sectionA );
     1387    HeapFree( GetProcessHeap(), 0, keyA );
     1388    HeapFree( GetProcessHeap(), 0, filenameA );
     1389
     1390    return ret;
     1391}
     1392
     1393
     1394/***********************************************************************
     1395 *           WritePrivateProfileStruct32A (KERNEL32.744)
     1396 */
     1397BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
     1398                                        LPVOID buf, UINT bufsize, LPCSTR filename)
     1399{
     1400    BOOL ret = FALSE;
     1401
     1402    if (!section && !key && !buf)  /* flush the cache */
     1403        return WritePrivateProfileStringA( NULL, NULL, NULL, filename );
     1404
     1405    EnterCriticalSection( &PROFILE_CritSect );
     1406
     1407    if (PROFILE_Open( filename ))
     1408        ret = PROFILE_SetString( section, key, (LPCSTR)buf );
     1409
     1410    LeaveCriticalSection( &PROFILE_CritSect );
     1411
     1412    return ret;
     1413}
     1414
     1415/***********************************************************************
     1416 *           WritePrivateProfileStruct32W (KERNEL32.544)
     1417 */
     1418BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
     1419               LPVOID buf, UINT bufsize, LPCWSTR filename)
     1420{
     1421    LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     1422    LPSTR keyA      = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
     1423    LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     1424    INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
     1425                 filenameA );
     1426    HeapFree( GetProcessHeap(), 0, sectionA );
     1427    HeapFree( GetProcessHeap(), 0, keyA );
     1428    HeapFree( GetProcessHeap(), 0, filenameA );
     1429
     1430    return ret;
     1431}
Note: See TracChangeset for help on using the changeset viewer.