inicache.c

来自「一个类似windows」· C语言 代码 · 共 1,188 行 · 第 1/2 页

C
1,188
字号
/*
 *  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 21704 2006-04-22 13:55:01Z tretiakov $
 * 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 <usetup.h>

#define NDEBUG
#include <debug.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->Data != NULL)
    {
      RtlFreeHeap(ProcessHeap,
		  0,
		  Key->Data);
      Key->Data = 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 Data,
	       ULONG DataLength)
{
  PINICACHEKEY Key;
  ULONG i;

  Key = NULL;

  if (Section == NULL ||
      Name == NULL ||
      NameLength == 0 ||
      Data == NULL ||
      DataLength == 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->Data = RtlAllocateHeap(ProcessHeap,
			      0,
			      (DataLength + 1) * sizeof(WCHAR));
  if (Key->Data == NULL)
    {
      DPRINT("RtlAllocateHeap() failed\n");
      RtlFreeHeap(ProcessHeap,
		  0,
		  Key->Name);
      RtlFreeHeap(ProcessHeap,
		  0,
		  Key);
      return(NULL);
    }

  /* Copy value data */
  for (i = 0; i < DataLength; i++)
    {
      Key->Data[i] = (WCHAR)Data[i];
    }
  Key->Data[DataLength] = 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);
}

#if 0
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);
}
#endif

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;

  while(Ptr && *Ptr)
  {
    *NamePtr = NULL;
    *NameSize = 0;
    Size = 0;

    /* skip whitespace and empty lines */
    while (isspace(*Ptr) || *Ptr == '\n' || *Ptr == '\r')
    {
      Ptr++;
    }
    if (*Ptr == 0)
    {
      continue;
    }

    *NamePtr = Ptr;

    while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '=' && *Ptr != ';')
    {
      Size++;
      Ptr++;
    }
    if (*Ptr == ';')
    {
      while (*Ptr != 0 && *Ptr != '\r' && *Ptr != '\n')
      {
	Ptr++;
      }
    }
    else
    {
      *NameSize = Size;
      break;
    }
  }

  return(Ptr);
}


static PCHAR
IniCacheGetKeyValue(PCHAR Ptr,
		    PCHAR *DataPtr,
		    PULONG DataSize,
		    BOOLEAN String)
{
  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++;
    }

  if (*Ptr == '"' && String)
    {
      Ptr++;

      /* Get data */
      *DataPtr = Ptr;
      while (*Ptr != '"')
	{
	  Ptr++;
	  Size++;
	}
      Ptr++;
      while (*Ptr && *Ptr != '\r' && *Ptr != '\n')
	{
	  Ptr++;
	}
    }
  else
    {
      /* Get data */
      *DataPtr = Ptr;
      while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';')
	{
	  Ptr++;
	  Size++;
	}
    }

  /* Skip to next line */
  if (*Ptr == '\r')
    Ptr++;
  if (*Ptr == '\n')
    Ptr++;

  *DataSize = Size;

  return(Ptr);
}




/* PUBLIC FUNCTIONS *********************************************************/

NTSTATUS
IniCacheLoad(PINICACHE *Cache,
	     PUNICODE_STRING FileName,
	     BOOLEAN String)
{
  OBJECT_ATTRIBUTES ObjectAttributes;
  FILE_STANDARD_INFORMATION FileInfo;
  IO_STATUS_BLOCK IoStatusBlock;
  HANDLE FileHandle;
  NTSTATUS Status;
  PCHAR FileBuffer;
  ULONG FileLength;
  PCHAR Ptr;
  LARGE_INTEGER FileOffset;

  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_SYNCHRONOUS_IO_NONALERT | 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 (!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,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?