[SETUPLIB] Don't create new INI sections or key-values if they already exist (#6815)

- If a section already exists, return the existing one. This allows
  avoiding different section entries with the same name in the cache.
  If an INI file has separate sections with the same name, their
  contents (key-values) get merged into a unique section.

- If a key-value already exists, update its data value and return the
  existing one. (Note that this may be subject to behaviour change in
  the future.)
This commit is contained in:
Hermès Bélusca-Maïto 2024-04-23 22:40:31 +02:00
parent 817c27a54e
commit b9ca9b0061
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
3 changed files with 141 additions and 111 deletions

View file

@ -214,10 +214,8 @@ CreateCommonFreeLdrSections(
* Cache the "FREELOADER" section for our future usage.
*/
/* Get or create the "FREELOADER" section */
IniSection = IniGetSection(BootStore->IniCache, L"FREELOADER");
if (!IniSection)
IniSection = IniAddSection(BootStore->IniCache, L"FREELOADER");
/* Create the "FREELOADER" section */
IniSection = IniAddSection(BootStore->IniCache, L"FREELOADER");
if (!IniSection)
DPRINT1("CreateCommonFreeLdrSections: Failed to create 'FREELOADER' section!\n");
@ -237,10 +235,8 @@ CreateCommonFreeLdrSections(
* Cache the "Operating Systems" section for our future usage.
*/
/* Get or create the "Operating Systems" section */
IniSection = IniGetSection(BootStore->IniCache, L"Operating Systems");
if (!IniSection)
IniSection = IniAddSection(BootStore->IniCache, L"Operating Systems");
/* Create the "Operating Systems" section */
IniSection = IniAddSection(BootStore->IniCache, L"Operating Systems");
if (!IniSection)
DPRINT1("CreateCommonFreeLdrSections: Failed to create 'Operating Systems' section!\n");

View file

@ -72,28 +72,36 @@ IniCacheFreeSection(
return Next;
}
static
PINI_SECTION
IniCacheFindSection(
_In_ PINICACHE Cache,
_In_ PCWSTR Name)
{
PINI_SECTION Section;
for (Section = Cache->FirstSection; Section; Section = Section->Next)
{
if (_wcsicmp(Section->Name, Name) == 0)
return Section;
}
return NULL;
}
static
PINI_KEYWORD
IniCacheFindKey(
PINI_SECTION Section,
PWCHAR Name,
ULONG NameLength)
_In_ PINI_SECTION Section,
_In_ PCWSTR Name)
{
PINI_KEYWORD Key;
Key = Section->FirstKey;
while (Key != NULL)
for (Key = Section->FirstKey; Key; Key = Key->Next)
{
if (NameLength == wcslen(Key->Name))
{
if (_wcsnicmp(Key->Name, Name, NameLength) == 0)
break;
}
Key = Key->Next;
if (_wcsicmp(Key->Name, Name) == 0)
return Key;
}
return Key;
return NULL;
}
static
@ -108,66 +116,98 @@ IniCacheAddKeyAorW(
_In_ ULONG DataLength,
_In_ BOOLEAN IsUnicode)
{
PINI_KEYWORD Key = NULL;
PINI_KEYWORD Key;
PWSTR NameU, DataU;
if (Section == NULL ||
Name == NULL ||
NameLength == 0 ||
Data == NULL ||
DataLength == 0)
if (!Section || !Name || NameLength == 0 || !Data || DataLength == 0)
{
DPRINT("Invalid parameter\n");
return NULL;
}
/* Allocate key buffer */
/* Allocate the UNICODE key name */
NameU = (PWSTR)RtlAllocateHeap(ProcessHeap,
0,
(NameLength + 1) * sizeof(WCHAR));
if (!NameU)
{
DPRINT("RtlAllocateHeap() failed\n");
return NULL;
}
/* Copy the value name (ANSI or UNICODE) */
if (IsUnicode)
wcsncpy(NameU, (PCWCH)Name, NameLength);
else
_snwprintf(NameU, NameLength, L"%.*S", NameLength, (PCCH)Name);
NameU[NameLength] = UNICODE_NULL;
/*
* Find whether a key with the given name already exists in the section.
* If so, modify the data and return it; otherwise create a new one.
*/
Key = IniCacheFindKey(Section, NameU);
if (Key)
{
RtlFreeHeap(ProcessHeap, 0, NameU);
/* Modify the existing data */
/* Allocate the UNICODE data buffer */
DataU = (PWSTR)RtlAllocateHeap(ProcessHeap,
0,
(DataLength + 1) * sizeof(WCHAR));
if (!DataU)
{
DPRINT("RtlAllocateHeap() failed\n");
return NULL; // We failed, don't modify the original key.
}
/* Copy the data (ANSI or UNICODE) */
if (IsUnicode)
wcsncpy(DataU, (PCWCH)Data, DataLength);
else
_snwprintf(DataU, DataLength, L"%.*S", DataLength, (PCCH)Data);
DataU[DataLength] = UNICODE_NULL;
/* Swap the old key data with the new one */
RtlFreeHeap(ProcessHeap, 0, Key->Data);
Key->Data = DataU;
/* Return the modified key */
return Key;
}
/* Allocate the key buffer and name */
Key = (PINI_KEYWORD)RtlAllocateHeap(ProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(INI_KEYWORD));
if (Key == NULL)
if (!Key)
{
DPRINT("RtlAllocateHeap() failed\n");
RtlFreeHeap(ProcessHeap, 0, NameU);
return NULL;
}
Key->Name = NameU;
/* Allocate name buffer */
Key->Name = (PWCHAR)RtlAllocateHeap(ProcessHeap,
0,
(NameLength + 1) * sizeof(WCHAR));
if (Key->Name == NULL)
/* Allocate the UNICODE data buffer */
DataU = (PWSTR)RtlAllocateHeap(ProcessHeap,
0,
(DataLength + 1) * sizeof(WCHAR));
if (!DataU)
{
DPRINT("RtlAllocateHeap() failed\n");
RtlFreeHeap(ProcessHeap, 0, NameU);
RtlFreeHeap(ProcessHeap, 0, Key);
return NULL;
}
/* Copy value name (ANSI or UNICODE) */
/* Copy the data (ANSI or UNICODE) */
if (IsUnicode)
wcsncpy(Key->Name, (PCWCH)Name, NameLength);
wcsncpy(DataU, (PCWCH)Data, DataLength);
else
_snwprintf(Key->Name, NameLength, L"%.*S", NameLength, (PCCH)Name);
Key->Name[NameLength] = UNICODE_NULL;
_snwprintf(DataU, DataLength, L"%.*S", DataLength, (PCCH)Data);
DataU[DataLength] = UNICODE_NULL;
Key->Data = DataU;
/* Allocate data buffer */
Key->Data = (PWCHAR)RtlAllocateHeap(ProcessHeap,
0,
(DataLength + 1) * sizeof(WCHAR));
if (Key->Data == NULL)
{
DPRINT("RtlAllocateHeap() failed\n");
RtlFreeHeap(ProcessHeap, 0, Key->Name);
RtlFreeHeap(ProcessHeap, 0, Key);
return NULL;
}
/* Copy value data (ANSI or UNICODE) */
if (IsUnicode)
wcsncpy(Key->Data, (PCWCH)Data, DataLength);
else
_snwprintf(Key->Data, DataLength, L"%.*S", DataLength, (PCCH)Data);
Key->Data[DataLength] = UNICODE_NULL;
/* Insert key into section */
/* Insert the key into section */
if (Section->FirstKey == NULL)
{
Section->FirstKey = Key;
@ -218,42 +258,55 @@ IniCacheAddSectionAorW(
_In_ ULONG NameLength,
_In_ BOOLEAN IsUnicode)
{
PINI_SECTION Section = NULL;
PINI_SECTION Section;
PWSTR NameU;
if (Cache == NULL || Name == NULL || NameLength == 0)
if (!Cache || !Name || NameLength == 0)
{
DPRINT("Invalid parameter\n");
return NULL;
}
/* Allocate the UNICODE section name */
NameU = (PWSTR)RtlAllocateHeap(ProcessHeap,
0,
(NameLength + 1) * sizeof(WCHAR));
if (!NameU)
{
DPRINT("RtlAllocateHeap() failed\n");
return NULL;
}
/* Copy the section name (ANSI or UNICODE) */
if (IsUnicode)
wcsncpy(NameU, (PCWCH)Name, NameLength);
else
_snwprintf(NameU, NameLength, L"%.*S", NameLength, (PCCH)Name);
NameU[NameLength] = UNICODE_NULL;
/*
* Find whether a section with the given name already exists.
* If so, just return it; otherwise create a new one.
*/
Section = IniCacheFindSection(Cache, NameU);
if (Section)
{
RtlFreeHeap(ProcessHeap, 0, NameU);
return Section;
}
/* Allocate the section buffer and name */
Section = (PINI_SECTION)RtlAllocateHeap(ProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(INI_SECTION));
if (Section == NULL)
if (!Section)
{
DPRINT("RtlAllocateHeap() failed\n");
RtlFreeHeap(ProcessHeap, 0, NameU);
return NULL;
}
Section->Name = NameU;
/* Allocate and initialize section name */
Section->Name = (PWCHAR)RtlAllocateHeap(ProcessHeap,
0,
(NameLength + 1) * sizeof(WCHAR));
if (Section->Name == NULL)
{
DPRINT("RtlAllocateHeap() failed\n");
RtlFreeHeap(ProcessHeap, 0, Section);
return NULL;
}
/* Copy section name (ANSI or UNICODE) */
if (IsUnicode)
wcsncpy(Section->Name, (PCWCH)Name, NameLength);
else
_snwprintf(Section->Name, NameLength, L"%.*S", NameLength, (PCCH)Name);
Section->Name[NameLength] = UNICODE_NULL;
/* Append section */
/* Append the section */
if (Cache->FirstSection == NULL)
{
Cache->FirstSection = Section;
@ -701,34 +754,15 @@ IniCacheDestroy(
PINI_SECTION
IniGetSection(
PINICACHE Cache,
PWCHAR Name)
_In_ PINICACHE Cache,
_In_ PCWSTR Name)
{
PINI_SECTION Section = NULL;
if (Cache == NULL || Name == NULL)
if (!Cache || !Name)
{
DPRINT("Invalid parameter\n");
return NULL;
}
/* Iterate through list of sections */
Section = Cache->FirstSection;
while (Section != NULL)
{
DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name);
/* Are the section names the same? */
if (_wcsicmp(Section->Name, Name) == 0)
return Section;
/* Get the next section */
Section = Section->Next;
}
DPRINT("Section not found\n");
return NULL;
return IniCacheFindSection(Cache, Name);
}
NTSTATUS
@ -747,7 +781,7 @@ IniGetKey(
*KeyData = NULL;
Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName));
Key = IniCacheFindKey(Section, KeyName);
if (Key == NULL)
{
return STATUS_INVALID_PARAMETER;

View file

@ -9,8 +9,8 @@
typedef struct _INI_KEYWORD
{
PWCHAR Name;
PWCHAR Data;
PWSTR Name;
PWSTR Data;
struct _INI_KEYWORD *Next;
struct _INI_KEYWORD *Prev;
@ -18,7 +18,7 @@ typedef struct _INI_KEYWORD
typedef struct _INI_SECTION
{
PWCHAR Name;
PWSTR Name;
PINI_KEYWORD FirstKey;
PINI_KEYWORD LastKey;
@ -74,8 +74,8 @@ IniCacheDestroy(
PINI_SECTION
IniGetSection(
PINICACHE Cache,
PWCHAR Name);
_In_ PINICACHE Cache,
_In_ PCWSTR Name);
NTSTATUS
IniGetKey(