setupapi: Add an initial implementation of SetupGetInfInformation.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 /***********************************************************************
64  *      SetupGetInfInformationA    (SETUPAPI.@)
65  *
66  * BUGS
67  *   If SearchControl is anything other than INFINFO_INF_SPEC_IS_HINF,
68  *   then InfSpec needs to be converted to unicode.
69  */
70 BOOL WINAPI SetupGetInfInformationA(LPCVOID InfSpec, DWORD SearchControl,
71                                     PSP_INF_INFORMATION ReturnBuffer,
72                                     DWORD ReturnBufferSize, PDWORD RequiredSize)
73 {
74     return SetupGetInfInformationW(InfSpec, SearchControl, ReturnBuffer,
75                                    ReturnBufferSize, RequiredSize);
76 }
77
78 /***********************************************************************
79  *      SetupGetInfInformationW    (SETUPAPI.@)
80  * 
81  * BUGS
82  *   Only handles the case when InfSpec is an INF handle.
83  */
84 BOOL WINAPI SetupGetInfInformationW(LPCVOID InfSpec, DWORD SearchControl,
85                                      PSP_INF_INFORMATION ReturnBuffer,
86                                      DWORD ReturnBufferSize, PDWORD RequiredSize)
87 {
88     HINF inf = (HINF)InfSpec;
89
90     TRACE("(%p, %ld, %p, %ld, %p)\n", InfSpec, SearchControl, ReturnBuffer,
91            ReturnBufferSize, RequiredSize);
92
93     if (!inf)
94     {
95         if (SearchControl == INFINFO_INF_SPEC_IS_HINF)
96             SetLastError(ERROR_INVALID_HANDLE);
97         else
98             SetLastError(ERROR_INVALID_PARAMETER);
99
100         return FALSE;
101     }
102
103     if (inf == INVALID_HANDLE_VALUE)
104     {
105         SetLastError(ERROR_FILE_NOT_FOUND);
106         return FALSE;
107     }
108
109     if (SearchControl < INFINFO_INF_SPEC_IS_HINF ||
110         SearchControl > INFINFO_INF_PATH_LIST_SEARCH)
111     {
112         SetLastError(ERROR_INVALID_PARAMETER);
113         return FALSE;
114     }
115
116     if (SearchControl != INFINFO_INF_SPEC_IS_HINF)
117     {
118         FIXME("Unhandled search control: %ld\n", SearchControl);
119
120         if (RequiredSize)
121             *RequiredSize = 0;
122
123         return FALSE;
124     }
125
126     return fill_inf_info(inf, ReturnBuffer, ReturnBufferSize, RequiredSize);
127 }
128
129 /***********************************************************************
130  *      SetupQueryInfFileInformationA    (SETUPAPI.@)
131  */
132 BOOL WINAPI SetupQueryInfFileInformationA(PSP_INF_INFORMATION InfInformation,
133                                           UINT InfIndex, PSTR ReturnBuffer,
134                                           DWORD ReturnBufferSize, PDWORD RequiredSize)
135 {
136     LPWSTR filenameW;
137     DWORD size;
138     BOOL ret;
139
140     ret = SetupQueryInfFileInformationW(InfInformation, InfIndex, NULL, 0, &size);
141     if (!ret)
142         return FALSE;
143
144     filenameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
145
146     ret = SetupQueryInfFileInformationW(InfInformation, InfIndex,
147                                         filenameW, size, &size);
148     if (!ret)
149     {
150         HeapFree(GetProcessHeap(), 0, filenameW);
151         return FALSE;
152     }
153
154     if (RequiredSize)
155         *RequiredSize = size;
156
157     if (!ReturnBuffer)
158         return TRUE;
159
160     if (size > ReturnBufferSize)
161     {
162         SetLastError(ERROR_INSUFFICIENT_BUFFER);
163         return FALSE;
164     }
165
166     WideCharToMultiByte(CP_ACP, 0, filenameW, -1, ReturnBuffer, size, NULL, NULL);
167     HeapFree(GetProcessHeap(), 0, filenameW);
168
169     return ret;
170 }
171
172 /***********************************************************************
173  *      SetupQueryInfFileInformationW    (SETUPAPI.@)
174  */
175 BOOL WINAPI SetupQueryInfFileInformationW(PSP_INF_INFORMATION InfInformation,
176                                           UINT InfIndex, PWSTR ReturnBuffer,
177                                           DWORD ReturnBufferSize, PDWORD RequiredSize) 
178 {
179     DWORD len;
180     LPWSTR ptr;
181
182     TRACE("(%p, %u, %p, %ld, %p) Stub!\n", InfInformation, InfIndex,
183           ReturnBuffer, ReturnBufferSize, RequiredSize);
184
185     if (!InfInformation)
186     {
187         SetLastError(ERROR_INVALID_PARAMETER);
188         return FALSE;
189     }
190
191     if (InfIndex != 0)
192         FIXME("Appended INF files are not handled\n");
193
194     ptr = (LPWSTR)&InfInformation->VersionData[0];
195     len = lstrlenW(ptr);
196
197     if (RequiredSize)
198         *RequiredSize = len + 1;
199
200     if (!ReturnBuffer)
201         return TRUE;
202
203     if (ReturnBufferSize < len)
204     {
205         SetLastError(ERROR_INSUFFICIENT_BUFFER);
206         return FALSE;
207     }
208
209     lstrcpyW(ReturnBuffer, ptr);
210     return TRUE;
211 }