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