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