[FREELDR]
[reactos.git] / reactos / 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
203 // Add it to the section list head
204 IniFileSectionCount++;
205 InsertHeadList(&IniFileSectionListHead, &Section->ListEntry);
206
207 *SectionId = (ULONG_PTR)Section;
208
209 return TRUE;
210 }
211
212 VOID IniFreeSection(PINI_SECTION Section)
213 {
214 PLIST_ENTRY ListEntry;
215 PINI_SECTION_ITEM SectionItem;
216
217 // Loop while there are section items
218 while (!IsListEmpty(&Section->SectionItemList))
219 {
220 // Remove the section item
221 ListEntry = RemoveHeadList(&Section->SectionItemList);
222 SectionItem = CONTAINING_RECORD(ListEntry, INI_SECTION_ITEM, ListEntry);
223
224 // Free it
225 FrLdrTempFree(SectionItem->ItemName, TAG_INI_NAME);
226 FrLdrTempFree(SectionItem->ItemValue, TAG_INI_VALUE);
227 FrLdrTempFree(SectionItem, TAG_INI_SECTION_ITEM);
228 }
229
230 FrLdrTempFree(Section->SectionName, TAG_INI_NAME);
231 FrLdrTempFree(Section, TAG_INI_SECTION);
232 }
233
234 VOID IniCleanup(VOID)
235 {
236 PLIST_ENTRY ListEntry;
237 PINI_SECTION Section;
238
239 // Loop while there are sections
240 while (!IsListEmpty(&IniFileSectionListHead))
241 {
242 // Remove the section
243 ListEntry = RemoveHeadList(&IniFileSectionListHead);
244 Section = CONTAINING_RECORD(ListEntry, INI_SECTION, ListEntry);
245
246 // Free it
247 IniFreeSection(Section);
248 }
249 }
250
251 BOOLEAN IniAddSettingValueToSection(ULONG_PTR SectionId, PCSTR SettingName, PCSTR SettingValue)
252 {
253 PINI_SECTION Section = (PINI_SECTION)SectionId;
254 PINI_SECTION_ITEM SectionItem;
255
256 // Allocate a new item structure
257 SectionItem = FrLdrTempAlloc(sizeof(INI_SECTION_ITEM), TAG_INI_SECTION_ITEM);
258 if (!SectionItem)
259 {
260 return FALSE;
261 }
262
263 RtlZeroMemory(SectionItem, sizeof(INI_SECTION_ITEM));
264
265 // Allocate the setting name buffer
266 SectionItem->ItemName = FrLdrTempAlloc(strlen(SettingName) + 1, TAG_INI_NAME);
267 if (!SectionItem->ItemName)
268 {
269 FrLdrTempFree(SectionItem, TAG_INI_SECTION_ITEM);
270 return FALSE;
271 }
272
273 // Allocate the setting value buffer
274 SectionItem->ItemValue = FrLdrTempAlloc(strlen(SettingValue) + 1, TAG_INI_VALUE);
275 if (!SectionItem->ItemValue)
276 {
277 FrLdrTempFree(SectionItem->ItemName, TAG_INI_NAME);
278 FrLdrTempFree(SectionItem, TAG_INI_SECTION_ITEM);
279 return FALSE;
280 }
281
282 strcpy(SectionItem->ItemName, SettingName);
283 strcpy(SectionItem->ItemValue, SettingValue);
284
285 // Add it to the current section
286 Section->SectionItemCount++;
287 InsertTailList(&Section->SectionItemList, &SectionItem->ListEntry);
288
289 return TRUE;
290 }