From e151ef9ae183458152a5d3e81cf0462030d0cb12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Wed, 24 Apr 2024 12:58:09 +0200 Subject: [PATCH] [SETUPLIB] Add support for removing sections and key values, and remove some hacks (#6815) - Use LIST_ENTRY instead of custom list pointers; - Fix key/section unlinking before freeing. --- base/setup/lib/utils/bldrsup.c | 72 ++++----- base/setup/lib/utils/inicache.c | 275 ++++++++++++++++---------------- base/setup/lib/utils/inicache.h | 53 +++--- 3 files changed, 201 insertions(+), 199 deletions(-) diff --git a/base/setup/lib/utils/bldrsup.c b/base/setup/lib/utils/bldrsup.c index e5017eaf210..d6f515ea89b 100644 --- a/base/setup/lib/utils/bldrsup.c +++ b/base/setup/lib/utils/bldrsup.c @@ -1006,9 +1006,8 @@ QueryBootStoreOptions( IN OUT PBOOT_STORE_OPTIONS BootOptions /* , IN PULONG BootOptionsLength */ ) { - NTSTATUS Status = STATUS_SUCCESS; PBOOT_STORE_CONTEXT BootStore = (PBOOT_STORE_CONTEXT)Handle; - PWCHAR TimeoutStr; + PCWSTR TimeoutStr; if (!BootStore || !BootOptions) return STATUS_INVALID_PARAMETER; @@ -1036,36 +1035,34 @@ QueryBootStoreOptions( { BootOptions->Version = FreeLdr; - Status = IniGetKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, - L"DefaultOS", (PWCHAR*)&BootOptions->CurrentBootEntryKey); - if (!NT_SUCCESS(Status)) - BootOptions->CurrentBootEntryKey = 0; + BootOptions->CurrentBootEntryKey = 0; + IniGetKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, + L"DefaultOS", (PCWSTR*)&BootOptions->CurrentBootEntryKey); - Status = IniGetKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, - L"TimeOut", &TimeoutStr); - if (NT_SUCCESS(Status) && TimeoutStr) + BootOptions->Timeout = 0; + if (IniGetKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, + L"TimeOut", &TimeoutStr) && TimeoutStr) + { BootOptions->Timeout = _wtoi(TimeoutStr); - else - BootOptions->Timeout = 0; + } } else if (BootStore->Type == NtLdr) { BootOptions->Version = NtLdr; - Status = IniGetKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, - L"default", (PWCHAR*)&BootOptions->CurrentBootEntryKey); - if (!NT_SUCCESS(Status)) - BootOptions->CurrentBootEntryKey = 0; + BootOptions->CurrentBootEntryKey = 0; + IniGetKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, + L"default", (PCWSTR*)&BootOptions->CurrentBootEntryKey); - Status = IniGetKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, - L"timeout", &TimeoutStr); - if (NT_SUCCESS(Status) && TimeoutStr) + BootOptions->Timeout = 0; + if (IniGetKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, + L"timeout", &TimeoutStr) && TimeoutStr) + { BootOptions->Timeout = _wtoi(TimeoutStr); - else - BootOptions->Timeout = 0; + } } - return STATUS_SUCCESS; // FIXME: use Status; instead? + return STATUS_SUCCESS; } NTSTATUS @@ -1110,9 +1107,8 @@ SetBootStoreOptions( L"DefaultOS", (PCWSTR)BootOptions->CurrentBootEntryKey); RtlStringCchPrintfW(TimeoutStr, ARRAYSIZE(TimeoutStr), L"%d", BootOptions->Timeout); - IniInsertKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, - NULL, INSERT_FIRST, // INSERT_LAST, // FIXME!! There is a bug in the INI parser where a given key can be inserted twice in the same section... - L"TimeOut", TimeoutStr); + IniAddKey(((PBOOT_STORE_INI_CONTEXT)BootStore)->OptionsIniSection, + L"TimeOut", TimeoutStr); return STATUS_SUCCESS; } @@ -1129,7 +1125,7 @@ FreeLdrEnumerateBootEntries( NTSTATUS Status = STATUS_SUCCESS; PINICACHEITERATOR Iterator; PINI_SECTION OsIniSection; - PWCHAR SectionName, KeyData; + PCWSTR SectionName, KeyData; UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + max(sizeof(NTOS_OPTIONS), sizeof(BOOT_SECTOR_OPTIONS))]; PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; @@ -1140,7 +1136,7 @@ FreeLdrEnumerateBootEntries( if (!Iterator) return STATUS_SUCCESS; do { - PWCHAR InstallName; + PCWSTR InstallName; ULONG InstallNameLength; /* Poor-man quotes removal (improvement over bootsup.c:UpdateFreeLoaderIni) */ @@ -1195,9 +1191,8 @@ FreeLdrEnumerateBootEntries( if (!OsIniSection) goto DoEnum; - /* Check for supported boot type "Windows2003" */ - Status = IniGetKey(OsIniSection, L"BootType", &KeyData); - if (!NT_SUCCESS(Status) || !KeyData) + /* Check for supported boot type */ + if (!IniGetKey(OsIniSection, L"BootType", &KeyData) || !KeyData) { /* Certainly not a ReactOS installation */ DPRINT1("No BootType value present!\n"); @@ -1222,15 +1217,13 @@ FreeLdrEnumerateBootEntries( /* Check its SystemPath */ Options->OsLoadPath = NULL; - Status = IniGetKey(OsIniSection, L"SystemPath", &KeyData); - if (NT_SUCCESS(Status)) + if (IniGetKey(OsIniSection, L"SystemPath", &KeyData)) Options->OsLoadPath = KeyData; // KeyData == SystemRoot; /* Check the optional Options */ Options->OsLoadOptions = NULL; - Status = IniGetKey(OsIniSection, L"Options", &KeyData); - if (NT_SUCCESS(Status)) + if (IniGetKey(OsIniSection, L"Options", &KeyData)) Options->OsLoadOptions = KeyData; } else @@ -1251,20 +1244,17 @@ FreeLdrEnumerateBootEntries( /* Check its BootDrive */ Options->Drive = NULL; - Status = IniGetKey(OsIniSection, L"BootDrive", &KeyData); - if (NT_SUCCESS(Status)) + if (IniGetKey(OsIniSection, L"BootDrive", &KeyData)) Options->Drive = KeyData; /* Check its BootPartition */ Options->Partition = NULL; - Status = IniGetKey(OsIniSection, L"BootPartition", &KeyData); - if (NT_SUCCESS(Status)) + if (IniGetKey(OsIniSection, L"BootPartition", &KeyData)) Options->Partition = KeyData; /* Check its BootSector */ Options->BootSectorFileName = NULL; - Status = IniGetKey(OsIniSection, L"BootSectorFile", &KeyData); - if (NT_SUCCESS(Status)) + if (IniGetKey(OsIniSection, L"BootSectorFile", &KeyData)) Options->BootSectorFileName = KeyData; } else @@ -1300,7 +1290,7 @@ NtLdrEnumerateBootEntries( { NTSTATUS Status = STATUS_SUCCESS; PINICACHEITERATOR Iterator; - PWCHAR SectionName, KeyData; + PCWSTR SectionName, KeyData; UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)]; PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; @@ -1312,7 +1302,7 @@ NtLdrEnumerateBootEntries( if (!Iterator) return STATUS_SUCCESS; do { - PWCHAR InstallName, OsOptions; + PCWSTR InstallName, OsOptions; ULONG InstallNameLength, OsOptionsLength; /* Poor-man quotes removal (improvement over bootsup.c:UpdateFreeLoaderIni) */ diff --git a/base/setup/lib/utils/inicache.c b/base/setup/lib/utils/inicache.c index 87917a1c175..2baba67978f 100644 --- a/base/setup/lib/utils/inicache.c +++ b/base/setup/lib/utils/inicache.c @@ -16,60 +16,38 @@ /* PRIVATE FUNCTIONS ********************************************************/ -static -PINI_KEYWORD +static VOID IniCacheFreeKey( - PINI_KEYWORD Key) + _In_ PINI_KEYWORD Key) { - PINI_KEYWORD Next; + /* Unlink the key */ + RemoveEntryList(&Key->ListEntry); - if (Key == NULL) - return NULL; - - Next = Key->Next; - if (Key->Name != NULL) - { + /* Free its data */ + if (Key->Name) RtlFreeHeap(ProcessHeap, 0, Key->Name); - Key->Name = NULL; - } - - if (Key->Data != NULL) - { + if (Key->Data) RtlFreeHeap(ProcessHeap, 0, Key->Data); - Key->Data = NULL; - } - RtlFreeHeap(ProcessHeap, 0, Key); - - return Next; } -static -PINI_SECTION +static VOID IniCacheFreeSection( - PINI_SECTION Section) + _In_ PINI_SECTION Section) { - PINI_SECTION Next; + /* Unlink the section */ + RemoveEntryList(&Section->ListEntry); - if (Section == NULL) - return NULL; - - Next = Section->Next; - while (Section->FirstKey != NULL) + /* Free its data */ + while (!IsListEmpty(&Section->KeyList)) { - Section->FirstKey = IniCacheFreeKey(Section->FirstKey); + PLIST_ENTRY Entry = RemoveHeadList(&Section->KeyList); + PINI_KEYWORD Key = CONTAINING_RECORD(Entry, INI_KEYWORD, ListEntry); + IniCacheFreeKey(Key); } - Section->LastKey = NULL; - - if (Section->Name != NULL) - { + if (Section->Name) RtlFreeHeap(ProcessHeap, 0, Section->Name); - Section->Name = NULL; - } - RtlFreeHeap(ProcessHeap, 0, Section); - - return Next; } static @@ -78,10 +56,13 @@ IniCacheFindSection( _In_ PINICACHE Cache, _In_ PCWSTR Name) { - PINI_SECTION Section; + PLIST_ENTRY Entry; - for (Section = Cache->FirstSection; Section; Section = Section->Next) + for (Entry = Cache->SectionList.Flink; + Entry != &Cache->SectionList; + Entry = Entry->Flink) { + PINI_SECTION Section = CONTAINING_RECORD(Entry, INI_SECTION, ListEntry); if (_wcsicmp(Section->Name, Name) == 0) return Section; } @@ -94,10 +75,13 @@ IniCacheFindKey( _In_ PINI_SECTION Section, _In_ PCWSTR Name) { - PINI_KEYWORD Key; + PLIST_ENTRY Entry; - for (Key = Section->FirstKey; Key; Key = Key->Next) + for (Entry = Section->KeyList.Flink; + Entry != &Section->KeyList; + Entry = Entry->Flink) { + PINI_KEYWORD Key = CONTAINING_RECORD(Entry, INI_KEYWORD, ListEntry); if (_wcsicmp(Key->Name, Name) == 0) return Key; } @@ -208,43 +192,33 @@ IniCacheAddKeyAorW( Key->Data = DataU; /* Insert the key into section */ - if (Section->FirstKey == NULL) + if (IsListEmpty(&Section->KeyList)) { - Section->FirstKey = Key; - Section->LastKey = Key; + InsertHeadList(&Section->KeyList, &Key->ListEntry); } else if ((InsertionType == INSERT_FIRST) || ((InsertionType == INSERT_BEFORE) && - ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey)))) + (!AnchorKey || (&AnchorKey->ListEntry == Section->KeyList.Flink)))) { /* Insert at the head of the list */ - Section->FirstKey->Prev = Key; - Key->Next = Section->FirstKey; - Section->FirstKey = Key; + InsertHeadList(&Section->KeyList, &Key->ListEntry); } - else if ((InsertionType == INSERT_BEFORE) && (AnchorKey != NULL)) + else if ((InsertionType == INSERT_BEFORE) && AnchorKey) { /* Insert before the anchor key */ - Key->Next = AnchorKey; - Key->Prev = AnchorKey->Prev; - AnchorKey->Prev->Next = Key; - AnchorKey->Prev = Key; + InsertTailList(&AnchorKey->ListEntry, &Key->ListEntry); } else if ((InsertionType == INSERT_LAST) || ((InsertionType == INSERT_AFTER) && - ((AnchorKey == NULL) || (AnchorKey == Section->LastKey)))) + (!AnchorKey || (&AnchorKey->ListEntry == Section->KeyList.Blink)))) { - Section->LastKey->Next = Key; - Key->Prev = Section->LastKey; - Section->LastKey = Key; + /* Insert at the tail of the list */ + InsertTailList(&Section->KeyList, &Key->ListEntry); } - else if ((InsertionType == INSERT_AFTER) && (AnchorKey != NULL)) + else if ((InsertionType == INSERT_AFTER) && AnchorKey) { /* Insert after the anchor key */ - Key->Next = AnchorKey->Next; - Key->Prev = AnchorKey; - AnchorKey->Next->Prev = Key; - AnchorKey->Next = Key; + InsertHeadList(&AnchorKey->ListEntry, &Key->ListEntry); } return Key; @@ -305,19 +279,10 @@ IniCacheAddSectionAorW( return NULL; } Section->Name = NameU; + InitializeListHead(&Section->KeyList); /* Append the section */ - if (Cache->FirstSection == NULL) - { - Cache->FirstSection = Section; - Cache->LastSection = Section; - } - else - { - Cache->LastSection->Next = Section; - Section->Prev = Cache->LastSection; - Cache->LastSection = Section; - } + InsertTailList(&Cache->SectionList, &Section->ListEntry); return Section; } @@ -540,14 +505,9 @@ IniCacheLoadFromMemory( ULONG KeyValueSize; /* Allocate inicache header */ - *Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, - HEAP_ZERO_MEMORY, - sizeof(INICACHE)); - if (*Cache == NULL) - { - DPRINT("RtlAllocateHeap() failed\n"); + *Cache = IniCacheCreate(); + if (!*Cache) return STATUS_INSUFFICIENT_RESOURCES; - } /* Parse ini file */ Section = NULL; @@ -737,16 +697,17 @@ IniCacheLoad( VOID IniCacheDestroy( - PINICACHE Cache) + _In_ PINICACHE Cache) { - if (Cache == NULL) + if (!Cache) return; - while (Cache->FirstSection != NULL) + while (!IsListEmpty(&Cache->SectionList)) { - Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection); + PLIST_ENTRY Entry = RemoveHeadList(&Cache->SectionList); + PINI_SECTION Section = CONTAINING_RECORD(Entry, INI_SECTION, ListEntry); + IniCacheFreeSection(Section); } - Cache->LastSection = NULL; RtlFreeHeap(ProcessHeap, 0, Cache); } @@ -765,110 +726,110 @@ IniGetSection( return IniCacheFindSection(Cache, Name); } -NTSTATUS +PINI_KEYWORD IniGetKey( - PINI_SECTION Section, - PWCHAR KeyName, - PWCHAR *KeyData) + _In_ PINI_SECTION Section, + _In_ PCWSTR KeyName, + _Out_ PCWSTR* KeyData) { PINI_KEYWORD Key; - if (Section == NULL || KeyName == NULL || KeyData == NULL) + if (!Section || !KeyName || !KeyData) { DPRINT("Invalid parameter\n"); - return STATUS_INVALID_PARAMETER; + return NULL; } *KeyData = NULL; Key = IniCacheFindKey(Section, KeyName); - if (Key == NULL) - { - return STATUS_INVALID_PARAMETER; - } + if (!Key) + return NULL; *KeyData = Key->Data; - return STATUS_SUCCESS; + return Key; } PINICACHEITERATOR IniFindFirstValue( - PINI_SECTION Section, - PWCHAR *KeyName, - PWCHAR *KeyData) + _In_ PINI_SECTION Section, + _Out_ PCWSTR* KeyName, + _Out_ PCWSTR* KeyData) { PINICACHEITERATOR Iterator; + PLIST_ENTRY Entry; PINI_KEYWORD Key; - if (Section == NULL || KeyName == NULL || KeyData == NULL) + if (!Section || !KeyName || !KeyData) { DPRINT("Invalid parameter\n"); return NULL; } - Key = Section->FirstKey; - if (Key == NULL) + Entry = Section->KeyList.Flink; + if (Entry == &Section->KeyList) { DPRINT("Invalid parameter\n"); return NULL; } - - *KeyName = Key->Name; - *KeyData = Key->Data; + Key = CONTAINING_RECORD(Entry, INI_KEYWORD, ListEntry); Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap, 0, sizeof(INICACHEITERATOR)); - if (Iterator == NULL) + if (!Iterator) { DPRINT("RtlAllocateHeap() failed\n"); return NULL; } - Iterator->Section = Section; Iterator->Key = Key; + *KeyName = Key->Name; + *KeyData = Key->Data; + return Iterator; } BOOLEAN IniFindNextValue( - PINICACHEITERATOR Iterator, - PWCHAR *KeyName, - PWCHAR *KeyData) + _In_ PINICACHEITERATOR Iterator, + _Out_ PCWSTR* KeyName, + _Out_ PCWSTR* KeyData) { + PLIST_ENTRY Entry; PINI_KEYWORD Key; - if (Iterator == NULL || KeyName == NULL || KeyData == NULL) + if (!Iterator || !KeyName || !KeyData) { DPRINT("Invalid parameter\n"); return FALSE; } - Key = Iterator->Key->Next; - if (Key == NULL) + Entry = Iterator->Key->ListEntry.Flink; + if (Entry == &Iterator->Section->KeyList) { DPRINT("No more entries\n"); return FALSE; } + Key = CONTAINING_RECORD(Entry, INI_KEYWORD, ListEntry); + + Iterator->Key = Key; *KeyName = Key->Name; *KeyData = Key->Data; - Iterator->Key = Key; - return TRUE; } VOID IniFindClose( - PINICACHEITERATOR Iterator) + _In_ PINICACHEITERATOR Iterator) { - if (Iterator == NULL) + if (!Iterator) return; - RtlFreeHeap(ProcessHeap, 0, Iterator); } @@ -886,6 +847,18 @@ IniAddSection( return IniCacheAddSectionAorW(Cache, Name, wcslen(Name), TRUE); } +VOID +IniRemoveSection( + _In_ PINI_SECTION Section) +{ + if (!Section) + { + DPRINT("Invalid parameter\n"); + return; + } + IniCacheFreeSection(Section); +} + PINI_KEYWORD IniInsertKey( _In_ PINI_SECTION Section, @@ -915,6 +888,32 @@ IniAddKey( return IniInsertKey(Section, NULL, INSERT_LAST, Name, Data); } +VOID +IniRemoveKeyByName( + _In_ PINI_SECTION Section, + _In_ PCWSTR KeyName) +{ + PINI_KEYWORD Key; + UNREFERENCED_PARAMETER(Section); + + Key = IniCacheFindKey(Section, KeyName); + if (Key) + IniCacheFreeKey(Key); +} + +VOID +IniRemoveKey( + _In_ PINI_SECTION Section, + _In_ PINI_KEYWORD Key) +{ + UNREFERENCED_PARAMETER(Section); + if (!Key) + { + DPRINT("Invalid parameter\n"); + return; + } + IniCacheFreeKey(Key); +} PINICACHE IniCacheCreate(VOID) @@ -925,11 +924,12 @@ IniCacheCreate(VOID) Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(INICACHE)); - if (Cache == NULL) + if (!Cache) { DPRINT("RtlAllocateHeap() failed\n"); return NULL; } + InitializeListHead(&Cache->SectionList); return Cache; } @@ -940,6 +940,7 @@ IniCacheSaveByHandle( HANDLE FileHandle) { NTSTATUS Status; + PLIST_ENTRY Entry1, Entry2; PINI_SECTION Section; PINI_KEYWORD Key; ULONG BufferSize; @@ -951,23 +952,25 @@ IniCacheSaveByHandle( /* Calculate required buffer size */ BufferSize = 0; - Section = Cache->FirstSection; - while (Section != NULL) + Entry1 = Cache->SectionList.Flink; + while (Entry1 != &Cache->SectionList) { + Section = CONTAINING_RECORD(Entry1, INI_SECTION, ListEntry); BufferSize += (Section->Name ? wcslen(Section->Name) : 0) + 4; /* "[]\r\n" */ - Key = Section->FirstKey; - while (Key != NULL) + Entry2 = Section->KeyList.Flink; + while (Entry2 != &Section->KeyList) { + Key = CONTAINING_RECORD(Entry2, INI_KEYWORD, ListEntry); BufferSize += wcslen(Key->Name) + (Key->Data ? wcslen(Key->Data) : 0) + 3; /* "=\r\n" */ - Key = Key->Next; + Entry2 = Entry2->Flink; } - Section = Section->Next; - if (Section != NULL) + Entry1 = Entry1->Flink; + if (Entry1 != &Cache->SectionList) BufferSize += 2; /* Extra "\r\n" at end of each section */ } @@ -985,22 +988,24 @@ IniCacheSaveByHandle( /* Fill file buffer */ Ptr = Buffer; - Section = Cache->FirstSection; - while (Section != NULL) + Entry1 = Cache->SectionList.Flink; + while (Entry1 != &Cache->SectionList) { + Section = CONTAINING_RECORD(Entry1, INI_SECTION, ListEntry); Len = sprintf(Ptr, "[%S]\r\n", Section->Name); Ptr += Len; - Key = Section->FirstKey; - while (Key != NULL) + Entry2 = Section->KeyList.Flink; + while (Entry2 != &Section->KeyList) { + Key = CONTAINING_RECORD(Entry2, INI_KEYWORD, ListEntry); Len = sprintf(Ptr, "%S=%S\r\n", Key->Name, Key->Data); Ptr += Len; - Key = Key->Next; + Entry2 = Entry2->Flink; } - Section = Section->Next; - if (Section != NULL) + Entry1 = Entry1->Flink; + if (Entry1 != &Cache->SectionList) { Len = sprintf(Ptr, "\r\n"); Ptr += Len; diff --git a/base/setup/lib/utils/inicache.h b/base/setup/lib/utils/inicache.h index f33780b8c78..c8ef57d9ba5 100644 --- a/base/setup/lib/utils/inicache.h +++ b/base/setup/lib/utils/inicache.h @@ -11,26 +11,19 @@ typedef struct _INI_KEYWORD { PWSTR Name; PWSTR Data; - - struct _INI_KEYWORD *Next; - struct _INI_KEYWORD *Prev; + LIST_ENTRY ListEntry; } INI_KEYWORD, *PINI_KEYWORD; typedef struct _INI_SECTION { PWSTR Name; - - PINI_KEYWORD FirstKey; - PINI_KEYWORD LastKey; - - struct _INI_SECTION *Next; - struct _INI_SECTION *Prev; + LIST_ENTRY KeyList; + LIST_ENTRY ListEntry; } INI_SECTION, *PINI_SECTION; typedef struct _INICACHE { - PINI_SECTION FirstSection; - PINI_SECTION LastSection; + LIST_ENTRY SectionList; } INICACHE, *PINICACHE; typedef struct _PINICACHEITERATOR @@ -70,40 +63,44 @@ IniCacheLoad( VOID IniCacheDestroy( - PINICACHE Cache); + _In_ PINICACHE Cache); PINI_SECTION IniGetSection( _In_ PINICACHE Cache, _In_ PCWSTR Name); -NTSTATUS +PINI_KEYWORD IniGetKey( - PINI_SECTION Section, - PWCHAR KeyName, - PWCHAR *KeyData); + _In_ PINI_SECTION Section, + _In_ PCWSTR KeyName, + _Out_ PCWSTR* KeyData); PINICACHEITERATOR IniFindFirstValue( - PINI_SECTION Section, - PWCHAR *KeyName, - PWCHAR *KeyData); + _In_ PINI_SECTION Section, + _Out_ PCWSTR* KeyName, + _Out_ PCWSTR* KeyData); BOOLEAN IniFindNextValue( - PINICACHEITERATOR Iterator, - PWCHAR *KeyName, - PWCHAR *KeyData); + _In_ PINICACHEITERATOR Iterator, + _Out_ PCWSTR* KeyName, + _Out_ PCWSTR* KeyData); VOID IniFindClose( - PINICACHEITERATOR Iterator); + _In_ PINICACHEITERATOR Iterator); PINI_SECTION IniAddSection( _In_ PINICACHE Cache, _In_ PCWSTR Name); +VOID +IniRemoveSection( + _In_ PINI_SECTION Section); + PINI_KEYWORD IniInsertKey( _In_ PINI_SECTION Section, @@ -118,6 +115,16 @@ IniAddKey( _In_ PCWSTR Name, _In_ PCWSTR Data); +VOID +IniRemoveKeyByName( + _In_ PINI_SECTION Section, + _In_ PCWSTR KeyName); + +VOID +IniRemoveKey( + _In_ PINI_SECTION Section, + _In_ PINI_KEYWORD Key); + PINICACHE IniCacheCreate(VOID);