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
22 #include "wine/port.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
47 } TABLE_SLOT
, *PTABLE_SLOT
;
49 typedef struct _STRING_TABLE
55 } STRING_TABLE
, *PSTRING_TABLE
;
58 /**************************************************************************
59 * StringTableInitialize [SETUPAPI.@]
61 * Creates a new string table and initializes it.
67 * Success: Handle to the string table
71 StringTableInitialize(VOID
)
73 PSTRING_TABLE pStringTable
;
77 pStringTable
= MyMalloc(sizeof(STRING_TABLE
));
78 if (pStringTable
== NULL
)
80 ERR("Invalid hStringTable!\n");
84 memset(pStringTable
, 0, sizeof(STRING_TABLE
));
86 pStringTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
87 if (pStringTable
->pSlots
== 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;
101 return (HSTRING_TABLE
)pStringTable
;
105 /**************************************************************************
106 * StringTableInitializeEx [SETUPAPI.@]
108 * Creates a new string table and initializes it.
111 * dwMaxExtraDataSize [I] Maximum extra data size
112 * dwReserved [I] Unused
115 * Success: Handle to the string table
119 StringTableInitializeEx(DWORD dwMaxExtraDataSize
,
122 PSTRING_TABLE pStringTable
;
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
);
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
;
146 return (HSTRING_TABLE
)pStringTable
;
150 /**************************************************************************
151 * StringTableDestroy [SETUPAPI.@]
153 * Destroys a string table.
156 * hStringTable [I] Handle to the string table to be destroyed
162 StringTableDestroy(HSTRING_TABLE hStringTable
)
164 PSTRING_TABLE pStringTable
;
167 TRACE("%p\n", hStringTable
);
169 pStringTable
= (PSTRING_TABLE
)hStringTable
;
170 if (pStringTable
== NULL
)
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.
198 * hStringTable [I] Handle to the string table
199 * lpString [I] String to be added to the string table
201 * 1: case sensitive compare
202 * lpExtraData [I] Pointer to the extra data
203 * dwExtraDataSize [I] Size of the extra data
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
215 StringTableAddStringEx(HSTRING_TABLE hStringTable
, LPWSTR lpString
,
216 DWORD dwFlags
, LPVOID lpExtraData
, DWORD dwExtraDataSize
)
218 PSTRING_TABLE pStringTable
;
221 TRACE("%p %s %x %p, %u\n", hStringTable
, debugstr_w(lpString
), dwFlags
,
222 lpExtraData
, dwExtraDataSize
);
224 pStringTable
= (PSTRING_TABLE
)hStringTable
;
227 ERR("Invalid hStringTable!\n");
231 /* Search for existing string in the string table */
232 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
234 if (pStringTable
->pSlots
[i
].pString
)
238 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
243 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
249 /* Check for filled slot table */
250 if (pStringTable
->dwUsedSlots
== pStringTable
->dwMaxSlots
)
252 FIXME("Resize the string table!\n");
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");
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");
275 memcpy(pStringTable
->pSlots
[i
].pData
, lpExtraData
, dwExtraDataSize
);
276 pStringTable
->pSlots
[i
].dwSize
= dwExtraDataSize
;
277 pStringTable
->dwUsedSlots
++;
281 TRACE("Couldn't find an empty slot!\n");
285 /**************************************************************************
286 * StringTableAddString [SETUPAPI.@]
288 * Adds a new string to the string table.
291 * hStringTable [I] Handle to the string table
292 * lpString [I] String to be added to the string table
294 * 1: case sensitive compare
301 * If the given string already exists in the string table it will not
302 * be added again. The ID of the existing string will be returned in
306 StringTableAddString(HSTRING_TABLE hStringTable
, LPWSTR lpString
, DWORD dwFlags
)
308 return StringTableAddStringEx(hStringTable
, lpString
, dwFlags
, NULL
, 0);
312 /**************************************************************************
313 * StringTableDuplicate [SETUPAPI.@]
315 * Duplicates a given string table.
318 * hStringTable [I] Handle to the string table
321 * Success: Handle to the duplicated string table
326 StringTableDuplicate(HSTRING_TABLE hStringTable
)
328 PSTRING_TABLE pSourceTable
;
329 PSTRING_TABLE pDestinationTable
;
333 TRACE("%p\n", hStringTable
);
335 pSourceTable
= (PSTRING_TABLE
)hStringTable
;
336 if (pSourceTable
== NULL
)
338 ERR("Invalid hStringTable!\n");
342 pDestinationTable
= MyMalloc(sizeof(STRING_TABLE
));
343 if (pDestinationTable
== NULL
)
345 ERR("Could not allocate a new string table!\n");
349 memset(pDestinationTable
, 0, sizeof(STRING_TABLE
));
351 pDestinationTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * pSourceTable
->dwMaxSlots
);
352 if (pDestinationTable
->pSlots
== NULL
)
354 MyFree(pDestinationTable
);
358 memset(pDestinationTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * pSourceTable
->dwMaxSlots
);
360 pDestinationTable
->dwUsedSlots
= 0;
361 pDestinationTable
->dwMaxSlots
= pSourceTable
->dwMaxSlots
;
363 for (i
= 0; i
< pSourceTable
->dwMaxSlots
; i
++)
365 if (pSourceTable
->pSlots
[i
].pString
!= NULL
)
367 length
= (lstrlenW(pSourceTable
->pSlots
[i
].pString
) + 1) * sizeof(WCHAR
);
368 pDestinationTable
->pSlots
[i
].pString
= MyMalloc(length
);
369 if (pDestinationTable
->pSlots
[i
].pString
!= NULL
)
371 memcpy(pDestinationTable
->pSlots
[i
].pString
,
372 pSourceTable
->pSlots
[i
].pString
,
374 pDestinationTable
->dwUsedSlots
++;
377 if (pSourceTable
->pSlots
[i
].pData
!= NULL
)
379 length
= pSourceTable
->pSlots
[i
].dwSize
;
380 pDestinationTable
->pSlots
[i
].pData
= MyMalloc(length
);
381 if (pDestinationTable
->pSlots
[i
].pData
)
383 memcpy(pDestinationTable
->pSlots
[i
].pData
,
384 pSourceTable
->pSlots
[i
].pData
,
386 pDestinationTable
->pSlots
[i
].dwSize
= length
;
392 return (HSTRING_TABLE
)pDestinationTable
;
396 /**************************************************************************
397 * StringTableGetExtraData [SETUPAPI.@]
399 * Retrieves extra data from a given string table entry.
402 * hStringTable [I] Handle to the string table
404 * lpExtraData [I] Pointer a buffer that receives the extra data
405 * dwExtraDataSize [I] Size of the buffer
412 StringTableGetExtraData(HSTRING_TABLE hStringTable
,
415 DWORD dwExtraDataSize
)
417 PSTRING_TABLE pStringTable
;
419 TRACE("%p %x %p %u\n",
420 hStringTable
, dwId
, lpExtraData
, dwExtraDataSize
);
422 pStringTable
= (PSTRING_TABLE
)hStringTable
;
423 if (pStringTable
== NULL
)
425 ERR("Invalid hStringTable!\n");
429 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
431 ERR("Invalid Slot id!\n");
435 if (pStringTable
->pSlots
[dwId
- 1].dwSize
> dwExtraDataSize
)
437 ERR("Data size is too large!\n");
442 pStringTable
->pSlots
[dwId
- 1].pData
,
449 /**************************************************************************
450 * StringTableLookUpStringEx [SETUPAPI.@]
452 * Searches a string table and extra data for a given string.
455 * hStringTable [I] Handle to the string table
456 * lpString [I] String to be searched for
458 * 1: case sensitive compare
459 * lpExtraData [O] Pointer to the buffer that receives the extra data
460 * dwReserved [I/O] Unused
467 StringTableLookUpStringEx(HSTRING_TABLE hStringTable
,
473 PSTRING_TABLE pStringTable
;
476 TRACE("%p %s %x %p, %x\n", hStringTable
, debugstr_w(lpString
), dwFlags
,
477 lpExtraData
, dwReserved
);
479 pStringTable
= (PSTRING_TABLE
)hStringTable
;
480 if (pStringTable
== NULL
)
482 ERR("Invalid hStringTable!\n");
486 /* Search for existing string in the string table */
487 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
489 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
493 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
496 memcpy(lpExtraData
, pStringTable
->pSlots
[i
].pData
, dwReserved
);
502 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
505 memcpy(lpExtraData
, pStringTable
->pSlots
[i
].pData
, dwReserved
);
515 /**************************************************************************
516 * StringTableLookUpString [SETUPAPI.@]
518 * Searches a string table for a given string.
521 * hStringTable [I] Handle to the string table
522 * lpString [I] String to be searched for
524 * 1: case sensitive compare
531 StringTableLookUpString(HSTRING_TABLE hStringTable
,
535 return StringTableLookUpStringEx(hStringTable
, lpString
, dwFlags
, NULL
, 0);
539 /**************************************************************************
540 * StringTableSetExtraData [SETUPAPI.@]
542 * Sets extra data for a given string table entry.
545 * hStringTable [I] Handle to the string table
547 * lpExtraData [I] Pointer to the extra data
548 * dwExtraDataSize [I] Size of the extra data
555 StringTableSetExtraData(HSTRING_TABLE hStringTable
,
558 DWORD dwExtraDataSize
)
560 PSTRING_TABLE pStringTable
;
562 TRACE("%p %x %p %u\n",
563 hStringTable
, dwId
, lpExtraData
, dwExtraDataSize
);
565 pStringTable
= (PSTRING_TABLE
)hStringTable
;
566 if (pStringTable
== NULL
)
568 ERR("Invalid hStringTable!\n");
572 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
574 ERR("Invalid Slot id!\n");
578 if (pStringTable
->dwMaxDataSize
< dwExtraDataSize
)
580 ERR("Data size is too large!\n");
584 pStringTable
->pSlots
[dwId
- 1].pData
= MyMalloc(dwExtraDataSize
);
585 if (pStringTable
->pSlots
[dwId
- 1].pData
== NULL
)
591 memcpy(pStringTable
->pSlots
[dwId
- 1].pData
,
594 pStringTable
->pSlots
[dwId
- 1].dwSize
= dwExtraDataSize
;
600 /**************************************************************************
601 * StringTableStringFromId [SETUPAPI.@]
603 * Returns a pointer to a string for the given string ID.
606 * hStringTable [I] Handle to the string table.
610 * Success: Pointer to the string
614 StringTableStringFromId(HSTRING_TABLE hStringTable
,
617 PSTRING_TABLE pStringTable
;
618 static WCHAR empty
[] = {0};
620 TRACE("%p %x\n", hStringTable
, dwId
);
622 pStringTable
= (PSTRING_TABLE
)hStringTable
;
623 if (pStringTable
== NULL
)
625 ERR("Invalid hStringTable!\n");
629 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
632 return pStringTable
->pSlots
[dwId
- 1].pString
;
636 /**************************************************************************
637 * StringTableStringFromIdEx [SETUPAPI.@]
639 * Returns a string for the given string ID.
642 * hStringTable [I] Handle to the string table
644 * lpBuffer [I] Pointer to string buffer
645 * lpBufferSize [I/O] Pointer to the size of the string buffer
652 StringTableStringFromIdEx(HSTRING_TABLE hStringTable
,
655 LPDWORD lpBufferLength
)
657 PSTRING_TABLE pStringTable
;
659 BOOL bResult
= FALSE
;
661 TRACE("%p %x %p %p\n", hStringTable
, dwId
, lpBuffer
, lpBufferLength
);
663 pStringTable
= (PSTRING_TABLE
)hStringTable
;
664 if (pStringTable
== NULL
)
666 ERR("Invalid hStringTable!\n");
671 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
||
672 pStringTable
->pSlots
[dwId
- 1].pString
== NULL
)
674 WARN("Invalid string ID!\n");
679 dwLength
= (lstrlenW(pStringTable
->pSlots
[dwId
- 1].pString
) + 1) * sizeof(WCHAR
);
680 if (dwLength
<= *lpBufferLength
)
682 lstrcpyW(lpBuffer
, pStringTable
->pSlots
[dwId
- 1].pString
);
686 *lpBufferLength
= dwLength
;
692 /**************************************************************************
693 * StringTableTrim [SETUPAPI.@]
698 * hStringTable [I] Handle to the string table
704 StringTableTrim(HSTRING_TABLE hStringTable
)
706 FIXME("%p\n", hStringTable
);