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