2 * PROJECT: .inf file parser
3 * LICENSE: GPL - See COPYING in the top level directory
4 * COPYRIGHT: Copyright 2005 Ge van Geldorp <gvg@reactos.org>
7 /* INCLUDES *****************************************************************/
17 typedef struct _OUTPUTBUFFER
24 } OUTPUTBUFFER
, *POUTPUTBUFFER
;
27 Output(POUTPUTBUFFER OutBuf
, PCWSTR Text
)
34 if (! INF_SUCCESS(OutBuf
->Status
))
40 Length
= (ULONG
)strlenW(Text
) * sizeof(WCHAR
);
41 if (OutBuf
->FreeSize
< Length
+ 1 && INF_SUCCESS(OutBuf
->Status
))
43 DPRINT("Out of free space. TotalSize %u FreeSize %u Length %u\n",
44 (UINT
)OutBuf
->TotalSize
, (UINT
)OutBuf
->FreeSize
, (UINT
)Length
);
45 /* Round up to next SIZE_INC */
46 NewSize
= OutBuf
->TotalSize
+
47 (((Length
+ 1) - OutBuf
->FreeSize
+ (SIZE_INC
- 1)) /
49 DPRINT("NewSize %u\n", (UINT
)NewSize
);
50 NewBuf
= MALLOC(NewSize
);
54 DPRINT1("MALLOC() failed\n");
55 OutBuf
->Status
= INF_STATUS_NO_MEMORY
;
59 /* Need to copy old contents? */
60 if (NULL
!= OutBuf
->Buffer
)
62 DPRINT("Copying %u bytes from old content\n",
63 (UINT
)(OutBuf
->TotalSize
- OutBuf
->FreeSize
));
64 MEMCPY(NewBuf
, OutBuf
->Buffer
, OutBuf
->TotalSize
- OutBuf
->FreeSize
);
65 OutBuf
->Current
= NewBuf
+ (OutBuf
->Current
- OutBuf
->Buffer
);
70 OutBuf
->Current
= NewBuf
;
72 OutBuf
->Buffer
= NewBuf
;
73 OutBuf
->FreeSize
+= NewSize
- OutBuf
->TotalSize
;
74 OutBuf
->TotalSize
= NewSize
;
75 DPRINT("After reallocation TotalSize %u FreeSize %u\n",
76 (UINT
)OutBuf
->TotalSize
, (UINT
)OutBuf
->FreeSize
);
79 /* We're guaranteed to have enough room now. Copy char by char because of
80 possible "conversion" from Unicode to Ansi */
83 *OutBuf
->Current
++ = *Text
++;
86 *OutBuf
->Current
= '\0';
90 InfpBuildFileBuffer(PINFCACHE Cache
,
95 PINFCACHESECTION CacheSection
;
96 PINFCACHELINE CacheLine
;
97 PINFCACHEFIELD CacheField
;
101 OutBuf
.Buffer
= NULL
;
102 OutBuf
.Current
= NULL
;
104 OutBuf
.TotalSize
= 0;
105 OutBuf
.Status
= INF_STATUS_SUCCESS
;
107 /* Iterate through list of sections */
108 CacheSection
= Cache
->FirstSection
;
109 while (CacheSection
!= NULL
)
111 DPRINT("Processing section %S\n", CacheSection
->Name
);
112 if (CacheSection
!= Cache
->FirstSection
)
114 Output(&OutBuf
, EOL
);
116 Output(&OutBuf
, L
"[");
117 Output(&OutBuf
, CacheSection
->Name
);
118 Output(&OutBuf
, L
"]");
119 Output(&OutBuf
, EOL
);
121 /* Iterate through list of lines */
122 CacheLine
= CacheSection
->FirstLine
;
123 while (CacheLine
!= NULL
)
125 if (NULL
!= CacheLine
->Key
)
127 DPRINT("Line with key %S\n", CacheLine
->Key
);
128 Output(&OutBuf
, CacheLine
->Key
);
129 Output(&OutBuf
, L
" = ");
133 DPRINT("Line without key\n");
136 /* Iterate through list of lines */
137 CacheField
= CacheLine
->FirstField
;
138 while (CacheField
!= NULL
)
140 if (CacheField
!= CacheLine
->FirstField
)
142 Output(&OutBuf
, L
",");
144 p
= CacheField
->Data
;
146 while (L
'\0' != *p
&& ! NeedQuotes
)
148 NeedQuotes
= (BOOLEAN
)(L
',' == *p
|| L
';' == *p
||
154 Output(&OutBuf
, L
"\"");
155 Output(&OutBuf
, CacheField
->Data
);
156 Output(&OutBuf
, L
"\"");
160 Output(&OutBuf
, CacheField
->Data
);
163 /* Get the next field */
164 CacheField
= CacheField
->Next
;
167 Output(&OutBuf
, EOL
);
168 /* Get the next line */
169 CacheLine
= CacheLine
->Next
;
172 /* Get the next section */
173 CacheSection
= CacheSection
->Next
;
176 if (INF_SUCCESS(OutBuf
.Status
))
178 *Buffer
= OutBuf
.Buffer
;
179 *BufferSize
= OutBuf
.TotalSize
- OutBuf
.FreeSize
;
181 else if (NULL
!= OutBuf
.Buffer
)
186 return INF_STATUS_SUCCESS
;
190 InfpFindOrAddSection(PINFCACHE Cache
,
192 PINFCONTEXT
*Context
)
194 PINFCACHESECTION CacheSection
;
195 DPRINT("InfpFindOrAddSection section %S\n", Section
);
197 *Context
= MALLOC(sizeof(INFCONTEXT
));
198 if (NULL
== *Context
)
200 DPRINT1("MALLOC() failed\n");
201 return INF_STATUS_NO_MEMORY
;
204 (*Context
)->Inf
= Cache
;
205 (*Context
)->Line
= 0;
206 CacheSection
= InfpFindSection(Cache
, Section
);
207 if (NULL
== CacheSection
)
209 DPRINT("Section not found, creating it\n");
210 CacheSection
= InfpAddSection(Cache
, Section
);
211 if (NULL
== CacheSection
)
213 DPRINT("Failed to create section\n");
215 return INF_STATUS_NO_MEMORY
;
219 (*Context
)->Section
= CacheSection
->Id
;
220 return INF_STATUS_SUCCESS
;
224 InfpAddLineWithKey(PINFCONTEXT Context
, PCWSTR Key
)
226 PINFCACHESECTION Section
;
231 DPRINT1("Invalid parameter\n");
232 return INF_STATUS_INVALID_PARAMETER
;
235 Section
= InfpGetSectionForContext(Context
);
236 Line
= InfpAddLine(Section
);
239 DPRINT("Failed to create line\n");
240 return INF_STATUS_NO_MEMORY
;
242 Context
->Line
= Line
->Id
;
244 if (NULL
!= Key
&& NULL
== InfpAddKeyToLine(Line
, Key
))
246 DPRINT("Failed to add key\n");
247 return INF_STATUS_NO_MEMORY
;
250 return INF_STATUS_SUCCESS
;
254 InfpAddField(PINFCONTEXT Context
, PCWSTR Data
)
260 DPRINT1("Invalid parameter\n");
261 return INF_STATUS_INVALID_PARAMETER
;
264 Line
= InfpGetLineForContext(Context
);
265 if (NULL
== InfpAddFieldToLine(Line
, Data
))
267 DPRINT("Failed to add field\n");
268 return INF_STATUS_NO_MEMORY
;
271 return INF_STATUS_SUCCESS
;