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