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 typedef struct _TABLE_SLOT
30 } TABLE_SLOT
, *PTABLE_SLOT
;
32 typedef struct _STRING_TABLE
38 } STRING_TABLE
, *PSTRING_TABLE
;
41 /**************************************************************************
42 * pSetupStringTableInitialize [SETUPAPI.@]
44 * Creates a new string table and initializes it.
50 * Success: Handle to the string table
54 pSetupStringTableInitialize(VOID
)
56 PSTRING_TABLE pStringTable
;
60 pStringTable
= MyMalloc(sizeof(STRING_TABLE
));
61 if (pStringTable
== NULL
)
63 ERR("Invalid hStringTable!\n");
67 memset(pStringTable
, 0, sizeof(STRING_TABLE
));
69 pStringTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
70 if (pStringTable
->pSlots
== NULL
)
76 memset(pStringTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
78 pStringTable
->dwUsedSlots
= 0;
79 pStringTable
->dwMaxSlots
= TABLE_DEFAULT_SIZE
;
80 pStringTable
->dwMaxDataSize
= 0;
84 return (HSTRING_TABLE
)pStringTable
;
88 /**************************************************************************
89 * pSetupStringTableInitializeEx [SETUPAPI.@]
91 * Creates a new string table and initializes it.
94 * dwMaxExtraDataSize [I] Maximum extra data size
95 * dwReserved [I] Unused
98 * Success: Handle to the string table
102 pSetupStringTableInitializeEx(DWORD dwMaxExtraDataSize
,
105 PSTRING_TABLE pStringTable
;
109 pStringTable
= MyMalloc(sizeof(STRING_TABLE
));
110 if (pStringTable
== NULL
) return NULL
;
112 memset(pStringTable
, 0, sizeof(STRING_TABLE
));
114 pStringTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
115 if (pStringTable
->pSlots
== NULL
)
117 MyFree(pStringTable
);
121 memset(pStringTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
123 pStringTable
->dwUsedSlots
= 0;
124 pStringTable
->dwMaxSlots
= TABLE_DEFAULT_SIZE
;
125 pStringTable
->dwMaxDataSize
= dwMaxExtraDataSize
;
129 return (HSTRING_TABLE
)pStringTable
;
133 /**************************************************************************
134 * pSetupStringTableDestroy [SETUPAPI.@]
136 * Destroys a string table.
139 * hStringTable [I] Handle to the string table to be destroyed
145 pSetupStringTableDestroy(HSTRING_TABLE hStringTable
)
147 PSTRING_TABLE pStringTable
;
150 TRACE("%p\n", hStringTable
);
152 pStringTable
= (PSTRING_TABLE
)hStringTable
;
153 if (pStringTable
== NULL
)
156 if (pStringTable
->pSlots
!= NULL
)
158 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
160 MyFree(pStringTable
->pSlots
[i
].pString
);
161 pStringTable
->pSlots
[i
].pString
= NULL
;
163 MyFree(pStringTable
->pSlots
[i
].pData
);
164 pStringTable
->pSlots
[i
].pData
= NULL
;
165 pStringTable
->pSlots
[i
].dwSize
= 0;
168 MyFree(pStringTable
->pSlots
);
171 MyFree(pStringTable
);
175 /**************************************************************************
176 * pSetupStringTableAddString [SETUPAPI.@]
178 * Adds a new string to the string table.
181 * hStringTable [I] Handle to the string table
182 * lpString [I] String to be added to the string table
184 * 1: case sensitive compare
191 * If the given string already exists in the string table it will not
192 * be added again. The ID of the existing string will be returned in
196 pSetupStringTableAddString(HSTRING_TABLE hStringTable
,
200 PSTRING_TABLE pStringTable
;
203 TRACE("%p %s %x\n", hStringTable
, debugstr_w(lpString
), dwFlags
);
205 pStringTable
= (PSTRING_TABLE
)hStringTable
;
206 if (pStringTable
== NULL
)
208 ERR("Invalid hStringTable!\n");
212 /* Search for existing string in the string table */
213 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
215 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
219 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
226 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
234 /* Check for filled slot table */
235 if (pStringTable
->dwUsedSlots
== pStringTable
->dwMaxSlots
)
237 PTABLE_SLOT pNewSlots
;
240 /* FIXME: not thread safe */
241 dwNewMaxSlots
= pStringTable
->dwMaxSlots
* 2;
242 pNewSlots
= MyMalloc(sizeof(TABLE_SLOT
) * dwNewMaxSlots
);
243 if (pNewSlots
== NULL
)
245 memset(&pNewSlots
[pStringTable
->dwMaxSlots
], 0, sizeof(TABLE_SLOT
) * (dwNewMaxSlots
- pStringTable
->dwMaxSlots
));
246 memcpy(pNewSlots
, pStringTable
->pSlots
, sizeof(TABLE_SLOT
) * pStringTable
->dwMaxSlots
);
247 pNewSlots
= InterlockedExchangePointer(&pStringTable
->pSlots
, pNewSlots
);
249 pStringTable
->dwMaxSlots
= dwNewMaxSlots
;
251 return pSetupStringTableAddString(hStringTable
, lpString
, dwFlags
);
254 /* Search for an empty slot */
255 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
257 if (pStringTable
->pSlots
[i
].pString
== NULL
)
259 pStringTable
->pSlots
[i
].pString
= MyMalloc((lstrlenW(lpString
) + 1) * sizeof(WCHAR
));
260 if (pStringTable
->pSlots
[i
].pString
== NULL
)
262 TRACE("Couldn't allocate memory for a new string!\n");
266 lstrcpyW(pStringTable
->pSlots
[i
].pString
, lpString
);
268 pStringTable
->dwUsedSlots
++;
274 TRACE("Couldn't find an empty slot!\n");
280 /**************************************************************************
281 * pSetupStringTableAddStringEx [SETUPAPI.@]
283 * Adds a new string plus extra data to the string table.
286 * hStringTable [I] Handle to the string table
287 * lpString [I] String to be added to the string table
289 * 1: case sensitive compare
290 * lpExtraData [I] Pointer to the extra data
291 * dwExtraDataSize [I] Size of the extra data
298 * If the given string already exists in the string table it will not
299 * be added again. The ID of the existing string will be returned in
303 pSetupStringTableAddStringEx(HSTRING_TABLE hStringTable
,
307 DWORD dwExtraDataSize
)
309 PSTRING_TABLE pStringTable
;
312 TRACE("%p %s %lx\n", (PVOID
)hStringTable
, debugstr_w(lpString
), dwFlags
);
314 pStringTable
= (PSTRING_TABLE
)hStringTable
;
315 if (pStringTable
== NULL
)
317 ERR("Invalid hStringTable!\n");
321 /* Search for existing string in the string table */
322 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
324 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
328 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
335 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
343 /* Check for filled slot table */
344 if (pStringTable
->dwUsedSlots
== pStringTable
->dwMaxSlots
)
346 FIXME("Resize the string table!\n");
350 /* Search for an empty slot */
351 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
353 if (pStringTable
->pSlots
[i
].pString
== NULL
)
355 pStringTable
->pSlots
[i
].pString
= MyMalloc((lstrlenW(lpString
) + 1) * sizeof(WCHAR
));
356 if (pStringTable
->pSlots
[i
].pString
== NULL
)
358 TRACE("Couldn't allocate memory for a new string!\n");
362 lstrcpyW(pStringTable
->pSlots
[i
].pString
, lpString
);
364 pStringTable
->pSlots
[i
].pData
= MyMalloc(dwExtraDataSize
);
365 if (pStringTable
->pSlots
[i
].pData
== NULL
)
367 TRACE("Couldn't allocate memory for a new extra data!\n");
368 MyFree(pStringTable
->pSlots
[i
].pString
);
369 pStringTable
->pSlots
[i
].pString
= NULL
;
373 memcpy(pStringTable
->pSlots
[i
].pData
,
376 pStringTable
->pSlots
[i
].dwSize
= dwExtraDataSize
;
378 pStringTable
->dwUsedSlots
++;
384 TRACE("Couldn't find an empty slot!\n");
390 /**************************************************************************
391 * pSetupStringTableDuplicate [SETUPAPI.@]
393 * Duplicates a given string table.
396 * hStringTable [I] Handle to the string table
399 * Success: Handle to the duplicated string table
404 pSetupStringTableDuplicate(HSTRING_TABLE hStringTable
)
406 PSTRING_TABLE pSourceTable
;
407 PSTRING_TABLE pDestinationTable
;
411 TRACE("%p\n", hStringTable
);
413 pSourceTable
= (PSTRING_TABLE
)hStringTable
;
414 if (pSourceTable
== NULL
)
416 ERR("Invalid hStringTable!\n");
417 return (HSTRING_TABLE
)NULL
;
420 pDestinationTable
= MyMalloc(sizeof(STRING_TABLE
));
421 if (pDestinationTable
== NULL
)
423 ERR("Could not allocate a new string table!\n");
424 return (HSTRING_TABLE
)NULL
;
427 memset(pDestinationTable
, 0, sizeof(STRING_TABLE
));
429 pDestinationTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * pSourceTable
->dwMaxSlots
);
430 if (pDestinationTable
->pSlots
== NULL
)
432 MyFree(pDestinationTable
);
433 return (HSTRING_TABLE
)NULL
;
436 memset(pDestinationTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * pSourceTable
->dwMaxSlots
);
438 pDestinationTable
->dwUsedSlots
= 0;
439 pDestinationTable
->dwMaxSlots
= pSourceTable
->dwMaxSlots
;
441 for (i
= 0; i
< pSourceTable
->dwMaxSlots
; i
++)
443 if (pSourceTable
->pSlots
[i
].pString
!= NULL
)
445 length
= (lstrlenW(pSourceTable
->pSlots
[i
].pString
) + 1) * sizeof(WCHAR
);
446 pDestinationTable
->pSlots
[i
].pString
= MyMalloc(length
);
447 if (pDestinationTable
->pSlots
[i
].pString
!= NULL
)
449 memcpy(pDestinationTable
->pSlots
[i
].pString
,
450 pSourceTable
->pSlots
[i
].pString
,
452 pDestinationTable
->dwUsedSlots
++;
455 if (pSourceTable
->pSlots
[i
].pData
!= NULL
)
457 length
= pSourceTable
->pSlots
[i
].dwSize
;
458 pDestinationTable
->pSlots
[i
].pData
= MyMalloc(length
);
459 if (pDestinationTable
->pSlots
[i
].pData
)
461 memcpy(pDestinationTable
->pSlots
[i
].pData
,
462 pSourceTable
->pSlots
[i
].pData
,
464 pDestinationTable
->pSlots
[i
].dwSize
= length
;
470 return (HSTRING_TABLE
)pDestinationTable
;
474 /**************************************************************************
475 * pSetupStringTableGetExtraData [SETUPAPI.@]
477 * Retrieves extra data from a given string table entry.
480 * hStringTable [I] Handle to the string table
482 * lpExtraData [I] Pointer a buffer that receives the extra data
483 * dwExtraDataSize [I] Size of the buffer
490 pSetupStringTableGetExtraData(HSTRING_TABLE hStringTable
,
493 DWORD dwExtraDataSize
)
495 PSTRING_TABLE pStringTable
;
497 TRACE("%p %x %p %u\n",
498 hStringTable
, dwId
, lpExtraData
, dwExtraDataSize
);
500 pStringTable
= (PSTRING_TABLE
)hStringTable
;
501 if (pStringTable
== NULL
)
503 ERR("Invalid hStringTable!\n");
507 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
509 ERR("Invalid Slot id!\n");
513 if (pStringTable
->pSlots
[dwId
- 1].dwSize
< dwExtraDataSize
)
515 ERR("Data size is too large!\n");
520 pStringTable
->pSlots
[dwId
- 1].pData
,
527 /**************************************************************************
528 * pSetupStringTableLookUpString [SETUPAPI.@]
530 * Searches a string table for a given string.
533 * hStringTable [I] Handle to the string table
534 * lpString [I] String to be searched for
536 * 1: case sensitive compare
543 pSetupStringTableLookUpString(HSTRING_TABLE hStringTable
,
547 PSTRING_TABLE pStringTable
;
550 TRACE("%p %s %x\n", hStringTable
, debugstr_w(lpString
), dwFlags
);
552 pStringTable
= (PSTRING_TABLE
)hStringTable
;
553 if (pStringTable
== NULL
)
555 ERR("Invalid hStringTable!\n");
559 /* Search for existing string in the string table */
560 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
562 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
566 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
571 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
581 /**************************************************************************
582 * pSetupStringTableLookUpStringEx [SETUPAPI.@]
584 * Searches a string table and extra data for a given string.
587 * hStringTable [I] Handle to the string table
588 * lpString [I] String to be searched for
590 * 1: case sensitive compare
591 * lpExtraData [O] Pointer to the buffer that receives the extra data
592 * lpReserved [I/O] Unused
599 pSetupStringTableLookUpStringEx(HSTRING_TABLE hStringTable
,
605 PSTRING_TABLE pStringTable
;
608 TRACE("%p %s %x %p, %x\n", hStringTable
, debugstr_w(lpString
), dwFlags
,
609 lpExtraData
, dwReserved
);
611 pStringTable
= (PSTRING_TABLE
)hStringTable
;
612 if (pStringTable
== NULL
)
614 ERR("Invalid hStringTable!\n");
618 /* Search for existing string in the string table */
619 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
621 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
625 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
628 memcpy(lpExtraData
, pStringTable
->pSlots
[i
].pData
, dwReserved
);
634 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
637 memcpy(lpExtraData
, pStringTable
->pSlots
[i
].pData
, dwReserved
);
647 /**************************************************************************
648 * pSetupStringTableSetExtraData [SETUPAPI.@]
650 * Sets extra data for a given string table entry.
653 * hStringTable [I] Handle to the string table
655 * lpExtraData [I] Pointer to the extra data
656 * dwExtraDataSize [I] Size of the extra data
663 pSetupStringTableSetExtraData(HSTRING_TABLE hStringTable
,
666 DWORD dwExtraDataSize
)
668 PSTRING_TABLE pStringTable
;
670 TRACE("%p %x %p %u\n",
671 hStringTable
, dwId
, lpExtraData
, dwExtraDataSize
);
673 pStringTable
= (PSTRING_TABLE
)hStringTable
;
674 if (pStringTable
== NULL
)
676 ERR("Invalid hStringTable!\n");
680 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
682 ERR("Invalid Slot id!\n");
686 if (pStringTable
->dwMaxDataSize
< dwExtraDataSize
)
688 ERR("Data size is too large!\n");
692 pStringTable
->pSlots
[dwId
- 1].pData
= MyMalloc(dwExtraDataSize
);
693 if (pStringTable
->pSlots
[dwId
- 1].pData
== NULL
)
699 memcpy(pStringTable
->pSlots
[dwId
- 1].pData
,
702 pStringTable
->pSlots
[dwId
- 1].dwSize
= dwExtraDataSize
;
708 /**************************************************************************
709 * pSetupStringTableStringFromId [SETUPAPI.@]
711 * Returns a pointer to a string for the given string ID.
714 * hStringTable [I] Handle to the string table.
718 * Success: Pointer to the string
722 pSetupStringTableStringFromId(HSTRING_TABLE hStringTable
,
725 PSTRING_TABLE pStringTable
;
726 static WCHAR empty
[] = {0};
728 TRACE("%p %x\n", hStringTable
, dwId
);
730 pStringTable
= (PSTRING_TABLE
)hStringTable
;
731 if (pStringTable
== NULL
)
733 ERR("Invalid hStringTable!\n");
737 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
740 return pStringTable
->pSlots
[dwId
- 1].pString
;
744 /**************************************************************************
745 * pSetupStringTableStringFromIdEx [SETUPAPI.@]
747 * Returns a string for the given string ID.
750 * hStringTable [I] Handle to the string table
752 * lpBuffer [I] Pointer to string buffer
753 * lpBufferSize [I/O] Pointer to the size of the string buffer
760 pSetupStringTableStringFromIdEx(HSTRING_TABLE hStringTable
,
763 LPDWORD lpBufferLength
)
765 PSTRING_TABLE pStringTable
;
767 BOOL bResult
= FALSE
;
769 TRACE("%p %x %p %p\n", hStringTable
, dwId
, lpBuffer
, lpBufferLength
);
771 pStringTable
= (PSTRING_TABLE
)hStringTable
;
772 if (pStringTable
== NULL
)
774 ERR("Invalid hStringTable!\n");
779 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
||
780 pStringTable
->pSlots
[dwId
- 1].pString
== NULL
)
782 WARN("Invalid string ID!\n");
787 dwLength
= (lstrlenW(pStringTable
->pSlots
[dwId
- 1].pString
) + 1) * sizeof(WCHAR
);
788 if (dwLength
<= *lpBufferLength
)
790 lstrcpyW(lpBuffer
, pStringTable
->pSlots
[dwId
- 1].pString
);
794 *lpBufferLength
= dwLength
;