1795895a78c40ef00b18c174d676fbd00f43d57a
[reactos.git] / base / setup / lib / genlist.c
1 /*
2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Generic list functions
5 * COPYRIGHT: Copyright 2008-2018 Christoph von Wittich <christoph at reactos.org>
6 */
7
8 /* INCLUDES *****************************************************************/
9
10 #include "precomp.h"
11
12 #include "genlist.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS ****************************************************************/
18
19 PGENERIC_LIST
20 CreateGenericList(VOID)
21 {
22 PGENERIC_LIST List;
23
24 List = (PGENERIC_LIST)RtlAllocateHeap(ProcessHeap,
25 0,
26 sizeof(GENERIC_LIST));
27 if (List == NULL)
28 return NULL;
29
30 InitializeListHead(&List->ListHead);
31 List->NumOfEntries = 0;
32
33 List->CurrentEntry = NULL;
34 List->BackupEntry = NULL;
35
36 return List;
37 }
38
39 VOID
40 DestroyGenericList(
41 IN OUT PGENERIC_LIST List,
42 IN BOOLEAN FreeUserData)
43 {
44 PGENERIC_LIST_ENTRY ListEntry;
45 PLIST_ENTRY Entry;
46
47 /* Release list entries */
48 while (!IsListEmpty(&List->ListHead))
49 {
50 Entry = RemoveHeadList(&List->ListHead);
51 ListEntry = CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
52
53 /* Release user data */
54 if (FreeUserData && ListEntry->UserData != NULL)
55 RtlFreeHeap(ProcessHeap, 0, ListEntry->UserData);
56
57 /* Release list entry */
58 RtlFreeHeap(ProcessHeap, 0, ListEntry);
59 }
60
61 /* Release list head */
62 RtlFreeHeap(ProcessHeap, 0, List);
63 }
64
65 BOOLEAN
66 AppendGenericListEntry(
67 IN OUT PGENERIC_LIST List,
68 IN PCHAR Text,
69 IN PVOID UserData,
70 IN BOOLEAN Current)
71 {
72 PGENERIC_LIST_ENTRY Entry;
73
74 Entry = (PGENERIC_LIST_ENTRY)RtlAllocateHeap(ProcessHeap,
75 0,
76 sizeof(GENERIC_LIST_ENTRY) + strlen(Text));
77 if (Entry == NULL)
78 return FALSE;
79
80 strcpy (Entry->Text, Text);
81 Entry->List = List;
82 Entry->UserData = UserData;
83
84 InsertTailList(&List->ListHead, &Entry->Entry);
85 List->NumOfEntries++;
86
87 if (Current || List->CurrentEntry == NULL)
88 {
89 List->CurrentEntry = Entry;
90 }
91
92 return TRUE;
93 }
94
95 VOID
96 SetCurrentListEntry(
97 IN PGENERIC_LIST List,
98 IN PGENERIC_LIST_ENTRY Entry)
99 {
100 if (Entry->List != List)
101 return;
102 List->CurrentEntry = Entry;
103 }
104
105 PGENERIC_LIST_ENTRY
106 GetCurrentListEntry(
107 IN PGENERIC_LIST List)
108 {
109 return List->CurrentEntry;
110 }
111
112 PGENERIC_LIST_ENTRY
113 GetFirstListEntry(
114 IN PGENERIC_LIST List)
115 {
116 PLIST_ENTRY Entry = List->ListHead.Flink;
117
118 if (Entry == &List->ListHead)
119 return NULL;
120 return CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
121 }
122
123 PGENERIC_LIST_ENTRY
124 GetNextListEntry(
125 IN PGENERIC_LIST_ENTRY Entry)
126 {
127 PLIST_ENTRY Next = Entry->Entry.Flink;
128
129 if (Next == &Entry->List->ListHead)
130 return NULL;
131 return CONTAINING_RECORD(Next, GENERIC_LIST_ENTRY, Entry);
132 }
133
134 PVOID
135 GetListEntryUserData(
136 IN PGENERIC_LIST_ENTRY Entry)
137 {
138 return Entry->UserData;
139 }
140
141 LPCSTR
142 GetListEntryText(
143 IN PGENERIC_LIST_ENTRY Entry)
144 {
145 return Entry->Text;
146 }
147
148 ULONG
149 GetNumberOfListEntries(
150 IN PGENERIC_LIST List)
151 {
152 return List->NumOfEntries;
153 }
154
155 VOID
156 SaveGenericListState(
157 IN PGENERIC_LIST List)
158 {
159 List->BackupEntry = List->CurrentEntry;
160 }
161
162 VOID
163 RestoreGenericListState(
164 IN PGENERIC_LIST List)
165 {
166 List->CurrentEntry = List->BackupEntry;
167 }
168
169 BOOLEAN
170 GenericListHasSingleEntry(
171 IN PGENERIC_LIST List)
172 {
173 if (!IsListEmpty(&List->ListHead) && List->ListHead.Flink == List->ListHead.Blink)
174 return TRUE;
175
176 /* if both list head pointers (which normally point to the first and last list member, respectively)
177 point to the same entry then it means that there's just a single thing in there, otherwise... false! */
178 return FALSE;
179 }
180
181 /* EOF */