Thread-safe implementation of profile functions (Windows and Wine).

diff --git a/files/profile.c b/files/profile.c
index fb67b71..0bceb87 100644
--- a/files/profile.c
+++ b/files/profile.c
@@ -36,7 +36,7 @@
 
 typedef struct
 {
-    BOOL           changed;
+    BOOL             changed;
     PROFILESECTION  *section;
     char            *dos_name;
     char            *unix_name;
@@ -53,7 +53,7 @@
 #define CurProfile (MRUProfile[0])
 
 /* wine.ini profile content */
-static PROFILESECTION *WineProfile;
+static PROFILESECTION *PROFILE_WineProfile;
 
 #define PROFILE_MAX_LINE_LEN   1024
 
@@ -70,6 +70,8 @@
 
 static LPCWSTR wininiW = NULL;
 
+static CRITICAL_SECTION PROFILE_CritSect;
+
 /***********************************************************************
  *           PROFILE_CopyEntry
  *
@@ -282,7 +284,7 @@
  * Delete a key from a profile tree.
  */
 static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
-                                 LPCSTR section_name, LPCSTR key_name )
+			       LPCSTR section_name, LPCSTR key_name )
 {
     while (*section)
     {
@@ -548,8 +550,8 @@
  * 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 )
+			       LPSTR buffer, UINT len, BOOL handle_env,
+			       BOOL return_values )
 {
     PROFILEKEY *key;
     while (section)
@@ -599,7 +601,7 @@
  * Get a profile string.
  */
 static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
-                                LPCSTR def_val, LPSTR buffer, UINT len )
+			      LPCSTR def_val, LPSTR buffer, UINT len )
 {
     PROFILEKEY *key = NULL;
 
@@ -624,7 +626,7 @@
  * Set a profile string.
  */
 static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
-                                 LPCSTR value )
+			       LPCSTR value )
 {
     if (!key_name)  /* Delete a whole section */
     {
@@ -675,16 +677,26 @@
 int PROFILE_GetWineIniString( const char *section, const char *key_name,
                               const char *def, char *buffer, int len )
 {
+    int	ret;
+
+    EnterCriticalSection( &PROFILE_CritSect );
+
     if (key_name)
     {
-        PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
+        PROFILEKEY *key = PROFILE_Find(&PROFILE_WineProfile, section, key_name, FALSE);
         PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
                            len, TRUE );
         TRACE(profile, "('%s','%s','%s'): returning '%s'\n",
                          section, key_name, def, buffer );
-        return strlen( buffer );
+        ret = strlen( buffer );
+    } 
+    else 
+    {
+       ret = PROFILE_GetSection( PROFILE_WineProfile, section, buffer, len, TRUE, FALSE );
     }
-    return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE, FALSE );
+    LeaveCriticalSection( &PROFILE_CritSect );
+
+    return ret;
 }
 
 
@@ -698,13 +710,23 @@
     char buffer[20];
     char *p;
     long result;
+    PROFILEKEY *key;
+    int	ret;
 
-    PROFILEKEY *key = PROFILE_Find( &WineProfile, section, key_name, FALSE );
-    if (!key || !key->value) return def;
-    PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
-    result = strtol( buffer, &p, 0 );
-    if (p == buffer) return 0;  /* No digits at all */
-    return (int)result;
+    EnterCriticalSection( &PROFILE_CritSect );
+
+    key = PROFILE_Find( &PROFILE_WineProfile, section, key_name, FALSE );
+    if (!key || !key->value) {
+       ret = def;
+    } else {
+       PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
+       result = strtol( buffer, &p, 0 );
+       ret = (p == buffer) ? 0  /* No digits at all */ : (int)result;
+    }
+
+    LeaveCriticalSection( &PROFILE_CritSect );
+
+    return ret;
 }
 
 
@@ -741,8 +763,10 @@
     PROFILEKEY  *scankey;
     int  calls = 0;
 
+    EnterCriticalSection( &PROFILE_CritSect );
+
     /* Search for the correct section */
-    for(scansect = WineProfile; scansect; scansect = scansect->next) {
+    for(scansect = PROFILE_WineProfile; scansect; scansect = scansect->next) {
 	if(scansect->name && !strcasecmp(scansect->name, section)) {
 
 	    /* Enumerate each key with the callback */
@@ -759,6 +783,7 @@
 	    break;
 	}
     }
+    LeaveCriticalSection( &PROFILE_CritSect );
 
     return calls;
 }
@@ -831,29 +856,32 @@
     const char *p;
     FILE *f;
 
+    InitializeCriticalSection( &PROFILE_CritSect );
+    MakeCriticalSectionGlobal( &PROFILE_CritSect );
+
     if ( (Options.configFileName!=NULL) && (f = fopen(Options.configFileName, "r")) )
     {
       /* Open -config specified file */
-      WineProfile = PROFILE_Load ( f);
+      PROFILE_WineProfile = PROFILE_Load ( f);
       fclose ( f );
       strncpy(PROFILE_WineIniUsed,Options.configFileName,MAX_PATHNAME_LEN-1);
       return 1;
     }
 
     if ( (p = getenv( "WINE_INI" )) && (f = fopen( p, "r" )) )
-      {
-	WineProfile = PROFILE_Load( f );
+    {
+	PROFILE_WineProfile = PROFILE_Load( f );
 	fclose( f );
 	strncpy(PROFILE_WineIniUsed,p,MAX_PATHNAME_LEN-1);
 	return 1;
-      }
+    }
     if ((p = getenv( "HOME" )) != NULL)
     {
         lstrcpynA(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
         strcat( buffer, PROFILE_WineIniName );
         if ((f = fopen( buffer, "r" )) != NULL)
         {
-            WineProfile = PROFILE_Load( f );
+            PROFILE_WineProfile = PROFILE_Load( f );
             fclose( f );
 	    strncpy(PROFILE_WineIniUsed,buffer,MAX_PATHNAME_LEN-1);
             return 1;
@@ -865,7 +893,7 @@
 
     if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
     {
-        WineProfile = PROFILE_Load( f );
+        PROFILE_WineProfile = PROFILE_Load( f );
         fclose( f );
 	strncpy(PROFILE_WineIniUsed,WINE_INI_GLOBAL,MAX_PATHNAME_LEN-1);
         return 1;
@@ -895,7 +923,6 @@
     /* RTFM, so to say */
 }
 
-
 /***********************************************************************
  *           PROFILE_GetStringItem
  *
@@ -921,7 +948,6 @@
     return NULL;
 }
 
-
 /********************* API functions **********************************/
 
 /***********************************************************************
@@ -964,21 +990,21 @@
  *           GetProfileString32A   (KERNEL32.268)
  */
 INT WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,
-                                  LPSTR buffer, UINT len )
+			      LPSTR buffer, UINT len )
 {
     return GetPrivateProfileStringA( section, entry, def_val,
-                                       buffer, len, "win.ini" );
+				     buffer, len, "win.ini" );
 }
 
 /***********************************************************************
  *           GetProfileString32W   (KERNEL32.269)
  */
 INT WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry,
-                                  LPCWSTR def_val, LPWSTR buffer, UINT len )
+			      LPCWSTR def_val, LPWSTR buffer, UINT len )
 {
     if (!wininiW) wininiW = HEAP_strdupAtoW( SystemHeap, 0, "win.ini" );
     return GetPrivateProfileStringW( section, entry, def_val,
-                                       buffer, len, wininiW );
+				     buffer, len, wininiW );
 }
 
 /***********************************************************************
@@ -999,10 +1025,6 @@
     return GetPrivateProfileSectionW( section, buffer, len, wininiW );
 }
 
-
-
-
-
 /***********************************************************************
  *           WriteProfileString16   (KERNEL.59)
  */
@@ -1016,7 +1038,7 @@
  *           WriteProfileString32A   (KERNEL32.587)
  */
 BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry,
-                                     LPCSTR string )
+				 LPCSTR string )
 {
     return WritePrivateProfileStringA( section, entry, string, "win.ini" );
 }
@@ -1050,7 +1072,7 @@
  *           GetPrivateProfileInt32A   (KERNEL32.251)
  */
 UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
-                                       INT def_val, LPCSTR filename )
+				   INT def_val, LPCSTR filename )
 {
     char buffer[20];
     char *p;
@@ -1068,7 +1090,7 @@
  *           GetPrivateProfileInt32W   (KERNEL32.252)
  */
 UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,
-                                       INT def_val, LPCWSTR filename )
+				   INT def_val, LPCWSTR filename )
 {
     LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     LPSTR entryA    = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
@@ -1094,23 +1116,34 @@
  *           GetPrivateProfileString32A   (KERNEL32.255)
  */
 INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
-                                         LPCSTR def_val, LPSTR buffer,
-                                         UINT len, LPCSTR filename )
+				     LPCSTR def_val, LPSTR buffer,
+				     UINT len, LPCSTR filename )
 {
+    int		ret;
+
     if (!filename) 
 	filename = "win.ini";
-    if (PROFILE_Open( filename ))
-        return PROFILE_GetString( section, entry, def_val, buffer, len );
-    lstrcpynA( buffer, def_val, len );
-    return strlen( buffer );
+
+    EnterCriticalSection( &PROFILE_CritSect );
+
+    if (PROFILE_Open( filename )) {
+        ret = PROFILE_GetString( section, entry, def_val, buffer, len );
+    } else {
+       lstrcpynA( buffer, def_val, len );
+       ret = strlen( buffer );
+    }
+
+    LeaveCriticalSection( &PROFILE_CritSect );
+    
+    return ret;
 }
 
 /***********************************************************************
  *           GetPrivateProfileString32W   (KERNEL32.256)
  */
 INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
-                                         LPCWSTR def_val, LPWSTR buffer,
-                                         UINT len, LPCWSTR filename )
+				     LPCWSTR def_val, LPWSTR buffer,
+				     UINT len, LPCWSTR filename )
 {
     LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     LPSTR entryA    = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
@@ -1132,11 +1165,17 @@
  *           GetPrivateProfileSection32A   (KERNEL32.255)
  */
 INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,
-                                          DWORD len, LPCSTR filename )
+				      DWORD len, LPCSTR filename )
 {
+    int		ret = 0;
+
+    EnterCriticalSection( &PROFILE_CritSect );
+
     if (PROFILE_Open( filename ))
-        return PROFILE_GetSection(CurProfile->section, section, buffer, len,
-                                FALSE, TRUE);
+        ret = PROFILE_GetSection(CurProfile->section, section, buffer, len,
+				 FALSE, TRUE);
+    
+    LeaveCriticalSection( &PROFILE_CritSect );
 
     return 0;
 }
@@ -1146,7 +1185,7 @@
  */
 
 INT WINAPI GetPrivateProfileSectionW (LPCWSTR section, LPWSTR buffer,
-                                          DWORD len, LPCWSTR filename )
+				      DWORD len, LPCWSTR filename )
 
 {
     LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
@@ -1173,25 +1212,37 @@
  *           WritePrivateProfileString32A   (KERNEL32.582)
  */
 BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
-                                            LPCSTR string, LPCSTR filename )
+					LPCSTR string, LPCSTR filename )
 {
-    if (!PROFILE_Open( filename )) return FALSE;
-    if (!section) return PROFILE_FlushFile();
-    return PROFILE_SetString( section, entry, string );
+    BOOL	ret;
+
+    EnterCriticalSection( &PROFILE_CritSect );
+
+    if (!PROFILE_Open( filename )) {
+       ret = FALSE;
+    } else if (!section) {
+       ret = PROFILE_FlushFile();
+    } else {
+       ret = PROFILE_SetString( section, entry, string );
+    }
+
+    LeaveCriticalSection( &PROFILE_CritSect );
+
+    return ret;
 }
 
 /***********************************************************************
  *           WritePrivateProfileString32W   (KERNEL32.583)
  */
 BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
-                                            LPCWSTR string, LPCWSTR filename )
+					LPCWSTR string, LPCWSTR filename )
 {
     LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     LPSTR entryA    = HEAP_strdupWtoA( GetProcessHeap(), 0, entry );
     LPSTR stringA   = HEAP_strdupWtoA( GetProcessHeap(), 0, string );
     LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     BOOL res = WritePrivateProfileStringA( sectionA, entryA,
-                                               stringA, filenameA );
+					   stringA, filenameA );
     HeapFree( GetProcessHeap(), 0, sectionA );
     HeapFree( GetProcessHeap(), 0, entryA );
     HeapFree( GetProcessHeap(), 0, stringA );
@@ -1203,7 +1254,7 @@
  *           WritePrivateProfileSection32A   (KERNEL32)
  */
 BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section, 
-                                            LPCSTR string, LPCSTR filename )
+					 LPCSTR string, LPCSTR filename )
 {
     char *p =(char*)string;
 
@@ -1224,7 +1275,7 @@
  *           WritePrivateProfileSection32W   (KERNEL32)
  */
 BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
-                                            LPCWSTR string, LPCWSTR filename)
+					 LPCWSTR string, LPCWSTR filename)
 
 {
     LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
@@ -1263,30 +1314,38 @@
 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
                                              LPCSTR filename )
 {
- char *buf;
- int l,cursize;
- PROFILESECTION *section;
+    char *buf;
+    int l,cursize;
+    PROFILESECTION *section;
+    BOOL	ret = FALSE;
+
+    EnterCriticalSection( &PROFILE_CritSect );
 
     if (PROFILE_Open( filename )) {
-	buf=buffer;
-	cursize=0;
-	section=CurProfile->section;
+        buf = buffer;
+	cursize = 0;
+	section = CurProfile->section;
 	for ( ; section; section = section->next) 
-            if (section->name) {
-		l=strlen (section->name);
-		cursize+=l+1;
-        	if (cursize > size+1)
-			return size-2;
-		strcpy (buf,section->name);
-		buf+=l;
-		*buf=0;
-		buf++;
+	    if (section->name) {
+	        l = strlen (section->name);
+		cursize += l+1;
+        	if (cursize > size+1) {
+		    LeaveCriticalSection( &PROFILE_CritSect );
+		    return size-2;
 		}
- 	buf++;
- 	*buf=0;
- 	return (buf-buffer);
- }
- return FALSE;
+		strcpy (buf,section->name);
+		buf += l;
+		*buf = 0;
+		buf++;
+	    }
+	buf++;
+	*buf=0;
+	ret = buf-buffer;
+    }
+
+    LeaveCriticalSection( &PROFILE_CritSect );
+
+    return ret;
 }
 
 
@@ -1296,7 +1355,7 @@
 WORD WINAPI GetProfileSectionNames16( LPSTR buffer, WORD size)
 
 {
- return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
+    return (GetPrivateProfileSectionNames16 (buffer,size,"win.ini"));
 }
 
 
@@ -1304,7 +1363,7 @@
  *           GetPrivateProfileSectionNames32A  (KERNEL32.365)
  */
 DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,
-					 LPCSTR filename)
+					     LPCSTR filename)
 
 {
  return (GetPrivateProfileSectionNames16 (buffer,size,filename));
@@ -1315,7 +1374,7 @@
  *           GetPrivateProfileSectionNames32W  (KERNEL32.366)
  */
 DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
-                                         LPCWSTR filename)
+					     LPCWSTR filename)
 
 {
    LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
@@ -1334,24 +1393,29 @@
  *           GetPrivateProfileStruct32A (KERNEL32.370)
  */
 BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key, 
-	LPVOID buf, UINT len, LPCSTR filename)
+				      LPVOID buf, UINT len, LPCSTR filename)
 {
-    PROFILEKEY *k;
+    BOOL	ret = FALSE;
+
+    EnterCriticalSection( &PROFILE_CritSect );
 
     if (PROFILE_Open( filename )) {
-        k=PROFILE_Find ( &CurProfile->section, section, key, FALSE);
-	if (!k) return FALSE;
-    	lstrcpynA( buf, k->value, strlen(k->value));
-        return TRUE;
+        PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE);
+	if (k) {
+	   lstrcpynA( buf, k->value, strlen(k->value));
+	   ret = TRUE;
+	}
     }
-  return FALSE;
+    LeaveCriticalSection( &PROFILE_CritSect );
+
+    return FALSE;
 }
 
 /***********************************************************************
  *           GetPrivateProfileStruct32W (KERNEL32.543)
  */
 BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
-        LPVOID buffer, UINT len, LPCWSTR filename)
+				      LPVOID buffer, UINT len, LPCWSTR filename)
 {
     LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     LPSTR keyA      = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
@@ -1359,7 +1423,7 @@
     LPSTR bufferA   = HeapAlloc( GetProcessHeap(), 0, len );
 
     INT ret = GetPrivateProfileStructA( sectionA, keyA, bufferA,
-                                            len, filenameA );
+					len, filenameA );
     lstrcpynAtoW( buffer, bufferA, len );
     HeapFree( GetProcessHeap(), 0, bufferA);
     HeapFree( GetProcessHeap(), 0, sectionA );
@@ -1378,26 +1442,36 @@
 BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key, 
 	LPVOID buf, UINT bufsize, LPCSTR filename)
 {
+    BOOL ret;
+
+    EnterCriticalSection( &PROFILE_CritSect );
+
     if ((!section) && (!key) && (!buf)) {	/* flush the cache */
         PROFILE_FlushFile();
-	return FALSE;
- 	}
+	ret = FALSE;
+    } else {
+       if (!PROFILE_Open( filename )) 
+	  ret = FALSE;
+       else 
+	  ret = PROFILE_SetString( section, key, buf);
+    }
 
-    if (!PROFILE_Open( filename )) return FALSE;
-    return PROFILE_SetString( section, key, buf);
+    LeaveCriticalSection( &PROFILE_CritSect );
+
+    return ret;
 }
 
 /***********************************************************************
  *           WritePrivateProfileStruct32W (KERNEL32.544)
  */
 BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
-        LPVOID buf, UINT bufsize, LPCWSTR filename)
+					LPVOID buf, UINT bufsize, LPCWSTR filename)
 {
     LPSTR sectionA  = HEAP_strdupWtoA( GetProcessHeap(), 0, section );
     LPSTR keyA      = HEAP_strdupWtoA( GetProcessHeap(), 0, key);
     LPSTR filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
     INT ret = WritePrivateProfileStructA( sectionA, keyA, buf, bufsize,
-                                             filenameA );
+					  filenameA );
     HeapFree( GetProcessHeap(), 0, sectionA );
     HeapFree( GetProcessHeap(), 0, keyA );
     HeapFree( GetProcessHeap(), 0, filenameA );
@@ -1411,5 +1485,7 @@
  */
 void WINAPI WriteOutProfiles16(void)
 {
+    EnterCriticalSection( &PROFILE_CritSect );
     PROFILE_FlushFile();
+    LeaveCriticalSection( &PROFILE_CritSect );
 }