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 * StringTableAddString [SETUPAPI.@]
194 *
195 * Adds a new string 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 *
203 * RETURNS
204 * Success: String ID
205 * Failure: -1
206 *
207 * NOTES
208 * If the given string already exists in the string table it will not
209 * be added again. The ID of the existing string will be returned in
210 * this case.
211 */
212 DWORD WINAPI
213 StringTableAddString(HSTRING_TABLE hStringTable,
214 LPWSTR lpString,
215 DWORD dwFlags)
216 {
217 PSTRING_TABLE pStringTable;
218 DWORD i;
219
220 TRACE("%p %s %x\n", hStringTable, debugstr_w(lpString), dwFlags);
221
222 pStringTable = (PSTRING_TABLE)hStringTable;
223 if (pStringTable == NULL)
224 {
225 ERR("Invalid hStringTable!\n");
226 return (DWORD)-1;
227 }
228
229 /* Search for existing string in the string table */
230 for (i = 0; i < pStringTable->dwMaxSlots; i++)
231 {
232 if (pStringTable->pSlots[i].pString != NULL)
233 {
234 if (dwFlags & 1)
235 {
236 if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString))
237 {
238 return i + 1;
239 }
240 }
241 else
242 {
243 if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString))
244 {
245 return i + 1;
246 }
247 }
248 }
249 }
250
251 /* Check for filled slot table */
252 if (pStringTable->dwUsedSlots == pStringTable->dwMaxSlots)
253 {
254 FIXME("Resize the string table!\n");
255 return (DWORD)-1;
256 }
257
258 /* Search for an empty slot */
259 for (i = 0; i < pStringTable->dwMaxSlots; i++)
260 {
261 if (pStringTable->pSlots[i].pString == NULL)
262 {
263 pStringTable->pSlots[i].pString = MyMalloc((lstrlenW(lpString) + 1) * sizeof(WCHAR));
264 if (pStringTable->pSlots[i].pString == NULL)
265 {
266 TRACE("Couldn't allocate memory for a new string!\n");
267 return (DWORD)-1;
268 }
269
270 lstrcpyW(pStringTable->pSlots[i].pString, lpString);
271
272 pStringTable->dwUsedSlots++;
273
274 return i + 1;
275 }
276 }
277
278 TRACE("Couldn't find an empty slot!\n");
279
280 return (DWORD)-1;
281 }
282
283
284 /**************************************************************************
285 * StringTableAddStringEx [SETUPAPI.@]
286 *
287 * Adds a new string plus extra data to the string table.
288 *
289 * PARAMS
290 * hStringTable [I] Handle to the string table
291 * lpString [I] String to be added to the string table
292 * dwFlags [I] Flags
293 * 1: case sensitive compare
294 * lpExtraData [I] Pointer to the extra data
295 * dwExtraDataSize [I] Size of the extra data
296 *
297 * RETURNS
298 * Success: String ID
299 * Failure: -1
300 *
301 * NOTES
302 * If the given string already exists in the string table it will not
303 * be added again. The ID of the existing string will be returned in
304 * this case.
305 */
306 DWORD WINAPI
307 StringTableAddStringEx(HSTRING_TABLE hStringTable,
308 LPWSTR lpString,
309 DWORD dwFlags,
310 LPVOID lpExtraData,
311 DWORD dwExtraDataSize)
312 {
313 FIXME("\n");
314 return (DWORD)-1;
315 }
316
317
318 /**************************************************************************
319 * StringTableDuplicate [SETUPAPI.@]
320 *
321 * Duplicates a given string table.
322 *
323 * PARAMS
324 * hStringTable [I] Handle to the string table
325 *
326 * RETURNS
327 * Success: Handle to the duplicated string table
328 * Failure: NULL
329 *
330 */
331 HSTRING_TABLE WINAPI
332 StringTableDuplicate(HSTRING_TABLE hStringTable)
333 {
334 PSTRING_TABLE pSourceTable;
335 PSTRING_TABLE pDestinationTable;
336 DWORD i;
337 DWORD length;
338
339 TRACE("%p\n", hStringTable);
340
341 pSourceTable = (PSTRING_TABLE)hStringTable;
342 if (pSourceTable == NULL)
343 {
344 ERR("Invalid hStringTable!\n");
345 return NULL;
346 }
347
348 pDestinationTable = MyMalloc(sizeof(STRING_TABLE));
349 if (pDestinationTable == NULL)
350 {
351 ERR("Could not allocate a new string table!\n");
352 return NULL;
353 }
354
355 memset(pDestinationTable, 0, sizeof(STRING_TABLE));
356
357 pDestinationTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * pSourceTable->dwMaxSlots);
358 if (pDestinationTable->pSlots == NULL)
359 {
360 MyFree(pDestinationTable);
361 return NULL;
362 }
363
364 memset(pDestinationTable->pSlots, 0, sizeof(TABLE_SLOT) * pSourceTable->dwMaxSlots);
365
366 pDestinationTable->dwUsedSlots = 0;
367 pDestinationTable->dwMaxSlots = pSourceTable->dwMaxSlots;
368
369 for (i = 0; i < pSourceTable->dwMaxSlots; i++)
370 {
371 if (pSourceTable->pSlots[i].pString != NULL)
372 {
373 length = (lstrlenW(pSourceTable->pSlots[i].pString) + 1) * sizeof(WCHAR);
374 pDestinationTable->pSlots[i].pString = MyMalloc(length);
375 if (pDestinationTable->pSlots[i].pString != NULL)
376 {
377 memcpy(pDestinationTable->pSlots[i].pString,
378 pSourceTable->pSlots[i].pString,
379 length);
380 pDestinationTable->dwUsedSlots++;
381 }
382
383 if (pSourceTable->pSlots[i].pData != NULL)
384 {
385 length = pSourceTable->pSlots[i].dwSize;
386 pDestinationTable->pSlots[i].pData = MyMalloc(length);
387 if (pDestinationTable->pSlots[i].pData)
388 {
389 memcpy(pDestinationTable->pSlots[i].pData,
390 pSourceTable->pSlots[i].pData,
391 length);
392 pDestinationTable->pSlots[i].dwSize = length;
393 }
394 }
395 }
396 }
397
398 return (HSTRING_TABLE)pDestinationTable;
399 }
400
401
402 /**************************************************************************
403 * StringTableGetExtraData [SETUPAPI.@]
404 *
405 * Retrieves extra data from a given string table entry.
406 *
407 * PARAMS
408 * hStringTable [I] Handle to the string table
409 * dwId [I] String ID
410 * lpExtraData [I] Pointer a buffer that receives the extra data
411 * dwExtraDataSize [I] Size of the buffer
412 *
413 * RETURNS
414 * Success: TRUE
415 * Failure: FALSE
416 */
417 BOOL WINAPI
418 StringTableGetExtraData(HSTRING_TABLE hStringTable,
419 DWORD dwId,
420 LPVOID lpExtraData,
421 DWORD dwExtraDataSize)
422 {
423 PSTRING_TABLE pStringTable;
424
425 TRACE("%p %x %p %u\n",
426 hStringTable, dwId, lpExtraData, dwExtraDataSize);
427
428 pStringTable = (PSTRING_TABLE)hStringTable;
429 if (pStringTable == NULL)
430 {
431 ERR("Invalid hStringTable!\n");
432 return FALSE;
433 }
434
435 if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
436 {
437 ERR("Invalid Slot id!\n");
438 return FALSE;
439 }
440
441 if (pStringTable->pSlots[dwId - 1].dwSize < dwExtraDataSize)
442 {
443 ERR("Data size is too large!\n");
444 return FALSE;
445 }
446
447 memcpy(lpExtraData,
448 pStringTable->pSlots[dwId - 1].pData,
449 dwExtraDataSize);
450
451 return TRUE;
452 }
453
454
455 /**************************************************************************
456 * StringTableLookUpString [SETUPAPI.@]
457 *
458 * Searches a string table for a given string.
459 *
460 * PARAMS
461 * hStringTable [I] Handle to the string table
462 * lpString [I] String to be searched for
463 * dwFlags [I] Flags
464 * 1: case sensitive compare
465 *
466 * RETURNS
467 * Success: String ID
468 * Failure: -1
469 */
470 DWORD WINAPI
471 StringTableLookUpString(HSTRING_TABLE hStringTable,
472 LPWSTR lpString,
473 DWORD dwFlags)
474 {
475 PSTRING_TABLE pStringTable;
476 DWORD i;
477
478 TRACE("%p %s %x\n", hStringTable, debugstr_w(lpString), dwFlags);
479
480 pStringTable = (PSTRING_TABLE)hStringTable;
481 if (pStringTable == NULL)
482 {
483 ERR("Invalid hStringTable!\n");
484 return (DWORD)-1;
485 }
486
487 /* Search for existing string in the string table */
488 for (i = 0; i < pStringTable->dwMaxSlots; i++)
489 {
490 if (pStringTable->pSlots[i].pString != NULL)
491 {
492 if (dwFlags & 1)
493 {
494 if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString))
495 return i + 1;
496 }
497 else
498 {
499 if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString))
500 return i + 1;
501 }
502 }
503 }
504
505 return (DWORD)-1;
506 }
507
508
509 /**************************************************************************
510 * StringTableLookUpStringEx [SETUPAPI.@]
511 *
512 * Searches a string table and extra data for a given string.
513 *
514 * PARAMS
515 * hStringTable [I] Handle to the string table
516 * lpString [I] String to be searched for
517 * dwFlags [I] Flags
518 * 1: case sensitive compare
519 * lpExtraData [O] Pointer to the buffer that receives the extra data
520 * lpReserved [I/O] Unused
521 *
522 * RETURNS
523 * Success: String ID
524 * Failure: -1
525 */
526 DWORD WINAPI
527 StringTableLookUpStringEx(HSTRING_TABLE hStringTable,
528 LPWSTR lpString,
529 DWORD dwFlags,
530 LPVOID lpExtraData,
531 LPDWORD lpReserved)
532 {
533 FIXME("\n");
534 return (DWORD)-1;
535 }
536
537
538 /**************************************************************************
539 * StringTableSetExtraData [SETUPAPI.@]
540 *
541 * Sets extra data for a given string table entry.
542 *
543 * PARAMS
544 * hStringTable [I] Handle to the string table
545 * dwId [I] String ID
546 * lpExtraData [I] Pointer to the extra data
547 * dwExtraDataSize [I] Size of the extra data
548 *
549 * RETURNS
550 * Success: TRUE
551 * Failure: FALSE
552 */
553 BOOL WINAPI
554 StringTableSetExtraData(HSTRING_TABLE hStringTable,
555 DWORD dwId,
556 LPVOID lpExtraData,
557 DWORD dwExtraDataSize)
558 {
559 PSTRING_TABLE pStringTable;
560
561 TRACE("%p %x %p %u\n",
562 hStringTable, dwId, lpExtraData, dwExtraDataSize);
563
564 pStringTable = (PSTRING_TABLE)hStringTable;
565 if (pStringTable == NULL)
566 {
567 ERR("Invalid hStringTable!\n");
568 return FALSE;
569 }
570
571 if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
572 {
573 ERR("Invalid Slot id!\n");
574 return FALSE;
575 }
576
577 if (pStringTable->dwMaxDataSize < dwExtraDataSize)
578 {
579 ERR("Data size is too large!\n");
580 return FALSE;
581 }
582
583 pStringTable->pSlots[dwId - 1].pData = MyMalloc(dwExtraDataSize);
584 if (pStringTable->pSlots[dwId - 1].pData == NULL)
585 {
586 ERR("\n");
587 return FALSE;
588 }
589
590 memcpy(pStringTable->pSlots[dwId - 1].pData,
591 lpExtraData,
592 dwExtraDataSize);
593 pStringTable->pSlots[dwId - 1].dwSize = dwExtraDataSize;
594
595 return TRUE;
596 }
597
598
599 /**************************************************************************
600 * StringTableStringFromId [SETUPAPI.@]
601 *
602 * Returns a pointer to a string for the given string ID.
603 *
604 * PARAMS
605 * hStringTable [I] Handle to the string table.
606 * dwId [I] String ID
607 *
608 * RETURNS
609 * Success: Pointer to the string
610 * Failure: NULL
611 */
612 LPWSTR WINAPI
613 StringTableStringFromId(HSTRING_TABLE hStringTable,
614 DWORD dwId)
615 {
616 PSTRING_TABLE pStringTable;
617 static WCHAR empty[] = {0};
618
619 TRACE("%p %x\n", hStringTable, dwId);
620
621 pStringTable = (PSTRING_TABLE)hStringTable;
622 if (pStringTable == NULL)
623 {
624 ERR("Invalid hStringTable!\n");
625 return NULL;
626 }
627
628 if (dwId == 0 || dwId > pStringTable->dwMaxSlots)
629 return empty;
630
631 return pStringTable->pSlots[dwId - 1].pString;
632 }
633
634
635 /**************************************************************************
636 * StringTableStringFromIdEx [SETUPAPI.@]
637 *
638 * Returns a string for the given string ID.
639 *
640 * PARAMS
641 * hStringTable [I] Handle to the string table
642 * dwId [I] String ID
643 * lpBuffer [I] Pointer to string buffer
644 * lpBufferSize [I/O] Pointer to the size of the string buffer
645 *
646 * RETURNS
647 * Success: TRUE
648 * Failure: FALSE
649 */
650 BOOL WINAPI
651 StringTableStringFromIdEx(HSTRING_TABLE hStringTable,
652 DWORD dwId,
653 LPWSTR lpBuffer,
654 LPDWORD lpBufferLength)
655 {
656 PSTRING_TABLE pStringTable;
657 DWORD dwLength;
658 BOOL bResult = FALSE;
659
660 TRACE("%p %x %p %p\n", hStringTable, dwId, lpBuffer, lpBufferLength);
661
662 pStringTable = (PSTRING_TABLE)hStringTable;
663 if (pStringTable == NULL)
664 {
665 ERR("Invalid hStringTable!\n");
666 *lpBufferLength = 0;
667 return FALSE;
668 }
669
670 if (dwId == 0 || dwId > pStringTable->dwMaxSlots ||
671 pStringTable->pSlots[dwId - 1].pString == NULL)
672 {
673 WARN("Invalid string ID!\n");
674 *lpBufferLength = 0;
675 return FALSE;
676 }
677
678 dwLength = (lstrlenW(pStringTable->pSlots[dwId - 1].pString) + 1) * sizeof(WCHAR);
679 if (dwLength <= *lpBufferLength)
680 {
681 lstrcpyW(lpBuffer, pStringTable->pSlots[dwId - 1].pString);
682 bResult = TRUE;
683 }
684
685 *lpBufferLength = dwLength;
686
687 return bResult;
688 }
689
690
691 /**************************************************************************
692 * StringTableTrim [SETUPAPI.@]
693 *
694 * ...
695 *
696 * PARAMS
697 * hStringTable [I] Handle to the string table
698 *
699 * RETURNS
700 * None
701 */
702 VOID WINAPI
703 StringTableTrim(HSTRING_TABLE hStringTable)
704 {
705 FIXME("%p\n", hStringTable);
706 }
707
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.