[INETCOMM_WINETEST] Sync with Wine 3.0. CORE-14225
[reactos.git] / dll / win32 / inseng / icif.c
1 /*
2 * Copyright 2016 Michael Müller
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include "inseng_private.h"
20
21 #define DEFAULT_INSTALLER_DESC "Active Setup Installation"
22
23 struct cifgroup
24 {
25 ICifGroup ICifGroup_iface;
26
27 struct list entry;
28
29 ICifFile *parent;
30
31 char *id;
32 char *description;
33 DWORD priority;
34 };
35
36 struct ciffenum_components
37 {
38 IEnumCifComponents IEnumCifComponents_iface;
39 LONG ref;
40
41 ICifFile *file;
42 struct list *start;
43 struct list *position;
44
45 char *group_id;
46 };
47
48 struct ciffenum_groups
49 {
50 IEnumCifGroups IEnumCifGroups_iface;
51 LONG ref;
52
53 ICifFile *file;
54 struct list *start;
55 struct list *position;
56 };
57
58 struct url_info
59 {
60 struct list entry;
61 INT index;
62 char *url;
63 DWORD flags;
64 };
65
66 struct dependency_info
67 {
68 struct list entry;
69 char *id;
70 char *type;
71 };
72
73 struct cifcomponent
74 {
75 ICifComponent ICifComponent_iface;
76
77 struct list entry;
78
79 ICifFile *parent;
80
81 char *id;
82 char *guid;
83 char *description;
84 char *details;
85 char *group;
86
87
88 DWORD version;
89 DWORD build;
90 char *patchid;
91
92 char *locale;
93 char *key_uninstall;
94
95 DWORD size_win;
96 DWORD size_app;
97 DWORD size_download;
98 DWORD size_extracted;
99
100 char *key_success;
101 char *key_progress;
102 char *key_cancel;
103
104 DWORD as_aware;
105 DWORD reboot;
106 DWORD admin;
107 DWORD visibleui;
108
109 DWORD priority;
110 DWORD platform;
111
112 struct list dependencies;
113 struct list urls;
114
115 /* mode */
116 /* det version */
117 /* one component */
118 /* custom data */
119
120 /* in memory state */
121 DWORD queue_state;
122 DWORD current_priority;
123 DWORD size_actual_download;
124 BOOL downloaded;
125 BOOL installed;
126 };
127
128 struct ciffile
129 {
130 ICifFile ICifFile_iface;
131 LONG ref;
132
133 struct list components;
134 struct list groups;
135
136 char *name;
137 };
138
139 static inline struct ciffile *impl_from_ICiffile(ICifFile *iface)
140 {
141 return CONTAINING_RECORD(iface, struct ciffile, ICifFile_iface);
142 }
143
144 static inline struct cifcomponent *impl_from_ICifComponent(ICifComponent *iface)
145 {
146 return CONTAINING_RECORD(iface, struct cifcomponent, ICifComponent_iface);
147 }
148
149 static inline struct cifgroup *impl_from_ICifGroup(ICifGroup *iface)
150 {
151 return CONTAINING_RECORD(iface, struct cifgroup, ICifGroup_iface);
152 }
153
154 static inline struct ciffenum_components *impl_from_IEnumCifComponents(IEnumCifComponents *iface)
155 {
156 return CONTAINING_RECORD(iface, struct ciffenum_components, IEnumCifComponents_iface);
157 }
158
159 static inline struct ciffenum_groups *impl_from_IEnumCifGroups(IEnumCifGroups *iface)
160 {
161 return CONTAINING_RECORD(iface, struct ciffenum_groups, IEnumCifGroups_iface);
162 }
163
164 static HRESULT enum_components_create(ICifFile *file, struct list *start, char *group_id, IEnumCifComponents **iface);
165
166 static HRESULT copy_substring_null(char *dest, int max_len, char *src)
167 {
168 if (!src)
169 return E_FAIL;
170
171 if (max_len <= 0)
172 return S_OK;
173
174 if (!dest)
175 return E_FAIL;
176
177 while (*src && max_len-- > 1)
178 *dest++ = *src++;
179 *dest = 0;
180
181 return S_OK;
182 }
183
184 static void url_entry_free(struct url_info *url)
185 {
186 heap_free(url->url);
187 heap_free(url);
188 }
189
190 static void dependency_entry_free(struct dependency_info *dependency)
191 {
192 heap_free(dependency->id);
193 heap_free(dependency);
194 }
195
196 static void component_free(struct cifcomponent *comp)
197 {
198 struct dependency_info *dependency, *dependency_next;
199 struct url_info *url, *url_next;
200
201 heap_free(comp->id);
202 heap_free(comp->guid);
203 heap_free(comp->description);
204 heap_free(comp->details);
205 heap_free(comp->group);
206
207 heap_free(comp->patchid);
208
209 heap_free(comp->locale);
210 heap_free(comp->key_uninstall);
211
212 heap_free(comp->key_success);
213 heap_free(comp->key_progress);
214 heap_free(comp->key_cancel);
215
216 LIST_FOR_EACH_ENTRY_SAFE(dependency, dependency_next, &comp->dependencies, struct dependency_info, entry)
217 {
218 list_remove(&dependency->entry);
219 dependency_entry_free(dependency);
220 }
221
222 LIST_FOR_EACH_ENTRY_SAFE(url, url_next, &comp->urls, struct url_info, entry)
223 {
224 list_remove(&url->entry);
225 url_entry_free(url);
226 }
227
228 heap_free(comp);
229 }
230
231 static void group_free(struct cifgroup *group)
232 {
233 heap_free(group->id);
234 heap_free(group->description);
235 heap_free(group);
236 }
237
238 static HRESULT WINAPI group_GetID(ICifGroup *iface, char *id, DWORD size)
239 {
240 struct cifgroup *This = impl_from_ICifGroup(iface);
241
242 TRACE("(%p)->(%p, %u)\n", This, id, size);
243
244 return copy_substring_null(id, size, This->id);
245 }
246
247 static HRESULT WINAPI group_GetDescription(ICifGroup *iface, char *desc, DWORD size)
248 {
249 struct cifgroup *This = impl_from_ICifGroup(iface);
250
251 TRACE("(%p)->(%p, %u)\n", This, desc, size);
252
253 return copy_substring_null(desc, size, This->description);
254 }
255
256 static DWORD WINAPI group_GetPriority(ICifGroup *iface)
257 {
258 struct cifgroup *This = impl_from_ICifGroup(iface);
259
260 TRACE("(%p)\n", This);
261
262 return This->priority;
263 }
264
265 static HRESULT WINAPI group_EnumComponents(ICifGroup *iface, IEnumCifComponents **enum_components, DWORD filter, LPVOID pv)
266 {
267 struct cifgroup *This = impl_from_ICifGroup(iface);
268 struct ciffile *file;
269
270 TRACE("(%p)->(%p, %u, %p)\n", This, enum_components, filter, pv);
271
272 if (filter)
273 FIXME("filter (%x) not supported\n", filter);
274 if (pv)
275 FIXME("how to handle pv (%p)?\n", pv);
276
277 file = impl_from_ICiffile(This->parent);
278 return enum_components_create(This->parent, &file->components, This->id, enum_components);
279 }
280
281 static DWORD WINAPI group_GetCurrentPriority(ICifGroup *iface)
282 {
283 struct cifgroup *This = impl_from_ICifGroup(iface);
284
285 FIXME("(%p): stub\n", This);
286
287 return 0;
288 }
289
290 static const ICifGroupVtbl cifgroupVtbl =
291 {
292 group_GetID,
293 group_GetDescription,
294 group_GetPriority,
295 group_EnumComponents,
296 group_GetCurrentPriority,
297 };
298
299 void component_set_actual_download_size(ICifComponent *iface, DWORD size)
300 {
301 struct cifcomponent *This = impl_from_ICifComponent(iface);
302
303 This->size_actual_download = size;
304 }
305
306 void component_set_downloaded(ICifComponent *iface, BOOL value)
307 {
308 struct cifcomponent *This = impl_from_ICifComponent(iface);
309
310 This->downloaded = value;
311 }
312
313 void component_set_installed(ICifComponent *iface, BOOL value)
314 {
315 struct cifcomponent *This = impl_from_ICifComponent(iface);
316
317 This->installed = value;
318 }
319
320 char *component_get_id(ICifComponent *iface)
321 {
322 struct cifcomponent *This = impl_from_ICifComponent(iface);
323
324 return This->id;
325 }
326
327 static HRESULT WINAPI component_GetID(ICifComponent *iface, char *id, DWORD size)
328 {
329 struct cifcomponent *This = impl_from_ICifComponent(iface);
330
331 TRACE("(%p)->(%p, %u)\n", This, id, size);
332
333 return copy_substring_null(id, size, This->id);
334 }
335
336 static HRESULT WINAPI component_GetGUID(ICifComponent *iface, char *guid, DWORD size)
337 {
338 struct cifcomponent *This = impl_from_ICifComponent(iface);
339
340 TRACE("(%p)->(%p, %u)\n", This, guid, size);
341
342 return copy_substring_null(guid, size, This->guid);
343 }
344
345 static HRESULT WINAPI component_GetDescription(ICifComponent *iface, char *desc, DWORD size)
346 {
347 struct cifcomponent *This = impl_from_ICifComponent(iface);
348
349 TRACE("(%p)->(%p, %u)\n", This, desc, size);
350
351 return copy_substring_null(desc, size, This->description);
352 }
353
354 static HRESULT WINAPI component_GetDetails(ICifComponent *iface, char *details, DWORD size)
355 {
356 struct cifcomponent *This = impl_from_ICifComponent(iface);
357
358 TRACE("(%p)->(%p, %u)\n", This, details, size);
359
360 return copy_substring_null(details, size, This->details);
361 }
362
363 static HRESULT WINAPI component_GetUrl(ICifComponent *iface, UINT index, char *url, DWORD size, DWORD *flags)
364 {
365 struct cifcomponent *This = impl_from_ICifComponent(iface);
366 struct url_info *entry;
367
368 TRACE("(%p)->(%u, %p, %u, %p)\n", This, index, url, size, flags);
369
370 /* FIXME: check how functions behaves for url == NULL */
371
372 if (!flags)
373 return E_FAIL;
374
375 LIST_FOR_EACH_ENTRY(entry, &This->urls, struct url_info, entry)
376 {
377 if (entry->index != index)
378 continue;
379
380 *flags = entry->flags;
381 return copy_substring_null(url, size, entry->url);
382 }
383
384 return E_FAIL;
385 }
386
387 static HRESULT WINAPI component_GetFileExtractList(ICifComponent *iface, UINT index, char *list, DWORD size)
388 {
389 struct cifcomponent *This = impl_from_ICifComponent(iface);
390
391 FIXME("(%p)->(%u, %p, %u): stub\n", This, index, list, size);
392
393 return E_NOTIMPL;
394 }
395
396 static HRESULT WINAPI component_GetUrlCheckRange(ICifComponent *iface, UINT index, DWORD *min, DWORD *max)
397 {
398 struct cifcomponent *This = impl_from_ICifComponent(iface);
399
400 FIXME("(%p)->(%u, %p, %p): stub\n", This, index, min, max);
401
402 return E_NOTIMPL;
403 }
404
405 static HRESULT WINAPI component_GetCommand(ICifComponent *iface, UINT index, char *cmd, DWORD cmd_size, char *switches, DWORD switch_size, DWORD *type)
406 {
407 struct cifcomponent *This = impl_from_ICifComponent(iface);
408
409 FIXME("(%p)->(%u, %p, %u, %p, %u, %p): stub\n", This, index, cmd, cmd_size, switches, switch_size, type);
410
411 return E_NOTIMPL;
412 }
413
414 static HRESULT WINAPI component_GetVersion(ICifComponent *iface, DWORD *version, DWORD *build)
415 {
416 struct cifcomponent *This = impl_from_ICifComponent(iface);
417
418 TRACE("(%p)->(%p, %p)\n", This, version, build);
419
420 if (!version || !build)
421 return E_FAIL;
422
423 *version = This->version;
424 *build = This->build;
425
426 return S_OK;
427 }
428
429 static HRESULT WINAPI component_GetLocale(ICifComponent *iface, char *locale, DWORD size)
430 {
431 struct cifcomponent *This = impl_from_ICifComponent(iface);
432
433 TRACE("(%p)->(%p, %u)\n", This, locale, size);
434
435 return copy_substring_null(locale, size, This->locale);
436 }
437
438 static HRESULT WINAPI component_GetUninstallKey(ICifComponent *iface, char *key, DWORD size)
439 {
440 struct cifcomponent *This = impl_from_ICifComponent(iface);
441
442 TRACE("(%p)->(%p, %u)\n", This, key, size);
443
444 return copy_substring_null(key, size, This->key_uninstall);
445 }
446
447 static HRESULT WINAPI component_GetInstalledSize(ICifComponent *iface, DWORD *win, DWORD *app)
448 {
449 struct cifcomponent *This = impl_from_ICifComponent(iface);
450
451 TRACE("(%p)->(%p, %p)\n", This, win, app);
452
453 if (!win || !app)
454 return E_FAIL;
455
456 *win = This->size_win;
457 *app = This->size_app;
458
459 return S_OK;
460 }
461
462 static DWORD WINAPI component_GetDownloadSize(ICifComponent *iface)
463 {
464 struct cifcomponent *This = impl_from_ICifComponent(iface);
465
466 TRACE("(%p)\n", This);
467
468 return This->size_download;
469 }
470
471 static DWORD WINAPI component_GetExtractSize(ICifComponent *iface)
472 {
473 struct cifcomponent *This = impl_from_ICifComponent(iface);
474
475 TRACE("(%p)\n", This);
476
477 return This->size_extracted;
478 }
479
480 static HRESULT WINAPI component_GetSuccessKey(ICifComponent *iface, char *key, DWORD size)
481 {
482 struct cifcomponent *This = impl_from_ICifComponent(iface);
483
484 TRACE("(%p)->(%p, %u)\n", This, key, size);
485
486 return copy_substring_null(key, size, This->key_success);
487 }
488
489 static HRESULT WINAPI component_GetProgressKeys(ICifComponent *iface, char *progress, DWORD progress_size,
490 char *cancel, DWORD cancel_size)
491 {
492 struct cifcomponent *This = impl_from_ICifComponent(iface);
493 HRESULT hr;
494
495 TRACE("(%p)->(%p, %u, %p, %u): semi-stub\n", This, progress, progress_size, cancel, cancel_size);
496
497 hr = copy_substring_null(progress, progress_size, This->key_progress);
498 if (hr != S_OK) return hr;
499
500 if (cancel_size > 0 && cancel)
501 *cancel = 0;
502
503 return S_OK;
504 }
505
506 static HRESULT WINAPI component_IsActiveSetupAware(ICifComponent *iface)
507 {
508 struct cifcomponent *This = impl_from_ICifComponent(iface);
509
510 TRACE("(%p)\n", This);
511
512 return This->as_aware ? S_OK : S_FALSE;
513 }
514
515 static HRESULT WINAPI component_IsRebootRequired(ICifComponent *iface)
516 {
517 struct cifcomponent *This = impl_from_ICifComponent(iface);
518
519 TRACE("(%p)\n", This);
520
521 return This->reboot ? S_OK : S_FALSE;
522 }
523
524 static HRESULT WINAPI component_RequiresAdminRights(ICifComponent *iface)
525 {
526 struct cifcomponent *This = impl_from_ICifComponent(iface);
527
528 TRACE("(%p)\n", This);
529
530 return This->admin ? S_OK : S_FALSE;
531 }
532
533 static DWORD WINAPI component_GetPriority(ICifComponent *iface)
534 {
535 struct cifcomponent *This = impl_from_ICifComponent(iface);
536
537 TRACE("(%p)\n", This);
538
539 return This->priority;
540 }
541
542 static HRESULT WINAPI component_GetDependency(ICifComponent *iface, UINT index, char *id, DWORD id_size, char *type, DWORD *ver, DWORD *build)
543 {
544 struct cifcomponent *This = impl_from_ICifComponent(iface);
545 struct dependency_info *entry;
546 ICifComponent *dependency;
547 int pos = 0;
548
549 TRACE("(%p)->(%u, %p, %u, %p, %p, %p)\n", This, index, id, id_size, type, ver, build);
550
551 if (!id || !ver || !build)
552 return E_FAIL;
553
554 LIST_FOR_EACH_ENTRY(entry, &This->dependencies, struct dependency_info, entry)
555 {
556 if (pos++ < index)
557 continue;
558
559 if (ICifFile_FindComponent(This->parent, entry->id, &dependency) == S_OK)
560 {
561 ICifComponent_GetVersion(dependency, ver, build);
562 }
563 else
564 {
565 *ver = -1;
566 *build = -1;
567 }
568
569 if (entry->type)
570 *type = *entry->type;
571 else
572 *type = 'I';
573
574 return copy_substring_null(id, id_size, entry->id);
575 }
576
577 return E_FAIL;
578 }
579
580 static DWORD WINAPI component_GetPlatform(ICifComponent *iface)
581 {
582 struct cifcomponent *This = impl_from_ICifComponent(iface);
583
584 TRACE("(%p)\n", This);
585
586 return This->platform;
587 }
588
589 static HRESULT WINAPI component_GetMode(ICifComponent *iface, UINT index, char *mode, DWORD size)
590 {
591 struct cifcomponent *This = impl_from_ICifComponent(iface);
592
593 FIXME("(%p)->(%u, %p, %u): stub\n", This, index, mode, size);
594
595 return E_NOTIMPL;
596 }
597
598 static HRESULT WINAPI component_GetGroup(ICifComponent *iface, char *id, DWORD size)
599 {
600 struct cifcomponent *This = impl_from_ICifComponent(iface);
601
602 TRACE("(%p)->(%p, %u)\n", This, id, size);
603
604 return copy_substring_null(id, size, This->group);
605 }
606
607 static HRESULT WINAPI component_IsUIVisible(ICifComponent *iface)
608 {
609 struct cifcomponent *This = impl_from_ICifComponent(iface);
610
611 TRACE("(%p)\n", This);
612
613 return This->visibleui ? S_OK : S_FALSE;
614 }
615
616 static HRESULT WINAPI component_GetPatchID(ICifComponent *iface, char *id, DWORD size)
617 {
618 struct cifcomponent *This = impl_from_ICifComponent(iface);
619
620 TRACE("(%p)->(%p, %u)\n", This, id, size);
621
622 return copy_substring_null(id, size, This->patchid);
623 }
624
625 static HRESULT WINAPI component_GetDetVersion(ICifComponent *iface, char *dll, DWORD dll_size, char *entry, DWORD entry_size)
626 {
627 struct cifcomponent *This = impl_from_ICifComponent(iface);
628
629 FIXME("(%p)->(%p, %u, %p, %u): stub\n", This, dll, dll_size, entry, entry_size);
630
631 return E_NOTIMPL;
632 }
633
634 static HRESULT WINAPI component_GetTreatAsOneComponents(ICifComponent *iface, UINT index, char *id, DWORD size)
635 {
636 struct cifcomponent *This = impl_from_ICifComponent(iface);
637
638 FIXME("(%p)->(%u, %p, %u): stub\n", This, index, id, size);
639
640 return E_NOTIMPL;
641 }
642
643 static HRESULT WINAPI component_GetCustomData(ICifComponent *iface, char *key, char *data, DWORD size)
644 {
645 struct cifcomponent *This = impl_from_ICifComponent(iface);
646
647 FIXME("(%p)->(%s, %p, %u): stub\n", This, debugstr_a(key), data, size);
648
649 return E_NOTIMPL;
650 }
651
652 static DWORD WINAPI component_IsComponentInstalled(ICifComponent *iface)
653 {
654 struct cifcomponent *This = impl_from_ICifComponent(iface);
655
656 TRACE("(%p)\n", This);
657
658 return This->installed;
659 }
660
661 static HRESULT WINAPI component_IsComponentDownloaded(ICifComponent *iface)
662 {
663 struct cifcomponent *This = impl_from_ICifComponent(iface);
664
665 TRACE("(%p)\n", This);
666
667 return This->downloaded ? S_OK : S_FALSE;
668 }
669
670 static DWORD WINAPI component_IsThisVersionInstalled(ICifComponent *iface, DWORD version, DWORD build, DWORD *ret_version, DWORD *ret_build)
671 {
672 struct cifcomponent *This = impl_from_ICifComponent(iface);
673
674 FIXME("(%p)->(%u, %u, %p, %p): stub\n", This, version, build, ret_version, ret_build);
675
676 return 0;
677 }
678
679 static DWORD WINAPI component_GetInstallQueueState(ICifComponent *iface)
680 {
681 struct cifcomponent *This = impl_from_ICifComponent(iface);
682
683 TRACE("(%p)\n", This);
684
685 return This->queue_state;
686 }
687
688 static HRESULT WINAPI component_SetInstallQueueState(ICifComponent *iface, DWORD state)
689 {
690 struct cifcomponent *This = impl_from_ICifComponent(iface);
691
692 TRACE("(%p)->(%u)\n", This, state);
693
694 This->queue_state = state;
695 return S_OK;
696 }
697
698 static DWORD WINAPI component_GetActualDownloadSize(ICifComponent *iface)
699 {
700 struct cifcomponent *This = impl_from_ICifComponent(iface);
701
702 TRACE("(%p)\n", This);
703
704 return This->size_download;
705 }
706
707 static DWORD WINAPI component_GetCurrentPriority(ICifComponent *iface)
708 {
709 struct cifcomponent *This = impl_from_ICifComponent(iface);
710
711 TRACE("(%p)\n", This);
712
713 return This->current_priority;
714 }
715
716
717 static HRESULT WINAPI component_SetCurrentPriority(ICifComponent *iface, DWORD priority)
718 {
719 struct cifcomponent *This = impl_from_ICifComponent(iface);
720
721 TRACE("(%p)->(%u)\n", This, priority);
722
723 This->current_priority = priority;
724 return S_OK;
725 }
726
727 static const ICifComponentVtbl cifcomponentVtbl =
728 {
729 component_GetID,
730 component_GetGUID,
731 component_GetDescription,
732 component_GetDetails,
733 component_GetUrl,
734 component_GetFileExtractList,
735 component_GetUrlCheckRange,
736 component_GetCommand,
737 component_GetVersion,
738 component_GetLocale,
739 component_GetUninstallKey,
740 component_GetInstalledSize,
741 component_GetDownloadSize,
742 component_GetExtractSize,
743 component_GetSuccessKey,
744 component_GetProgressKeys,
745 component_IsActiveSetupAware,
746 component_IsRebootRequired,
747 component_RequiresAdminRights,
748 component_GetPriority,
749 component_GetDependency,
750 component_GetPlatform,
751 component_GetMode,
752 component_GetGroup,
753 component_IsUIVisible,
754 component_GetPatchID,
755 component_GetDetVersion,
756 component_GetTreatAsOneComponents,
757 component_GetCustomData,
758 component_IsComponentInstalled,
759 component_IsComponentDownloaded,
760 component_IsThisVersionInstalled,
761 component_GetInstallQueueState,
762 component_SetInstallQueueState,
763 component_GetActualDownloadSize,
764 component_GetCurrentPriority,
765 component_SetCurrentPriority,
766 };
767
768 static HRESULT WINAPI enum_components_QueryInterface(IEnumCifComponents *iface, REFIID riid, void **ppv)
769 {
770 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface);
771
772 if (IsEqualGUID(&IID_IUnknown, riid))
773 {
774 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
775 *ppv = &This->IEnumCifComponents_iface;
776 }
777 /*
778 else if (IsEqualGUID(&IID_IEnumCifComponents, riid))
779 {
780 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv);
781 *ppv = &This->IEnumCifComponents_iface;
782 }
783 */
784 else
785 {
786 FIXME("(%p)->(%s %p) not found\n", This, debugstr_guid(riid), ppv);
787 *ppv = NULL;
788 return E_NOINTERFACE;
789 }
790
791 IUnknown_AddRef((IUnknown *)*ppv);
792 return S_OK;
793 }
794
795 static ULONG WINAPI enum_components_AddRef(IEnumCifComponents *iface)
796 {
797 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface);
798 LONG ref = InterlockedIncrement(&This->ref);
799
800 TRACE("(%p) ref=%d\n", This, ref);
801
802 return ref;
803 }
804
805 static ULONG WINAPI enum_components_Release(IEnumCifComponents *iface)
806 {
807 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface);
808 LONG ref = InterlockedDecrement(&This->ref);
809
810 TRACE("(%p) ref=%d\n", This, ref);
811
812 if(!ref)
813 {
814 ICifFile_Release(This->file);
815 heap_free(This);
816 }
817
818 return ref;
819 }
820
821 static HRESULT WINAPI enum_components_Next(IEnumCifComponents *iface, ICifComponent **component)
822 {
823 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface);
824 struct cifcomponent *comp;
825
826 TRACE("(%p)->(%p)\n", This, component);
827
828 if (!component)
829 return E_FAIL;
830
831 if (!This->position)
832 {
833 *component = NULL;
834 return E_FAIL;
835 }
836
837 do
838 {
839 This->position = list_next(This->start, This->position);
840 if (!This->position)
841 {
842 *component = NULL;
843 return E_FAIL;
844 }
845
846 comp = CONTAINING_RECORD(This->position, struct cifcomponent, entry);
847 } while (This->group_id && (!comp->group || strcmp(This->group_id, comp->group)));
848
849 *component = &comp->ICifComponent_iface;
850 return S_OK;
851 }
852
853 static HRESULT WINAPI enum_components_Reset(IEnumCifComponents *iface)
854 {
855 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface);
856
857 TRACE("(%p)\n", This);
858
859 This->position = This->start;
860 return S_OK;
861 }
862
863 static const IEnumCifComponentsVtbl enum_componentsVtbl =
864 {
865 enum_components_QueryInterface,
866 enum_components_AddRef,
867 enum_components_Release,
868 enum_components_Next,
869 enum_components_Reset,
870 };
871
872 static HRESULT enum_components_create(ICifFile *file, struct list *start, char *group_id, IEnumCifComponents **iface)
873 {
874 struct ciffenum_components *enumerator;
875
876 enumerator = heap_zero_alloc(sizeof(*enumerator));
877 if (!enumerator) return E_OUTOFMEMORY;
878
879 enumerator->IEnumCifComponents_iface.lpVtbl = &enum_componentsVtbl;
880 enumerator->ref = 1;
881 enumerator->file = file;
882 enumerator->start = start;
883 enumerator->position = start;
884 enumerator->group_id = group_id;
885
886 ICifFile_AddRef(file);
887
888 *iface = &enumerator->IEnumCifComponents_iface;
889 return S_OK;
890 }
891
892 static HRESULT WINAPI enum_groups_QueryInterface(IEnumCifGroups *iface, REFIID riid, void **ppv)
893 {
894 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface);
895
896 if (IsEqualGUID(&IID_IUnknown, riid))
897 {
898 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
899 *ppv = &This->IEnumCifGroups_iface;
900 }
901 /*
902 else if (IsEqualGUID(&IID_IEnumCifGroups, riid))
903 {
904 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv);
905 *ppv = &This->IEnumCifGroups_iface;
906 }
907 */
908 else
909 {
910 FIXME("(%p)->(%s %p) not found\n", This, debugstr_guid(riid), ppv);
911 *ppv = NULL;
912 return E_NOINTERFACE;
913 }
914
915 IUnknown_AddRef((IUnknown *)*ppv);
916 return S_OK;
917 }
918
919 static ULONG WINAPI enum_groups_AddRef(IEnumCifGroups *iface)
920 {
921 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface);
922 LONG ref = InterlockedIncrement(&This->ref);
923
924 TRACE("(%p) ref=%d\n", This, ref);
925
926 return ref;
927 }
928
929 static ULONG WINAPI enum_groups_Release(IEnumCifGroups *iface)
930 {
931 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface);
932 LONG ref = InterlockedDecrement(&This->ref);
933
934 TRACE("(%p) ref=%d\n", This, ref);
935
936 if(!ref)
937 {
938 ICifFile_Release(This->file);
939 heap_free(This);
940 }
941
942 return ref;
943 }
944
945 static HRESULT WINAPI enum_groups_Next(IEnumCifGroups *iface, ICifGroup **group)
946 {
947 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface);
948 struct cifgroup *gp;
949
950 TRACE("(%p)->(%p)\n", This, group);
951
952 if (!This->position || !group)
953 return E_FAIL;
954
955 This->position = list_next(This->start, This->position);
956
957 if (!This->position)
958 return E_FAIL;
959
960 gp = CONTAINING_RECORD(This->position, struct cifgroup, entry);
961 *group = &gp->ICifGroup_iface;
962 return S_OK;
963 }
964
965 static HRESULT WINAPI enum_groups_Reset(IEnumCifGroups *iface)
966 {
967 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface);
968
969 TRACE("(%p)\n", This);
970
971 This->position = This->start;
972 return S_OK;
973 }
974
975 static const IEnumCifGroupsVtbl enum_groupsVtbl =
976 {
977 enum_groups_QueryInterface,
978 enum_groups_AddRef,
979 enum_groups_Release,
980 enum_groups_Next,
981 enum_groups_Reset,
982 };
983
984 static HRESULT enum_groups_create(ICifFile *file, struct list *start, IEnumCifGroups **iface)
985 {
986 struct ciffenum_groups *enumerator;
987
988 enumerator = heap_zero_alloc(sizeof(*enumerator));
989 if (!enumerator) return E_OUTOFMEMORY;
990
991 enumerator->IEnumCifGroups_iface.lpVtbl = &enum_groupsVtbl;
992 enumerator->ref = 1;
993 enumerator->file = file;
994 enumerator->start = start;
995 enumerator->position = start;
996
997 ICifFile_AddRef(file);
998
999 *iface = &enumerator->IEnumCifGroups_iface;
1000 return S_OK;
1001 }
1002
1003 static HRESULT WINAPI ciffile_QueryInterface(ICifFile *iface, REFIID riid, void **ppv)
1004 {
1005 struct ciffile *This = impl_from_ICiffile(iface);
1006
1007 if (IsEqualGUID(&IID_IUnknown, riid))
1008 {
1009 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1010 *ppv = &This->ICifFile_iface;
1011 }
1012 else if (IsEqualGUID(&IID_ICifFile, riid))
1013 {
1014 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv);
1015 *ppv = &This->ICifFile_iface;
1016 }
1017 else
1018 {
1019 FIXME("(%p)->(%s %p) not found\n", This, debugstr_guid(riid), ppv);
1020 *ppv = NULL;
1021 return E_NOINTERFACE;
1022 }
1023
1024 IUnknown_AddRef((IUnknown *)*ppv);
1025 return S_OK;
1026 }
1027
1028 static ULONG WINAPI ciffile_AddRef(ICifFile *iface)
1029 {
1030 struct ciffile *This = impl_from_ICiffile(iface);
1031 LONG ref = InterlockedIncrement(&This->ref);
1032
1033 TRACE("(%p) ref=%d\n", This, ref);
1034
1035 return ref;
1036 }
1037
1038 static ULONG WINAPI ciffile_Release(ICifFile *iface)
1039 {
1040 struct ciffile *This = impl_from_ICiffile(iface);
1041 LONG ref = InterlockedDecrement(&This->ref);
1042
1043 TRACE("(%p) ref=%d\n", This, ref);
1044
1045 if(!ref)
1046 {
1047 struct cifcomponent *comp, *comp_next;
1048 struct cifgroup *group, *group_next;
1049
1050 heap_free(This->name);
1051
1052 LIST_FOR_EACH_ENTRY_SAFE(comp, comp_next, &This->components, struct cifcomponent, entry)
1053 {
1054 list_remove(&comp->entry);
1055 component_free(comp);
1056 }
1057
1058 LIST_FOR_EACH_ENTRY_SAFE(group, group_next, &This->groups, struct cifgroup, entry)
1059 {
1060 list_remove(&group->entry);
1061 group_free(group);
1062 }
1063
1064 heap_free(This);
1065 }
1066
1067 return ref;
1068 }
1069
1070 static HRESULT WINAPI ciffile_EnumComponents(ICifFile *iface, IEnumCifComponents **enum_components, DWORD filter, void *pv)
1071 {
1072 struct ciffile *This = impl_from_ICiffile(iface);
1073
1074 TRACE("(%p)->(%p, %u, %p)\n", This, enum_components, filter, pv);
1075
1076 if (filter)
1077 FIXME("filter (%x) not supported\n", filter);
1078 if (pv)
1079 FIXME("how to handle pv (%p)?\n", pv);
1080
1081 return enum_components_create(iface, &This->components, NULL, enum_components);
1082 }
1083
1084 static HRESULT WINAPI ciffile_FindComponent(ICifFile *iface, const char *id, ICifComponent **component)
1085 {
1086 struct ciffile *This = impl_from_ICiffile(iface);
1087 struct cifcomponent *comp;
1088
1089 TRACE("(%p)->(%s, %p)\n", This, debugstr_a(id), component);
1090
1091 LIST_FOR_EACH_ENTRY(comp, &This->components, struct cifcomponent, entry)
1092 {
1093 if (strcmp(comp->id, id) != 0)
1094 continue;
1095
1096 *component = &comp->ICifComponent_iface;
1097 return S_OK;
1098 }
1099
1100 return E_FAIL;
1101 }
1102
1103 static HRESULT WINAPI ciffile_EnumGroups(ICifFile *iface, IEnumCifGroups **enum_groups, DWORD filter, void *pv)
1104 {
1105 struct ciffile *This = impl_from_ICiffile(iface);
1106
1107 TRACE("(%p)->(%p, %u, %p)\n", This, enum_groups, filter, pv);
1108
1109 if (filter)
1110 FIXME("filter (%x) not supported\n", filter);
1111 if (pv)
1112 FIXME("how to handle pv (%p)?\n", pv);
1113
1114 return enum_groups_create(iface, &This->groups, enum_groups);
1115 }
1116
1117 static HRESULT WINAPI ciffile_FindGroup(ICifFile *iface, const char *id, ICifGroup **group)
1118 {
1119 struct ciffile *This = impl_from_ICiffile(iface);
1120 struct cifgroup *gp;
1121
1122 TRACE("(%p)->(%s, %p)\n", This, debugstr_a(id), group);
1123
1124 LIST_FOR_EACH_ENTRY(gp, &This->groups, struct cifgroup, entry)
1125 {
1126 if (strcmp(gp->id, id) != 0)
1127 continue;
1128
1129 *group = &gp->ICifGroup_iface;
1130 return S_OK;
1131 }
1132
1133 return E_FAIL;
1134 }
1135
1136 static HRESULT WINAPI ciffile_EnumModes(ICifFile *iface, IEnumCifModes **cuf_modes, DWORD filter, void *pv)
1137 {
1138 struct ciffile *This = impl_from_ICiffile(iface);
1139
1140 FIXME("(%p)->(%p, %u, %p): stub\n", This, cuf_modes, filter, pv);
1141
1142 return E_NOTIMPL;
1143 }
1144
1145 static HRESULT WINAPI ciffile_FindMode(ICifFile *iface, const char *id, ICifMode **mode)
1146 {
1147 struct ciffile *This = impl_from_ICiffile(iface);
1148
1149 FIXME("(%p)->(%s, %p): stub\n", This, debugstr_a(id), mode);
1150
1151 return E_NOTIMPL;
1152 }
1153
1154 static HRESULT WINAPI ciffile_GetDescription(ICifFile *iface, char *desc, DWORD size)
1155 {
1156 struct ciffile *This = impl_from_ICiffile(iface);
1157
1158 TRACE("(%p)->(%p, %u)\n", This, desc, size);
1159
1160 return copy_substring_null(desc, size, This->name);
1161 }
1162
1163 static HRESULT WINAPI ciffile_GetDetDlls(ICifFile *iface, char *dlls, DWORD size)
1164 {
1165 struct ciffile *This = impl_from_ICiffile(iface);
1166
1167 FIXME("(%p)->(%p, %u): stub\n", This, dlls, size);
1168
1169 return E_NOTIMPL;
1170 }
1171
1172 static const ICifFileVtbl ciffileVtbl =
1173 {
1174 ciffile_QueryInterface,
1175 ciffile_AddRef,
1176 ciffile_Release,
1177 ciffile_EnumComponents,
1178 ciffile_FindComponent,
1179 ciffile_EnumGroups,
1180 ciffile_FindGroup,
1181 ciffile_EnumModes,
1182 ciffile_FindMode,
1183 ciffile_GetDescription,
1184 ciffile_GetDetDlls,
1185 };
1186
1187 static BOOL copy_string(char **dest, const char *source)
1188 {
1189 if (!source)
1190 {
1191 *dest = NULL;
1192 return TRUE;
1193 }
1194
1195 *dest = strdupA(source);
1196 if (!dest) return FALSE;
1197 return TRUE;
1198 }
1199
1200 static BOOL section_get_str(struct inf_section *inf_sec, const char *key, char **value, const char *def)
1201 {
1202 struct inf_value *inf_val;
1203
1204 inf_val = inf_get_value(inf_sec, key);
1205 if (!inf_val) return copy_string(value, def);
1206
1207 *value = inf_value_get_value(inf_val);
1208 if (!*value) return FALSE;
1209
1210 return TRUE;
1211 }
1212
1213 static char *next_part(char **str, BOOL strip_quotes)
1214 {
1215 char *start = *str;
1216 char *next = *str;
1217
1218 while (*next && *next != ',')
1219 next++;
1220
1221 if (!*next)
1222 {
1223 *str = trim(start, NULL, strip_quotes);
1224 return NULL;
1225 }
1226
1227 *next = 0;
1228 *str = trim(start, NULL, strip_quotes);
1229 return ++next;
1230 }
1231
1232 static BOOL value_get_str_field(struct inf_value *inf_val, int field, char **value, const char *def)
1233 {
1234 char *line, *str, *next;
1235 int i = 0;
1236
1237 line = inf_value_get_value(inf_val);
1238 if (!line) return FALSE;
1239
1240 str = line;
1241 do
1242 {
1243 i++;
1244 next = next_part(&str, TRUE);
1245
1246 if (field == i)
1247 {
1248 BOOL ret = copy_string(value, str);
1249 heap_free(line);
1250 return ret;
1251 }
1252
1253 str = next;
1254 } while (str);
1255
1256 return copy_string(value, def);
1257 }
1258
1259 /*
1260 static BOOL section_get_str_field(struct inf_section *inf_sec, const char *key, int field, char **value, const char *def)
1261 {
1262 struct inf_value *inf_val;
1263
1264 inf_val = inf_get_value(inf_sec, key);
1265 if (!inf_val) return copy_string(value, def);
1266
1267 return value_get_str_field(inf_val, field, value, def);
1268 }
1269 */
1270
1271 static BOOL section_get_dword(struct inf_section *inf_sec, const char *key, DWORD *value, DWORD def)
1272 {
1273 struct inf_value *inf_val;
1274 char *str;
1275
1276 inf_val = inf_get_value(inf_sec, key);
1277 if (!inf_val)
1278 {
1279 *value = def;
1280 return TRUE;
1281 }
1282
1283 str = inf_value_get_value(inf_val);
1284 if (!str) return FALSE;
1285
1286 *value = atoi(str);
1287 heap_free(str);
1288
1289 return TRUE;
1290 }
1291
1292 static BOOL value_get_dword_field(struct inf_value *inf_val, int field, DWORD *value, DWORD def)
1293 {
1294 char *value_str;
1295 BOOL ret;
1296
1297 ret = value_get_str_field(inf_val, field, &value_str, NULL);
1298 if (!ret) return FALSE;
1299 if (!value_str)
1300 {
1301 *value = def;
1302 return TRUE;
1303 }
1304
1305 *value = atoi(value_str);
1306 heap_free(value_str);
1307
1308 return TRUE;
1309 }
1310
1311 static BOOL section_get_dword_field(struct inf_section *inf_sec, const char *key, int field, DWORD *value, DWORD def)
1312 {
1313 struct inf_value *inf_val;
1314
1315 inf_val = inf_get_value(inf_sec, key);
1316 if (!inf_val)
1317 {
1318 *value = def;
1319 return TRUE;
1320 }
1321
1322 return value_get_dword_field(inf_val, field, value, def);
1323 }
1324
1325 static HRESULT process_version(struct ciffile *file, struct inf_section *section)
1326 {
1327 if (!section_get_str(section, "DisplayName", &file->name, DEFAULT_INSTALLER_DESC))
1328 return E_OUTOFMEMORY;
1329
1330 return S_OK;
1331 }
1332
1333 static BOOL read_version_entry(struct inf_section *section, DWORD *ret_ver, DWORD *ret_build)
1334 {
1335 DWORD version = 0;
1336 DWORD build = 0;
1337 char *line, *str, *next;
1338
1339 if (!section_get_str(section, "Version", &line, NULL))
1340 return FALSE;
1341 if (!line) goto done;
1342
1343 str = line;
1344
1345 next = next_part(&str, TRUE);
1346 version |= atoi(str) << 16;
1347 if (!next) goto done;
1348 str = next;
1349
1350 next = next_part(&str, TRUE);
1351 version |= atoi(str) & 0xffff;
1352 if (!next) goto done;
1353 str = next;
1354
1355 next = next_part(&str, TRUE);
1356 build |= atoi(str) << 16;
1357 if (!next) goto done;
1358 str = next;
1359
1360 next_part(&str, TRUE);
1361 build |= atoi(str) & 0xffff;
1362
1363 done:
1364 heap_free(line);
1365 *ret_ver = version;
1366 *ret_build = build;
1367 return TRUE;
1368 }
1369
1370 static BOOL read_platform_entry(struct inf_section *section, DWORD *ret_platform)
1371 {
1372 DWORD platform = PLATFORM_ALL;
1373 char *line, *str, *next;
1374
1375 if (!section_get_str(section, "Platform", &line, NULL))
1376 return FALSE;
1377 if (!line) goto done;
1378
1379 platform = 0;
1380 str = line;
1381 do
1382 {
1383 next = next_part(&str, TRUE);
1384
1385 if (strcasecmp(str, "Win95") == 0)
1386 platform |= PLATFORM_WIN98;
1387 else if (strcasecmp(str, "Win98") == 0)
1388 platform |= PLATFORM_WIN98;
1389 else if (strcasecmp(str, "NT4") == 0)
1390 platform |= PLATFORM_NT4;
1391 else if (strcasecmp(str, "NT5") == 0)
1392 platform |= PLATFORM_NT5;
1393 else if (strcasecmp(str, "NT4Alpha") == 0)
1394 platform |= PLATFORM_NT4;
1395 else if (strcasecmp(str, "NT5Alpha") == 0)
1396 platform |= PLATFORM_NT5;
1397 else if (strcasecmp(str, "Millen") == 0)
1398 platform |= PLATFORM_MILLEN;
1399 else
1400 FIXME("Unknown platform: %s\n", debugstr_a(str));
1401
1402 str = next;
1403 } while (str);
1404
1405 done:
1406 heap_free(line);
1407 *ret_platform = platform;
1408 return TRUE;
1409 }
1410
1411 static BOOL read_dependencies(struct cifcomponent *component, struct inf_section *section)
1412 {
1413 struct dependency_info *dependency;
1414 char *line, *str, *next;
1415 BOOL ret = TRUE;
1416
1417 if (!section_get_str(section, "Dependencies", &line, NULL))
1418 return E_OUTOFMEMORY;
1419 if (!line) goto done;
1420
1421 ret = FALSE;
1422 str = line;
1423 do
1424 {
1425 next = next_part(&str, TRUE);
1426
1427 dependency = heap_zero_alloc(sizeof(*dependency));
1428 if (!dependency) goto done;
1429
1430 dependency->id = strdupA(str);
1431 if (!dependency->id)
1432 {
1433 heap_free(dependency);
1434 goto done;
1435 }
1436
1437 dependency->type = strstr(dependency->id, ":");
1438 if (dependency->type) *dependency->type++ = 0;
1439
1440 list_add_tail(&component->dependencies, &dependency->entry);
1441
1442 str = next;
1443 } while (str);
1444
1445 ret = TRUE;
1446
1447 done:
1448 heap_free(line);
1449 return ret;
1450 }
1451
1452 static BOOL read_urls(struct cifcomponent *component, struct inf_section *section)
1453 {
1454 struct inf_value *inf_value = NULL;
1455 struct url_info *url_entry;
1456 char *str, *next;
1457 int index;
1458
1459 while (inf_section_next_value(section, &inf_value))
1460 {
1461 str = inf_value_get_key(inf_value);
1462 if (!str) return E_OUTOFMEMORY;
1463
1464 if (strncasecmp(str, "URL", 3))
1465 goto next;
1466
1467 if (!str[3])
1468 goto next;
1469
1470 index = strtol(str+3, &next, 10);
1471 if (next == str+3 || *next != 0 || index < 1)
1472 goto next;
1473 index--;
1474
1475 url_entry = heap_zero_alloc(sizeof(*url_entry));
1476 if (!url_entry) goto error;
1477
1478 url_entry->index = index;
1479
1480 if (!value_get_str_field(inf_value, 1, &url_entry->url, NULL))
1481 goto error;
1482 if (!url_entry->url || !*url_entry->url)
1483 {
1484 url_entry_free(url_entry);
1485 goto next;
1486 }
1487
1488 if (!value_get_dword_field(inf_value, 2, &url_entry->flags, 0))
1489 goto error;
1490
1491 list_add_tail(&component->urls, &url_entry->entry);
1492
1493 next:
1494 heap_free(str);
1495 }
1496
1497 return TRUE;
1498
1499 error:
1500 heap_free(str);
1501 url_entry_free(url_entry);
1502 return FALSE;
1503 };
1504
1505 void add_component_by_priority(struct ciffile *file, struct cifcomponent *component)
1506 {
1507 struct cifcomponent *entry;
1508
1509 LIST_FOR_EACH_ENTRY(entry, &file->components, struct cifcomponent, entry)
1510 {
1511 if (entry->priority > component->priority)
1512 continue;
1513
1514 list_add_before(&entry->entry, &component->entry);
1515 return;
1516 }
1517
1518 list_add_tail(&file->components, &component->entry);
1519 }
1520
1521 static HRESULT process_component(struct ciffile *file, struct inf_section *section, const char *section_name)
1522 {
1523 struct cifcomponent *component;
1524 HRESULT hr = E_OUTOFMEMORY;
1525
1526 component = heap_zero_alloc(sizeof(*component));
1527 if (!component) return E_OUTOFMEMORY;
1528
1529 component->ICifComponent_iface.lpVtbl = &cifcomponentVtbl;
1530 component->parent = &file->ICifFile_iface;
1531
1532 list_init(&component->urls);
1533 list_init(&component->dependencies);
1534
1535 component->queue_state = ActionNone;
1536
1537 component->id = strdupA(section_name);
1538 if (!component->id) goto error;
1539
1540 if (!section_get_str(section, "DisplayName", &component->description, NULL))
1541 goto error;
1542 if (!section_get_str(section, "GUID", &component->guid, NULL))
1543 goto error;
1544 if (!section_get_str(section, "Details", &component->details, NULL))
1545 goto error;
1546 if (!section_get_str(section, "Group", &component->group, NULL))
1547 goto error;
1548 if (!section_get_str(section, "Locale", &component->locale, "en"))
1549 goto error;
1550 if (!section_get_str(section, "PatchID", &component->patchid, NULL))
1551 goto error;
1552
1553 if (!section_get_dword_field(section, "Size", 1, &component->size_download, 0))
1554 goto error;
1555 if (!section_get_dword_field(section, "Size", 2, &component->size_extracted, 0))
1556 goto error;
1557 if (!section_get_dword_field(section, "InstalledSize", 1, &component->size_app, 0))
1558 goto error;
1559 if (!section_get_dword_field(section, "InstalledSize", 2, &component->size_win, 0))
1560 goto error;
1561
1562 if (!section_get_str(section, "SuccessKey", &component->key_success, NULL))
1563 goto error;
1564 if (!section_get_str(section, "CancelKey", &component->key_cancel, NULL))
1565 goto error;
1566 if (!section_get_str(section, "ProgressKey", &component->key_progress, NULL))
1567 goto error;
1568 if (!section_get_str(section, "UninstallKey", &component->key_uninstall, NULL))
1569 goto error;
1570 if (!section_get_dword(section, "Reboot", &component->reboot, 0))
1571 goto error;
1572 if (!section_get_dword(section, "AdminCheck", &component->admin, 0))
1573 goto error;
1574 if (!section_get_dword(section, "UIVisible", &component->visibleui, 1))
1575 goto error;
1576 if (!section_get_dword(section, "ActiveSetupAware", &component->as_aware, 0))
1577 goto error;
1578 if (!section_get_dword(section, "Priority", &component->priority, 0))
1579 goto error;
1580
1581 if (!read_version_entry(section, &component->version, &component->build))
1582 goto error;
1583 if (!read_platform_entry(section, &component->platform))
1584 goto error;
1585 if (!read_urls(component, section))
1586 goto error;
1587 if (!read_dependencies(component, section))
1588 goto error;
1589
1590 component->current_priority = component->priority;
1591
1592 add_component_by_priority(file, component);
1593 return S_OK;
1594
1595 error:
1596 component_free(component);
1597 return hr;
1598 }
1599
1600 static HRESULT process_group(struct ciffile *file, struct inf_section *section, const char *section_name)
1601 {
1602 struct cifgroup *group;
1603 HRESULT hr = E_OUTOFMEMORY;
1604
1605 group = heap_zero_alloc(sizeof(*group));
1606 if (!group) return E_OUTOFMEMORY;
1607
1608 group->ICifGroup_iface.lpVtbl = &cifgroupVtbl;
1609 group->parent = &file->ICifFile_iface;
1610
1611 group->id = strdupA(section_name);
1612 if (!group->id) goto error;
1613
1614 if (!section_get_str(section, "DisplayName", &group->description, NULL))
1615 goto error;
1616 if (!section_get_dword(section, "Priority", &group->priority, 0))
1617 goto error;
1618
1619 list_add_head(&file->groups, &group->entry);
1620 return S_OK;
1621
1622 error:
1623 group_free(group);
1624 return hr;
1625 }
1626
1627 static HRESULT process_section(struct ciffile *file, struct inf_section *section, const char *section_name)
1628 {
1629 HRESULT hr;
1630 char *type;
1631
1632 if (!section_get_str(section, "SectionType", &type, "Component"))
1633 return E_OUTOFMEMORY;
1634
1635 if (!strcasecmp(type, "Component"))
1636 hr = process_component(file, section, section_name);
1637 else if (strcasecmp(type, "Group") == 0)
1638 hr = process_group(file, section, section_name);
1639 else
1640 FIXME("Don't know how to process %s\n", debugstr_a(type));
1641
1642 heap_free(type);
1643 return hr;
1644 }
1645
1646 static HRESULT process_inf(struct ciffile *file, struct inf_file *inf)
1647 {
1648 struct inf_section *section = NULL;
1649 char *section_name;
1650 HRESULT hr = S_OK;
1651
1652 while (SUCCEEDED(hr) && inf_next_section(inf, &section))
1653 {
1654 section_name = inf_section_get_name(section);
1655 if (!section_name) return E_OUTOFMEMORY;
1656
1657 TRACE("start processing section %s\n", debugstr_a(section_name));
1658
1659 if (!strcasecmp(section_name, "Strings") ||
1660 !strncasecmp(section_name, "Strings.", strlen("Strings.")))
1661 {
1662 /* Ignore string sections */
1663 }
1664 else if (strcasecmp(section_name, "Version") == 0)
1665 hr = process_version(file, section);
1666 else
1667 hr = process_section(file, section, section_name);
1668
1669 TRACE("finished processing section %s (%x)\n", debugstr_a(section_name), hr);
1670 heap_free(section_name);
1671 }
1672
1673 /* In case there was no version section, set the default installer description */
1674 if (SUCCEEDED(hr) && !file->name)
1675 {
1676 file->name = strdupA(DEFAULT_INSTALLER_DESC);
1677 if (!file->name) hr = E_OUTOFMEMORY;
1678 }
1679
1680 return hr;
1681 }
1682
1683 static HRESULT load_ciffile(const char *path, ICifFile **icif)
1684 {
1685 struct inf_file *inf = NULL;
1686 struct ciffile *file;
1687 HRESULT hr = E_FAIL;
1688
1689 file = heap_zero_alloc(sizeof(*file));
1690 if(!file) return E_OUTOFMEMORY;
1691
1692 file->ICifFile_iface.lpVtbl = &ciffileVtbl;
1693 file->ref = 1;
1694
1695 list_init(&file->components);
1696 list_init(&file->groups);
1697
1698 hr = inf_load(path, &inf);
1699 if (FAILED(hr)) goto error;
1700
1701 hr = process_inf(file, inf);
1702 if (FAILED(hr)) goto error;
1703
1704 *icif = &file->ICifFile_iface;
1705 return S_OK;
1706
1707 error:
1708 if (inf) inf_free(inf);
1709 ICifFile_Release(&file->ICifFile_iface);
1710 return hr;
1711 }
1712
1713 HRESULT WINAPI GetICifFileFromFile(ICifFile **icif, const char *path)
1714 {
1715 TRACE("(%p, %s)\n", icif, debugstr_a(path));
1716
1717 return load_ciffile(path, icif);
1718 }
1719
1720
1721 HRESULT WINAPI GetICifRWFileFromFile(ICifRWFile **icif, const char *path)
1722 {
1723 FIXME("(%p, %s): stub\n", icif, debugstr_a(path));
1724
1725 return E_NOTIMPL;
1726 }