* Sync up to trunk HEAD (r62502).
[reactos.git] / dll / win32 / 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., 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
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
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
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
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(&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
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
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
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
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
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
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
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
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) * sizeof(WCHAR);
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 }