mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 17:06:29 +00:00
842 lines
15 KiB
C
842 lines
15 KiB
C
|
/*
|
||
|
* ReactOS kernel
|
||
|
* Copyright (C) 2002 ReactOS Team
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program 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 General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
*/
|
||
|
/* $Id: inicache.c,v 1.1 2002/11/13 18:25:18 ekohl Exp $
|
||
|
* COPYRIGHT: See COPYING in the top level directory
|
||
|
* PROJECT: ReactOS text-mode setup
|
||
|
* FILE: subsys/system/usetup/inicache.c
|
||
|
* PURPOSE: INI file parser that caches contents of INI file in memory
|
||
|
* PROGRAMMER: Royce Mitchell III
|
||
|
* Eric Kohl
|
||
|
*/
|
||
|
|
||
|
/* INCLUDES *****************************************************************/
|
||
|
|
||
|
#include <ddk/ntddk.h>
|
||
|
#include "usetup.h"
|
||
|
#include "inicache.h"
|
||
|
|
||
|
|
||
|
/* PRIVATE FUNCTIONS ********************************************************/
|
||
|
|
||
|
static PINICACHEKEY
|
||
|
IniCacheFreeKey(PINICACHEKEY Key)
|
||
|
{
|
||
|
PINICACHEKEY Next;
|
||
|
|
||
|
if (Key == NULL)
|
||
|
{
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
Next = Key->Next;
|
||
|
if (Key->Name != NULL)
|
||
|
{
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Key->Name);
|
||
|
Key->Name = NULL;
|
||
|
}
|
||
|
|
||
|
if (Key->Value != NULL)
|
||
|
{
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Key->Value);
|
||
|
Key->Value = NULL;
|
||
|
}
|
||
|
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Key);
|
||
|
|
||
|
return(Next);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PINICACHESECTION
|
||
|
IniCacheFreeSection(PINICACHESECTION Section)
|
||
|
{
|
||
|
PINICACHESECTION Next;
|
||
|
|
||
|
if (Section == NULL)
|
||
|
{
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
Next = Section->Next;
|
||
|
while (Section->FirstKey != NULL)
|
||
|
{
|
||
|
Section->FirstKey = IniCacheFreeKey(Section->FirstKey);
|
||
|
}
|
||
|
Section->LastKey = NULL;
|
||
|
|
||
|
if (Section->Name != NULL)
|
||
|
{
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Section->Name);
|
||
|
Section->Name = NULL;
|
||
|
}
|
||
|
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Section);
|
||
|
|
||
|
return(Next);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PINICACHEKEY
|
||
|
IniCacheFindKey(PINICACHESECTION Section,
|
||
|
PWCHAR Name,
|
||
|
ULONG NameLength)
|
||
|
{
|
||
|
PINICACHEKEY Key;
|
||
|
|
||
|
Key = Section->FirstKey;
|
||
|
while (Key != NULL)
|
||
|
{
|
||
|
if (NameLength == wcslen(Key->Name))
|
||
|
{
|
||
|
if (_wcsnicmp(Key->Name, Name, NameLength) == 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Key = Key->Next;
|
||
|
}
|
||
|
|
||
|
return(Key);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PINICACHEKEY
|
||
|
IniCacheAddKey(PINICACHESECTION Section,
|
||
|
PCHAR Name,
|
||
|
ULONG NameLength,
|
||
|
PCHAR Value,
|
||
|
ULONG ValueLength)
|
||
|
{
|
||
|
PINICACHEKEY Key;
|
||
|
ULONG i;
|
||
|
|
||
|
Key = NULL;
|
||
|
|
||
|
if (Section == NULL ||
|
||
|
Name == NULL ||
|
||
|
NameLength == 0 ||
|
||
|
Value == NULL ||
|
||
|
ValueLength == 0)
|
||
|
{
|
||
|
DPRINT("Invalid parameter\n");
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
|
||
|
0,
|
||
|
sizeof(INICACHEKEY));
|
||
|
if (Key == NULL)
|
||
|
{
|
||
|
DPRINT("RtlAllocateHeap() failed\n");
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
RtlZeroMemory(Key,
|
||
|
sizeof(INICACHEKEY));
|
||
|
|
||
|
|
||
|
Key->Name = RtlAllocateHeap(ProcessHeap,
|
||
|
0,
|
||
|
(NameLength + 1) * sizeof(WCHAR));
|
||
|
if (Key->Name == NULL)
|
||
|
{
|
||
|
DPRINT("RtlAllocateHeap() failed\n");
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Key);
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
/* Copy value name */
|
||
|
for (i = 0; i < NameLength; i++)
|
||
|
{
|
||
|
Key->Name[i] = (WCHAR)Name[i];
|
||
|
}
|
||
|
Key->Name[NameLength] = 0;
|
||
|
|
||
|
|
||
|
Key->Value = RtlAllocateHeap(ProcessHeap,
|
||
|
0,
|
||
|
(ValueLength + 1) * sizeof(WCHAR));
|
||
|
if (Key->Value == NULL)
|
||
|
{
|
||
|
DPRINT("RtlAllocateHeap() failed\n");
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Key->Name);
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Key);
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
/* Copy value data */
|
||
|
for (i = 0; i < ValueLength; i++)
|
||
|
{
|
||
|
Key->Value[i] = (WCHAR)Value[i];
|
||
|
}
|
||
|
Key->Value[ValueLength] = 0;
|
||
|
|
||
|
|
||
|
if (Section->FirstKey == NULL)
|
||
|
{
|
||
|
Section->FirstKey = Key;
|
||
|
Section->LastKey = Key;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Section->LastKey->Next = Key;
|
||
|
Key->Prev = Section->LastKey;
|
||
|
Section->LastKey = Key;
|
||
|
}
|
||
|
|
||
|
return(Key);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PINICACHESECTION
|
||
|
IniCacheFindSection(PINICACHE Cache,
|
||
|
PWCHAR Name,
|
||
|
ULONG NameLength)
|
||
|
{
|
||
|
PINICACHESECTION Section = NULL;
|
||
|
|
||
|
if (Cache == NULL || Name == NULL || NameLength == 0)
|
||
|
{
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
Section = Cache->FirstSection;
|
||
|
|
||
|
/* iterate through list of sections */
|
||
|
while (Section != NULL)
|
||
|
{
|
||
|
if (NameLength == wcslen(Section->Name))
|
||
|
{
|
||
|
/* are the contents the same too? */
|
||
|
if (_wcsnicmp(Section->Name, Name, NameLength) == 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* get the next section*/
|
||
|
Section = Section->Next;
|
||
|
}
|
||
|
|
||
|
return(Section);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PINICACHESECTION
|
||
|
IniCacheAddSection(PINICACHE Cache,
|
||
|
PCHAR Name,
|
||
|
ULONG NameLength)
|
||
|
{
|
||
|
PINICACHESECTION Section = NULL;
|
||
|
ULONG i;
|
||
|
|
||
|
if (Cache == NULL || Name == NULL || NameLength == 0)
|
||
|
{
|
||
|
DPRINT("Invalid parameter\n");
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
|
||
|
0,
|
||
|
sizeof(INICACHESECTION));
|
||
|
if (Section == NULL)
|
||
|
{
|
||
|
DPRINT("RtlAllocateHeap() failed\n");
|
||
|
return(NULL);
|
||
|
}
|
||
|
RtlZeroMemory(Section,
|
||
|
sizeof(INICACHESECTION));
|
||
|
|
||
|
/* Allocate and initialize section name */
|
||
|
Section->Name = RtlAllocateHeap(ProcessHeap,
|
||
|
0,
|
||
|
(NameLength + 1) * sizeof(WCHAR));
|
||
|
if (Section->Name == NULL)
|
||
|
{
|
||
|
DPRINT("RtlAllocateHeap() failed\n");
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Section);
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
/* Copy section name */
|
||
|
for (i = 0; i < NameLength; i++)
|
||
|
{
|
||
|
Section->Name[i] = (WCHAR)Name[i];
|
||
|
}
|
||
|
Section->Name[NameLength] = 0;
|
||
|
|
||
|
/* Append section */
|
||
|
if (Cache->FirstSection == NULL)
|
||
|
{
|
||
|
Cache->FirstSection = Section;
|
||
|
Cache->LastSection = Section;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Cache->LastSection->Next = Section;
|
||
|
Section->Prev = Cache->LastSection;
|
||
|
Cache->LastSection = Section;
|
||
|
}
|
||
|
|
||
|
return(Section);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PCHAR
|
||
|
IniCacheSkipWhitespace(PCHAR Ptr)
|
||
|
{
|
||
|
while (*Ptr != 0 && isspace(*Ptr))
|
||
|
Ptr++;
|
||
|
|
||
|
return((*Ptr == 0) ? NULL : Ptr);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PCHAR
|
||
|
IniCacheSkipToNextSection(PCHAR Ptr)
|
||
|
{
|
||
|
while (*Ptr != 0 && *Ptr != '[')
|
||
|
{
|
||
|
while (*Ptr != 0 && *Ptr != L'\n')
|
||
|
{
|
||
|
Ptr++;
|
||
|
}
|
||
|
Ptr++;
|
||
|
}
|
||
|
|
||
|
return((*Ptr == 0) ? NULL : Ptr);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PCHAR
|
||
|
IniCacheGetSectionName(PCHAR Ptr,
|
||
|
PCHAR *NamePtr,
|
||
|
PULONG NameSize)
|
||
|
{
|
||
|
ULONG Size = 0;
|
||
|
CHAR Name[256];
|
||
|
|
||
|
*NamePtr = NULL;
|
||
|
*NameSize = 0;
|
||
|
|
||
|
/* skip whitespace */
|
||
|
while (*Ptr != 0 && isspace(*Ptr))
|
||
|
{
|
||
|
Ptr++;
|
||
|
}
|
||
|
|
||
|
*NamePtr = Ptr;
|
||
|
|
||
|
while (*Ptr != 0 && *Ptr != ']')
|
||
|
{
|
||
|
Size++;
|
||
|
Ptr++;
|
||
|
}
|
||
|
|
||
|
Ptr++;
|
||
|
|
||
|
while (*Ptr != 0 && *Ptr != L'\n')
|
||
|
{
|
||
|
Ptr++;
|
||
|
}
|
||
|
Ptr++;
|
||
|
|
||
|
*NameSize = Size;
|
||
|
|
||
|
strncpy(Name, *NamePtr, Size);
|
||
|
Name[Size] = 0;
|
||
|
|
||
|
DPRINT("SectionName: '%s'\n", Name);
|
||
|
|
||
|
return(Ptr);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PCHAR
|
||
|
IniCacheGetKeyName(PCHAR Ptr,
|
||
|
PCHAR *NamePtr,
|
||
|
PULONG NameSize)
|
||
|
{
|
||
|
ULONG Size = 0;
|
||
|
|
||
|
*NamePtr = NULL;
|
||
|
*NameSize = 0;
|
||
|
|
||
|
/* skip whitespace */
|
||
|
while (*Ptr != 0 && isspace(*Ptr))
|
||
|
{
|
||
|
Ptr++;
|
||
|
}
|
||
|
|
||
|
*NamePtr = Ptr;
|
||
|
|
||
|
while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '=')
|
||
|
{
|
||
|
Size++;
|
||
|
Ptr++;
|
||
|
}
|
||
|
|
||
|
*NameSize = Size;
|
||
|
|
||
|
return(Ptr);
|
||
|
}
|
||
|
|
||
|
|
||
|
static PCHAR
|
||
|
IniCacheGetKeyValue(PCHAR Ptr,
|
||
|
PCHAR *DataPtr,
|
||
|
PULONG DataSize)
|
||
|
{
|
||
|
ULONG Size = 0;
|
||
|
|
||
|
*DataPtr = NULL;
|
||
|
*DataSize = 0;
|
||
|
|
||
|
/* skip whitespace */
|
||
|
while (*Ptr != 0 && isspace(*Ptr))
|
||
|
{
|
||
|
Ptr++;
|
||
|
}
|
||
|
|
||
|
/* check and skip '=' */
|
||
|
if (*Ptr != '=')
|
||
|
{
|
||
|
return(NULL);
|
||
|
}
|
||
|
Ptr++;
|
||
|
|
||
|
/* skip whitespace */
|
||
|
while (*Ptr != 0 && isspace(*Ptr))
|
||
|
{
|
||
|
Ptr++;
|
||
|
}
|
||
|
|
||
|
/* check for quoted data */
|
||
|
if (*Ptr == '\"')
|
||
|
{
|
||
|
Ptr++;
|
||
|
*DataPtr = Ptr;
|
||
|
|
||
|
while (*Ptr != 0 && *Ptr != '\"')
|
||
|
{
|
||
|
Ptr++;
|
||
|
Size++;
|
||
|
}
|
||
|
Ptr++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*DataPtr = Ptr;
|
||
|
|
||
|
while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '\n')
|
||
|
{
|
||
|
Ptr++;
|
||
|
Size++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Skip to next line */
|
||
|
while (*Ptr != 0 && *Ptr != '\n')
|
||
|
{
|
||
|
Ptr++;
|
||
|
}
|
||
|
Ptr++;
|
||
|
|
||
|
*DataSize = Size;
|
||
|
|
||
|
return(Ptr);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* PUBLIC FUNCTIONS *********************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
IniCacheLoad(PINICACHE *Cache,
|
||
|
PUNICODE_STRING FileName)
|
||
|
{
|
||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
|
FILE_STANDARD_INFORMATION FileInfo;
|
||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||
|
HANDLE FileHandle;
|
||
|
NTSTATUS Status;
|
||
|
PCHAR FileBuffer;
|
||
|
ULONG FileLength;
|
||
|
PCHAR Ptr;
|
||
|
LARGE_INTEGER FileOffset;
|
||
|
|
||
|
ULONG i;
|
||
|
PINICACHESECTION Section;
|
||
|
PINICACHEKEY Key;
|
||
|
|
||
|
PCHAR SectionName;
|
||
|
ULONG SectionNameSize;
|
||
|
|
||
|
PCHAR KeyName;
|
||
|
ULONG KeyNameSize;
|
||
|
|
||
|
PCHAR KeyValue;
|
||
|
ULONG KeyValueSize;
|
||
|
|
||
|
*Cache = NULL;
|
||
|
|
||
|
/* Open ini file */
|
||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||
|
FileName,
|
||
|
0,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
Status = NtOpenFile(&FileHandle,
|
||
|
GENERIC_READ | SYNCHRONIZE,
|
||
|
&ObjectAttributes,
|
||
|
&IoStatusBlock,
|
||
|
FILE_SHARE_READ,
|
||
|
FILE_NON_DIRECTORY_FILE);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
DPRINT("NtOpenFile() successful\n");
|
||
|
|
||
|
/* Query file size */
|
||
|
Status = NtQueryInformationFile(FileHandle,
|
||
|
&IoStatusBlock,
|
||
|
&FileInfo,
|
||
|
sizeof(FILE_STANDARD_INFORMATION),
|
||
|
FileStandardInformation);
|
||
|
if (Status == STATUS_PENDING)
|
||
|
{
|
||
|
DPRINT("NtQueryInformationFile() returns STATUS_PENDING\n");
|
||
|
|
||
|
}
|
||
|
else if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
|
||
|
NtClose(FileHandle);
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
FileLength = FileInfo.EndOfFile.u.LowPart;
|
||
|
|
||
|
DPRINT("File size: %lu\n", FileLength);
|
||
|
|
||
|
/* Allocate file buffer */
|
||
|
FileBuffer = RtlAllocateHeap(ProcessHeap,
|
||
|
0,
|
||
|
FileLength + 1);
|
||
|
if (FileBuffer == NULL)
|
||
|
{
|
||
|
DPRINT1("RtlAllocateHeap() failed\n");
|
||
|
NtClose(FileHandle);
|
||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
|
}
|
||
|
|
||
|
/* Read file */
|
||
|
FileOffset.QuadPart = 0ULL;
|
||
|
Status = NtReadFile(FileHandle,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatusBlock,
|
||
|
FileBuffer,
|
||
|
FileLength,
|
||
|
&FileOffset,
|
||
|
NULL);
|
||
|
|
||
|
if (Status == STATUS_PENDING)
|
||
|
{
|
||
|
DPRINT("NtReadFile() returns STATUS_PENDING\n");
|
||
|
|
||
|
Status = IoStatusBlock.Status;
|
||
|
}
|
||
|
|
||
|
/* Append string terminator */
|
||
|
FileBuffer[FileLength] = 0;
|
||
|
|
||
|
NtClose(FileHandle);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
DPRINT("NtReadFile() failed (Status %lx)\n", Status);
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
FileBuffer);
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Allocate inicache header */
|
||
|
*Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
|
||
|
0,
|
||
|
sizeof(INICACHE));
|
||
|
if (*Cache == NULL)
|
||
|
{
|
||
|
DPRINT("RtlAllocateHeap() failed\n");
|
||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
|
}
|
||
|
|
||
|
/* Initialize inicache header */
|
||
|
RtlZeroMemory(*Cache,
|
||
|
sizeof(INICACHE));
|
||
|
|
||
|
/* Parse ini file */
|
||
|
Section = NULL;
|
||
|
Ptr = FileBuffer;
|
||
|
while (Ptr != NULL && *Ptr != 0)
|
||
|
{
|
||
|
Ptr = IniCacheSkipWhitespace(Ptr);
|
||
|
if (Ptr == NULL)
|
||
|
continue;
|
||
|
|
||
|
if (*Ptr == '[')
|
||
|
{
|
||
|
Section = NULL;
|
||
|
Ptr++;
|
||
|
|
||
|
Ptr = IniCacheGetSectionName(Ptr,
|
||
|
&SectionName,
|
||
|
&SectionNameSize);
|
||
|
|
||
|
Section = IniCacheAddSection(*Cache,
|
||
|
SectionName,
|
||
|
SectionNameSize);
|
||
|
if (Section == NULL)
|
||
|
{
|
||
|
DPRINT("IniCacheAddSection() failed\n");
|
||
|
Ptr = IniCacheSkipToNextSection(Ptr);
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (Section == NULL)
|
||
|
{
|
||
|
Ptr = IniCacheSkipToNextSection(Ptr);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
Ptr = IniCacheGetKeyName(Ptr,
|
||
|
&KeyName,
|
||
|
&KeyNameSize);
|
||
|
|
||
|
Ptr = IniCacheGetKeyValue(Ptr,
|
||
|
&KeyValue,
|
||
|
&KeyValueSize);
|
||
|
|
||
|
Key = IniCacheAddKey(Section,
|
||
|
KeyName,
|
||
|
KeyNameSize,
|
||
|
KeyValue,
|
||
|
KeyValueSize);
|
||
|
if (Key == NULL)
|
||
|
{
|
||
|
DPRINT("IniCacheAddKey() failed\n");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Free file buffer */
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
FileBuffer);
|
||
|
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
IniCacheDestroy(PINICACHE Cache)
|
||
|
{
|
||
|
if (Cache == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
while (Cache->FirstSection != NULL)
|
||
|
{
|
||
|
Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection);
|
||
|
}
|
||
|
Cache->LastSection = NULL;
|
||
|
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Cache);
|
||
|
}
|
||
|
|
||
|
|
||
|
PINICACHESECTION
|
||
|
IniCacheGetSection(PINICACHE Cache,
|
||
|
PWCHAR Name)
|
||
|
{
|
||
|
PINICACHESECTION Section = NULL;
|
||
|
|
||
|
if (Cache == NULL || Name == NULL)
|
||
|
{
|
||
|
DPRINT("Invalid parameter\n");
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
/* iterate through list of sections */
|
||
|
Section = Cache->FirstSection;
|
||
|
while (Section != NULL)
|
||
|
{
|
||
|
DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name);
|
||
|
|
||
|
/* Are the section names the same? */
|
||
|
if (_wcsicmp(Section->Name, Name) == 0)
|
||
|
return(Section);
|
||
|
|
||
|
/* Get the next section */
|
||
|
Section = Section->Next;
|
||
|
}
|
||
|
|
||
|
DPRINT("Section not found\n");
|
||
|
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
IniCacheGetKey(PINICACHESECTION Section,
|
||
|
PWCHAR KeyName,
|
||
|
PWCHAR *KeyValue)
|
||
|
{
|
||
|
PINICACHEKEY Key;
|
||
|
|
||
|
if (Section == NULL || KeyName == NULL || KeyValue == NULL)
|
||
|
{
|
||
|
DPRINT("Invalid parameter\n");
|
||
|
return(STATUS_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
*KeyValue = NULL;
|
||
|
|
||
|
Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName));
|
||
|
if (Key == NULL)
|
||
|
{
|
||
|
return(STATUS_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
*KeyValue = Key->Value;
|
||
|
|
||
|
return(STATUS_SUCCESS);
|
||
|
}
|
||
|
|
||
|
|
||
|
PINICACHEITERATOR
|
||
|
IniCacheFindFirstValue(PINICACHESECTION Section,
|
||
|
PWCHAR *KeyName,
|
||
|
PWCHAR *KeyValue)
|
||
|
{
|
||
|
PINICACHEITERATOR Iterator;
|
||
|
PINICACHEKEY Key;
|
||
|
|
||
|
if (Section == NULL || KeyName == NULL || KeyValue == NULL)
|
||
|
{
|
||
|
DPRINT("Invalid parameter\n");
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
Key = Section->FirstKey;
|
||
|
if (Key == NULL)
|
||
|
{
|
||
|
DPRINT("Invalid parameter\n");
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
*KeyName = Key->Name;
|
||
|
*KeyValue = Key->Value;
|
||
|
|
||
|
Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap,
|
||
|
0,
|
||
|
sizeof(INICACHEITERATOR));
|
||
|
if (Iterator == NULL)
|
||
|
{
|
||
|
DPRINT("RtlAllocateHeap() failed\n");
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
Iterator->Section = Section;
|
||
|
Iterator->Key = Key;
|
||
|
|
||
|
return(Iterator);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
IniCacheFindNextValue(PINICACHEITERATOR Iterator,
|
||
|
PWCHAR *KeyName,
|
||
|
PWCHAR *KeyValue)
|
||
|
{
|
||
|
PINICACHEKEY Key;
|
||
|
|
||
|
if (Iterator == NULL || KeyName == NULL || KeyValue == NULL)
|
||
|
{
|
||
|
DPRINT("Invalid parameter\n");
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
Key = Iterator->Key->Next;
|
||
|
if (Key == NULL)
|
||
|
{
|
||
|
DPRINT("No more entries\n");
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
*KeyName = Key->Name;
|
||
|
*KeyValue = Key->Value;
|
||
|
|
||
|
Iterator->Key = Key;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
IniCacheFindClose(PINICACHEITERATOR Iterator)
|
||
|
{
|
||
|
if (Iterator == NULL)
|
||
|
return;
|
||
|
|
||
|
RtlFreeHeap(ProcessHeap,
|
||
|
0,
|
||
|
Iterator);
|
||
|
}
|
||
|
|
||
|
/* EOF */
|