Commit in reactos/lib/kernel32 on MAIN
makefile+2-21.89 -> 1.90
misc/dllmain.c+1-81.37 -> 1.38
    /profile.c+1444-14611.14 -> 1.15
+1447-1471
3 modified files
"import" profiles.c from wine. all Wine's profile reg. tests now pass

reactos/lib/kernel32
makefile 1.89 -> 1.90
diff -u -r1.89 -r1.90
--- makefile	20 Oct 2004 20:51:21 -0000	1.89
+++ makefile	29 Nov 2004 00:08:59 -0000	1.90
@@ -1,4 +1,4 @@
-# $Id: makefile,v 1.89 2004/10/20 20:51:21 chorns Exp $
+# $Id: makefile,v 1.90 2004/11/29 00:08:59 gdalsnes Exp $
 
 PATH_TO_TOP = ../..
 
@@ -17,7 +17,7 @@
 
 TARGET_RCFLAGS += -DWINVER=0x0500
 
-TARGET_SDKLIBS = pseh.a rosrtl.a ntdll.a kernel32.a
+TARGET_SDKLIBS = pseh.a rosrtl.a ntdll.a kernel32.a libwine.a
 
 TARGET_GCCLIBS = gcc
 

reactos/lib/kernel32/misc
dllmain.c 1.37 -> 1.38
diff -u -r1.37 -r1.38
--- dllmain.c	24 Oct 2004 12:39:53 -0000	1.37
+++ dllmain.c	29 Nov 2004 00:08:59 -0000	1.38
@@ -1,4 +1,4 @@
-/* $Id: dllmain.c,v 1.37 2004/10/24 12:39:53 chorns Exp $
+/* $Id: dllmain.c,v 1.38 2004/11/29 00:08:59 gdalsnes Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -37,7 +37,6 @@
 CRITICAL_SECTION ConsoleLock;
 
 extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
-extern BOOL FASTCALL PROFILE_Init();
 
 extern BOOL FASTCALL NlsInit();
 extern VOID FASTCALL NlsUninit();
@@ -138,12 +137,6 @@
 	/* Initialize the DLL critical section */
 	RtlInitializeCriticalSection(&DllLock);
 
-	/* Initialize the profile (.ini) routines */
-	if (! PROFILE_Init())
-          {
-            return FALSE;
-          }
-
 	/* Initialize the National Language Support routines */
         if (! NlsInit())
           {

reactos/lib/kernel32/misc
profile.c 1.14 -> 1.15
diff -u -r1.14 -r1.15
--- profile.c	13 Oct 2004 19:52:09 -0000	1.14
+++ profile.c	29 Nov 2004 00:08:59 -0000	1.15
@@ -1,46 +1,76 @@
-/* $Id: profile.c,v 1.14 2004/10/13 19:52:09 gvg Exp $
+/*
+ * Profile functions
  *
- * Imported from Wine
  * Copyright 1993 Miguel de Icaza
  * Copyright 1996 Alexandre Julliard
  *
- * PROJECT:         ReactOS system libraries
- * FILE:            lib/kernel32/misc/profile.c
- * PURPOSE:         Profiles functions
- * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
- *                  modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
- * UPDATE HISTORY:
- *                  Created 01/11/98
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <k32.h>
 
-#define NDEBUG
-#include <debug.h>
+/*
+ * Whole file ripped from Wine's dlls\kernel\profile.c, rev 1.13 and is 
+ * unchanged (to make merging easier) except that includes are different 
+ * and some prototypes were changed to comply with w32api.
+ *
+ * -Gunnar
+ */
+ 
+#define WINVER 0x0500
+
+#include <k32.h>
 
-static CRITICAL_SECTION ProfileLock;
+#include "wine/config.h"
+//#include "wine/port.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(profile);
+
+static const char bom_utf8[] = {0xEF,0xBB,0xBF};
+
+typedef enum
+{
+    ENCODING_ANSI = 1,
+    ENCODING_UTF8,
+    ENCODING_UTF16LE,
+    ENCODING_UTF16BE
+} ENCODING;
 
 typedef struct tagPROFILEKEY
 {
-  WCHAR                 *Value;
-  struct tagPROFILEKEY  *Next;
-  WCHAR                  Name[1];
+    WCHAR                 *value;
+    struct tagPROFILEKEY  *next;
+    WCHAR                  name[1];
 } PROFILEKEY;
 
 typedef struct tagPROFILESECTION
 {
-  struct tagPROFILEKEY       *Key;
-  struct tagPROFILESECTION   *Next;
-  WCHAR                       Name[1];
+    struct tagPROFILEKEY       *key;
+    struct tagPROFILESECTION   *next;
+    WCHAR                       name[1];
 } PROFILESECTION;
 
 
 typedef struct
 {
-  BOOL             Changed;
-  PROFILESECTION  *Section;
-  WCHAR           *FullName;
-  FILETIME         LastWriteTime;
+    BOOL             changed;
+    PROFILESECTION  *section;
+    WCHAR           *filename;
+    FILETIME LastWriteTime;
+    ENCODING encoding;
 } PROFILE;
 
 
@@ -51,12 +81,22 @@
 
 #define CurProfile (MRUProfile[0])
 
-#define PROFILE_MAX_LINE_LEN   1024
-
 /* Check for comments in profile */
 #define IS_ENTRY_COMMENT(str)  ((str)[0] == ';')
 
-/* FUNCTIONS *****************************************************************/
+static const WCHAR emptystringW[] = {0};
+static const WCHAR wininiW[] = { 'w','i','n','.','i','n','i',0 };
+
+static CRITICAL_SECTION PROFILE_CritSect;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &PROFILE_CritSect,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { 0, (DWORD)(__FILE__ ": PROFILE_CritSect") }
+};
+static CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+static const char hex[16] = "0123456789ABCDEF";
 
 /***********************************************************************
  *           PROFILE_CopyEntry
@@ -64,65 +104,146 @@
  * Copy the content of an entry into a buffer, removing quotes, and possibly
  * translating environment variables.
  */
-STATIC void FASTCALL
-PROFILE_CopyEntry(LPWSTR Buffer, LPCWSTR Value, int Len, BOOL StripQuote)
+static void PROFILE_CopyEntry( LPWSTR buffer, LPCWSTR value, int len,
+                               BOOL strip_quote )
 {
-  WCHAR Quote = L'\0';
-
-  if (NULL == Buffer)
-    {
-      return;
-    }
+    WCHAR quote = '\0';
 
-  if (StripQuote && (L'\'' == *Value || L'\"' == *Value))
-    {
-      if (L'\0' != Value[1] && (Value[wcslen(Value) - 1] == *Value))
-        {
-          Quote = *Value++;
-        }
-    }
+    if(!buffer) return;
 
-  lstrcpynW(Buffer, Value, Len);
-  if (L'\0' != Quote && wcslen(Value) <= Len)
+    if (strip_quote && ((*value == '\'') || (*value == '\"')))
     {
-      Buffer[wcslen(Buffer) - 1] = L'\0';
+        if (value[1] && (value[strlenW(value)-1] == *value)) quote = *value++;
+    }
+
+    lstrcpynW( buffer, value, len );
+    if (quote && (len >= strlenW(value))) buffer[strlenW(buffer)-1] = '\0';
+}
+
+/* byte-swaps shorts in-place in a buffer. len is in WCHARs */
+static inline void PROFILE_ByteSwapShortBuffer(WCHAR * buffer, int len)
+{
+    int i;
+    USHORT * shortbuffer = (USHORT *)buffer;
+    for (i = 0; i < len; i++)
+        shortbuffer[i] = RtlUshortByteSwap(shortbuffer[i]);
+}
+
+/* writes any necessary encoding marker to the file */
+static inline void PROFILE_WriteMarker(HANDLE hFile, ENCODING encoding)
+{
+    DWORD dwBytesWritten;
+    DWORD bom;
+    switch (encoding)
+    {
+    case ENCODING_ANSI:
+        break;
+    case ENCODING_UTF8:
+        WriteFile(hFile, bom_utf8, sizeof(bom_utf8), &dwBytesWritten, NULL);
+        break;
+    case ENCODING_UTF16LE:
+        bom = 0xFEFF;
+        WriteFile(hFile, &bom, sizeof(bom), &dwBytesWritten, NULL);
+        break;
+    case ENCODING_UTF16BE:
+        bom = 0xFFFE;
+        WriteFile(hFile, &bom, sizeof(bom), &dwBytesWritten, NULL);
+        break;
+    }
+}
+
+static void PROFILE_WriteLine( HANDLE hFile, WCHAR * szLine, int len, ENCODING encoding)
+{
+    char * write_buffer;
+    int write_buffer_len;
+    DWORD dwBytesWritten;
+
+    TRACE("writing: %s\n", debugstr_wn(szLine, len));
+
+    switch (encoding)
+    {
+    case ENCODING_ANSI:
+        write_buffer_len = WideCharToMultiByte(CP_ACP, 0, szLine, len, NULL, 0, NULL, NULL);
+        write_buffer = HeapAlloc(GetProcessHeap(), 0, write_buffer_len);
+        if (!write_buffer) return;
+        len = WideCharToMultiByte(CP_ACP, 0, szLine, len, write_buffer, write_buffer_len, NULL, NULL);
+        WriteFile(hFile, write_buffer, len, &dwBytesWritten, NULL);
+        HeapFree(GetProcessHeap(), 0, write_buffer);
+        break;
+    case ENCODING_UTF8:
+        write_buffer_len = WideCharToMultiByte(CP_UTF8, 0, szLine, len, NULL, 0, NULL, NULL);
+        write_buffer = HeapAlloc(GetProcessHeap(), 0, write_buffer_len);
+        if (!write_buffer) return;
+        len = WideCharToMultiByte(CP_UTF8, 0, szLine, len, write_buffer, write_buffer_len, NULL, NULL);
+        WriteFile(hFile, write_buffer, len, &dwBytesWritten, NULL);
+        HeapFree(GetProcessHeap(), 0, write_buffer);
+        break;
+    case ENCODING_UTF16LE:
+        WriteFile(hFile, szLine, len * sizeof(WCHAR), &dwBytesWritten, NULL);
+        break;
+    case ENCODING_UTF16BE:
+        PROFILE_ByteSwapShortBuffer(szLine, len);
+        WriteFile(hFile, szLine, len * sizeof(WCHAR), &dwBytesWritten, NULL);
+        break;
+    default:
+        FIXME("encoding type %d not implemented\n", encoding);
     }
 }
 
-
 /***********************************************************************
  *           PROFILE_Save
  *
  * Save a profile tree to a file.
  */
-STATIC void FASTCALL
-PROFILE_Save(HANDLE File, PROFILESECTION *Section)
+static void PROFILE_Save( HANDLE hFile, const PROFILESECTION *section, ENCODING encoding )
 {
-  PROFILEKEY *Key;
-  char Buffer[PROFILE_MAX_LINE_LEN];
-  DWORD BytesWritten;
+    PROFILEKEY *key;
+    WCHAR *buffer, *p;
+
+    PROFILE_WriteMarker(hFile, encoding);
 
-  for ( ; NULL != Section; Section = Section->Next)
+    for ( ; section; section = section->next)
     {
-      if (L'\0' != Section->Name[0])
+        int len = 0;
+
+        if (section->name[0]) len += strlenW(section->name) + 6;
+
+        for (key = section->key; key; key = key->next)
         {
-          strcpy(Buffer, "\r\n[");
-          WideCharToMultiByte(CP_ACP, 0, Section->Name, -1, Buffer + 3, sizeof(Buffer) - 6, NULL, NULL);
-          strcat(Buffer, "]\r\n");
-          WriteFile(File, Buffer, strlen(Buffer), &BytesWritten, NULL);
+            len += strlenW(key->name) + 2;
+            if (key->value) len += strlenW(key->value) + 1;
         }
-      for (Key = Section->Key; NULL != Key; Key = Key->Next)
+
+        buffer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+        if (!buffer) return;
+
+        p = buffer;
+        if (section->name[0])
+        {
+            *p++ = '\r';
+            *p++ = '\n';
+            *p++ = '[';
+            strcpyW( p, section->name );
+            p += strlenW(p);
+            *p++ = ']';
+            *p++ = '\r';
+            *p++ = '\n';
+        }
+        for (key = section->key; key; key = key->next)
         {
-          WideCharToMultiByte(CP_ACP, 0, Key->Name, -1, Buffer, sizeof(Buffer) - 3, NULL, NULL);
-          if (Key->Value)
+            strcpyW( p, key->name );
+            p += strlenW(p);
+            if (key->value)
             {
-              strcat(Buffer, "=");
-              WideCharToMultiByte(CP_ACP, 0, Key->Value, -1, Buffer + strlen(Buffer),
-                                  sizeof(Buffer) - strlen(Buffer) - 2, NULL, NULL);
+                *p++ = '=';
+                strcpyW( p, key->value );
+                p += strlenW(p);
             }
-          strcat(Buffer, "\r\n");
-          WriteFile(File, Buffer, strlen(Buffer), &BytesWritten, NULL);
+            *p++ = '\r';
+            *p++ = '\n';
         }
+        PROFILE_WriteLine( hFile, buffer, len, encoding );
+        HeapFree(GetProcessHeap(), 0, buffer);
     }
 }
 
@@ -132,233 +253,340 @@
  *
  * Free a profile tree.
  */
-STATIC void FASTCALL
-PROFILE_Free(PROFILESECTION *Section)
+static void PROFILE_Free( PROFILESECTION *section )
 {
-  PROFILESECTION *NextSection;
-  PROFILEKEY *Key, *NextKey;
+    PROFILESECTION *next_section;
+    PROFILEKEY *key, *next_key;
 
-  for ( ; NULL != Section; Section = NextSection)
+    for ( ; section; section = next_section)
     {
-      for (Key = Section->Key; NULL != Key; Key = NextKey)
+        for (key = section->key; key; key = next_key)
         {
-          NextKey = Key->Next;
-          if (NULL != Key->Value)
-            {
-              HeapFree(GetProcessHeap(), 0, Key->Value);
-            }
-          HeapFree(GetProcessHeap(), 0, Key);
+            next_key = key->next;
+            if (key->value) HeapFree( GetProcessHeap(), 0, key->value );
+            HeapFree( GetProcessHeap(), 0, key );
         }
-      NextSection = Section->Next;
-      HeapFree(GetProcessHeap(), 0, Section);
+        next_section = section->next;
+        HeapFree( GetProcessHeap(), 0, section );
     }
 }
 
-STATIC inline int
-PROFILE_isspace(char c)
+/* returns 1 if a character white space else 0 */
+static inline int PROFILE_isspaceW(WCHAR c)
+{
+   if (isspaceW(c)) return 1;
+   if (c=='\r' || c==0x1a) return 1;
+   /* CR and ^Z (DOS EOF) are spaces too  (found on CD-ROMs) */
+   return 0;
+}
+
+static inline ENCODING PROFILE_DetectTextEncoding(const void * buffer, int * len)
 {
-  if (isspace(c))
+    DWORD flags = IS_TEXT_UNICODE_SIGNATURE |
+                  IS_TEXT_UNICODE_REVERSE_SIGNATURE |
+                  IS_TEXT_UNICODE_ODD_LENGTH;
+    if (*len >= sizeof(bom_utf8) && !memcmp(buffer, bom_utf8, sizeof(bom_utf8)))
+    {
+        *len = sizeof(bom_utf8);
+        return ENCODING_UTF8;
+    }
+    RtlIsTextUnicode((void *)buffer, *len, &flags);
+    if (flags & IS_TEXT_UNICODE_SIGNATURE)
     {
-      return 1;
+        *len = sizeof(WCHAR);
+        return ENCODING_UTF16LE;
     }
-  if ('\r' == c || 0x1a == c)
+    if (flags & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
     {
-      /* CR and ^Z (DOS EOF) are spaces too  (found on CD-ROMs) */
-      return 1;
+        *len = sizeof(WCHAR);
+        return ENCODING_UTF16BE;
     }
-  return 0;
+    *len = 0;
+    return ENCODING_ANSI;
 }
 
+static const WCHAR * PROFILE_GetLine(const WCHAR * szStart, const WCHAR * szEnd)
+{
+    return memchrW(szStart, '\n', szEnd - szStart);
+}
 
 /***********************************************************************
  *           PROFILE_Load
  *
  * Load a profile tree from a file.
  */
-static PROFILESECTION * FASTCALL
-PROFILE_Load(HANDLE File)
+static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
 {
-  char *p, *p2;
-  int Len;
-  PROFILESECTION *Section, *FirstSection;
-  PROFILESECTION **NextSection;
-  PROFILEKEY *Key, *PrevKey, **NextKey;
-  LARGE_INTEGER FileSize;
-  HANDLE Mapping;
-  PVOID BaseAddress;
-  char *Input, *End, *EndLine, *LastNonSpace;
+    void *pBuffer;
+    WCHAR * szFile;
+    const WCHAR *szLineStart, *szLineEnd;
+    const WCHAR *szValueStart, *szNameEnd, *szEnd;
+    int line = 0, len;
+    PROFILESECTION *section, *first_section;
+    PROFILESECTION **next_section;
+    PROFILEKEY *key, *prev_key, **next_key;
+    DWORD dwFileSize;
+    
+    TRACE("%p\n", hFile);
+    
+    dwFileSize = GetFileSize(hFile, NULL);
+    if (dwFileSize == INVALID_FILE_SIZE)
+        return NULL;
+
+    pBuffer = HeapAlloc(GetProcessHeap(), 0 , dwFileSize);
+    if (!pBuffer) return NULL;
+    
+    if (!ReadFile(hFile, pBuffer, dwFileSize, &dwFileSize, NULL))
+    {
+        HeapFree(GetProcessHeap(), 0, pBuffer);
+        WARN("Error %ld reading file\n", GetLastError());
+        return NULL;
+    }
+    len = dwFileSize;
+    *pEncoding = PROFILE_DetectTextEncoding(pBuffer, &len);
+    /* len is set to the number of bytes in the character marker.
+     * we want to skip these bytes */
+    pBuffer = (char *)pBuffer + len;
+    dwFileSize -= len;
+    switch (*pEncoding)
+    {
+    case ENCODING_ANSI:
+        TRACE("ANSI encoding\n");
+
+        len = MultiByteToWideChar(CP_ACP, 0, (char *)pBuffer, dwFileSize, NULL, 0);
+        szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+        if (!szFile)
+        {
+            HeapFree(GetProcessHeap(), 0, pBuffer);
+            return NULL;
+        }
+        MultiByteToWideChar(CP_ACP, 0, (char *)pBuffer, dwFileSize, szFile, len);
+        szEnd = szFile + len;
+        break;
+    case ENCODING_UTF8:
+        TRACE("UTF8 encoding\n");
+        
+        len = MultiByteToWideChar(CP_UTF8, 0, (char *)pBuffer, dwFileSize, NULL, 0);
+        szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+        if (!szFile)
+        {
+            HeapFree(GetProcessHeap(), 0, pBuffer);
+            return NULL;
+        }
+        MultiByteToWideChar(CP_UTF8, 0, (char *)pBuffer, dwFileSize, szFile, len);
+        szEnd = szFile + len;
+        break;
+    case ENCODING_UTF16LE:
+        TRACE("UTF16 Little Endian encoding\n");
+        szFile = (WCHAR *)pBuffer + 1;
+        szEnd = (WCHAR *)((char *)pBuffer + dwFileSize);
+        break;
+    case ENCODING_UTF16BE:
+        TRACE("UTF16 Big Endian encoding\n");
+        szFile = (WCHAR *)pBuffer + 1;
+        szEnd = (WCHAR *)((char *)pBuffer + dwFileSize);
+        PROFILE_ByteSwapShortBuffer(szFile, dwFileSize / sizeof(WCHAR));
+        break;
+    default:
+        FIXME("encoding type %d not implemented\n", *pEncoding);
+        HeapFree(GetProcessHeap(), 0, pBuffer);
+        return NULL;
+    }
+
+    first_section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) );
+    if(first_section == NULL)
+    {
+        if (szFile != pBuffer)
+            HeapFree(GetProcessHeap(), 0, szFile);
+        HeapFree(GetProcessHeap(), 0, pBuffer);
+        return NULL;
+    }
+    first_section->name[0] = 0;
+    first_section->key  = NULL;
+    first_section->next = NULL;
+    next_section = &first_section->next;
+    next_key     = &first_section->key;
+    prev_key     = NULL;
+    szLineEnd = szFile - 1; /* will be increased to correct value in loop */
+
+    while (TRUE)
+    {
+        szLineStart = szLineEnd + 1;
+        if (szLineStart >= szEnd)
+            break;
+        szLineEnd = PROFILE_GetLine(szLineStart, szEnd);
+        if (!szLineEnd)
+            szLineEnd = szEnd;
+        line++;
+        
+        while (szLineStart < szLineEnd && PROFILE_isspaceW(*szLineStart)) szLineStart++;
+        
+        if (szLineStart >= szLineEnd) continue;
+
+        if (*szLineStart == '[')  /* section start */
+        {
+            const WCHAR * szSectionEnd;
+            if (!(szSectionEnd = memrchrW( szLineStart, ']', szLineEnd - szLineStart )))
+            {
+                WARN("Invalid section header at line %d: %s\n",
+                    line, debugstr_wn(szLineStart, (int)(szLineEnd - szLineStart)) );
+            }
+            else
+            {
+                szLineStart++;
+                len = (int)(szSectionEnd - szLineStart);
+                /* no need to allocate +1 for NULL terminating character as
+                 * already included in structure */
+                if (!(section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) + len * sizeof(WCHAR) )))
+                    break;
+                memcpy(section->name, szLineStart, len * sizeof(WCHAR));
+                section->name[len] = '\0';
+                section->key  = NULL;
+                section->next = NULL;
+                *next_section = section;
+                next_section  = &section->next;
+                next_key      = &section->key;
+                prev_key      = NULL;
+
+                TRACE("New section: %s\n", debugstr_w(section->name));
+
+                continue;
+            }
+        }
+
+        /* get rid of white space at the end of the line */
+        while ((szLineEnd > szLineStart) && ((*szLineEnd == '\n') || PROFILE_isspaceW(*szLineEnd))) szLineEnd--;
+
+        /* line end should be pointing to character *after* the last wanted character */
+        szLineEnd++;
+
+        /* get rid of white space after the name and before the start
+         * of the value */
+        if ((szNameEnd = szValueStart = memchrW( szLineStart, '=', szLineEnd - szLineStart )) != NULL)
+        {
+            szNameEnd = szValueStart - 1;
+            while ((szNameEnd > szLineStart) && PROFILE_isspaceW(*szNameEnd)) szNameEnd--;
+            szValueStart++;
+            while (szValueStart < szLineEnd && PROFILE_isspaceW(*szValueStart)) szValueStart++;
+        }
+        if (!szNameEnd)
+            szNameEnd = szLineEnd - 1;
+        /* name end should be pointing to character *after* the last wanted character */
+        szNameEnd++;
+
+        len = (int)(szNameEnd - szLineStart);
+        
+        if (len || !prev_key || *prev_key->name)
+        {
+            /* no need to allocate +1 for NULL terminating character as
+             * already included in structure */
+            if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) + len * sizeof(WCHAR) ))) break;
+            memcpy(key->name, szLineStart, len * sizeof(WCHAR));
+            key->name[len] = '\0';
+            if (szValueStart)
+            {
+                len = (int)(szLineEnd - szValueStart);
+                key->value = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
+                memcpy(key->value, szValueStart, len * sizeof(WCHAR));
+                key->value[len] = '\0';
+            }
+            else key->value = NULL;
+
+           key->next  = NULL;
+           *next_key  = key;
+           next_key   = &key->next;
+           prev_key   = key;
+
+           TRACE("New key: name=%s, value=%s\n",
+               debugstr_w(key->name), key->value ? debugstr_w(key->value) : "(none)");
+        }
+    }
+    if (szFile != pBuffer)
+        HeapFree(GetProcessHeap(), 0, szFile);
+    HeapFree(GetProcessHeap(), 0, pBuffer);
+    return first_section;
+}
 
-  FileSize.u.LowPart = GetFileSize(File, &FileSize.u.HighPart);
-  if (INVALID_FILE_SIZE == FileSize.u.LowPart && 0 != GetLastError())
-    {
-      return NULL;
-    }
 
-  FirstSection = HeapAlloc(GetProcessHeap(), 0, sizeof(*Section));
-  if (NULL == FirstSection)
+/***********************************************************************
+ *           PROFILE_DeleteSection
+ *
+ * Delete a section from a profile tree.
+ */
+static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCWSTR name )
+{
+    while (*section)
     {
-      return NULL;
+        if ((*section)->name[0] && !strcmpiW( (*section)->name, name ))
+        {
+            PROFILESECTION *to_del = *section;
+            *section = to_del->next;
+            to_del->next = NULL;
+            PROFILE_Free( to_del );
+            return TRUE;
+        }
+        section = &(*section)->next;
     }
-  FirstSection->Name[0] = L'\0';
-  FirstSection->Key  = NULL;
-  FirstSection->Next = NULL;
-  NextSection = &FirstSection->Next;
-  NextKey     = &FirstSection->Key;
-  PrevKey     = NULL;
+    return FALSE;
+}
 
-  if (0 == FileSize.QuadPart)
-    {
-      return FirstSection;
-    }
-  Mapping = CreateFileMappingW(File, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
-  if (NULL == Mapping)
-    {
-      HeapFree(GetProcessHeap(), 0, FirstSection);
-      return NULL;
-    }
-  BaseAddress = MapViewOfFile(Mapping, FILE_MAP_READ, 0, 0, 0);
-  if (NULL == BaseAddress)
-    {
-      CloseHandle(Mapping);
-      HeapFree(GetProcessHeap(), 0, FirstSection);
-      return NULL;
-    }
 
-  Input = (char *) BaseAddress;
-  End = Input + FileSize.QuadPart;
-  while (Input < End)
+/***********************************************************************
+ *           PROFILE_DeleteKey
+ *
+ * Delete a key from a profile tree.
+ */
+static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
+                LPCWSTR section_name, LPCWSTR key_name )
+{
+    while (*section)
     {
-      EndLine = Input;
-      LastNonSpace = NULL;
-      while (EndLine < End && '\n' != *EndLine && ';' != *EndLine)
-        {
-          if (! PROFILE_isspace(*EndLine))
-            {
-              LastNonSpace = EndLine;
-            }
-          EndLine++;
-        }
-      if (NULL != LastNonSpace)
-        {
-          EndLine = LastNonSpace + 1;
-        }
-      while (Input < EndLine && PROFILE_isspace(*Input))
-        {
-          Input++;
-        }
-      if (End <= Input)
-        {
-          break;
-        }
-      if ('[' == *Input)  /* section start */
+        if ((*section)->name[0] && !strcmpiW( (*section)->name, section_name ))
         {
-          p = ++Input;
-          while (p < EndLine && ']' != *p)
+            PROFILEKEY **key = &(*section)->key;
+            while (*key)
             {
-              p++;
-            }
-          if (p < EndLine && ']' == *p)
-            {
-              Len = p - Input;
-              if (NULL == (Section = HeapAlloc(GetProcessHeap(), 0,
-                                               sizeof(*Section) + Len * sizeof(WCHAR))))
+                if (!strcmpiW( (*key)->name, key_name ))
                 {
-                  break;
+                    PROFILEKEY *to_del = *key;
+                    *key = to_del->next;
+                    if (to_del->value) HeapFree( GetProcessHeap(), 0, to_del->value);
+                    HeapFree( GetProcessHeap(), 0, to_del );
+                    return TRUE;
                 }
-              MultiByteToWideChar(CP_ACP, 0, Input, Len, Section->Name, Len);
-              Section->Name[Len] = L'\0';
-              Section->Key  = NULL;
-              Section->Next = NULL;
-              *NextSection = Section;
-              NextSection  = &Section->Next;
-              NextKey      = &Section->Key;
-              PrevKey      = NULL;
-
-              DPRINT("New section: %S\n", Section->Name);
-
+                key = &(*key)->next;
             }
-          Input = p;
-          while (Input < End && '\n' != *Input)
-            {
-              Input++;
-            }
-          Input++; /* Skip past the \n */
-          continue;
         }
+        section = &(*section)->next;
+    }
+    return FALSE;
+}
 
-      p = Input;
-      p2 = p;
-      while (p < EndLine && '=' != *p)
-        {
-          if (! PROFILE_isspace(*p))
-            {
-              p2 = p;
-            }
-          p++;
-        }
 
-      if (p2 != Input)
+/***********************************************************************
+ *           PROFILE_DeleteAllKeys
+ *
+ * Delete all keys from a profile tree.
+ */
+void PROFILE_DeleteAllKeys( LPCWSTR section_name)
+{
+    PROFILESECTION **section= &CurProfile->section;
+    while (*section)
+    {
+        if ((*section)->name[0] && !strcmpiW( (*section)->name, section_name ))
         {
-          Len = p2 - Input + 1;
-          if (NULL == (Key = HeapAlloc(GetProcessHeap(), 0,
-                                       sizeof(*Key) + Len * sizeof(WCHAR))))
-            {
-              break;
-            }
-          MultiByteToWideChar(CP_ACP, 0, Input, Len, Key->Name, Len);
-          Key->Name[Len] = L'\0';
-          Input = p + 1;
-          while (Input < EndLine && PROFILE_isspace(*Input))
+            PROFILEKEY **key = &(*section)->key;
+            while (*key)
             {
-              Input++;
+                PROFILEKEY *to_del = *key;
+      *key = to_del->next;
+      if (to_del->value) HeapFree( GetProcessHeap(), 0, to_del->value);
+      HeapFree( GetProcessHeap(), 0, to_del );
+      CurProfile->changed =TRUE;
             }
-          if (EndLine <= Input)
-            {
-              Key->Value = NULL;
-            }
-          else
-            {
-              p2 = Input;
-              p = Input + 1;
-              while (p < EndLine)
-                {
-                  if (! PROFILE_isspace(*p))
-                    {
-                      p2 = p;
-                    }
-                  p++;
-                }
-              Len = p2 - Input + 1;
-              if (NULL == (Key->Value = HeapAlloc(GetProcessHeap(), 0,
-                                                  (Len + 1) * sizeof(WCHAR))))
-                {
-                  break;
-                }
-              MultiByteToWideChar(CP_ACP, 0, Input, Len, Key->Value, Len);
-              Key->Value[Len] = L'\0';
-           }  
-
-          Key->Next  = NULL;
-          *NextKey  = Key;
-          NextKey   = &Key->Next;
-          PrevKey   = Key;
-
-          DPRINT("New key: name=%S, value=%S\n",
-                 Key->Name, NULL != Key->Value ? Key->Value : L"(none)");
-
-          Input = p;
-        }
-      while (Input < End && '\n' != *Input)
-        {
-          Input++;
         }
-      Input++; /* Skip past the \n */
+        section = &(*section)->next;
     }
-
-  UnmapViewOfFile(BaseAddress);
-  CloseHandle(Mapping);
-
-  return FirstSection;
 }
 
 
@@ -367,101 +595,70 @@
  *
  * Find a key in a profile tree, optionally creating it.
  */
-static PROFILEKEY * FASTCALL
-PROFILE_Find(PROFILESECTION **Section, LPCWSTR SectionName,
-             LPCWSTR KeyName, BOOL Create, BOOL CreateAlways)
+static PROFILEKEY *PROFILE_Find( PROFILESECTION **section, LPCWSTR section_name,
+                                 LPCWSTR key_name, BOOL create, BOOL create_always )
 {
-  LPCWSTR p;
-  int SecLen, KeyLen;
-
-  while (PROFILE_isspace(*SectionName))
-    {
-      SectionName++;
-    }
-  p = SectionName + wcslen(SectionName) - 1;
-  while (SectionName < p && PROFILE_isspace(*p))
-    {
-      p--;
-    }
-  SecLen = p - SectionName + 1;
+    LPCWSTR p;
+    int seclen, keylen;
 
-  while (PROFILE_isspace(*KeyName))
-    {
-      KeyName++;
-    }
-  p = KeyName + wcslen(KeyName) - 1;
-  while (KeyName < p && PROFILE_isspace(*p))
-    {
-      p--;
-    }
-  KeyLen = p - KeyName + 1;
-
-  while (NULL != *Section)
-    {
-      if (L'\0' != ((*Section)->Name[0])
-          && 0 == _wcsnicmp((*Section)->Name, SectionName, SecLen)
-          && L'\0' == ((*Section)->Name)[SecLen])
-        {
-          PROFILEKEY **Key = &(*Section)->Key;
-
-          while (NULL != *Key)
-            {
-              /* If create_always is FALSE then we check if the keyname
-               * already exists. Otherwise we add it regardless of its
-               * existence, to allow keys to be added more than once in
-               * some cases.
-               */
-              if (! CreateAlways)
+    while (PROFILE_isspaceW(*section_name)) section_name++;
+    p = section_name + strlenW(section_name) - 1;
+    while ((p > section_name) && PROFILE_isspaceW(*p)) p--;
+    seclen = p - section_name + 1;
+
+    while (PROFILE_isspaceW(*key_name)) key_name++;
+    p = key_name + strlenW(key_name) - 1;
+    while ((p > key_name) && PROFILE_isspaceW(*p)) p--;
+    keylen = p - key_name + 1;
+
+    while (*section)
+    {
+        if ( ((*section)->name[0])
+             && (!(strncmpiW( (*section)->name, section_name, seclen )))
+             && (((*section)->name)[seclen] == '\0') )
+        {
+            PROFILEKEY **key = &(*section)->key;
+
+            while (*key)
+            {
+                /* If create_always is FALSE then we check if the keyname
+                 * already exists. Otherwise we add it regardless of its
+                 * existence, to allow keys to be added more than once in
+                 * some cases.
+                 */
+                if(!create_always)
                 {
-                  if (0 == _wcsnicmp((*Key)->Name, KeyName, KeyLen)
-                      && L'\0' == ((*Key)->Name)[KeyLen])
-                    {
-                      return *Key;
-                    }
+                    if ( (!(strncmpiW( (*key)->name, key_name, keylen )))
+                         && (((*key)->name)[keylen] == '\0') )
+                        return *key;
                 }
-              Key = &(*Key)->Next;
-            }
-          if (! Create)
-            {
-              return NULL;
-            }
-          if (NULL == (*Key = HeapAlloc(GetProcessHeap(), 0,
-                                        sizeof(PROFILEKEY) + wcslen(KeyName) * sizeof(WCHAR))))
-            {
-              return NULL;
+                key = &(*key)->next;
             }
-          wcscpy((*Key)->Name, KeyName);
-          (*Key)->Value = NULL;
-          (*Key)->Next  = NULL;
-          return *Key;
-        }
-      Section = &(*Section)->Next;
-    }
-
-  if (! Create)
-    {
-      return NULL;
-    }
-
-  *Section = HeapAlloc(GetProcessHeap(), 0,
-                       sizeof(PROFILESECTION) + wcslen(SectionName) * sizeof(WCHAR));
-  if (NULL == *Section)
-    {
-      return NULL;
-    }
-  wcscpy((*Section)->Name, SectionName);
-  (*Section)->Next = NULL;
-  if (NULL == ((*Section)->Key = HeapAlloc(GetProcessHeap(), 0,
-                                           sizeof(PROFILEKEY) + wcslen(KeyName) * sizeof(WCHAR))))
-    {
-      HeapFree(GetProcessHeap(), 0, *Section);
-      return NULL;
-    }
-  wcscpy((*Section)->Key->Name, KeyName );
-  (*Section)->Key->Value = NULL;
-  (*Section)->Key->Next  = NULL;
-
-  return (*Section)->Key;
+            if (!create) return NULL;
+            if (!(*key = HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILEKEY) + strlenW(key_name) * sizeof(WCHAR) )))
+                return NULL;
+            strcpyW( (*key)->name, key_name );
+            (*key)->value = NULL;
+            (*key)->next  = NULL;
+            return *key;
+        }
+        section = &(*section)->next;
+    }
+    if (!create) return NULL;
+    *section = HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILESECTION) + strlenW(section_name) * sizeof(WCHAR) );
+    if(*section == NULL) return NULL;
+    strcpyW( (*section)->name, section_name );
+    (*section)->next = NULL;
+    if (!((*section)->key  = HeapAlloc( GetProcessHeap(), 0,
+                                        sizeof(PROFILEKEY) + strlenW(key_name) * sizeof(WCHAR) )))
+    {
+        HeapFree(GetProcessHeap(), 0, *section);
+        return NULL;
+    }
+    strcpyW( (*section)->key->name, key_name );
+    (*section)->key->value = NULL;
+    (*section)->key->next  = NULL;
+    return (*section)->key;
 }
 
[truncated at 1000 lines; 2278 more skipped]
CVSspam 0.2.8