mirror of
https://github.com/reactos/reactos.git
synced 2024-11-06 06:33:08 +00:00
527f2f9057
* Create a branch for some evul shell experiments. svn path=/branches/shell-experiments/; revision=61927
264 lines
6.6 KiB
C
264 lines
6.6 KiB
C
/*
|
|
* PROJECT: .inf file parser
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* COPYRIGHT: Copyright 2005 Ge van Geldorp <gvg@reactos.org>
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include "inflib.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#define EOL L"\r\n"
|
|
#define SIZE_INC 1024
|
|
|
|
typedef struct _OUTPUTBUFFER
|
|
{
|
|
PWCHAR Buffer;
|
|
PWCHAR Current;
|
|
ULONG TotalSize;
|
|
ULONG FreeSize;
|
|
INFSTATUS Status;
|
|
} OUTPUTBUFFER, *POUTPUTBUFFER;
|
|
|
|
static void
|
|
Output(POUTPUTBUFFER OutBuf, PCWSTR Text)
|
|
{
|
|
ULONG Length;
|
|
PWCHAR NewBuf;
|
|
ULONG NewSize;
|
|
|
|
/* Skip mode? */
|
|
if (! INF_SUCCESS(OutBuf->Status))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Doesn't fit? */
|
|
Length = (ULONG)strlenW(Text) * sizeof(WCHAR);
|
|
if (OutBuf->FreeSize < Length + 1 && INF_SUCCESS(OutBuf->Status))
|
|
{
|
|
DPRINT("Out of free space. TotalSize %u FreeSize %u Length %u\n",
|
|
(UINT)OutBuf->TotalSize, (UINT)OutBuf->FreeSize, (UINT)Length);
|
|
/* Round up to next SIZE_INC */
|
|
NewSize = OutBuf->TotalSize +
|
|
(((Length + 1) - OutBuf->FreeSize + (SIZE_INC - 1)) /
|
|
SIZE_INC) * SIZE_INC;
|
|
DPRINT("NewSize %u\n", (UINT)NewSize);
|
|
NewBuf = MALLOC(NewSize);
|
|
/* Abort if failed */
|
|
if (NULL == NewBuf)
|
|
{
|
|
DPRINT1("MALLOC() failed\n");
|
|
OutBuf->Status = INF_STATUS_NO_MEMORY;
|
|
return;
|
|
}
|
|
|
|
/* Need to copy old contents? */
|
|
if (NULL != OutBuf->Buffer)
|
|
{
|
|
DPRINT("Copying %u bytes from old content\n",
|
|
(UINT)(OutBuf->TotalSize - OutBuf->FreeSize));
|
|
MEMCPY(NewBuf, OutBuf->Buffer, OutBuf->TotalSize - OutBuf->FreeSize);
|
|
OutBuf->Current = NewBuf + (OutBuf->Current - OutBuf->Buffer);
|
|
FREE(OutBuf->Buffer);
|
|
}
|
|
else
|
|
{
|
|
OutBuf->Current = NewBuf;
|
|
}
|
|
OutBuf->Buffer = NewBuf;
|
|
OutBuf->FreeSize += NewSize - OutBuf->TotalSize;
|
|
OutBuf->TotalSize = NewSize;
|
|
DPRINT("After reallocation TotalSize %u FreeSize %u\n",
|
|
(UINT)OutBuf->TotalSize, (UINT)OutBuf->FreeSize);
|
|
}
|
|
|
|
/* We're guaranteed to have enough room now. Copy char by char because of
|
|
possible "conversion" from Unicode to Ansi */
|
|
while (Length--)
|
|
{
|
|
*OutBuf->Current++ = *Text++;
|
|
OutBuf->FreeSize--;
|
|
}
|
|
*OutBuf->Current = '\0';
|
|
}
|
|
|
|
INFSTATUS
|
|
InfpBuildFileBuffer(PINFCACHE Cache,
|
|
PWCHAR *Buffer,
|
|
PULONG BufferSize)
|
|
{
|
|
OUTPUTBUFFER OutBuf;
|
|
PINFCACHESECTION CacheSection;
|
|
PINFCACHELINE CacheLine;
|
|
PINFCACHEFIELD CacheField;
|
|
PWCHAR p;
|
|
BOOLEAN NeedQuotes;
|
|
|
|
OutBuf.Buffer = NULL;
|
|
OutBuf.Current = NULL;
|
|
OutBuf.FreeSize = 0;
|
|
OutBuf.TotalSize = 0;
|
|
OutBuf.Status = INF_STATUS_SUCCESS;
|
|
|
|
/* Iterate through list of sections */
|
|
CacheSection = Cache->FirstSection;
|
|
while (CacheSection != NULL)
|
|
{
|
|
DPRINT("Processing section %S\n", CacheSection->Name);
|
|
if (CacheSection != Cache->FirstSection)
|
|
{
|
|
Output(&OutBuf, EOL);
|
|
}
|
|
Output(&OutBuf, L"[");
|
|
Output(&OutBuf, CacheSection->Name);
|
|
Output(&OutBuf, L"]");
|
|
Output(&OutBuf, EOL);
|
|
|
|
/* Iterate through list of lines */
|
|
CacheLine = CacheSection->FirstLine;
|
|
while (CacheLine != NULL)
|
|
{
|
|
if (NULL != CacheLine->Key)
|
|
{
|
|
DPRINT("Line with key %S\n", CacheLine->Key);
|
|
Output(&OutBuf, CacheLine->Key);
|
|
Output(&OutBuf, L" = ");
|
|
}
|
|
else
|
|
{
|
|
DPRINT("Line without key\n");
|
|
}
|
|
|
|
/* Iterate through list of lines */
|
|
CacheField = CacheLine->FirstField;
|
|
while (CacheField != NULL)
|
|
{
|
|
if (CacheField != CacheLine->FirstField)
|
|
{
|
|
Output(&OutBuf, L",");
|
|
}
|
|
p = CacheField->Data;
|
|
NeedQuotes = FALSE;
|
|
while (L'\0' != *p && ! NeedQuotes)
|
|
{
|
|
NeedQuotes = (BOOLEAN)(L',' == *p || L';' == *p ||
|
|
L'\\' == *p);
|
|
p++;
|
|
}
|
|
if (NeedQuotes)
|
|
{
|
|
Output(&OutBuf, L"\"");
|
|
Output(&OutBuf, CacheField->Data);
|
|
Output(&OutBuf, L"\"");
|
|
}
|
|
else
|
|
{
|
|
Output(&OutBuf, CacheField->Data);
|
|
}
|
|
|
|
/* Get the next field */
|
|
CacheField = CacheField->Next;
|
|
}
|
|
|
|
Output(&OutBuf, EOL);
|
|
/* Get the next line */
|
|
CacheLine = CacheLine->Next;
|
|
}
|
|
|
|
/* Get the next section */
|
|
CacheSection = CacheSection->Next;
|
|
}
|
|
|
|
if (INF_SUCCESS(OutBuf.Status))
|
|
{
|
|
*Buffer = OutBuf.Buffer;
|
|
*BufferSize = OutBuf.TotalSize - OutBuf.FreeSize;
|
|
}
|
|
else if (NULL != OutBuf.Buffer)
|
|
{
|
|
FREE(OutBuf.Buffer);
|
|
}
|
|
|
|
return INF_STATUS_SUCCESS;
|
|
}
|
|
|
|
INFSTATUS
|
|
InfpFindOrAddSection(PINFCACHE Cache,
|
|
PCWSTR Section,
|
|
PINFCONTEXT *Context)
|
|
{
|
|
DPRINT("InfpFindOrAddSection section %S\n", Section);
|
|
|
|
*Context = MALLOC(sizeof(INFCONTEXT));
|
|
if (NULL == *Context)
|
|
{
|
|
DPRINT1("MALLOC() failed\n");
|
|
return INF_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
(*Context)->Inf = Cache;
|
|
(*Context)->Section = InfpFindSection(Cache, Section);
|
|
(*Context)->Line = NULL;
|
|
if (NULL == (*Context)->Section)
|
|
{
|
|
DPRINT("Section not found, creating it\n");
|
|
(*Context)->Section = InfpAddSection(Cache, Section);
|
|
if (NULL == (*Context)->Section)
|
|
{
|
|
DPRINT("Failed to create section\n");
|
|
FREE(*Context);
|
|
return INF_STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
|
|
return INF_STATUS_SUCCESS;
|
|
}
|
|
|
|
INFSTATUS
|
|
InfpAddLineWithKey(PINFCONTEXT Context, PCWSTR Key)
|
|
{
|
|
if (NULL == Context)
|
|
{
|
|
DPRINT1("Invalid parameter\n");
|
|
return INF_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Context->Line = InfpAddLine(Context->Section);
|
|
if (NULL == Context->Line)
|
|
{
|
|
DPRINT("Failed to create line\n");
|
|
return INF_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
if (NULL != Key && NULL == InfpAddKeyToLine(Context->Line, Key))
|
|
{
|
|
DPRINT("Failed to add key\n");
|
|
return INF_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
return INF_STATUS_SUCCESS;
|
|
}
|
|
|
|
INFSTATUS
|
|
InfpAddField(PINFCONTEXT Context, PCWSTR Data)
|
|
{
|
|
if (NULL == Context || NULL == Context->Line)
|
|
{
|
|
DPRINT1("Invalid parameter\n");
|
|
return INF_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (NULL == InfpAddFieldToLine(Context->Line, Data))
|
|
{
|
|
DPRINT("Failed to add field\n");
|
|
return INF_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
return INF_STATUS_SUCCESS;
|
|
}
|
|
|
|
/* EOF */
|