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 "setupapi_private.h"
22
23 static const WCHAR source_disks_names[] =
24 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
25 static const WCHAR source_disks_files[] =
26 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
27
28 /* fills the PSP_INF_INFORMATION struct fill_info is TRUE
29 * always returns the required size of the information
30 */
fill_inf_info(HINF inf,PSP_INF_INFORMATION buffer,DWORD size,DWORD * required)31 static BOOL fill_inf_info(HINF inf, PSP_INF_INFORMATION buffer, DWORD size, DWORD *required)
32 {
33 LPCWSTR filename = PARSER_get_inf_filename(inf);
34 DWORD total_size = FIELD_OFFSET(SP_INF_INFORMATION, VersionData)
35 + (lstrlenW(filename) + 1) * sizeof(WCHAR);
36
37 if (required) *required = total_size;
38
39 /* FIXME: we need to parse the INF file to find the correct version info */
40 if (buffer)
41 {
42 if (size < total_size)
43 {
44 SetLastError(ERROR_INSUFFICIENT_BUFFER);
45 return FALSE;
46 }
47 buffer->InfStyle = INF_STYLE_WIN4;
48 buffer->InfCount = 1;
49 /* put the filename in buffer->VersionData */
50 lstrcpyW((LPWSTR)&buffer->VersionData[0], filename);
51 }
52 return TRUE;
53 }
54
search_for_inf(LPCVOID InfSpec,DWORD SearchControl)55 static HINF search_for_inf(LPCVOID InfSpec, DWORD SearchControl)
56 {
57 HINF hInf = INVALID_HANDLE_VALUE;
58 WCHAR inf_path[MAX_PATH];
59
60 static const WCHAR infW[] = {'\\','i','n','f','\\',0};
61 static const WCHAR system32W[] = {'\\','s','y','s','t','e','m','3','2','\\',0};
62
63 if (SearchControl == INFINFO_REVERSE_DEFAULT_SEARCH)
64 {
65 GetWindowsDirectoryW(inf_path, MAX_PATH);
66 lstrcatW(inf_path, system32W);
67 lstrcatW(inf_path, InfSpec);
68
69 hInf = SetupOpenInfFileW(inf_path, NULL,
70 INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
71 if (hInf != INVALID_HANDLE_VALUE)
72 return hInf;
73
74 GetWindowsDirectoryW(inf_path, MAX_PATH);
75 lstrcpyW(inf_path, infW);
76 lstrcatW(inf_path, InfSpec);
77
78 return SetupOpenInfFileW(inf_path, NULL,
79 INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
80 }
81
82 return INVALID_HANDLE_VALUE;
83 }
84
85 /***********************************************************************
86 * SetupGetInfInformationA (SETUPAPI.@)
87 *
88 */
SetupGetInfInformationA(LPCVOID InfSpec,DWORD SearchControl,PSP_INF_INFORMATION ReturnBuffer,DWORD ReturnBufferSize,PDWORD RequiredSize)89 BOOL WINAPI SetupGetInfInformationA(LPCVOID InfSpec, DWORD SearchControl,
90 PSP_INF_INFORMATION ReturnBuffer,
91 DWORD ReturnBufferSize, PDWORD RequiredSize)
92 {
93 LPWSTR inf = (LPWSTR)InfSpec;
94 DWORD len;
95 BOOL ret;
96
97 if (InfSpec && SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE)
98 {
99 len = MultiByteToWideChar(CP_ACP, 0, InfSpec, -1, NULL, 0);
100 inf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
101 if (!inf)
102 {
103 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
104 return FALSE;
105 }
106 MultiByteToWideChar(CP_ACP, 0, InfSpec, -1, inf, len);
107 }
108
109 ret = SetupGetInfInformationW(inf, SearchControl, ReturnBuffer,
110 ReturnBufferSize, RequiredSize);
111
112 if (SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE)
113 HeapFree(GetProcessHeap(), 0, inf);
114
115 return ret;
116 }
117
118 /***********************************************************************
119 * SetupGetInfInformationW (SETUPAPI.@)
120 *
121 * BUGS
122 * Only handles the case when InfSpec is an INF handle.
123 */
SetupGetInfInformationW(LPCVOID InfSpec,DWORD SearchControl,PSP_INF_INFORMATION ReturnBuffer,DWORD ReturnBufferSize,PDWORD RequiredSize)124 BOOL WINAPI SetupGetInfInformationW(LPCVOID InfSpec, DWORD SearchControl,
125 PSP_INF_INFORMATION ReturnBuffer,
126 DWORD ReturnBufferSize, PDWORD RequiredSize)
127 {
128 HINF inf;
129 BOOL ret;
130 DWORD infSize;
131
132 TRACE("(%p, %d, %p, %d, %p)\n", InfSpec, SearchControl, ReturnBuffer,
133 ReturnBufferSize, RequiredSize);
134
135 if (!InfSpec)
136 {
137 if (SearchControl == INFINFO_INF_SPEC_IS_HINF)
138 SetLastError(ERROR_INVALID_HANDLE);
139 else
140 SetLastError(ERROR_INVALID_PARAMETER);
141
142 return FALSE;
143 }
144
145 switch (SearchControl)
146 {
147 case INFINFO_INF_SPEC_IS_HINF:
148 inf = (HINF)InfSpec;
149 break;
150 case INFINFO_INF_NAME_IS_ABSOLUTE:
151 case INFINFO_DEFAULT_SEARCH:
152 inf = SetupOpenInfFileW(InfSpec, NULL,
153 INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
154 break;
155 case INFINFO_REVERSE_DEFAULT_SEARCH:
156 inf = search_for_inf(InfSpec, SearchControl);
157 break;
158 case INFINFO_INF_PATH_LIST_SEARCH:
159 FIXME("Unhandled search control: %d\n", SearchControl);
160
161 if (RequiredSize)
162 *RequiredSize = 0;
163
164 return FALSE;
165 default:
166 SetLastError(ERROR_INVALID_PARAMETER);
167 return FALSE;
168 }
169
170 if (inf == INVALID_HANDLE_VALUE)
171 {
172 SetLastError(ERROR_FILE_NOT_FOUND);
173 return FALSE;
174 }
175
176 ret = fill_inf_info(inf, ReturnBuffer, ReturnBufferSize, &infSize);
177 if (!ReturnBuffer && (ReturnBufferSize >= infSize))
178 {
179 SetLastError(ERROR_INVALID_PARAMETER);
180 ret = FALSE;
181 }
182 if (RequiredSize) *RequiredSize = infSize;
183
184 if (SearchControl >= INFINFO_INF_NAME_IS_ABSOLUTE)
185 SetupCloseInfFile(inf);
186
187 return ret;
188 }
189
190 /***********************************************************************
191 * SetupQueryInfFileInformationA (SETUPAPI.@)
192 */
SetupQueryInfFileInformationA(PSP_INF_INFORMATION InfInformation,UINT InfIndex,PSTR ReturnBuffer,DWORD ReturnBufferSize,PDWORD RequiredSize)193 BOOL WINAPI SetupQueryInfFileInformationA(PSP_INF_INFORMATION InfInformation,
194 UINT InfIndex, PSTR ReturnBuffer,
195 DWORD ReturnBufferSize, PDWORD RequiredSize)
196 {
197 LPWSTR filenameW;
198 DWORD size;
199 BOOL ret;
200
201 ret = SetupQueryInfFileInformationW(InfInformation, InfIndex, NULL, 0, &size);
202 if (!ret)
203 return FALSE;
204
205 filenameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
206
207 ret = SetupQueryInfFileInformationW(InfInformation, InfIndex,
208 filenameW, size, &size);
209 if (!ret)
210 {
211 HeapFree(GetProcessHeap(), 0, filenameW);
212 return FALSE;
213 }
214
215 if (RequiredSize)
216 *RequiredSize = size;
217
218 if (!ReturnBuffer)
219 {
220 HeapFree(GetProcessHeap(), 0, filenameW);
221 if (ReturnBufferSize)
222 {
223 SetLastError(ERROR_INVALID_PARAMETER);
224 return FALSE;
225 }
226
227 return TRUE;
228 }
229
230 if (size > ReturnBufferSize)
231 {
232 HeapFree(GetProcessHeap(), 0, filenameW);
233 SetLastError(ERROR_INSUFFICIENT_BUFFER);
234 return FALSE;
235 }
236
237 WideCharToMultiByte(CP_ACP, 0, filenameW, -1, ReturnBuffer, size, NULL, NULL);
238 HeapFree(GetProcessHeap(), 0, filenameW);
239
240 return ret;
241 }
242
243 /***********************************************************************
244 * SetupQueryInfFileInformationW (SETUPAPI.@)
245 */
SetupQueryInfFileInformationW(PSP_INF_INFORMATION InfInformation,UINT InfIndex,PWSTR ReturnBuffer,DWORD ReturnBufferSize,PDWORD RequiredSize)246 BOOL WINAPI SetupQueryInfFileInformationW(PSP_INF_INFORMATION InfInformation,
247 UINT InfIndex, PWSTR ReturnBuffer,
248 DWORD ReturnBufferSize, PDWORD RequiredSize)
249 {
250 DWORD len;
251 LPWSTR ptr;
252
253 TRACE("(%p, %u, %p, %d, %p) Stub!\n", InfInformation, InfIndex,
254 ReturnBuffer, ReturnBufferSize, RequiredSize);
255
256 if (!InfInformation)
257 {
258 SetLastError(ERROR_INVALID_PARAMETER);
259 return FALSE;
260 }
261
262 if (InfIndex != 0)
263 FIXME("Appended INF files are not handled\n");
264
265 ptr = (LPWSTR)InfInformation->VersionData;
266 len = lstrlenW(ptr);
267
268 if (RequiredSize)
269 *RequiredSize = len + 1;
270
271 if (!ReturnBuffer)
272 return TRUE;
273
274 if (ReturnBufferSize < len)
275 {
276 SetLastError(ERROR_INSUFFICIENT_BUFFER);
277 return FALSE;
278 }
279
280 lstrcpyW(ReturnBuffer, ptr);
281 return TRUE;
282 }
283
284 /***********************************************************************
285 * SetupGetSourceFileLocationA (SETUPAPI.@)
286 */
287
SetupGetSourceFileLocationA(HINF hinf,PINFCONTEXT context,PCSTR filename,PUINT source_id,PSTR buffer,DWORD buffer_size,PDWORD required_size)288 BOOL WINAPI SetupGetSourceFileLocationA( HINF hinf, PINFCONTEXT context, PCSTR filename,
289 PUINT source_id, PSTR buffer, DWORD buffer_size,
290 PDWORD required_size )
291 {
292 BOOL ret = FALSE;
293 WCHAR *filenameW = NULL, *bufferW = NULL;
294 DWORD required;
295 INT size;
296
297 TRACE("%p, %p, %s, %p, %p, 0x%08x, %p\n", hinf, context, debugstr_a(filename), source_id,
298 buffer, buffer_size, required_size);
299
300 if (filename && *filename && !(filenameW = strdupAtoW( filename )))
301 return FALSE;
302
303 if (!SetupGetSourceFileLocationW( hinf, context, filenameW, source_id, NULL, 0, &required ))
304 goto done;
305
306 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) )))
307 goto done;
308
309 if (!SetupGetSourceFileLocationW( hinf, context, filenameW, source_id, bufferW, required, NULL ))
310 goto done;
311
312 size = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
313 if (required_size) *required_size = size;
314
315 if (buffer)
316 {
317 if (buffer_size >= size)
318 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, buffer_size, NULL, NULL );
319 else
320 {
321 SetLastError( ERROR_INSUFFICIENT_BUFFER );
322 goto done;
323 }
324 }
325 ret = TRUE;
326
327 done:
328 HeapFree( GetProcessHeap(), 0, filenameW );
329 HeapFree( GetProcessHeap(), 0, bufferW );
330 return ret;
331 }
332
get_source_id(HINF hinf,PINFCONTEXT context,PCWSTR filename)333 static LPWSTR get_source_id( HINF hinf, PINFCONTEXT context, PCWSTR filename )
334 {
335 WCHAR Section[MAX_PATH];
336 DWORD size;
337 LPWSTR source_id;
338
339 if (!SetupDiGetActualSectionToInstallW(hinf, source_disks_files, Section, MAX_PATH, NULL, NULL))
340 return NULL;
341
342 if (!SetupFindFirstLineW( hinf, Section, filename, context ) &&
343 !SetupFindFirstLineW( hinf, source_disks_files, filename, context ))
344 return NULL;
345
346 if (!SetupGetStringFieldW( context, 1, NULL, 0, &size ))
347 return NULL;
348
349 if (!(source_id = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )))
350 return NULL;
351
352 if (!SetupGetStringFieldW( context, 1, source_id, size, NULL ))
353 {
354 HeapFree( GetProcessHeap(), 0, source_id );
355 return NULL;
356 }
357
358 if (!SetupDiGetActualSectionToInstallW(hinf, source_disks_names, Section, MAX_PATH, NULL, NULL))
359 {
360 HeapFree( GetProcessHeap(), 0, source_id );
361 return NULL;
362 }
363
364 if (!SetupFindFirstLineW( hinf, Section, source_id, context ) &&
365 !SetupFindFirstLineW( hinf, source_disks_names, source_id, context ))
366 {
367 HeapFree( GetProcessHeap(), 0, source_id );
368 return NULL;
369 }
370 return source_id;
371 }
372
373 /***********************************************************************
374 * SetupGetSourceFileLocationW (SETUPAPI.@)
375 */
376
SetupGetSourceFileLocationW(HINF hinf,PINFCONTEXT context,PCWSTR filename,PUINT source_id,PWSTR buffer,DWORD buffer_size,PDWORD required_size)377 BOOL WINAPI SetupGetSourceFileLocationW( HINF hinf, PINFCONTEXT context, PCWSTR filename,
378 PUINT source_id, PWSTR buffer, DWORD buffer_size,
379 PDWORD required_size )
380 {
381 INFCONTEXT ctx;
382 WCHAR *end, *source_id_str;
383
384 TRACE("%p, %p, %s, %p, %p, 0x%08x, %p\n", hinf, context, debugstr_w(filename), source_id,
385 buffer, buffer_size, required_size);
386
387 if (!context) context = &ctx;
388
389 if (!(source_id_str = get_source_id( hinf, context, filename )))
390 return FALSE;
391
392 *source_id = strtolW( source_id_str, &end, 10 );
393 if (end == source_id_str || *end)
394 {
395 HeapFree( GetProcessHeap(), 0, source_id_str );
396 return FALSE;
397 }
398 HeapFree( GetProcessHeap(), 0, source_id_str );
399
400 if (SetupGetStringFieldW( context, 4, buffer, buffer_size, required_size ))
401 return TRUE;
402
403 if (required_size) *required_size = 1;
404 if (buffer)
405 {
406 if (buffer_size >= 1) buffer[0] = 0;
407 else
408 {
409 SetLastError( ERROR_INSUFFICIENT_BUFFER );
410 return FALSE;
411 }
412 }
413 return TRUE;
414 }
415
416 /***********************************************************************
417 * SetupGetSourceInfoA (SETUPAPI.@)
418 */
419
SetupGetSourceInfoA(HINF hinf,UINT source_id,UINT info,PSTR buffer,DWORD buffer_size,LPDWORD required_size)420 BOOL WINAPI SetupGetSourceInfoA( HINF hinf, UINT source_id, UINT info,
421 PSTR buffer, DWORD buffer_size, LPDWORD required_size )
422 {
423 BOOL ret = FALSE;
424 WCHAR *bufferW = NULL;
425 DWORD required;
426 INT size;
427
428 TRACE("%p, %d, %d, %p, %d, %p\n", hinf, source_id, info, buffer, buffer_size,
429 required_size);
430
431 if (!SetupGetSourceInfoW( hinf, source_id, info, NULL, 0, &required ))
432 return FALSE;
433
434 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) )))
435 return FALSE;
436
437 if (!SetupGetSourceInfoW( hinf, source_id, info, bufferW, required, NULL ))
438 goto done;
439
440 size = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
441 if (required_size) *required_size = size;
442
443 if (buffer)
444 {
445 if (buffer_size >= size)
446 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, buffer_size, NULL, NULL );
447 else
448 {
449 SetLastError( ERROR_INSUFFICIENT_BUFFER );
450 goto done;
451 }
452 }
453 ret = TRUE;
454
455 done:
456 HeapFree( GetProcessHeap(), 0, bufferW );
457 return ret;
458 }
459
460 /***********************************************************************
461 * SetupGetSourceInfoW (SETUPAPI.@)
462 */
463
SetupGetSourceInfoW(HINF hinf,UINT source_id,UINT info,PWSTR buffer,DWORD buffer_size,LPDWORD required_size)464 BOOL WINAPI SetupGetSourceInfoW( HINF hinf, UINT source_id, UINT info,
465 PWSTR buffer, DWORD buffer_size, LPDWORD required_size )
466 {
467 WCHAR Section[MAX_PATH];
468 INFCONTEXT ctx;
469 WCHAR source_id_str[11];
470 static const WCHAR fmt[] = {'%','d',0};
471 DWORD index;
472
473 TRACE("%p, %d, %d, %p, %d, %p\n", hinf, source_id, info, buffer, buffer_size,
474 required_size);
475
476 sprintfW( source_id_str, fmt, source_id );
477
478 if (!SetupDiGetActualSectionToInstallW(hinf, source_disks_names, Section, MAX_PATH, NULL, NULL))
479 return FALSE;
480
481 if (!SetupFindFirstLineW( hinf, Section, source_id_str, &ctx ) &&
482 !SetupFindFirstLineW( hinf, source_disks_names, source_id_str, &ctx ))
483 return FALSE;
484
485 switch (info)
486 {
487 case SRCINFO_PATH: index = 4; break;
488 case SRCINFO_TAGFILE: index = 2; break;
489 case SRCINFO_DESCRIPTION: index = 1; break;
490 default:
491 WARN("unknown info level: %d\n", info);
492 return FALSE;
493 }
494
495 if (SetupGetStringFieldW( &ctx, index, buffer, buffer_size, required_size ))
496 return TRUE;
497
498 if (required_size) *required_size = 1;
499 if (buffer)
500 {
501 if (buffer_size >= 1) buffer[0] = 0;
502 else
503 {
504 SetLastError( ERROR_INSUFFICIENT_BUFFER );
505 return FALSE;
506 }
507 }
508 return TRUE;
509 }
510
511 /***********************************************************************
512 * SetupGetTargetPathA (SETUPAPI.@)
513 */
514
SetupGetTargetPathA(HINF hinf,PINFCONTEXT context,PCSTR section,PSTR buffer,DWORD buffer_size,PDWORD required_size)515 BOOL WINAPI SetupGetTargetPathA( HINF hinf, PINFCONTEXT context, PCSTR section, PSTR buffer,
516 DWORD buffer_size, PDWORD required_size )
517 {
518 BOOL ret = FALSE;
519 WCHAR *sectionW = NULL, *bufferW = NULL;
520 DWORD required;
521 INT size;
522
523 TRACE("%p, %p, %s, %p, 0x%08x, %p\n", hinf, context, debugstr_a(section), buffer,
524 buffer_size, required_size);
525
526 if (section && !(sectionW = strdupAtoW( section )))
527 return FALSE;
528
529 if (!SetupGetTargetPathW( hinf, context, sectionW, NULL, 0, &required ))
530 goto done;
531
532 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, required * sizeof(WCHAR) )))
533 goto done;
534
535 if (!SetupGetTargetPathW( hinf, context, sectionW, bufferW, required, NULL ))
536 goto done;
537
538 size = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
539 if (required_size) *required_size = size;
540
541 if (buffer)
542 {
543 if (buffer_size >= size)
544 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, buffer_size, NULL, NULL );
545 else
546 {
547 SetLastError( ERROR_INSUFFICIENT_BUFFER );
548 goto done;
549 }
550 }
551 ret = TRUE;
552
553 done:
554 HeapFree( GetProcessHeap(), 0, sectionW );
555 HeapFree( GetProcessHeap(), 0, bufferW );
556 return ret;
557 }
558
559 /***********************************************************************
560 * SetupGetTargetPathW (SETUPAPI.@)
561 */
562
SetupGetTargetPathW(HINF hinf,PINFCONTEXT context,PCWSTR section,PWSTR buffer,DWORD buffer_size,PDWORD required_size)563 BOOL WINAPI SetupGetTargetPathW( HINF hinf, PINFCONTEXT context, PCWSTR section, PWSTR buffer,
564 DWORD buffer_size, PDWORD required_size )
565 {
566 static const WCHAR destination_dirs[] =
567 {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
568 static const WCHAR default_dest_dir[] =
569 {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
570
571 INFCONTEXT ctx;
572 WCHAR *dir, systemdir[MAX_PATH];
573 unsigned int size;
574 BOOL ret = FALSE;
575
576 TRACE("%p, %p, %s, %p, 0x%08x, %p\n", hinf, context, debugstr_w(section), buffer,
577 buffer_size, required_size);
578
579 if (context) ret = SetupFindFirstLineW( hinf, destination_dirs, NULL, context );
580 else if (section)
581 {
582 if (!(ret = SetupFindFirstLineW( hinf, destination_dirs, section, &ctx )))
583 ret = SetupFindFirstLineW( hinf, destination_dirs, default_dest_dir, &ctx );
584 }
585 if (!ret || !(dir = PARSER_get_dest_dir( context ? context : &ctx )))
586 {
587 GetSystemDirectoryW( systemdir, MAX_PATH );
588 dir = systemdir;
589 }
590 size = strlenW( dir ) + 1;
591 if (required_size) *required_size = size;
592
593 if (buffer)
594 {
595 if (buffer_size >= size)
596 lstrcpyW( buffer, dir );
597 else
598 {
599 SetLastError( ERROR_INSUFFICIENT_BUFFER );
600 if (dir != systemdir) HeapFree( GetProcessHeap(), 0, dir );
601 return FALSE;
602 }
603 }
604 if (dir != systemdir) HeapFree( GetProcessHeap(), 0, dir );
605 return TRUE;
606 }
607
608 /***********************************************************************
609 * SetupQueryInfOriginalFileInformationA (SETUPAPI.@)
610 */
SetupQueryInfOriginalFileInformationA(PSP_INF_INFORMATION InfInformation,UINT InfIndex,PSP_ALTPLATFORM_INFO AlternativePlatformInfo,PSP_ORIGINAL_FILE_INFO_A OriginalFileInfo)611 BOOL WINAPI SetupQueryInfOriginalFileInformationA(
612 PSP_INF_INFORMATION InfInformation, UINT InfIndex,
613 PSP_ALTPLATFORM_INFO AlternativePlatformInfo,
614 PSP_ORIGINAL_FILE_INFO_A OriginalFileInfo)
615 {
616 BOOL ret;
617 SP_ORIGINAL_FILE_INFO_W OriginalFileInfoW;
618
619 TRACE("(%p, %d, %p, %p)\n", InfInformation, InfIndex,
620 AlternativePlatformInfo, OriginalFileInfo);
621
622 if (OriginalFileInfo->cbSize != sizeof(*OriginalFileInfo))
623 {
624 WARN("incorrect OriginalFileInfo->cbSize of %d\n", OriginalFileInfo->cbSize);
625 SetLastError( ERROR_INVALID_USER_BUFFER );
626 return FALSE;
627 }
628
629 OriginalFileInfoW.cbSize = sizeof(OriginalFileInfoW);
630 ret = SetupQueryInfOriginalFileInformationW(InfInformation, InfIndex,
631 AlternativePlatformInfo, &OriginalFileInfoW);
632 if (ret)
633 {
634 WideCharToMultiByte(CP_ACP, 0, OriginalFileInfoW.OriginalInfName, -1,
635 OriginalFileInfo->OriginalInfName, MAX_PATH, NULL, NULL);
636 WideCharToMultiByte(CP_ACP, 0, OriginalFileInfoW.OriginalCatalogName, -1,
637 OriginalFileInfo->OriginalCatalogName, MAX_PATH, NULL, NULL);
638 }
639
640 return ret;
641 }
642
643 /***********************************************************************
644 * SetupQueryInfOriginalFileInformationW (SETUPAPI.@)
645 */
SetupQueryInfOriginalFileInformationW(PSP_INF_INFORMATION InfInformation,UINT InfIndex,PSP_ALTPLATFORM_INFO AlternativePlatformInfo,PSP_ORIGINAL_FILE_INFO_W OriginalFileInfo)646 BOOL WINAPI SetupQueryInfOriginalFileInformationW(
647 PSP_INF_INFORMATION InfInformation, UINT InfIndex,
648 PSP_ALTPLATFORM_INFO AlternativePlatformInfo,
649 PSP_ORIGINAL_FILE_INFO_W OriginalFileInfo)
650 {
651 LPCWSTR inf_name;
652 LPCWSTR inf_path;
653 HINF hinf;
654 static const WCHAR wszVersion[] = { 'V','e','r','s','i','o','n',0 };
655 static const WCHAR wszCatalogFile[] = { 'C','a','t','a','l','o','g','F','i','l','e',0 };
656
657 FIXME("(%p, %d, %p, %p): semi-stub\n", InfInformation, InfIndex,
658 AlternativePlatformInfo, OriginalFileInfo);
659
660 if (OriginalFileInfo->cbSize != sizeof(*OriginalFileInfo))
661 {
662 WARN("incorrect OriginalFileInfo->cbSize of %d\n", OriginalFileInfo->cbSize);
663 SetLastError(ERROR_INVALID_USER_BUFFER);
664 return FALSE;
665 }
666
667 inf_path = (LPWSTR)InfInformation->VersionData;
668
669 /* FIXME: we should get OriginalCatalogName from CatalogFile line in
670 * the original inf file and cache it, but that would require building a
671 * .pnf file. */
672 hinf = SetupOpenInfFileW(inf_path, NULL, INF_STYLE_WIN4, NULL);
673 if (hinf == INVALID_HANDLE_VALUE) return FALSE;
674
675 if (!SetupGetLineTextW(NULL, hinf, wszVersion, wszCatalogFile,
676 OriginalFileInfo->OriginalCatalogName,
677 sizeof(OriginalFileInfo->OriginalCatalogName)/sizeof(OriginalFileInfo->OriginalCatalogName[0]),
678 NULL))
679 {
680 OriginalFileInfo->OriginalCatalogName[0] = '\0';
681 }
682 SetupCloseInfFile(hinf);
683
684 /* FIXME: not quite correct as we just return the same file name as
685 * destination (copied) inf file, not the source (original) inf file.
686 * to fix it properly would require building a .pnf file */
687 /* file name is stored in VersionData field of InfInformation */
688 inf_name = strrchrW(inf_path, '\\');
689 if (inf_name) inf_name++;
690 else inf_name = inf_path;
691
692 strcpyW(OriginalFileInfo->OriginalInfName, inf_name);
693
694 return TRUE;
695 }
696