ReactOS  0.4.14-dev-608-gd495a4f
sdbstringtable.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Application compatibility module
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Shim database string table builder
5  * COPYRIGHT: Copyright 2016-2019 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #if !defined(SDBWRITE_HOSTTOOL)
9 #define WIN32_NO_STATUS
10 #include "windows.h"
11 #include <appcompat/sdbtypes.h>
12 #include "sdbpapi.h"
13 #else /* !defined(SDBWRITE_HOSTTOOL) */
14 #include <typedefs.h>
15 #include <guiddef.h>
16 #include "sdbtypes.h"
17 #include "sdbpapi.h"
18 #endif /* !defined(SDBWRITE_HOSTTOOL) */
19 
20 #include "sdbstringtable.h"
21 
22 #if !defined(offsetof)
23 #if defined(__GNUC__)
24 #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
25 #else
26 #define offsetof(TYPE, MEMBER) ((size_t)&(((TYPE *)0)->MEMBER))
27 #endif
28 #endif // !defined(offsetof)
29 
30 #define DEFAULT_TABLE_SIZE 0x100
31 
32 typedef struct SdbHashEntry
33 {
34  struct SdbHashEntry* Next;
36  WCHAR Name[1];
37 } SdbHashEntry;
38 
40 {
43 };
44 
45 
46 static struct SdbStringHashTable* HashCreate(void)
47 {
48  struct SdbStringHashTable* tab = SdbAlloc(sizeof(*tab));
49  if (!tab)
50  {
51  SHIM_ERR("Failed to allocate 8 bytes.\r\n");
52  return tab;
53  }
54  tab->Size = DEFAULT_TABLE_SIZE;
55  tab->Entries = SdbAlloc(tab->Size * sizeof(*tab->Entries));
56  return tab;
57 }
58 
59 
61 {
62  struct SdbStringHashTable* table = *pTable;
63  struct SdbHashEntry* entry, *next;
64  DWORD n, depth = 0, once = 1;
65 
66  *pTable = NULL;
67  for (n = 0; n < table->Size; ++n)
68  {
69  depth = 0;
70  entry = next = table->Entries[n];
71  while (entry)
72  {
73  next = entry->Next;
74  SdbFree(entry);
75  entry = next;
76  depth++;
77  }
78  if (once && depth > 3)
79  {
80  // warn
81  once = 0;
82  }
83  }
84  SdbFree(table->Entries);
85  SdbFree(table);
86 }
87 
88 /* Based on RtlHashUnicodeString */
89 static DWORD StringHash(const WCHAR* str)
90 {
91  DWORD hash = 0;
92  for (; *str; str++)
93  {
94  hash = ((65599 * hash) + (ULONG)(*str));
95  }
96  return hash;
97 }
98 
99 int Sdbwcscmp(const WCHAR* s1, const WCHAR* s2)
100 {
101  while (*s1 == *s2)
102  {
103  if (*s1 == 0)
104  return 0;
105  s1++;
106  s2++;
107  }
108  return *s1 - *s2;
109 }
110 
111 
112 // implementation taken from reactos/sdk/lib/crt/string/wcs.c
113 INT Sdbwcscpy(WCHAR* wcDest, size_t numElement, const WCHAR *wcSrc)
114 {
115  size_t size = 0;
116  if(!wcDest || !numElement)
117  return 22; /* EINVAL */
118 
119  wcDest[0] = 0;
120 
121  if(!wcSrc)
122  return 22; /* EINVAL */
123 
124  size = SdbpStrlen(wcSrc) + 1;
125 
126  if(size > numElement)
127  return 34; /* ERANGE */
128 
129  memcpy(wcDest, wcSrc, size * sizeof(WCHAR));
130 
131  return 0;
132 }
133 
134 static struct SdbHashEntry** TableFindPtr(struct SdbStringHashTable* table, const WCHAR* str)
135 {
137  struct SdbHashEntry** entry = &table->Entries[hash % table->Size];
138  while (*entry)
139  {
140  if (!Sdbwcscmp((*entry)->Name, str))
141  return entry;
142  entry = &(*entry)->Next;
143  }
144  return entry;
145 }
146 
147 static BOOL HashAddString(struct SdbStringHashTable* table, struct SdbHashEntry** position, const WCHAR* str, TAGID tagid)
148 {
149  struct SdbHashEntry* entry;
150  SIZE_T size, len;
151 
152  if (!position)
153  position = TableFindPtr(table, str);
154 
155  len = SdbpStrlen(str) + 1;
156  size = offsetof(struct SdbHashEntry, Name[len]);
157  entry = (*position) = SdbAlloc(size);
158  if (!entry)
159  {
160  SHIM_ERR("Failed to allocate %u bytes.", size);
161  return FALSE;
162  }
163  entry->Tagid = tagid;
164  Sdbwcscpy(entry->Name, len, str);
165  return TRUE;
166 }
167 
168 
170 {
171  struct SdbHashEntry** entry;
172 
173  if (!*table)
174  {
175  *table = HashCreate();
176  if (!*table)
177  {
178  SHIM_ERR("Error creating hash table\n");
179  return FALSE;
180  }
181  }
182 
184  if (*entry)
185  {
186  *tagid = (*entry)->Tagid;
187  return FALSE;
188  }
189  return HashAddString(*table, entry, str, *tagid);
190 }
191 
struct S2 s2
#define TRUE
Definition: types.h:120
INT Sdbwcscpy(WCHAR *wcDest, size_t numElement, const WCHAR *wcSrc)
GLdouble n
Definition: glext.h:7729
void SdbpTableDestroy(struct SdbStringHashTable **pTable)
int32_t INT
Definition: typedefs.h:56
#define SdbFree(mem)
Definition: sdbpapi.h:37
#define SdbAlloc(size)
Definition: sdbpapi.h:35
struct SdbHashEntry * Next
static const unsigned char *static size_t const wchar_t * wcSrc
Definition: string.c:66
int hash
Definition: main.c:58
unsigned int BOOL
Definition: ntddk_ex.h:94
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
static DWORD StringHash(const WCHAR *str)
#define DEFAULT_TABLE_SIZE
static BOOL HashAddString(struct SdbStringHashTable *table, struct SdbHashEntry **position, const WCHAR *str, TAGID tagid)
GLsizeiptr size
Definition: glext.h:5919
__wchar_t WCHAR
Definition: xmlstorage.h:180
struct S1 s1
unsigned long DWORD
Definition: ntddk_ex.h:95
struct SdbHashEntry ** Entries
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
int Sdbwcscmp(const WCHAR *s1, const WCHAR *s2)
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
struct SdbHashEntry SdbHashEntry
static struct SdbStringHashTable * HashCreate(void)
DWORD SdbpStrlen(PCWSTR string)
Definition: sdbapi.c:152
ULONG_PTR SIZE_T
Definition: typedefs.h:78
static unsigned __int64 next
Definition: rand_nt.c:6
unsigned int ULONG
Definition: retypes.h:1
static const EHCI_PERIOD pTable[]
Definition: usbehci.c:29
DWORD TAGID
Definition: _hash_fun.h:40
BOOL SdbpAddStringToTable(struct SdbStringHashTable **table, const WCHAR *str, TAGID *tagid)
static struct SdbHashEntry ** TableFindPtr(struct SdbStringHashTable *table, const WCHAR *str)