includes: Fix alignment for 64-bits
[wine/wine64.git] / dlls / setupapi / stringtable.c
blob2f43c5c1924f55790bbd21eaa144ec5584c5387a
1 /*
2 * Setupapi string table functions
4 * Copyright 2005 Eric Kohl
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winreg.h"
31 #include "setupapi.h"
33 #include "wine/debug.h"
36 #define TABLE_DEFAULT_SIZE 256
38 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
40 DECLARE_HANDLE(HSTRING_TABLE);
42 typedef struct _TABLE_SLOT
44 LPWSTR pString;
45 LPVOID pData;
46 DWORD dwSize;
47 } TABLE_SLOT, *PTABLE_SLOT;
49 typedef struct _STRING_TABLE
51 PTABLE_SLOT pSlots;
52 DWORD dwUsedSlots;
53 DWORD dwMaxSlots;
54 DWORD dwMaxDataSize;
55 } STRING_TABLE, *PSTRING_TABLE;
58 /**************************************************************************
59 * StringTableInitialize [SETUPAPI.@]
61 * Creates a new string table and initializes it.
63 * PARAMS
64 * None
66 * RETURNS
67 * Success: Handle to the string table
68 * Failure: NULL
70 HSTRING_TABLE WINAPI
71 StringTableInitialize(VOID)
73 PSTRING_TABLE pStringTable;
75 TRACE("\n");
77 pStringTable = MyMalloc(sizeof(STRING_TABLE));
78 if (pStringTable == NULL)
80 ERR("Invalid hStringTable!\n");
81 return NULL;
84 memset(pStringTable, 0, sizeof(STRING_TABLE));
86 pStringTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE);
87 if (pStringTable->pSlots == NULL)
89 MyFree(pStringTable);
90 return NULL;
93 memset(pStringTable->pSlots, 0, sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE);
95 pStringTable->dwUsedSlots = 0;
96 pStringTable->dwMaxSlots = TABLE_DEFAULT_SIZE;
97 pStringTable->dwMaxDataSize = 0;
99 TRACE("Done\n");
101 return (HSTRING_TABLE)pStringTable;
105 /**************************************************************************
106 * StringTableInitializeEx [SETUPAPI.@]
108 * Creates a new string table and initializes it.
110 * PARAMS
111 * dwMaxExtraDataSize [I] Maximum extra data size
112 * dwReserved [I] Unused
114 * RETURNS
115 * Success: Handle to the string table
116 * Failure: NULL
118 HSTRING_TABLE WINAPI
119 StringTableInitializeEx(DWORD dwMaxExtraDataSize,
120 DWORD dwReserved)
122 PSTRING_TABLE pStringTable;
124 TRACE("\n");
126 pStringTable = MyMalloc(sizeof(STRING_TABLE));
127 if (pStringTable == NULL) return NULL;
129 memset(pStringTable, 0, sizeof(STRING_TABLE));
131 pStringTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE);
132 if (pStringTable->pSlots == NULL)
134 MyFree(pStringTable);
135 return NULL;
138 memset(pStringTable->pSlots, 0, sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE);
140 pStringTable->dwUsedSlots = 0;
141 pStringTable->dwMaxSlots = TABLE_DEFAULT_SIZE;
142 pStringTable->dwMaxDataSize = dwMaxExtraDataSize;
144 TRACE("Done\n");
146 return (HSTRING_TABLE)pStringTable;
150 /**************************************************************************
151 * StringTableDestroy [SETUPAPI.@]
153 * Destroys a string table.
155 * PARAMS
156 * hStringTable [I] Handle to the string table to be destroyed
158 * RETURNS
159 * None
161 VOID WINAPI
162 StringTableDestroy(HSTRING_TABLE hStringTable)
164 PSTRING_TABLE pStringTable;
165 DWORD i;
167 TRACE("%p\n", hStringTable);
169 pStringTable = (PSTRING_TABLE)hStringTable;
170 if (pStringTable == NULL)
171 return;
173 if (pStringTable->pSlots != NULL)
175 for (i = 0; i < pStringTable->dwMaxSlots; i++)
177 MyFree(pStringTable->pSlots[i].pString);
178 pStringTable->pSlots[i].pString = NULL;
180 MyFree(pStringTable->pSlots[i].pData);
181 pStringTable->pSlots[i].pData = NULL;
182 pStringTable->pSlots[i].dwSize = 0;
185 MyFree(pStringTable->pSlots);
188 MyFree(pStringTable);
192 /**************************************************************************
193 * StringTableAddStringEx [SETUPAPI.@]
195 * Adds a new string plus extra data to the string table.
197 * PARAMS
198 * hStringTable [I] Handle to the string table
199 * lpString [I] String to be added to the string table
200 * dwFlags [I] Flags
201 * 1: case sensitive compare
202 * lpExtraData [I] Pointer to the extra data
203 * dwExtraDataSize [I] Size of the extra data
205 * RETURNS
206 * Success: String ID
207 * Failure: ~0u
209 * NOTES
210 * If the given string already exists in the string table it will not
211 * be added again. The ID of the existing string will be returned in
212 * this case.
214 DWORD WINAPI
215 StringTableAddStringEx(HSTRING_TABLE hStringTable, LPWSTR lpString,
216 DWORD dwFlags, LPVOID lpExtraData, DWORD dwExtraDataSize)
218 PSTRING_TABLE pStringTable;
219 DWORD i;
221 TRACE("%p %s %x %p, %u\n", hStringTable, debugstr_w(lpString), dwFlags,
222 lpExtraData, dwExtraDataSize);
224 pStringTable = (PSTRING_TABLE)hStringTable;
225 if (!pStringTable)
227 ERR("Invalid hStringTable!\n");
228 return ~0u;
231 /* Search for existing string in the string table */
232 for (i = 0; i < pStringTable->dwMaxSlots; i++)
234 if (pStringTable->pSlots[i].pString)
236 if (dwFlags & 1)
238 if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString))
239 return i + 1;
241 else
243 if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString))
244 return i + 1;
249 /* Check for filled slot table */
250 if (pStringTable->dwUsedSlots == pStringTable->dwMaxSlots)
252 FIXME("Resize the string table!\n");
253 return ~0u;
256 /* Search for an empty slot */
257 for (i = 0; i < pStringTable->dwMaxSlots; i++)
259 if (!pStringTable->pSlots[i].pString)
261 pStringTable->pSlots[i].pString = MyMalloc((lstrlenW(lpString) + 1) * sizeof(WCHAR));
262 if (!pStringTable->pSlots[i].pString)
264 WARN("Couldn't allocate memory for a new string!\n");
265 return ~0u;
267 lstrcpyW(pStringTable->pSlots[i].pString, lpString);
269 pStringTable->pSlots[i].pData = MyMalloc(dwExtraDataSize);
270 if (!pStringTable->pSlots[i].pData)
272 TRACE("Couldn't allocate memory for data!\n");
273 return ~0u;
275 memcpy(pStringTable->pSlots[i].pData, lpExtraData, dwExtraDataSize);
276 pStringTable->dwUsedSlots++;
277 return i + 1;
280 TRACE("Couldn't find an empty slot!\n");
281 return ~0u;
284 /**************************************************************************
285 * StringTableAddString [SETUPAPI.@]
287 * Adds a new string to the string table.
289 * PARAMS
290 * hStringTable [I] Handle to the string table
291 * lpString [I] String to be added to the string table
292 * dwFlags [I] Flags
293 * 1: case sensitive compare
295 * RETURNS
296 * Success: String ID
297 * Failure: ~0u
299 * NOTES
300 * If the given string already exists in the string table it will not
301 * be added again. The ID of the existing string will be returned in
302 * this case.
304 DWORD WINAPI
305 StringTableAddString(HSTRING_TABLE hStringTable, LPWSTR lpString, DWORD dwFlags)
307 return StringTableAddStringEx(hStringTable, lpString, dwFlags, NULL, 0);
311 /**************************************************************************
312 * StringTableDuplicate [SETUPAPI.@]
314 * Duplicates a given string table.
316 * PARAMS
317 * hStringTable [I] Handle to the string table
319 * RETURNS
320 * Success: Handle to the duplicated string table
321 * Failure: NULL
324 HSTRING_TABLE WINAPI
325 StringTableDuplicate(HSTRING_TABLE hStringTable)
327 PSTRING_TABLE pSourceTable;
328 PSTRING_TABLE pDestinationTable;
329 DWORD i;
330 DWORD length;
332 TRACE("%p\n", hStringTable);
334 pSourceTable = (PSTRING_TABLE)hStringTable;
335 if (pSourceTable == NULL)
337 ERR("Invalid hStringTable!\n");
338 return NULL;
341 pDestinationTable = MyMalloc(sizeof(STRING_TABLE));
342 if (pDestinationTable == NULL)
344 ERR("Could not allocate a new string table!\n");
345 return NULL;
348 memset(pDestinationTable, 0, sizeof(STRING_TABLE));
350 pDestinationTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * pSourceTable->dwMaxSlots);
351 if (pDestinationTable->pSlots == NULL)
353 MyFree(pDestinationTable);
354 return NULL;
357 memset(pDestinationTable->pSlots, 0, sizeof(TABLE_SLOT) * pSourceTable->dwMaxSlots);
359 pDestinationTable->dwUsedSlots = 0;
360 pDestinationTable->dwMaxSlots = pSourceTable->dwMaxSlots;
362 for (i = 0; i < pSourceTable->dwMaxSlots; i++)
364 if (pSourceTable->pSlots[i].pString != NULL)
366 length = (lstrlenW(pSourceTable->pSlots[i].pString) + 1) * sizeof(WCHAR);
367 pDestinationTable->pSlots[i].pString = MyMalloc(length);
368 if (pDestinationTable->pSlots[i].pString != NULL)
370 memcpy(pDestinationTable->pSlots[i].pString,
371 pSourceTable->pSlots[i].pString,
372 length);
373 pDestinationTable->dwUsedSlots++;
376 if (pSourceTable->pSlots[i].pData != NULL)
378 length = pSourceTable->pSlots[i].dwSize;
379 pDestinationTable->pSlots[i].pData = MyMalloc(length);
380 if (pDestinationTable->pSlots[i].pData)
382 memcpy(pDestinationTable->pSlots[i].pData,
383 pSourceTable->pSlots[i].pData,
384 length);
385 pDestinationTable->pSlots[i].dwSize = length;
391 return (HSTRING_TABLE)pDestinationTable;
395 /**************************************************************************
396 * StringTableGetExtraData [SETUPAPI.@]
398 * Retrieves extra data from a given string table entry.
400 * PARAMS
401 * hStringTable [I] Handle to the string table
402 * dwId [I] String ID
403 * lpExtraData [I] Pointer a buffer that receives the extra data
404 * dwExtraDataSize [I] Size of the buffer
406 * RETURNS
407 * Success: TRUE
408 * Failure: FALSE
410 BOOL WINAPI
411 StringTableGetExtraData(HSTRING_TABLE hStringTable,
412 DWORD dwId,
413 LPVOID lpExtraData,
414 DWORD dwExtraDataSize)
416 PSTRING_TABLE pStringTable;
418 TRACE("%p %x %p %u\n",
419 hStringTable, dwId, lpExtraData, dwExtraDataSize);
421 pStringTable = (PSTRING_TABLE)hStringTable;
422 if (pStringTable == NULL)
424 ERR("Invalid hStringTable!\n");
425 return FALSE;
428 if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
430 ERR("Invalid Slot id!\n");
431 return FALSE;
434 if (pStringTable->pSlots[dwId - 1].dwSize > dwExtraDataSize)
436 ERR("Data size is too large!\n");
437 return FALSE;
440 memcpy(lpExtraData,
441 pStringTable->pSlots[dwId - 1].pData,
442 dwExtraDataSize);
444 return TRUE;
448 /**************************************************************************
449 * StringTableLookUpString [SETUPAPI.@]
451 * Searches a string table for a given string.
453 * PARAMS
454 * hStringTable [I] Handle to the string table
455 * lpString [I] String to be searched for
456 * dwFlags [I] Flags
457 * 1: case sensitive compare
459 * RETURNS
460 * Success: String ID
461 * Failure: -1
463 DWORD WINAPI
464 StringTableLookUpString(HSTRING_TABLE hStringTable,
465 LPWSTR lpString,
466 DWORD dwFlags)
468 PSTRING_TABLE pStringTable;
469 DWORD i;
471 TRACE("%p %s %x\n", hStringTable, debugstr_w(lpString), dwFlags);
473 pStringTable = (PSTRING_TABLE)hStringTable;
474 if (pStringTable == NULL)
476 ERR("Invalid hStringTable!\n");
477 return (DWORD)-1;
480 /* Search for existing string in the string table */
481 for (i = 0; i < pStringTable->dwMaxSlots; i++)
483 if (pStringTable->pSlots[i].pString != NULL)
485 if (dwFlags & 1)
487 if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString))
488 return i + 1;
490 else
492 if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString))
493 return i + 1;
498 return (DWORD)-1;
502 /**************************************************************************
503 * StringTableLookUpStringEx [SETUPAPI.@]
505 * Searches a string table and extra data for a given string.
507 * PARAMS
508 * hStringTable [I] Handle to the string table
509 * lpString [I] String to be searched for
510 * dwFlags [I] Flags
511 * 1: case sensitive compare
512 * lpExtraData [O] Pointer to the buffer that receives the extra data
513 * lpReserved [I/O] Unused
515 * RETURNS
516 * Success: String ID
517 * Failure: -1
519 DWORD WINAPI
520 StringTableLookUpStringEx(HSTRING_TABLE hStringTable,
521 LPWSTR lpString,
522 DWORD dwFlags,
523 LPVOID lpExtraData,
524 LPDWORD lpReserved)
526 FIXME("\n");
527 return (DWORD)-1;
531 /**************************************************************************
532 * StringTableSetExtraData [SETUPAPI.@]
534 * Sets extra data for a given string table entry.
536 * PARAMS
537 * hStringTable [I] Handle to the string table
538 * dwId [I] String ID
539 * lpExtraData [I] Pointer to the extra data
540 * dwExtraDataSize [I] Size of the extra data
542 * RETURNS
543 * Success: TRUE
544 * Failure: FALSE
546 BOOL WINAPI
547 StringTableSetExtraData(HSTRING_TABLE hStringTable,
548 DWORD dwId,
549 LPVOID lpExtraData,
550 DWORD dwExtraDataSize)
552 PSTRING_TABLE pStringTable;
554 TRACE("%p %x %p %u\n",
555 hStringTable, dwId, lpExtraData, dwExtraDataSize);
557 pStringTable = (PSTRING_TABLE)hStringTable;
558 if (pStringTable == NULL)
560 ERR("Invalid hStringTable!\n");
561 return FALSE;
564 if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
566 ERR("Invalid Slot id!\n");
567 return FALSE;
570 if (pStringTable->dwMaxDataSize < dwExtraDataSize)
572 ERR("Data size is too large!\n");
573 return FALSE;
576 pStringTable->pSlots[dwId - 1].pData = MyMalloc(dwExtraDataSize);
577 if (pStringTable->pSlots[dwId - 1].pData == NULL)
579 ERR("\n");
580 return FALSE;
583 memcpy(pStringTable->pSlots[dwId - 1].pData,
584 lpExtraData,
585 dwExtraDataSize);
586 pStringTable->pSlots[dwId - 1].dwSize = dwExtraDataSize;
588 return TRUE;
592 /**************************************************************************
593 * StringTableStringFromId [SETUPAPI.@]
595 * Returns a pointer to a string for the given string ID.
597 * PARAMS
598 * hStringTable [I] Handle to the string table.
599 * dwId [I] String ID
601 * RETURNS
602 * Success: Pointer to the string
603 * Failure: NULL
605 LPWSTR WINAPI
606 StringTableStringFromId(HSTRING_TABLE hStringTable,
607 DWORD dwId)
609 PSTRING_TABLE pStringTable;
610 static WCHAR empty[] = {0};
612 TRACE("%p %x\n", hStringTable, dwId);
614 pStringTable = (PSTRING_TABLE)hStringTable;
615 if (pStringTable == NULL)
617 ERR("Invalid hStringTable!\n");
618 return NULL;
621 if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
622 return empty;
624 return pStringTable->pSlots[dwId - 1].pString;
628 /**************************************************************************
629 * StringTableStringFromIdEx [SETUPAPI.@]
631 * Returns a string for the given string ID.
633 * PARAMS
634 * hStringTable [I] Handle to the string table
635 * dwId [I] String ID
636 * lpBuffer [I] Pointer to string buffer
637 * lpBufferSize [I/O] Pointer to the size of the string buffer
639 * RETURNS
640 * Success: TRUE
641 * Failure: FALSE
643 BOOL WINAPI
644 StringTableStringFromIdEx(HSTRING_TABLE hStringTable,
645 DWORD dwId,
646 LPWSTR lpBuffer,
647 LPDWORD lpBufferLength)
649 PSTRING_TABLE pStringTable;
650 DWORD dwLength;
651 BOOL bResult = FALSE;
653 TRACE("%p %x %p %p\n", hStringTable, dwId, lpBuffer, lpBufferLength);
655 pStringTable = (PSTRING_TABLE)hStringTable;
656 if (pStringTable == NULL)
658 ERR("Invalid hStringTable!\n");
659 *lpBufferLength = 0;
660 return FALSE;
663 if (dwId == 0 || dwId > pStringTable->dwMaxSlots ||
664 pStringTable->pSlots[dwId - 1].pString == NULL)
666 WARN("Invalid string ID!\n");
667 *lpBufferLength = 0;
668 return FALSE;
671 dwLength = (lstrlenW(pStringTable->pSlots[dwId - 1].pString) + 1) * sizeof(WCHAR);
672 if (dwLength <= *lpBufferLength)
674 lstrcpyW(lpBuffer, pStringTable->pSlots[dwId - 1].pString);
675 bResult = TRUE;
678 *lpBufferLength = dwLength;
680 return bResult;
684 /**************************************************************************
685 * StringTableTrim [SETUPAPI.@]
687 * ...
689 * PARAMS
690 * hStringTable [I] Handle to the string table
692 * RETURNS
693 * None
695 VOID WINAPI
696 StringTableTrim(HSTRING_TABLE hStringTable)
698 FIXME("%p\n", hStringTable);