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 typedef struct _TABLE_SLOT
45 } TABLE_SLOT
, *PTABLE_SLOT
;
47 typedef struct _STRING_TABLE
53 } STRING_TABLE
, *PSTRING_TABLE
;
56 /**************************************************************************
57 * StringTableInitialize [SETUPAPI.@]
59 * Creates a new string table and initializes it.
65 * Success: Handle to the string table
69 StringTableInitialize(VOID
)
71 PSTRING_TABLE pStringTable
;
75 pStringTable
= MyMalloc(sizeof(STRING_TABLE
));
76 if (pStringTable
== NULL
)
78 ERR("Invalid hStringTable!\n");
82 memset(pStringTable
, 0, sizeof(STRING_TABLE
));
84 pStringTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
85 if (pStringTable
->pSlots
== NULL
)
87 MyFree(pStringTable
->pSlots
);
91 memset(pStringTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
93 pStringTable
->dwUsedSlots
= 0;
94 pStringTable
->dwMaxSlots
= TABLE_DEFAULT_SIZE
;
95 pStringTable
->dwMaxDataSize
= 0;
99 return (HSTRING_TABLE
)pStringTable
;
103 /**************************************************************************
104 * StringTableInitializeEx [SETUPAPI.@]
106 * Creates a new string table and initializes it.
109 * dwMaxExtraDataSize [I] Maximum extra data size
110 * dwReserved [I] Unused
113 * Success: Handle to the string table
117 StringTableInitializeEx(DWORD dwMaxExtraDataSize
,
120 PSTRING_TABLE pStringTable
;
124 pStringTable
= MyMalloc(sizeof(STRING_TABLE
));
125 if (pStringTable
== NULL
) return NULL
;
127 memset(pStringTable
, 0, sizeof(STRING_TABLE
));
129 pStringTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
130 if (pStringTable
->pSlots
== NULL
)
132 MyFree(pStringTable
->pSlots
);
136 memset(pStringTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * TABLE_DEFAULT_SIZE
);
138 pStringTable
->dwUsedSlots
= 0;
139 pStringTable
->dwMaxSlots
= TABLE_DEFAULT_SIZE
;
140 pStringTable
->dwMaxDataSize
= dwMaxExtraDataSize
;
144 return (HSTRING_TABLE
)pStringTable
;
148 /**************************************************************************
149 * StringTableDestroy [SETUPAPI.@]
151 * Destroys a string table.
154 * hStringTable [I] Handle to the string table to be destroyed
160 StringTableDestroy(HSTRING_TABLE hStringTable
)
162 PSTRING_TABLE pStringTable
;
165 TRACE("%p\n", hStringTable
);
167 pStringTable
= (PSTRING_TABLE
)hStringTable
;
168 if (pStringTable
== NULL
)
171 if (pStringTable
->pSlots
!= NULL
)
173 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
175 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
177 MyFree(pStringTable
->pSlots
[i
].pString
);
178 pStringTable
->pSlots
[i
].pString
= NULL
;
181 if (pStringTable
->pSlots
[i
].pData
!= NULL
)
183 MyFree(pStringTable
->pSlots
[i
].pData
);
184 pStringTable
->pSlots
[i
].pData
= NULL
;
185 pStringTable
->pSlots
[i
].dwSize
= 0;
189 MyFree(pStringTable
->pSlots
);
192 MyFree(pStringTable
);
196 /**************************************************************************
197 * StringTableAddString [SETUPAPI.@]
199 * Adds a new string to the string table.
202 * hStringTable [I] Handle to the string table
203 * lpString [I] String to be added to the string table
205 * 1: case sensitive compare
212 * If the given string already exists in the string table it will not
213 * be added again. The ID of the existing string will be returned in
217 StringTableAddString(HSTRING_TABLE hStringTable
,
221 PSTRING_TABLE pStringTable
;
224 TRACE("%p %s %lx\n", hStringTable
, debugstr_w(lpString
), dwFlags
);
226 pStringTable
= (PSTRING_TABLE
)hStringTable
;
227 if (pStringTable
== NULL
)
229 ERR("Invalid hStringTable!\n");
233 /* Search for existing string in the string table */
234 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
236 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
240 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
247 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
255 /* Check for filled slot table */
256 if (pStringTable
->dwUsedSlots
== pStringTable
->dwMaxSlots
)
258 FIXME("Resize the string table!\n");
262 /* Search for an empty slot */
263 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
265 if (pStringTable
->pSlots
[i
].pString
== NULL
)
267 pStringTable
->pSlots
[i
].pString
= MyMalloc((lstrlenW(lpString
) + 1) * sizeof(WCHAR
));
268 if (pStringTable
->pSlots
[i
].pString
== NULL
)
270 TRACE("Couldn't allocate memory for a new string!\n");
274 lstrcpyW(pStringTable
->pSlots
[i
].pString
, lpString
);
276 pStringTable
->dwUsedSlots
++;
282 TRACE("Couldn't find an empty slot!\n");
288 /**************************************************************************
289 * StringTableAddStringEx [SETUPAPI.@]
291 * Adds a new string plus extra data to the string table.
294 * hStringTable [I] Handle to the string table
295 * lpString [I] String to be added to the string table
297 * 1: case sensitive compare
298 * lpExtraData [I] Pointer to the extra data
299 * dwExtraDataSize [I] Size of the extra data
306 * If the given string already exists in the string table it will not
307 * be added again. The ID of the existing string will be returned in
311 StringTableAddStringEx(HSTRING_TABLE hStringTable
,
315 DWORD dwExtraDataSize
)
322 /**************************************************************************
323 * StringTableDuplicate [SETUPAPI.@]
325 * Duplicates a given string table.
328 * hStringTable [I] Handle to the string table
331 * Success: Handle to the duplicated string table
336 StringTableDuplicate(HSTRING_TABLE hStringTable
)
338 PSTRING_TABLE pSourceTable
;
339 PSTRING_TABLE pDestinationTable
;
343 TRACE("%p\n", hStringTable
);
345 pSourceTable
= (PSTRING_TABLE
)hStringTable
;
346 if (pSourceTable
== NULL
)
348 ERR("Invalid hStringTable!\n");
349 return (HSTRING_TABLE
)NULL
;
352 pDestinationTable
= MyMalloc(sizeof(STRING_TABLE
));
353 if (pDestinationTable
== NULL
)
355 ERR("Cound not allocate a new string table!\n");
356 return (HSTRING_TABLE
)NULL
;
359 memset(pDestinationTable
, 0, sizeof(STRING_TABLE
));
361 pDestinationTable
->pSlots
= MyMalloc(sizeof(TABLE_SLOT
) * pSourceTable
->dwMaxSlots
);
362 if (pDestinationTable
->pSlots
== NULL
)
364 MyFree(pDestinationTable
);
365 return (HSTRING_TABLE
)NULL
;
368 memset(pDestinationTable
->pSlots
, 0, sizeof(TABLE_SLOT
) * pSourceTable
->dwMaxSlots
);
370 pDestinationTable
->dwUsedSlots
= 0;
371 pDestinationTable
->dwMaxSlots
= pSourceTable
->dwMaxSlots
;
373 for (i
= 0; i
< pSourceTable
->dwMaxSlots
; i
++)
375 if (pSourceTable
->pSlots
[i
].pString
!= NULL
)
377 length
= (lstrlenW(pSourceTable
->pSlots
[i
].pString
) + 1) * sizeof(WCHAR
);
378 pDestinationTable
->pSlots
[i
].pString
= MyMalloc(length
);
379 if (pDestinationTable
->pSlots
[i
].pString
!= NULL
)
381 memcpy(pDestinationTable
->pSlots
[i
].pString
,
382 pSourceTable
->pSlots
[i
].pString
,
384 pDestinationTable
->dwUsedSlots
++;
387 if (pSourceTable
->pSlots
[i
].pData
!= NULL
)
389 length
= pSourceTable
->pSlots
[i
].dwSize
;
390 pDestinationTable
->pSlots
[i
].pData
= MyMalloc(length
);
391 if (pDestinationTable
->pSlots
[i
].pData
)
393 memcpy(pDestinationTable
->pSlots
[i
].pData
,
394 pSourceTable
->pSlots
[i
].pData
,
396 pDestinationTable
->pSlots
[i
].dwSize
= length
;
402 return (HSTRING_TABLE
)pDestinationTable
;
406 /**************************************************************************
407 * StringTableGetExtraData [SETUPAPI.@]
409 * Retrieves extra data from a given string table entry.
412 * hStringTable [I] Handle to the string table
414 * lpExtraData [I] Pointer a buffer that receives the extra data
415 * dwExtraDataSize [I] Size of the buffer
422 StringTableGetExtraData(HSTRING_TABLE hStringTable
,
425 DWORD dwExtraDataSize
)
427 PSTRING_TABLE pStringTable
;
429 TRACE("%p %lx %p %lu\n",
430 hStringTable
, dwId
, lpExtraData
, dwExtraDataSize
);
432 pStringTable
= (PSTRING_TABLE
)hStringTable
;
433 if (pStringTable
== NULL
)
435 ERR("Invalid hStringTable!\n");
439 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
441 ERR("Invalid Slot id!\n");
445 if (pStringTable
->pSlots
[dwId
- 1].dwSize
< dwExtraDataSize
)
447 ERR("Data size is too large!\n");
452 pStringTable
->pSlots
[dwId
- 1].pData
,
459 /**************************************************************************
460 * StringTableLookUpString [SETUPAPI.@]
462 * Searches a string table for a given string.
465 * hStringTable [I] Handle to the string table
466 * lpString [I] String to be searched for
468 * 1: case sensitive compare
475 StringTableLookUpString(HSTRING_TABLE hStringTable
,
479 PSTRING_TABLE pStringTable
;
482 TRACE("%p %s %lx\n", hStringTable
, debugstr_w(lpString
), dwFlags
);
484 pStringTable
= (PSTRING_TABLE
)hStringTable
;
485 if (pStringTable
== NULL
)
487 ERR("Invalid hStringTable!\n");
491 /* Search for existing string in the string table */
492 for (i
= 0; i
< pStringTable
->dwMaxSlots
; i
++)
494 if (pStringTable
->pSlots
[i
].pString
!= NULL
)
498 if (!lstrcmpW(pStringTable
->pSlots
[i
].pString
, lpString
))
503 if (!lstrcmpiW(pStringTable
->pSlots
[i
].pString
, lpString
))
513 /**************************************************************************
514 * StringTableLookUpStringEx [SETUPAPI.@]
516 * Searches a string table and extra data for a given string.
519 * hStringTable [I] Handle to the string table
520 * lpString [I] String to be searched for
522 * 1: case sensitive compare
523 * lpExtraData [O] Pointer to the buffer that receives the extra data
524 * lpReserved [I/O] Unused
531 StringTableLookUpStringEx(HSTRING_TABLE hStringTable
,
542 /**************************************************************************
543 * StringTableSetExtraData [SETUPAPI.@]
545 * Sets extra data for a given string table entry.
548 * hStringTable [I] Handle to the string table
550 * lpExtraData [I] Pointer to the extra data
551 * dwExtraDataSize [I] Size of the extra data
558 StringTableSetExtraData(HSTRING_TABLE hStringTable
,
561 DWORD dwExtraDataSize
)
563 PSTRING_TABLE pStringTable
;
565 TRACE("%p %lx %p %lu\n",
566 hStringTable
, dwId
, lpExtraData
, dwExtraDataSize
);
568 pStringTable
= (PSTRING_TABLE
)hStringTable
;
569 if (pStringTable
== NULL
)
571 ERR("Invalid hStringTable!\n");
575 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
577 ERR("Invalid Slot id!\n");
581 if (pStringTable
->dwMaxDataSize
< dwExtraDataSize
)
583 ERR("Data size is too large!\n");
587 pStringTable
->pSlots
[dwId
- 1].pData
= MyMalloc(dwExtraDataSize
);
588 if (pStringTable
->pSlots
[dwId
- 1].pData
== NULL
)
594 memcpy(pStringTable
->pSlots
[dwId
- 1].pData
,
597 pStringTable
->pSlots
[dwId
- 1].dwSize
= dwExtraDataSize
;
603 /**************************************************************************
604 * StringTableStringFromId [SETUPAPI.@]
606 * Returns a pointer to a string for the given string ID.
609 * hStringTable [I] Handle to the string table.
613 * Success: Pointer to the string
617 StringTableStringFromId(HSTRING_TABLE hStringTable
,
620 PSTRING_TABLE pStringTable
;
621 static WCHAR empty
[] = {0};
623 TRACE("%p %lx\n", hStringTable
, dwId
);
625 pStringTable
= (PSTRING_TABLE
)hStringTable
;
626 if (pStringTable
== NULL
)
628 ERR("Invalid hStringTable!\n");
632 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
)
635 return pStringTable
->pSlots
[dwId
- 1].pString
;
639 /**************************************************************************
640 * StringTableStringFromIdEx [SETUPAPI.@]
642 * Returns a string for the given string ID.
645 * hStringTable [I] Handle to the string table
647 * lpBuffer [I] Pointer to string buffer
648 * lpBufferSize [I/O] Pointer to the size of the string buffer
655 StringTableStringFromIdEx(HSTRING_TABLE hStringTable
,
658 LPDWORD lpBufferLength
)
660 PSTRING_TABLE pStringTable
;
662 BOOL bResult
= FALSE
;
664 TRACE("%p %lx %p %p\n", hStringTable
, dwId
, lpBuffer
, lpBufferLength
);
666 pStringTable
= (PSTRING_TABLE
)hStringTable
;
667 if (pStringTable
== NULL
)
669 ERR("Invalid hStringTable!\n");
674 if (dwId
== 0 || dwId
> pStringTable
->dwMaxSlots
||
675 pStringTable
->pSlots
[dwId
- 1].pString
== NULL
)
677 WARN("Invalid string ID!\n");
682 dwLength
= (lstrlenW(pStringTable
->pSlots
[dwId
- 1].pString
) + 1) * sizeof(WCHAR
);
683 if (dwLength
<= *lpBufferLength
)
685 lstrcpyW(lpBuffer
, pStringTable
->pSlots
[dwId
- 1].pString
);
689 *lpBufferLength
= dwLength
;
695 /**************************************************************************
696 * StringTableTrim [SETUPAPI.@]
701 * hStringTable [I] Handle to the string table
707 StringTableTrim(HSTRING_TABLE hStringTable
)
709 FIXME("%p\n", hStringTable
);