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