[MKHIVE/USETUP]
[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 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 */