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