- Factor out .inf handling code from usetup
[reactos.git] / reactos / lib / inflib / infrosgen.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: .inf file parser
4 * FILE: lib/inflib/infrosgen.c
5 * PURPOSE: General .inf routines for use in ReactOS
6 * PROGRAMMER: Royce Mitchell III
7 * Eric Kohl
8 * Ge van Geldorp
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include "inflib.h"
14 #include "infros.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* PRIVATE FUNCTIONS ********************************************************/
20
21 static int InfpHeapRefCount;
22
23 static VOID
24 CheckHeap()
25 {
26 if (NULL == InfpHeap)
27 {
28 InfpHeap = RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL);
29 }
30 if (0 <= InfpHeapRefCount)
31 {
32 InfpHeapRefCount++;
33 }
34 }
35
36
37 /* PUBLIC FUNCTIONS *********************************************************/
38
39 PVOID InfpHeap;
40
41 VOID
42 InfSetHeap(PVOID Heap)
43 {
44 if (NULL == InfpHeap)
45 {
46 InfpHeap = Heap;
47 InfpHeapRefCount = -1;
48 }
49 }
50
51
52 NTSTATUS
53 InfOpenBufferedFile(PHINF InfHandle,
54 PVOID Buffer,
55 ULONG BufferSize,
56 PULONG ErrorLine)
57 {
58 INFSTATUS Status;
59 PINFCACHE Cache;
60 PCHAR FileBuffer;
61
62 CheckHeap();
63
64 *InfHandle = NULL;
65 *ErrorLine = (ULONG)-1;
66
67 /* Allocate file buffer */
68 FileBuffer = MALLOC(BufferSize + 1);
69 if (FileBuffer == NULL)
70 {
71 DPRINT1("MALLOC() failed\n");
72 return(INF_STATUS_INSUFFICIENT_RESOURCES);
73 }
74
75 MEMCPY(FileBuffer, Buffer, BufferSize);
76
77 /* Append string terminator */
78 FileBuffer[BufferSize] = 0;
79
80 /* Allocate infcache header */
81 Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
82 if (Cache == NULL)
83 {
84 DPRINT("MALLOC() failed\n");
85 FREE(FileBuffer);
86 return(INF_STATUS_INSUFFICIENT_RESOURCES);
87 }
88
89 /* Initialize inicache header */
90 ZEROMEMORY(Cache,
91 sizeof(INFCACHE));
92
93 /* Parse the inf buffer */
94 Status = InfpParseBuffer (Cache,
95 FileBuffer,
96 FileBuffer + BufferSize,
97 ErrorLine);
98 if (!INF_SUCCESS(Status))
99 {
100 FREE(Cache);
101 Cache = NULL;
102 }
103
104 /* Free file buffer */
105 FREE(FileBuffer);
106
107 *InfHandle = (HINF)Cache;
108
109 return(Status);
110 }
111
112
113 NTSTATUS
114 InfOpenFile(PHINF InfHandle,
115 PUNICODE_STRING FileName,
116 PULONG ErrorLine)
117 {
118 OBJECT_ATTRIBUTES ObjectAttributes;
119 FILE_STANDARD_INFORMATION FileInfo;
120 IO_STATUS_BLOCK IoStatusBlock;
121 HANDLE FileHandle;
122 NTSTATUS Status;
123 PCHAR FileBuffer;
124 ULONG FileLength;
125 LARGE_INTEGER FileOffset;
126 PINFCACHE Cache;
127
128 CheckHeap();
129
130 *InfHandle = NULL;
131 *ErrorLine = (ULONG)-1;
132
133 /* Open the inf file */
134 InitializeObjectAttributes(&ObjectAttributes,
135 FileName,
136 0,
137 NULL,
138 NULL);
139
140 Status = NtOpenFile(&FileHandle,
141 GENERIC_READ | SYNCHRONIZE,
142 &ObjectAttributes,
143 &IoStatusBlock,
144 FILE_SHARE_READ,
145 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
146 if (!INF_SUCCESS(Status))
147 {
148 DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
149 return(Status);
150 }
151
152 DPRINT("NtOpenFile() successful\n");
153
154 /* Query file size */
155 Status = NtQueryInformationFile(FileHandle,
156 &IoStatusBlock,
157 &FileInfo,
158 sizeof(FILE_STANDARD_INFORMATION),
159 FileStandardInformation);
160 if (!INF_SUCCESS(Status))
161 {
162 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
163 NtClose(FileHandle);
164 return(Status);
165 }
166
167 FileLength = FileInfo.EndOfFile.u.LowPart;
168
169 DPRINT("File size: %lu\n", FileLength);
170
171 /* Allocate file buffer */
172 FileBuffer = MALLOC(FileLength + 1);
173 if (FileBuffer == NULL)
174 {
175 DPRINT1("MALLOC() failed\n");
176 NtClose(FileHandle);
177 return(INF_STATUS_INSUFFICIENT_RESOURCES);
178 }
179
180 /* Read file */
181 FileOffset.QuadPart = 0ULL;
182 Status = NtReadFile(FileHandle,
183 NULL,
184 NULL,
185 NULL,
186 &IoStatusBlock,
187 FileBuffer,
188 FileLength,
189 &FileOffset,
190 NULL);
191
192 /* Append string terminator */
193 FileBuffer[FileLength] = 0;
194
195 NtClose(FileHandle);
196
197 if (!INF_SUCCESS(Status))
198 {
199 DPRINT("NtReadFile() failed (Status %lx)\n", Status);
200 FREE(FileBuffer);
201 return(Status);
202 }
203
204 /* Allocate infcache header */
205 Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
206 if (Cache == NULL)
207 {
208 DPRINT("MALLOC() failed\n");
209 FREE(FileBuffer);
210 return(INF_STATUS_INSUFFICIENT_RESOURCES);
211 }
212
213 /* Initialize inicache header */
214 ZEROMEMORY(Cache,
215 sizeof(INFCACHE));
216
217 /* Parse the inf buffer */
218 Status = InfpParseBuffer (Cache,
219 FileBuffer,
220 FileBuffer + FileLength,
221 ErrorLine);
222 if (!INF_SUCCESS(Status))
223 {
224 FREE(Cache);
225 Cache = NULL;
226 }
227
228 /* Free file buffer */
229 FREE(FileBuffer);
230
231 *InfHandle = (HINF)Cache;
232
233 return(Status);
234 }
235
236
237 VOID
238 InfCloseFile(HINF InfHandle)
239 {
240 PINFCACHE Cache;
241
242 Cache = (PINFCACHE)InfHandle;
243
244 if (Cache == NULL)
245 {
246 return;
247 }
248
249 while (Cache->FirstSection != NULL)
250 {
251 Cache->FirstSection = InfpCacheFreeSection(Cache->FirstSection);
252 }
253 Cache->LastSection = NULL;
254
255 FREE(Cache);
256
257 if (0 < InfpHeapRefCount)
258 {
259 InfpHeapRefCount--;
260 if (0 == InfpHeapRefCount)
261 {
262 RtlDestroyHeap(InfpHeap);
263 InfpHeap = NULL;
264 }
265 }
266 }
267
268
269 /* EOF */