xref: /reactos/dll/win32/setupapi/stringtable.c (revision c2c66aff)
1 /*
2  * Setupapi string table functions
3  *
4  * Copyright 2005 Eric Kohl
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include "setupapi_private.h"
22 
23 #define TABLE_DEFAULT_SIZE 256
24 
25 typedef struct _TABLE_SLOT
26 {
27     LPWSTR pString;
28     LPVOID pData;
29     DWORD dwSize;
30 } TABLE_SLOT, *PTABLE_SLOT;
31 
32 typedef struct _STRING_TABLE
33 {
34     PTABLE_SLOT pSlots;
35     DWORD dwUsedSlots;
36     DWORD dwMaxSlots;
37     DWORD dwMaxDataSize;
38 } STRING_TABLE, *PSTRING_TABLE;
39 
40 
41 /**************************************************************************
42  * pSetupStringTableInitialize [SETUPAPI.@]
43  *
44  * Creates a new string table and initializes it.
45  *
46  * PARAMS
47  *     None
48  *
49  * RETURNS
50  *     Success: Handle to the string table
51  *     Failure: NULL
52  */
53 HSTRING_TABLE WINAPI
pSetupStringTableInitialize(VOID)54 pSetupStringTableInitialize(VOID)
55 {
56     PSTRING_TABLE pStringTable;
57 
58     TRACE("\n");
59 
60     pStringTable = MyMalloc(sizeof(STRING_TABLE));
61     if (pStringTable == NULL)
62     {
63         ERR("Invalid hStringTable!\n");
64         return NULL;
65     }
66 
67     memset(pStringTable, 0, sizeof(STRING_TABLE));
68 
69     pStringTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE);
70     if (pStringTable->pSlots == NULL)
71     {
72         MyFree(pStringTable);
73         return NULL;
74     }
75 
76     memset(pStringTable->pSlots, 0, sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE);
77 
78     pStringTable->dwUsedSlots = 0;
79     pStringTable->dwMaxSlots = TABLE_DEFAULT_SIZE;
80     pStringTable->dwMaxDataSize = 0;
81 
82     TRACE("Done\n");
83 
84     return (HSTRING_TABLE)pStringTable;
85 }
86 
87 
88 /**************************************************************************
89  * pSetupStringTableInitializeEx [SETUPAPI.@]
90  *
91  * Creates a new string table and initializes it.
92  *
93  * PARAMS
94  *     dwMaxExtraDataSize [I] Maximum extra data size
95  *     dwReserved         [I] Unused
96  *
97  * RETURNS
98  *     Success: Handle to the string table
99  *     Failure: NULL
100  */
101 HSTRING_TABLE WINAPI
pSetupStringTableInitializeEx(DWORD dwMaxExtraDataSize,DWORD dwReserved)102 pSetupStringTableInitializeEx(DWORD dwMaxExtraDataSize,
103                               DWORD dwReserved)
104 {
105     PSTRING_TABLE pStringTable;
106 
107     TRACE("\n");
108 
109     pStringTable = MyMalloc(sizeof(STRING_TABLE));
110     if (pStringTable == NULL) return NULL;
111 
112     memset(pStringTable, 0, sizeof(STRING_TABLE));
113 
114     pStringTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE);
115     if (pStringTable->pSlots == NULL)
116     {
117         MyFree(pStringTable);
118         return NULL;
119     }
120 
121     memset(pStringTable->pSlots, 0, sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE);
122 
123     pStringTable->dwUsedSlots = 0;
124     pStringTable->dwMaxSlots = TABLE_DEFAULT_SIZE;
125     pStringTable->dwMaxDataSize = dwMaxExtraDataSize;
126 
127     TRACE("Done\n");
128 
129     return (HSTRING_TABLE)pStringTable;
130 }
131 
132 
133 /**************************************************************************
134  * pSetupStringTableDestroy [SETUPAPI.@]
135  *
136  * Destroys a string table.
137  *
138  * PARAMS
139  *     hStringTable [I] Handle to the string table to be destroyed
140  *
141  * RETURNS
142  *     None
143  */
144 VOID WINAPI
pSetupStringTableDestroy(HSTRING_TABLE hStringTable)145 pSetupStringTableDestroy(HSTRING_TABLE hStringTable)
146 {
147     PSTRING_TABLE pStringTable;
148     DWORD i;
149 
150     TRACE("%p\n", hStringTable);
151 
152     pStringTable = (PSTRING_TABLE)hStringTable;
153     if (pStringTable == NULL)
154         return;
155 
156     if (pStringTable->pSlots != NULL)
157     {
158         for (i = 0; i < pStringTable->dwMaxSlots; i++)
159         {
160             MyFree(pStringTable->pSlots[i].pString);
161             pStringTable->pSlots[i].pString = NULL;
162 
163             MyFree(pStringTable->pSlots[i].pData);
164             pStringTable->pSlots[i].pData = NULL;
165             pStringTable->pSlots[i].dwSize = 0;
166         }
167 
168         MyFree(pStringTable->pSlots);
169     }
170 
171     MyFree(pStringTable);
172 }
173 
174 
175 /**************************************************************************
176  * pSetupStringTableAddString [SETUPAPI.@]
177  *
178  * Adds a new string to the string table.
179  *
180  * PARAMS
181  *     hStringTable [I] Handle to the string table
182  *     lpString     [I] String to be added to the string table
183  *     dwFlags      [I] Flags
184  *                        1: case sensitive compare
185  *
186  * RETURNS
187  *     Success: String ID
188  *     Failure: -1
189  *
190  * NOTES
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
193  *     this case.
194  */
195 DWORD WINAPI
pSetupStringTableAddString(HSTRING_TABLE hStringTable,LPWSTR lpString,DWORD dwFlags)196 pSetupStringTableAddString(HSTRING_TABLE hStringTable,
197                            LPWSTR lpString,
198                            DWORD dwFlags)
199 {
200     PSTRING_TABLE pStringTable;
201     DWORD i;
202 
203     TRACE("%p %s %x\n", hStringTable, debugstr_w(lpString), dwFlags);
204 
205     pStringTable = (PSTRING_TABLE)hStringTable;
206     if (pStringTable == NULL)
207     {
208         ERR("Invalid hStringTable!\n");
209         return (DWORD)-1;
210     }
211 
212     /* Search for existing string in the string table */
213     for (i = 0; i < pStringTable->dwMaxSlots; i++)
214     {
215         if (pStringTable->pSlots[i].pString != NULL)
216         {
217             if (dwFlags & 1)
218             {
219                 if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString))
220                 {
221                     return i + 1;
222                 }
223             }
224             else
225             {
226                 if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString))
227                 {
228                     return i + 1;
229                 }
230             }
231         }
232     }
233 
234     /* Check for filled slot table */
235     if (pStringTable->dwUsedSlots == pStringTable->dwMaxSlots)
236     {
237         PTABLE_SLOT pNewSlots;
238         DWORD dwNewMaxSlots;
239 
240         /* FIXME: not thread safe */
241         dwNewMaxSlots = pStringTable->dwMaxSlots * 2;
242         pNewSlots = MyMalloc(sizeof(TABLE_SLOT) * dwNewMaxSlots);
243         if (pNewSlots == NULL)
244             return (DWORD)-1;
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((PVOID*)&pStringTable->pSlots, pNewSlots);
248         MyFree(pNewSlots);
249         pStringTable->dwMaxSlots = dwNewMaxSlots;
250 
251         return pSetupStringTableAddString(hStringTable, lpString, dwFlags);
252     }
253 
254     /* Search for an empty slot */
255     for (i = 0; i < pStringTable->dwMaxSlots; i++)
256     {
257         if (pStringTable->pSlots[i].pString == NULL)
258         {
259             pStringTable->pSlots[i].pString = MyMalloc((lstrlenW(lpString) + 1) * sizeof(WCHAR));
260             if (pStringTable->pSlots[i].pString == NULL)
261             {
262                 TRACE("Couldn't allocate memory for a new string!\n");
263                 return (DWORD)-1;
264             }
265 
266             lstrcpyW(pStringTable->pSlots[i].pString, lpString);
267 
268             pStringTable->dwUsedSlots++;
269 
270             return i + 1;
271         }
272     }
273 
274     TRACE("Couldn't find an empty slot!\n");
275 
276     return (DWORD)-1;
277 }
278 
279 
280 /**************************************************************************
281  * pSetupStringTableAddStringEx [SETUPAPI.@]
282  *
283  * Adds a new string plus extra data to the string table.
284  *
285  * PARAMS
286  *     hStringTable    [I] Handle to the string table
287  *     lpString        [I] String to be added to the string table
288  *     dwFlags         [I] Flags
289  *                           1: case sensitive compare
290  *     lpExtraData     [I] Pointer to the extra data
291  *     dwExtraDataSize [I] Size of the extra data
292  *
293  * RETURNS
294  *     Success: String ID
295  *     Failure: -1
296  *
297  * NOTES
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
300  *     this case.
301  */
302 DWORD WINAPI
pSetupStringTableAddStringEx(HSTRING_TABLE hStringTable,LPWSTR lpString,DWORD dwFlags,LPVOID lpExtraData,DWORD dwExtraDataSize)303 pSetupStringTableAddStringEx(HSTRING_TABLE hStringTable,
304                              LPWSTR lpString,
305                              DWORD dwFlags,
306                              LPVOID lpExtraData,
307                              DWORD dwExtraDataSize)
308 {
309     PSTRING_TABLE pStringTable;
310     DWORD i;
311 
312     TRACE("%p %s %lx\n", (PVOID)hStringTable, debugstr_w(lpString), dwFlags);
313 
314     pStringTable = (PSTRING_TABLE)hStringTable;
315     if (pStringTable == NULL)
316     {
317         ERR("Invalid hStringTable!\n");
318         return (DWORD)-1;
319     }
320 
321     /* Search for existing string in the string table */
322     for (i = 0; i < pStringTable->dwMaxSlots; i++)
323     {
324         if (pStringTable->pSlots[i].pString != NULL)
325         {
326             if (dwFlags & 1)
327             {
328                 if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString))
329                 {
330                     return i + 1;
331                 }
332             }
333             else
334             {
335                 if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString))
336                 {
337                     return i + 1;
338                 }
339             }
340         }
341     }
342 
343     /* Check for filled slot table */
344     if (pStringTable->dwUsedSlots == pStringTable->dwMaxSlots)
345     {
346         FIXME("Resize the string table!\n");
347         return (DWORD)-1;
348     }
349 
350     /* Search for an empty slot */
351     for (i = 0; i < pStringTable->dwMaxSlots; i++)
352     {
353         if (pStringTable->pSlots[i].pString == NULL)
354         {
355             pStringTable->pSlots[i].pString = MyMalloc((lstrlenW(lpString) + 1) * sizeof(WCHAR));
356             if (pStringTable->pSlots[i].pString == NULL)
357             {
358                 TRACE("Couldn't allocate memory for a new string!\n");
359                 return (DWORD)-1;
360             }
361 
362             lstrcpyW(pStringTable->pSlots[i].pString, lpString);
363 
364             pStringTable->pSlots[i].pData = MyMalloc(dwExtraDataSize);
365             if (pStringTable->pSlots[i].pData == NULL)
366             {
367                 TRACE("Couldn't allocate memory for a new extra data!\n");
368                 MyFree(pStringTable->pSlots[i].pString);
369                 pStringTable->pSlots[i].pString = NULL;
370                 return (DWORD)-1;
371             }
372 
373             memcpy(pStringTable->pSlots[i].pData,
374                    lpExtraData,
375                    dwExtraDataSize);
376             pStringTable->pSlots[i].dwSize = dwExtraDataSize;
377 
378             pStringTable->dwUsedSlots++;
379 
380             return i + 1;
381         }
382     }
383 
384     TRACE("Couldn't find an empty slot!\n");
385 
386     return (DWORD)-1;
387 }
388 
389 
390 /**************************************************************************
391  * pSetupStringTableDuplicate [SETUPAPI.@]
392  *
393  * Duplicates a given string table.
394  *
395  * PARAMS
396  *     hStringTable [I] Handle to the string table
397  *
398  * RETURNS
399  *     Success: Handle to the duplicated string table
400  *     Failure: NULL
401  *
402  */
403 HSTRING_TABLE WINAPI
pSetupStringTableDuplicate(HSTRING_TABLE hStringTable)404 pSetupStringTableDuplicate(HSTRING_TABLE hStringTable)
405 {
406     PSTRING_TABLE pSourceTable;
407     PSTRING_TABLE pDestinationTable;
408     DWORD i;
409     DWORD length;
410 
411     TRACE("%p\n", hStringTable);
412 
413     pSourceTable = (PSTRING_TABLE)hStringTable;
414     if (pSourceTable == NULL)
415     {
416         ERR("Invalid hStringTable!\n");
417         return (HSTRING_TABLE)NULL;
418     }
419 
420     pDestinationTable = MyMalloc(sizeof(STRING_TABLE));
421     if (pDestinationTable == NULL)
422     {
423         ERR("Could not allocate a new string table!\n");
424         return (HSTRING_TABLE)NULL;
425     }
426 
427     memset(pDestinationTable, 0, sizeof(STRING_TABLE));
428 
429     pDestinationTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * pSourceTable->dwMaxSlots);
430     if (pDestinationTable->pSlots == NULL)
431     {
432         MyFree(pDestinationTable);
433         return (HSTRING_TABLE)NULL;
434     }
435 
436     memset(pDestinationTable->pSlots, 0, sizeof(TABLE_SLOT) * pSourceTable->dwMaxSlots);
437 
438     pDestinationTable->dwUsedSlots = 0;
439     pDestinationTable->dwMaxSlots = pSourceTable->dwMaxSlots;
440 
441     for (i = 0; i < pSourceTable->dwMaxSlots; i++)
442     {
443         if (pSourceTable->pSlots[i].pString != NULL)
444         {
445             length = (lstrlenW(pSourceTable->pSlots[i].pString) + 1) * sizeof(WCHAR);
446             pDestinationTable->pSlots[i].pString = MyMalloc(length);
447             if (pDestinationTable->pSlots[i].pString != NULL)
448             {
449                 memcpy(pDestinationTable->pSlots[i].pString,
450                        pSourceTable->pSlots[i].pString,
451                        length);
452                 pDestinationTable->dwUsedSlots++;
453             }
454 
455             if (pSourceTable->pSlots[i].pData != NULL)
456             {
457                 length = pSourceTable->pSlots[i].dwSize;
458                 pDestinationTable->pSlots[i].pData = MyMalloc(length);
459                 if (pDestinationTable->pSlots[i].pData)
460                 {
461                     memcpy(pDestinationTable->pSlots[i].pData,
462                            pSourceTable->pSlots[i].pData,
463                            length);
464                     pDestinationTable->pSlots[i].dwSize = length;
465                 }
466             }
467         }
468     }
469 
470     return (HSTRING_TABLE)pDestinationTable;
471 }
472 
473 
474 /**************************************************************************
475  * pSetupStringTableGetExtraData [SETUPAPI.@]
476  *
477  * Retrieves extra data from a given string table entry.
478  *
479  * PARAMS
480  *     hStringTable    [I] Handle to the string table
481  *     dwId            [I] String ID
482  *     lpExtraData     [I] Pointer a buffer that receives the extra data
483  *     dwExtraDataSize [I] Size of the buffer
484  *
485  * RETURNS
486  *     Success: TRUE
487  *     Failure: FALSE
488  */
489 BOOL WINAPI
pSetupStringTableGetExtraData(HSTRING_TABLE hStringTable,DWORD dwId,LPVOID lpExtraData,DWORD dwExtraDataSize)490 pSetupStringTableGetExtraData(HSTRING_TABLE hStringTable,
491                               DWORD dwId,
492                               LPVOID lpExtraData,
493                               DWORD dwExtraDataSize)
494 {
495     PSTRING_TABLE pStringTable;
496 
497     TRACE("%p %x %p %u\n",
498           hStringTable, dwId, lpExtraData, dwExtraDataSize);
499 
500     pStringTable = (PSTRING_TABLE)hStringTable;
501     if (pStringTable == NULL)
502     {
503         ERR("Invalid hStringTable!\n");
504         return FALSE;
505     }
506 
507     if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
508     {
509         ERR("Invalid Slot id!\n");
510         return FALSE;
511     }
512 
513     if (pStringTable->pSlots[dwId - 1].dwSize < dwExtraDataSize)
514     {
515         ERR("Data size is too large!\n");
516         return FALSE;
517     }
518 
519     memcpy(lpExtraData,
520            pStringTable->pSlots[dwId - 1].pData,
521            dwExtraDataSize);
522 
523     return TRUE;
524 }
525 
526 
527 /**************************************************************************
528  * pSetupStringTableLookUpString [SETUPAPI.@]
529  *
530  * Searches a string table for a given string.
531  *
532  * PARAMS
533  *     hStringTable [I] Handle to the string table
534  *     lpString     [I] String to be searched for
535  *     dwFlags      [I] Flags
536  *                        1: case sensitive compare
537  *
538  * RETURNS
539  *     Success: String ID
540  *     Failure: -1
541  */
542 DWORD WINAPI
pSetupStringTableLookUpString(HSTRING_TABLE hStringTable,LPWSTR lpString,DWORD dwFlags)543 pSetupStringTableLookUpString(HSTRING_TABLE hStringTable,
544                               LPWSTR lpString,
545                               DWORD dwFlags)
546 {
547     PSTRING_TABLE pStringTable;
548     DWORD i;
549 
550     TRACE("%p %s %x\n", hStringTable, debugstr_w(lpString), dwFlags);
551 
552     pStringTable = (PSTRING_TABLE)hStringTable;
553     if (pStringTable == NULL)
554     {
555         ERR("Invalid hStringTable!\n");
556         return (DWORD)-1;
557     }
558 
559     /* Search for existing string in the string table */
560     for (i = 0; i < pStringTable->dwMaxSlots; i++)
561     {
562         if (pStringTable->pSlots[i].pString != NULL)
563         {
564             if (dwFlags & 1)
565             {
566                 if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString))
567                     return i + 1;
568             }
569             else
570             {
571                 if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString))
572                     return i + 1;
573             }
574         }
575     }
576 
577     return (DWORD)-1;
578 }
579 
580 
581 /**************************************************************************
582  * pSetupStringTableLookUpStringEx [SETUPAPI.@]
583  *
584  * Searches a string table and extra data for a given string.
585  *
586  * PARAMS
587  *     hStringTable [I] Handle to the string table
588  *     lpString     [I] String to be searched for
589  *     dwFlags      [I] Flags
590  *                        1: case sensitive compare
591  *     lpExtraData  [O] Pointer to the buffer that receives the extra data
592  *     lpReserved   [I/O] Unused
593  *
594  * RETURNS
595  *     Success: String ID
596  *     Failure: -1
597  */
598 DWORD WINAPI
pSetupStringTableLookUpStringEx(HSTRING_TABLE hStringTable,LPWSTR lpString,DWORD dwFlags,LPVOID lpExtraData,DWORD dwReserved)599 pSetupStringTableLookUpStringEx(HSTRING_TABLE hStringTable,
600                                 LPWSTR lpString,
601                                 DWORD dwFlags,
602                                 LPVOID lpExtraData,
603                                 DWORD dwReserved)
604 {
605     PSTRING_TABLE pStringTable;
606     DWORD i;
607 
608     TRACE("%p %s %x %p, %x\n", hStringTable, debugstr_w(lpString), dwFlags,
609           lpExtraData, dwReserved);
610 
611     pStringTable = (PSTRING_TABLE)hStringTable;
612     if (pStringTable == NULL)
613     {
614         ERR("Invalid hStringTable!\n");
615         return ~0u;
616     }
617 
618     /* Search for existing string in the string table */
619     for (i = 0; i < pStringTable->dwMaxSlots; i++)
620     {
621         if (pStringTable->pSlots[i].pString != NULL)
622         {
623             if (dwFlags & 1)
624             {
625                 if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString))
626                 {
627                     if (lpExtraData)
628                         memcpy(lpExtraData, pStringTable->pSlots[i].pData, dwReserved);
629                     return i + 1;
630                 }
631             }
632             else
633             {
634                 if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString))
635                 {
636                     if (lpExtraData)
637                         memcpy(lpExtraData, pStringTable->pSlots[i].pData, dwReserved);
638                     return i + 1;
639                 }
640             }
641         }
642     }
643     return ~0u;
644 }
645 
646 
647 /**************************************************************************
648  * pSetupStringTableSetExtraData [SETUPAPI.@]
649  *
650  * Sets extra data for a given string table entry.
651  *
652  * PARAMS
653  *     hStringTable    [I] Handle to the string table
654  *     dwId            [I] String ID
655  *     lpExtraData     [I] Pointer to the extra data
656  *     dwExtraDataSize [I] Size of the extra data
657  *
658  * RETURNS
659  *     Success: TRUE
660  *     Failure: FALSE
661  */
662 BOOL WINAPI
pSetupStringTableSetExtraData(HSTRING_TABLE hStringTable,DWORD dwId,LPVOID lpExtraData,DWORD dwExtraDataSize)663 pSetupStringTableSetExtraData(HSTRING_TABLE hStringTable,
664                               DWORD dwId,
665                               LPVOID lpExtraData,
666                               DWORD dwExtraDataSize)
667 {
668     PSTRING_TABLE pStringTable;
669 
670     TRACE("%p %x %p %u\n",
671           hStringTable, dwId, lpExtraData, dwExtraDataSize);
672 
673     pStringTable = (PSTRING_TABLE)hStringTable;
674     if (pStringTable == NULL)
675     {
676         ERR("Invalid hStringTable!\n");
677         return FALSE;
678     }
679 
680     if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
681     {
682         ERR("Invalid Slot id!\n");
683         return FALSE;
684     }
685 
686     if (pStringTable->dwMaxDataSize < dwExtraDataSize)
687     {
688         ERR("Data size is too large!\n");
689         return FALSE;
690     }
691 
692     pStringTable->pSlots[dwId - 1].pData = MyMalloc(dwExtraDataSize);
693     if (pStringTable->pSlots[dwId - 1].pData == NULL)
694     {
695         ERR("\n");
696         return FALSE;
697     }
698 
699     memcpy(pStringTable->pSlots[dwId - 1].pData,
700            lpExtraData,
701            dwExtraDataSize);
702     pStringTable->pSlots[dwId - 1].dwSize = dwExtraDataSize;
703 
704     return TRUE;
705 }
706 
707 
708 /**************************************************************************
709  * pSetupStringTableStringFromId [SETUPAPI.@]
710  *
711  * Returns a pointer to a string for the given string ID.
712  *
713  * PARAMS
714  *     hStringTable [I] Handle to the string table.
715  *     dwId         [I] String ID
716  *
717  * RETURNS
718  *     Success: Pointer to the string
719  *     Failure: NULL
720  */
721 LPWSTR WINAPI
pSetupStringTableStringFromId(HSTRING_TABLE hStringTable,DWORD dwId)722 pSetupStringTableStringFromId(HSTRING_TABLE hStringTable,
723                               DWORD dwId)
724 {
725     PSTRING_TABLE pStringTable;
726     static WCHAR empty[] = {0};
727 
728     TRACE("%p %x\n", hStringTable, dwId);
729 
730     pStringTable = (PSTRING_TABLE)hStringTable;
731     if (pStringTable == NULL)
732     {
733         ERR("Invalid hStringTable!\n");
734         return NULL;
735     }
736 
737     if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
738         return empty;
739 
740     return pStringTable->pSlots[dwId - 1].pString;
741 }
742 
743 
744 /**************************************************************************
745  * pSetupStringTableStringFromIdEx [SETUPAPI.@]
746  *
747  * Returns a string for the given string ID.
748  *
749  * PARAMS
750  *     hStringTable [I] Handle to the string table
751  *     dwId         [I] String ID
752  *     lpBuffer     [I] Pointer to string buffer
753  *     lpBufferSize [I/O] Pointer to the size of the string buffer
754  *
755  * RETURNS
756  *     Success: TRUE
757  *     Failure: FALSE
758  */
759 BOOL WINAPI
pSetupStringTableStringFromIdEx(HSTRING_TABLE hStringTable,DWORD dwId,LPWSTR lpBuffer,LPDWORD lpBufferLength)760 pSetupStringTableStringFromIdEx(HSTRING_TABLE hStringTable,
761                                 DWORD dwId,
762                                 LPWSTR lpBuffer,
763                                 LPDWORD lpBufferLength)
764 {
765     PSTRING_TABLE pStringTable;
766     DWORD dwLength;
767     BOOL bResult = FALSE;
768 
769     TRACE("%p %x %p %p\n", hStringTable, dwId, lpBuffer, lpBufferLength);
770 
771     pStringTable = (PSTRING_TABLE)hStringTable;
772     if (pStringTable == NULL)
773     {
774         ERR("Invalid hStringTable!\n");
775         *lpBufferLength = 0;
776         return FALSE;
777     }
778 
779     if (dwId == 0 || dwId > pStringTable->dwMaxSlots ||
780         pStringTable->pSlots[dwId - 1].pString == NULL)
781     {
782         WARN("Invalid string ID!\n");
783         *lpBufferLength = 0;
784         return FALSE;
785     }
786 
787     dwLength = (lstrlenW(pStringTable->pSlots[dwId - 1].pString) + 1);
788     if (dwLength <= *lpBufferLength)
789     {
790         lstrcpyW(lpBuffer, pStringTable->pSlots[dwId - 1].pString);
791         bResult = TRUE;
792     }
793 
794     *lpBufferLength = dwLength;
795 
796     return bResult;
797 }
798