xref: /reactos/sdk/lib/inflib/infrosgen.c (revision 40462c92)
1 /*
2  * PROJECT:    .inf file parser
3  * LICENSE:    GPL - See COPYING in the top level directory
4  * PROGRAMMER: Royce Mitchell III
5  *             Eric Kohl
6  *             Ge van Geldorp <gvg@reactos.org>
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include "inflib.h"
12 #include "infros.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* PRIVATE FUNCTIONS ********************************************************/
18 
19 static int InfpHeapRefCount;
20 
21 static VOID
22 CheckHeap(VOID)
23 {
24   if (NULL == InfpHeap)
25     {
26       InfpHeap = RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL);
27     }
28   if (0 <= InfpHeapRefCount)
29     {
30       InfpHeapRefCount++;
31     }
32 }
33 
34 
35 /* PUBLIC FUNCTIONS *********************************************************/
36 
37 PVOID InfpHeap;
38 
39 VOID
40 InfSetHeap(PVOID Heap)
41 {
42   if (NULL == InfpHeap)
43     {
44       InfpHeap = Heap;
45       InfpHeapRefCount = -1;
46     }
47 }
48 
49 
50 NTSTATUS
51 InfOpenBufferedFile(PHINF InfHandle,
52                     PVOID Buffer,
53                     ULONG BufferSize,
54                     LANGID LanguageId,
55                     PULONG ErrorLine)
56 {
57   INFSTATUS Status;
58   PINFCACHE Cache;
59   PCHAR FileBuffer;
60   ULONG FileBufferSize;
61 
62   CheckHeap();
63 
64   *InfHandle = NULL;
65   *ErrorLine = (ULONG)-1;
66 
67   /* Allocate file buffer */
68   FileBufferSize = BufferSize + 2;
69   FileBuffer = MALLOC(FileBufferSize);
70   if (FileBuffer == NULL)
71     {
72       DPRINT1("MALLOC() failed\n");
73       return(INF_STATUS_INSUFFICIENT_RESOURCES);
74     }
75 
76   MEMCPY(FileBuffer, Buffer, BufferSize);
77 
78   /* Append string terminator */
79   FileBuffer[BufferSize] = 0;
80   FileBuffer[BufferSize + 1] = 0;
81 
82   /* Allocate infcache header */
83   Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
84   if (Cache == NULL)
85     {
86       DPRINT("MALLOC() failed\n");
87       FREE(FileBuffer);
88       return(INF_STATUS_INSUFFICIENT_RESOURCES);
89     }
90 
91   /* Initialize inicache header */
92   ZEROMEMORY(Cache,
93              sizeof(INFCACHE));
94 
95     Cache->LanguageId = LanguageId;
96 
97     /* Parse the inf buffer */
98     if (!RtlIsTextUnicode(FileBuffer, FileBufferSize, NULL))
99     {
100 //        static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
101         WCHAR *new_buff;
102 //        UINT codepage = CP_ACP;
103         UINT offset = 0;
104 
105 //        if (BufferSize > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
106 //        {
107 //            codepage = CP_UTF8;
108 //            offset = sizeof(utf8_bom);
109 //        }
110 
111         new_buff = MALLOC(FileBufferSize * sizeof(WCHAR));
112         if (new_buff != NULL)
113         {
114             ULONG len;
115             Status = RtlMultiByteToUnicodeN(new_buff,
116                                             FileBufferSize * sizeof(WCHAR),
117                                             &len,
118                                             (char *)FileBuffer + offset,
119                                             FileBufferSize - offset);
120 
121             Status = InfpParseBuffer(Cache,
122                                      new_buff,
123                                      new_buff + len / sizeof(WCHAR),
124                                      ErrorLine);
125             FREE(new_buff);
126         }
127         else
128             Status = INF_STATUS_INSUFFICIENT_RESOURCES;
129     }
130     else
131     {
132         WCHAR *new_buff = (WCHAR *)FileBuffer;
133         /* UCS-16 files should start with the Unicode BOM; we should skip it */
134         if (*new_buff == 0xfeff)
135         {
136             new_buff++;
137             FileBufferSize -= sizeof(WCHAR);
138         }
139         Status = InfpParseBuffer(Cache,
140                                  new_buff,
141                                  (WCHAR*)((char*)new_buff + FileBufferSize),
142                                  ErrorLine);
143     }
144 
145   if (!INF_SUCCESS(Status))
146     {
147       FREE(Cache);
148       Cache = NULL;
149     }
150 
151   /* Free file buffer */
152   FREE(FileBuffer);
153 
154   *InfHandle = (HINF)Cache;
155 
156   return(Status);
157 }
158 
159 
160 NTSTATUS
161 InfOpenFile(PHINF InfHandle,
162 	    PUNICODE_STRING FileName,
163 	    LANGID LanguageId,
164 	    PULONG ErrorLine)
165 {
166   OBJECT_ATTRIBUTES ObjectAttributes;
167   FILE_STANDARD_INFORMATION FileInfo;
168   IO_STATUS_BLOCK IoStatusBlock;
169   HANDLE FileHandle;
170   NTSTATUS Status;
171   PCHAR FileBuffer;
172   ULONG FileLength;
173   ULONG FileBufferLength;
174   LARGE_INTEGER FileOffset;
175   PINFCACHE Cache;
176 
177   CheckHeap();
178 
179   *InfHandle = NULL;
180   *ErrorLine = (ULONG)-1;
181 
182   /* Open the inf file */
183   InitializeObjectAttributes(&ObjectAttributes,
184 			     FileName,
185 			     0,
186 			     NULL,
187 			     NULL);
188 
189   Status = NtOpenFile(&FileHandle,
190 		      GENERIC_READ | SYNCHRONIZE,
191 		      &ObjectAttributes,
192 		      &IoStatusBlock,
193 		      FILE_SHARE_READ,
194 		      FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
195   if (!INF_SUCCESS(Status))
196     {
197       DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
198       return(Status);
199     }
200 
201   DPRINT("NtOpenFile() successful\n");
202 
203   /* Query file size */
204   Status = NtQueryInformationFile(FileHandle,
205 				  &IoStatusBlock,
206 				  &FileInfo,
207 				  sizeof(FILE_STANDARD_INFORMATION),
208 				  FileStandardInformation);
209   if (!INF_SUCCESS(Status))
210     {
211       DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
212       NtClose(FileHandle);
213       return(Status);
214     }
215 
216   FileLength = FileInfo.EndOfFile.u.LowPart;
217 
218   DPRINT("File size: %lu\n", FileLength);
219 
220   /* Allocate file buffer */
221   FileBufferLength = FileLength + 2;
222   FileBuffer = MALLOC(FileBufferLength);
223   if (FileBuffer == NULL)
224     {
225       DPRINT1("MALLOC() failed\n");
226       NtClose(FileHandle);
227       return(INF_STATUS_INSUFFICIENT_RESOURCES);
228     }
229 
230   /* Read file */
231   FileOffset.QuadPart = 0ULL;
232   Status = NtReadFile(FileHandle,
233 		      NULL,
234 		      NULL,
235 		      NULL,
236 		      &IoStatusBlock,
237 		      FileBuffer,
238 		      FileLength,
239 		      &FileOffset,
240 		      NULL);
241 
242   /* Append string terminator */
243   FileBuffer[FileLength] = 0;
244   FileBuffer[FileLength + 1] = 0;
245 
246   NtClose(FileHandle);
247 
248   if (!INF_SUCCESS(Status))
249     {
250       DPRINT("NtReadFile() failed (Status %lx)\n", Status);
251       FREE(FileBuffer);
252       return(Status);
253     }
254 
255   /* Allocate infcache header */
256   Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
257   if (Cache == NULL)
258     {
259       DPRINT("MALLOC() failed\n");
260       FREE(FileBuffer);
261       return(INF_STATUS_INSUFFICIENT_RESOURCES);
262     }
263 
264   /* Initialize inicache header */
265   ZEROMEMORY(Cache,
266              sizeof(INFCACHE));
267 
268     Cache->LanguageId = LanguageId;
269 
270     /* Parse the inf buffer */
271     if (!RtlIsTextUnicode(FileBuffer, FileBufferLength, NULL))
272     {
273 //        static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
274         WCHAR *new_buff;
275 //        UINT codepage = CP_ACP;
276         UINT offset = 0;
277 
278 //        if (FileLength > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
279 //        {
280 //            codepage = CP_UTF8;
281 //            offset = sizeof(utf8_bom);
282 //        }
283 
284         new_buff = MALLOC(FileBufferLength * sizeof(WCHAR));
285         if (new_buff != NULL)
286         {
287             ULONG len;
288             Status = RtlMultiByteToUnicodeN(new_buff,
289                                             FileBufferLength * sizeof(WCHAR),
290                                             &len,
291                                             (char *)FileBuffer + offset,
292                                             FileBufferLength - offset);
293 
294             Status = InfpParseBuffer(Cache,
295                                      new_buff,
296                                      new_buff + len / sizeof(WCHAR),
297                                      ErrorLine);
298             FREE(new_buff);
299         }
300         else
301             Status = INF_STATUS_INSUFFICIENT_RESOURCES;
302     }
303     else
304     {
305         WCHAR *new_buff = (WCHAR *)FileBuffer;
306         /* UCS-16 files should start with the Unicode BOM; we should skip it */
307         if (*new_buff == 0xfeff)
308         {
309             new_buff++;
310             FileBufferLength -= sizeof(WCHAR);
311         }
312         Status = InfpParseBuffer(Cache,
313                                  new_buff,
314                                  (WCHAR*)((char*)new_buff + FileBufferLength),
315                                  ErrorLine);
316     }
317 
318   if (!INF_SUCCESS(Status))
319     {
320       FREE(Cache);
321       Cache = NULL;
322     }
323 
324   /* Free file buffer */
325   FREE(FileBuffer);
326 
327   *InfHandle = (HINF)Cache;
328 
329   return(Status);
330 }
331 
332 
333 VOID
334 InfCloseFile(HINF InfHandle)
335 {
336   PINFCACHE Cache;
337 
338   Cache = (PINFCACHE)InfHandle;
339 
340   if (Cache == NULL)
341     {
342       return;
343     }
344 
345   while (Cache->FirstSection != NULL)
346     {
347       Cache->FirstSection = InfpFreeSection(Cache->FirstSection);
348     }
349   Cache->LastSection = NULL;
350 
351   FREE(Cache);
352 
353   if (0 < InfpHeapRefCount)
354     {
355       InfpHeapRefCount--;
356       if (0 == InfpHeapRefCount)
357         {
358           RtlDestroyHeap(InfpHeap);
359           InfpHeap = NULL;
360         }
361     }
362 }
363 
364 
365 /* EOF */
366