dinput: Move SetEventNotification and associated event into base class.
[wine] / dlls / setupapi / query.c
1 /*
2  * setupapi query functions
3  *
4  * Copyright 2006 James Hawkins
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 <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "winreg.h"
27 #include "winver.h"
28 #include "setupapi.h"
29 #include "advpub.h"
30 #include "winnls.h"
31 #include "wine/debug.h"
32 #include "setupapi_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
35
36 /* fills the PSP_INF_INFORMATION struct fill_info is TRUE
37  * always returns the required size of the information
38  */
39 static BOOL fill_inf_info(HINF inf, PSP_INF_INFORMATION buffer, DWORD size, DWORD *required)
40 {
41     LPCWSTR filename = PARSER_get_inf_filename(inf);
42     DWORD total_size = FIELD_OFFSET(SP_INF_INFORMATION, VersionData)
43                         + (lstrlenW(filename) + 1) * sizeof(WCHAR);
44
45     if (required) *required = total_size;
46
47     /* FIXME: we need to parse the INF file to find the correct version info */
48     if (buffer)
49     {
50         if (size < total_size)
51         {
52             SetLastError(ERROR_INSUFFICIENT_BUFFER);
53             return FALSE;
54         }
55         buffer->InfStyle = INF_STYLE_WIN4;
56         buffer->InfCount = 1;
57         /* put the filename in buffer->VersionData */
58         lstrcpyW((LPWSTR)&buffer->VersionData[0], filename);
59     }
60     return TRUE;
61 }
62
63 static HINF search_for_inf(LPCVOID InfSpec, DWORD SearchControl)
64 {
65     HINF hInf = INVALID_HANDLE_VALUE;
66     WCHAR inf_path[MAX_PATH];
67
68     static const WCHAR infW[] = {'\\','i','n','f','\\',0};
69     static const WCHAR system32W[] = {'\\','s','y','s','t','e','m','3','2','\\',0};
70
71     if (SearchControl == INFINFO_REVERSE_DEFAULT_SEARCH)
72     {
73         GetWindowsDirectoryW(inf_path, MAX_PATH);
74         lstrcatW(inf_path, system32W);
75         lstrcatW(inf_path, InfSpec);
76
77         hInf = SetupOpenInfFileW(inf_path, NULL,
78                                  INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
79         if (hInf != INVALID_HANDLE_VALUE)
80             return hInf;
81
82         GetWindowsDirectoryW(inf_path, MAX_PATH);
83         lstrcpyW(inf_path, infW);
84         lstrcatW(inf_path, InfSpec);
85
86         return SetupOpenInfFileW(inf_path, NULL,
87                                  INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
88     }
89
90     return INVALID_HANDLE_VALUE;
91 }
92
93 /***********************************************************************
94  *      SetupGetInfInformationA    (SETUPAPI.@)
95  *
96  */
97 BOOL WINAPI SetupGetInfInformationA(LPCVOID InfSpec, DWORD SearchControl,
98                                     PSP_INF_INFORMATION ReturnBuffer,
99                                     DWORD ReturnBufferSize, PDWORD RequiredSize)
100 {
101     LPWSTR inf = (LPWSTR)InfSpec;
102     DWORD len;
103     BOOL ret;
104
105     if (InfSpec && SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE)
106     {
107         len = lstrlenA(InfSpec) + 1;
108         inf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
109         MultiByteToWideChar(CP_ACP, 0, InfSpec, -1, inf, len);
110     }
111
112     ret = SetupGetInfInformationW(inf, SearchControl, ReturnBuffer,
113                                   ReturnBufferSize, RequiredSize);
114
115     if (SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE)
116         HeapFree(GetProcessHeap(), 0, inf);
117
118     return ret;
119 }
120
121 /***********************************************************************
122  *      SetupGetInfInformationW    (SETUPAPI.@)
123  * 
124  * BUGS
125  *   Only handles the case when InfSpec is an INF handle.
126  */
127 BOOL WINAPI SetupGetInfInformationW(LPCVOID InfSpec, DWORD SearchControl,
128                                      PSP_INF_INFORMATION ReturnBuffer,
129                                      DWORD ReturnBufferSize, PDWORD RequiredSize)
130 {
131     HINF inf;
132     BOOL ret;
133     DWORD infSize;
134
135     TRACE("(%p, %d, %p, %d, %p)\n", InfSpec, SearchControl, ReturnBuffer,
136            ReturnBufferSize, RequiredSize);
137
138     if (!InfSpec)
139     {
140         if (SearchControl == INFINFO_INF_SPEC_IS_HINF)
141             SetLastError(ERROR_INVALID_HANDLE);
142         else
143             SetLastError(ERROR_INVALID_PARAMETER);
144
145         return FALSE;
146     }
147
148     switch (SearchControl)
149     {
150         case INFINFO_INF_SPEC_IS_HINF:
151             inf = (HINF)InfSpec;
152             break;
153         case INFINFO_INF_NAME_IS_ABSOLUTE:
154         case INFINFO_DEFAULT_SEARCH:
155             inf = SetupOpenInfFileW(InfSpec, NULL,
156                                     INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
157             break;
158         case INFINFO_REVERSE_DEFAULT_SEARCH:
159             inf = search_for_inf(InfSpec, SearchControl);
160             break;
161         case INFINFO_INF_PATH_LIST_SEARCH:
162             FIXME("Unhandled search control: %d\n", SearchControl);
163
164             if (RequiredSize)
165                 *RequiredSize = 0;
166
167             return FALSE;
168         default:
169             SetLastError(ERROR_INVALID_PARAMETER);
170             return FALSE;
171     }
172
173     if (inf == INVALID_HANDLE_VALUE)
174     {
175         SetLastError(ERROR_FILE_NOT_FOUND);
176         return FALSE;
177     }
178
179     ret = fill_inf_info(inf, ReturnBuffer, ReturnBufferSize, &infSize);
180     if (!ReturnBuffer && (ReturnBufferSize >= infSize))
181     {
182         SetLastError(ERROR_INVALID_PARAMETER);
183         ret = FALSE;
184     }
185     if (RequiredSize) *RequiredSize = infSize;
186
187     if (SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE)
188         SetupCloseInfFile(inf);
189
190     return ret;
191 }
192
193 /***********************************************************************
194  *      SetupQueryInfFileInformationA    (SETUPAPI.@)
195  */
196 BOOL WINAPI SetupQueryInfFileInformationA(PSP_INF_INFORMATION InfInformation,
197                                           UINT InfIndex, PSTR ReturnBuffer,
198                                           DWORD ReturnBufferSize, PDWORD RequiredSize)
199 {
200     LPWSTR filenameW;
201     DWORD size;
202     BOOL ret;
203
204     ret = SetupQueryInfFileInformationW(InfInformation, InfIndex, NULL, 0, &size);
205     if (!ret)
206         return FALSE;
207
208     filenameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
209
210     ret = SetupQueryInfFileInformationW(InfInformation, InfIndex,
211                                         filenameW, size, &size);
212     if (!ret)
213     {
214         HeapFree(GetProcessHeap(), 0, filenameW);
215         return FALSE;
216     }
217
218     if (RequiredSize)
219         *RequiredSize = size;
220
221     if (!ReturnBuffer)
222     {
223         if (ReturnBufferSize)
224         {
225             SetLastError(ERROR_INVALID_PARAMETER);
226             return FALSE;
227         }
228
229         return TRUE;
230     }
231
232     if (size > ReturnBufferSize)
233     {
234         SetLastError(ERROR_INSUFFICIENT_BUFFER);
235         return FALSE;
236     }
237
238     WideCharToMultiByte(CP_ACP, 0, filenameW, -1, ReturnBuffer, size, NULL, NULL);
239     HeapFree(GetProcessHeap(), 0, filenameW);
240
241     return ret;
242 }
243
244 /***********************************************************************
245  *      SetupQueryInfFileInformationW    (SETUPAPI.@)
246  */
247 BOOL WINAPI SetupQueryInfFileInformationW(PSP_INF_INFORMATION InfInformation,
248                                           UINT InfIndex, PWSTR ReturnBuffer,
249                                           DWORD ReturnBufferSize, PDWORD RequiredSize) 
250 {
251     DWORD len;
252     LPWSTR ptr;
253
254     TRACE("(%p, %u, %p, %d, %p) Stub!\n", InfInformation, InfIndex,
255           ReturnBuffer, ReturnBufferSize, RequiredSize);
256
257     if (!InfInformation)
258     {
259         SetLastError(ERROR_INVALID_PARAMETER);
260         return FALSE;
261     }
262
263     if (InfIndex != 0)
264         FIXME("Appended INF files are not handled\n");
265
266     ptr = (LPWSTR)&InfInformation->VersionData[0];
267     len = lstrlenW(ptr);
268
269     if (RequiredSize)
270         *RequiredSize = len + 1;
271
272     if (!ReturnBuffer)
273         return TRUE;
274
275     if (ReturnBufferSize < len)
276     {
277         SetLastError(ERROR_INSUFFICIENT_BUFFER);
278         return FALSE;
279     }
280
281     lstrcpyW(ReturnBuffer, ptr);
282     return TRUE;
283 }