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