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