mirror of
https://github.com/reactos/reactos.git
synced 2024-11-07 07:00:19 +00:00
c501d8112c
svn path=/branches/aicom-network-fixes/; revision=34994
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 _T("\r\n")
|
|
#define SIZE_INC 1024
|
|
|
|
typedef struct _OUTPUTBUFFER
|
|
{
|
|
PCHAR Buffer;
|
|
PCHAR Current;
|
|
ULONG TotalSize;
|
|
ULONG FreeSize;
|
|
INFSTATUS Status;
|
|
} OUTPUTBUFFER, *POUTPUTBUFFER;
|
|
|
|
static void
|
|
Output(POUTPUTBUFFER OutBuf, PCTSTR Text)
|
|
{
|
|
ULONG Length;
|
|
PCHAR NewBuf;
|
|
ULONG NewSize;
|
|
|
|
/* Skip mode? */
|
|
if (! INF_SUCCESS(OutBuf->Status))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Doesn't fit? */
|
|
Length = _tcslen(Text);
|
|
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++ = (char) *Text++;
|
|
OutBuf->FreeSize--;
|
|
}
|
|
*OutBuf->Current = '\0';
|
|
}
|
|
|
|
INFSTATUS
|
|
InfpBuildFileBuffer(PINFCACHE Cache,
|
|
PCHAR *Buffer,
|
|
PULONG BufferSize)
|
|
{
|
|
OUTPUTBUFFER OutBuf;
|
|
PINFCACHESECTION CacheSection;
|
|
PINFCACHELINE CacheLine;
|
|
PINFCACHEFIELD CacheField;
|
|
PTCHAR 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 " STRFMT "\n", CacheSection->Name);
|
|
if (CacheSection != Cache->FirstSection)
|
|
{
|
|
Output(&OutBuf, EOL);
|
|
}
|
|
Output(&OutBuf, _T("["));
|
|
Output(&OutBuf, CacheSection->Name);
|
|
Output(&OutBuf, _T("]"));
|
|
Output(&OutBuf, EOL);
|
|
|
|
/* Iterate through list of lines */
|
|
CacheLine = CacheSection->FirstLine;
|
|
while (CacheLine != NULL)
|
|
{
|
|
if (NULL != CacheLine->Key)
|
|
{
|
|
DPRINT("Line with key " STRFMT "\n", CacheLine->Key);
|
|
Output(&OutBuf, CacheLine->Key);
|
|
Output(&OutBuf, _T(" = "));
|
|
}
|
|
else
|
|
{
|
|
DPRINT("Line without key\n");
|
|
}
|
|
|
|
/* Iterate through list of lines */
|
|
CacheField = CacheLine->FirstField;
|
|
while (CacheField != NULL)
|
|
{
|
|
if (CacheField != CacheLine->FirstField)
|
|
{
|
|
Output(&OutBuf, _T(","));
|
|
}
|
|
p = CacheField->Data;
|
|
NeedQuotes = FALSE;
|
|
while (_T('\0') != *p && ! NeedQuotes)
|
|
{
|
|
NeedQuotes = _T(',') == *p || _T(';') == *p ||
|
|
_T('\\') == *p;
|
|
p++;
|
|
}
|
|
if (NeedQuotes)
|
|
{
|
|
Output(&OutBuf, _T("\""));
|
|
Output(&OutBuf, CacheField->Data);
|
|
Output(&OutBuf, _T("\""));
|
|
}
|
|
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,
|
|
PCTSTR Section,
|
|
PINFCONTEXT *Context)
|
|
{
|
|
DPRINT("InfpFindOrAddSection section " STRFMT "\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, PCTSTR 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, PCTSTR 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 */
|