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 "setupapi_private.h"
23 #define TABLE_DEFAULT_SIZE 256
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
27 typedef struct _TABLE_SLOT
32 } TABLE_SLOT
, *PTABLE_SLOT
;
34 typedef struct _STRING_TABLE
40 } STRING_TABLE
, *PSTRING_TABLE
;
43 /**************************************************************************
44 * pSetupStringTableInitialize [SETUPAPI.@]
46 * Creates a new string table and initializes it.
52 * Success: Handle to the string table
56 pSetupStringTableInitialize(VOID
)
58 PSTRING_TABLE pStringTable
;
62 pStringTable
= MyMalloc(sizeof(STRING_TABLE
));
63 if (pStringTable
== NULL
)
65 ERR("Invalid hStringTable!\n");
69 memset(pStringTable
, 0, sizeof(STRING_TABLE
));
71 pStringTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
72 if (pStringTable
->pSlots
== NULL
)
78 memset(pStringTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
80 pStringTable
->dwUsedSlots
= 0;
81 pStringTable
->dwMaxSlots
= TABLE_DEFAULT_SIZE
;
82 pStringTable
->dwMaxDataSize
= 0;
86 return (HSTRING_TABLE
)pStringTable
;
90 /**************************************************************************
91 * pSetupStringTableInitializeEx [SETUPAPI.@]
93 * Creates a new string table and initializes it.
96 * dwMaxExtraDataSize [I] Maximum extra data size
97 * dwReserved [I] Unused
100 * Success: Handle to the string table
104 pSetupStringTableInitializeEx(DWORD dwMaxExtraDataSize
,
107 PSTRING_TABLE pStringTable
;
111 pStringTable
= MyMalloc(sizeof(STRING_TABLE
));
112 if (pStringTable
== NULL
) return NULL
;
114 memset(pStringTable
, 0, sizeof(STRING_TABLE
));
116 pStringTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
117 if (pStringTable
->pSlots
== NULL
)
119 MyFree(pStringTable
);
123 memset(pStringTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
125 pStringTable
->dwUsedSlots
= 0;
126 pStringTable
->dwMaxSlots
= TABLE_DEFAULT_SIZE
;
127 pStringTable
->dwMaxDataSize
= dwMaxExtraDataSize
;
131 return (HSTRING_TABLE
)pStringTable
;
135 /**************************************************************************
136 * pSetupStringTableDestroy [SETUPAPI.@]
138 * Destroys a string table.
141 * hStringTable [I] Handle to the string table to be destroyed
147 pSetupStringTableDestroy(HSTRING_TABLE hStringTable
)
149 PSTRING_TABLE pStringTable
;
152 TRACE("%p\n", hStringTable
);
154 pStringTable
= (PSTRING_TABLE
)hStringTable
;
155 if (pStringTable
== NULL
)
158 if (pStringTable
->pSlots
!= NULL
)
160 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
162 MyFree(pStringTable
->pSlots
[i
].pString
);
163 pStringTable
->pSlots
[i
].pString
= NULL
;
165 MyFree(pStringTable
->pSlots
[i
].pData
);
166 pStringTable
->pSlots
[i
].pData
= NULL
;
167 pStringTable
->pSlots
[i
].dwSize
= 0;
170 MyFree(pStringTable
->pSlots
);
173 MyFree(pStringTable
);
177 /**************************************************************************
178 * pSetupStringTableAddString [SETUPAPI.@]
180 * Adds a new string to the string table.
183 * hStringTable [I] Handle to the string table
184 * lpString [I] String to be added to the string table
186 * 1: case sensitive compare
193 * If the given string already exists in the string table it will not
194 * be added again. The ID of the existing string will be returned in
198 pSetupStringTableAddString(HSTRING_TABLE hStringTable
,
202 PSTRING_TABLE pStringTable
;
205 TRACE("%p %s %x\n", hStringTable
, debugstr_w(lpString
), dwFlags
);
207 pStringTable
= (PSTRING_TABLE
)hStringTable
;
208 if (pStringTable
== NULL
)
210 ERR("Invalid hStringTable!\n");
214 /* Search for existing string in the string table */
215 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
217 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
221 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
228 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
236 /* Check for filled slot table */
237 if (pStringTable
->dwUsedSlots
== pStringTable
->dwMaxSlots
)
239 PTABLE_SLOT pNewSlots
;
242 /* FIXME: not thread safe */
243 dwNewMaxSlots
= pStringTable
->dwMaxSlots
* 2;
244 pNewSlots
= MyMalloc(sizeof(TABLE_SLOT
) * dwNewMaxSlots
);
245 if (pNewSlots
== NULL
)
247 memset(&pNewSlots
[pStringTable
->dwMaxSlots
], 0, sizeof(TABLE_SLOT
) * (dwNewMaxSlots
- pStringTable
->dwMaxSlots
));
248 memcpy(pNewSlots
, pStringTable
->pSlots
, sizeof(TABLE_SLOT
) * pStringTable
->dwMaxSlots
);
249 pNewSlots
= InterlockedExchangePointer(&pStringTable
->pSlots
, pNewSlots
);
251 pStringTable
->dwMaxSlots
= dwNewMaxSlots
;
253 return pSetupStringTableAddString(hStringTable
, lpString
, dwFlags
);
256 /* Search for an empty slot */
257 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
259 if (pStringTable
->pSlots
[i
].pString
== NULL
)
261 pStringTable
->pSlots
[i
].pString
= MyMalloc((lstrlenW(lpString
) + 1) * sizeof(WCHAR
));
262 if (pStringTable
->pSlots
[i
].pString
== NULL
)
264 TRACE("Couldn't allocate memory for a new string!\n");
268 lstrcpyW(pStringTable
->pSlots
[i
].pString
, lpString
);
270 pStringTable
->dwUsedSlots
++;
276 TRACE("Couldn't find an empty slot!\n");
282 /**************************************************************************
283 * pSetupStringTableAddStringEx [SETUPAPI.@]
285 * Adds a new string plus extra data to the string table.
288 * hStringTable [I] Handle to the string table
289 * lpString [I] String to be added to the string table
291 * 1: case sensitive compare
292 * lpExtraData [I] Pointer to the extra data
293 * dwExtraDataSize [I] Size of the extra data
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
305 pSetupStringTableAddStringEx(HSTRING_TABLE hStringTable
,
309 DWORD dwExtraDataSize
)
311 PSTRING_TABLE pStringTable
;
314 TRACE("%p %s %lx\n", (PVOID
)hStringTable
, debugstr_w(lpString
), dwFlags
);
316 pStringTable
= (PSTRING_TABLE
)hStringTable
;
317 if (pStringTable
== NULL
)
319 ERR("Invalid hStringTable!\n");
323 /* Search for existing string in the string table */
324 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
326 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
330 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
337 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
345 /* Check for filled slot table */
346 if (pStringTable
->dwUsedSlots
== pStringTable
->dwMaxSlots
)
348 FIXME("Resize the string table!\n");
352 /* Search for an empty slot */
353 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
355 if (pStringTable
->pSlots
[i
].pString
== NULL
)
357 pStringTable
->pSlots
[i
].pString
= MyMalloc((lstrlenW(lpString
) + 1) * sizeof(WCHAR
));
358 if (pStringTable
->pSlots
[i
].pString
== NULL
)
360 TRACE("Couldn't allocate memory for a new string!\n");
364 lstrcpyW(pStringTable
->pSlots
[i
].pString
, lpString
);
366 pStringTable
->pSlots
[i
].pData
= MyMalloc(dwExtraDataSize
);
367 if (pStringTable
->pSlots
[i
].pData
== NULL
)
369 TRACE("Couldn't allocate memory for a new extra data!\n");
370 MyFree(pStringTable
->pSlots
[i
].pString
);
371 pStringTable
->pSlots
[i
].pString
= NULL
;
375 memcpy(pStringTable
->pSlots
[i
].pData
,
378 pStringTable
->pSlots
[i
].dwSize
= dwExtraDataSize
;
380 pStringTable
->dwUsedSlots
++;
386 TRACE("Couldn't find an empty slot!\n");
392 /**************************************************************************
393 * pSetupStringTableDuplicate [SETUPAPI.@]
395 * Duplicates a given string table.
398 * hStringTable [I] Handle to the string table
401 * Success: Handle to the duplicated string table
406 pSetupStringTableDuplicate(HSTRING_TABLE hStringTable
)
408 PSTRING_TABLE pSourceTable
;
409 PSTRING_TABLE pDestinationTable
;
413 TRACE("%p\n", hStringTable
);
415 pSourceTable
= (PSTRING_TABLE
)hStringTable
;
416 if (pSourceTable
== NULL
)
418 ERR("Invalid hStringTable!\n");
419 return (HSTRING_TABLE
)NULL
;
422 pDestinationTable
= MyMalloc(sizeof(STRING_TABLE
));
423 if (pDestinationTable
== NULL
)
425 ERR("Could not allocate a new string table!\n");
426 return (HSTRING_TABLE
)NULL
;
429 memset(pDestinationTable
, 0, sizeof(STRING_TABLE
));
431 pDestinationTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * pSourceTable
->dwMaxSlots
);
432 if (pDestinationTable
->pSlots
== NULL
)
434 MyFree(pDestinationTable
);
435 return (HSTRING_TABLE
)NULL
;
438 memset(pDestinationTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * pSourceTable
->dwMaxSlots
);
440 pDestinationTable
->dwUsedSlots
= 0;
441 pDestinationTable
->dwMaxSlots
= pSourceTable
->dwMaxSlots
;
443 for (i
= 0; i
< pSourceTable
->dwMaxSlots
; i
++)
445 if (pSourceTable
->pSlots
[i
].pString
!= NULL
)
447 length
= (lstrlenW(pSourceTable
->pSlots
[i
].pString
) + 1) * sizeof(WCHAR
);
448 pDestinationTable
->pSlots
[i
].pString
= MyMalloc(length
);
449 if (pDestinationTable
->pSlots
[i
].pString
!= NULL
)
451 memcpy(pDestinationTable
->pSlots
[i
].pString
,
452 pSourceTable
->pSlots
[i
].pString
,
454 pDestinationTable
->dwUsedSlots
++;
457 if (pSourceTable
->pSlots
[i
].pData
!= NULL
)
459 length
= pSourceTable
->pSlots
[i
].dwSize
;
460 pDestinationTable
->pSlots
[i
].pData
= MyMalloc(length
);
461 if (pDestinationTable
->pSlots
[i
].pData
)
463 memcpy(pDestinationTable
->pSlots
[i
].pData
,
464 pSourceTable
->pSlots
[i
].pData
,
466 pDestinationTable
->pSlots
[i
].dwSize
= length
;
472 return (HSTRING_TABLE
)pDestinationTable
;
476 /**************************************************************************
477 * pSetupStringTableGetExtraData [SETUPAPI.@]
479 * Retrieves extra data from a given string table entry.
482 * hStringTable [I] Handle to the string table
484 * lpExtraData [I] Pointer a buffer that receives the extra data
485 * dwExtraDataSize [I] Size of the buffer
492 pSetupStringTableGetExtraData(HSTRING_TABLE hStringTable
,
495 DWORD dwExtraDataSize
)
497 PSTRING_TABLE pStringTable
;
499 TRACE("%p %x %p %u\n",
500 hStringTable
, dwId
, lpExtraData
, dwExtraDataSize
);
502 pStringTable
= (PSTRING_TABLE
)hStringTable
;
503 if (pStringTable
== NULL
)
505 ERR("Invalid hStringTable!\n");
509 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
511 ERR("Invalid Slot id!\n");
515 if (pStringTable
->pSlots
[dwId
- 1].dwSize
< dwExtraDataSize
)
517 ERR("Data size is too large!\n");
522 pStringTable
->pSlots
[dwId
- 1].pData
,
529 /**************************************************************************
530 * pSetupStringTableLookUpString [SETUPAPI.@]
532 * Searches a string table for a given string.
535 * hStringTable [I] Handle to the string table
536 * lpString [I] String to be searched for
538 * 1: case sensitive compare
545 pSetupStringTableLookUpString(HSTRING_TABLE hStringTable
,
549 PSTRING_TABLE pStringTable
;
552 TRACE("%p %s %x\n", hStringTable
, debugstr_w(lpString
), dwFlags
);
554 pStringTable
= (PSTRING_TABLE
)hStringTable
;
555 if (pStringTable
== NULL
)
557 ERR("Invalid hStringTable!\n");
561 /* Search for existing string in the string table */
562 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
564 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
568 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
573 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
583 /**************************************************************************
584 * pSetupStringTableLookUpStringEx [SETUPAPI.@]
586 * Searches a string table and extra data for a given string.
589 * hStringTable [I] Handle to the string table
590 * lpString [I] String to be searched for
592 * 1: case sensitive compare
593 * lpExtraData [O] Pointer to the buffer that receives the extra data
594 * lpReserved [I/O] Unused
601 pSetupStringTableLookUpStringEx(HSTRING_TABLE hStringTable
,
607 PSTRING_TABLE pStringTable
;
610 TRACE("%p %s %x %p, %x\n", hStringTable
, debugstr_w(lpString
), dwFlags
,
611 lpExtraData
, dwReserved
);
613 pStringTable
= (PSTRING_TABLE
)hStringTable
;
614 if (pStringTable
== NULL
)
616 ERR("Invalid hStringTable!\n");
620 /* Search for existing string in the string table */
621 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
623 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
627 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
630 memcpy(lpExtraData
, pStringTable
->pSlots
[i
].pData
, dwReserved
);
636 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
639 memcpy(lpExtraData
, pStringTable
->pSlots
[i
].pData
, dwReserved
);
649 /**************************************************************************
650 * pSetupStringTableSetExtraData [SETUPAPI.@]
652 * Sets extra data for a given string table entry.
655 * hStringTable [I] Handle to the string table
657 * lpExtraData [I] Pointer to the extra data
658 * dwExtraDataSize [I] Size of the extra data
665 pSetupStringTableSetExtraData(HSTRING_TABLE hStringTable
,
668 DWORD dwExtraDataSize
)
670 PSTRING_TABLE pStringTable
;
672 TRACE("%p %x %p %u\n",
673 hStringTable
, dwId
, lpExtraData
, dwExtraDataSize
);
675 pStringTable
= (PSTRING_TABLE
)hStringTable
;
676 if (pStringTable
== NULL
)
678 ERR("Invalid hStringTable!\n");
682 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
684 ERR("Invalid Slot id!\n");
688 if (pStringTable
->dwMaxDataSize
< dwExtraDataSize
)
690 ERR("Data size is too large!\n");
694 pStringTable
->pSlots
[dwId
- 1].pData
= MyMalloc(dwExtraDataSize
);
695 if (pStringTable
->pSlots
[dwId
- 1].pData
== NULL
)
701 memcpy(pStringTable
->pSlots
[dwId
- 1].pData
,
704 pStringTable
->pSlots
[dwId
- 1].dwSize
= dwExtraDataSize
;
710 /**************************************************************************
711 * pSetupStringTableStringFromId [SETUPAPI.@]
713 * Returns a pointer to a string for the given string ID.
716 * hStringTable [I] Handle to the string table.
720 * Success: Pointer to the string
724 pSetupStringTableStringFromId(HSTRING_TABLE hStringTable
,
727 PSTRING_TABLE pStringTable
;
728 static WCHAR empty
[] = {0};
730 TRACE("%p %x\n", hStringTable
, dwId
);
732 pStringTable
= (PSTRING_TABLE
)hStringTable
;
733 if (pStringTable
== NULL
)
735 ERR("Invalid hStringTable!\n");
739 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
742 return pStringTable
->pSlots
[dwId
- 1].pString
;
746 /**************************************************************************
747 * pSetupStringTableStringFromIdEx [SETUPAPI.@]
749 * Returns a string for the given string ID.
752 * hStringTable [I] Handle to the string table
754 * lpBuffer [I] Pointer to string buffer
755 * lpBufferSize [I/O] Pointer to the size of the string buffer
762 pSetupStringTableStringFromIdEx(HSTRING_TABLE hStringTable
,
765 LPDWORD lpBufferLength
)
767 PSTRING_TABLE pStringTable
;
769 BOOL bResult
= FALSE
;
771 TRACE("%p %x %p %p\n", hStringTable
, dwId
, lpBuffer
, lpBufferLength
);
773 pStringTable
= (PSTRING_TABLE
)hStringTable
;
774 if (pStringTable
== NULL
)
776 ERR("Invalid hStringTable!\n");
781 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
||
782 pStringTable
->pSlots
[dwId
- 1].pString
== NULL
)
784 WARN("Invalid string ID!\n");
789 dwLength
= (lstrlenW(pStringTable
->pSlots
[dwId
- 1].pString
) + 1) * sizeof(WCHAR
);
790 if (dwLength
<= *lpBufferLength
)
792 lstrcpyW(lpBuffer
, pStringTable
->pSlots
[dwId
- 1].pString
);
796 *lpBufferLength
= dwLength
;