* Change newinflib to inflib.
[reactos.git] / reactos / lib / inflib / infrosgen.c
diff --git a/reactos/lib/inflib/infrosgen.c b/reactos/lib/inflib/infrosgen.c
new file mode 100644 (file)
index 0000000..b23403b
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * PROJECT:    .inf file parser
+ * LICENSE:    GPL - See COPYING in the top level directory
+ * PROGRAMMER: Royce Mitchell III
+ *             Eric Kohl
+ *             Ge van Geldorp <gvg@reactos.org>
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "inflib.h"
+#include "infros.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* PRIVATE FUNCTIONS ********************************************************/
+
+static int InfpHeapRefCount;
+
+static VOID
+CheckHeap()
+{
+  if (NULL == InfpHeap)
+    {
+      InfpHeap = RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL);
+    }
+  if (0 <= InfpHeapRefCount)
+    {
+      InfpHeapRefCount++;
+    }
+}
+
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+PVOID InfpHeap;
+
+VOID
+InfSetHeap(PVOID Heap)
+{
+  if (NULL == InfpHeap)
+    {
+      InfpHeap = Heap;
+      InfpHeapRefCount = -1;
+    }
+}
+
+
+NTSTATUS
+InfOpenBufferedFile(PHINF InfHandle,
+                    PVOID Buffer,
+                    ULONG BufferSize,
+                    LANGID LanguageId,
+                    PULONG ErrorLine)
+{
+  INFSTATUS Status;
+  PINFCACHE Cache;
+  PCHAR FileBuffer;
+  ULONG FileBufferSize;
+
+  CheckHeap();
+
+  *InfHandle = NULL;
+  *ErrorLine = (ULONG)-1;
+
+  /* Allocate file buffer */
+  FileBufferSize = BufferSize + 2;
+  FileBuffer = MALLOC(FileBufferSize);
+  if (FileBuffer == NULL)
+    {
+      DPRINT1("MALLOC() failed\n");
+      return(INF_STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  MEMCPY(FileBuffer, Buffer, BufferSize);
+
+  /* Append string terminator */
+  FileBuffer[BufferSize] = 0;
+  FileBuffer[BufferSize + 1] = 0;
+
+  /* Allocate infcache header */
+  Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
+  if (Cache == NULL)
+    {
+      DPRINT("MALLOC() failed\n");
+      FREE(FileBuffer);
+      return(INF_STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  /* Initialize inicache header */
+  ZEROMEMORY(Cache,
+             sizeof(INFCACHE));
+
+    Cache->LanguageId = LanguageId;
+
+    /* Parse the inf buffer */
+    if (!RtlIsTextUnicode(FileBuffer, FileBufferSize, NULL))
+    {
+//        static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
+        WCHAR *new_buff;
+//        UINT codepage = CP_ACP;
+        UINT offset = 0;
+
+//        if (BufferSize > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
+//        {
+//            codepage = CP_UTF8;
+//            offset = sizeof(utf8_bom);
+//        }
+
+        new_buff = MALLOC(FileBufferSize * sizeof(WCHAR));
+        if (new_buff != NULL)
+        {
+            ULONG len;
+            Status = RtlMultiByteToUnicodeN(new_buff,
+                                            FileBufferSize * sizeof(WCHAR),
+                                            &len,
+                                            (char *)FileBuffer + offset,
+                                            FileBufferSize - offset);
+
+            Status = InfpParseBuffer(Cache,
+                                     new_buff,
+                                     new_buff + len / sizeof(WCHAR),
+                                     ErrorLine);
+            FREE(new_buff);
+        }
+        else
+            Status = INF_STATUS_INSUFFICIENT_RESOURCES;
+    }
+    else
+    {
+        WCHAR *new_buff = (WCHAR *)FileBuffer;
+        /* UCS-16 files should start with the Unicode BOM; we should skip it */
+        if (*new_buff == 0xfeff)
+        {
+            new_buff++;
+            FileBufferSize -= sizeof(WCHAR);
+        }
+        Status = InfpParseBuffer(Cache,
+                                 new_buff,
+                                 (WCHAR*)((char*)new_buff + FileBufferSize),
+                                 ErrorLine);
+    }
+
+  if (!INF_SUCCESS(Status))
+    {
+      FREE(Cache);
+      Cache = NULL;
+    }
+
+  /* Free file buffer */
+  FREE(FileBuffer);
+
+  *InfHandle = (HINF)Cache;
+
+  return(Status);
+}
+
+
+NTSTATUS
+InfOpenFile(PHINF InfHandle,
+           PUNICODE_STRING FileName,
+           LANGID LanguageId,
+           PULONG ErrorLine)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  FILE_STANDARD_INFORMATION FileInfo;
+  IO_STATUS_BLOCK IoStatusBlock;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+  PCHAR FileBuffer;
+  ULONG FileLength;
+  ULONG FileBufferLength;
+  LARGE_INTEGER FileOffset;
+  PINFCACHE Cache;
+
+  CheckHeap();
+
+  *InfHandle = NULL;
+  *ErrorLine = (ULONG)-1;
+
+  /* Open the inf 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 (!INF_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 (!INF_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 */
+  FileBufferLength = FileLength + 2;
+  FileBuffer = MALLOC(FileBufferLength);
+  if (FileBuffer == NULL)
+    {
+      DPRINT1("MALLOC() failed\n");
+      NtClose(FileHandle);
+      return(INF_STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  /* Read file */
+  FileOffset.QuadPart = 0ULL;
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     FileBuffer,
+                     FileLength,
+                     &FileOffset,
+                     NULL);
+
+  /* Append string terminator */
+  FileBuffer[FileLength] = 0;
+  FileBuffer[FileLength + 1] = 0;
+
+  NtClose(FileHandle);
+
+  if (!INF_SUCCESS(Status))
+    {
+      DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+      FREE(FileBuffer);
+      return(Status);
+    }
+
+  /* Allocate infcache header */
+  Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
+  if (Cache == NULL)
+    {
+      DPRINT("MALLOC() failed\n");
+      FREE(FileBuffer);
+      return(INF_STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  /* Initialize inicache header */
+  ZEROMEMORY(Cache,
+             sizeof(INFCACHE));
+
+    Cache->LanguageId = LanguageId;
+
+    /* Parse the inf buffer */
+    if (!RtlIsTextUnicode(FileBuffer, FileBufferLength, NULL))
+    {
+//        static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
+        WCHAR *new_buff;
+//        UINT codepage = CP_ACP;
+        UINT offset = 0;
+
+//        if (FileLength > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
+//        {
+//            codepage = CP_UTF8;
+//            offset = sizeof(utf8_bom);
+//        }
+
+        new_buff = MALLOC(FileBufferLength * sizeof(WCHAR));
+        if (new_buff != NULL)
+        {
+            ULONG len;
+            Status = RtlMultiByteToUnicodeN(new_buff,
+                                            FileBufferLength * sizeof(WCHAR),
+                                            &len,
+                                            (char *)FileBuffer + offset,
+                                            FileBufferLength - offset);
+
+            Status = InfpParseBuffer(Cache,
+                                     new_buff,
+                                     new_buff + len / sizeof(WCHAR),
+                                     ErrorLine);
+            FREE(new_buff);
+        }
+        else
+            Status = INF_STATUS_INSUFFICIENT_RESOURCES;
+    }
+    else
+    {
+        WCHAR *new_buff = (WCHAR *)FileBuffer;
+        /* UCS-16 files should start with the Unicode BOM; we should skip it */
+        if (*new_buff == 0xfeff)
+        {
+            new_buff++;
+            FileBufferLength -= sizeof(WCHAR);
+        }
+        Status = InfpParseBuffer(Cache,
+                                 new_buff,
+                                 (WCHAR*)((char*)new_buff + FileBufferLength),
+                                 ErrorLine);
+    }
+
+  if (!INF_SUCCESS(Status))
+    {
+      FREE(Cache);
+      Cache = NULL;
+    }
+
+  /* Free file buffer */
+  FREE(FileBuffer);
+
+  *InfHandle = (HINF)Cache;
+
+  return(Status);
+}
+
+
+VOID
+InfCloseFile(HINF InfHandle)
+{
+  PINFCACHE Cache;
+
+  Cache = (PINFCACHE)InfHandle;
+
+  if (Cache == NULL)
+    {
+      return;
+    }
+
+  while (Cache->FirstSection != NULL)
+    {
+      Cache->FirstSection = InfpFreeSection(Cache->FirstSection);
+    }
+  Cache->LastSection = NULL;
+
+  FREE(Cache);
+
+  if (0 < InfpHeapRefCount)
+    {
+      InfpHeapRefCount--;
+      if (0 == InfpHeapRefCount)
+        {
+          RtlDestroyHeap(InfpHeap);
+          InfpHeap = NULL;
+        }
+    }
+}
+
+
+/* EOF */