[NEWINFLIB]
[reactos.git] / reactos / lib / newinflib / infrosgen.c
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()
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 LCID LocaleId,
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->LocaleId = LocaleId;
96
97 if (!RtlIsTextUnicode(FileBuffer, FileBufferSize, NULL))
98 {
99 // static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
100 WCHAR *new_buff;
101 // UINT codepage = CP_ACP;
102 UINT offset = 0;
103
104 // if (BufferSize > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
105 // {
106 // codepage = CP_UTF8;
107 // offset = sizeof(utf8_bom);
108 // }
109
110 new_buff = MALLOC(FileBufferSize * sizeof(WCHAR));
111 if (new_buff != NULL)
112 {
113 // DWORD len = MultiByteToWideChar( codepage, 0, (char *)FileBuffer + offset,
114 // FileBufferSize - offset, new_buff, FileBufferSize);
115
116 ULONG len;
117 Status = RtlMultiByteToUnicodeN(new_buff,
118 FileBufferSize * sizeof(WCHAR),
119 &len,
120 (char *)FileBuffer + offset,
121 FileBufferSize - offset);
122
123 Status = InfpParseBuffer(Cache,
124 new_buff,
125 new_buff + len,
126 ErrorLine);
127 FREE(new_buff);
128 }
129 else
130 Status = INF_STATUS_INSUFFICIENT_RESOURCES;
131 }
132 else
133 {
134 WCHAR *new_buff = (WCHAR *)FileBuffer;
135 /* UCS-16 files should start with the Unicode BOM; we should skip it */
136 if (*new_buff == 0xfeff)
137 {
138 new_buff++;
139 FileBufferSize -= sizeof(WCHAR);
140 }
141 Status = InfpParseBuffer(Cache,
142 new_buff,
143 (WCHAR*)((char*)new_buff + FileBufferSize),
144 ErrorLine);
145 }
146
147 if (!INF_SUCCESS(Status))
148 {
149 FREE(Cache);
150 Cache = NULL;
151 }
152
153 /* Free file buffer */
154 FREE(FileBuffer);
155
156 *InfHandle = (HINF)Cache;
157
158 return(Status);
159 }
160
161
162 NTSTATUS
163 InfOpenFile(PHINF InfHandle,
164 PUNICODE_STRING FileName,
165 LCID LocaleId,
166 PULONG ErrorLine)
167 {
168 OBJECT_ATTRIBUTES ObjectAttributes;
169 FILE_STANDARD_INFORMATION FileInfo;
170 IO_STATUS_BLOCK IoStatusBlock;
171 HANDLE FileHandle;
172 NTSTATUS Status;
173 PCHAR FileBuffer;
174 ULONG FileLength;
175 ULONG FileBufferLength;
176 LARGE_INTEGER FileOffset;
177 PINFCACHE Cache;
178
179 CheckHeap();
180
181 *InfHandle = NULL;
182 *ErrorLine = (ULONG)-1;
183
184 /* Open the inf file */
185 InitializeObjectAttributes(&ObjectAttributes,
186 FileName,
187 0,
188 NULL,
189 NULL);
190
191 Status = NtOpenFile(&FileHandle,
192 GENERIC_READ | SYNCHRONIZE,
193 &ObjectAttributes,
194 &IoStatusBlock,
195 FILE_SHARE_READ,
196 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
197 if (!INF_SUCCESS(Status))
198 {
199 DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
200 return(Status);
201 }
202
203 DPRINT("NtOpenFile() successful\n");
204
205 /* Query file size */
206 Status = NtQueryInformationFile(FileHandle,
207 &IoStatusBlock,
208 &FileInfo,
209 sizeof(FILE_STANDARD_INFORMATION),
210 FileStandardInformation);
211 if (!INF_SUCCESS(Status))
212 {
213 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
214 NtClose(FileHandle);
215 return(Status);
216 }
217
218 FileLength = FileInfo.EndOfFile.u.LowPart;
219
220 DPRINT("File size: %lu\n", FileLength);
221
222 /* Allocate file buffer */
223 FileBufferLength = FileLength + 2;
224 FileBuffer = MALLOC(FileBufferLength);
225 if (FileBuffer == NULL)
226 {
227 DPRINT1("MALLOC() failed\n");
228 NtClose(FileHandle);
229 return(INF_STATUS_INSUFFICIENT_RESOURCES);
230 }
231
232 /* Read file */
233 FileOffset.QuadPart = 0ULL;
234 Status = NtReadFile(FileHandle,
235 NULL,
236 NULL,
237 NULL,
238 &IoStatusBlock,
239 FileBuffer,
240 FileLength,
241 &FileOffset,
242 NULL);
243
244 /* Append string terminator */
245 FileBuffer[FileLength] = 0;
246 FileBuffer[FileLength + 1] = 0;
247
248 NtClose(FileHandle);
249
250 if (!INF_SUCCESS(Status))
251 {
252 DPRINT("NtReadFile() failed (Status %lx)\n", Status);
253 FREE(FileBuffer);
254 return(Status);
255 }
256
257 /* Allocate infcache header */
258 Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
259 if (Cache == NULL)
260 {
261 DPRINT("MALLOC() failed\n");
262 FREE(FileBuffer);
263 return(INF_STATUS_INSUFFICIENT_RESOURCES);
264 }
265
266 /* Initialize inicache header */
267 ZEROMEMORY(Cache,
268 sizeof(INFCACHE));
269
270 Cache->LocaleId = LocaleId;
271
272 /* Parse the inf buffer */
273 if (!RtlIsTextUnicode(FileBuffer, FileBufferLength, NULL))
274 {
275 // static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
276 WCHAR *new_buff;
277 // UINT codepage = CP_ACP;
278 UINT offset = 0;
279
280 // if (FileLength > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
281 // {
282 // codepage = CP_UTF8;
283 // offset = sizeof(utf8_bom);
284 // }
285
286 new_buff = MALLOC(FileBufferLength * sizeof(WCHAR));
287 if (new_buff != NULL)
288 {
289 // DWORD len = MultiByteToWideChar( codepage, 0, (char *)FileBuffer + offset,
290 // FileLength - offset, new_buff, FileLength);
291
292 ULONG len;
293 Status = RtlMultiByteToUnicodeN(new_buff,
294 FileBufferLength * sizeof(WCHAR),
295 &len,
296 (char *)FileBuffer + offset,
297 FileBufferLength - offset);
298
299 Status = InfpParseBuffer(Cache,
300 new_buff,
301 new_buff + len,
302 ErrorLine);
303 FREE(new_buff);
304 }
305 else
306 Status = INF_STATUS_INSUFFICIENT_RESOURCES;
307 }
308 else
309 {
310 WCHAR *new_buff = (WCHAR *)FileBuffer;
311 /* UCS-16 files should start with the Unicode BOM; we should skip it */
312 if (*new_buff == 0xfeff)
313 {
314 new_buff++;
315 FileBufferLength -= sizeof(WCHAR);
316 }
317 Status = InfpParseBuffer(Cache,
318 new_buff,
319 (WCHAR*)((char*)new_buff + FileBufferLength),
320 ErrorLine);
321 }
322
323 if (!INF_SUCCESS(Status))
324 {
325 FREE(Cache);
326 Cache = NULL;
327 }
328
329 /* Free file buffer */
330 FREE(FileBuffer);
331
332 *InfHandle = (HINF)Cache;
333
334 return(Status);
335 }
336
337
338 VOID
339 InfCloseFile(HINF InfHandle)
340 {
341 PINFCACHE Cache;
342
343 Cache = (PINFCACHE)InfHandle;
344
345 if (Cache == NULL)
346 {
347 return;
348 }
349
350 while (Cache->FirstSection != NULL)
351 {
352 Cache->FirstSection = InfpFreeSection(Cache->FirstSection);
353 }
354 Cache->LastSection = NULL;
355
356 FREE(Cache);
357
358 if (0 < InfpHeapRefCount)
359 {
360 InfpHeapRefCount--;
361 if (0 == InfpHeapRefCount)
362 {
363 RtlDestroyHeap(InfpHeap);
364 InfpHeap = NULL;
365 }
366 }
367 }
368
369
370 /* EOF */