reactos/lib/kernel32/misc
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 = §ion->next;
+ next_key = §ion->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]