inicache.c

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

C
1,188
字号
		      &IoStatusBlock,
		      FileBuffer,
		      FileLength,
		      &FileOffset,
		      NULL);

  /* 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);

	  DPRINT1("[%.*s]\n", SectionNameSize, SectionName);

	  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,
				    String);

	  DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue);

	  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 *KeyData)
{
  PINICACHEKEY Key;

  if (Section == NULL || KeyName == NULL || KeyData == NULL)
    {
      DPRINT("Invalid parameter\n");
      return(STATUS_INVALID_PARAMETER);
    }

  *KeyData = NULL;

  Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName));
  if (Key == NULL)
    {
      return(STATUS_INVALID_PARAMETER);
    }

  *KeyData = Key->Data;

  return(STATUS_SUCCESS);
}


PINICACHEITERATOR
IniCacheFindFirstValue(PINICACHESECTION Section,
		       PWCHAR *KeyName,
		       PWCHAR *KeyData)
{
  PINICACHEITERATOR Iterator;
  PINICACHEKEY Key;

  if (Section == NULL || KeyName == NULL || KeyData == NULL)
    {
      DPRINT("Invalid parameter\n");
      return(NULL);
    }

  Key = Section->FirstKey;
  if (Key == NULL)
    {
      DPRINT("Invalid parameter\n");
      return(NULL);
    }

  *KeyName = Key->Name;
  *KeyData = Key->Data;

  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 *KeyData)
{
  PINICACHEKEY Key;

  if (Iterator == NULL || KeyName == NULL || KeyData == NULL)
    {
      DPRINT("Invalid parameter\n");
      return(FALSE);
    }

  Key = Iterator->Key->Next;
  if (Key == NULL)
    {
      DPRINT("No more entries\n");
      return(FALSE);
    }

  *KeyName = Key->Name;
  *KeyData = Key->Data;

  Iterator->Key = Key;

  return(TRUE);
}


VOID
IniCacheFindClose(PINICACHEITERATOR Iterator)
{
  if (Iterator == NULL)
    return;

  RtlFreeHeap(ProcessHeap,
	      0,
	      Iterator);
}


PINICACHEKEY
IniCacheInsertKey(PINICACHESECTION Section,
		  PINICACHEKEY AnchorKey,
		  INSERTATION_TYPE InsertationType,
		  PWCHAR Name,
		  PWCHAR Data)
{
  PINICACHEKEY Key;

  Key = NULL;

  if (Section == NULL ||
      Name == NULL ||
      *Name == 0 ||
      Data == NULL ||
      *Data == 0)
    {
      DPRINT("Invalid parameter\n");
      return(NULL);
    }

  /* Allocate key buffer */
  Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
				      0,
				      sizeof(INICACHEKEY));
  if (Key == NULL)
    {
      DPRINT("RtlAllocateHeap() failed\n");
      return(NULL);
    }
  RtlZeroMemory(Key,
		sizeof(INICACHEKEY));

  /* Allocate name buffer */
  Key->Name = RtlAllocateHeap(ProcessHeap,
			      0,
			      (wcslen(Name) + 1) * sizeof(WCHAR));
  if (Key->Name == NULL)
    {
      DPRINT("RtlAllocateHeap() failed\n");
      RtlFreeHeap(ProcessHeap,
		  0,
		  Key);
      return(NULL);
    }

  /* Copy value name */
  wcscpy(Key->Name, Name);

  /* Allocate data buffer */
  Key->Data = RtlAllocateHeap(ProcessHeap,
			      0,
			      (wcslen(Data) + 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 */
  wcscpy(Key->Data, Data);

  /* Insert key into section */
  if (Section->FirstKey == NULL)
    {
      Section->FirstKey = Key;
      Section->LastKey = Key;
    }
  else if ((InsertationType == INSERT_FIRST) ||
	   ((InsertationType == INSERT_BEFORE) && ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey))))
    {
      /* Insert at the head of the list */
      Section->FirstKey->Prev = Key;
      Key->Next = Section->FirstKey;
      Section->FirstKey = Key;
    }
  else if ((InsertationType == INSERT_BEFORE) && (AnchorKey != NULL))
    {
      /* Insert before the anchor key */
      Key->Next = AnchorKey;
      Key->Prev = AnchorKey->Prev;
      AnchorKey->Prev->Next = Key;
      AnchorKey->Prev = Key;
    }
  else if ((InsertationType == INSERT_LAST) ||
	   ((InsertationType == INSERT_AFTER) && ((AnchorKey == NULL) || (AnchorKey == Section->LastKey))))
    {
      Section->LastKey->Next = Key;
      Key->Prev = Section->LastKey;
      Section->LastKey = Key;
    }
  else if ((InsertationType == INSERT_AFTER) && (AnchorKey != NULL))
    {
      /* Insert before the anchor key */
      Key->Next = AnchorKey->Next;
      Key->Prev = AnchorKey;
      AnchorKey->Next->Prev = Key;
      AnchorKey->Next = Key;
    }

  return(Key);
}


PINICACHE
IniCacheCreate(VOID)
{
  PINICACHE Cache;

  /* Allocate inicache header */
  Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
				     0,
				     sizeof(INICACHE));
  if (Cache == NULL)
    {
      DPRINT("RtlAllocateHeap() failed\n");
      return(NULL);
    }

  /* Initialize inicache header */
  RtlZeroMemory(Cache,
		sizeof(INICACHE));

  return(Cache);
}


NTSTATUS
IniCacheSave(PINICACHE Cache,
	     PWCHAR FileName)
{
  UNICODE_STRING Name;
  PINICACHESECTION Section;
  PINICACHEKEY Key;
  ULONG BufferSize;
  PCHAR Buffer;
  PCHAR Ptr;
  ULONG Len;
  NTSTATUS Status;

  OBJECT_ATTRIBUTES ObjectAttributes;
  IO_STATUS_BLOCK IoStatusBlock;
  LARGE_INTEGER Offset;
  HANDLE FileHandle;


  /* Calculate required buffer size */
  BufferSize = 0;
  Section = Cache->FirstSection;
  while (Section != NULL)
    {
      BufferSize += (Section->Name ? wcslen(Section->Name) : 0)
		    + 4; /* "[]\r\n" */

      Key = Section->FirstKey;
      while (Key != NULL)
	{
	  BufferSize += wcslen(Key->Name)
			+ (Key->Data ? wcslen(Key->Data) : 0)
			+ 3; /* "=\r\n" */
	  Key = Key->Next;
	}

      Section = Section->Next;
      if (Section != NULL)
	BufferSize += 2; /* extra "\r\n" at end of each section */
    }
  BufferSize++; /* Null-terminator */

  DPRINT1("BufferSize: %lu\n", BufferSize);

  /* Allocate file buffer */
  Buffer = RtlAllocateHeap(ProcessHeap,
			   0,
			   BufferSize);
  if (Buffer == NULL)
    {
      DPRINT1("RtlAllocateHeap() failed\n");
      return(STATUS_INSUFFICIENT_RESOURCES);
    }
  RtlZeroMemory(Buffer, BufferSize);

  /* Fill file buffer */
  Ptr = Buffer;
  Section = Cache->FirstSection;
  while (Section != NULL)
    {
      Len = sprintf(Ptr, "[%S]\r\n", Section->Name);
      Ptr += Len;

      Key = Section->FirstKey;
      while (Key != NULL)
	{
	  Len = sprintf(Ptr, "%S=%S\r\n", Key->Name, Key->Data);
	  Ptr += Len;
	  Key = Key->Next;
	}

      Section = Section->Next;
      if (Section != NULL)
	{
	  Len = sprintf(Ptr, "\r\n");
	  Ptr += Len;
	}
    }

  /* Create ini file */
  RtlInitUnicodeString(&Name,
		       FileName);

  InitializeObjectAttributes(&ObjectAttributes,
			     &Name,
			     0,
			     NULL,
			     NULL);

  Status = NtCreateFile(&FileHandle,
			GENERIC_WRITE,
			&ObjectAttributes,
			&IoStatusBlock,
			NULL,
			FILE_ATTRIBUTE_NORMAL,
			0,
			FILE_SUPERSEDE,
			FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
			NULL,
			0);
  if (!NT_SUCCESS(Status))
    {
      DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
      RtlFreeHeap(ProcessHeap,
		  0,
		  Buffer);
      return(Status);
    }

  Offset.QuadPart = 0LL;
  Status = NtWriteFile(FileHandle,
		       NULL,
		       NULL,
		       NULL,
		       &IoStatusBlock,
		       Buffer,
		       BufferSize,
		       &Offset,
		       NULL);
  if (!NT_SUCCESS(Status))
    {
      DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
      NtClose(FileHandle);
      RtlFreeHeap(ProcessHeap,
		  0,
		  Buffer);
      return(Status);
    }

  NtClose(FileHandle);

  RtlFreeHeap(ProcessHeap,
	      0,
	      Buffer);

  return(STATUS_SUCCESS);
}


PINICACHESECTION
IniCacheAppendSection(PINICACHE Cache,
		      PWCHAR Name)
{
  PINICACHESECTION Section = NULL;

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

  /* Copy section name */
  wcscpy(Section->Name, Name);

  /* 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);
}

/* EOF */

⌨️ 快捷键说明

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