2 * Copyright 2016 Michael Müller
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.
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.
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
33 #include "inseng_private.h"
35 #include "wine/list.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(inseng
);
40 #define DEFAULT_INSTALLER_DESC "Active Setup Installation"
44 ICifGroup ICifGroup_iface
;
55 struct ciffenum_components
57 IEnumCifComponents IEnumCifComponents_iface
;
62 struct list
*position
;
67 struct ciffenum_groups
69 IEnumCifGroups IEnumCifGroups_iface
;
74 struct list
*position
;
85 struct dependency_info
94 ICifComponent ICifComponent_iface
;
117 DWORD size_extracted
;
131 struct list dependencies
;
139 /* in memory state */
141 DWORD current_priority
;
142 DWORD size_actual_download
;
149 ICifFile ICifFile_iface
;
152 struct list components
;
158 static inline struct ciffile
*impl_from_ICiffile(ICifFile
*iface
)
160 return CONTAINING_RECORD(iface
, struct ciffile
, ICifFile_iface
);
163 static inline struct cifcomponent
*impl_from_ICifComponent(ICifComponent
*iface
)
165 return CONTAINING_RECORD(iface
, struct cifcomponent
, ICifComponent_iface
);
168 static inline struct cifgroup
*impl_from_ICifGroup(ICifGroup
*iface
)
170 return CONTAINING_RECORD(iface
, struct cifgroup
, ICifGroup_iface
);
173 static inline struct ciffenum_components
*impl_from_IEnumCifComponents(IEnumCifComponents
*iface
)
175 return CONTAINING_RECORD(iface
, struct ciffenum_components
, IEnumCifComponents_iface
);
178 static inline struct ciffenum_groups
*impl_from_IEnumCifGroups(IEnumCifGroups
*iface
)
180 return CONTAINING_RECORD(iface
, struct ciffenum_groups
, IEnumCifGroups_iface
);
183 static HRESULT
enum_components_create(ICifFile
*file
, struct list
*start
, char *group_id
, IEnumCifComponents
**iface
);
185 static HRESULT
copy_substring_null(char *dest
, int max_len
, char *src
)
196 while (*src
&& max_len
-- > 1)
203 static void url_entry_free(struct url_info
*url
)
209 static void dependency_entry_free(struct dependency_info
*dependency
)
211 heap_free(dependency
->id
);
212 heap_free(dependency
);
215 static void component_free(struct cifcomponent
*comp
)
217 struct dependency_info
*dependency
, *dependency_next
;
218 struct url_info
*url
, *url_next
;
221 heap_free(comp
->guid
);
222 heap_free(comp
->description
);
223 heap_free(comp
->details
);
224 heap_free(comp
->group
);
226 heap_free(comp
->patchid
);
228 heap_free(comp
->locale
);
229 heap_free(comp
->key_uninstall
);
231 heap_free(comp
->key_success
);
232 heap_free(comp
->key_progress
);
233 heap_free(comp
->key_cancel
);
235 LIST_FOR_EACH_ENTRY_SAFE(dependency
, dependency_next
, &comp
->dependencies
, struct dependency_info
, entry
)
237 list_remove(&dependency
->entry
);
238 dependency_entry_free(dependency
);
241 LIST_FOR_EACH_ENTRY_SAFE(url
, url_next
, &comp
->urls
, struct url_info
, entry
)
243 list_remove(&url
->entry
);
250 static void group_free(struct cifgroup
*group
)
252 heap_free(group
->id
);
253 heap_free(group
->description
);
257 static HRESULT WINAPI
group_GetID(ICifGroup
*iface
, char *id
, DWORD size
)
259 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
261 TRACE("(%p)->(%p, %u)\n", This
, id
, size
);
263 return copy_substring_null(id
, size
, This
->id
);
266 static HRESULT WINAPI
group_GetDescription(ICifGroup
*iface
, char *desc
, DWORD size
)
268 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
270 TRACE("(%p)->(%p, %u)\n", This
, desc
, size
);
272 return copy_substring_null(desc
, size
, This
->description
);
275 static DWORD WINAPI
group_GetPriority(ICifGroup
*iface
)
277 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
279 TRACE("(%p)\n", This
);
281 return This
->priority
;
284 static HRESULT WINAPI
group_EnumComponents(ICifGroup
*iface
, IEnumCifComponents
**enum_components
, DWORD filter
, LPVOID pv
)
286 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
287 struct ciffile
*file
;
289 TRACE("(%p)->(%p, %u, %p)\n", This
, enum_components
, filter
, pv
);
292 FIXME("filter (%x) not supported\n", filter
);
294 FIXME("how to handle pv (%p)?\n", pv
);
296 file
= impl_from_ICiffile(This
->parent
);
297 return enum_components_create(This
->parent
, &file
->components
, This
->id
, enum_components
);
300 static DWORD WINAPI
group_GetCurrentPriority(ICifGroup
*iface
)
302 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
304 FIXME("(%p): stub\n", This
);
309 static const ICifGroupVtbl cifgroupVtbl
=
312 group_GetDescription
,
314 group_EnumComponents
,
315 group_GetCurrentPriority
,
318 void component_set_actual_download_size(ICifComponent
*iface
, DWORD size
)
320 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
322 This
->size_actual_download
= size
;
325 void component_set_downloaded(ICifComponent
*iface
, BOOL value
)
327 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
329 This
->downloaded
= value
;
332 void component_set_installed(ICifComponent
*iface
, BOOL value
)
334 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
336 This
->installed
= value
;
339 char *component_get_id(ICifComponent
*iface
)
341 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
346 static HRESULT WINAPI
component_GetID(ICifComponent
*iface
, char *id
, DWORD size
)
348 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
350 TRACE("(%p)->(%p, %u)\n", This
, id
, size
);
352 return copy_substring_null(id
, size
, This
->id
);
355 static HRESULT WINAPI
component_GetGUID(ICifComponent
*iface
, char *guid
, DWORD size
)
357 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
359 TRACE("(%p)->(%p, %u)\n", This
, guid
, size
);
361 return copy_substring_null(guid
, size
, This
->guid
);
364 static HRESULT WINAPI
component_GetDescription(ICifComponent
*iface
, char *desc
, DWORD size
)
366 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
368 TRACE("(%p)->(%p, %u)\n", This
, desc
, size
);
370 return copy_substring_null(desc
, size
, This
->description
);
373 static HRESULT WINAPI
component_GetDetails(ICifComponent
*iface
, char *details
, DWORD size
)
375 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
377 TRACE("(%p)->(%p, %u)\n", This
, details
, size
);
379 return copy_substring_null(details
, size
, This
->details
);
382 static HRESULT WINAPI
component_GetUrl(ICifComponent
*iface
, UINT index
, char *url
, DWORD size
, DWORD
*flags
)
384 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
385 struct url_info
*entry
;
387 TRACE("(%p)->(%u, %p, %u, %p)\n", This
, index
, url
, size
, flags
);
389 /* FIXME: check how functions behaves for url == NULL */
394 LIST_FOR_EACH_ENTRY(entry
, &This
->urls
, struct url_info
, entry
)
396 if (entry
->index
!= index
)
399 *flags
= entry
->flags
;
400 return copy_substring_null(url
, size
, entry
->url
);
406 static HRESULT WINAPI
component_GetFileExtractList(ICifComponent
*iface
, UINT index
, char *list
, DWORD size
)
408 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
410 FIXME("(%p)->(%u, %p, %u): stub\n", This
, index
, list
, size
);
415 static HRESULT WINAPI
component_GetUrlCheckRange(ICifComponent
*iface
, UINT index
, DWORD
*min
, DWORD
*max
)
417 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
419 FIXME("(%p)->(%u, %p, %p): stub\n", This
, index
, min
, max
);
424 static HRESULT WINAPI
component_GetCommand(ICifComponent
*iface
, UINT index
, char *cmd
, DWORD cmd_size
, char *switches
, DWORD switch_size
, DWORD
*type
)
426 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
428 FIXME("(%p)->(%u, %p, %u, %p, %u, %p): stub\n", This
, index
, cmd
, cmd_size
, switches
, switch_size
, type
);
433 static HRESULT WINAPI
component_GetVersion(ICifComponent
*iface
, DWORD
*version
, DWORD
*build
)
435 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
437 TRACE("(%p)->(%p, %p)\n", This
, version
, build
);
439 if (!version
|| !build
)
442 *version
= This
->version
;
443 *build
= This
->build
;
448 static HRESULT WINAPI
component_GetLocale(ICifComponent
*iface
, char *locale
, DWORD size
)
450 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
452 TRACE("(%p)->(%p, %u)\n", This
, locale
, size
);
454 return copy_substring_null(locale
, size
, This
->locale
);
457 static HRESULT WINAPI
component_GetUninstallKey(ICifComponent
*iface
, char *key
, DWORD size
)
459 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
461 TRACE("(%p)->(%p, %u)\n", This
, key
, size
);
463 return copy_substring_null(key
, size
, This
->key_uninstall
);
466 static HRESULT WINAPI
component_GetInstalledSize(ICifComponent
*iface
, DWORD
*win
, DWORD
*app
)
468 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
470 TRACE("(%p)->(%p, %p)\n", This
, win
, app
);
475 *win
= This
->size_win
;
476 *app
= This
->size_app
;
481 static DWORD WINAPI
component_GetDownloadSize(ICifComponent
*iface
)
483 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
485 TRACE("(%p)\n", This
);
487 return This
->size_download
;
490 static DWORD WINAPI
component_GetExtractSize(ICifComponent
*iface
)
492 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
494 TRACE("(%p)\n", This
);
496 return This
->size_extracted
;
499 static HRESULT WINAPI
component_GetSuccessKey(ICifComponent
*iface
, char *key
, DWORD size
)
501 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
503 TRACE("(%p)->(%p, %u)\n", This
, key
, size
);
505 return copy_substring_null(key
, size
, This
->key_success
);
508 static HRESULT WINAPI
component_GetProgressKeys(ICifComponent
*iface
, char *progress
, DWORD progress_size
,
509 char *cancel
, DWORD cancel_size
)
511 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
514 TRACE("(%p)->(%p, %u, %p, %u): semi-stub\n", This
, progress
, progress_size
, cancel
, cancel_size
);
516 hr
= copy_substring_null(progress
, progress_size
, This
->key_progress
);
517 if (hr
!= S_OK
) return hr
;
519 if (cancel_size
> 0 && cancel
)
525 static HRESULT WINAPI
component_IsActiveSetupAware(ICifComponent
*iface
)
527 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
529 TRACE("(%p)\n", This
);
531 return This
->as_aware
? S_OK
: S_FALSE
;
534 static HRESULT WINAPI
component_IsRebootRequired(ICifComponent
*iface
)
536 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
538 TRACE("(%p)\n", This
);
540 return This
->reboot
? S_OK
: S_FALSE
;
543 static HRESULT WINAPI
component_RequiresAdminRights(ICifComponent
*iface
)
545 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
547 TRACE("(%p)\n", This
);
549 return This
->admin
? S_OK
: S_FALSE
;
552 static DWORD WINAPI
component_GetPriority(ICifComponent
*iface
)
554 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
556 TRACE("(%p)\n", This
);
558 return This
->priority
;
561 static HRESULT WINAPI
component_GetDependency(ICifComponent
*iface
, UINT index
, char *id
, DWORD id_size
, char *type
, DWORD
*ver
, DWORD
*build
)
563 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
564 struct dependency_info
*entry
;
565 ICifComponent
*dependency
;
568 TRACE("(%p)->(%u, %p, %u, %p, %p, %p)\n", This
, index
, id
, id_size
, type
, ver
, build
);
570 if (!id
|| !ver
|| !build
)
573 LIST_FOR_EACH_ENTRY(entry
, &This
->dependencies
, struct dependency_info
, entry
)
578 if (ICifFile_FindComponent(This
->parent
, entry
->id
, &dependency
) == S_OK
)
580 ICifComponent_GetVersion(dependency
, ver
, build
);
589 *type
= *entry
->type
;
593 return copy_substring_null(id
, id_size
, entry
->id
);
599 static DWORD WINAPI
component_GetPlatform(ICifComponent
*iface
)
601 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
603 TRACE("(%p)\n", This
);
605 return This
->platform
;
608 static HRESULT WINAPI
component_GetMode(ICifComponent
*iface
, UINT index
, char *mode
, DWORD size
)
610 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
612 FIXME("(%p)->(%u, %p, %u): stub\n", This
, index
, mode
, size
);
617 static HRESULT WINAPI
component_GetGroup(ICifComponent
*iface
, char *id
, DWORD size
)
619 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
621 TRACE("(%p)->(%p, %u)\n", This
, id
, size
);
623 return copy_substring_null(id
, size
, This
->group
);
626 static HRESULT WINAPI
component_IsUIVisible(ICifComponent
*iface
)
628 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
630 TRACE("(%p)\n", This
);
632 return This
->visibleui
? S_OK
: S_FALSE
;
635 static HRESULT WINAPI
component_GetPatchID(ICifComponent
*iface
, char *id
, DWORD size
)
637 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
639 TRACE("(%p)->(%p, %u)\n", This
, id
, size
);
641 return copy_substring_null(id
, size
, This
->patchid
);
644 static HRESULT WINAPI
component_GetDetVersion(ICifComponent
*iface
, char *dll
, DWORD dll_size
, char *entry
, DWORD entry_size
)
646 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
648 FIXME("(%p)->(%p, %u, %p, %u): stub\n", This
, dll
, dll_size
, entry
, entry_size
);
653 static HRESULT WINAPI
component_GetTreatAsOneComponents(ICifComponent
*iface
, UINT index
, char *id
, DWORD size
)
655 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
657 FIXME("(%p)->(%u, %p, %u): stub\n", This
, index
, id
, size
);
662 static HRESULT WINAPI
component_GetCustomData(ICifComponent
*iface
, char *key
, char *data
, DWORD size
)
664 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
666 FIXME("(%p)->(%s, %p, %u): stub\n", This
, debugstr_a(key
), data
, size
);
671 static DWORD WINAPI
component_IsComponentInstalled(ICifComponent
*iface
)
673 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
675 TRACE("(%p)\n", This
);
677 return This
->installed
;
680 static HRESULT WINAPI
component_IsComponentDownloaded(ICifComponent
*iface
)
682 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
684 TRACE("(%p)\n", This
);
686 return This
->downloaded
? S_OK
: S_FALSE
;
689 static DWORD WINAPI
component_IsThisVersionInstalled(ICifComponent
*iface
, DWORD version
, DWORD build
, DWORD
*ret_version
, DWORD
*ret_build
)
691 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
693 FIXME("(%p)->(%u, %u, %p, %p): stub\n", This
, version
, build
, ret_version
, ret_build
);
698 static DWORD WINAPI
component_GetInstallQueueState(ICifComponent
*iface
)
700 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
702 TRACE("(%p)\n", This
);
704 return This
->queue_state
;
707 static HRESULT WINAPI
component_SetInstallQueueState(ICifComponent
*iface
, DWORD state
)
709 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
711 TRACE("(%p)->(%u)\n", This
, state
);
713 This
->queue_state
= state
;
717 static DWORD WINAPI
component_GetActualDownloadSize(ICifComponent
*iface
)
719 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
721 TRACE("(%p)\n", This
);
723 return This
->size_download
;
726 static DWORD WINAPI
component_GetCurrentPriority(ICifComponent
*iface
)
728 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
730 TRACE("(%p)\n", This
);
732 return This
->current_priority
;
736 static HRESULT WINAPI
component_SetCurrentPriority(ICifComponent
*iface
, DWORD priority
)
738 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
740 TRACE("(%p)->(%u)\n", This
, priority
);
742 This
->current_priority
= priority
;
746 static const ICifComponentVtbl cifcomponentVtbl
=
750 component_GetDescription
,
751 component_GetDetails
,
753 component_GetFileExtractList
,
754 component_GetUrlCheckRange
,
755 component_GetCommand
,
756 component_GetVersion
,
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
,
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
,
787 static HRESULT WINAPI
enum_components_QueryInterface(IEnumCifComponents
*iface
, REFIID riid
, void **ppv
)
789 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
791 if (IsEqualGUID(&IID_IUnknown
, riid
))
793 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
794 *ppv
= &This
->IEnumCifComponents_iface
;
797 else if (IsEqualGUID(&IID_IEnumCifComponents, riid))
799 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv);
800 *ppv = &This->IEnumCifComponents_iface;
805 FIXME("(%p)->(%s %p) not found\n", This
, debugstr_guid(riid
), ppv
);
807 return E_NOINTERFACE
;
810 IUnknown_AddRef((IUnknown
*)*ppv
);
814 static ULONG WINAPI
enum_components_AddRef(IEnumCifComponents
*iface
)
816 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
817 LONG ref
= InterlockedIncrement(&This
->ref
);
819 TRACE("(%p) ref=%d\n", This
, ref
);
824 static ULONG WINAPI
enum_components_Release(IEnumCifComponents
*iface
)
826 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
827 LONG ref
= InterlockedDecrement(&This
->ref
);
829 TRACE("(%p) ref=%d\n", This
, ref
);
833 ICifFile_Release(This
->file
);
840 static HRESULT WINAPI
enum_components_Next(IEnumCifComponents
*iface
, ICifComponent
**component
)
842 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
843 struct cifcomponent
*comp
;
845 TRACE("(%p)->(%p)\n", This
, component
);
858 This
->position
= list_next(This
->start
, This
->position
);
865 comp
= CONTAINING_RECORD(This
->position
, struct cifcomponent
, entry
);
866 } while (This
->group_id
&& (!comp
->group
|| strcmp(This
->group_id
, comp
->group
)));
868 *component
= &comp
->ICifComponent_iface
;
872 static HRESULT WINAPI
enum_components_Reset(IEnumCifComponents
*iface
)
874 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
876 TRACE("(%p)\n", This
);
878 This
->position
= This
->start
;
882 static const IEnumCifComponentsVtbl enum_componentsVtbl
=
884 enum_components_QueryInterface
,
885 enum_components_AddRef
,
886 enum_components_Release
,
887 enum_components_Next
,
888 enum_components_Reset
,
891 static HRESULT
enum_components_create(ICifFile
*file
, struct list
*start
, char *group_id
, IEnumCifComponents
**iface
)
893 struct ciffenum_components
*enumerator
;
895 enumerator
= heap_alloc_zero(sizeof(*enumerator
));
896 if (!enumerator
) return E_OUTOFMEMORY
;
898 enumerator
->IEnumCifComponents_iface
.lpVtbl
= &enum_componentsVtbl
;
900 enumerator
->file
= file
;
901 enumerator
->start
= start
;
902 enumerator
->position
= start
;
903 enumerator
->group_id
= group_id
;
905 ICifFile_AddRef(file
);
907 *iface
= &enumerator
->IEnumCifComponents_iface
;
911 static HRESULT WINAPI
enum_groups_QueryInterface(IEnumCifGroups
*iface
, REFIID riid
, void **ppv
)
913 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
915 if (IsEqualGUID(&IID_IUnknown
, riid
))
917 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
918 *ppv
= &This
->IEnumCifGroups_iface
;
921 else if (IsEqualGUID(&IID_IEnumCifGroups, riid))
923 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv);
924 *ppv = &This->IEnumCifGroups_iface;
929 FIXME("(%p)->(%s %p) not found\n", This
, debugstr_guid(riid
), ppv
);
931 return E_NOINTERFACE
;
934 IUnknown_AddRef((IUnknown
*)*ppv
);
938 static ULONG WINAPI
enum_groups_AddRef(IEnumCifGroups
*iface
)
940 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
941 LONG ref
= InterlockedIncrement(&This
->ref
);
943 TRACE("(%p) ref=%d\n", This
, ref
);
948 static ULONG WINAPI
enum_groups_Release(IEnumCifGroups
*iface
)
950 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
951 LONG ref
= InterlockedDecrement(&This
->ref
);
953 TRACE("(%p) ref=%d\n", This
, ref
);
957 ICifFile_Release(This
->file
);
964 static HRESULT WINAPI
enum_groups_Next(IEnumCifGroups
*iface
, ICifGroup
**group
)
966 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
969 TRACE("(%p)->(%p)\n", This
, group
);
971 if (!This
->position
|| !group
)
974 This
->position
= list_next(This
->start
, This
->position
);
979 gp
= CONTAINING_RECORD(This
->position
, struct cifgroup
, entry
);
980 *group
= &gp
->ICifGroup_iface
;
984 static HRESULT WINAPI
enum_groups_Reset(IEnumCifGroups
*iface
)
986 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
988 TRACE("(%p)\n", This
);
990 This
->position
= This
->start
;
994 static const IEnumCifGroupsVtbl enum_groupsVtbl
=
996 enum_groups_QueryInterface
,
1003 static HRESULT
enum_groups_create(ICifFile
*file
, struct list
*start
, IEnumCifGroups
**iface
)
1005 struct ciffenum_groups
*enumerator
;
1007 enumerator
= heap_alloc_zero(sizeof(*enumerator
));
1008 if (!enumerator
) return E_OUTOFMEMORY
;
1010 enumerator
->IEnumCifGroups_iface
.lpVtbl
= &enum_groupsVtbl
;
1011 enumerator
->ref
= 1;
1012 enumerator
->file
= file
;
1013 enumerator
->start
= start
;
1014 enumerator
->position
= start
;
1016 ICifFile_AddRef(file
);
1018 *iface
= &enumerator
->IEnumCifGroups_iface
;
1022 static HRESULT WINAPI
ciffile_QueryInterface(ICifFile
*iface
, REFIID riid
, void **ppv
)
1024 struct ciffile
*This
= impl_from_ICiffile(iface
);
1026 if (IsEqualGUID(&IID_IUnknown
, riid
))
1028 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
1029 *ppv
= &This
->ICifFile_iface
;
1031 else if (IsEqualGUID(&IID_ICifFile
, riid
))
1033 TRACE("(%p)->(IID_ICifFile %p)\n", This
, ppv
);
1034 *ppv
= &This
->ICifFile_iface
;
1038 FIXME("(%p)->(%s %p) not found\n", This
, debugstr_guid(riid
), ppv
);
1040 return E_NOINTERFACE
;
1043 IUnknown_AddRef((IUnknown
*)*ppv
);
1047 static ULONG WINAPI
ciffile_AddRef(ICifFile
*iface
)
1049 struct ciffile
*This
= impl_from_ICiffile(iface
);
1050 LONG ref
= InterlockedIncrement(&This
->ref
);
1052 TRACE("(%p) ref=%d\n", This
, ref
);
1057 static ULONG WINAPI
ciffile_Release(ICifFile
*iface
)
1059 struct ciffile
*This
= impl_from_ICiffile(iface
);
1060 LONG ref
= InterlockedDecrement(&This
->ref
);
1062 TRACE("(%p) ref=%d\n", This
, ref
);
1066 struct cifcomponent
*comp
, *comp_next
;
1067 struct cifgroup
*group
, *group_next
;
1069 heap_free(This
->name
);
1071 LIST_FOR_EACH_ENTRY_SAFE(comp
, comp_next
, &This
->components
, struct cifcomponent
, entry
)
1073 list_remove(&comp
->entry
);
1074 component_free(comp
);
1077 LIST_FOR_EACH_ENTRY_SAFE(group
, group_next
, &This
->groups
, struct cifgroup
, entry
)
1079 list_remove(&group
->entry
);
1089 static HRESULT WINAPI
ciffile_EnumComponents(ICifFile
*iface
, IEnumCifComponents
**enum_components
, DWORD filter
, void *pv
)
1091 struct ciffile
*This
= impl_from_ICiffile(iface
);
1093 TRACE("(%p)->(%p, %u, %p)\n", This
, enum_components
, filter
, pv
);
1096 FIXME("filter (%x) not supported\n", filter
);
1098 FIXME("how to handle pv (%p)?\n", pv
);
1100 return enum_components_create(iface
, &This
->components
, NULL
, enum_components
);
1103 static HRESULT WINAPI
ciffile_FindComponent(ICifFile
*iface
, const char *id
, ICifComponent
**component
)
1105 struct ciffile
*This
= impl_from_ICiffile(iface
);
1106 struct cifcomponent
*comp
;
1108 TRACE("(%p)->(%s, %p)\n", This
, debugstr_a(id
), component
);
1110 LIST_FOR_EACH_ENTRY(comp
, &This
->components
, struct cifcomponent
, entry
)
1112 if (strcmp(comp
->id
, id
) != 0)
1115 *component
= &comp
->ICifComponent_iface
;
1122 static HRESULT WINAPI
ciffile_EnumGroups(ICifFile
*iface
, IEnumCifGroups
**enum_groups
, DWORD filter
, void *pv
)
1124 struct ciffile
*This
= impl_from_ICiffile(iface
);
1126 TRACE("(%p)->(%p, %u, %p)\n", This
, enum_groups
, filter
, pv
);
1129 FIXME("filter (%x) not supported\n", filter
);
1131 FIXME("how to handle pv (%p)?\n", pv
);
1133 return enum_groups_create(iface
, &This
->groups
, enum_groups
);
1136 static HRESULT WINAPI
ciffile_FindGroup(ICifFile
*iface
, const char *id
, ICifGroup
**group
)
1138 struct ciffile
*This
= impl_from_ICiffile(iface
);
1139 struct cifgroup
*gp
;
1141 TRACE("(%p)->(%s, %p)\n", This
, debugstr_a(id
), group
);
1143 LIST_FOR_EACH_ENTRY(gp
, &This
->groups
, struct cifgroup
, entry
)
1145 if (strcmp(gp
->id
, id
) != 0)
1148 *group
= &gp
->ICifGroup_iface
;
1155 static HRESULT WINAPI
ciffile_EnumModes(ICifFile
*iface
, IEnumCifModes
**cuf_modes
, DWORD filter
, void *pv
)
1157 struct ciffile
*This
= impl_from_ICiffile(iface
);
1159 FIXME("(%p)->(%p, %u, %p): stub\n", This
, cuf_modes
, filter
, pv
);
1164 static HRESULT WINAPI
ciffile_FindMode(ICifFile
*iface
, const char *id
, ICifMode
**mode
)
1166 struct ciffile
*This
= impl_from_ICiffile(iface
);
1168 FIXME("(%p)->(%s, %p): stub\n", This
, debugstr_a(id
), mode
);
1173 static HRESULT WINAPI
ciffile_GetDescription(ICifFile
*iface
, char *desc
, DWORD size
)
1175 struct ciffile
*This
= impl_from_ICiffile(iface
);
1177 TRACE("(%p)->(%p, %u)\n", This
, desc
, size
);
1179 return copy_substring_null(desc
, size
, This
->name
);
1182 static HRESULT WINAPI
ciffile_GetDetDlls(ICifFile
*iface
, char *dlls
, DWORD size
)
1184 struct ciffile
*This
= impl_from_ICiffile(iface
);
1186 FIXME("(%p)->(%p, %u): stub\n", This
, dlls
, size
);
1191 static const ICifFileVtbl ciffileVtbl
=
1193 ciffile_QueryInterface
,
1196 ciffile_EnumComponents
,
1197 ciffile_FindComponent
,
1202 ciffile_GetDescription
,
1206 static BOOL
copy_string(char **dest
, const char *source
)
1214 *dest
= strdupA(source
);
1215 if (!dest
) return FALSE
;
1219 static BOOL
section_get_str(struct inf_section
*inf_sec
, const char *key
, char **value
, const char *def
)
1221 struct inf_value
*inf_val
;
1223 inf_val
= inf_get_value(inf_sec
, key
);
1224 if (!inf_val
) return copy_string(value
, def
);
1226 *value
= inf_value_get_value(inf_val
);
1227 if (!*value
) return FALSE
;
1232 static char *next_part(char **str
, BOOL strip_quotes
)
1237 while (*next
&& *next
!= ',')
1242 *str
= trim(start
, NULL
, strip_quotes
);
1247 *str
= trim(start
, NULL
, strip_quotes
);
1251 static BOOL
value_get_str_field(struct inf_value
*inf_val
, int field
, char **value
, const char *def
)
1253 char *line
, *str
, *next
;
1256 line
= inf_value_get_value(inf_val
);
1257 if (!line
) return FALSE
;
1263 next
= next_part(&str
, TRUE
);
1267 BOOL ret
= copy_string(value
, str
);
1275 return copy_string(value
, def
);
1279 static BOOL section_get_str_field(struct inf_section *inf_sec, const char *key, int field, char **value, const char *def)
1281 struct inf_value *inf_val;
1283 inf_val = inf_get_value(inf_sec, key);
1284 if (!inf_val) return copy_string(value, def);
1286 return value_get_str_field(inf_val, field, value, def);
1290 static BOOL
section_get_dword(struct inf_section
*inf_sec
, const char *key
, DWORD
*value
, DWORD def
)
1292 struct inf_value
*inf_val
;
1295 inf_val
= inf_get_value(inf_sec
, key
);
1302 str
= inf_value_get_value(inf_val
);
1303 if (!str
) return FALSE
;
1311 static BOOL
value_get_dword_field(struct inf_value
*inf_val
, int field
, DWORD
*value
, DWORD def
)
1316 ret
= value_get_str_field(inf_val
, field
, &value_str
, NULL
);
1317 if (!ret
) return FALSE
;
1324 *value
= atoi(value_str
);
1325 heap_free(value_str
);
1330 static BOOL
section_get_dword_field(struct inf_section
*inf_sec
, const char *key
, int field
, DWORD
*value
, DWORD def
)
1332 struct inf_value
*inf_val
;
1334 inf_val
= inf_get_value(inf_sec
, key
);
1341 return value_get_dword_field(inf_val
, field
, value
, def
);
1344 static HRESULT
process_version(struct ciffile
*file
, struct inf_section
*section
)
1346 if (!section_get_str(section
, "DisplayName", &file
->name
, DEFAULT_INSTALLER_DESC
))
1347 return E_OUTOFMEMORY
;
1352 static BOOL
read_version_entry(struct inf_section
*section
, DWORD
*ret_ver
, DWORD
*ret_build
)
1356 char *line
, *str
, *next
;
1358 if (!section_get_str(section
, "Version", &line
, NULL
))
1360 if (!line
) goto done
;
1364 next
= next_part(&str
, TRUE
);
1365 version
|= atoi(str
) << 16;
1366 if (!next
) goto done
;
1369 next
= next_part(&str
, TRUE
);
1370 version
|= atoi(str
) & 0xffff;
1371 if (!next
) goto done
;
1374 next
= next_part(&str
, TRUE
);
1375 build
|= atoi(str
) << 16;
1376 if (!next
) goto done
;
1379 next_part(&str
, TRUE
);
1380 build
|= atoi(str
) & 0xffff;
1389 static BOOL
read_platform_entry(struct inf_section
*section
, DWORD
*ret_platform
)
1391 DWORD platform
= PLATFORM_ALL
;
1392 char *line
, *str
, *next
;
1394 if (!section_get_str(section
, "Platform", &line
, NULL
))
1396 if (!line
) goto done
;
1402 next
= next_part(&str
, TRUE
);
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
;
1419 FIXME("Unknown platform: %s\n", debugstr_a(str
));
1426 *ret_platform
= platform
;
1430 static BOOL
read_dependencies(struct cifcomponent
*component
, struct inf_section
*section
)
1432 struct dependency_info
*dependency
;
1433 char *line
, *str
, *next
;
1436 if (!section_get_str(section
, "Dependencies", &line
, NULL
))
1437 return E_OUTOFMEMORY
;
1438 if (!line
) goto done
;
1444 next
= next_part(&str
, TRUE
);
1446 dependency
= heap_alloc_zero(sizeof(*dependency
));
1447 if (!dependency
) goto done
;
1449 dependency
->id
= strdupA(str
);
1450 if (!dependency
->id
)
1452 heap_free(dependency
);
1456 dependency
->type
= strstr(dependency
->id
, ":");
1457 if (dependency
->type
) *dependency
->type
++ = 0;
1459 list_add_tail(&component
->dependencies
, &dependency
->entry
);
1471 static BOOL
read_urls(struct cifcomponent
*component
, struct inf_section
*section
)
1473 struct inf_value
*inf_value
= NULL
;
1474 struct url_info
*url_entry
;
1478 while (inf_section_next_value(section
, &inf_value
))
1480 str
= inf_value_get_key(inf_value
);
1481 if (!str
) return E_OUTOFMEMORY
;
1483 if (strncasecmp(str
, "URL", 3))
1489 index
= strtol(str
+3, &next
, 10);
1490 if (next
== str
+3 || *next
!= 0 || index
< 1)
1494 url_entry
= heap_alloc_zero(sizeof(*url_entry
));
1495 if (!url_entry
) goto error
;
1497 url_entry
->index
= index
;
1499 if (!value_get_str_field(inf_value
, 1, &url_entry
->url
, NULL
))
1501 if (!url_entry
->url
|| !*url_entry
->url
)
1503 url_entry_free(url_entry
);
1507 if (!value_get_dword_field(inf_value
, 2, &url_entry
->flags
, 0))
1510 list_add_tail(&component
->urls
, &url_entry
->entry
);
1520 url_entry_free(url_entry
);
1524 void add_component_by_priority(struct ciffile
*file
, struct cifcomponent
*component
)
1526 struct cifcomponent
*entry
;
1528 LIST_FOR_EACH_ENTRY(entry
, &file
->components
, struct cifcomponent
, entry
)
1530 if (entry
->priority
> component
->priority
)
1533 list_add_before(&entry
->entry
, &component
->entry
);
1537 list_add_tail(&file
->components
, &component
->entry
);
1540 static HRESULT
process_component(struct ciffile
*file
, struct inf_section
*section
, const char *section_name
)
1542 struct cifcomponent
*component
;
1543 HRESULT hr
= E_OUTOFMEMORY
;
1545 component
= heap_alloc_zero(sizeof(*component
));
1546 if (!component
) return E_OUTOFMEMORY
;
1548 component
->ICifComponent_iface
.lpVtbl
= &cifcomponentVtbl
;
1549 component
->parent
= &file
->ICifFile_iface
;
1551 list_init(&component
->urls
);
1552 list_init(&component
->dependencies
);
1554 component
->queue_state
= ActionNone
;
1556 component
->id
= strdupA(section_name
);
1557 if (!component
->id
) goto error
;
1559 if (!section_get_str(section
, "DisplayName", &component
->description
, NULL
))
1561 if (!section_get_str(section
, "GUID", &component
->guid
, NULL
))
1563 if (!section_get_str(section
, "Details", &component
->details
, NULL
))
1565 if (!section_get_str(section
, "Group", &component
->group
, NULL
))
1567 if (!section_get_str(section
, "Locale", &component
->locale
, "en"))
1569 if (!section_get_str(section
, "PatchID", &component
->patchid
, NULL
))
1572 if (!section_get_dword_field(section
, "Size", 1, &component
->size_download
, 0))
1574 if (!section_get_dword_field(section
, "Size", 2, &component
->size_extracted
, 0))
1576 if (!section_get_dword_field(section
, "InstalledSize", 1, &component
->size_app
, 0))
1578 if (!section_get_dword_field(section
, "InstalledSize", 2, &component
->size_win
, 0))
1581 if (!section_get_str(section
, "SuccessKey", &component
->key_success
, NULL
))
1583 if (!section_get_str(section
, "CancelKey", &component
->key_cancel
, NULL
))
1585 if (!section_get_str(section
, "ProgressKey", &component
->key_progress
, NULL
))
1587 if (!section_get_str(section
, "UninstallKey", &component
->key_uninstall
, NULL
))
1589 if (!section_get_dword(section
, "Reboot", &component
->reboot
, 0))
1591 if (!section_get_dword(section
, "AdminCheck", &component
->admin
, 0))
1593 if (!section_get_dword(section
, "UIVisible", &component
->visibleui
, 1))
1595 if (!section_get_dword(section
, "ActiveSetupAware", &component
->as_aware
, 0))
1597 if (!section_get_dword(section
, "Priority", &component
->priority
, 0))
1600 if (!read_version_entry(section
, &component
->version
, &component
->build
))
1602 if (!read_platform_entry(section
, &component
->platform
))
1604 if (!read_urls(component
, section
))
1606 if (!read_dependencies(component
, section
))
1609 component
->current_priority
= component
->priority
;
1611 add_component_by_priority(file
, component
);
1615 component_free(component
);
1619 static HRESULT
process_group(struct ciffile
*file
, struct inf_section
*section
, const char *section_name
)
1621 struct cifgroup
*group
;
1622 HRESULT hr
= E_OUTOFMEMORY
;
1624 group
= heap_alloc_zero(sizeof(*group
));
1625 if (!group
) return E_OUTOFMEMORY
;
1627 group
->ICifGroup_iface
.lpVtbl
= &cifgroupVtbl
;
1628 group
->parent
= &file
->ICifFile_iface
;
1630 group
->id
= strdupA(section_name
);
1631 if (!group
->id
) goto error
;
1633 if (!section_get_str(section
, "DisplayName", &group
->description
, NULL
))
1635 if (!section_get_dword(section
, "Priority", &group
->priority
, 0))
1638 list_add_head(&file
->groups
, &group
->entry
);
1646 static HRESULT
process_section(struct ciffile
*file
, struct inf_section
*section
, const char *section_name
)
1651 if (!section_get_str(section
, "SectionType", &type
, "Component"))
1652 return E_OUTOFMEMORY
;
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
);
1659 FIXME("Don't know how to process %s\n", debugstr_a(type
));
1665 static HRESULT
process_inf(struct ciffile
*file
, struct inf_file
*inf
)
1667 struct inf_section
*section
= NULL
;
1671 while (SUCCEEDED(hr
) && inf_next_section(inf
, §ion
))
1673 section_name
= inf_section_get_name(section
);
1674 if (!section_name
) return E_OUTOFMEMORY
;
1676 TRACE("start processing section %s\n", debugstr_a(section_name
));
1678 if (!strcasecmp(section_name
, "Strings") ||
1679 !strncasecmp(section_name
, "Strings.", strlen("Strings.")))
1681 /* Ignore string sections */
1683 else if (strcasecmp(section_name
, "Version") == 0)
1684 hr
= process_version(file
, section
);
1686 hr
= process_section(file
, section
, section_name
);
1688 TRACE("finished processing section %s (%x)\n", debugstr_a(section_name
), hr
);
1689 heap_free(section_name
);
1692 /* In case there was no version section, set the default installer description */
1693 if (SUCCEEDED(hr
) && !file
->name
)
1695 file
->name
= strdupA(DEFAULT_INSTALLER_DESC
);
1696 if (!file
->name
) hr
= E_OUTOFMEMORY
;
1702 static HRESULT
load_ciffile(const char *path
, ICifFile
**icif
)
1704 struct inf_file
*inf
= NULL
;
1705 struct ciffile
*file
;
1706 HRESULT hr
= E_FAIL
;
1708 file
= heap_alloc_zero(sizeof(*file
));
1709 if(!file
) return E_OUTOFMEMORY
;
1711 file
->ICifFile_iface
.lpVtbl
= &ciffileVtbl
;
1714 list_init(&file
->components
);
1715 list_init(&file
->groups
);
1717 hr
= inf_load(path
, &inf
);
1718 if (FAILED(hr
)) goto error
;
1720 hr
= process_inf(file
, inf
);
1721 if (FAILED(hr
)) goto error
;
1723 *icif
= &file
->ICifFile_iface
;
1727 if (inf
) inf_free(inf
);
1728 ICifFile_Release(&file
->ICifFile_iface
);
1732 HRESULT WINAPI
GetICifFileFromFile(ICifFile
**icif
, const char *path
)
1734 TRACE("(%p, %s)\n", icif
, debugstr_a(path
));
1736 return load_ciffile(path
, icif
);
1740 HRESULT WINAPI
GetICifRWFileFromFile(ICifRWFile
**icif
, const char *path
)
1742 FIXME("(%p, %s): stub\n", icif
, debugstr_a(path
));