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