fa231e8518dba9a93142f83033548fd6ada6d1f0
[reactos.git] / boot / freeldr / freeldr / lib / inifile / inifile.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <freeldr.h>
21 #include <debug.h>
22
23 DBG_DEFAULT_CHANNEL(INIFILE);
24
25 BOOLEAN IniOpenSection(PCSTR SectionName, ULONG_PTR* SectionId)
26 {
27 PINI_SECTION Section;
28
29 TRACE("IniOpenSection() SectionName = %s\n", SectionName);
30
31 // Loop through each section and find the one they want
32 Section = CONTAINING_RECORD(IniFileSectionListHead.Flink, INI_SECTION, ListEntry);
33 while (&Section->ListEntry != &IniFileSectionListHead)
34 {
35 // Compare against the section name
36 if (_stricmp(SectionName, Section->SectionName) == 0)
37 {
38 // We found it
39 if (SectionId)
40 *SectionId = (ULONG_PTR)Section;
41 TRACE("IniOpenSection() Found it! SectionId = 0x%x\n", SectionId);
42 return TRUE;
43 }
44
45 // Get the next section in the list
46 Section = CONTAINING_RECORD(Section->ListEntry.Flink, INI_SECTION, ListEntry);
47 }
48
49 TRACE("IniOpenSection() Section not found.\n");
50
51 return FALSE;
52 }
53
54 ULONG IniGetNumSectionItems(ULONG_PTR SectionId)
55 {
56 PINI_SECTION Section = (PINI_SECTION)SectionId;
57
58 TRACE("IniGetNumSectionItems() SectionId = 0x%x\n", SectionId);
59 TRACE("IniGetNumSectionItems() Item count = %d\n", Section->SectionItemCount);
60
61 return Section->SectionItemCount;
62 }
63
64 PINI_SECTION_ITEM IniGetSettingByNumber(ULONG_PTR SectionId, ULONG SettingNumber)
65 {
66 PINI_SECTION Section = (PINI_SECTION)SectionId;
67 PINI_SECTION_ITEM SectionItem;
68
69 // Loop through each section item and find the one they want
70 SectionItem = CONTAINING_RECORD(Section->SectionItemList.Flink, INI_SECTION_ITEM, ListEntry);
71 while (&SectionItem->ListEntry != &Section->SectionItemList)
72 {
73 // Check to see if this is the setting they want
74 if (SettingNumber == 0)
75 {
76 return SectionItem;
77 }
78
79 // Nope, keep going
80 SettingNumber--;
81
82 // Get the next section item in the list
83 SectionItem = CONTAINING_RECORD(SectionItem->ListEntry.Flink, INI_SECTION_ITEM, ListEntry);
84 }
85 return NULL;
86 }
87
88 ULONG IniGetSectionSettingNameSize(ULONG_PTR SectionId, ULONG SettingIndex)
89 {
90 PINI_SECTION_ITEM SectionItem;
91
92 // Retrieve requested setting
93 SectionItem = IniGetSettingByNumber(SectionId, SettingIndex);
94 if (!SectionItem)
95 return 0;
96
97 // Return the size of the string plus 1 for the null-terminator
98 return (ULONG)(strlen(SectionItem->ItemName) + 1);
99 }
100
101 ULONG IniGetSectionSettingValueSize(ULONG_PTR SectionId, ULONG SettingIndex)
102 {
103 PINI_SECTION_ITEM SectionItem;
104
105 // Retrieve requested setting
106 SectionItem = IniGetSettingByNumber(SectionId, SettingIndex);
107 if (!SectionItem)
108 return 0;
109
110 // Return the size of the string plus 1 for the null-terminator
111 return (ULONG)(strlen(SectionItem->ItemValue) + 1);
112 }
113
114 BOOLEAN IniReadSettingByNumber(ULONG_PTR SectionId, ULONG SettingNumber, PCHAR SettingName, ULONG NameSize, PCHAR SettingValue, ULONG ValueSize)
115 {
116 PINI_SECTION_ITEM SectionItem;
117 TRACE(".001 NameSize = %d ValueSize = %d\n", NameSize, ValueSize);
118
119 TRACE("IniReadSettingByNumber() SectionId = 0x%x\n", SectionId);
120
121 // Retrieve requested setting
122 SectionItem = IniGetSettingByNumber(SectionId, SettingNumber);
123 if (!SectionItem)
124 {
125 TRACE("IniReadSettingByNumber() Setting number %d not found.\n", SettingNumber);
126 return FALSE;
127 }
128
129 TRACE("IniReadSettingByNumber() Setting number %d found.\n", SettingNumber);
130 TRACE("IniReadSettingByNumber() Setting name = %s\n", SectionItem->ItemName);
131 TRACE("IniReadSettingByNumber() Setting value = %s\n", SectionItem->ItemValue);
132
133 TRACE("1 NameSize = %d ValueSize = %d\n", NameSize, ValueSize);
134 TRACE("2 NameSize = %d ValueSize = %d\n", NameSize, ValueSize);
135 strncpy(SettingName, SectionItem->ItemName, NameSize - 1);
136 SettingName[NameSize - 1] = '\0';
137 TRACE("3 NameSize = %d ValueSize = %d\n", NameSize, ValueSize);
138 strncpy(SettingValue, SectionItem->ItemValue, ValueSize - 1);
139 SettingValue[ValueSize - 1] = '\0';
140 TRACE("4 NameSize = %d ValueSize = %d\n", NameSize, ValueSize);
141 DbgDumpBuffer(DPRINT_INIFILE, SettingName, NameSize);
142 DbgDumpBuffer(DPRINT_INIFILE, SettingValue, ValueSize);
143
144 return TRUE;
145 }
146
147 BOOLEAN IniReadSettingByName(ULONG_PTR SectionId, PCSTR SettingName, PCHAR Buffer, ULONG BufferSize)
148 {
149 PINI_SECTION Section = (PINI_SECTION)SectionId;
150 PINI_SECTION_ITEM SectionItem;
151
152 TRACE("IniReadSettingByName() SectionId = 0x%x\n", SectionId);
153
154 // Loop through each section item and find the one they want
155 SectionItem = CONTAINING_RECORD(Section->SectionItemList.Flink, INI_SECTION_ITEM, ListEntry);
156 while (&SectionItem->ListEntry != &Section->SectionItemList)
157 {
158 // Check to see if this is the setting they want
159 if (_stricmp(SettingName, SectionItem->ItemName) == 0)
160 {
161 TRACE("IniReadSettingByName() Setting \'%s\' found.\n", SettingName);
162 TRACE("IniReadSettingByName() Setting value = %s\n", SectionItem->ItemValue);
163
164 strncpy(Buffer, SectionItem->ItemValue, BufferSize - 1);
165 Buffer[BufferSize - 1] = '\0';
166
167 return TRUE;
168 }
169
170 // Get the next section item in the list
171 SectionItem = CONTAINING_RECORD(SectionItem->ListEntry.Flink, INI_SECTION_ITEM, ListEntry);
172 }
173
174 WARN("IniReadSettingByName() Setting \'%s\' not found.\n", SettingName);
175
176 return FALSE;
177 }
178
179 BOOLEAN IniAddSection(PCSTR SectionName, ULONG_PTR* SectionId)
180 {
181 PINI_SECTION Section;
182
183 // Allocate a new section structure
184 Section = FrLdrTempAlloc(sizeof(INI_SECTION), TAG_INI_SECTION);
185 if (!Section)
186 {
187 return FALSE;
188 }
189
190 RtlZeroMemory(Section, sizeof(INI_SECTION));
191
192 // Allocate the section name buffer
193 Section->SectionName = FrLdrTempAlloc(strlen(SectionName) + sizeof(CHAR), TAG_INI_NAME);
194 if (!Section->SectionName)
195 {
196 FrLdrTempFree(Section, TAG_INI_SECTION);
197 return FALSE;
198 }
199
200 // Get the section name
201 strcpy(Section->SectionName, SectionName);
202 InitializeListHead(&Section->SectionItemList);
203
204 // Add it to the section list head
205 IniFileSectionCount++;
206 InsertHeadList(&IniFileSectionListHead, &Section->ListEntry);
207
208 *SectionId = (ULONG_PTR)Section;
209
210 return TRUE;
211 }
212
213 VOID IniFreeSection(PINI_SECTION Section)
214 {
215 PLIST_ENTRY ListEntry;
216 PINI_SECTION_ITEM SectionItem;
217
218 // Loop while there are section items
219 while (!IsListEmpty(&Section->SectionItemList))
220 {
221 // Remove the section item
222 ListEntry = RemoveHeadList(&Section->SectionItemList);
223 SectionItem = CONTAINING_RECORD(ListEntry, INI_SECTION_ITEM, ListEntry);
224
225 // Free it
226 FrLdrTempFree(SectionItem->ItemName, TAG_INI_NAME);
227 FrLdrTempFree(SectionItem->ItemValue, TAG_INI_VALUE);
228 FrLdrTempFree(SectionItem, TAG_INI_SECTION_ITEM);
229 }
230
231 FrLdrTempFree(Section->SectionName, TAG_INI_NAME);
232 FrLdrTempFree(Section, TAG_INI_SECTION);
233 }
234
235 VOID IniCleanup(VOID)
236 {
237 PLIST_ENTRY ListEntry;
238 PINI_SECTION Section;
239
240 // Loop while there are sections
241 while (!IsListEmpty(&IniFileSectionListHead))
242 {
243 // Remove the section
244 ListEntry = RemoveHeadList(&IniFileSectionListHead);
245 Section = CONTAINING_RECORD(ListEntry, INI_SECTION, ListEntry);
246
247 // Free it
248 IniFreeSection(Section);
249 }
250 }
251
252 BOOLEAN IniAddSettingValueToSection(ULONG_PTR SectionId, PCSTR SettingName, PCSTR SettingValue)
253 {
254 PINI_SECTION Section = (PINI_SECTION)SectionId;
255 PINI_SECTION_ITEM SectionItem;
256
257 // Allocate a new item structure
258 SectionItem = FrLdrTempAlloc(sizeof(INI_SECTION_ITEM), TAG_INI_SECTION_ITEM);
259 if (!SectionItem)
260 {
261 return FALSE;
262 }
263
264 RtlZeroMemory(SectionItem, sizeof(INI_SECTION_ITEM));
265
266 // Allocate the setting name buffer
267 SectionItem->ItemName = FrLdrTempAlloc(strlen(SettingName) + 1, TAG_INI_NAME);
268 if (!SectionItem->ItemName)
269 {
270 FrLdrTempFree(SectionItem, TAG_INI_SECTION_ITEM);
271 return FALSE;
272 }
273
274 // Allocate the setting value buffer
275 SectionItem->ItemValue = FrLdrTempAlloc(strlen(SettingValue) + 1, TAG_INI_VALUE);
276 if (!SectionItem->ItemValue)
277 {
278 FrLdrTempFree(SectionItem->ItemName, TAG_INI_NAME);
279 FrLdrTempFree(SectionItem, TAG_INI_SECTION_ITEM);
280 return FALSE;
281 }
282
283 strcpy(SectionItem->ItemName, SettingName);
284 strcpy(SectionItem->ItemValue, SettingValue);
285
286 // Add it to the current section
287 Section->SectionItemCount++;
288 InsertTailList(&Section->SectionItemList, &SectionItem->ListEntry);
289
290 return TRUE;
291 }
292
293 BOOLEAN IniModifySettingValue(ULONG_PTR SectionId, PCSTR SettingName, PCSTR SettingValue)
294 {
295 PINI_SECTION Section = (PINI_SECTION)SectionId;
296 PINI_SECTION_ITEM SectionItem;
297 PCHAR NewItemValue;
298
299 // Loop through each section item and find the one we want
300 SectionItem = CONTAINING_RECORD(Section->SectionItemList.Flink, INI_SECTION_ITEM, ListEntry);
301 while (&SectionItem->ListEntry != &Section->SectionItemList)
302 {
303 // Check to see if this is the setting we want
304 if (_stricmp(SectionItem->ItemName, SettingName) == 0)
305 {
306 break;
307 }
308
309 // Nope, keep going
310 // Get the next section item in the list
311 SectionItem = CONTAINING_RECORD(SectionItem->ListEntry.Flink, INI_SECTION_ITEM, ListEntry);
312 }
313 // If the section item does not exist, create it
314 if (&SectionItem->ListEntry == &Section->SectionItemList)
315 {
316 return IniAddSettingValueToSection(SectionId, SettingName, SettingValue);
317 }
318
319 // Reallocate the new setting value buffer
320 NewItemValue = FrLdrTempAlloc(strlen(SettingValue) + 1, TAG_INI_VALUE);
321 if (!NewItemValue)
322 {
323 // We failed, bail out
324 return FALSE;
325 }
326 FrLdrTempFree(SectionItem->ItemValue, TAG_INI_VALUE);
327 SectionItem->ItemValue = NewItemValue;
328
329 strcpy(SectionItem->ItemValue, SettingValue);
330
331 return TRUE;
332 }